Java tutorial
/******************************************************************************* * Copyright (C) 2005, 2015 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.map2.view; import java.awt.Point; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Set; import net.tourbook.application.TourbookPlugin; import net.tourbook.chart.Chart; import net.tourbook.chart.ChartDataModel; import net.tourbook.chart.SelectionChartInfo; import net.tourbook.chart.SelectionChartXSliderPosition; import net.tourbook.common.UI; import net.tourbook.common.action.ActionOpenPrefDialog; import net.tourbook.common.color.ColorProviderConfig; import net.tourbook.common.color.IGradientColorProvider; import net.tourbook.common.color.IMapColorProvider; import net.tourbook.common.color.MapGraphId; import net.tourbook.common.map.GeoPosition; import net.tourbook.common.util.ITourToolTipProvider; import net.tourbook.common.util.TourToolTip; import net.tourbook.common.util.Util; import net.tourbook.data.TourData; import net.tourbook.data.TourMarker; import net.tourbook.data.TourWayPoint; import net.tourbook.importdata.RawDataManager; import net.tourbook.map.MapColorProvider; import net.tourbook.map.MapUtils; import net.tourbook.map2.Messages; import net.tourbook.map2.action.ActionDimMap; import net.tourbook.map2.action.ActionManageMapProviders; import net.tourbook.map2.action.ActionMap2Color; import net.tourbook.map2.action.ActionPhotoProperties; import net.tourbook.map2.action.ActionReloadFailedMapImages; import net.tourbook.map2.action.ActionSaveDefaultPosition; import net.tourbook.map2.action.ActionSelectMapProvider; import net.tourbook.map2.action.ActionSetDefaultPosition; import net.tourbook.map2.action.ActionShowAllFilteredPhotos; import net.tourbook.map2.action.ActionShowLegendInMap; import net.tourbook.map2.action.ActionShowPOI; import net.tourbook.map2.action.ActionShowPhotos; import net.tourbook.map2.action.ActionShowScaleInMap; import net.tourbook.map2.action.ActionShowSliderInLegend; import net.tourbook.map2.action.ActionShowSliderInMap; import net.tourbook.map2.action.ActionShowStartEndInMap; import net.tourbook.map2.action.ActionShowTourInMap; import net.tourbook.map2.action.ActionShowTourInfoInMap; import net.tourbook.map2.action.ActionShowTourMarker; import net.tourbook.map2.action.ActionShowWayPoints; import net.tourbook.map2.action.ActionSynchTourZoomLevel; import net.tourbook.map2.action.ActionSynchWithPhoto; import net.tourbook.map2.action.ActionSynchWithSlider; import net.tourbook.map2.action.ActionSynchWithTour; import net.tourbook.map2.action.ActionTourColor; import net.tourbook.map2.action.ActionZoomCentered; import net.tourbook.map2.action.ActionZoomIn; import net.tourbook.map2.action.ActionZoomOut; import net.tourbook.map2.action.ActionZoomShowEntireEarth; import net.tourbook.map2.action.ActionZoomShowEntireTour; import net.tourbook.photo.IPhotoEventListener; import net.tourbook.photo.Photo; import net.tourbook.photo.PhotoEventId; import net.tourbook.photo.PhotoManager; import net.tourbook.photo.PhotoSelection; import net.tourbook.preferences.ITourbookPreferences; import net.tourbook.preferences.PrefPageMap2Appearance; import net.tourbook.srtm.IPreferences; 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.SelectionTourMarker; import net.tourbook.tour.TourEvent; import net.tourbook.tour.TourEventId; import net.tourbook.tour.TourInfoIconToolTipProvider; import net.tourbook.tour.TourManager; import net.tourbook.tour.photo.DialogPhotoProperties; import net.tourbook.tour.photo.IPhotoPropertiesListener; import net.tourbook.tour.photo.PhotoPropertiesEvent; import net.tourbook.tour.photo.TourPhotoLink; import net.tourbook.tour.photo.TourPhotoLinkSelection; import net.tourbook.training.TrainingManager; 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.ui.views.tourSegmenter.SelectedTourSegmenterSegments; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.dialogs.MessageDialogWithToggle; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.PreferenceConverter; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.graphics.PaletteData; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IPartListener2; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IViewPart; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchPartReference; import org.eclipse.ui.part.ViewPart; import de.byteholder.geoclipse.GeoclipseExtensions; import de.byteholder.geoclipse.map.IMapContextProvider; import de.byteholder.geoclipse.map.Map; import de.byteholder.geoclipse.map.MapLegend; import de.byteholder.geoclipse.map.event.IPOIListener; import de.byteholder.geoclipse.map.event.IPositionListener; import de.byteholder.geoclipse.map.event.IZoomListener; import de.byteholder.geoclipse.map.event.MapPOIEvent; import de.byteholder.geoclipse.map.event.MapPositionEvent; import de.byteholder.geoclipse.map.event.ZoomEvent; import de.byteholder.geoclipse.mapprovider.MP; import de.byteholder.geoclipse.mapprovider.MapProviderManager; import de.byteholder.gpx.PointOfInterest; /** * @author Wolfgang Schramm * @since 1.3.0 */ public class Map2View extends ViewPart implements IMapContextProvider, IPhotoEventListener, IPhotoPropertiesListener { public static final String ID = "net.tourbook.map2.view.Map2ViewId"; //$NON-NLS-1$ private static final String IMAGE_ACTION_TOUR_COLOR_ALTITUDE = net.tourbook.Messages.Image__graph_altitude; private static final String IMAGE_ACTION_TOUR_COLOR_ALTITUDE_DISABLED = net.tourbook.Messages.Image__graph_altitude_disabled; private static final String IMAGE_ACTION_TOUR_COLOR_GRADIENT = net.tourbook.Messages.Image__graph_gradient; private static final String IMAGE_ACTION_TOUR_COLOR_GRADIENT_DISABLED = net.tourbook.Messages.Image__graph_gradient_disabled; private static final String IMAGE_ACTION_TOUR_COLOR_PACE = net.tourbook.Messages.Image__graph_pace; private static final String IMAGE_ACTION_TOUR_COLOR_PACE_DISABLED = net.tourbook.Messages.Image__graph_pace_disabled; private static final String IMAGE_ACTION_TOUR_COLOR_PULSE = net.tourbook.Messages.Image__graph_heartbeat; private static final String IMAGE_ACTION_TOUR_COLOR_PULSE_DISABLED = net.tourbook.Messages.Image__graph_heartbeat_disabled; private static final String IMAGE_ACTION_TOUR_COLOR_SPEED = net.tourbook.Messages.Image__graph_speed; private static final String IMAGE_ACTION_TOUR_COLOR_SPEED_DISABLED = net.tourbook.Messages.Image__graph_speed_disabled; private static final String STATE_IS_SHOW_TOUR_IN_MAP = "STATE_IS_SHOW_TOUR_IN_MAP"; //$NON-NLS-1$ private static final String STATE_IS_SHOW_PHOTO_IN_MAP = "STATE_IS_SHOW_PHOTO_IN_MAP"; //$NON-NLS-1$ private static final String STATE_IS_SHOW_LEGEND_IN_MAP = "STATE_IS_SHOW_LEGEND_IN_MAP"; //$NON-NLS-1$ private static final String STATE_SYNC_WITH_PHOTO = "STATE_SYNC_WITH_PHOTO"; //$NON-NLS-1$ private static final String MEMENTO_SHOW_START_END_IN_MAP = "action.show-start-end-in-map"; //$NON-NLS-1$ private static final String MEMENTO_SHOW_TOUR_MARKER = "action.show-tour-marker"; //$NON-NLS-1$ private static final String MEMENTO_SHOW_SLIDER_IN_MAP = "action.show-slider-in-map"; //$NON-NLS-1$ private static final String MEMENTO_SHOW_SLIDER_IN_LEGEND = "action.show-slider-in-legend"; //$NON-NLS-1$ private static final String MEMENTO_SHOW_SCALE_IN_MAP = "action.show-scale-in-map"; //$NON-NLS-1$ private static final String MEMENTO_SHOW_TOUR_INFO_IN_MAP = "action.show-tour-info-in-map"; //$NON-NLS-1$ private static final String MEMENTO_SHOW_WAY_POINTS = "action.show-way-points-in-map"; //$NON-NLS-1$ private static final String MEMENTO_SYNCH_WITH_SELECTED_TOUR = "action.synch-with-selected-tour"; //$NON-NLS-1$ private static final String MEMENTO_SYNCH_WITH_TOURCHART_SLIDER = "action.synch-with-tourchart-slider"; //$NON-NLS-1$ private static final String MEMENTO_ZOOM_CENTERED = "action.zoom-centered"; //$NON-NLS-1$ private static final String MEMENTO_MAP_DIM_LEVEL = "action.map-dim-level"; //$NON-NLS-1$ private static final String MEMENTO_SYNCH_TOUR_ZOOM_LEVEL = "synch-tour-zoom-level"; //$NON-NLS-1$ private static final String MEMENTO_SELECTED_MAP_PROVIDER_ID = "selected.map-provider-id"; //$NON-NLS-1$ private static final String MEMENTO_DEFAULT_POSITION_ZOOM = "default.position.zoom-level"; //$NON-NLS-1$ private static final String MEMENTO_DEFAULT_POSITION_LATITUDE = "default.position.latitude"; //$NON-NLS-1$ private static final String MEMENTO_DEFAULT_POSITION_LONGITUDE = "default.position.longitude"; //$NON-NLS-1$ private static final String MEMENTO_TOUR_COLOR_ID = "tour-color-id"; //$NON-NLS-1$ static final String PREF_SHOW_TILE_INFO = "MapDebug.ShowTileInfo"; //$NON-NLS-1$ static final String PREF_SHOW_TILE_BORDER = "MapDebug.ShowTileBorder"; //$NON-NLS-1$ static final String PREF_DEBUG_MAP_DIM_LEVEL = "MapDebug.MapDimLevel"; //$NON-NLS-1$ private final IPreferenceStore _prefStore = TourbookPlugin.getDefault().getPreferenceStore(); private final IDialogSettings _state = TourbookPlugin.getDefault().getDialogSettingsSection(ID); private boolean _isPartVisible; /** * contains selection which was set when the part is hidden */ private ISelection _selectionWhenHidden; private IPartListener2 _partListener; private ISelectionListener _postSelectionListener; private IPropertyChangeListener _prefChangeListener; private ITourEventListener _tourEventListener; /** * Contains all tours which are displayed in the map. */ private final ArrayList<TourData> _allTourData = new ArrayList<TourData>(); private TourData _previousTourData; /** * contains photos which are displayed in the map */ private final ArrayList<Photo> _allPhotos = new ArrayList<Photo>(); private final ArrayList<Photo> _filteredPhotos = new ArrayList<Photo>(); private boolean _isPhotoFilterActive; private int _photoFilterRatingStars; private int _photoFilterRatingStarOperator; private boolean _isShowTour; private boolean _isShowPhoto; private boolean _isShowLegend; private boolean _isMapSynchedWithPhoto; private boolean _isMapSynchedWithTour; private boolean _isMapSynchedWithSlider; private boolean _isPositionCentered; private int _defaultZoom; private GeoPosition _defaultPosition = null; /** * when <code>true</code> a tour is painted, <code>false</code> a point of interrest is painted */ private boolean _isTourOrWayPoint; /* * tool tips */ private TourToolTip _tourToolTip; private TourInfoIconToolTipProvider _tourInfoToolTipProvider = new TourInfoIconToolTipProvider(); private ITourToolTipProvider _wayPointToolTipProvider = new WayPointToolTipProvider(); private String _poiName; private GeoPosition _poiPosition; private int _poiZoomLevel; private final DirectMappingPainter _directMappingPainter = new DirectMappingPainter(); /* * current position for the x-sliders */ private int _currentLeftSliderValueIndex; private int _currentRightSliderValueIndex; private int _currentSelectedSliderValueIndex; private MapLegend _mapLegend; private long _previousOverlayKey; private int _mapDimLevel = -1; private RGB _mapDimColor; private int _selectedProfileKey = 0; private final MapInfoManager _mapInfoManager = MapInfoManager.getInstance(); private final TourPainterConfiguration _tourPainterConfig = TourPainterConfiguration.getInstance(); private MapGraphId _tourColorId; private int _hashTourId; private int _hashTourData; private long _hashTourOverlayKey; private int _hashAllPhotos; /** * Is <code>true</code> when a link photo is displayed, otherwise a tour photo (photo which is * save in a tour) is displayed. */ private boolean _isLinkPhotoDisplayed; private ActionTourColor _actionTourColorAltitude; private ActionTourColor _actionTourColorGradient; private ActionTourColor _actionTourColorPulse; private ActionTourColor _actionTourColorSpeed; private ActionTourColor _actionTourColorPace; private ActionTourColor _actionTourColorHrZone; private ActionDimMap _actionDimMap; private ActionOpenPrefDialog _actionEdit2DMapPreferences; private ActionMap2Color _actionMapColor; private ActionManageMapProviders _actionManageProvider; private ActionPhotoProperties _actionPhotoFilter; private ActionReloadFailedMapImages _actionReloadFailedMapImages; private ActionSaveDefaultPosition _actionSaveDefaultPosition; private ActionSelectMapProvider _actionSelectMapProvider; private ActionSetDefaultPosition _actionSetDefaultPosition; private ActionShowAllFilteredPhotos _actionShowAllFilteredPhotos; private ActionShowLegendInMap _actionShowLegendInMap; private ActionShowPhotos _actionShowPhotos; private ActionShowPOI _actionShowPOI; private ActionShowScaleInMap _actionShowScaleInMap; private ActionShowSliderInMap _actionShowSliderInMap; private ActionShowSliderInLegend _actionShowSliderInLegend; private ActionShowStartEndInMap _actionShowStartEndInMap; private ActionShowTourInMap _actionShowTourInMap; private ActionShowTourInfoInMap _actionShowTourInfoInMap; private ActionShowTourMarker _actionShowTourMarker; private ActionShowWayPoints _actionShowWayPoints; private ActionSynchWithPhoto _actionSynchWithPhoto; private ActionSynchWithSlider _actionSynchWithSlider; private ActionSynchWithTour _actionSynchWithTour; private ActionSynchTourZoomLevel _actionSynchTourZoomLevel; private ActionZoomIn _actionZoomIn; private ActionZoomOut _actionZoomOut; private ActionZoomCentered _actionZoomCentered; private ActionZoomShowEntireEarth _actionZoomShowAll; private ActionZoomShowEntireTour _actionShowEntireTour; /* * UI controls */ private Map _map; public Map2View() { } public void actionDimMap(final int dimLevel) { // check if the dim level/color was changed if (_mapDimLevel != dimLevel) { _mapDimLevel = dimLevel; /* * dim color is stored in the pref store and not in the memento */ final RGB dimColor = PreferenceConverter.getColor(_prefStore, ITourbookPreferences.MAP_LAYOUT_MAP_DIMM_COLOR); _map.dimMap(dimLevel, dimColor); } } private void actionDimMap(final RGB dimColor) { if (_mapDimColor != dimColor) { _mapDimColor = dimColor; _map.dimMap(_mapDimLevel, dimColor); } } public void actionOpenMapProviderDialog() { final DialogModifyMapProvider dialog = new DialogModifyMapProvider(Display.getCurrent().getActiveShell()); if (dialog.open() == Window.OK) { _actionSelectMapProvider.updateMapProviders(); } } public void actionPhotoProperties(final boolean isFilterActive) { _isPhotoFilterActive = isFilterActive; updateFilteredPhotos(); } public void actionPOI() { final boolean isShowPOI = _actionShowPOI.isChecked(); _map.setShowPOI(isShowPOI); if (isShowPOI) { _map.setPoi(_poiPosition, _map.getZoom(), _poiName); } } public void actionReloadFailedMapImages() { _map.deleteFailedImageFiles(); _map.resetAll(); } public void actionSaveDefaultPosition() { _defaultZoom = _map.getZoom(); _defaultPosition = _map.getGeoCenter(); } public void actionSetDefaultPosition() { if (_defaultPosition == null) { _map.setZoom(_map.getMapProvider().getMinimumZoomLevel()); _map.setMapCenter(new GeoPosition(0, 0)); } else { _map.setZoom(_defaultZoom); _map.setMapCenter(_defaultPosition); } _map.paint(); } public void actionSetShowScaleInMap() { final boolean isScaleVisible = _actionShowScaleInMap.isChecked(); _map.setShowScale(isScaleVisible); _map.paint(); } public void actionSetShowStartEndInMap() { _tourPainterConfig.isShowStartEndInMap = _actionShowStartEndInMap.isChecked(); _map.disposeOverlayImageCache(); _map.paint(); } public void actionSetShowTourInfoInMap() { final boolean isVisible = _actionShowTourInfoInMap.isChecked(); if (isVisible) { _tourToolTip.addToolTipProvider(_tourInfoToolTipProvider); } else { _tourToolTip.removeToolTipProvider(_tourInfoToolTipProvider); } _map.paint(); } public void actionSetShowTourMarkerInMap() { _tourPainterConfig.isShowTourMarker = _actionShowTourMarker.isChecked(); _map.disposeOverlayImageCache(); _map.paint(); } public void actionSetShowWayPointsInMap() { final boolean isShowWayPoints = _actionShowWayPoints.isChecked(); if (isShowWayPoints) { _tourToolTip.addToolTipProvider(_wayPointToolTipProvider); } else { _tourToolTip.removeToolTipProvider(_wayPointToolTipProvider); } _tourPainterConfig.isShowWayPoints = isShowWayPoints; _map.disposeOverlayImageCache(); _map.paint(); } public void actionSetTourColor(final MapGraphId colorId) { setTourPainterColorProvider(colorId); _map.disposeOverlayImageCache(); _map.paint(); createLegendImage(getColorProvider(colorId)); } public void actionSetZoomCentered() { _isPositionCentered = _actionZoomCentered.isChecked(); } public void actionShowLegend() { _isShowLegend = _actionShowLegendInMap.isChecked(); _map.setShowLegend(_isShowLegend); _actionShowSliderInLegend.setEnabled(_isShowLegend); if (_isShowLegend == false) { _actionShowSliderInLegend.setChecked(false); } // update legend actionShowSlider(); _map.paint(); } public void actionShowPhotos() { _isShowPhoto = _actionShowPhotos.isChecked(); enableActions(); _tourPainterConfig.isPhotoVisible = _isShowPhoto; _map.setOverlayKey(Integer.toString(_filteredPhotos.hashCode())); _map.disposeOverlayImageCache(); _map.paint(); } public void actionShowSlider() { if ((_allTourData == null) || (_allTourData.size() == 0)) { return; } // repaint map _directMappingPainter.setPaintContext(_map, _isShowTour, _allTourData.get(0), _currentLeftSliderValueIndex, _currentRightSliderValueIndex, _actionShowSliderInMap.isChecked(), _actionShowSliderInLegend.isChecked()); _map.redraw(); } public void actionShowTour() { _isShowTour = _actionShowTourInMap.isChecked(); paintTours_10_All(); } /** * Sync map with photo */ public void actionSynchWithPhoto() { _isMapSynchedWithPhoto = _actionSynchWithPhoto.isChecked(); if (_isMapSynchedWithPhoto) { centerPhotos(_filteredPhotos, false); _map.paint(); } enableActions(true); } public void actionSynchWithSlider() { if (_allTourData.size() == 0) { return; } _isMapSynchedWithSlider = _actionSynchWithSlider.isChecked(); if (_isMapSynchedWithSlider) { _actionShowTourInMap.setChecked(true); // map must be synched with selected tour _actionSynchWithTour.setChecked(true); _isMapSynchedWithTour = true; _map.setShowOverlays(true); final TourData firstTourData = _allTourData.get(0); paintTours_20_One(firstTourData, false); positionMapTo_ValueIndex(firstTourData, _currentSelectedSliderValueIndex); } } public void actionSynchWithTour() { if (_allTourData.size() == 0) { return; } _isMapSynchedWithTour = _actionSynchWithTour.isChecked(); if (_isMapSynchedWithTour) { // force tour to be repainted, that it is synched immediately _previousTourData = null; _actionShowTourInMap.setChecked(true); _map.setShowOverlays(true); paintTours_20_One(_allTourData.get(0), true); } else { // disable synch with slider _isMapSynchedWithSlider = false; _actionSynchWithSlider.setChecked(false); } } public void actionZoomIn() { _map.setZoom(_map.getZoom() + 1); centerTour(); _map.paint(); } public void actionZoomOut() { _map.setZoom(_map.getZoom() - 1); centerTour(); _map.paint(); } public void actionZoomShowAllPhotos() { centerPhotos(_filteredPhotos, true); } public void actionZoomShowEntireMap() { _map.setMapCenter(new GeoPosition(0.0, 0.0)); _map.setZoom(_map.getMapProvider().getMinimumZoomLevel()); _map.paint(); } public void actionZoomShowEntireTour() { /* * reset position for all tours, it was really annoying that previous selected tours moved * to their previous positions, implemented in 11.8.2 */ TourManager.getInstance().resetMapPositions(); _actionShowTourInMap.setChecked(true); _map.setShowOverlays(true); paintEntireTour(); } private void addMapListener() { _map.addZoomListener(new IZoomListener() { @Override public void zoomChanged(final ZoomEvent event) { _mapInfoManager.setZoom(event.getZoom()); centerTour(); } }); _map.addMousePositionListener(new IPositionListener() { @Override public void setPosition(final MapPositionEvent event) { _mapInfoManager.setMousePosition(event.mapGeoPosition); } }); _map.addPOIListener(new IPOIListener() { @Override public void setPOI(final MapPOIEvent poiEvent) { _poiPosition = poiEvent.mapGeoPosition; _poiZoomLevel = poiEvent.mapZoomLevel; _poiName = poiEvent.mapPOIText; _actionShowPOI.setEnabled(true); _actionShowPOI.setChecked(true); } }); _map.setMapContextProvider(this); } private void addPartListener() { _partListener = new IPartListener2() { @Override public void partActivated(final IWorkbenchPartReference partRef) { } @Override public void partBroughtToTop(final IWorkbenchPartReference partRef) { } @Override public void partClosed(final IWorkbenchPartReference partRef) { if (partRef.getPart(false) == Map2View.this) { saveState(); _mapInfoManager.resetInfo(); } } @Override public void partDeactivated(final IWorkbenchPartReference partRef) { } @Override public void partHidden(final IWorkbenchPartReference partRef) { if (partRef.getPart(false) == Map2View.this) { _isPartVisible = false; } } @Override public void partInputChanged(final IWorkbenchPartReference partRef) { } @Override public void partOpened(final IWorkbenchPartReference partRef) { } @Override public void partVisible(final IWorkbenchPartReference partRef) { if (partRef.getPart(false) == Map2View.this) { _isPartVisible = true; if (_selectionWhenHidden != null) { onSelectionChanged(_selectionWhenHidden); _selectionWhenHidden = null; } } } }; getViewSite().getPage().addPartListener(_partListener); } private void addPrefListener() { _prefChangeListener = new IPropertyChangeListener() { @Override public void propertyChange(final PropertyChangeEvent event) { final String property = event.getProperty(); if (property.equals(PREF_SHOW_TILE_INFO) || property.equals(PREF_SHOW_TILE_BORDER)) { // map properties has changed final boolean isShowTileInfo = _prefStore.getBoolean(PREF_SHOW_TILE_INFO); final boolean isShowTileBorder = _prefStore.getBoolean(PREF_SHOW_TILE_BORDER); _map.setShowDebugInfo(isShowTileInfo, isShowTileBorder); _map.paint(); } else if (property.equals(PREF_DEBUG_MAP_DIM_LEVEL)) { float prefDimLevel = _prefStore.getInt(Map2View.PREF_DEBUG_MAP_DIM_LEVEL); prefDimLevel *= 2.55; prefDimLevel -= 255; final int dimLevel = (int) Math.abs(prefDimLevel); _actionDimMap.setDimLevel(dimLevel); actionDimMap(dimLevel); } else if (property.equals(ITourbookPreferences.MAP_LAYOUT_MAP_DIMM_COLOR)) { actionDimMap(PreferenceConverter.getColor(_prefStore, ITourbookPreferences.MAP_LAYOUT_MAP_DIMM_COLOR)); } else if (property.equals(ITourbookPreferences.MEASUREMENT_SYSTEM)) { // measurement system has changed net.tourbook.ui.UI.updateUnits(); _map.setMeasurementSystem(net.tourbook.ui.UI.UNIT_VALUE_DISTANCE, UI.UNIT_LABEL_DISTANCE); createLegendImage(_tourPainterConfig.getMapColorProvider()); _map.paint(); } else if (property.equals(ITourbookPreferences.MAP_LAYOUT_TOUR_PAINT_METHOD)) { _map.setTourPaintMethodEnhanced(// event.getNewValue().equals(PrefPageMap2Appearance.TOUR_PAINT_METHOD_COMPLEX)); } else if (property.equals(ITourbookPreferences.GRAPH_COLORS_HAS_CHANGED)) { // update tour and legend createLegendImage(_tourPainterConfig.getMapColorProvider()); _map.disposeOverlayImageCache(); _map.paint(); } else if (property.equals(IPreferences.SRTM_COLORS_SELECTED_PROFILE_KEY)) { final String newValue = event.getNewValue().toString(); final Integer prefProfileKey = Integer.valueOf(newValue); if (prefProfileKey != _selectedProfileKey) { _selectedProfileKey = prefProfileKey; _map.disposeTiles(); _map.paint(); } } } }; _prefStore.addPropertyChangeListener(_prefChangeListener); } /** * listen for events when a tour is selected */ private void addSelectionListener() { _postSelectionListener = new ISelectionListener() { @Override public void selectionChanged(final IWorkbenchPart part, final ISelection selection) { onSelectionChanged(selection); } }; getSite().getPage().addPostSelectionListener(_postSelectionListener); } private void addTourEventListener() { _tourEventListener = new ITourEventListener() { @Override public void tourChanged(final IWorkbenchPart part, final TourEventId eventId, final Object eventData) { if (part == Map2View.this) { return; } if (eventId == TourEventId.TOUR_CHART_PROPERTY_IS_MODIFIED) { resetMap(); } else if ((eventId == TourEventId.TOUR_CHANGED) && (eventData instanceof TourEvent)) { final ArrayList<TourData> modifiedTours = ((TourEvent) eventData).getModifiedTours(); if ((modifiedTours != null) && (modifiedTours.size() > 0)) { _allTourData.clear(); _allTourData.addAll(modifiedTours); resetMap(); } } else if (eventId == TourEventId.UPDATE_UI || eventId == TourEventId.CLEAR_DISPLAYED_TOUR) { clearView(); } else if (eventId == TourEventId.MARKER_SELECTION) { if (eventData instanceof SelectionTourMarker) { onSelectionChanged_TourMarker((SelectionTourMarker) eventData, false); } } else if ((eventId == TourEventId.TOUR_SELECTION) && eventData instanceof ISelection) { onSelectionChanged((ISelection) eventData); } else if (eventId == TourEventId.SLIDER_POSITION_CHANGED && eventData instanceof ISelection) { onSelectionChanged((ISelection) eventData); } } }; TourManager.getInstance().addTourEventListener(_tourEventListener); } /** * Center photo in the map * * @param allPhotos * @param isForceZooming */ private void centerPhotos(final ArrayList<Photo> allPhotos, final boolean isForceZooming) { final Set<GeoPosition> positionBounds = getPhotoBounds(allPhotos); if (positionBounds == null) { return; } final int zoom = _map.getZoom(); final Rectangle positionRect = _map.getPositionRect(positionBounds, zoom); final Point center = new Point(// positionRect.x + positionRect.width / 2, positionRect.y + positionRect.height / 2); final GeoPosition geoPosition = _map.getMapProvider().pixelToGeo(center, zoom); _map.setMapCenter(geoPosition); if (isForceZooming) { setBoundsZoomLevel(positionBounds, false); } } /** * Center the tour in the map when action is enabled */ private void centerTour() { if (_isPositionCentered) { final int zoom = _map.getZoom(); Set<GeoPosition> positionBounds = null; if (_isTourOrWayPoint) { positionBounds = _tourPainterConfig.getTourBounds(); if (positionBounds == null) { return; } } else { if (_poiPosition == null) { return; } positionBounds = new HashSet<GeoPosition>(); positionBounds.add(_poiPosition); } final Rectangle positionRect = _map.getPositionRect(positionBounds, zoom); final Point center = new Point(// positionRect.x + positionRect.width / 2, positionRect.y + positionRect.height / 2); final GeoPosition geoPosition = _map.getMapProvider().pixelToGeo(center, zoom); _map.setMapCenter(geoPosition); } } private void clearView() { // disable tour data _allTourData.clear(); _previousTourData = null; _tourPainterConfig.resetTourData(); _tourPainterConfig.setPhotos(null, false, false); _tourInfoToolTipProvider.setTourData(null); showDefaultMap(false); enableActions(); } private void createActions(final Composite parent) { _actionTourColorAltitude = new ActionTourColor(this, MapGraphId.Altitude, Messages.map_action_tour_color_altitude_tooltip, IMAGE_ACTION_TOUR_COLOR_ALTITUDE, IMAGE_ACTION_TOUR_COLOR_ALTITUDE_DISABLED); _actionTourColorGradient = new ActionTourColor(this, MapGraphId.Gradient, Messages.map_action_tour_color_gradient_tooltip, IMAGE_ACTION_TOUR_COLOR_GRADIENT, IMAGE_ACTION_TOUR_COLOR_GRADIENT_DISABLED); _actionTourColorPulse = new ActionTourColor(this, MapGraphId.Pulse, Messages.map_action_tour_color_pulse_tooltip, IMAGE_ACTION_TOUR_COLOR_PULSE, IMAGE_ACTION_TOUR_COLOR_PULSE_DISABLED); _actionTourColorSpeed = new ActionTourColor(this, MapGraphId.Speed, Messages.map_action_tour_color_speed_tooltip, IMAGE_ACTION_TOUR_COLOR_SPEED, IMAGE_ACTION_TOUR_COLOR_SPEED_DISABLED); _actionTourColorPace = new ActionTourColor(this, MapGraphId.Pace, Messages.map_action_tour_color_pase_tooltip, IMAGE_ACTION_TOUR_COLOR_PACE, IMAGE_ACTION_TOUR_COLOR_PACE_DISABLED); _actionTourColorHrZone = new ActionTourColor(this, MapGraphId.HrZone, Messages.Tour_Action_ShowHrZones_Tooltip, Messages.Image__PulseZones, Messages.Image__PulseZones_Disabled); _actionZoomIn = new ActionZoomIn(this); _actionZoomOut = new ActionZoomOut(this); _actionZoomCentered = new ActionZoomCentered(this); _actionZoomShowAll = new ActionZoomShowEntireEarth(this); _actionShowEntireTour = new ActionZoomShowEntireTour(this); _actionSynchWithPhoto = new ActionSynchWithPhoto(this); _actionSynchWithTour = new ActionSynchWithTour(this); _actionSynchWithSlider = new ActionSynchWithSlider(this); _actionSynchTourZoomLevel = new ActionSynchTourZoomLevel(this); _actionEdit2DMapPreferences = new ActionOpenPrefDialog(Messages.Map_Action_Edit2DMapPreferences, PrefPageMap2Appearance.ID); _actionMapColor = new ActionMap2Color(); _actionSelectMapProvider = new ActionSelectMapProvider(this); _actionSetDefaultPosition = new ActionSetDefaultPosition(this); _actionSaveDefaultPosition = new ActionSaveDefaultPosition(this); _actionPhotoFilter = new ActionPhotoProperties(this, parent, _state); _actionShowPhotos = new ActionShowPhotos(this); _actionShowAllFilteredPhotos = new ActionShowAllFilteredPhotos(this); _actionShowSliderInMap = new ActionShowSliderInMap(this); _actionShowSliderInLegend = new ActionShowSliderInLegend(this); _actionShowLegendInMap = new ActionShowLegendInMap(this); _actionShowScaleInMap = new ActionShowScaleInMap(this); _actionShowStartEndInMap = new ActionShowStartEndInMap(this); _actionShowPOI = new ActionShowPOI(this); _actionShowTourInMap = new ActionShowTourInMap(this); _actionShowTourInfoInMap = new ActionShowTourInfoInMap(this); _actionShowTourMarker = new ActionShowTourMarker(this); _actionShowWayPoints = new ActionShowWayPoints(this); _actionReloadFailedMapImages = new ActionReloadFailedMapImages(this); _actionDimMap = new ActionDimMap(this); _actionManageProvider = new ActionManageMapProviders(this); } /** * Creates a new legend image and disposes the old image. * * @param mapColorProvider */ private void createLegendImage(final IMapColorProvider mapColorProvider) { Image legendImage = _mapLegend.getImage(); // legend requires a tour with coordinates if (mapColorProvider == null /* || isPaintDataValid(fTourData) == false */) { showDefaultMap(_isShowPhoto); return; } // dispose old legend image if ((legendImage != null) && !legendImage.isDisposed()) { legendImage.dispose(); } final int legendWidth = IMapColorProvider.DEFAULT_LEGEND_WIDTH; int legendHeight = IMapColorProvider.DEFAULT_LEGEND_HEIGHT; final Rectangle mapBounds = _map.getBounds(); legendHeight = Math.max(1, Math.min(legendHeight, mapBounds.height - IMapColorProvider.LEGEND_TOP_MARGIN)); final RGB rgbTransparent = new RGB(0xfe, 0xfe, 0xfe); final ImageData overlayImageData = new ImageData(// legendWidth, legendHeight, 24, new PaletteData(0xff, 0xff00, 0xff0000)); overlayImageData.transparentPixel = overlayImageData.palette.getPixel(rgbTransparent); final Display display = Display.getCurrent(); legendImage = new Image(display, overlayImageData); final Rectangle imageBounds = legendImage.getBounds(); final int legendHeightNoMargin = imageBounds.height - 2 * IMapColorProvider.LEGEND_MARGIN_TOP_BOTTOM; boolean isDataAvailable = false; if (mapColorProvider instanceof IGradientColorProvider) { isDataAvailable = MapUtils.configureColorProvider(_allTourData, (IGradientColorProvider) mapColorProvider, ColorProviderConfig.MAP2, legendHeightNoMargin); } else if (mapColorProvider instanceof IDiscreteColorProvider) { isDataAvailable = createLegendImage_20_SetProviderValues((IDiscreteColorProvider) mapColorProvider, legendHeightNoMargin); } final Color transparentColor = new Color(display, rgbTransparent); final GC gc = new GC(legendImage); { gc.setBackground(transparentColor); gc.fillRectangle(imageBounds); if (isDataAvailable) { TourMapPainter.drawMap2Legend(gc, imageBounds, mapColorProvider, true); } else { // draws only a transparent image to hide the legend } } gc.dispose(); transparentColor.dispose(); _mapLegend.setImage(legendImage); } private boolean createLegendImage_20_SetProviderValues(final IDiscreteColorProvider legendProvider, final int legendHeight) { if (_allTourData.size() == 0) { return false; } // tell the legend provider how to draw the legend switch (legendProvider.getGraphId()) { case HrZone: boolean isValidData = false; for (final TourData tourData : _allTourData) { if (TrainingManager.isRequiredHrZoneDataAvailable(tourData) == false) { continue; } isValidData = true; } return isValidData; default: break; } return false; } @Override public void createPartControl(final Composite parent) { _mapLegend = new MapLegend(); _map = new Map(parent, SWT.NONE); _map.setPainting(false); _map.setDirectPainter(_directMappingPainter); // _map.setLiveView(true); _map.setLegend(_mapLegend); _map.setShowLegend(true); _map.setMeasurementSystem(net.tourbook.ui.UI.UNIT_VALUE_DISTANCE, UI.UNIT_LABEL_DISTANCE); final String tourPaintMethod = _prefStore.getString(ITourbookPreferences.MAP_LAYOUT_TOUR_PAINT_METHOD); _map.setTourPaintMethodEnhanced(tourPaintMethod.equals(PrefPageMap2Appearance.TOUR_PAINT_METHOD_COMPLEX)); // setup tool tip's _map.setTourToolTip(_tourToolTip = new TourToolTip(_map)); _tourInfoToolTipProvider.setActionsEnabled(true); _map.addControlListener(new ControlAdapter() { @Override public void controlResized(final ControlEvent e) { /* * check if the legend size must be adjusted */ final Image legendImage = _mapLegend.getImage(); if ((legendImage == null) || legendImage.isDisposed()) { return; } if ((_isTourOrWayPoint == false) || (_isShowTour == false) || (_isShowLegend == false)) { return; } /* * check height */ final Rectangle mapBounds = _map.getBounds(); final Rectangle legendBounds = legendImage.getBounds(); if ((mapBounds.height < IMapColorProvider.DEFAULT_LEGEND_HEIGHT + IMapColorProvider.LEGEND_TOP_MARGIN) || ((mapBounds.height > IMapColorProvider.DEFAULT_LEGEND_HEIGHT + IMapColorProvider.LEGEND_TOP_MARGIN) // && (legendBounds.height < IMapColorProvider.DEFAULT_LEGEND_HEIGHT)) // ) { createLegendImage(_tourPainterConfig.getMapColorProvider()); } } }); createActions(parent); fillActionBars(); addPartListener(); addPrefListener(); addSelectionListener(); addTourEventListener(); addMapListener(); PhotoManager.addPhotoEventListener(this); // register overlays which draw the tour GeoclipseExtensions.registerOverlays(_map); // initialize map when part is created and the map size is > 0 Display.getCurrent().asyncExec(new Runnable() { @Override public void run() { restoreState(); enableActions(); if (_allTourData.size() == 0) { // a tour is not displayed, find a tour provider which provides a tour showToursFromTourProvider(); } else { _map.paint(); } /* * enable map drawing, this is done very late to disable flickering which is caused * by setting up the map */ _map.setPainting(true); if (_mapDimLevel < 30) { showDimWarning(); } } }); } @Override public void dispose() { _allTourData.clear(); _filteredPhotos.clear(); _allPhotos.clear(); // dispose tilefactory resources final ArrayList<MP> allMapProviders = MapProviderManager.getInstance().getAllMapProviders(true); for (final MP mp : allMapProviders) { mp.disposeAllImages(); } _map.disposeOverlayImageCache(); getViewSite().getPage().removePostSelectionListener(_postSelectionListener); getViewSite().getPage().removePartListener(_partListener); TourManager.getInstance().removeTourEventListener(_tourEventListener); PhotoManager.removePhotoEventListener(this); _prefStore.removePropertyChangeListener(_prefChangeListener); super.dispose(); } private void enableActions() { enableActions(false); } private void enableActions(final boolean isForceTourColor) { _actionShowPOI.setEnabled(_poiPosition != null); // update legend action if (_isTourOrWayPoint) { _map.setShowLegend(_isShowLegend); if (_isShowLegend == false) { _actionShowSliderInLegend.setChecked(false); } } final boolean isAllPhotoAvailable = _allPhotos.size() > 0; final boolean isFilteredPhotoAvailable = _filteredPhotos.size() > 0; final boolean canShowFilteredPhoto = isFilteredPhotoAvailable && _isShowPhoto; /* * sync photo has a higher priority than sync tour, both cannot be synced at the same time */ final boolean isPhotoSynced = canShowFilteredPhoto && _isMapSynchedWithPhoto; final boolean canSyncTour = isPhotoSynced == false; /* * photo actions */ _actionPhotoFilter.setEnabled(isAllPhotoAvailable && _isShowPhoto); _actionShowAllFilteredPhotos.setEnabled(canShowFilteredPhoto); _actionShowPhotos.setEnabled(isAllPhotoAvailable); _actionSynchWithPhoto.setEnabled(canShowFilteredPhoto); /* * tour actions */ final int numberOfTours = _allTourData.size(); final boolean isTourAvailable = numberOfTours > 0; final boolean isMultipleTours = numberOfTours > 1 && _isShowTour; final boolean isOneTour = _isTourOrWayPoint && (isMultipleTours == false) && _isShowTour; _actionMapColor.setEnabled(isTourAvailable); _actionShowEntireTour.setEnabled(_isTourOrWayPoint && _isShowTour && isTourAvailable); _actionShowLegendInMap.setEnabled(_isTourOrWayPoint); _actionShowSliderInLegend.setEnabled(_isTourOrWayPoint && _isShowLegend); _actionShowSliderInMap.setEnabled(_isTourOrWayPoint); _actionShowStartEndInMap.setEnabled(isOneTour); _actionShowTourInfoInMap.setEnabled(isOneTour); _actionShowTourInMap.setEnabled(_isTourOrWayPoint); _actionShowTourMarker.setEnabled(_isTourOrWayPoint); _actionShowWayPoints.setEnabled(_isTourOrWayPoint); _actionSynchTourZoomLevel.setEnabled(isOneTour); _actionSynchWithSlider.setEnabled(canSyncTour); _actionSynchWithTour.setEnabled(canSyncTour); if (numberOfTours == 0) { _actionTourColorAltitude.setEnabled(false); _actionTourColorGradient.setEnabled(false); _actionTourColorPulse.setEnabled(false); _actionTourColorSpeed.setEnabled(false); _actionTourColorPace.setEnabled(false); _actionTourColorHrZone.setEnabled(false); } else if (isForceTourColor) { _actionTourColorAltitude.setEnabled(true); _actionTourColorGradient.setEnabled(true); _actionTourColorPulse.setEnabled(true); _actionTourColorSpeed.setEnabled(true); _actionTourColorPace.setEnabled(true); _actionTourColorHrZone.setEnabled(true); } else if (isOneTour) { final TourData oneTourData = _allTourData.get(0); final boolean isPulse = oneTourData.pulseSerie != null; final boolean canShowHrZones = oneTourData.getNumberOfHrZones() > 0 && isPulse; _actionTourColorAltitude.setEnabled(true); _actionTourColorGradient.setEnabled(oneTourData.getGradientSerie() != null); _actionTourColorPulse.setEnabled(isPulse); _actionTourColorSpeed.setEnabled(oneTourData.getSpeedSerie() != null); _actionTourColorPace.setEnabled(oneTourData.getPaceSerie() != null); _actionTourColorHrZone.setEnabled(canShowHrZones); } else { _actionTourColorAltitude.setEnabled(false); _actionTourColorGradient.setEnabled(false); _actionTourColorPulse.setEnabled(false); _actionTourColorSpeed.setEnabled(false); _actionTourColorPace.setEnabled(false); _actionTourColorHrZone.setEnabled(false); } } private void fillActionBars() { /* * fill view toolbar */ final IToolBarManager viewTbm = getViewSite().getActionBars().getToolBarManager(); viewTbm.add(_actionTourColorAltitude); viewTbm.add(_actionTourColorPulse); viewTbm.add(_actionTourColorSpeed); viewTbm.add(_actionTourColorPace); viewTbm.add(_actionTourColorGradient); viewTbm.add(_actionTourColorHrZone); viewTbm.add(new Separator()); viewTbm.add(_actionPhotoFilter); viewTbm.add(_actionShowPhotos); viewTbm.add(_actionShowAllFilteredPhotos); viewTbm.add(_actionSynchWithPhoto); viewTbm.add(new Separator()); viewTbm.add(_actionShowTourInMap); viewTbm.add(_actionShowEntireTour); viewTbm.add(_actionSynchWithTour); viewTbm.add(_actionSynchWithSlider); viewTbm.add(new Separator()); viewTbm.add(_actionSelectMapProvider); viewTbm.add(new Separator()); viewTbm.add(_actionZoomCentered); viewTbm.add(_actionZoomIn); viewTbm.add(_actionZoomOut); viewTbm.add(_actionZoomShowAll); viewTbm.add(_actionShowPOI); /* * fill view menu */ final IMenuManager menuMgr = getViewSite().getActionBars().getMenuManager(); fillMapContextMenu(menuMgr); } @Override public void fillContextMenu(final IMenuManager menuMgr) { fillMapContextMenu(menuMgr); } private void fillMapContextMenu(final IMenuManager menuMgr) { menuMgr.add(_actionShowLegendInMap); menuMgr.add(_actionShowScaleInMap); menuMgr.add(_actionShowSliderInMap); menuMgr.add(_actionShowSliderInLegend); menuMgr.add(new Separator()); menuMgr.add(_actionShowTourMarker); menuMgr.add(_actionShowWayPoints); menuMgr.add(_actionShowPOI); menuMgr.add(_actionShowStartEndInMap); menuMgr.add(_actionShowTourInfoInMap); menuMgr.add(new Separator()); menuMgr.add(_actionSetDefaultPosition); menuMgr.add(_actionSaveDefaultPosition); menuMgr.add(new Separator()); // it can happen that color id is not yet set if (_tourColorId != null) { // set color before menu is filled, this sets the action image and color id _actionMapColor.setColorId(_tourColorId); if (_tourColorId != MapGraphId.HrZone) { // hr zone has a different color provider and is not yet supported menuMgr.add(_actionMapColor); } } menuMgr.add(_actionEdit2DMapPreferences); menuMgr.add(_actionDimMap); menuMgr.add(_actionSynchTourZoomLevel); menuMgr.add(new Separator()); menuMgr.add(_actionManageProvider); menuMgr.add(_actionReloadFailedMapImages); } private IMapColorProvider getColorProvider(final MapGraphId colorId) { // final ColorDefinition colorDefinition = GraphColorManager.getInstance().getColorDefinition(colorId); // // final IMapColorProvider colorProvider = colorDefinition.getMap2Color_Active(); // // return colorProvider; return MapColorProvider.getActiveMap2ColorProvider(colorId); } public Map getMap() { return _map; } public int getMapDimLevel() { return _mapDimLevel; } /** * Calculate lat/lon bounds for all photos. * * @param allPhotos * @return */ private Set<GeoPosition> getPhotoBounds(final ArrayList<Photo> allPhotos) { /* * get min/max longitude/latitude */ double minLatitude = 0; double maxLatitude = 0; double minLongitude = 0; double maxLongitude = 0; boolean isFirst = true; for (final Photo photo : allPhotos) { final boolean isPhotoWithGps = _isLinkPhotoDisplayed ? photo.isLinkPhotoWithGps : photo.isTourPhotoWithGps; if (isPhotoWithGps) { double latitude; double longitude; if (_isLinkPhotoDisplayed) { latitude = photo.getLinkLatitude(); longitude = photo.getLinkLongitude(); } else { latitude = photo.getTourLatitude(); longitude = photo.getTourLongitude(); } // exclude invalid positions if (latitude == 0) { continue; } // System.out.println(net.tourbook.common.UI.timeStampNano() + " " + photo); // System.out.println(net.tourbook.common.UI.timeStampNano() + " \t" + latitude + "\t" + longitude); // // TODO remove SYSTEM.OUT.PRINTLN if (isFirst) { isFirst = false; minLatitude = maxLatitude = latitude; minLongitude = maxLongitude = longitude; } else { minLatitude = latitude < minLatitude ? latitude : minLatitude; maxLatitude = latitude > maxLatitude ? latitude : maxLatitude; minLongitude = longitude < minLongitude ? longitude : minLongitude; maxLongitude = longitude > maxLongitude ? longitude : maxLongitude; if (minLatitude == 0) { minLatitude = -180.0; } } } } if (isFirst) { // there are no photos with geo return null; } final Set<GeoPosition> mapPositions = new HashSet<GeoPosition>(); mapPositions.add(new GeoPosition(minLatitude, minLongitude)); mapPositions.add(new GeoPosition(maxLatitude, maxLongitude)); return mapPositions; } private Set<GeoPosition> getTourBounds(final ArrayList<TourData> tourDataList) { /* * get min/max longitude/latitude */ double allMinLatitude = Double.MIN_VALUE; double allMaxLatitude = 0; double allMinLongitude = 0; double allMaxLongitude = 0; for (final TourData tourData : tourDataList) { final double[] latitudeSerie = tourData.latitudeSerie; final double[] longitudeSerie = tourData.longitudeSerie; if ((latitudeSerie == null) || (longitudeSerie == null)) { continue; } final GeoPosition[] geoPosition = tourData.getGeoBounds(); if (geoPosition == null) { continue; } final double tourMinLatitude = geoPosition[0].latitude; final double tourMinLongitude = geoPosition[0].longitude; final double tourMaxLatitude = geoPosition[1].latitude; final double tourMaxLongitude = geoPosition[1].longitude; if (allMinLatitude == Double.MIN_VALUE) { // initialize first data point allMinLatitude = tourMinLatitude; allMinLongitude = tourMinLongitude; allMaxLatitude = tourMaxLatitude; allMaxLongitude = tourMaxLongitude; } else { allMinLatitude = tourMinLatitude < allMinLatitude ? tourMinLatitude : allMinLatitude; allMaxLatitude = tourMaxLatitude > allMaxLatitude ? tourMaxLatitude : allMaxLatitude; allMinLongitude = tourMinLongitude < allMinLongitude ? tourMinLongitude : allMinLongitude; allMaxLongitude = tourMaxLongitude > allMaxLongitude ? tourMaxLongitude : allMaxLongitude; } } if (allMinLatitude == Double.MIN_VALUE) { return null; } else { final Set<GeoPosition> mapPositions = new HashSet<GeoPosition>(); mapPositions.add(new GeoPosition(allMinLatitude, allMinLongitude)); mapPositions.add(new GeoPosition(allMaxLatitude, allMaxLongitude)); return mapPositions; } } private void keepMapPosition(final TourData tourData) { final GeoPosition centerPosition = _map.getGeoCenter(); tourData.mapZoomLevel = _map.getZoom(); tourData.mapCenterPositionLatitude = centerPosition.latitude; tourData.mapCenterPositionLongitude = centerPosition.longitude; } private void onSelectionChanged(final ISelection selection) { // System.out.println((UI.timeStampNano() + " [" + getClass().getSimpleName() + "] ") // + ("\tonSelectionChanged: " + selection)); // // TODO remove SYSTEM.OUT.PRINTLN if (_isPartVisible == false) { if (selection instanceof SelectionTourData || selection instanceof SelectionTourId || selection instanceof SelectionTourIds) { // keep only selected tours _selectionWhenHidden = selection; } return; } if (selection instanceof SelectionTourData) { final SelectionTourData selectionTourData = (SelectionTourData) selection; final TourData tourData = selectionTourData.getTourData(); paintTours_20_One(tourData, false); paintPhotoSelection(selection); enableActions(); } else if (selection instanceof SelectionTourId) { final SelectionTourId tourIdSelection = (SelectionTourId) selection; final TourData tourData = TourManager.getInstance().getTourData(tourIdSelection.getTourId()); paintTours_20_One(tourData, false); paintPhotoSelection(selection); enableActions(); } else if (selection instanceof SelectionTourIds) { // paint all selected tours final ArrayList<Long> tourIds = ((SelectionTourIds) selection).getTourIds(); if (tourIds.size() == 0) { // history tour (without tours) is displayed final ArrayList<Photo> allPhotos = paintPhotoSelection(selection); if (allPhotos.size() > 0) { // centerPhotos(allPhotos, false); showDefaultMap(true); enableActions(); } } else if (tourIds.size() == 1) { // only 1 tour is displayed, synch with this tour !!! final TourData tourData = TourManager.getInstance().getTourData(tourIds.get(0)); paintTours_20_One(tourData, false); paintPhotoSelection(selection); enableActions(); } else { // paint multiple tours paintTours(tourIds); paintPhotoSelection(selection); enableActions(true); } } else if (selection instanceof SelectionChartInfo) { final SelectionChartInfo chartInfo = (SelectionChartInfo) selection; TourData tourData = null; final Chart chart = chartInfo.getChart(); if (chart instanceof TourChart) { final TourChart tourChart = (TourChart) chart; tourData = tourChart.getTourData(); } if (tourData != null && tourData.isMultipleTours()) { // multiple tours are selected } else { // use old behaviour final ChartDataModel chartDataModel = chartInfo.chartDataModel; if (chartDataModel != null) { final Object tourId = chartDataModel.getCustomData(Chart.CUSTOM_DATA_TOUR_ID); if (tourId instanceof Long) { tourData = TourManager.getInstance().getTourData((Long) tourId); if (tourData == null) { // tour is not in the database, try to get it from the raw data manager final HashMap<Long, TourData> rawData = RawDataManager.getInstance().getImportedTours(); tourData = rawData.get(tourId); } } } } if (tourData != null) { positionMapTo_TourSliders(tourData, chartInfo.leftSliderValuesIndex, chartInfo.rightSliderValuesIndex, chartInfo.selectedSliderValuesIndex, null); enableActions(); } } else if (selection instanceof SelectionChartXSliderPosition) { final SelectionChartXSliderPosition xSliderPos = (SelectionChartXSliderPosition) selection; final Chart chart = xSliderPos.getChart(); if (chart == null) { return; } final Object customData = xSliderPos.getCustomData(); if (customData instanceof SelectedTourSegmenterSegments) { /* * This event is fired in the tour chart when a toursegmenter segment is selected */ selectTourSegments((SelectedTourSegmenterSegments) customData); } else { final ChartDataModel chartDataModel = chart.getChartDataModel(); final Object tourId = chartDataModel.getCustomData(Chart.CUSTOM_DATA_TOUR_ID); if (tourId instanceof Long) { final TourData tourData = TourManager.getInstance().getTourData((Long) tourId); if (tourData != null) { final int leftSliderValueIndex = xSliderPos.getLeftSliderValueIndex(); int rightSliderValueIndex = xSliderPos.getRightSliderValueIndex(); rightSliderValueIndex = rightSliderValueIndex == SelectionChartXSliderPosition.IGNORE_SLIDER_POSITION ? leftSliderValueIndex : rightSliderValueIndex; positionMapTo_TourSliders(// tourData, leftSliderValueIndex, rightSliderValueIndex, leftSliderValueIndex, null); enableActions(); } } } } else if (selection instanceof SelectionTourMarker) { final SelectionTourMarker markerSelection = (SelectionTourMarker) selection; onSelectionChanged_TourMarker(markerSelection, true); } else if (selection instanceof SelectionMapPosition) { final SelectionMapPosition mapPositionSelection = (SelectionMapPosition) selection; final int valueIndex1 = mapPositionSelection.getSlider1ValueIndex(); int valueIndex2 = mapPositionSelection.getSlider2ValueIndex(); valueIndex2 = valueIndex2 == SelectionChartXSliderPosition.IGNORE_SLIDER_POSITION ? valueIndex1 : valueIndex2; positionMapTo_TourSliders(// mapPositionSelection.getTourData(), valueIndex1, valueIndex2, valueIndex1, null); enableActions(); } else if (selection instanceof PointOfInterest) { _isTourOrWayPoint = false; clearView(); final PointOfInterest poi = (PointOfInterest) selection; _poiPosition = poi.getPosition(); _poiName = poi.getName(); final String boundingBox = poi.getBoundingBox(); if (boundingBox == null) { _poiZoomLevel = _map.getZoom(); } else { _poiZoomLevel = _map.getZoom(boundingBox); } if (_poiZoomLevel == -1) { _poiZoomLevel = _map.getZoom(); } _map.setPoi(_poiPosition, _poiZoomLevel, _poiName); _actionShowPOI.setChecked(true); enableActions(); } else if (selection instanceof StructuredSelection) { final StructuredSelection structuredSelection = (StructuredSelection) selection; final Object firstElement = structuredSelection.getFirstElement(); if (firstElement instanceof TVICatalogComparedTour) { final TVICatalogComparedTour comparedTour = (TVICatalogComparedTour) firstElement; final long tourId = comparedTour.getTourId(); final TourData tourData = TourManager.getInstance().getTourData(tourId); paintTours_20_One(tourData, false); } else if (firstElement instanceof TVICompareResultComparedTour) { final TVICompareResultComparedTour compareResultItem = (TVICompareResultComparedTour) firstElement; final TourData tourData = TourManager.getInstance() .getTourData(compareResultItem.getComparedTourData().getTourId()); paintTours_20_One(tourData, false); } else if (firstElement instanceof TourWayPoint) { final TourWayPoint wp = (TourWayPoint) firstElement; final TourData tourData = wp.getTourData(); paintTours_20_One(tourData, false); _map.setPOI(_wayPointToolTipProvider, wp); enableActions(); } enableActions(); } else if (selection instanceof PhotoSelection) { paintPhotos(((PhotoSelection) selection).galleryPhotos); enableActions(); } else if (selection instanceof SelectionTourCatalogView) { // show reference tour final SelectionTourCatalogView tourCatalogSelection = (SelectionTourCatalogView) selection; final TVICatalogRefTourItem refItem = tourCatalogSelection.getRefItem(); if (refItem != null) { final TourData tourData = TourManager.getInstance().getTourData(refItem.getTourId()); paintTours_20_One(tourData, false); enableActions(); } } else if (selection instanceof SelectionDeletedTours) { clearView(); } } private void onSelectionChanged_TourMarker(final SelectionTourMarker markerSelection, final boolean isDrawSlider) { // System.out.println((UI.timeStampNano() + " [" + getClass().getSimpleName() + "] ") // + ("\tonSelectionChanged_TourMarker")); // // TODO remove SYSTEM.OUT.PRINTLN final TourData tourData = markerSelection.getTourData(); updateUI_ShowTour(tourData); final ArrayList<TourMarker> allTourMarker = markerSelection.getSelectedTourMarker(); final int numberOfTourMarkers = allTourMarker.size(); int leftSliderValueIndex = 0; int rightSliderValueIndex = 0; if (tourData.isMultipleTours()) { if (numberOfTourMarkers == 1) { leftSliderValueIndex = allTourMarker.get(0).getMultiTourSerieIndex(); rightSliderValueIndex = leftSliderValueIndex; } else if (numberOfTourMarkers > 1) { leftSliderValueIndex = allTourMarker.get(0).getMultiTourSerieIndex(); rightSliderValueIndex = allTourMarker.get(numberOfTourMarkers - 1).getMultiTourSerieIndex(); } } else { if (numberOfTourMarkers == 1) { leftSliderValueIndex = allTourMarker.get(0).getSerieIndex(); rightSliderValueIndex = leftSliderValueIndex; } else if (numberOfTourMarkers > 1) { leftSliderValueIndex = allTourMarker.get(0).getSerieIndex(); rightSliderValueIndex = allTourMarker.get(numberOfTourMarkers - 1).getSerieIndex(); } } if (_isMapSynchedWithTour || _isMapSynchedWithSlider) { if (isDrawSlider) { positionMapTo_TourSliders(// tourData, leftSliderValueIndex, rightSliderValueIndex, leftSliderValueIndex, null); } else { positionMapTo_ValueIndex(tourData, leftSliderValueIndex); } keepMapPosition(tourData); } } private void paintEntireTour() { // get overlay key for all tours which have valid tour data long newOverlayKey = -1; for (final TourData tourData : _allTourData) { if (TourManager.isLatLonAvailable(tourData)) { newOverlayKey += tourData.getTourId(); } } // check if a valid tour is available if (newOverlayKey == -1) { showDefaultMap(_isShowPhoto); return; } // force single tour to be repainted _previousTourData = null; _tourPainterConfig.setTourData(_allTourData, _isShowTour); _tourPainterConfig.setPhotos(_filteredPhotos, _isShowPhoto, _isLinkPhotoDisplayed); _tourInfoToolTipProvider.setTourDataList(_allTourData); // final TourData firstTourData = _allTourData.get(0); // // // set slider position // _directMappingPainter.setPaintContext( // _map, // _isShowTour, // firstTourData, // _currentLeftSliderValueIndex, // _currentRightSliderValueIndex, // _actionShowSliderInMap.isChecked(), // _actionShowSliderInLegend.isChecked()); final Set<GeoPosition> tourBounds = getTourBounds(_allTourData); _tourPainterConfig.setTourBounds(tourBounds); _directMappingPainter.disablePaintContext(); _map.setShowOverlays(_isShowTour || _isShowPhoto); _map.setShowLegend(_isShowTour && _isShowLegend); if (_previousOverlayKey != newOverlayKey) { _previousOverlayKey = newOverlayKey; _map.setOverlayKey(Long.toString(newOverlayKey)); _map.disposeOverlayImageCache(); } setBoundsZoomLevel(tourBounds, false); createLegendImage(_tourPainterConfig.getMapColorProvider()); _map.paint(); } private void paintPhotos(final ArrayList<Photo> allNewPhotos) { /* * TESTING if a map redraw can be avoided, 15.6.2015 */ // DISABLED BECAUSE PHOTOS ARE NOT ALWAYS DISPLAYED final int allNewPhotoHash = allNewPhotos.hashCode(); if (allNewPhotoHash == _hashAllPhotos) { return; } _allPhotos.clear(); _allPhotos.addAll(allNewPhotos); _hashAllPhotos = _allPhotos.hashCode(); runPhotoFilter(); // // dump tour photos // System.out.println(net.tourbook.common.UI.timeStampNano() + " paintPhotos\t"); // // TODO remove SYSTEM.OUT.PRINTLN // // for (final Photo photo : allPhotos) { // System.out.println(net.tourbook.common.UI.timeStampNano() // + " " // + photo.imageFileName // + ("\t" + new DateTime(photo.adjustedTime))); // // TODO remove SYSTEM.OUT.PRINTLN // } if (_isShowPhoto && _isMapSynchedWithPhoto) { centerPhotos(_filteredPhotos, false); } _map.setShowOverlays(_isShowTour || _isShowPhoto); _map.setOverlayKey(Integer.toString(_filteredPhotos.hashCode())); _map.disposeOverlayImageCache(); _map.paint(); } /** * @param selection * @return Returns a list which contains all photos. */ private ArrayList<Photo> paintPhotoSelection(final ISelection selection) { _isLinkPhotoDisplayed = false; final ArrayList<Photo> allPhotos = new ArrayList<Photo>(); if (selection instanceof TourPhotoLinkSelection) { _isLinkPhotoDisplayed = true; final TourPhotoLinkSelection linkSelection = (TourPhotoLinkSelection) selection; final ArrayList<TourPhotoLink> tourPhotoLinks = linkSelection.tourPhotoLinks; for (final TourPhotoLink tourPhotoLink : tourPhotoLinks) { allPhotos.addAll(tourPhotoLink.linkPhotos); } } else { for (final TourData tourData : _allTourData) { final ArrayList<Photo> galleryPhotos = tourData.getGalleryPhotos(); if (galleryPhotos != null) { allPhotos.addAll(galleryPhotos); } } } paintPhotos(allPhotos); return allPhotos; } private void paintTours(final ArrayList<Long> tourIdList) { /* * TESTING if a map redraw can be avoided, 15.6.2015 */ final int tourIdsHashCode = tourIdList.hashCode(); final int allToursHashCode = _allTourData.hashCode(); if (tourIdsHashCode == _hashTourId && allToursHashCode == _hashTourData) { return; } _isTourOrWayPoint = true; // force single tour to be repainted _previousTourData = null; _directMappingPainter.disablePaintContext(); _map.setShowOverlays(_isShowTour || _isShowPhoto); _map.setShowLegend(_isShowTour && _isShowLegend); long newOverlayKey = _hashTourOverlayKey; if (tourIdList.hashCode() != _hashTourId || _allTourData.hashCode() != _hashTourData) { // tour data needs to be loaded newOverlayKey = TourManager.loadTourData(tourIdList, _allTourData, true); _hashTourId = tourIdList.hashCode(); _hashTourData = _allTourData.hashCode(); _hashTourOverlayKey = newOverlayKey; } _tourPainterConfig.setTourData(_allTourData, _isShowTour); _tourPainterConfig.setPhotos(_filteredPhotos, _isShowPhoto, _isLinkPhotoDisplayed); _tourInfoToolTipProvider.setTourDataList(_allTourData); if (_previousOverlayKey != newOverlayKey) { _previousOverlayKey = newOverlayKey; _map.setOverlayKey(Long.toString(newOverlayKey)); _map.disposeOverlayImageCache(); } if (_isMapSynchedWithTour) { // use default position for the tour final Set<GeoPosition> tourBounds = getTourBounds(_allTourData); setBoundsZoomLevel(tourBounds, true); } createLegendImage(_tourPainterConfig.getMapColorProvider()); _map.paint(); } /** * Show tours which are set in {@link #_allTourData}. */ private void paintTours_10_All() { if (_allTourData.size() == 0) { _tourInfoToolTipProvider.setTourData(null); return; } // show/hide legend _map.setShowLegend(_isShowTour); if (_allTourData.size() > 1) { // multiple tours are displayed paintTours_30_Multiple(); enableActions(true); } else { paintTours_20_One(_allTourData.get(0), true); enableActions(); } paintPhotoSelection(null); } /** * Paint the currently selected tour in the map * * @param tourData * @param forceRedraw * @param isSynchronized * when <code>true</code>, map will be synchronized */ private void paintTours_20_One(final TourData tourData, final boolean forceRedraw) { _isTourOrWayPoint = true; if (TourManager.isLatLonAvailable(tourData) == false) { showDefaultMap(_isShowPhoto); return; } // prevent loading the same tour if (forceRedraw == false) { if ((_allTourData.size() == 1) && (_allTourData.get(0) == tourData)) { return; } } // force multiple tours to be repainted _previousOverlayKey = -1; // check if this is a new tour boolean isNewTour = true; if ((_previousTourData != null) && (_previousTourData.getTourId().longValue() == tourData.getTourId().longValue())) { isNewTour = false; } _tourPainterConfig.setTourData(tourData, _isShowTour); /* * set tour into tour data list, this is currently used to draw the legend, it's also used * to figure out if multiple tours are selected */ _allTourData.clear(); _allTourData.add(tourData); _tourInfoToolTipProvider.setTourDataList(_allTourData); // set the paint context (slider position) for the direct mapping painter _directMappingPainter.setPaintContext(_map, _isShowTour, tourData, _currentLeftSliderValueIndex, _currentRightSliderValueIndex, _actionShowSliderInMap.isChecked(), _actionShowSliderInLegend.isChecked()); // set the tour bounds final GeoPosition[] tourBounds = tourData.getGeoBounds(); final HashSet<GeoPosition> tourBoundsSet = new HashSet<GeoPosition>(); tourBoundsSet.add(tourBounds[0]); tourBoundsSet.add(tourBounds[1]); _tourPainterConfig.setTourBounds(tourBoundsSet); _map.setShowOverlays(_isShowTour || _isShowPhoto); _map.setShowLegend(_isShowTour && _isShowLegend); /* * set position and zoom level for the tour */ if (_isMapSynchedWithTour) { if (((forceRedraw == false) && (_previousTourData != null)) || (tourData == _previousTourData)) { /* * keep map area for the previous tour */ keepMapPosition(_previousTourData); } if (tourData.mapCenterPositionLatitude == Double.MIN_VALUE) { // use default position for the tour setBoundsZoomLevel(tourBoundsSet, true); } else { // position tour to the previous position _map.setZoom(tourData.mapZoomLevel); _map.setMapCenter( new GeoPosition(tourData.mapCenterPositionLatitude, tourData.mapCenterPositionLongitude)); } } // keep tour data _previousTourData = tourData; if (isNewTour || forceRedraw) { // adjust legend values for the new or changed tour createLegendImage(_tourPainterConfig.getMapColorProvider()); _map.setOverlayKey(tourData.getTourId().toString()); _map.disposeOverlayImageCache(); } _map.paint(); } /** * paints the tours which are set in {@link #_allTourData} */ private void paintTours_30_Multiple() { _isTourOrWayPoint = true; // force single tour to be repainted _previousTourData = null; _tourPainterConfig.setTourData(_allTourData, _isShowTour); _tourPainterConfig.setPhotos(_filteredPhotos, _isShowPhoto, _isLinkPhotoDisplayed); _tourInfoToolTipProvider.setTourDataList(_allTourData); _directMappingPainter.disablePaintContext(); _map.setShowOverlays(_isShowTour || _isShowPhoto); _map.setShowLegend(_isShowTour && _isShowLegend); // get overlay key for all tours which have valid tour data long newOverlayKey = -1; for (final TourData tourData : _allTourData) { if (TourManager.isLatLonAvailable(tourData)) { newOverlayKey += tourData.getTourId(); } } if (_previousOverlayKey != newOverlayKey) { _previousOverlayKey = newOverlayKey; _map.setOverlayKey(Long.toString(newOverlayKey)); _map.disposeOverlayImageCache(); } createLegendImage(_tourPainterConfig.getMapColorProvider()); _map.paint(); } @Override public void photoEvent(final IViewPart viewPart, final PhotoEventId photoEventId, final Object data) { if (photoEventId == PhotoEventId.PHOTO_SELECTION) { if (data instanceof TourPhotoLinkSelection) { onSelectionChanged((TourPhotoLinkSelection) data); } else if (data instanceof PhotoSelection) { onSelectionChanged((PhotoSelection) data); } } else if (photoEventId == PhotoEventId.PHOTO_ATTRIBUTES_ARE_MODIFIED) { if (data instanceof ArrayList<?>) { updateFilteredPhotos(); } } else if (photoEventId == PhotoEventId.PHOTO_IMAGE_PATH_IS_MODIFIED) { // this is not working, manual refresh is necessary // _map.redraw(); } } @Override public void photoPropertyEvent(final PhotoPropertiesEvent event) { _photoFilterRatingStars = event.filterRatingStars; _photoFilterRatingStarOperator = event.fiterRatingStarOperator; updateFilteredPhotos(); } private void positionMapTo_TourSliders(final TourData tourData, final int leftSliderValuesIndex, final int rightSliderValuesIndex, final int selectedSliderIndex, final Set<GeoPosition> geoPositions) { _isTourOrWayPoint = true; if (TourManager.isLatLonAvailable(tourData) == false) { showDefaultMap(_isShowPhoto); return; } _currentLeftSliderValueIndex = leftSliderValuesIndex; _currentRightSliderValueIndex = rightSliderValuesIndex; _currentSelectedSliderValueIndex = selectedSliderIndex; _directMappingPainter.setPaintContext(_map, _isShowTour, tourData, leftSliderValuesIndex, rightSliderValuesIndex, _actionShowSliderInMap.isChecked(), _actionShowSliderInLegend.isChecked()); if (_isMapSynchedWithSlider) { if (geoPositions != null) { // center to the left AND right slider setBoundsZoomLevel(geoPositions, true); } else { positionMapTo_ValueIndex(tourData, _currentSelectedSliderValueIndex); } _map.paint(); } else { _map.redraw(); } } /** * Calculate the bounds for the tour in latitude and longitude values * * @param tourData * @param valueIndex * @return */ private void positionMapTo_ValueIndex(final TourData tourData, final int valueIndex) { if (tourData == null || tourData.latitudeSerie == null) { return; } final double[] latitudeSerie = tourData.latitudeSerie; final double[] longitudeSerie = tourData.longitudeSerie; final int sliderIndex = Math.max(0, Math.min(valueIndex, latitudeSerie.length - 1)); _map.setMapCenter(new GeoPosition(latitudeSerie[sliderIndex], longitudeSerie[sliderIndex])); } private void resetMap() { if (_allTourData.size() == 0) { return; } _map.disposeOverlayImageCache(); paintTours_10_All(); _map.paint(); } private void restoreState() { // is show tour _isShowTour = Util.getStateBoolean(_state, STATE_IS_SHOW_TOUR_IN_MAP, true); _actionShowTourInMap.setChecked(_isShowTour); // is show photo _isShowPhoto = Util.getStateBoolean(_state, STATE_IS_SHOW_PHOTO_IN_MAP, true); _actionShowPhotos.setChecked(_isShowPhoto); // is show legend _isShowLegend = Util.getStateBoolean(_state, STATE_IS_SHOW_LEGEND_IN_MAP, true); _actionShowLegendInMap.setChecked(_isShowLegend); // is sync with photo _isMapSynchedWithPhoto = Util.getStateBoolean(_state, STATE_SYNC_WITH_PHOTO, true); _actionSynchWithPhoto.setChecked(_isMapSynchedWithPhoto); // checkbox: is tour centered final boolean isTourCentered = _state.getBoolean(MEMENTO_ZOOM_CENTERED); _actionZoomCentered.setChecked(isTourCentered); _isPositionCentered = isTourCentered; // checkbox: synch map with tour final boolean isSynchTour = Util.getStateBoolean(_state, MEMENTO_SYNCH_WITH_SELECTED_TOUR, true); _actionSynchWithTour.setChecked(isSynchTour); _isMapSynchedWithTour = isSynchTour; // ckeckbox: synch with tour chart slider final boolean isSynchSlider = _state.getBoolean(MEMENTO_SYNCH_WITH_TOURCHART_SLIDER); _actionSynchWithSlider.setChecked(isSynchSlider); _isMapSynchedWithSlider = isSynchSlider; // _actionSynchTourZoomLevel.setZoomLevel(Util.getStateInt(_state, MEMENTO_SYNCH_TOUR_ZOOM_LEVEL, 0)); _mapDimLevel = Util.getStateInt(_state, MEMENTO_MAP_DIM_LEVEL, -1); // checkbox: show start/end in map _actionShowStartEndInMap.setChecked(_state.getBoolean(MEMENTO_SHOW_START_END_IN_MAP)); _tourPainterConfig.isShowStartEndInMap = _actionShowStartEndInMap.isChecked(); // show tour marker final boolean isShowMarker = Util.getStateBoolean(_state, MEMENTO_SHOW_TOUR_MARKER, true); _actionShowTourMarker.setChecked(isShowMarker); _tourPainterConfig.isShowTourMarker = isShowMarker; // checkbox: show way points final boolean isShowWayPoints = Util.getStateBoolean(_state, MEMENTO_SHOW_WAY_POINTS, true); _actionShowWayPoints.setChecked(isShowWayPoints); _tourPainterConfig.isShowWayPoints = isShowWayPoints; if (isShowWayPoints) { _tourToolTip.addToolTipProvider(_wayPointToolTipProvider); } // checkbox: show tour info in map final boolean isShowTourInfo = Util.getStateBoolean(_state, MEMENTO_SHOW_TOUR_INFO_IN_MAP, true); _actionShowTourInfoInMap.setChecked(isShowTourInfo); if (isShowTourInfo) { _tourToolTip.addToolTipProvider(_tourInfoToolTipProvider); } // checkbox: show scale final boolean isScaleVisible = Util.getStateBoolean(_state, MEMENTO_SHOW_SCALE_IN_MAP, true); _actionShowScaleInMap.setChecked(isScaleVisible); _map.setShowScale(isScaleVisible); // show slider _actionShowSliderInMap.setChecked(Util.getStateBoolean(_state, MEMENTO_SHOW_SLIDER_IN_MAP, true)); _actionShowSliderInLegend.setChecked(_state.getBoolean(MEMENTO_SHOW_SLIDER_IN_LEGEND)); // restore map provider by selecting the last used map factory _actionSelectMapProvider.selectMapProvider(_state.get(MEMENTO_SELECTED_MAP_PROVIDER_ID)); _actionPhotoFilter.restoreState(); // default position _defaultZoom = Util.getStateInt(_state, MEMENTO_DEFAULT_POSITION_ZOOM, 10); _defaultPosition = new GeoPosition(// Util.getStateDouble(_state, MEMENTO_DEFAULT_POSITION_LATITUDE, 46.303074), Util.getStateDouble(_state, MEMENTO_DEFAULT_POSITION_LONGITUDE, 7.526386)); // tour color try { final String stateColorId = Util.getStateString(_state, MEMENTO_TOUR_COLOR_ID, MapGraphId.Altitude.name()); MapGraphId colorId; try { colorId = MapGraphId.valueOf(stateColorId); } catch (final Exception e) { // set default colorId = MapGraphId.Altitude; } switch (colorId) { case Altitude: _actionTourColorAltitude.setChecked(true); break; case Gradient: _actionTourColorGradient.setChecked(true); break; case Pace: _actionTourColorPace.setChecked(true); break; case Pulse: _actionTourColorPulse.setChecked(true); break; case Speed: _actionTourColorSpeed.setChecked(true); break; case HrZone: _actionTourColorHrZone.setChecked(true); break; default: _actionTourColorAltitude.setChecked(true); break; } setTourPainterColorProvider(colorId); } catch (final NumberFormatException e) { _actionTourColorAltitude.setChecked(true); } // draw tour with default color _map.setShowOverlays(_isShowTour || _isShowPhoto); _map.setShowLegend(_isShowTour); // check legend provider if (_tourPainterConfig.getMapColorProvider() == null) { // set default legend provider setTourPainterColorProvider(MapGraphId.Altitude); // hide legend _map.setShowLegend(false); } // debug info final boolean isShowTileInfo = _prefStore.getBoolean(Map2View.PREF_SHOW_TILE_INFO); final boolean isShowTileBorder = _prefStore.getBoolean(PREF_SHOW_TILE_BORDER); _map.setShowDebugInfo(isShowTileInfo, isShowTileBorder); // set dim level/color after the map providers are set if (_mapDimLevel == -1) { _mapDimLevel = 0xff; } final RGB dimColor = PreferenceConverter.getColor(_prefStore, ITourbookPreferences.MAP_LAYOUT_MAP_DIMM_COLOR); _map.setDimLevel(_mapDimLevel, dimColor); _mapDimLevel = _actionDimMap.setDimLevel(_mapDimLevel); // display the map with the default position actionSetDefaultPosition(); } /** * Filter photos by rating stars. */ private void runPhotoFilter() { _filteredPhotos.clear(); if (_isPhotoFilterActive) { final boolean isNoStar = _photoFilterRatingStars == 0; final boolean isEqual = _photoFilterRatingStarOperator == DialogPhotoProperties.OPERATOR_IS_EQUAL; final boolean isMore = _photoFilterRatingStarOperator == DialogPhotoProperties.OPERATOR_IS_MORE_OR_EQUAL; final boolean isLess = _photoFilterRatingStarOperator == DialogPhotoProperties.OPERATOR_IS_LESS_OR_EQUAL; for (final Photo photo : _allPhotos) { final int ratingStars = photo.ratingStars; if (isNoStar && ratingStars == 0) { // only photos without stars are displayed _filteredPhotos.add(photo); } else if (isEqual && ratingStars == _photoFilterRatingStars) { _filteredPhotos.add(photo); } else if (isMore && ratingStars >= _photoFilterRatingStars) { _filteredPhotos.add(photo); } else if (isLess && ratingStars <= _photoFilterRatingStars) { _filteredPhotos.add(photo); } } } else { // photo filter is not active _filteredPhotos.addAll(_allPhotos); } _tourPainterConfig.setPhotos(_filteredPhotos, _isShowPhoto, _isLinkPhotoDisplayed); enableActions(true); PhotoManager.firePhotoEvent(this, PhotoEventId.PHOTO_FILTER, new MapFilterData(_allPhotos.size(), _filteredPhotos.size())); // System.out.println(net.tourbook.common.UI.timeStampNano() // + " runPhotoFilter" // + ("\tall=" + _allPhotos.size()) // + ("\tfilter=" + _filteredPhotos.size())); // // TODO remove SYSTEM.OUT.PRINTLN } private void saveState() { // save checked actions _state.put(STATE_IS_SHOW_TOUR_IN_MAP, _isShowTour); _state.put(STATE_IS_SHOW_PHOTO_IN_MAP, _isShowPhoto); _state.put(STATE_IS_SHOW_LEGEND_IN_MAP, _isShowLegend); _state.put(STATE_SYNC_WITH_PHOTO, _isMapSynchedWithPhoto); _state.put(MEMENTO_ZOOM_CENTERED, _actionZoomCentered.isChecked()); _state.put(MEMENTO_SYNCH_WITH_SELECTED_TOUR, _actionSynchWithTour.isChecked()); _state.put(MEMENTO_SYNCH_WITH_TOURCHART_SLIDER, _actionSynchWithSlider.isChecked()); _state.put(MEMENTO_SYNCH_TOUR_ZOOM_LEVEL, _actionSynchTourZoomLevel.getZoomLevel()); _state.put(MEMENTO_MAP_DIM_LEVEL, _mapDimLevel); _state.put(MEMENTO_SHOW_START_END_IN_MAP, _actionShowStartEndInMap.isChecked()); _state.put(MEMENTO_SHOW_SCALE_IN_MAP, _actionShowScaleInMap.isChecked()); _state.put(MEMENTO_SHOW_SLIDER_IN_MAP, _actionShowSliderInMap.isChecked()); _state.put(MEMENTO_SHOW_SLIDER_IN_LEGEND, _actionShowSliderInLegend.isChecked()); _state.put(MEMENTO_SHOW_TOUR_MARKER, _actionShowTourMarker.isChecked()); _state.put(MEMENTO_SHOW_TOUR_INFO_IN_MAP, _actionShowTourInfoInMap.isChecked()); _state.put(MEMENTO_SHOW_WAY_POINTS, _actionShowWayPoints.isChecked()); _state.put(MEMENTO_SELECTED_MAP_PROVIDER_ID, _actionSelectMapProvider.getSelectedMapProvider().getId()); if (_defaultPosition == null) { final MP mapProvider = _map.getMapProvider(); _state.put(MEMENTO_DEFAULT_POSITION_ZOOM, mapProvider == null ? // _defaultZoom : mapProvider.getMinimumZoomLevel()); _state.put(MEMENTO_DEFAULT_POSITION_LATITUDE, 0.0F); _state.put(MEMENTO_DEFAULT_POSITION_LONGITUDE, 0.0F); } else { _state.put(MEMENTO_DEFAULT_POSITION_ZOOM, _defaultZoom); _state.put(MEMENTO_DEFAULT_POSITION_LATITUDE, (float) _defaultPosition.latitude); _state.put(MEMENTO_DEFAULT_POSITION_LONGITUDE, (float) _defaultPosition.longitude); } // tour color MapGraphId colorId; if (_actionTourColorGradient.isChecked()) { colorId = MapGraphId.Gradient; } else if (_actionTourColorPulse.isChecked()) { colorId = MapGraphId.Pulse; } else if (_actionTourColorSpeed.isChecked()) { colorId = MapGraphId.Speed; } else if (_actionTourColorPace.isChecked()) { colorId = MapGraphId.Pace; } else if (_actionTourColorHrZone.isChecked()) { colorId = MapGraphId.HrZone; } else { // use altitude as default colorId = MapGraphId.Altitude; } _state.put(MEMENTO_TOUR_COLOR_ID, colorId.name()); _actionPhotoFilter.saveState(); } private void selectTourSegments(final SelectedTourSegmenterSegments selectedSegmenterConfig) { if (_allTourData.size() < 1) { return; } final int leftSliderValueIndex = selectedSegmenterConfig.xSliderSerieIndexLeft; final int rightSliderValueIndex = selectedSegmenterConfig.xSliderSerieIndexRight; final TourData segmenterTourData = selectedSegmenterConfig.tourData; final Set<GeoPosition> mapPositions = new HashSet<GeoPosition>(); if (_allTourData.size() == 1) { final TourData mapTourData = _allTourData.get(0); // ensure it's the same tour if (segmenterTourData != mapTourData) { return; } final GeoPosition leftPosition = new GeoPosition(mapTourData.latitudeSerie[leftSliderValueIndex], mapTourData.longitudeSerie[leftSliderValueIndex]); final GeoPosition rightPosition = new GeoPosition(mapTourData.latitudeSerie[rightSliderValueIndex], mapTourData.longitudeSerie[rightSliderValueIndex]); mapPositions.add(leftPosition); mapPositions.add(rightPosition); positionMapTo_TourSliders(// mapTourData, leftSliderValueIndex, rightSliderValueIndex, leftSliderValueIndex, mapPositions); enableActions(); } else { // multiple tourdata, I'm not sure if this still occures after merging multiple tours into one tourdata } } /** * Calculates a zoom level so that all points in the specified set will be visible on screen. * This is useful if you have a bunch of points in an area like a city and you want to zoom out * so that the entire city and it's points are visible without panning. * * @param positions * A set of GeoPositions to calculate the new zoom from * @param adjustZoomLevel * when <code>true</code> the zoom level will be adjusted to user settings */ private void setBoundsZoomLevel(final Set<GeoPosition> positions, final boolean isAdjustZoomLevel) { if ((positions == null) || (positions.size() < 2)) { return; } final MP mp = _map.getMapProvider(); final int maximumZoomLevel = mp.getMaximumZoomLevel(); int zoom = mp.getMinimumZoomLevel(); Rectangle positionRect = _map.getPositionRect(positions, zoom); Rectangle viewport = _map.getWorldPixelViewport(); // zoom in until the tour is larger than the viewport while ((positionRect.width < viewport.width) && (positionRect.height < viewport.height)) { // center position in the map final Point center = new Point(// positionRect.x + positionRect.width / 2, positionRect.y + positionRect.height / 2); _map.setMapCenter(mp.pixelToGeo(center, zoom)); zoom++; // check zoom level if (zoom >= maximumZoomLevel) { break; } _map.setZoom(zoom); positionRect = _map.getPositionRect(positions, zoom); viewport = _map.getWorldPixelViewport(); } // the algorithm generated a larger zoom level as necessary zoom--; int adjustedZoomLevel = 0; if (isAdjustZoomLevel) { adjustedZoomLevel = _tourPainterConfig.getSynchTourZoomLevel(); } _map.setZoom(zoom + adjustedZoomLevel); } @Override public void setFocus() { _map.setFocus(); } private void setTourPainterColorProvider(final MapGraphId colorId) { _tourColorId = colorId; final IMapColorProvider mapColorProvider = getColorProvider(colorId); _tourPainterConfig.setMapColorProvider(mapColorProvider); } private void showDefaultMap(final boolean isShowOverlays) { // disable tour actions in this view _isTourOrWayPoint = false; // disable tour data _allTourData.clear(); _previousTourData = null; _tourPainterConfig.resetTourData(); // update direct painter to draw nothing _directMappingPainter.setPaintContext(_map, false, null, 0, 0, false, false); _map.setShowOverlays(isShowOverlays); _map.setShowLegend(false); _map.paint(); } /** * show warning that map is dimmed and can be invisible */ private void showDimWarning() { if (_prefStore.getBoolean(ITourbookPreferences.MAP_VIEW_CONFIRMATION_SHOW_DIM_WARNING) == false) { Display.getCurrent().asyncExec(new Runnable() { @Override public void run() { final MessageDialogWithToggle dialog = MessageDialogWithToggle.openInformation( Display.getCurrent().getActiveShell(), // Messages.map_dlg_dim_warning_title, // title Messages.map_dlg_dim_warning_message, // message Messages.map_dlg_dim_warning_toggle_message, // toggle message false, // toggle default state null, null); _prefStore.setValue(ITourbookPreferences.MAP_VIEW_CONFIRMATION_SHOW_DIM_WARNING, dialog.getToggleState()); } }); } } private void showToursFromTourProvider() { Display.getCurrent().asyncExec(new Runnable() { @Override public void run() { // validate widget if (_map.isDisposed()) { return; } /* * check if tour is set from a selection provider */ if (_allTourData.size() > 0) { return; } final ArrayList<TourData> tourDataList = TourManager.getSelectedTours(); if (tourDataList != null) { _allTourData.clear(); _allTourData.addAll(tourDataList); paintTours_10_All(); } } }); } private void updateFilteredPhotos() { runPhotoFilter(); _map.disposeOverlayImageCache(); _map.paint(); } /** * Show tour when it is not yet displayed. * * @param tourData */ private void updateUI_ShowTour(final TourData tourData) { // check if the marker tour is displayed final long markerTourId = tourData.getTourId().longValue(); boolean isTourVisible = false; for (final TourData mapTourData : _allTourData) { if (mapTourData.getTourId().longValue() == markerTourId) { isTourVisible = true; break; } } if (isTourVisible == false) { // tour is not yet visible, show it now _allTourData.clear(); _allTourData.add(tourData); paintTours_10_All(); } } }