1 package tim.prune.gui.colour;
4 import java.awt.Component;
5 import java.awt.GridLayout;
6 import java.awt.event.ActionEvent;
7 import java.awt.event.ActionListener;
9 import javax.swing.BorderFactory;
10 import javax.swing.BoxLayout;
11 import javax.swing.JComboBox;
12 import javax.swing.JLabel;
13 import javax.swing.JPanel;
14 import javax.swing.border.EtchedBorder;
16 import tim.prune.I18nManager;
17 import tim.prune.gui.GuiGridLayout;
18 import tim.prune.gui.colour.ColourerFactory.ColourerId;
21 * Class to provide a gui panel for selecting a colourer
22 * including which colourer, the start/end colours and
23 * optionally the max number of colours
25 public class ColourerSelectorPanel extends JPanel
27 /** Combo box for selecting the type of colourer */
28 private JComboBox<String> _typeCombo = null;
29 /** Array of type ids as stored in combo box */
30 private ColourerId[] _typeIds = null;
31 /** Panel object holding the colour patches */
32 private JPanel _patchPanel = null;
33 /** Array of colour patches for start and end */
34 private ColourPatch[] _startEndPatches = null;
35 /** Panel holding the max colours selection */
36 JPanel _maxColoursPanel = null;
37 private JComboBox<String> _maxColoursCombo = null;
39 /** Array of label keys for the 2 patches */
40 private static final String[] LABEL_KEYS = {"start", "end"};
45 * @param inColourChooser colour chooser to use (needs reference to parent dialog)
47 public ColourerSelectorPanel(ColourChooser inColourChooser)
49 _typeIds = new ColourerId[] {ColourerId.NONE, ColourerId.BY_FILE,
50 ColourerId.BY_SEGMENT, ColourerId.BY_DATE, ColourerId.BY_ALTITUDE,
51 ColourerId.BY_SPEED, ColourerId.BY_VSPEED, ColourerId.BY_GRADIENT};
52 makeGuiComponents(inColourChooser);
57 * Create all the gui components and lay them out in the panel
58 * @param inColourChooser colour chooser to use
60 private void makeGuiComponents(ColourChooser inColourChooser)
62 // Etched border and vertical layout
63 setBorder(BorderFactory.createCompoundBorder(
64 BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), BorderFactory.createEmptyBorder(4, 4, 4, 4))
66 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
69 JLabel introLabel = new JLabel(I18nManager.getText("dialog.colourer.intro"));
70 introLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
73 // Combo box for selecting which colourer to use
74 JPanel typePanel = new JPanel();
75 GuiGridLayout grid = new GuiGridLayout(typePanel);
76 final String keyPrefix = "dialog.colourer.type.";
77 String[] colourerTypes = new String[_typeIds.length];
78 for (int i=0; i<colourerTypes.length; i++)
80 colourerTypes[i] = I18nManager.getText(keyPrefix +
81 ColourerFactory.getDescriptionKey(_typeIds[i]));
83 _typeCombo = new JComboBox<String>(colourerTypes);
84 _typeCombo.setAlignmentX(Component.LEFT_ALIGNMENT);
85 _typeCombo.addActionListener(new ActionListener() {
86 public void actionPerformed(ActionEvent e)
88 onColourerTypeChanged();
92 grid.add(new JLabel(I18nManager.getText("dialog.colourer.type")));
94 typePanel.setAlignmentX(Component.LEFT_ALIGNMENT);
97 // Make panel for colour patches
98 _patchPanel = new JPanel();
99 _patchPanel.setLayout(new GridLayout());
100 _startEndPatches = new ColourPatch[2];
103 JPanel blankColumn = new JPanel();
104 ColourPatch blankPatch = new ColourPatch(Color.BLACK);
105 blankPatch.setVisible(false);
106 blankColumn.add(blankPatch);
107 _patchPanel.add(blankColumn);
109 // Loop over two columns of patches
110 for (int i=0; i<2; i++)
112 JPanel colPanel = new JPanel();
113 colPanel.setLayout(new BoxLayout(colPanel, BoxLayout.Y_AXIS));
114 // Top label and patch
115 colPanel.add(new JLabel(I18nManager.getText("dialog.colourer." + LABEL_KEYS[i])));
116 ColourPatch patch = new ColourPatch(Color.BLUE); // will be set by init() method shortly
117 patch.addMouseListener(new PatchListener(patch, inColourChooser));
119 _startEndPatches[i] = patch;
121 // Add column to panel
122 colPanel.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
123 _patchPanel.add(colPanel);
127 blankColumn = new JPanel();
128 blankPatch = new ColourPatch(Color.BLACK);
129 blankPatch.setVisible(false);
130 blankColumn.add(blankPatch);
131 _patchPanel.add(blankColumn);
133 _patchPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
136 // Combo box for selecting max colours
137 _maxColoursPanel = new JPanel();
138 grid = new GuiGridLayout(_maxColoursPanel);
139 grid.add(new JLabel(I18nManager.getText("dialog.colourer.maxcolours")));
140 String[] colourOptions = new String[] {"2", "3", "5", "10", "15"};
141 _maxColoursCombo = new JComboBox<String>(colourOptions);
142 grid.add(_maxColoursCombo);
143 _maxColoursPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
144 add(_maxColoursPanel);
148 * Init the colours from the colourer (if possible) or the default colour
149 * @param inColourer current colourer object, or null
150 * @param inDefaultColour current colour for points
152 public void init(PointColourer inColourer, Color inDefaultColour)
154 Color startColour = null, endColour = null;
155 if (inColourer != null)
157 selectColourerType(ColourerFactory.getId(inColourer));
158 startColour = inColourer.getStartColour();
159 endColour = inColourer.getEndColour();
160 _maxColoursCombo.setSelectedItem("" + inColourer.getMaxColours());
164 // no colourer, so default to 5 colours maximum
165 _maxColoursCombo.setSelectedIndex(2);
167 if (startColour == null) {startColour = inDefaultColour;}
168 if (endColour == null) {endColour = makeDefaultEndColour(inDefaultColour);}
169 if (startColour != null) {_startEndPatches[0].setBackground(startColour);}
170 if (endColour != null) {_startEndPatches[1].setBackground(endColour);}
171 onColourerTypeChanged(); // make sure gui is updated
175 * Make a default end colour if there isn't one already defined
176 * @param inStartColour start colour
177 * @return end colour, with the hue shifted by a third from the start
179 private static Color makeDefaultEndColour(Color inStartColour)
181 float[] defaultHSB = Color.RGBtoHSB(inStartColour.getRed(), inStartColour.getGreen(), inStartColour.getBlue(), null);
182 // add 120 degrees to the hue
183 defaultHSB[0] += (1.0f/3f);
184 return Color.getHSBColor(defaultHSB[0], defaultHSB[1], defaultHSB[2]);
188 * React to the colourer type being changed
189 * by showing / hiding gui elements
191 private void onColourerTypeChanged()
193 final ColourerId id = _typeIds[_typeCombo.getSelectedIndex()];
194 // Set visibility of controls according to whether they're needed for the selected type
195 _patchPanel.setVisible(ColourerFactory.areColoursRequired(id));
196 _maxColoursPanel.setVisible(ColourerFactory.isMaxColoursRequired(id));
200 * @return the selected colourer object, or null
202 public PointColourer getSelectedColourer()
204 final ColourerId id = _typeIds[_typeCombo.getSelectedIndex()];
205 return ColourerFactory.createColourer(id, _startEndPatches[0].getBackground(),
206 _startEndPatches[1].getBackground(), _maxColoursCombo.getSelectedItem().toString());
210 * Select the appropriate item in the dropdown
211 * @param inId id of colourer to choose
213 private void selectColourerType(ColourerId inId)
216 for (int i=0; i<_typeIds.length; i++)
218 if (_typeIds[i] == inId) {
224 System.err.println("Id " + inId + " not found in _typeIds!");
227 _typeCombo.setSelectedIndex(selIndex);