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