]> gitweb.fperrin.net Git - GpsPrune.git/blob - src/tim/prune/gui/SelectorDisplay.java
9dfc24f42394ad624d925589a2acd344411c12a0
[GpsPrune.git] / src / 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<String> _waypointList = null;
47         private WaypointListModel _waypointListModel = null;
48         // Photos
49         private JPanel _photoListPanel = null;
50         private JList<String> _photoList = null;
51         private MediaListModel _photoListModel = null;
52         // Audio files
53         private JPanel _audioListPanel = null;
54         private JList<String> _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<String>(_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<String>(_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<String>(_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                         _filenameLabel.setToolTipText("");
215                 }
216                 else
217                 {
218                         _trackpointsLabel.setText(I18nManager.getText("details.track.points") + ": "
219                                 + _track.getNumPoints());
220                         int numFiles = _trackInfo.getFileInfo().getNumFiles();
221                         if (numFiles == 1)
222                         {
223                                 final String filenameString = _trackInfo.getFileInfo().getFilename();
224                                 _filenameLabel.setText(I18nManager.getText("details.track.file") + ": "
225                                         + filenameString);
226                                 _filenameLabel.setToolTipText(filenameString);
227                         }
228                         else if (numFiles > 1)
229                         {
230                                 final String labelText = I18nManager.getText("details.track.numfiles") + ": " + numFiles;
231                                 final String filenameString = String.join(", ", _trackInfo.getFileInfo().getFilenames());
232                                 _filenameLabel.setText(labelText);
233                                 _filenameLabel.setToolTipText(filenameString);
234                         }
235                         else
236                         {
237                                 _filenameLabel.setText("");
238                                 _filenameLabel.setToolTipText("");
239                         }
240                 }
241
242                 // Update scroller settings
243                 int currentPointIndex = _trackInfo.getSelection().getCurrentPointIndex();
244                 _ignoreScrollEvents = true;
245                 if (_track == null || _track.getNumPoints() < 2)
246                 {
247                         // careful to avoid event loops here
248                         // _scroller.setValue(0);
249                         _scroller.setEnabled(false);
250                 }
251                 else
252                 {
253                         _scroller.setMaximum(_track.getNumPoints() -1 + SCROLLBAR_INTERVAL);
254                         if (currentPointIndex >= 0)
255                                 _scroller.setValue(currentPointIndex);
256                         _scroller.setEnabled(true);
257                 }
258                 _ignoreScrollEvents = false;
259
260                 // update waypoints and photos if necessary
261                 if ((inUpdateType |
262                         (DataSubscriber.DATA_ADDED_OR_REMOVED | DataSubscriber.DATA_EDITED | DataSubscriber.WAYPOINTS_MODIFIED)) > 0)
263                 {
264                         _waypointListModel.fireChanged();
265                 }
266                 if ((inUpdateType &
267                         (DataSubscriber.DATA_ADDED_OR_REMOVED | DataSubscriber.DATA_EDITED | DataSubscriber.PHOTOS_MODIFIED)) > 0)
268                 {
269                         _photoListModel.fireChanged();
270                         _audioListModel.fireChanged();
271                 }
272                 // Deselect selected waypoint if selected point has since changed
273                 if (_waypointList.getSelectedIndex() >= 0)
274                 {
275                         if (_trackInfo.getCurrentPoint() == null
276                          || _waypointList.getSelectedIndex() >= _waypointListModel.getSize()
277                          || !_waypointListModel.getWaypoint(_waypointList.getSelectedIndex()).equals(_trackInfo.getCurrentPoint()))
278                         {
279                                 // point is selected in list but different from current point - deselect
280                                 _waypointList.clearSelection();
281                         }
282                 }
283                 // Hide photo list if no photos loaded, same for audio
284                 redrawLists(_photoListModel.getSize() > 0, _audioListModel.getSize() > 0);
285
286                 // Make sure correct photo is selected
287                 if (_photoListModel.getSize() > 0)
288                 {
289                         int photoIndex = _trackInfo.getSelection().getCurrentPhotoIndex();
290                         int listSelection = _photoList.getSelectedIndex();
291                         // Change listbox selection if indexes not equal
292                         if (listSelection != photoIndex)
293                         {
294                                 if (photoIndex < 0) {
295                                         _photoList.clearSelection();
296                                 }
297                                 else {
298                                         _photoList.setSelectedIndex(photoIndex);
299                                 }
300                         }
301                 }
302                 // Same for audio clips
303                 if (_audioListModel.getSize() > 0)
304                 {
305                         int audioIndex = _trackInfo.getSelection().getCurrentAudioIndex();
306                         int listSelection = _audioList.getSelectedIndex();
307                         // Change listbox selection if indexes not equal
308                         if (listSelection != audioIndex)
309                         {
310                                 if (audioIndex < 0) {
311                                         _audioList.clearSelection();
312                                 }
313                                 else {
314                                         _audioList.setSelectedIndex(audioIndex);
315                                 }
316                         }
317                 }
318         }
319
320         /**
321          * Make one of the three list panels
322          * @param inNameKey key for heading text
323          * @param inList list object
324          * @return panel object
325          */
326         private static JPanel makeListPanel(String inNameKey, JList<String> inList)
327         {
328                 JPanel panel = new JPanel();
329                 panel.setLayout(new BorderLayout());
330                 panel.add(new JLabel(I18nManager.getText(inNameKey)), BorderLayout.NORTH);
331                 inList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
332                 panel.add(new JScrollPane(inList), BorderLayout.CENTER);
333                 return panel;
334         }
335
336         /**
337          * Redraw the list panels in the display according to which ones should be shown
338          * @param inShowPhotos true to show photo list
339          * @param inShowAudio true to show audio list
340          */
341         private void redrawLists(boolean inShowPhotos, boolean inShowAudio)
342         {
343                 // exit if same as last time
344                 int panels = 1 + (inShowPhotos?2:0) + (inShowAudio?4:0);
345                 if (panels == _visiblePanels) return;
346                 _visiblePanels = panels;
347                 // remove all panels and re-add them
348                 _listsPanel.removeAll();
349                 _listsPanel.setLayout(new GridLayout(0, 1));
350                 _listsPanel.add(_waypointListPanel);
351                 if (inShowPhotos) {
352                         _listsPanel.add(_photoListPanel);
353                 }
354                 if (inShowAudio) {
355                         _listsPanel.add(_audioListPanel);
356                 }
357                 _listsPanel.invalidate();
358                 _listsPanel.getParent().validate();
359         }
360 }