X-Git-Url: http://gitweb.fperrin.net/?p=GpsPrune.git;a=blobdiff_plain;f=src%2Ftim%2Fprune%2Fgui%2FSelectorDisplay.java;fp=src%2Ftim%2Fprune%2Fgui%2FSelectorDisplay.java;h=fa6630dc5b71400bd4f7202fb688f9a911cc3f6f;hp=0000000000000000000000000000000000000000;hb=ce6f2161b8596f7018d6a76bff79bc9e571f35fd;hpb=2d8cb72e84d5cc1089ce77baf1e34ea3ea2f8465 diff --git a/src/tim/prune/gui/SelectorDisplay.java b/src/tim/prune/gui/SelectorDisplay.java new file mode 100644 index 0000000..fa6630d --- /dev/null +++ b/src/tim/prune/gui/SelectorDisplay.java @@ -0,0 +1,359 @@ +package tim.prune.gui; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GridLayout; +import java.awt.event.AdjustmentEvent; +import java.awt.event.AdjustmentListener; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollBar; +import javax.swing.JScrollPane; +import javax.swing.ListSelectionModel; +import javax.swing.border.EtchedBorder; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +import tim.prune.DataSubscriber; +import tim.prune.I18nManager; +import tim.prune.data.TrackInfo; + +/** + * Class to allow selection of points and photos + * as a visual component + */ +public class SelectorDisplay extends GenericDisplay +{ + // Track details + private JLabel _trackpointsLabel = null; + private JLabel _filenameLabel = null; + // Scroll bar + private JScrollBar _scroller = null; + private boolean _ignoreScrollEvents = false; + + // Panel containing lists + private JPanel _listsPanel = null; + private int _visiblePanels = 1; + // Waypoints + private JPanel _waypointListPanel = null; + private JList _waypointList = null; + private WaypointListModel _waypointListModel = null; + // Photos + private JPanel _photoListPanel = null; + private JList _photoList = null; + private MediaListModel _photoListModel = null; + // Audio files + private JPanel _audioListPanel = null; + private JList _audioList = null; + private MediaListModel _audioListModel = null; + + // scrollbar interval + private static final int SCROLLBAR_INTERVAL = 50; + // number of rows in lists + private static final int NUM_LIST_ENTRIES = 7; + + + /** + * Constructor + * @param inTrackInfo Track info object + */ + public SelectorDisplay(TrackInfo inTrackInfo) + { + super(inTrackInfo); + setLayout(new BorderLayout()); + + JPanel mainPanel = new JPanel(); + mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); + mainPanel.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3)); + + // Track details panel + JPanel trackDetailsPanel = new JPanel(); + trackDetailsPanel.setLayout(new BoxLayout(trackDetailsPanel, BoxLayout.Y_AXIS)); + trackDetailsPanel.setBorder(BorderFactory.createCompoundBorder( + BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), BorderFactory.createEmptyBorder(3, 3, 3, 3)) + ); + JLabel trackDetailsLabel = new JLabel(I18nManager.getText("details.trackdetails")); + Font biggerFont = trackDetailsLabel.getFont(); + biggerFont = biggerFont.deriveFont(Font.BOLD, biggerFont.getSize2D() + 2.0f); + trackDetailsLabel.setFont(biggerFont); + trackDetailsPanel.add(trackDetailsLabel); + _trackpointsLabel = new JLabel(I18nManager.getText("details.notrack")); + trackDetailsPanel.add(_trackpointsLabel); + _filenameLabel = new JLabel(""); + _filenameLabel.setMinimumSize(new Dimension(120, 10)); + trackDetailsPanel.add(_filenameLabel); + + // Scroll bar + _scroller = new JScrollBar(JScrollBar.HORIZONTAL, 0, SCROLLBAR_INTERVAL, 0, 100); + _scroller.addAdjustmentListener(new AdjustmentListener() { + public void adjustmentValueChanged(AdjustmentEvent e) { + selectPoint(e.getValue()); + } + }); + _scroller.setEnabled(false); + + // Add panel for waypoints / photos + _listsPanel = new JPanel(); + _listsPanel.setLayout(new GridLayout(0, 1)); + _listsPanel.setBorder(BorderFactory.createCompoundBorder( + BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), BorderFactory.createEmptyBorder(3, 3, 3, 3)) + ); + _waypointListModel = new WaypointListModel(_trackInfo.getTrack()); + _waypointList = new JList(_waypointListModel); + _waypointList.setVisibleRowCount(NUM_LIST_ENTRIES); + _waypointList.addListSelectionListener(new ListSelectionListener() { + public void valueChanged(ListSelectionEvent e) + { + if (!e.getValueIsAdjusting()) selectWaypoint(_waypointList.getSelectedIndex()); + } + }); + _waypointListPanel = makeListPanel("details.lists.waypoints", _waypointList); + _listsPanel.add(_waypointListPanel); + // photo list + _photoListModel = new MediaListModel(_trackInfo.getPhotoList()); + _photoList = new JList(_photoListModel); + _photoList.setVisibleRowCount(NUM_LIST_ENTRIES); + _photoList.addListSelectionListener(new ListSelectionListener() { + public void valueChanged(ListSelectionEvent e) + { + if (!e.getValueIsAdjusting()) { + selectPhoto(_photoList.getSelectedIndex()); + } + }}); + _photoListPanel = makeListPanel("details.lists.photos", _photoList); + // don't add photo list (because there aren't any photos yet) + + // List for audio clips + _audioListModel = new MediaListModel(_trackInfo.getAudioList()); + _audioList = new JList(_audioListModel); + _audioList.addListSelectionListener(new ListSelectionListener() { + public void valueChanged(ListSelectionEvent e) + { + if (!e.getValueIsAdjusting()) { + selectAudio(_audioList.getSelectedIndex()); + } + }}); + _audioListPanel = makeListPanel("details.lists.audio", _audioList); + // don't add audio list either + _listsPanel.setAlignmentX(Component.LEFT_ALIGNMENT); + + // add the controls to the main panel + mainPanel.add(trackDetailsPanel); + mainPanel.add(Box.createVerticalStrut(5)); + mainPanel.add(_scroller); + mainPanel.add(Box.createVerticalStrut(5)); + + // add the main panel at the top + add(mainPanel, BorderLayout.NORTH); + // and lists in the centre + add(_listsPanel, BorderLayout.CENTER); + // set preferred width to be small + setPreferredSize(new Dimension(100, 100)); + } + + + /** + * Select the specified point + * @param inValue value to select + */ + private void selectPoint(int inValue) + { + if (_track != null && !_ignoreScrollEvents) { + _trackInfo.selectPoint(inValue); + } + } + + + /** + * Select the specified photo + * @param inPhotoIndex index of selected photo + */ + private void selectPhoto(int inPhotoIndex) + { + _trackInfo.selectPhoto(inPhotoIndex); + } + + /** + * Select the specified audio clip + * @param inIndex index of selected audio clip + */ + private void selectAudio(int inIndex) + { + _trackInfo.selectAudio(inIndex); + } + + /** + * Select the specified waypoint + * @param inWaypointIndex index of selected waypoint + */ + private void selectWaypoint(int inWaypointIndex) + { + if (inWaypointIndex >= 0) { + _trackInfo.selectPoint(_waypointListModel.getWaypoint(inWaypointIndex)); + } + } + + + /** + * Notification that Track has been updated + */ + public void dataUpdated(byte inUpdateType) + { + // Update track data + if (_track == null || _track.getNumPoints() <= 0) + { + _trackpointsLabel.setText(I18nManager.getText("details.notrack")); + _filenameLabel.setText(""); + _filenameLabel.setToolTipText(""); + } + else + { + _trackpointsLabel.setText(I18nManager.getText("details.track.points") + ": " + + _track.getNumPoints()); + int numFiles = _trackInfo.getFileInfo().getNumFiles(); + if (numFiles == 1) + { + final String filenameString = _trackInfo.getFileInfo().getFilename(); + _filenameLabel.setText(I18nManager.getText("details.track.file") + ": " + + filenameString); + _filenameLabel.setToolTipText(filenameString); + } + else if (numFiles > 1) + { + final String labelText = I18nManager.getText("details.track.numfiles") + ": " + numFiles; + _filenameLabel.setText(labelText); + _filenameLabel.setToolTipText(labelText); + } + else + { + _filenameLabel.setText(""); + _filenameLabel.setToolTipText(""); + } + } + + // Update scroller settings + int currentPointIndex = _trackInfo.getSelection().getCurrentPointIndex(); + _ignoreScrollEvents = true; + if (_track == null || _track.getNumPoints() < 2) + { + // careful to avoid event loops here + // _scroller.setValue(0); + _scroller.setEnabled(false); + } + else + { + _scroller.setMaximum(_track.getNumPoints() -1 + SCROLLBAR_INTERVAL); + if (currentPointIndex >= 0) + _scroller.setValue(currentPointIndex); + _scroller.setEnabled(true); + } + _ignoreScrollEvents = false; + + // update waypoints and photos if necessary + if ((inUpdateType | + (DataSubscriber.DATA_ADDED_OR_REMOVED | DataSubscriber.DATA_EDITED | DataSubscriber.WAYPOINTS_MODIFIED)) > 0) + { + _waypointListModel.fireChanged(); + } + if ((inUpdateType & + (DataSubscriber.DATA_ADDED_OR_REMOVED | DataSubscriber.DATA_EDITED | DataSubscriber.PHOTOS_MODIFIED)) > 0) + { + _photoListModel.fireChanged(); + _audioListModel.fireChanged(); + } + // Deselect selected waypoint if selected point has since changed + if (_waypointList.getSelectedIndex() >= 0) + { + if (_trackInfo.getCurrentPoint() == null + || _waypointList.getSelectedIndex() >= _waypointListModel.getSize() + || !_waypointListModel.getWaypoint(_waypointList.getSelectedIndex()).equals(_trackInfo.getCurrentPoint())) + { + // point is selected in list but different from current point - deselect + _waypointList.clearSelection(); + } + } + // Hide photo list if no photos loaded, same for audio + redrawLists(_photoListModel.getSize() > 0, _audioListModel.getSize() > 0); + + // Make sure correct photo is selected + if (_photoListModel.getSize() > 0) + { + int photoIndex = _trackInfo.getSelection().getCurrentPhotoIndex(); + int listSelection = _photoList.getSelectedIndex(); + // Change listbox selection if indexes not equal + if (listSelection != photoIndex) + { + if (photoIndex < 0) { + _photoList.clearSelection(); + } + else { + _photoList.setSelectedIndex(photoIndex); + } + } + } + // Same for audio clips + if (_audioListModel.getSize() > 0) + { + int audioIndex = _trackInfo.getSelection().getCurrentAudioIndex(); + int listSelection = _audioList.getSelectedIndex(); + // Change listbox selection if indexes not equal + if (listSelection != audioIndex) + { + if (audioIndex < 0) { + _audioList.clearSelection(); + } + else { + _audioList.setSelectedIndex(audioIndex); + } + } + } + } + + /** + * Make one of the three list panels + * @param inNameKey key for heading text + * @param inList list object + * @return panel object + */ + private static JPanel makeListPanel(String inNameKey, JList inList) + { + JPanel panel = new JPanel(); + panel.setLayout(new BorderLayout()); + panel.add(new JLabel(I18nManager.getText(inNameKey)), BorderLayout.NORTH); + inList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + panel.add(new JScrollPane(inList), BorderLayout.CENTER); + return panel; + } + + /** + * Redraw the list panels in the display according to which ones should be shown + * @param inShowPhotos true to show photo list + * @param inShowAudio true to show audio list + */ + private void redrawLists(boolean inShowPhotos, boolean inShowAudio) + { + // exit if same as last time + int panels = 1 + (inShowPhotos?2:0) + (inShowAudio?4:0); + if (panels == _visiblePanels) return; + _visiblePanels = panels; + // remove all panels and re-add them + _listsPanel.removeAll(); + _listsPanel.setLayout(new GridLayout(0, 1)); + _listsPanel.add(_waypointListPanel); + if (inShowPhotos) { + _listsPanel.add(_photoListPanel); + } + if (inShowAudio) { + _listsPanel.add(_audioListPanel); + } + _listsPanel.invalidate(); + _listsPanel.getParent().validate(); + } +}