View Javadoc
1   package org.opentrafficsim.swing.gui;
2   
3   import java.awt.Dimension;
4   import java.awt.GridBagConstraints;
5   import java.awt.GridBagLayout;
6   import java.beans.PropertyChangeListener;
7   import java.util.Arrays;
8   import java.util.Locale;
9   
10  import javax.swing.JLabel;
11  import javax.swing.JPanel;
12  import javax.swing.SwingConstants;
13  
14  import com.bric.multislider.MultiThumbSlider;
15  import com.bric.multislider.MultiThumbSliderUi;
16  import com.bric.multislider.MultiThumbSliderUi.Thumb;
17  
18  /**
19   * Wrapper for Jeremy Wood's MultiThumbSlider.
20   * <p>
21   * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
22   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
23   * </p>
24   * @author <a href="https://tudelft.nl/staff/p.knoppers-1">Peter Knoppers</a>
25   */
26  public class ProbabilityDistributionEditor extends JPanel
27  {
28      /** */
29      private static final long serialVersionUID = 20141222L;
30  
31      /** The internal MultiThumbSlider. */
32      private MultiThumbSlider<String> slider;
33  
34      /** The JLabels that indicate the current values. */
35      private JLabel[] labels;
36  
37      /**
38       * Construct a graphical ProbabilityDistributioneEditor.
39       * @param elementNames String[]; the names of the elements of the probability distribution
40       * @param values Double[]; the initial values of the probabilities (should add up to 1.0 and should have same length as
41       *            <cite>elementNames</cite>)
42       */
43      public ProbabilityDistributionEditor(final String[] elementNames, final Double[] values)
44      {
45          super(new GridBagLayout());
46          GridBagConstraints gbc = new GridBagConstraints();
47          gbc.fill = GridBagConstraints.BOTH;
48          gbc.gridx = 0;
49          gbc.gridy = 0;
50          gbc.gridwidth = 2;
51          float[] initialValues = new float[values.length - 1];
52          double sum = 0;
53          String[] reducedNames = new String[elementNames.length - 1];
54          for (int i = 0; i < values.length - 1; i++)
55          {
56              sum += values[i];
57              initialValues[i] = (float) sum;
58              reducedNames[i] = elementNames[i];
59          }
60          this.slider = new MultiThumbSlider<String>(MultiThumbSlider.HORIZONTAL, initialValues, reducedNames);
61          this.slider.setThumbOverlap(true);
62          this.slider.putClientProperty(MultiThumbSliderUi.THUMB_SHAPE_PROPERTY, Thumb.Hourglass);
63          this.slider.setThumbOverlap(true);
64          this.slider.setAutoAdding(false);
65          this.slider.setPreferredSize(new Dimension(250, 50));
66          add(this.slider, gbc);
67          gbc.gridwidth = 1;
68          this.labels = new JLabel[values.length];
69          for (int i = 0; i < values.length; i++)
70          {
71              gbc.gridy++;
72              gbc.gridx = 0;
73              JLabel caption = new JLabel(elementNames[i] + ": ");
74              caption.setHorizontalAlignment(SwingConstants.TRAILING);
75              add(caption, gbc);
76              JLabel value = new JLabel("");
77              value.setHorizontalAlignment(SwingConstants.LEADING);
78              gbc.gridx = 1;
79              add(value, gbc);
80              this.labels[i] = value;
81          }
82      }
83  
84      /**
85       * Retrieve the current probability values.
86       * @return Double[]; the probability values
87       */
88      public final Double[] getProbabilities()
89      {
90          float[] positions = this.slider.getThumbPositions();
91          Double[] result = new Double[positions.length + 1];
92          double previous = 0;
93          for (int i = 0; i < result.length - 1; i++)
94          {
95              double thisValue = positions[i];
96              result[i] = new Double(thisValue - previous);
97              previous = thisValue;
98          }
99          result[positions.length] = 1 - previous;
100         for (int i = 0; i < result.length; i++)
101         {
102             this.labels[i].setText(String.format(Locale.getDefault(), "%.3f", result[i]));
103         }
104         return result;
105     }
106 
107     /**
108      * {@inheritDoc}
109      */
110     @Override
111     public final void addPropertyChangeListener(final PropertyChangeListener pcl)
112     {
113         this.slider.addPropertyChangeListener(pcl);
114     }
115 
116     /**
117      * {@inheritDoc}
118      */
119     @Override
120     public final void removePropertyChangeListener(final PropertyChangeListener pcl)
121     {
122         this.slider.removePropertyChangeListener(pcl);
123     }
124 
125     /**
126      * {@inheritDoc}
127      */
128     @Override
129     public final void addPropertyChangeListener(final String key, final PropertyChangeListener pcl)
130     {
131         this.slider.addPropertyChangeListener(key, pcl);
132     }
133 
134     /**
135      * {@inheritDoc}
136      */
137     @Override
138     public final void removePropertyChangeListener(final String key, final PropertyChangeListener pcl)
139     {
140         this.slider.removePropertyChangeListener(key, pcl);
141     }
142 
143     /** {@inheritDoc} */
144     @Override
145     public final String toString()
146     {
147         return "ProbabilityDistributionEditor [slider=" + this.slider + ", labels=" + Arrays.toString(this.labels) + "]";
148     }
149 
150 }