net.tourbook.tour.photo.TourPhotosView.java Source code

Java tutorial

Introduction

Here is the source code for net.tourbook.tour.photo.TourPhotosView.java

Source

/*******************************************************************************
 * 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.tour.photo;

import java.util.ArrayList;

import net.tourbook.Messages;
import net.tourbook.application.TourbookPlugin;
import net.tourbook.common.time.TimeTools;
import net.tourbook.common.util.PostSelectionProvider;
import net.tourbook.common.util.Util;
import net.tourbook.data.TourData;
import net.tourbook.photo.IPhotoEventListener;
import net.tourbook.photo.IPhotoGalleryProvider;
import net.tourbook.photo.IPhotoPreferences;
import net.tourbook.photo.Photo;
import net.tourbook.photo.PhotoEventId;
import net.tourbook.photo.PhotoGallery;
import net.tourbook.photo.PhotoManager;
import net.tourbook.photo.PhotoSelection;
import net.tourbook.tour.ITourEventListener;
import net.tourbook.tour.SelectionTourData;
import net.tourbook.tour.SelectionTourId;
import net.tourbook.tour.SelectionTourIds;
import net.tourbook.tour.SelectionTourMarker;
import net.tourbook.tour.TourEventId;
import net.tourbook.tour.TourManager;
import net.tourbook.ui.UI;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ColorRegistry;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.part.ViewPart;

public class TourPhotosView extends ViewPart implements IPhotoEventListener {

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

    private static final String STATE_PHOTO_GALLERY_IS_VERTICAL = "STATE_PHOTO_GALLERY_IS_VERTICAL"; //$NON-NLS-1$

    private static final IDialogSettings _state = TourbookPlugin.getDefault()//
            .getDialogSettingsSection(ID);
    private final IPreferenceStore _prefStore = TourbookPlugin.getDefault()//
            .getPreferenceStore();

    private PostSelectionProvider _postSelectionProvider;

    private ISelectionListener _postSelectionListener;
    private IPropertyChangeListener _prefChangeListener;
    private ITourEventListener _tourEventListener;
    private IPartListener2 _partListener;

    private boolean _isPartVisible;

    private ActionToggleGalleryOrientation _actionToggleGalleryOrientation;

    /**
     * contains selection which was set when the part is hidden
     */
    private TourPhotoLinkSelection _selectionWhenHidden;

    private PhotoGallery _photoGallery;

    private boolean _isVerticalGallery;
    public IToolBarManager _galleryToolbarManager;

    private int _galleryPositionKey;

    private long _photoStartTime;
    private long _photoEndTime;

    private boolean _isLinkPhotoDisplayed;

    /*
     * UI controls
     */
    private ToolBar _toolbarLeft;
    private Label _labelTitle;

    private class ActionToggleGalleryOrientation extends Action {

        public ActionToggleGalleryOrientation() {

            super(null, Action.AS_PUSH_BUTTON);

            /**
             * VERY IMPORTANT
             * <p>
             * an image must be set in the constructor, otherwise the button is small when only ONE
             * action is in the toolbar
             */
            setImageDescriptor(TourbookPlugin.getImageDescriptor(Messages.Image__PhotoGalleryHorizontal));
        }

        @Override
        public void run() {
            actionToggleVH();
        }
    }

    private final class PhotoGalleryProvider implements IPhotoGalleryProvider {

        @Override
        public IStatusLineManager getStatusLineManager() {
            return getViewSite().getActionBars().getStatusLineManager();
        }

        @Override
        public IToolBarManager getToolBarManager() {
            return getViewSite().getActionBars().getToolBarManager();
        }

        @Override
        public void registerContextMenu(final String menuId, final MenuManager menuManager) {
        }

        @Override
        public void setSelection(final PhotoSelection photoSelection) {
            _postSelectionProvider.setSelection(photoSelection);
        }
    }

    public TourPhotosView() {
        super();
    }

    private void actionToggleVH() {

        // keep state for current orientation
        _photoGallery.saveState();

        // toggle gallery
        _isVerticalGallery = !_isVerticalGallery;

        updateUI_ToogleAction();

        _photoGallery.setVertical(_isVerticalGallery);
    }

    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) == TourPhotosView.this) {
                    saveState();
                }
            }

            @Override
            public void partDeactivated(final IWorkbenchPartReference partRef) {
            }

            @Override
            public void partHidden(final IWorkbenchPartReference partRef) {
                if (partRef.getPart(false) == TourPhotosView.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) == TourPhotosView.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(IPhotoPreferences.PHOTO_VIEWER_PREF_EVENT_IMAGE_VIEWER_UI_IS_MODIFIED)) {

                    updateColors(false);
                }
            }
        };
        _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 == TourPhotosView.this) {
                    return;
                }
                onSelectionChanged(selection);
            }
        };
        getViewSite().getPage().addPostSelectionListener(_postSelectionListener);
    }

    private void addTourEventListener() {

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

                if (part == TourPhotosView.this) {
                    return;
                }

                if (eventId == TourEventId.TOUR_CHANGED || eventId == TourEventId.UPDATE_UI) {

                    // check if a tour must be updated

                } else if (eventId == TourEventId.MARKER_SELECTION && eventData instanceof SelectionTourMarker) {

                    onSelectionChanged((SelectionTourMarker) eventData);

                } else if ((eventId == TourEventId.TOUR_SELECTION) && eventData instanceof ISelection) {

                    onSelectionChanged((ISelection) eventData);

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

                    clearView();
                }
            }
        };

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

    private void clearView() {

    }

    private void createActions() {

        _actionToggleGalleryOrientation = new ActionToggleGalleryOrientation();
    }

    @Override
    public void createPartControl(final Composite parent) {

        createUI(parent);

        createActions();
        fillActionBar();

        addSelectionListener();
        addTourEventListener();
        addPrefListener();
        addPartListener();
        PhotoManager.addPhotoEventListener(this);

        restoreState();

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

        showTour();
    }

    private void createUI(final Composite parent) {

        createUI_10_Gallery(parent);
        createUI_20_ActionBar(_photoGallery.getCustomActionBarContainer());

        // must be called after the custom action bar is created
        _photoGallery.createActionBar();
    }

    private void createUI_10_Gallery(final Composite parent) {

        final Composite container = new Composite(parent, SWT.NONE);
        GridDataFactory.fillDefaults().grab(true, true).applyTo(container);
        GridLayoutFactory.fillDefaults().numColumns(1).applyTo(container);
        {
            _photoGallery = new PhotoGallery(_state);

            _photoGallery.setShowCustomActionBar();
            _photoGallery.setShowThumbnailSize();

            _photoGallery.createPhotoGallery(container, SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI,
                    new PhotoGalleryProvider());

            _photoGallery.setDefaultStatusMessage(Messages.Photo_Gallery_Label_NoTourWithPhoto);
        }
    }

    private void createUI_20_ActionBar(final Composite parent) {

        GridLayoutFactory.fillDefaults().applyTo(parent);

        final Composite container = new Composite(parent, SWT.NONE);
        GridDataFactory.fillDefaults()//
                .grab(true, true).align(SWT.FILL, SWT.CENTER).applyTo(container);
        GridLayoutFactory.fillDefaults().numColumns(2).applyTo(container);
        //      container.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_MAGENTA));
        {
            /*
             * label: title
             */
            _labelTitle = new Label(container, SWT.NONE);
            GridDataFactory.fillDefaults()//
                    .grab(true, true).align(SWT.FILL, SWT.CENTER)
                    //               .hint(20, SWT.DEFAULT)
                    .applyTo(_labelTitle);
            //         _labelTitle.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_BLUE));

            /*
             * create toolbar for the buttons on the left side
             */
            _toolbarLeft = new ToolBar(container, SWT.FLAT);
            GridDataFactory.fillDefaults()//
                    .align(SWT.FILL, SWT.CENTER)
                    //               .grab(false, true)
                    .applyTo(_toolbarLeft);
            //         _toolbarLeft.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_YELLOW));
        }
    }

    @Override
    public void dispose() {

        final IWorkbenchPage page = getViewSite().getPage();

        page.removePostSelectionListener(_postSelectionListener);
        page.removePartListener(_partListener);

        TourManager.getInstance().removeTourEventListener(_tourEventListener);
        PhotoManager.removePhotoEventListener(this);

        _prefStore.removePropertyChangeListener(_prefChangeListener);

        super.dispose();
    }

    private void fillActionBar() {

        /*
         * fill gallery toolbar
         */
        _galleryToolbarManager = new ToolBarManager(_toolbarLeft);

        _galleryToolbarManager.add(_actionToggleGalleryOrientation);

        _galleryToolbarManager.update(true);
    }

    /**
     * Get photos from a tour.
     * 
     * @param allPhotos
     * @param tourData
     */
    private void getPhotos(final ArrayList<Photo> allPhotos, final TourData tourData) {

        if (tourData == null) {
            return;
        }

        final ArrayList<Photo> galleryPhotos = tourData.getGalleryPhotos();

        if (galleryPhotos == null) {
            return;
        }

        allPhotos.addAll(galleryPhotos);

        _galleryPositionKey += galleryPhotos.hashCode();

        final int gallerySize = galleryPhotos.size();
        if (gallerySize > 0) {

            final long tourStartTime = galleryPhotos.get(0).adjustedTimeTour;
            final long tourEndTime = galleryPhotos.get(gallerySize - 1).adjustedTimeTour;

            if (tourStartTime < _photoStartTime) {
                _photoStartTime = tourStartTime;
            }
            if (tourEndTime > _photoEndTime) {
                _photoEndTime = tourEndTime;
            }
        }
    }

    private void onSelectionChanged(final ISelection selection) {

        //      System.out.println(net.tourbook.common.UI.timeStampNano() + " TourPhotosView\t" + selection);
        //      // TODO remove SYSTEM.OUT.PRINTLN

        final ArrayList<Photo> allPhotos = new ArrayList<Photo>();

        _galleryPositionKey = 0;
        _photoStartTime = Long.MAX_VALUE;
        _photoEndTime = Long.MIN_VALUE;
        _isLinkPhotoDisplayed = false;

        if (selection instanceof TourPhotoLinkSelection) {

            _isLinkPhotoDisplayed = true;

            final TourPhotoLinkSelection tourPhotoSelection = (TourPhotoLinkSelection) selection;

            final ArrayList<TourPhotoLink> photoLinks = tourPhotoSelection.tourPhotoLinks;

            for (final TourPhotoLink photoLink : photoLinks) {

                allPhotos.addAll(photoLink.linkPhotos);

                _galleryPositionKey += photoLink.linkId;

                final long tourStartTime = photoLink.tourStartTime;
                final long tourEndTime = photoLink.tourEndTime;

                if (tourStartTime < _photoStartTime) {
                    _photoStartTime = tourStartTime;
                }
                if (tourEndTime > _photoEndTime) {
                    _photoEndTime = tourEndTime;
                }
            }

            updateUI(allPhotos);

        } else if (selection instanceof SelectionTourMarker) {

            final TourData tourData = ((SelectionTourMarker) selection).getTourData();

            getPhotos(allPhotos, tourData);
            updateUI(allPhotos);

        } else if (selection instanceof SelectionTourData) {

            final TourData tourData = ((SelectionTourData) selection).getTourData();

            getPhotos(allPhotos, tourData);
            updateUI(allPhotos);

        } else if (selection instanceof SelectionTourId) {

            final SelectionTourId tourIdSelection = (SelectionTourId) selection;
            final TourData tourData = TourManager.getInstance().getTourData(tourIdSelection.getTourId());

            getPhotos(allPhotos, tourData);
            updateUI(allPhotos);

        } else if (selection instanceof SelectionTourIds) {

            // paint all selected tours

            final ArrayList<Long> tourIds = ((SelectionTourIds) selection).getTourIds();

            for (final Long tourId : tourIds) {

                final TourData tourData = TourManager.getInstance().getTourData(tourId);

                getPhotos(allPhotos, tourData);
            }

            updateUI(allPhotos);
        }

        /*
         * ensure the selection is set correctly and overwrite PhotogalleryProvider.setSelection()
         * which caused wrong behaviour
         */
        _postSelectionProvider.setSelectionNoFireEvent(selection);
    }

    @Override
    public void photoEvent(final IViewPart viewPart, final PhotoEventId photoEventId, final Object data) {

        if (photoEventId == PhotoEventId.PHOTO_SELECTION) {

            if (data instanceof TourPhotoLinkSelection) {

                final TourPhotoLinkSelection linkSelection = (TourPhotoLinkSelection) data;

                if (_isPartVisible == false) {

                    _selectionWhenHidden = linkSelection;

                } else {

                    onSelectionChanged(linkSelection);
                }
            }

        } else if (photoEventId == PhotoEventId.PHOTO_ATTRIBUTES_ARE_MODIFIED) {

            if (data instanceof ArrayList<?>) {

                final ArrayList<?> arrayList = (ArrayList<?>) data;

                _photoGallery.updatePhotos(arrayList);
            }

        } else if (photoEventId == PhotoEventId.PHOTO_IMAGE_PATH_IS_MODIFIED) {

            _photoGallery.refreshUI();
        }
    }

    private void restoreState() {

        updateColors(true);

        _photoGallery.restoreState();

        // set gallery orientation, default is horizontal
        _isVerticalGallery = Util.getStateBoolean(_state, STATE_PHOTO_GALLERY_IS_VERTICAL, false);
        _photoGallery.setVertical(_isVerticalGallery);

        updateUI_ToogleAction();
    }

    private void saveState() {

        _state.put(STATE_PHOTO_GALLERY_IS_VERTICAL, _isVerticalGallery);

        _photoGallery.saveState();
    }

    @Override
    public void setFocus() {

    }

    private void showTour() {

        Display.getCurrent().asyncExec(new Runnable() {
            @Override
            public void run() {

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

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

    private void updateColors(final boolean isRestore) {

        final ColorRegistry colorRegistry = JFaceResources.getColorRegistry();

        final Color fgColor = colorRegistry.get(IPhotoPreferences.PHOTO_VIEWER_COLOR_FOREGROUND);
        final Color bgColor = colorRegistry.get(IPhotoPreferences.PHOTO_VIEWER_COLOR_BACKGROUND);
        final Color selectionFgColor = colorRegistry.get(IPhotoPreferences.PHOTO_VIEWER_COLOR_SELECTION_FOREGROUND);

        final Color noFocusSelectionFgColor = Display.getCurrent()
                .getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND);

        _photoGallery.updateColors(fgColor, bgColor, selectionFgColor, noFocusSelectionFgColor, isRestore);
    }

    private void updateUI(final ArrayList<Photo> allPhotos) {

        /*
         * update photo gallery
         */

        _photoGallery.showImages(//
                allPhotos, Long.toString(_galleryPositionKey) + "_TourPhotosView", //$NON-NLS-1$
                _isLinkPhotoDisplayed, false);

        /*
         * set title
         */
        final int size = allPhotos.size();
        String labelText;

        if (size == 1) {

            labelText = TimeTools.getZonedDateTime(_photoStartTime).format(TimeTools.Formatter_DateTime_M);

        } else if (size > 1) {

            labelText = TimeTools.getZonedDateTime(_photoStartTime).format(TimeTools.Formatter_DateTime_M)
                    + UI.DASH_WITH_DOUBLE_SPACE
                    + TimeTools.getZonedDateTime(_photoEndTime).format(TimeTools.Formatter_DateTime_M);

        } else {

            labelText = UI.EMPTY_STRING;
        }

        _labelTitle.setText(labelText);
        _labelTitle.setToolTipText(labelText);
    }

    private void updateUI_ToogleAction() {

        if (_isVerticalGallery) {

            _actionToggleGalleryOrientation.setToolTipText(//
                    Messages.Photo_Gallery_Action_ToggleGalleryHorizontal_ToolTip);

            _actionToggleGalleryOrientation.setImageDescriptor(//
                    TourbookPlugin.getImageDescriptor(Messages.Image__PhotoGalleryHorizontal));

        } else {

            _actionToggleGalleryOrientation.setToolTipText(//
                    Messages.Photo_Gallery_Action_ToggleGalleryVertical_ToolTip);

            _actionToggleGalleryOrientation.setImageDescriptor(//
                    TourbookPlugin.getImageDescriptor(Messages.Image__PhotoGalleryVertical));
        }
    }
}