net.tourbook.ui.views.TourMarkerView.java Source code

Java tutorial

Introduction

Here is the source code for net.tourbook.ui.views.TourMarkerView.java

Source

/*******************************************************************************
 * Copyright (C) 2005, 2011  Wolfgang Schramm and Contributors
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation version 2 of the License.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
 *******************************************************************************/
package net.tourbook.ui.views;

import java.text.NumberFormat;
import java.util.ArrayList;

import net.tourbook.Messages;
import net.tourbook.application.TourbookPlugin;
import net.tourbook.chart.Chart;
import net.tourbook.chart.ChartLabel;
import net.tourbook.chart.SelectionChartXSliderPosition;
import net.tourbook.data.TourData;
import net.tourbook.data.TourMarker;
import net.tourbook.database.TourDatabase;
import net.tourbook.preferences.ITourbookPreferences;
import net.tourbook.tour.ActionOpenMarkerDialog;
import net.tourbook.tour.ITourEventListener;
import net.tourbook.tour.SelectionDeletedTours;
import net.tourbook.tour.SelectionTourData;
import net.tourbook.tour.SelectionTourId;
import net.tourbook.tour.SelectionTourIds;
import net.tourbook.tour.TourEvent;
import net.tourbook.tour.TourEventId;
import net.tourbook.tour.TourManager;
import net.tourbook.ui.ITourProvider;
import net.tourbook.ui.UI;
import net.tourbook.ui.tourChart.TourChart;
import net.tourbook.ui.views.tourCatalog.SelectionTourCatalogView;
import net.tourbook.ui.views.tourCatalog.TVICatalogComparedTour;
import net.tourbook.ui.views.tourCatalog.TVICatalogRefTourItem;
import net.tourbook.ui.views.tourCatalog.TVICompareResultComparedTour;
import net.tourbook.util.PostSelectionProvider;

import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.layout.PixelConverter;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.ColumnPixelData;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.part.PageBook;
import org.eclipse.ui.part.ViewPart;

public class TourMarkerView extends ViewPart implements ITourProvider {

    public static final String ID = "net.tourbook.views.TourMarkerView"; //$NON-NLS-1$

    public static final int COLUMN_TIME = 0;
    public static final int COLUMN_DISTANCE = 1;
    public static final int COLUMN_REMARK = 2;
    public static final int COLUMN_VISUAL_POSITION = 3;
    public static final int COLUMN_X_OFFSET = 4;
    public static final int COLUMN_Y_OFFSET = 5;

    private final IPreferenceStore _prefStore = TourbookPlugin.getDefault().getPreferenceStore();

    private TourData _tourData;

    private PostSelectionProvider _postSelectionProvider;
    private ISelectionListener _postSelectionListener;
    private IPropertyChangeListener _prefChangeListener;
    private ITourEventListener _tourPropertyListener;
    private IPartListener2 _partListener;

    private PixelConverter _pc;

    private final NumberFormat _nf_3_3 = NumberFormat.getNumberInstance();
    {
        _nf_3_3.setMinimumFractionDigits(3);
        _nf_3_3.setMaximumFractionDigits(3);
    }
    /*
     * UI controls
     */
    private PageBook _pageBook;
    private Label _pageNoChart;
    private Composite _viewerContainer;

    private TableViewer _markerViewer;
    private Chart _tourChart;

    private ActionOpenMarkerDialog _actionEditTourMarkers;

    class MarkerViewerContentProvicer implements IStructuredContentProvider {

        public void dispose() {
        }

        public Object[] getElements(final Object inputElement) {
            if (_tourData == null) {
                return new Object[0];
            } else {
                return _tourData.getTourMarkers().toArray();
            }
        }

        public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput) {
        }
    }

    /**
     * Sort the markers by time
     */
    private static class MarkerViewerSorter extends ViewerSorter {

        @Override
        public int compare(final Viewer viewer, final Object obj1, final Object obj2) {
            //         return ((TourMarker) (obj1)).getTime() - ((TourMarker) (obj2)).getTime();
            // time is disabled because it's not always available in gpx files
            return ((TourMarker) (obj1)).getSerieIndex() - ((TourMarker) (obj2)).getSerieIndex();
        }
    }

    public TourMarkerView() {
        super();
    }

    private void addPartListener() {
        _partListener = new IPartListener2() {

            public void partActivated(final IWorkbenchPartReference partRef) {
            }

            public void partBroughtToTop(final IWorkbenchPartReference partRef) {
            }

            public void partClosed(final IWorkbenchPartReference partRef) {
                if (partRef.getPart(false) == TourMarkerView.this) {
                    //               TourManager.fireEvent(TourEventId.CLEAR_DISPLAYED_TOUR, null, TourMarkerView.this);
                }
            }

            public void partDeactivated(final IWorkbenchPartReference partRef) {
            }

            public void partHidden(final IWorkbenchPartReference partRef) {
            }

            public void partInputChanged(final IWorkbenchPartReference partRef) {
            }

            public void partOpened(final IWorkbenchPartReference partRef) {
            }

            public void partVisible(final IWorkbenchPartReference partRef) {
            }
        };
        getViewSite().getPage().addPartListener(_partListener);
    }

    private void addPrefListener() {

        _prefChangeListener = new IPropertyChangeListener() {
            public void propertyChange(final PropertyChangeEvent event) {

                final String property = event.getProperty();

                if (property.equals(ITourbookPreferences.MEASUREMENT_SYSTEM)) {

                    // measurement system has changed

                    UI.updateUnits();

                    // dispose viewer
                    final Control[] children = _viewerContainer.getChildren();
                    for (final Control element : children) {
                        element.dispose();
                    }

                    createUI10TableViewer(_viewerContainer);
                    _viewerContainer.layout();

                    // update the viewer
                    _markerViewer.setInput(this);

                } else if (property.equals(ITourbookPreferences.VIEW_LAYOUT_CHANGED)) {

                    _markerViewer.getTable()
                            .setLinesVisible(_prefStore.getBoolean(ITourbookPreferences.VIEW_LAYOUT_DISPLAY_LINES));

                    _markerViewer.refresh();

                    /*
                     * the tree must be redrawn because the styled text does not show with the new
                     * color
                     */
                    _markerViewer.getTable().redraw();

                }
            }
        };
        _prefStore.addPropertyChangeListener(_prefChangeListener);
    }

    /**
     * listen for events when a tour is selected
     */
    private void addSelectionListener() {

        _postSelectionListener = new ISelectionListener() {
            public void selectionChanged(final IWorkbenchPart part, final ISelection selection) {
                if (part == TourMarkerView.this) {
                    return;
                }
                onSelectionChanged(selection);
            }
        };
        getSite().getPage().addPostSelectionListener(_postSelectionListener);
    }

    private void addTourEventListener() {

        _tourPropertyListener = new ITourEventListener() {
            public void tourChanged(final IWorkbenchPart part, final TourEventId eventId, final Object eventData) {

                if ((_tourData == null) || (part == TourMarkerView.this)) {
                    return;
                }

                if ((eventId == TourEventId.TOUR_CHANGED) && (eventData instanceof TourEvent)) {

                    final ArrayList<TourData> modifiedTours = ((TourEvent) eventData).getModifiedTours();
                    if (modifiedTours != null) {

                        // update modified tour

                        final long viewTourId = _tourData.getTourId();

                        for (final TourData tourData : modifiedTours) {
                            if (tourData.getTourId() == viewTourId) {

                                // get modified tour
                                _tourData = tourData;

                                _markerViewer.setInput(new Object[0]);

                                // removed old tour data from the selection provider
                                _postSelectionProvider.clearSelection();

                                // nothing more to do, the view contains only one tour
                                return;
                            }
                        }
                    }

                } else if (eventId == TourEventId.CLEAR_DISPLAYED_TOUR) {

                    clearView();
                }
            }
        };

        TourManager.getInstance().addTourEventListener(_tourPropertyListener);
    }

    private void clearView() {

        _tourData = null;

        _markerViewer.setInput(new Object[0]);

        _postSelectionProvider.clearSelection();

        _pageBook.showPage(_pageNoChart);
    }

    @Override
    public void createPartControl(final Composite parent) {

        createUI(parent);

        _actionEditTourMarkers = new ActionOpenMarkerDialog(this, true);

        addSelectionListener();
        addTourEventListener();
        addPrefListener();
        addPartListener();

        // this part is a selection provider
        getSite().setSelectionProvider(_postSelectionProvider = new PostSelectionProvider());

        // show default page
        _pageBook.showPage(_pageNoChart);

        // show marker from last selection
        onSelectionChanged(getSite().getWorkbenchWindow().getSelectionService().getSelection());

        if (_tourData == null) {
            showTourFromTourProvider();
        }
    }

    private void createUI(final Composite parent) {

        _pc = new PixelConverter(parent);

        _pageBook = new PageBook(parent, SWT.NONE);
        _pageBook.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

        _pageNoChart = new Label(_pageBook, SWT.NONE);
        _pageNoChart.setText(Messages.UI_Label_no_chart_is_selected);

        _viewerContainer = new Composite(_pageBook, SWT.NONE);
        GridLayoutFactory.fillDefaults().applyTo(_viewerContainer);
        {
            createUI10TableViewer(_viewerContainer);
        }

        createUI20ContextMenu();
    }

    private void createUI10TableViewer(final Composite parent) {

        final TableColumnLayout tableLayout = new TableColumnLayout();

        final Composite layoutContainer = new Composite(parent, SWT.NONE);
        layoutContainer.setLayout(tableLayout);
        GridDataFactory.fillDefaults().grab(true, true).applyTo(layoutContainer);

        /*
         * create table
         */
        final Table table = new Table(layoutContainer, SWT.FULL_SELECTION | SWT.MULTI | SWT.BORDER);

        table.setLayout(new TableLayout());
        table.setHeaderVisible(true);
        //      table.setLinesVisible(_prefStore.getBoolean(ITourbookPreferences.VIEW_LAYOUT_DISPLAY_LINES));
        table.setLinesVisible(true);

        table.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(final KeyEvent e) {

                if (isTourInDb() == false) {
                    return;
                }

                final IStructuredSelection selection = (IStructuredSelection) _markerViewer.getSelection();
                if ((selection.size() > 0) && (e.keyCode == SWT.CR)) {

                    // run async, otherwise it would pop up the dialog two times
                    Display.getCurrent().asyncExec(new Runnable() {
                        public void run() {
                            _actionEditTourMarkers.setSelectedMarker((TourMarker) selection.getFirstElement());
                            _actionEditTourMarkers.run();
                        }
                    });
                }
            }
        });

        _markerViewer = new TableViewer(table);

        /*
         * create columns
         */
        TableViewerColumn tvc;
        TableColumn tvcColumn;

        // column: time
        tvc = new TableViewerColumn(_markerViewer, SWT.TRAIL);
        tvcColumn = tvc.getColumn();
        tvcColumn.setText(Messages.Tour_Marker_Column_time);
        tvc.setLabelProvider(new CellLabelProvider() {
            @Override
            public void update(final ViewerCell cell) {
                cell.setText(UI.format_hh_mm_ss(((TourMarker) cell.getElement()).getTime()));
            }
        });
        tableLayout.setColumnData(tvcColumn, new ColumnPixelData(_pc.convertWidthInCharsToPixels(12), false));

        // column: distance km/mi
        tvc = new TableViewerColumn(_markerViewer, SWT.TRAIL);
        tvcColumn = tvc.getColumn();
        tvcColumn.setText(UI.UNIT_LABEL_DISTANCE);
        tvcColumn.setToolTipText(Messages.Tour_Marker_Column_km_tooltip);

        tvc.setLabelProvider(new CellLabelProvider() {
            @Override
            public void update(final ViewerCell cell) {

                final TourMarker tourMarker = (TourMarker) cell.getElement();

                final int markerDistance = tourMarker.getDistance();
                if (markerDistance == -1) {
                    cell.setText(UI.EMPTY_STRING);
                } else {
                    cell.setText(_nf_3_3.format(((float) markerDistance) / 1000 / UI.UNIT_VALUE_DISTANCE));
                }

                if (tourMarker.getType() == ChartLabel.MARKER_TYPE_DEVICE) {
                    cell.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_RED));
                }
            }
        });
        tableLayout.setColumnData(tvcColumn, new ColumnPixelData(_pc.convertWidthInCharsToPixels(11), false));

        // column: remark
        tvc = new TableViewerColumn(_markerViewer, SWT.LEAD);
        tvcColumn = tvc.getColumn();
        tvcColumn.setText(Messages.Tour_Marker_Column_remark);
        tvc.setLabelProvider(new CellLabelProvider() {
            @Override
            public void update(final ViewerCell cell) {

                final TourMarker tourMarker = (TourMarker) cell.getElement();

                cell.setText(tourMarker.getLabel());
            }
        });
        tableLayout.setColumnData(tvcColumn, new ColumnWeightData(50, true));

        /*
         * create table viewer
         */

        _markerViewer.setContentProvider(new MarkerViewerContentProvicer());
        _markerViewer.setSorter(new MarkerViewerSorter());

        _markerViewer.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(final SelectionChangedEvent event) {
                final StructuredSelection selection = (StructuredSelection) event.getSelection();
                if (selection != null) {
                    fireSliderPosition(selection);
                }
            }
        });

        _markerViewer.addDoubleClickListener(new IDoubleClickListener() {
            public void doubleClick(final DoubleClickEvent event) {

                if (isTourInDb() == false) {
                    return;
                }

                // edit selected marker
                final IStructuredSelection selection = (IStructuredSelection) _markerViewer.getSelection();
                if (selection.size() > 0) {
                    _actionEditTourMarkers.setSelectedMarker((TourMarker) selection.getFirstElement());
                    _actionEditTourMarkers.run();
                }
            }
        });
    }

    /**
     * create the views context menu
     */
    private void createUI20ContextMenu() {

        final MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$
        menuMgr.setRemoveAllWhenShown(true);
        menuMgr.addMenuListener(new IMenuListener() {
            public void menuAboutToShow(final IMenuManager manager) {
                fillContextMenu(manager);
            }
        });

        final Table table = (Table) _markerViewer.getControl();
        final Menu menu = menuMgr.createContextMenu(table);

        table.setMenu(menu);

        getSite().registerContextMenu(menuMgr, _markerViewer);
    }

    @Override
    public void dispose() {

        TourManager.getInstance().removeTourEventListener(_tourPropertyListener);
        getSite().getPage().removePostSelectionListener(_postSelectionListener);
        getViewSite().getPage().removePartListener(_partListener);

        _prefStore.removePropertyChangeListener(_prefChangeListener);

        super.dispose();
    }

    private void fillContextMenu(final IMenuManager menuMgr) {

        menuMgr.add(_actionEditTourMarkers);

        // add standard group which allows other plug-ins to contribute here
        menuMgr.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));

        // set the marker which should be selected in the marker dialog
        final IStructuredSelection selection = (IStructuredSelection) _markerViewer.getSelection();
        _actionEditTourMarkers.setSelectedMarker((TourMarker) selection.getFirstElement());

        /*
         * enable actions
         */
        final boolean tourInDb = isTourInDb();

        _actionEditTourMarkers.setEnabled(tourInDb);
    }

    /**
     * select the chart slider(s) according to the selected marker(s)
     */
    private void fireSliderPosition(final StructuredSelection selection) {

        // a chart must be available
        if (_tourChart == null) {

            final TourChart tourChart = TourManager.getInstance().getActiveTourChart();

            if ((tourChart == null) || tourChart.isDisposed()) {
                return;
            } else {
                _tourChart = tourChart;
            }
        }

        final Object[] segments = selection.toArray();

        if (segments.length > 1) {

            // two or more markers are selected

            _postSelectionProvider.setSelection(
                    new SelectionChartXSliderPosition(_tourChart, ((TourMarker) segments[0]).getSerieIndex(),
                            ((TourMarker) segments[segments.length - 1]).getSerieIndex()));

        } else if (segments.length > 0) {

            // one marker is selected

            _postSelectionProvider.setSelection(
                    new SelectionChartXSliderPosition(_tourChart, ((TourMarker) segments[0]).getSerieIndex(),
                            SelectionChartXSliderPosition.IGNORE_SLIDER_POSITION));
        }
    }

    public Object getMarkerViewer() {
        return _markerViewer;
    }

    public ArrayList<TourData> getSelectedTours() {

        final ArrayList<TourData> selectedTours = new ArrayList<TourData>();
        selectedTours.add(_tourData);

        return selectedTours;
    }

    /**
     * @return Returns <code>true</code> when the tour is saved in the database
     */
    private boolean isTourInDb() {

        if ((_tourData != null) && (_tourData.getTourPerson() != null)) {
            return true;
        }

        return false;
    }

    private void onSelectionChanged(final ISelection selection) {

        long tourId = TourDatabase.ENTITY_IS_NOT_SAVED;

        if (selection instanceof SelectionTourData) {

            // a tour was selected, get the chart and update the marker viewer

            final SelectionTourData tourDataSelection = (SelectionTourData) selection;
            _tourData = tourDataSelection.getTourData();

            if (_tourData == null) {
                _tourChart = null;
            } else {
                _tourChart = tourDataSelection.getTourChart();
                tourId = _tourData.getTourId();
            }

        } else if (selection instanceof SelectionTourId) {

            _tourChart = null;
            tourId = ((SelectionTourId) selection).getTourId();

        } else if (selection instanceof SelectionTourIds) {

            final ArrayList<Long> tourIds = ((SelectionTourIds) selection).getTourIds();
            if ((tourIds != null) && (tourIds.size() > 0)) {
                _tourChart = null;
                tourId = tourIds.get(0);
            }

        } else if (selection instanceof SelectionTourCatalogView) {

            final SelectionTourCatalogView tourCatalogSelection = (SelectionTourCatalogView) selection;

            final TVICatalogRefTourItem refItem = tourCatalogSelection.getRefItem();
            if (refItem != null) {
                _tourChart = null;
                tourId = refItem.getTourId();
            }

        } else if (selection instanceof StructuredSelection) {

            _tourChart = null;
            final Object firstElement = ((StructuredSelection) selection).getFirstElement();
            if (firstElement instanceof TVICatalogComparedTour) {
                tourId = ((TVICatalogComparedTour) firstElement).getTourId();
            } else if (firstElement instanceof TVICompareResultComparedTour) {
                tourId = ((TVICompareResultComparedTour) firstElement).getComparedTourData().getTourId();
            }

        } else if (selection instanceof SelectionDeletedTours) {

            clearView();
        }

        if (tourId >= TourDatabase.ENTITY_IS_NOT_SAVED) {

            final TourData tourData = TourManager.getInstance().getTourData(tourId);
            if (tourData != null) {
                _tourData = tourData;
            }
        }

        final boolean isTour = (tourId >= 0) && (_tourData != null);

        if (isTour) {
            _pageBook.showPage(_viewerContainer);
            _markerViewer.setInput(new Object[0]);
        }

        _actionEditTourMarkers.setEnabled(isTour);
    }

    @Override
    public void setFocus() {
        _markerViewer.getTable().setFocus();
    }

    private void showTourFromTourProvider() {

        _pageBook.showPage(_pageNoChart);

        // a tour is not displayed, find a tour provider which provides a tour
        Display.getCurrent().asyncExec(new Runnable() {
            public void run() {

                // validate widget
                if (_pageBook.isDisposed()) {
                    return;
                }

                /*
                 * check if tour was set from a selection provider
                 */
                if (_tourData != null) {
                    return;
                }

                final ArrayList<TourData> selectedTours = TourManager.getSelectedTours();
                if ((selectedTours != null) && (selectedTours.size() > 0)) {
                    onSelectionChanged(new SelectionTourData(selectedTours.get(0)));
                }
            }
        });
    }

}