Java tutorial
/******************************************************************************* * Copyright (C) 2005, 2016 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.tour.photo; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; import net.tourbook.Messages; import net.tourbook.application.TourbookPlugin; import net.tourbook.common.UI; import net.tourbook.common.time.TimeTools; import net.tourbook.common.util.ColumnDefinition; import net.tourbook.common.util.ColumnManager; import net.tourbook.common.util.ITourViewer; import net.tourbook.common.util.Util; import net.tourbook.data.TourData; import net.tourbook.data.TourPhoto; import net.tourbook.photo.Camera; import net.tourbook.photo.Photo; import net.tourbook.photo.PhotoEventId; import net.tourbook.photo.PhotoManager; import net.tourbook.photo.PhotoSelection; import net.tourbook.photo.PicDirView; import net.tourbook.preferences.ITourbookPreferences; import net.tourbook.tour.SelectionDeletedTours; import net.tourbook.tour.TourManager; import net.tourbook.ui.ITourProvider; import net.tourbook.ui.TableColumnFactory; import net.tourbook.ui.action.ActionModifyColumns; import org.eclipse.core.commands.Command; import org.eclipse.core.commands.State; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.dialogs.MessageDialogWithToggle; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.layout.PixelConverter; 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.ColumnViewer; 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.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerCell; import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseWheelListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Link; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Spinner; import org.eclipse.swt.widgets.Table; import org.eclipse.ui.IPartListener2; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IViewPart; import org.eclipse.ui.IViewReference; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchPartReference; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.commands.ICommandService; import org.eclipse.ui.handlers.RegistryToggleState; import org.eclipse.ui.part.PageBook; import org.eclipse.ui.part.ViewPart; import org.joda.time.Period; import org.joda.time.format.PeriodFormatter; import org.joda.time.format.PeriodFormatterBuilder; public class TourPhotoLinkView extends ViewPart implements ITourProvider, ITourViewer { public static final String ID = "net.tourbook.photo.PhotosAndToursView.ID"; //$NON-NLS-1$ private static final String STATE_FILTER_NOT_SAVED_PHOTOS = "STATE_FILTER_NOT_SAVED_PHOTOS"; //$NON-NLS-1$ private static final String STATE_FILTER_TOUR_WITH_PHOTOS = "STATE_FILTER_TOUR_WITH_PHOTOS"; //$NON-NLS-1$ private static final String STATE_SELECTED_CAMERA_NAME = "STATE_SELECTED_CAMERA_NAME"; //$NON-NLS-1$ public static final String IMAGE_PIC_DIR_VIEW = "IMAGE_PIC_DIR_VIEW"; //$NON-NLS-1$ public static final String IMAGE_PHOTO_PHOTO = "IMAGE_PHOTO_PHOTO"; //$NON-NLS-1$ private final IPreferenceStore _prefStore = TourbookPlugin.getDefault().getPreferenceStore(); private final IDialogSettings _state = TourbookPlugin.getDefault().getDialogSettingsSection(ID); private static final TourPhotoManager _photoMgr = TourPhotoManager.getInstance(); private ArrayList<TourPhotoLink> _visibleTourPhotoLinks = new ArrayList<TourPhotoLink>(); private ArrayList<Photo> _allPhotos = new ArrayList<Photo>(); /** * Contains all cameras which are used in all displayed tours. */ private HashMap<String, Camera> _allTourCameras = new HashMap<String, Camera>(); /** * All cameras sorted by camera name */ private Camera[] _allTourCamerasSorted; /** * Tour photo link which is currently selected in the tour viewer. */ private ArrayList<TourPhotoLink> _selectedLinks = new ArrayList<TourPhotoLink>(); /** * Contains only tour photo links with real tours and which contain geo positions. */ private List<TourPhotoLink> _selectedTourPhotoLinksWithGps = new ArrayList<TourPhotoLink>(); private TourPhotoLinkSelection _tourPhotoLinkSelection; private ISelectionListener _postSelectionListener; private IPropertyChangeListener _prefChangeListener; private IPartListener2 _partListener; private PixelConverter _pc; private ColumnManager _columnManager; private ActionFilterTourWithoutSavedPhotos _actionFilterTourWithoutSavedPhotos; private ActionFilterTourWithPhotos _actionFilterTourWithPhotos; private ActionFilterOneHistoryTour _actionFilterOneHistory; private ActionModifyColumns _actionModifyColumns; private ActionSavePhotosInTour _actionSavePhotoInTour; private final PeriodFormatter _durationFormatter; private final NumberFormat _nf_1_1; { _nf_1_1 = NumberFormat.getNumberInstance(); _nf_1_1.setMinimumFractionDigits(1); _nf_1_1.setMaximumFractionDigits(1); _durationFormatter = new PeriodFormatterBuilder()// .appendYears().appendSuffix("y ", "y ") //$NON-NLS-1$ //$NON-NLS-2$ .appendMonths().appendSuffix("m ", "m ") //$NON-NLS-1$ //$NON-NLS-2$ .appendDays().appendSuffix("d ", "d ") //$NON-NLS-1$ //$NON-NLS-2$ .appendHours().appendSuffix("h ", "h ") //$NON-NLS-1$ //$NON-NLS-2$ .toFormatter(); } /** * When <code>true</code>, only tours with photos are displayed. */ private boolean _isShowToursWithPhotos = true; /** * When <code>true</code>, only tours with <b>NOT</b> saved photos are displayed. */ private boolean _isShowToursWithoutSavedPhotos; /** * It's dangerous when set to <code>true</code>, it will hide all tours which can confuses the * user, therefore this state is <b>NOT</b> saved. */ private boolean _isFilterOneHistoryTour = false; private ArrayList<TourPhotoLink> _selectionBackupBeforeOneHistory = new ArrayList<TourPhotoLink>(); private ICommandService _commandService; /* * UI controls */ private PageBook _pageBook; private Composite _pageNoImage; private Composite _pageViewer; private Composite _viewerContainer; private TableViewer _tourViewer; private Label _lblAdjustTime; private Spinner _spinnerHours; private Spinner _spinnerMinutes; private Spinner _spinnerSeconds; private Combo _comboCamera; private static class ContentComparator extends ViewerComparator { @Override public int compare(final Viewer viewer, final Object e1, final Object e2) { final TourPhotoLink mt1 = (TourPhotoLink) e1; final TourPhotoLink mt2 = (TourPhotoLink) e2; /* * sort by time */ final long mt1Time = mt1.isHistoryTour ? mt1.historyStartTime : mt1.tourStartTime; final long mt2Time = mt2.isHistoryTour ? mt2.historyStartTime : mt2.tourStartTime; if (mt1Time != 0 && mt2Time != 0) { return mt1Time > mt2Time ? 1 : -1; } return mt1Time != 0 ? 1 : -1; } } private class ContentProvider implements IStructuredContentProvider { @Override public void dispose() { } @Override public Object[] getElements(final Object inputElement) { return _visibleTourPhotoLinks.toArray(); } @Override public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput) { } } public TourPhotoLinkView() { super(); } void actionFilterNotSavedPhotos() { _isShowToursWithoutSavedPhotos = _actionFilterTourWithoutSavedPhotos.isChecked(); updateUI(_selectedLinks, null); } void actionFilterOneHistoryTour() { _isFilterOneHistoryTour = _actionFilterOneHistory.isChecked(); ArrayList<TourPhotoLink> links = null; if (_isFilterOneHistoryTour) { // backup current selection final ISelection selection = _tourViewer.getSelection(); if (selection instanceof StructuredSelection) { _selectionBackupBeforeOneHistory.clear(); for (final Object linkElement : ((StructuredSelection) selection).toArray()) { if (linkElement instanceof TourPhotoLink) { _selectionBackupBeforeOneHistory.add((TourPhotoLink) linkElement); } } } } else { links = _selectionBackupBeforeOneHistory; } updateUI(null, links); enableControls(); if (_isFilterOneHistoryTour == false) { final Table table = _tourViewer.getTable(); table.setSelection(table.getSelectionIndices()); } } void actionFilterPhotos() { _isShowToursWithPhotos = _actionFilterTourWithPhotos.isChecked(); updateUI(_selectedLinks, null); } void actionSavePhotoInTour() { if (TourManager.isTourEditorModified()) { return; } final TourManager tourManager = TourManager.getInstance(); // contains all photos which are modified (it also contains not modified photos) final HashSet<Photo> modifiedPhotos = new HashSet<Photo>(); final ArrayList<TourData> modifiedTours = new ArrayList<TourData>(); final ArrayList<TourPhotoLink> modifiedLinks = new ArrayList<TourPhotoLink>(); final Object[] allSelectedPhotoLinks = ((IStructuredSelection) _tourViewer.getSelection()).toArray(); int historyTours = 0; for (final Object linkElement : allSelectedPhotoLinks) { if (linkElement instanceof TourPhotoLink) { final TourPhotoLink photoLink = (TourPhotoLink) linkElement; final boolean isRealTour = photoLink.tourId != Long.MIN_VALUE; if (isRealTour) { final ArrayList<Photo> linkPhotos = photoLink.linkPhotos; if (linkPhotos.size() > 0) { final TourData tourData = tourManager.getTourData(photoLink.tourId); if (tourData != null) { final HashMap<String, TourPhoto> oldTourPhotos = new HashMap<String, TourPhoto>(); final Set<TourPhoto> tourPhotosSet = tourData.getTourPhotos(); for (final TourPhoto tourPhoto : tourPhotosSet) { oldTourPhotos.put(tourPhoto.getImageFilePathName(), tourPhoto); } // keep existing photos final ArrayList<Photo> oldGalleryPhotos = tourData.getGalleryPhotos(); if (oldGalleryPhotos != null) { modifiedPhotos.addAll(oldGalleryPhotos); } final HashSet<TourPhoto> tourPhotos = new HashSet<TourPhoto>(); for (final Photo galleryPhoto : linkPhotos) { // get existing tour photo TourPhoto tourPhoto = oldTourPhotos.get(galleryPhoto.imageFilePathName); if (tourPhoto == null) { tourPhoto = new TourPhoto(tourData, galleryPhoto); } // set adjusted time / geo location tourPhoto.setAdjustedTime(galleryPhoto.adjustedTimeLink); tourPhoto.setGeoLocation(galleryPhoto.getLinkLatitude(), galleryPhoto.getLinkLongitude()); tourPhotos.add(tourPhoto); // add new/old photos modifiedPhotos.add(galleryPhoto); } tourData.setTourPhotos(tourPhotos, linkPhotos); modifiedTours.add(tourData); modifiedLinks.add(photoLink); } } } else { historyTours++; } } } // show message that photos can be saved only in real tours if (historyTours > 0) { if (_prefStore.getBoolean(ITourbookPreferences.TOGGLE_STATE_SHOW_HISTORY_TOUR_SAVE_WARNING) == false) { final MessageDialogWithToggle dialog = MessageDialogWithToggle.openInformation(// Display.getCurrent().getActiveShell(), Messages.Photos_AndTours_Dialog_CannotSaveHistoryTour_Title, Messages.Photos_AndTours_Dialog_CannotSaveHistoryTour_Message, Messages.App_ToggleState_DoNotShowAgain, false, // toggle default state null, null); // save toggle state _prefStore.setValue(ITourbookPreferences.TOGGLE_STATE_SHOW_HISTORY_TOUR_SAVE_WARNING, dialog.getToggleState()); } } final ArrayList<TourData> savedTours = TourManager.saveModifiedTours(modifiedTours); /* * after saving tour + photos, update the photos and put them into the photo cache */ for (final TourData savedTourData : savedTours) { savedTourData.createGalleryPhotos(); } // update viewer data for (final TourPhotoLink photoLink : modifiedLinks) { final TourData tourData = tourManager.getTourData(photoLink.tourId); if (tourData != null) { photoLink.numberOfTourPhotos = tourData.getTourPhotos().size(); photoLink.photoTimeAdjustment = tourData.getPhotoTimeAdjustment(); } } // update viewer UI _tourViewer.update(modifiedLinks.toArray(), null); PhotoManager.firePhotoEvent(this, // PhotoEventId.PHOTO_ATTRIBUTES_ARE_MODIFIED, new ArrayList<Photo>(modifiedPhotos)); } private void addPartListener() { _partListener = new IPartListener2() { @Override public void partActivated(final IWorkbenchPartReference partRef) { if (partRef.getPart(false) == TourPhotoLinkView.this) { onPartActivate(); } } @Override public void partBroughtToTop(final IWorkbenchPartReference partRef) { } @Override public void partClosed(final IWorkbenchPartReference partRef) { if (partRef.getPart(false) == TourPhotoLinkView.this) { onPartClosed(); } } @Override public void partDeactivated(final IWorkbenchPartReference partRef) { } @Override public void partHidden(final IWorkbenchPartReference partRef) { } @Override public void partInputChanged(final IWorkbenchPartReference partRef) { } @Override public void partOpened(final IWorkbenchPartReference partRef) { } @Override public void partVisible(final IWorkbenchPartReference partRef) { } }; 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(ITourbookPreferences.MEASUREMENT_SYSTEM)) { // // measurement system has changed // // UI.updateUnits(); // updateInternalUnitValues(); // // _columnManager.saveState(_state); // _columnManager.clearColumns(); // defineAllColumns(_viewerContainer); // // _tourViewer = (TableViewer) recreateViewer(_tourViewer); } else if (property.equals(ITourbookPreferences.APP_DATA_FILTER_IS_MODIFIED)) { // app filter is modified // sql filter is dirty, force reloading cached start/end _photoMgr.resetTourStartEnd(); updateUI(_selectedLinks, null); } else if (property.equals(ITourbookPreferences.VIEW_LAYOUT_CHANGED)) { _tourViewer.getTable() .setLinesVisible(_prefStore.getBoolean(ITourbookPreferences.VIEW_LAYOUT_DISPLAY_LINES)); _tourViewer.refresh(); /* * the tree must be redrawn because the styled text does not show with the new * color */ _tourViewer.getTable().redraw(); } } }; _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) { if (part == TourPhotoLinkView.this) { return; } onSelectionChanged(selection, part); } }; getViewSite().getPage().addPostSelectionListener(_postSelectionListener); } private void clearView() { _visibleTourPhotoLinks.clear(); _allPhotos.clear(); _selectedLinks.clear(); _selectedTourPhotoLinksWithGps.clear(); _tourPhotoLinkSelection = null; _tourViewer.setInput(new Object[0]); enableControls(); _pageBook.showPage(_pageNoImage); } private void createActions() { _actionFilterOneHistory = new ActionFilterOneHistoryTour(this); _actionFilterTourWithoutSavedPhotos = new ActionFilterTourWithoutSavedPhotos(this); _actionFilterTourWithPhotos = new ActionFilterTourWithPhotos(this); _actionModifyColumns = new ActionModifyColumns(this); _actionSavePhotoInTour = new ActionSavePhotosInTour(this); } /** * create the views context menu */ private void createContextMenu() { final MenuManager menuMgr = new MenuManager(); menuMgr.setRemoveAllWhenShown(true); menuMgr.addMenuListener(new IMenuListener() { @Override public void menuAboutToShow(final IMenuManager menuMgr2) { fillContextMenu(menuMgr2); } }); final Table table = _tourViewer.getTable(); final Menu tableContextMenu = menuMgr.createContextMenu(table); table.setMenu(tableContextMenu); _columnManager.createHeaderContextMenu(table, tableContextMenu); } @Override public void createPartControl(final Composite parent) { _pc = new PixelConverter(parent); _columnManager = new ColumnManager(this, _state); defineAllColumns(parent); createUI(parent); createActions(); fillToolbar(); addSelectionListener(); addPrefListener(); addPartListener(); restoreState(); enableControls(); _commandService = ((ICommandService) PlatformUI.getWorkbench().getActiveWorkbenchWindow() .getService(ICommandService.class)); // show default page _pageBook.showPage(_pageNoImage); } private void createUI(final Composite parent) { _pageBook = new PageBook(parent, SWT.NONE); { _pageViewer = new Composite(_pageBook, SWT.NONE); GridDataFactory.fillDefaults().grab(true, true).applyTo(_pageViewer); GridLayoutFactory.fillDefaults().applyTo(_pageViewer); _pageViewer.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_RED)); { createUI_20_Tours(_pageViewer); } _pageNoImage = createUI_90_PageNoImage(_pageBook); } } private void createUI_20_Tours(final Composite parent) { _viewerContainer = new Composite(parent, SWT.NONE); GridDataFactory.fillDefaults().grab(true, true).applyTo(_viewerContainer); GridLayoutFactory.fillDefaults().spacing(0, 0).applyTo(_viewerContainer); { createUI_40_Header(_viewerContainer); createUI_50_TourViewer(_viewerContainer); } } private void createUI_40_Header(final Composite parent) { final Composite container = new Composite(parent, SWT.NONE); GridDataFactory.fillDefaults().grab(true, false).applyTo(container); GridLayoutFactory.fillDefaults()// .numColumns(3).margins(2, 2).applyTo(container); { /* * label: adjust time */ _lblAdjustTime = new Label(container, SWT.NONE); GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).applyTo(_lblAdjustTime); _lblAdjustTime.setText(Messages.Photos_AndTours_Label_AdjustTime); _lblAdjustTime.setToolTipText(Messages.Photos_AndTours_Label_AdjustTime_Tooltip); // /* // * radio: all/selected tours // */ // final Composite containerTours = new Composite(container, SWT.NONE); // GridDataFactory.fillDefaults().grab(false, false).applyTo(containerTours); // GridLayoutFactory.fillDefaults().numColumns(2).applyTo(containerTours); // { // _rdoAdjustAllTours = new Button(containerTours, SWT.RADIO); // _rdoAdjustAllTours.setText(Messages.Photos_AndTours_Radio_AdjustTime_AllTours); // _rdoAdjustAllTours.setToolTipText(Messages.Photos_AndTours_Radio_AdjustTime_AllTours_Tooltip); // // _rdoAdjustSelectedTours = new Button(containerTours, SWT.RADIO); // _rdoAdjustSelectedTours.setText(Messages.Photos_AndTours_Radio_AdjustTime_SelectedTours); // _rdoAdjustSelectedTours.setToolTipText(Messages.Photos_AndTours_Radio_AdjustTime_SelectedTours_Tooltip); // } createUI_44_AdjustTime(container); /* * combo: camera */ _comboCamera = new Combo(container, SWT.READ_ONLY); GridDataFactory.fillDefaults()// .align(SWT.BEGINNING, SWT.FILL) // .hint(_pc.convertWidthInCharsToPixels(15), SWT.DEFAULT) .applyTo(_comboCamera); _comboCamera.setVisibleItemCount(33); _comboCamera.setToolTipText(Messages.Photos_AndTours_Combo_Camera_Tooltip); _comboCamera.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { onSelectCamera(); } }); } } private void createUI_44_AdjustTime(final Composite parent) { final Composite container = new Composite(parent, SWT.NONE); GridDataFactory.fillDefaults().grab(false, false).applyTo(container); GridLayoutFactory.fillDefaults().numColumns(3).spacing(0, 0).applyTo(container); { /* * spinner: adjust hours */ _spinnerHours = new Spinner(container, SWT.BORDER); GridDataFactory.fillDefaults() // .applyTo(_spinnerHours); _spinnerHours.setMinimum(-100); _spinnerHours.setMaximum(100); _spinnerHours.setIncrement(1); _spinnerHours.setPageIncrement(24); _spinnerHours.setToolTipText(Messages.Photos_AndTours_Spinner_AdjustHours_Tooltip); _spinnerHours.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { onSelectTimeAdjustment(); } }); _spinnerHours.addMouseWheelListener(new MouseWheelListener() { @Override public void mouseScrolled(final MouseEvent event) { Util.adjustSpinnerValueOnMouseScroll(event); onSelectTimeAdjustment(); } }); /* * spinner: adjust minutes */ _spinnerMinutes = new Spinner(container, SWT.BORDER); GridDataFactory.fillDefaults() // .applyTo(_spinnerMinutes); _spinnerMinutes.setMinimum(-100); _spinnerMinutes.setMaximum(100); _spinnerMinutes.setIncrement(1); _spinnerMinutes.setPageIncrement(10); _spinnerMinutes.setToolTipText(Messages.Photos_AndTours_Spinner_AdjustMinutes_Tooltip); _spinnerMinutes.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { onSelectTimeAdjustment(); } }); _spinnerMinutes.addMouseWheelListener(new MouseWheelListener() { @Override public void mouseScrolled(final MouseEvent event) { Util.adjustSpinnerValueOnMouseScroll(event); onSelectTimeAdjustment(); } }); /* * spinner: adjust seconds */ _spinnerSeconds = new Spinner(container, SWT.BORDER); GridDataFactory.fillDefaults() // .applyTo(_spinnerSeconds); _spinnerSeconds.setMinimum(-100); _spinnerSeconds.setMaximum(100); _spinnerSeconds.setIncrement(1); _spinnerSeconds.setPageIncrement(10); _spinnerSeconds.setToolTipText(Messages.Photos_AndTours_Spinner_AdjustSeconds_Tooltip); _spinnerSeconds.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { onSelectTimeAdjustment(); } }); _spinnerSeconds.addMouseWheelListener(new MouseWheelListener() { @Override public void mouseScrolled(final MouseEvent event) { Util.adjustSpinnerValueOnMouseScroll(event); onSelectTimeAdjustment(); } }); } } private void createUI_50_TourViewer(final Composite parent) { final Table table = new Table(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.MULTI); GridDataFactory.fillDefaults().grab(true, true).applyTo(table); table.setHeaderVisible(true); table.setLinesVisible(_prefStore.getBoolean(ITourbookPreferences.VIEW_LAYOUT_DISPLAY_LINES)); /* * create table viewer */ _tourViewer = new TableViewer(table); _columnManager.createColumns(_tourViewer); _tourViewer.setUseHashlookup(true); _tourViewer.setContentProvider(new ContentProvider()); _tourViewer.setComparator(new ContentComparator()); _tourViewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(final SelectionChangedEvent event) { final ISelection eventSelection = event.getSelection(); if (eventSelection instanceof StructuredSelection) { onSelectTour(((StructuredSelection) eventSelection).toArray()); } } }); createContextMenu(); } private Composite createUI_90_PageNoImage(final Composite parent) { final int defaultWidth = 200; final Composite page = new Composite(parent, SWT.NONE); GridLayoutFactory.fillDefaults().applyTo(page); { final Composite container = new Composite(page, SWT.NONE); GridDataFactory.fillDefaults().grab(true, false).applyTo(container); GridLayoutFactory.swtDefaults().numColumns(2).applyTo(container); { final Label label = new Label(container, SWT.WRAP); label.setText(Messages.Photos_AndTours_Label_NoSelectedPhoto); GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(label); /* * link: import */ final Image picDirIcon = net.tourbook.ui.UI.IMAGE_REGISTRY.get(IMAGE_PIC_DIR_VIEW); final CLabel iconPicDirView = new CLabel(container, SWT.NONE); GridDataFactory.fillDefaults().indent(0, 10).applyTo(iconPicDirView); iconPicDirView.setImage(picDirIcon); iconPicDirView.setText(UI.EMPTY_STRING); final Link linkImport = new Link(container, SWT.NONE); GridDataFactory.fillDefaults()// .hint(defaultWidth, SWT.DEFAULT).align(SWT.FILL, SWT.CENTER).grab(true, false).indent(0, 10) .applyTo(linkImport); linkImport.setText(Messages.Photos_AndTours_Link_PhotoDirectory); linkImport.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { Util.showView(PicDirView.ID, true); } }); } } return page; } private void defineAllColumns(final Composite parent) { defineColumn_Tour_TypeImage(); defineColumn_Photo_NumberOfTourPhotos(); defineColumn_Photo_TimeAdjustment(); defineColumn_Photo_NumberOfGPSPhotos(); defineColumn_Photo_NumberOfNoGPSPhotos(); defineColumn_Time_TourStartDate(); defineColumn_Time_TourDurationTime(); defineColumn_Photo_TourCameras(); defineColumn_Time_TourStartTime(); defineColumn_Time_TourEndDate(); defineColumn_Time_TourEndTime(); defineColumn_Tour_TypeText(); } /** * column: number of photos which contain gps data */ private void defineColumn_Photo_NumberOfGPSPhotos() { final ColumnDefinition colDef = TableColumnFactory.PHOTO_NUMBER_OF_GPS_PHOTOS.createColumn(_columnManager, _pc); colDef.setIsDefaultColumn(); colDef.setLabelProvider(new CellLabelProvider() { @Override public void update(final ViewerCell cell) { final TourPhotoLink link = (TourPhotoLink) cell.getElement(); final int numberOfGPSPhotos = link.numberOfGPSPhotos; cell.setText(numberOfGPSPhotos == 0 ? UI.EMPTY_STRING : Long.toString(numberOfGPSPhotos)); setBgColor(cell, link); } }); } /** * column: number of photos which contain gps data */ private void defineColumn_Photo_NumberOfNoGPSPhotos() { final ColumnDefinition colDef = TableColumnFactory.PHOTO_NUMBER_OF_NO_GPS_PHOTOS .createColumn(_columnManager, _pc); colDef.setIsDefaultColumn(); colDef.setLabelProvider(new CellLabelProvider() { @Override public void update(final ViewerCell cell) { final TourPhotoLink link = (TourPhotoLink) cell.getElement(); final int numberOfNoGPSPhotos = link.numberOfNoGPSPhotos; cell.setText(numberOfNoGPSPhotos == 0 ? UI.EMPTY_STRING : Long.toString(numberOfNoGPSPhotos)); setBgColor(cell, link); } }); } /** * column: number of photos which are saved in the tour */ private void defineColumn_Photo_NumberOfTourPhotos() { final ColumnDefinition colDef = TableColumnFactory.PHOTO_NUMBER_OF_PHOTOS.createColumn(_columnManager, _pc); colDef.setIsDefaultColumn(); colDef.setLabelProvider(new CellLabelProvider() { @Override public void update(final ViewerCell cell) { final TourPhotoLink link = (TourPhotoLink) cell.getElement(); final int numberOfPhotos = link.numberOfTourPhotos; cell.setText(numberOfPhotos == 0 ? UI.EMPTY_STRING : Integer.toString(numberOfPhotos)); setBgColor(cell, link); } }); } /** * column: number of photos which are saved in the tour */ private void defineColumn_Photo_TimeAdjustment() { final ColumnDefinition colDef = TableColumnFactory.PHOTO_TIME_ADJUSTMENT.createColumn(_columnManager, _pc); colDef.setIsDefaultColumn(); colDef.setLabelProvider(new CellLabelProvider() { @Override public void update(final ViewerCell cell) { final TourPhotoLink link = (TourPhotoLink) cell.getElement(); final int numberOfTourPhotos = link.numberOfTourPhotos; final int timeAdjustment = link.photoTimeAdjustment; cell.setText(numberOfTourPhotos == 0 // ? UI.EMPTY_STRING : UI.formatHhMmSs(timeAdjustment)); setBgColor(cell, link); } }); } /** * column: tour type text */ private void defineColumn_Photo_TourCameras() { final ColumnDefinition colDef = TableColumnFactory.PHOTO_TOUR_CAMERA.createColumn(_columnManager, _pc); colDef.setIsDefaultColumn(); colDef.setLabelProvider(new CellLabelProvider() { @Override public void update(final ViewerCell cell) { final Object element = cell.getElement(); if (element instanceof TourPhotoLink) { final TourPhotoLink link = (TourPhotoLink) element; cell.setText(link.tourCameras); setBgColor(cell, link); } } }); } /** * column: duration time */ private void defineColumn_Time_TourDurationTime() { final ColumnDefinition colDef = TableColumnFactory.TIME_TOUR_DURATION_TIME.createColumn(_columnManager, _pc); colDef.setIsDefaultColumn(); colDef.setLabelProvider(new CellLabelProvider() { @Override public void update(final ViewerCell cell) { final TourPhotoLink link = (TourPhotoLink) cell.getElement(); final Period period = link.tourPeriod; int periodSum = 0; for (final int value : period.getValues()) { periodSum += value; } if (periodSum == 0) { // < 1 h cell.setText(Messages.Photos_AndTours_Label_DurationLess1Hour); } else { // > 1 h cell.setText(period.toString(_durationFormatter)); } setBgColor(cell, link); } }); } /** * column: tour end date */ private void defineColumn_Time_TourEndDate() { final ColumnDefinition colDef = TableColumnFactory.TIME_TOUR_END_DATE.createColumn(_columnManager, _pc); // colDef.setCanModifyVisibility(false); // colDef.setIsDefaultColumn(); colDef.setLabelProvider(new CellLabelProvider() { @Override public void update(final ViewerCell cell) { final TourPhotoLink link = (TourPhotoLink) cell.getElement(); final long historyTime = link.historyEndTime; cell.setText(historyTime == Long.MIN_VALUE // ? TimeTools.getZonedDateTime(link.tourEndTime).format(TimeTools.Formatter_Date_S) : TimeTools.getZonedDateTime(historyTime).format(TimeTools.Formatter_Date_S)); setBgColor(cell, link); } }); } /** * column: tour end time */ private void defineColumn_Time_TourEndTime() { final ColumnDefinition colDef = TableColumnFactory.TIME_TOUR_END_TIME.createColumn(_columnManager, _pc); colDef.setLabelProvider(new CellLabelProvider() { @Override public void update(final ViewerCell cell) { final TourPhotoLink link = (TourPhotoLink) cell.getElement(); final long historyTime = link.historyEndTime; cell.setText(historyTime == Long.MIN_VALUE // ? TimeTools.getZonedDateTime(link.tourEndTime).format(TimeTools.Formatter_Time_M) : TimeTools.getZonedDateTime(historyTime).format(TimeTools.Formatter_Time_M)); setBgColor(cell, link); } }); } /** * column: tour start date */ private void defineColumn_Time_TourStartDate() { final ColumnDefinition colDef = TableColumnFactory.TIME_TOUR_START_DATE.createColumn(_columnManager, _pc); // colDef.setCanModifyVisibility(false); colDef.setIsDefaultColumn(); colDef.setLabelProvider(new CellLabelProvider() { @Override public void update(final ViewerCell cell) { final TourPhotoLink link = (TourPhotoLink) cell.getElement(); final long historyTime = link.historyStartTime; cell.setText(historyTime == Long.MIN_VALUE // ? TimeTools.getZonedDateTime(link.tourStartTime).format(TimeTools.Formatter_Date_S) : TimeTools.getZonedDateTime(historyTime).format(TimeTools.Formatter_Date_S)); setBgColor(cell, link); } }); } /** * column: tour start time */ private void defineColumn_Time_TourStartTime() { final ColumnDefinition colDef = TableColumnFactory.TIME_TOUR_START_TIME.createColumn(_columnManager, _pc); colDef.setLabelProvider(new CellLabelProvider() { @Override public void update(final ViewerCell cell) { final TourPhotoLink link = (TourPhotoLink) cell.getElement(); final long historyTime = link.historyStartTime; cell.setText(historyTime == Long.MIN_VALUE // ? TimeTools.getZonedDateTime(link.tourStartTime).format(TimeTools.Formatter_Time_M) : TimeTools.getZonedDateTime(historyTime).format(TimeTools.Formatter_Time_M)); setBgColor(cell, link); } }); } /** * column: tour type image */ private void defineColumn_Tour_TypeImage() { final ColumnDefinition colDef = TableColumnFactory.TOUR_TYPE.createColumn(_columnManager, _pc); colDef.setIsDefaultColumn(); colDef.setLabelProvider(new CellLabelProvider() { @Override public void update(final ViewerCell cell) { final Object element = cell.getElement(); if (element instanceof TourPhotoLink) { final TourPhotoLink link = (TourPhotoLink) element; if (link.isHistoryTour) { cell.setImage(net.tourbook.ui.UI.IMAGE_REGISTRY.get(IMAGE_PHOTO_PHOTO)); } else { final long tourTypeId = link.tourTypeId; if (tourTypeId == -1) { cell.setImage(null); } else { final Image tourTypeImage = net.tourbook.ui.UI.getInstance() .getTourTypeImage(tourTypeId); /* * when a tour type image is modified, it will keep the same image * resource only the content is modified but in the rawDataView the * modified image is not displayed compared with the tourBookView which * displays the correct image */ cell.setImage(tourTypeImage); } } } } }); } /** * column: tour type text */ private void defineColumn_Tour_TypeText() { final ColumnDefinition colDef = TableColumnFactory.TOUR_TYPE_TEXT.createColumn(_columnManager, _pc); colDef.setLabelProvider(new CellLabelProvider() { @Override public void update(final ViewerCell cell) { final Object element = cell.getElement(); if (element instanceof TourPhotoLink) { final TourPhotoLink link = (TourPhotoLink) element; if (link.isHistoryTour) { cell.setText(Messages.Photos_AndTours_Label_HistoryTour); } else { final long tourTypeId = link.tourTypeId; if (tourTypeId == -1) { cell.setText(UI.EMPTY_STRING); } else { cell.setText(net.tourbook.ui.UI.getTourTypeLabel(tourTypeId)); } } setBgColor(cell, link); } } }); } @Override public void dispose() { final IWorkbenchPage page = getViewSite().getPage(); page.removePostSelectionListener(_postSelectionListener); page.removePartListener(_partListener); _prefStore.removePropertyChangeListener(_prefChangeListener); super.dispose(); } private void enableControls() { final boolean isPhotoAvailable = _allPhotos.size() > 0; final boolean isOneHistory = _actionFilterOneHistory.isChecked(); final boolean isNoHistory = !isOneHistory; final boolean isPhotoFilter = isPhotoAvailable && isNoHistory; _lblAdjustTime.setEnabled(isPhotoFilter); _spinnerHours.setEnabled(isPhotoFilter); _spinnerMinutes.setEnabled(isPhotoFilter); _spinnerSeconds.setEnabled(isPhotoFilter); _comboCamera.setEnabled(isPhotoFilter); _actionFilterTourWithPhotos.setEnabled(isPhotoFilter && _isShowToursWithoutSavedPhotos == false); _actionFilterTourWithoutSavedPhotos.setEnabled(isPhotoFilter); _actionFilterOneHistory.setEnabled(isPhotoAvailable); _actionSavePhotoInTour.setEnabled(isPhotoAvailable); } private void fillContextMenu(final IMenuManager menuMgr) { menuMgr.add(_actionSavePhotoInTour); } private void fillToolbar() { /* * fill view menu */ final IMenuManager menuMgr = getViewSite().getActionBars().getMenuManager(); menuMgr.add(new Separator()); menuMgr.add(_actionModifyColumns); /* * fill view toolbar */ final IToolBarManager tbm = getViewSite().getActionBars().getToolBarManager(); tbm.add(_actionFilterTourWithPhotos); tbm.add(_actionFilterTourWithoutSavedPhotos); tbm.add(_actionFilterOneHistory); tbm.add(new Separator()); } @Override public ColumnManager getColumnManager() { return _columnManager; } private PicDirView getPicDirView(final IWorkbenchWindow wbWindow) { final IWorkbenchPage wbPage = wbWindow.getActivePage(); if (wbPage != null) { for (final IViewReference viewRef : wbPage.getViewReferences()) { if (viewRef.getId().equals(PicDirView.ID)) { final IViewPart viewPart = viewRef.getView(false); if (viewPart instanceof PicDirView) { return (PicDirView) viewPart; } } } } return null; } private Camera getSelectedCamera() { final int cameraIndex = _comboCamera.getSelectionIndex(); if (cameraIndex == -1) { return null; } return _allTourCamerasSorted[cameraIndex]; } @Override public ArrayList<TourData> getSelectedTours() { return new ArrayList<TourData>(); } @Override public ColumnViewer getViewer() { return _tourViewer; } private void onPartActivate() { // fire selection if (_tourPhotoLinkSelection != null) { PhotoManager.firePhotoEvent(this, PhotoEventId.PHOTO_SELECTION, _tourPhotoLinkSelection); } } private void onPartClosed() { // close sql connections _photoMgr.resetTourStartEnd(); saveState(); } private void onSelectCamera() { final Camera camera = getSelectedCamera(); if (camera == null) { return; } // update UI final long timeAdjustment = camera.timeAdjustment / 1000; final int hours = (int) (timeAdjustment / 3600); final int minutes = (int) ((timeAdjustment % 3600) / 60); final int seconds = (int) ((timeAdjustment % 3600) % 60); _spinnerHours.setSelection(hours); _spinnerMinutes.setSelection(minutes); _spinnerSeconds.setSelection(seconds); } private void onSelectionChanged(final ISelection selection, final IWorkbenchPart part) { // System.out.println(UI.timeStampNano() + " onSelectionChanged\t" + selection); // // TODO remove SYSTEM.OUT.PRINTLN if (selection instanceof SyncSelection) { final ISelection originalSelection = ((SyncSelection) selection).getSelection(); if (originalSelection instanceof PhotoSelection) { showPhotosAndTours(((PhotoSelection) originalSelection).galleryPhotos); } } else if (selection instanceof PhotoSelection && part instanceof PicDirView) { /** * accept photo selection ONLY from the pic dir view, otherwise other photo selections * will cause a view update */ final PhotoSelection photoSelection = (PhotoSelection) selection; final Command command = _commandService.getCommand(ActionHandlerSyncPhotoWithTour.COMMAND_ID); final State state = command.getState(RegistryToggleState.STATE_ID); final boolean isSync = (Boolean) state.getValue(); if (isSync) { showPhotosAndTours(photoSelection.galleryPhotos); } } else if (selection instanceof SelectionDeletedTours) { clearView(); _photoMgr.resetTourStartEnd(); } } private void onSelectTimeAdjustment() { if (_selectedLinks.size() == 0) { // a tour is not selected return; } final Camera camera = getSelectedCamera(); if (camera == null) { return; } camera.setTimeAdjustment(_spinnerHours.getSelection(), _spinnerMinutes.getSelection(), _spinnerSeconds.getSelection()); updateUI(_selectedLinks, null); } /** * Creates a {@link TourPhotoLinkSelection} * * @param allSelectedLinks * All elements of type {@link TourPhotoLink} */ private void onSelectTour(final Object[] allSelectedLinks) { // get all real tours with geo positions _selectedTourPhotoLinksWithGps.clear(); // contains tour id's for all real tours final ArrayList<Long> selectedTourIds = new ArrayList<Long>(); final ArrayList<TourPhotoLink> selectedLinks = new ArrayList<TourPhotoLink>(); for (final Object linkElement : allSelectedLinks) { if (linkElement instanceof TourPhotoLink) { final TourPhotoLink selectedLink = (TourPhotoLink) linkElement; selectedLinks.add(selectedLink); final boolean isRealTour = selectedLink.tourId != Long.MIN_VALUE; if (isRealTour) { selectedTourIds.add(selectedLink.tourId); } if (isRealTour && selectedLink.linkPhotos.size() > 0) { final TourData tourData = TourManager.getInstance().getTourData(selectedLink.tourId); if (tourData != null && tourData.latitudeSerie != null) { _selectedTourPhotoLinksWithGps.add(selectedLink); } } } } if (_selectedLinks.equals(selectedLinks)) { // currently selected tour is already selected and selection is fired return; } _selectedLinks.clear(); _selectedLinks.addAll(selectedLinks); enableControls(); // create tour selection _tourPhotoLinkSelection = new TourPhotoLinkSelection(_selectedLinks, selectedTourIds); PhotoManager.firePhotoEvent(this, PhotoEventId.PHOTO_SELECTION, _tourPhotoLinkSelection); } @Override public ColumnViewer recreateViewer(final ColumnViewer columnViewer) { _viewerContainer.setRedraw(false); { _tourViewer.getTable().dispose(); createUI_50_TourViewer(_viewerContainer); _viewerContainer.layout(); // update the viewer reloadViewer(); } _viewerContainer.setRedraw(true); return _tourViewer; } @Override public void reloadViewer() { _tourViewer.setInput(new Object[0]); } private void restoreState() { // photo filter _isShowToursWithPhotos = Util.getStateBoolean(_state, STATE_FILTER_TOUR_WITH_PHOTOS, true); _isShowToursWithoutSavedPhotos = Util.getStateBoolean(_state, STATE_FILTER_NOT_SAVED_PHOTOS, false); _actionFilterOneHistory.setChecked(_isFilterOneHistoryTour); _actionFilterTourWithoutSavedPhotos.setChecked(_isShowToursWithoutSavedPhotos); _actionFilterTourWithPhotos.setChecked(_isShowToursWithPhotos); final String prevCameraName = Util.getStateString(_state, STATE_SELECTED_CAMERA_NAME, null); updateUI_Cameras(prevCameraName); } private void saveState() { // check if UI is disposed final Table table = _tourViewer.getTable(); if (table.isDisposed()) { return; } /* * selected camera */ final Camera selectedCamera = getSelectedCamera(); if (selectedCamera != null) { final String cameraName = selectedCamera.cameraName; if (cameraName != null) { _state.put(STATE_SELECTED_CAMERA_NAME, cameraName); } } // photo filter _state.put(STATE_FILTER_NOT_SAVED_PHOTOS, _actionFilterTourWithoutSavedPhotos.isChecked()); _state.put(STATE_FILTER_TOUR_WITH_PHOTOS, _actionFilterTourWithPhotos.isChecked()); _columnManager.saveState(_state); } /** * @param prevTourPhotoLink * Previously selected link, can be <code>null</code>. */ private void selectTour(final TourPhotoLink prevTourPhotoLink) { if (_visibleTourPhotoLinks.size() == 0) { return; } TourPhotoLink selectedTour = null; /* * 1st try to select a tour */ if (prevTourPhotoLink == null) { // select first tour selectedTour = _visibleTourPhotoLinks.get(0); } else if (prevTourPhotoLink.isHistoryTour == false) { // select a real tour by tour id selectedTour = prevTourPhotoLink; } ISelection newSelection = null; if (selectedTour != null) { _tourViewer.setSelection(new StructuredSelection(selectedTour), true); newSelection = _tourViewer.getSelection(); } if (prevTourPhotoLink == null) { // there is nothing which can be compared in equals() return; } /* * 2nd try to select a tour */ // check if tour is selected if (newSelection == null || newSelection.isEmpty()) { TourPhotoLink linkSelection = null; final ArrayList<Photo> tourPhotos = prevTourPhotoLink.linkPhotos; if (tourPhotos.size() > 0) { // get tour for the first photo final long tourPhotoTime = tourPhotos.get(0).adjustedTimeLink; for (final TourPhotoLink link : _visibleTourPhotoLinks) { final long linkStartTime = link.isHistoryTour // ? link.historyStartTime : link.tourStartTime; final long linkEndTime = link.isHistoryTour // ? link.historyEndTime : link.tourEndTime; if (tourPhotoTime >= linkStartTime && tourPhotoTime <= linkEndTime) { linkSelection = link; break; } } } else { // get tour by checking intersection final long requestedStartTime = prevTourPhotoLink.isHistoryTour ? prevTourPhotoLink.historyStartTime : prevTourPhotoLink.tourStartTime; final long requestedEndTime = prevTourPhotoLink.isHistoryTour // ? prevTourPhotoLink.historyEndTime : prevTourPhotoLink.tourEndTime; final long requestedTime = requestedStartTime + ((requestedEndTime - requestedStartTime) / 2); for (final TourPhotoLink link : _visibleTourPhotoLinks) { final long linkStartTime = link.isHistoryTour ? link.historyStartTime : link.tourStartTime; final long linkEndTime = link.isHistoryTour // ? link.historyEndTime : link.tourEndTime; final boolean isIntersects = requestedTime > linkStartTime && requestedTime < linkEndTime; if (isIntersects) { linkSelection = link; break; } } } if (linkSelection != null) { _tourViewer.setSelection(new StructuredSelection(linkSelection), false); newSelection = _tourViewer.getSelection(); } } /* * 3rd try to select a tour */ if (newSelection == null || newSelection.isEmpty()) { // previous selections failed, select first tour final TourPhotoLink firstTour = _visibleTourPhotoLinks.get(0); _tourViewer.setSelection(new StructuredSelection(firstTour), true); } // set focus rubberband to selected item, most of the time it is not at the correct position final Table table = _tourViewer.getTable(); table.setSelection(table.getSelectionIndex()); } private void setBgColor(final ViewerCell cell, final TourPhotoLink linkTour) { // if (linkTour.isHistoryTour()) { // cell.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_LIST_BACKGROUND)); // } else { // cell.setBackground(JFaceResources.getColorRegistry().get(net.tourbook.ui.UI.VIEW_COLOR_BG_HISTORY_TOUR)); // } } @Override public void setFocus() { _tourViewer.getTable().setFocus(); } private void setPhotoTimeAdjustment() { for (final Photo photo : _allPhotos) { final long exifTime = photo.imageExifTime; final long cameraTimeAdjustment = photo.camera.timeAdjustment; photo.adjustedTimeLink = exifTime + cameraTimeAdjustment; // force that the position are updated photo.resetLinkWorldPosition(); } Collections.sort(_allPhotos, TourPhotoManager.AdjustTimeComparatorLink); } /** * @param tourPhotos */ void showPhotosAndTours(final ArrayList<Photo> tourPhotos) { final int numberOfPhotos = tourPhotos.size(); if (numberOfPhotos == 0) { clearView(); return; } _allPhotos.clear(); _allPhotos.addAll(tourPhotos); _allTourCameras.clear(); // ensure camera is set in all photos for (final Photo photo : _allPhotos) { if (photo.camera == null) { _photoMgr.setCamera(photo, _allTourCameras); } } if (numberOfPhotos > 100) { BusyIndicator.showWhile(_pageBook.getDisplay(), new Runnable() { @Override public void run() { updateUI(null, _visibleTourPhotoLinks); } }); } else { updateUI(null, _visibleTourPhotoLinks); } } /** * Update GPS annotation in the image gallery. */ private void updateAnnotationsInPicDirView() { PicDirView picDirView = null; final IWorkbench wb = PlatformUI.getWorkbench(); picDirView = getPicDirView(wb.getActiveWorkbenchWindow()); if (picDirView == null) { for (final IWorkbenchWindow wbWindow : wb.getWorkbenchWindows()) { picDirView = getPicDirView(wbWindow); if (picDirView != null) { break; } } } if (picDirView != null) { picDirView.refreshUI(); } } @Override public void updateColumnHeader(final ColumnDefinition colDef) { // TODO Auto-generated method stub } private void updateUI(final ArrayList<TourPhotoLink> tourPhotoLinksWhichShouldBeSelected, final ArrayList<TourPhotoLink> allLinksWhichShouldBeSelected) { if (_allPhotos.size() == 0) { // view is not fully initialized, this happend in the pref listener return; } // get previous selected tour final TourPhotoLink prevTourPhotoLink[] = { null }; if (tourPhotoLinksWhichShouldBeSelected != null && tourPhotoLinksWhichShouldBeSelected.size() > 0) { prevTourPhotoLink[0] = tourPhotoLinksWhichShouldBeSelected.get(0); } // this must be called BEFORE start/end date are set setPhotoTimeAdjustment(); _visibleTourPhotoLinks.clear(); _selectedLinks.clear(); _selectedTourPhotoLinksWithGps.clear(); if (_isFilterOneHistoryTour) { _photoMgr.createTourPhotoLinks_01_OneHistoryTour(// _allPhotos, _visibleTourPhotoLinks, _allTourCameras); } else { _photoMgr.createTourPhotoLinks(// _allPhotos, _visibleTourPhotoLinks, _allTourCameras, _isShowToursWithPhotos, _isShowToursWithoutSavedPhotos); } updateUI_Cameras(null); enableControls(); // tour viewer update can be a longer task, update other UI element before _pageBook.getDisplay().asyncExec(new Runnable() { @Override public void run() { if (_tourViewer.getTable().isDisposed()) { return; } _tourViewer.setInput(new Object[0]); _pageBook.showPage(_pageViewer); updateAnnotationsInPicDirView(); if (allLinksWhichShouldBeSelected != null && allLinksWhichShouldBeSelected.size() > 0) { _tourViewer.setSelection(new StructuredSelection(allLinksWhichShouldBeSelected), true); } else { selectTour(prevTourPhotoLink[0]); } } }); } /** * fill camera combo and select previous selection * * @param defaultCameraName */ private void updateUI_Cameras(final String defaultCameraName) { // get previous camera String currentSelectedCameraName = null; if (defaultCameraName == null) { final int currentSelectedCameraIndex = _comboCamera.getSelectionIndex(); if (currentSelectedCameraIndex != -1) { currentSelectedCameraName = _comboCamera.getItem(currentSelectedCameraIndex); } } else { currentSelectedCameraName = defaultCameraName; } _comboCamera.removeAll(); // sort cameras final Collection<Camera> cameraValues = _allTourCameras.values(); _allTourCamerasSorted = cameraValues.toArray(new Camera[cameraValues.size()]); Arrays.sort(_allTourCamerasSorted); int cameraComboIndex = -1; for (int cameraIndex = 0; cameraIndex < _allTourCamerasSorted.length; cameraIndex++) { final Camera camera = _allTourCamerasSorted[cameraIndex]; _comboCamera.add(camera.cameraName); // get index for the last selected camera if (cameraComboIndex == -1 && currentSelectedCameraName != null && currentSelectedCameraName.equals(camera.cameraName)) { cameraComboIndex = cameraIndex; } } _comboCamera.getParent().layout(); // select previous camera _comboCamera.select(cameraComboIndex == -1 ? 0 : cameraComboIndex); // update spinners for camera time adjustment onSelectCamera(); } }