]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/gui/SelectorDisplay.java
Version 14, October 2012
[GpsPrune.git] / tim / prune / gui / SelectorDisplay.java
1 package tim.prune.gui;
2
3 import java.awt.BorderLayout;
4 import java.awt.Component;
5 import java.awt.Dimension;
6 import java.awt.Font;
7 import java.awt.GridLayout;
8 import java.awt.event.AdjustmentEvent;
9 import java.awt.event.AdjustmentListener;
10
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;
23
24 import tim.prune.DataSubscriber;
25 import tim.prune.I18nManager;
26 import tim.prune.data.TrackInfo;
27
28 /**
29  * Class to allow selection of points and photos
30  * as a visual component
31  */
32 public class SelectorDisplay extends GenericDisplay
33 {
34         // Track details
35         private JLabel _trackpointsLabel = null;
36         private JLabel _filenameLabel = null;
37         // Scroll bar
38         private JScrollBar _scroller = null;
39         private boolean _ignoreScrollEvents = false;
40
41         // Panel containing lists
42         private JPanel _listsPanel = null;
43         private int _visiblePanels = 1;
44         // Waypoints
45         private JPanel _waypointListPanel = null;
46         private JList _waypointList = null;
47         private WaypointListModel _waypointListModel = null;
48         // Photos
49         private JPanel _photoListPanel = null;
50         private JList _photoList = null;
51         private MediaListModel _photoListModel = null;
52         // Audio files
53         private JPanel _audioListPanel = null;
54         private JList _audioList = null;
55         private MediaListModel _audioListModel = null;
56
57         // scrollbar interval
58         private static final int SCROLLBAR_INTERVAL = 50;
59         // number of rows in lists
60         private static final int NUM_LIST_ENTRIES = 7;
61
62
63         /**
64          * Constructor
65          * @param inTrackInfo Track info object
66          */
67         public SelectorDisplay(TrackInfo inTrackInfo)
68         {
69                 super(inTrackInfo);
70                 setLayout(new BorderLayout());
71
72                 JPanel mainPanel = new JPanel();
73                 mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
74                 mainPanel.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
75
76                 // Track details panel
77                 JPanel trackDetailsPanel = new JPanel();
78                 trackDetailsPanel.setLayout(new BoxLayout(trackDetailsPanel, BoxLayout.Y_AXIS));
79                 trackDetailsPanel.setBorder(BorderFactory.createCompoundBorder(
80                         BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), BorderFactory.createEmptyBorder(3, 3, 3, 3))
81                 );
82                 JLabel trackDetailsLabel = new JLabel(I18nManager.getText("details.trackdetails"));
83                 Font biggerFont = trackDetailsLabel.getFont();
84                 biggerFont = biggerFont.deriveFont(Font.BOLD, biggerFont.getSize2D() + 2.0f);
85                 trackDetailsLabel.setFont(biggerFont);
86                 trackDetailsPanel.add(trackDetailsLabel);
87                 _trackpointsLabel = new JLabel(I18nManager.getText("details.notrack"));
88                 trackDetailsPanel.add(_trackpointsLabel);
89                 _filenameLabel = new JLabel("");
90                 _filenameLabel.setMinimumSize(new Dimension(120, 10));
91                 trackDetailsPanel.add(_filenameLabel);
92
93                 // Scroll bar
94                 _scroller = new JScrollBar(JScrollBar.HORIZONTAL, 0, SCROLLBAR_INTERVAL, 0, 100);
95                 _scroller.addAdjustmentListener(new AdjustmentListener() {
96                         public void adjustmentValueChanged(AdjustmentEvent e) {
97                                 selectPoint(e.getValue());
98                         }
99                 });
100                 _scroller.setEnabled(false);
101
102                 // Add panel for waypoints / photos
103                 _listsPanel = new JPanel();
104                 _listsPanel.setLayout(new GridLayout(0, 1));
105                 _listsPanel.setBorder(BorderFactory.createCompoundBorder(
106                         BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), BorderFactory.createEmptyBorder(3, 3, 3, 3))
107                 );
108                 _waypointListModel = new WaypointListModel(_trackInfo.getTrack());
109                 _waypointList = new JList(_waypointListModel);
110                 _waypointList.setVisibleRowCount(NUM_LIST_ENTRIES);
111                 _waypointList.addListSelectionListener(new ListSelectionListener() {
112                         public void valueChanged(ListSelectionEvent e)
113                         {
114                                 if (!e.getValueIsAdjusting()) selectWaypoint(_waypointList.getSelectedIndex());
115                         }
116                 });
117                 _waypointListPanel = makeListPanel("details.lists.waypoints", _waypointList);
118                 _listsPanel.add(_waypointListPanel);
119                 // photo list
120                 _photoListModel = new MediaListModel(_trackInfo.getPhotoList());
121                 _photoList = new JList(_photoListModel);
122                 _photoList.setVisibleRowCount(NUM_LIST_ENTRIES);
123                 _photoList.addListSelectionListener(new ListSelectionListener() {
124                         public void valueChanged(ListSelectionEvent e)
125                         {
126                                 if (!e.getValueIsAdjusting()) {
127                                         selectPhoto(_photoList.getSelectedIndex());
128                                 }
129                         }});
130                 _photoListPanel = makeListPanel("details.lists.photos", _photoList);
131                 // don't add photo list (because there aren't any photos yet)
132
133                 // List for audio clips
134                 _audioListModel = new MediaListModel(_trackInfo.getAudioList());
135                 _audioList = new JList(_audioListModel);
136                 _audioList.addListSelectionListener(new ListSelectionListener() {
137                         public void valueChanged(ListSelectionEvent e)
138                         {
139                                 if (!e.getValueIsAdjusting()) {
140                                         selectAudio(_audioList.getSelectedIndex());
141                                 }
142                         }});
143                 _audioListPanel = makeListPanel("details.lists.audio", _audioList);
144                 // don't add audio list either
145                 _listsPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
146
147                 // add the controls to the main panel
148                 mainPanel.add(trackDetailsPanel);
149                 mainPanel.add(Box.createVerticalStrut(5));
150                 mainPanel.add(_scroller);
151                 mainPanel.add(Box.createVerticalStrut(5));
152
153                 // add the main panel at the top
154                 add(mainPanel, BorderLayout.NORTH);
155                 // and lists in the centre
156                 add(_listsPanel, BorderLayout.CENTER);
157                 // set preferred width to be small
158                 setPreferredSize(new Dimension(100, 100));
159         }
160
161
162         /**
163          * Select the specified point
164          * @param inValue value to select
165          */
166         private void selectPoint(int inValue)
167         {
168                 if (_track != null && !_ignoreScrollEvents) {
169                         _trackInfo.selectPoint(inValue);
170                 }
171         }
172
173
174         /**
175          * Select the specified photo
176          * @param inPhotoIndex index of selected photo
177          */
178         private void selectPhoto(int inPhotoIndex)
179         {
180                 _trackInfo.selectPhoto(inPhotoIndex);
181         }
182
183         /**
184          * Select the specified audio clip
185          * @param inIndex index of selected audio clip
186          */
187         private void selectAudio(int inIndex)
188         {
189                 _trackInfo.selectAudio(inIndex);
190         }
191
192         /**
193          * Select the specified waypoint
194          * @param inWaypointIndex index of selected waypoint
195          */
196         private void selectWaypoint(int inWaypointIndex)
197         {
198                 if (inWaypointIndex >= 0) {
199                         _trackInfo.selectPoint(_waypointListModel.getWaypoint(inWaypointIndex));
200                 }
201         }
202
203
204         /**
205          * Notification that Track has been updated
206          */
207         public void dataUpdated(byte inUpdateType)
208         {
209                 // Update track data
210                 if (_track == null || _track.getNumPoints() <= 0)
211                 {
212                         _trackpointsLabel.setText(I18nManager.getText("details.notrack"));
213                         _filenameLabel.setText("");
214                 }
215                 else
216                 {
217                         _trackpointsLabel.setText(I18nManager.getText("details.track.points") + ": "
218                                 + _track.getNumPoints());
219                         int numFiles = _trackInfo.getFileInfo().getNumFiles();
220                         if (numFiles == 1)
221                         {
222                                 _filenameLabel.setText(I18nManager.getText("details.track.file") + ": "
223                                         + _trackInfo.getFileInfo().getFilename());
224                         }
225                         else if (numFiles > 1)
226                         {
227                                 _filenameLabel.setText(I18nManager.getText("details.track.numfiles") + ": " + numFiles);
228                         }
229                         else _filenameLabel.setText("");
230                 }
231
232                 // Update scroller settings
233                 int currentPointIndex = _trackInfo.getSelection().getCurrentPointIndex();
234                 _ignoreScrollEvents = true;
235                 if (_track == null || _track.getNumPoints() < 2)
236                 {
237                         // careful to avoid event loops here
238                         // _scroller.setValue(0);
239                         _scroller.setEnabled(false);
240                 }
241                 else
242                 {
243                         _scroller.setMaximum(_track.getNumPoints() -1 + SCROLLBAR_INTERVAL);
244                         if (currentPointIndex >= 0)
245                                 _scroller.setValue(currentPointIndex);
246                         _scroller.setEnabled(true);
247                 }
248                 _ignoreScrollEvents = false;
249
250                 // update waypoints and photos if necessary
251                 if ((inUpdateType |
252                         (DataSubscriber.DATA_ADDED_OR_REMOVED | DataSubscriber.DATA_EDITED | DataSubscriber.WAYPOINTS_MODIFIED)) > 0)
253                 {
254                         _waypointListModel.fireChanged();
255                 }
256                 if ((inUpdateType &
257                         (DataSubscriber.DATA_ADDED_OR_REMOVED | DataSubscriber.DATA_EDITED | DataSubscriber.PHOTOS_MODIFIED)) > 0)
258                 {
259                         _photoListModel.fireChanged();
260                         _audioListModel.fireChanged();
261                 }
262                 // Deselect selected waypoint if selected point has since changed
263                 if (_waypointList.getSelectedIndex() >= 0)
264                 {
265                         if (_trackInfo.getCurrentPoint() == null
266                          || _waypointList.getSelectedIndex() >= _waypointListModel.getSize()
267                          || !_waypointListModel.getWaypoint(_waypointList.getSelectedIndex()).equals(_trackInfo.getCurrentPoint()))
268                         {
269                                 // point is selected in list but different from current point - deselect
270                                 _waypointList.clearSelection();
271                         }
272                 }
273                 // Hide photo list if no photos loaded, same for audio
274                 redrawLists(_photoListModel.getSize() > 0, _audioListModel.getSize() > 0);
275
276                 // Make sure correct photo is selected
277                 if (_photoListModel.getSize() > 0)
278                 {
279                         int photoIndex = _trackInfo.getSelection().getCurrentPhotoIndex();
280                         int listSelection = _photoList.getSelectedIndex();
281                         // Change listbox selection if indexes not equal
282                         if (listSelection != photoIndex)
283                         {
284                                 if (photoIndex < 0) {
285                                         _photoList.clearSelection();
286                                 }
287                                 else {
288                                         _photoList.setSelectedIndex(photoIndex);
289                                 }
290                         }
291                 }
292                 // Same for audio clips
293                 if (_audioListModel.getSize() > 0)
294                 {
295                         int audioIndex = _trackInfo.getSelection().getCurrentAudioIndex();
296                         int listSelection = _audioList.getSelectedIndex();
297                         // Change listbox selection if indexes not equal
298                         if (listSelection != audioIndex)
299                         {
300                                 if (audioIndex < 0) {
301                                         _audioList.clearSelection();
302                                 }
303                                 else {
304                                         _audioList.setSelectedIndex(audioIndex);
305                                 }
306                         }
307                 }
308         }
309
310         /**
311          * Make one of the three list panels
312          * @param inNameKey key for heading text
313          * @param inList list object
314          * @return panel object
315          */
316         private static JPanel makeListPanel(String inNameKey, JList inList)
317         {
318                 JPanel panel = new JPanel();
319                 panel.setLayout(new BorderLayout());
320                 panel.add(new JLabel(I18nManager.getText(inNameKey)), BorderLayout.NORTH);
321                 inList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
322                 panel.add(new JScrollPane(inList), BorderLayout.CENTER);
323                 return panel;
324         }
325
326         /**
327          * Redraw the list panels in the display according to which ones should be shown
328          * @param inShowPhotos true to show photo list
329          * @param inShowAudio true to show audio list
330          */
331         private void redrawLists(boolean inShowPhotos, boolean inShowAudio)
332         {
333                 // exit if same as last time
334                 int panels = 1 + (inShowPhotos?2:0) + (inShowAudio?4:0);
335                 if (panels == _visiblePanels) return;
336                 _visiblePanels = panels;
337                 // remove all panels and re-add them
338                 _listsPanel.removeAll();
339                 _listsPanel.setLayout(new GridLayout(0, 1));
340                 _listsPanel.add(_waypointListPanel);
341                 if (inShowPhotos) {
342                         _listsPanel.add(_photoListPanel);
343                 }
344                 if (inShowAudio) {
345                         _listsPanel.add(_audioListPanel);
346                 }
347                 _listsPanel.invalidate();
348                 _listsPanel.getParent().validate();
349         }
350 }