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