3 import java.awt.BorderLayout;
4 import java.awt.Component;
5 import java.awt.Dimension;
7 import java.awt.GridLayout;
8 import java.awt.event.AdjustmentEvent;
9 import java.awt.event.AdjustmentListener;
11 import javax.swing.BorderFactory;
12 import javax.swing.Box;
13 import javax.swing.BoxLayout;
14 import javax.swing.JLabel;
15 import javax.swing.JList;
16 import javax.swing.JPanel;
17 import javax.swing.JScrollBar;
18 import javax.swing.JScrollPane;
19 import javax.swing.ListSelectionModel;
20 import javax.swing.border.EtchedBorder;
21 import javax.swing.event.ListSelectionEvent;
22 import javax.swing.event.ListSelectionListener;
24 import tim.prune.DataSubscriber;
25 import tim.prune.I18nManager;
26 import tim.prune.data.TrackInfo;
29 * Class to allow selection of points and photos
30 * as a visual component
32 public class SelectorDisplay extends GenericDisplay
35 private JLabel _trackpointsLabel = null;
36 private JLabel _filenameLabel = null;
38 private JScrollBar _scroller = null;
39 private boolean _ignoreScrollEvents = false;
41 // Panel containing lists
42 private JPanel _listsPanel = null;
43 private int _visiblePanels = 1;
45 private JPanel _waypointListPanel = null;
46 private JList<String> _waypointList = null;
47 private WaypointListModel _waypointListModel = null;
49 private JPanel _photoListPanel = null;
50 private JList<String> _photoList = null;
51 private MediaListModel _photoListModel = null;
53 private JPanel _audioListPanel = null;
54 private JList<String> _audioList = null;
55 private MediaListModel _audioListModel = null;
57 private JPanel _segmentListPanel = null;
58 private JList<String> _segmentList = null;
59 private SegmentListModel _segmentListModel = null;
62 private static final int SCROLLBAR_INTERVAL = 50;
63 // number of rows in lists
64 private static final int NUM_LIST_ENTRIES = 7;
69 * @param inTrackInfo Track info object
71 public SelectorDisplay(TrackInfo inTrackInfo)
74 setLayout(new BorderLayout());
76 JPanel mainPanel = new JPanel();
77 mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
78 mainPanel.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
80 // Track details panel
81 JPanel trackDetailsPanel = new JPanel();
82 trackDetailsPanel.setLayout(new BoxLayout(trackDetailsPanel, BoxLayout.Y_AXIS));
83 trackDetailsPanel.setBorder(BorderFactory.createCompoundBorder(
84 BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), BorderFactory.createEmptyBorder(3, 3, 3, 3))
86 JLabel trackDetailsLabel = new JLabel(I18nManager.getText("details.trackdetails"));
87 Font biggerFont = trackDetailsLabel.getFont();
88 biggerFont = biggerFont.deriveFont(Font.BOLD, biggerFont.getSize2D() + 2.0f);
89 trackDetailsLabel.setFont(biggerFont);
90 trackDetailsPanel.add(trackDetailsLabel);
91 _trackpointsLabel = new JLabel(I18nManager.getText("details.notrack"));
92 trackDetailsPanel.add(_trackpointsLabel);
93 _filenameLabel = new JLabel("");
94 _filenameLabel.setMinimumSize(new Dimension(120, 10));
95 trackDetailsPanel.add(_filenameLabel);
98 _scroller = new JScrollBar(JScrollBar.HORIZONTAL, 0, SCROLLBAR_INTERVAL, 0, 100);
99 _scroller.addAdjustmentListener(new AdjustmentListener() {
100 public void adjustmentValueChanged(AdjustmentEvent e) {
101 selectPoint(e.getValue());
104 _scroller.setEnabled(false);
106 // Add panel for waypoints / photos
107 _listsPanel = new JPanel();
108 _listsPanel.setLayout(new GridLayout(0, 1));
109 _listsPanel.setBorder(BorderFactory.createCompoundBorder(
110 BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), BorderFactory.createEmptyBorder(3, 3, 3, 3))
112 _waypointListModel = new WaypointListModel(_trackInfo.getTrack());
113 _waypointList = new JList<String>(_waypointListModel);
114 _waypointList.setVisibleRowCount(NUM_LIST_ENTRIES);
115 _waypointList.addListSelectionListener(new ListSelectionListener() {
116 public void valueChanged(ListSelectionEvent e)
118 if (!e.getValueIsAdjusting()) selectWaypoint(_waypointList.getSelectedIndex());
121 _waypointListPanel = makeListPanel("details.lists.waypoints", _waypointList);
122 _listsPanel.add(_waypointListPanel);
124 _photoListModel = new MediaListModel(_trackInfo.getPhotoList());
125 _photoList = new JList<String>(_photoListModel);
126 _photoList.setVisibleRowCount(NUM_LIST_ENTRIES);
127 _photoList.addListSelectionListener(new ListSelectionListener() {
128 public void valueChanged(ListSelectionEvent e)
130 if (!e.getValueIsAdjusting()) {
131 selectPhoto(_photoList.getSelectedIndex());
134 _photoListPanel = makeListPanel("details.lists.photos", _photoList);
135 // don't add photo list (because there aren't any photos yet)
137 // List for audio clips
138 _audioListModel = new MediaListModel(_trackInfo.getAudioList());
139 _audioList = new JList<String>(_audioListModel);
140 _audioList.addListSelectionListener(new ListSelectionListener() {
141 public void valueChanged(ListSelectionEvent e)
143 if (!e.getValueIsAdjusting()) {
144 selectAudio(_audioList.getSelectedIndex());
147 _audioListPanel = makeListPanel("details.lists.audio", _audioList);
148 // don't add audio list either
149 _listsPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
152 _segmentListModel = new SegmentListModel(_trackInfo.getTrack());
153 _segmentList = new JList<String>(_segmentListModel);
154 _segmentList.addListSelectionListener(new ListSelectionListener() {
155 public void valueChanged(ListSelectionEvent e)
157 if (!e.getValueIsAdjusting()) {
158 selectSegment(_segmentList.getSelectedIndex());
161 _segmentListPanel = makeListPanel("details.lists.segments", _segmentList);
163 // add the controls to the main panel
164 mainPanel.add(trackDetailsPanel);
165 mainPanel.add(Box.createVerticalStrut(5));
166 mainPanel.add(_scroller);
167 mainPanel.add(Box.createVerticalStrut(5));
169 // add the main panel at the top
170 add(mainPanel, BorderLayout.NORTH);
171 // and lists in the centre
172 add(_listsPanel, BorderLayout.CENTER);
173 // set preferred width to be small
174 setPreferredSize(new Dimension(100, 100));
179 * Select the specified point
180 * @param inValue value to select
182 private void selectPoint(int inValue)
184 if (_track != null && !_ignoreScrollEvents) {
185 _trackInfo.selectPoint(inValue);
191 * Select the specified photo
192 * @param inPhotoIndex index of selected photo
194 private void selectPhoto(int inPhotoIndex)
196 _trackInfo.selectPhoto(inPhotoIndex);
200 * Select the specified audio clip
201 * @param inIndex index of selected audio clip
203 private void selectAudio(int inIndex)
205 _trackInfo.selectAudio(inIndex);
211 private void selectSegment(int inIndex)
214 int start = _segmentListModel.getSegmentStart(inIndex);
215 int end = _segmentListModel.getSegmentEnd(inIndex);
216 _trackInfo.getSelection().selectRange(start, end);
221 * Select the specified waypoint
222 * @param inWaypointIndex index of selected waypoint
224 private void selectWaypoint(int inWaypointIndex)
226 if (inWaypointIndex >= 0) {
227 _trackInfo.selectPoint(_waypointListModel.getWaypoint(inWaypointIndex));
233 * Notification that Track has been updated
235 public void dataUpdated(byte inUpdateType)
238 if (_track == null || _track.getNumPoints() <= 0)
240 _trackpointsLabel.setText(I18nManager.getText("details.notrack"));
241 _filenameLabel.setText("");
242 _filenameLabel.setToolTipText("");
246 _trackpointsLabel.setText(I18nManager.getText("details.track.points") + ": "
247 + _track.getNumPoints());
248 int numFiles = _trackInfo.getFileInfo().getNumFiles();
251 final String filenameString = _trackInfo.getFileInfo().getFilename();
252 _filenameLabel.setText(I18nManager.getText("details.track.file") + ": "
254 _filenameLabel.setToolTipText(filenameString);
256 else if (numFiles > 1)
258 final String labelText = I18nManager.getText("details.track.numfiles") + ": " + numFiles;
259 _filenameLabel.setText(labelText);
260 _filenameLabel.setToolTipText(labelText);
264 _filenameLabel.setText("");
265 _filenameLabel.setToolTipText("");
269 // Update scroller settings
270 int currentPointIndex = _trackInfo.getSelection().getCurrentPointIndex();
271 _ignoreScrollEvents = true;
272 if (_track == null || _track.getNumPoints() < 2)
274 // careful to avoid event loops here
275 // _scroller.setValue(0);
276 _scroller.setEnabled(false);
280 _scroller.setMaximum(_track.getNumPoints() -1 + SCROLLBAR_INTERVAL);
281 if (currentPointIndex >= 0)
282 _scroller.setValue(currentPointIndex);
283 _scroller.setEnabled(true);
285 _ignoreScrollEvents = false;
287 // update waypoints and photos if necessary
289 (DataSubscriber.DATA_ADDED_OR_REMOVED | DataSubscriber.DATA_EDITED | DataSubscriber.WAYPOINTS_MODIFIED)) > 0)
291 _waypointListModel.fireChanged();
294 (DataSubscriber.DATA_ADDED_OR_REMOVED | DataSubscriber.DATA_EDITED | DataSubscriber.PHOTOS_MODIFIED)) > 0)
296 _photoListModel.fireChanged();
297 _audioListModel.fireChanged();
299 // Deselect selected waypoint if selected point has since changed
300 if (_waypointList.getSelectedIndex() >= 0)
302 if (_trackInfo.getCurrentPoint() == null
303 || _waypointList.getSelectedIndex() >= _waypointListModel.getSize()
304 || !_waypointListModel.getWaypoint(_waypointList.getSelectedIndex()).equals(_trackInfo.getCurrentPoint()))
306 // point is selected in list but different from current point - deselect
307 _waypointList.clearSelection();
310 if ((inUpdateType & (DataSubscriber.DATA_ADDED_OR_REMOVED | DataSubscriber.DATA_EDITED)) > 0)
312 _segmentListModel.fireChanged();
313 if (_segmentListModel.getSize() > 1)
315 _listsPanel.add(_segmentListPanel);
318 // Deselect segment if selection goes beyond the selected
320 if ((inUpdateType & DataSubscriber.SELECTION_CHANGED) > 0)
322 int segmentSelected = _segmentList.getSelectedIndex();
323 if (segmentSelected >= 0)
325 if (_trackInfo.getSelection().getStart() != _segmentListModel.getSegmentStart(segmentSelected) ||
326 _trackInfo.getSelection().getEnd() != _segmentListModel.getSegmentEnd(segmentSelected))
328 _segmentList.clearSelection();
332 // Hide photo list if no photos loaded, same for audio
333 redrawLists(_photoListModel.getSize() > 0, _audioListModel.getSize() > 0);
335 // Make sure correct photo is selected
336 if (_photoListModel.getSize() > 0)
338 int photoIndex = _trackInfo.getSelection().getCurrentPhotoIndex();
339 int listSelection = _photoList.getSelectedIndex();
340 // Change listbox selection if indexes not equal
341 if (listSelection != photoIndex)
343 if (photoIndex < 0) {
344 _photoList.clearSelection();
347 _photoList.setSelectedIndex(photoIndex);
351 // Same for audio clips
352 if (_audioListModel.getSize() > 0)
354 int audioIndex = _trackInfo.getSelection().getCurrentAudioIndex();
355 int listSelection = _audioList.getSelectedIndex();
356 // Change listbox selection if indexes not equal
357 if (listSelection != audioIndex)
359 if (audioIndex < 0) {
360 _audioList.clearSelection();
363 _audioList.setSelectedIndex(audioIndex);
370 * Make one of the three list panels
371 * @param inNameKey key for heading text
372 * @param inList list object
373 * @return panel object
375 private static JPanel makeListPanel(String inNameKey, JList<String> inList)
377 JPanel panel = new JPanel();
378 panel.setLayout(new BorderLayout());
379 panel.add(new JLabel(I18nManager.getText(inNameKey)), BorderLayout.NORTH);
380 inList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
381 panel.add(new JScrollPane(inList), BorderLayout.CENTER);
386 * Redraw the list panels in the display according to which ones should be shown
387 * @param inShowPhotos true to show photo list
388 * @param inShowAudio true to show audio list
390 private void redrawLists(boolean inShowPhotos, boolean inShowAudio)
392 // exit if same as last time
393 int panels = 1 + (inShowPhotos?2:0) + (inShowAudio?4:0);
394 if (panels == _visiblePanels) return;
395 _visiblePanels = panels;
396 // remove all panels and re-add them
397 _listsPanel.removeAll();
398 _listsPanel.setLayout(new GridLayout(0, 1));
399 _listsPanel.add(_waypointListPanel);
400 _listsPanel.add(_segmentListPanel);
402 _listsPanel.add(_photoListPanel);
405 _listsPanel.add(_audioListPanel);
407 _listsPanel.invalidate();
408 _listsPanel.getParent().validate();