Java tutorial
/******************************************************************************* * Copyright (C) 2005, 2013 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 net.tourbook.Messages; import net.tourbook.common.tooltip.AnimatedToolTipShell; import net.tourbook.common.util.Util; import net.tourbook.map2.view.MapFilterData; import net.tourbook.photo.IPhotoEventListener; import net.tourbook.photo.IPhotoPreferences; import net.tourbook.photo.Photo; import net.tourbook.photo.PhotoEventId; import net.tourbook.photo.PhotoManager; import net.tourbook.photo.RatingStars; import org.eclipse.core.runtime.ListenerList; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.resource.ColorRegistry; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseTrackAdapter; import org.eclipse.swt.events.MouseWheelListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Spinner; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.ui.IViewPart; import de.byteholder.geoclipse.map.UI; /** * Photo properties dialog. */ public class DialogPhotoProperties extends AnimatedToolTipShell implements IPhotoEventListener { private static final int SHELL_MARGIN = 5; private static final int MIN_IMAGE_WIDTH = 10; /** * This value is small because a map do not yet load large images !!! */ private static final int MAX_IMAGE_WIDTH = 200; private static final String STATE_PHOTO_FILTER_RATING_STARS = "STATE_PHOTO_FILTER_RATING_STARS"; //$NON-NLS-1$ private static final String STATE_PHOTO_FILTER_RATING_STAR_OPERATOR = "STATE_PHOTO_FILTER_RATING_STAR_OPERATOR"; //$NON-NLS-1$ private static final String STATE_PHOTO_PROPERTIES_IMAGE_SIZE = "STATE_PHOTO_PROPERTIES_IMAGE_SIZE"; //$NON-NLS-1$ private IDialogSettings _state; // initialize with default values which are (should) never be used private Rectangle _itemBounds = new Rectangle(0, 0, 50, 50); private final WaitTimer _waitTimer = new WaitTimer(); private boolean _canOpenToolTip; private boolean _isWaitTimerStarted; private int _filterRatingStars = RatingStars.MAX_RATING_STARS; private final ListenerList _propertiesListeners = new ListenerList(ListenerList.IDENTITY); private int _imageSize; /* * filter operator */ private int _filterRatingStarOperatorIndex; /* * UI resources */ private Color _fgColor; private Color _bgColor; private MapFilterData _oldMapFilterData; /* * UI controls */ private Composite _shellContainer; private Composite _containerFilterHeader; private Label _lblAllPhotos; private Label _lblFilteredPhotos; private Combo _comboRatingStarOperators; private RatingStars _ratingStars; private Spinner _spinnerImageSize; public static final int OPERATOR_IS_LESS_OR_EQUAL = 0; public static final int OPERATOR_IS_EQUAL = 1; public static final int OPERATOR_IS_MORE_OR_EQUAL = 2; private static final String[] _ratingStarOperatorsText = { Messages.Photo_Filter_Operator_IsLess, Messages.Photo_Filter_Operator_IsEqual, Messages.Photo_Filter_Operator_IsMore, // }; /** * <b>THEY MUST BE IN SYNC WITH </b> {@link #_filterRatingStarOperatorsText} */ private static final int[] _ratingStarOperatorsValues = { OPERATOR_IS_LESS_OR_EQUAL, OPERATOR_IS_EQUAL, OPERATOR_IS_MORE_OR_EQUAL, // }; private final class WaitTimer implements Runnable { @Override public void run() { open_Runnable(); } } public DialogPhotoProperties(final Control ownerControl, final ToolBar toolBar, final IDialogSettings state) { super(ownerControl); _state = state; toolBar.addMouseTrackListener(new MouseTrackAdapter() { @Override public void mouseExit(final MouseEvent e) { // prevent to open the tooltip _canOpenToolTip = false; } }); PhotoManager.addPhotoEventListener(this); setToolTipCreateStyle(AnimatedToolTipShell.TOOLTIP_STYLE_KEEP_CONTENT); setBehaviourOnMouseOver(AnimatedToolTipShell.MOUSE_OVER_BEHAVIOUR_IGNORE_OWNER); setIsKeepShellOpenWhenMoved(false); setFadeInSteps(1); } public void addPropertiesListener(final IPhotoPropertiesListener listener) { _propertiesListeners.add(listener); } @Override protected boolean canShowToolTip() { return true; } @Override protected Composite createToolTipContentArea(final Composite parent) { final Composite container = createUI(parent); final ColorRegistry colorRegistry = JFaceResources.getColorRegistry(); _fgColor = colorRegistry.get(IPhotoPreferences.PHOTO_VIEWER_COLOR_FOREGROUND); _bgColor = colorRegistry.get(IPhotoPreferences.PHOTO_VIEWER_COLOR_BACKGROUND); updateUI(); net.tourbook.common.UI.setChildColors(parent, _fgColor, _bgColor); if (_oldMapFilterData != null) { /* * _oldMapFilterData can be set before the UI is created */ updateFilterUI(_oldMapFilterData); } enableActions(); return container; } private Composite createUI(final Composite parent) { _shellContainer = new Composite(parent, SWT.NONE); GridLayoutFactory.fillDefaults()// .margins(SHELL_MARGIN, SHELL_MARGIN).numColumns(3).applyTo(_shellContainer); { createUI_10_Filter(_shellContainer); // spacer final Label label = new Label(_shellContainer, SWT.NONE); GridDataFactory.fillDefaults().hint(20, 0).applyTo(label); createUI_20_ImageSize(_shellContainer); } return _shellContainer; } private void createUI_10_Filter(final Composite parent) { final Composite container = new Composite(parent, SWT.NO_FOCUS); GridLayoutFactory.fillDefaults().numColumns(2).applyTo(container); container.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_BLUE)); { /* * label: photo filter */ final Label label = new Label(container, SWT.NO_FOCUS); GridDataFactory.fillDefaults().applyTo(label); label.setText(Messages.Photo_Filter_Label_RatingStars); label.setToolTipText(Messages.Photo_Filter_Label_RatingStars_Tooltip); createUI_12_FilterHeader(container); /* * combo: > = < */ // _comboRatingStarOperators = new Combo(container, SWT.READ_ONLY); _comboRatingStarOperators = new Combo(container, SWT.READ_ONLY); GridDataFactory.fillDefaults()// .align(SWT.END, SWT.FILL) // .hint(_pc.convertWidthInCharsToPixels(15), SWT.DEFAULT) .applyTo(_comboRatingStarOperators); _comboRatingStarOperators.setVisibleItemCount(10); // _comboRatingStarOperators.setToolTipText(Messages.Photos_PhotoFilter_Combo_RatingStarOperands_Tooltip); _comboRatingStarOperators.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { onSelectRatingStarOperands(); } }); /* * rating stars */ _ratingStars = new RatingStars(container); _ratingStars.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { onSelectRatingStars(); } }); } } private void createUI_12_FilterHeader(final Composite parent) { _containerFilterHeader = new Composite(parent, SWT.NONE); GridDataFactory.fillDefaults()// .applyTo(_containerFilterHeader); GridLayoutFactory.fillDefaults()// .applyTo(_containerFilterHeader); // _containerFilterHeader.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_RED)); { /* * inner container is used to center horizontally */ final Composite innerContainer = new Composite(_containerFilterHeader, SWT.NONE); GridDataFactory.fillDefaults().// grab(true, false).align(SWT.CENTER, SWT.FILL).applyTo(innerContainer); GridLayoutFactory.fillDefaults().numColumns(3).applyTo(innerContainer); // innerContainer.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_MAGENTA)); { /* * value: number of all photos */ _lblAllPhotos = new Label(innerContainer, SWT.NO_FOCUS); _lblAllPhotos.setText(UI.EMPTY_STRING); _lblAllPhotos.setToolTipText(Messages.Photo_Filter_Label_NumberOfAllPhotos_Tooltip); /* * label: number of filtered photos */ final Label label = new Label(innerContainer, SWT.NO_FOCUS); label.setText(UI.DASH_WITH_SPACE); /* * value: number of filtered photos */ _lblFilteredPhotos = new Label(innerContainer, SWT.NO_FOCUS); _lblFilteredPhotos.setText(UI.EMPTY_STRING); _lblFilteredPhotos.setToolTipText(Messages.Photo_Filter_Label_NumberOfFilteredPhotos_Tooltip); } } } private void createUI_20_ImageSize(final Composite parent) { final Composite container = new Composite(parent, SWT.NONE); // GridDataFactory.fillDefaults().grab(true, false).applyTo(container); GridLayoutFactory.fillDefaults().numColumns(1).applyTo(container); { /* * label: displayed photos */ final Label label = new Label(container, SWT.NO_FOCUS); GridDataFactory.fillDefaults()// // .align(SWT.CENTER, SWT.BEGINNING) .applyTo(label); label.setText(Messages.Photo_Properties_Label_Size); label.setToolTipText(Messages.Photo_Properties_Label_ThumbnailSize_Tooltip); /* * spinner: size */ _spinnerImageSize = new Spinner(container, SWT.BORDER); GridDataFactory.fillDefaults() // .align(SWT.BEGINNING, SWT.FILL).applyTo(_spinnerImageSize); _spinnerImageSize.setMinimum(MIN_IMAGE_WIDTH); _spinnerImageSize.setMaximum(MAX_IMAGE_WIDTH); _spinnerImageSize.setIncrement(1); _spinnerImageSize.setPageIncrement(10); _spinnerImageSize.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { onSelectImageSize(); } }); _spinnerImageSize.addMouseWheelListener(new MouseWheelListener() { @Override public void mouseScrolled(final MouseEvent event) { Util.adjustSpinnerValueOnMouseScroll(event); onSelectImageSize(); } }); } } private void enableActions() { // final boolean isRatingStars = _filterRatingStars > 0; // // _comboRatingStarOperators.setEnabled(isRatingStars); } private void firePropertiesEvent() { final PhotoPropertiesEvent propertyEvent = new PhotoPropertiesEvent(); propertyEvent.filterRatingStars = _filterRatingStars; propertyEvent.fiterRatingStarOperator = _ratingStarOperatorsValues[_filterRatingStarOperatorIndex]; final Object[] listeners = _propertiesListeners.getListeners(); for (final Object listener : listeners) { ((IPhotoPropertiesListener) listener).photoPropertyEvent(propertyEvent); } } @Override public Point getToolTipLocation(final Point tipSize) { final int tipWidth = tipSize.x; final int itemWidth = _itemBounds.width; final int itemHeight = _itemBounds.height; final int itemWidth2 = itemWidth / 2; final int tipWidth2 = tipWidth / 2; final int devX = _itemBounds.x + itemWidth2 - tipWidth2; final int devY = _itemBounds.y + itemHeight + 0; return new Point(devX, devY); } @Override protected Rectangle noHideOnMouseMove() { return _itemBounds; } @Override protected void onDispose() { PhotoManager.removePhotoEventListener(this); } private void onSelectImageSize() { final int oldImageSize = _imageSize; _imageSize = _spinnerImageSize.getSelection(); // optimize fire event if (oldImageSize != _imageSize) { Photo.setPaintedMapImageWidth(_imageSize); firePropertiesEvent(); } } private void onSelectRatingStarOperands() { _filterRatingStarOperatorIndex = _comboRatingStarOperators.getSelectionIndex(); firePropertiesEvent(); } private void onSelectRatingStars() { final int selectedStars = _ratingStars.getSelection(); _filterRatingStars = selectedStars; enableActions(); firePropertiesEvent(); } /** * @param itemBounds * @param isOpenDelayed */ public void open(final Rectangle itemBounds, final boolean isOpenDelayed) { if (isToolTipVisible()) { return; } if (isOpenDelayed == false) { if (itemBounds != null) { _itemBounds = itemBounds; showToolTip(); } } else { if (itemBounds == null) { // item is not hovered any more _canOpenToolTip = false; return; } _itemBounds = itemBounds; _canOpenToolTip = true; // System.out.println(UI.timeStampNano() // + " open\t2\t_isWaitTimerStarted=" // + _isWaitTimerStarted // + ("\t_canOpenToolTip=" + _canOpenToolTip) // + ("\t__itemBounds=" + _itemBounds) // // // ); // // TODO remove SYSTEM.OUT.PRINTLN if (_isWaitTimerStarted == false) { _isWaitTimerStarted = true; Display.getCurrent().timerExec(50, _waitTimer); } } } private void open_Runnable() { _isWaitTimerStarted = false; if (_canOpenToolTip) { showToolTip(); } } @Override public void photoEvent(final IViewPart viewPart, final PhotoEventId photoEventId, final Object data) { if (photoEventId == PhotoEventId.PHOTO_FILTER) { if (data instanceof MapFilterData) { updateFilterUI((MapFilterData) data); } } } public void restoreState() { _filterRatingStars = Util.getStateInt(_state, STATE_PHOTO_FILTER_RATING_STARS, RatingStars.MAX_RATING_STARS); _filterRatingStarOperatorIndex = Util.getStateInt(_state, STATE_PHOTO_FILTER_RATING_STAR_OPERATOR, OPERATOR_IS_EQUAL); _imageSize = Util.getStateInt(_state, STATE_PHOTO_PROPERTIES_IMAGE_SIZE, Photo.MAP_IMAGE_DEFAULT_WIDTH_HEIGHT); // ensure that an image is displayed, it happend that image size was 0 if (_imageSize < 10) { _imageSize = Photo.MAP_IMAGE_DEFAULT_WIDTH_HEIGHT; } // set image size for the map photos Photo.setPaintedMapImageWidth(_imageSize); // set photo filter into the map firePropertiesEvent(); } public void saveState() { _state.put(STATE_PHOTO_FILTER_RATING_STARS, _filterRatingStars); _state.put(STATE_PHOTO_FILTER_RATING_STAR_OPERATOR, _filterRatingStarOperatorIndex); _state.put(STATE_PHOTO_PROPERTIES_IMAGE_SIZE, _imageSize); } /** * This is called when the filter is run and filter statistics are available. * * @param data */ protected void updateFilterActionUI(final MapFilterData data) { // do nothing } private void updateFilterUI(final MapFilterData data) { if (_lblAllPhotos == null || _lblAllPhotos.isDisposed()) { // UI is not initialized _oldMapFilterData = data; return; } _lblAllPhotos.setText(Integer.toString(data.allPhotos)); _lblFilteredPhotos.setText(Integer.toString(data.filteredPhotos)); _containerFilterHeader.layout(); // update action button updateFilterActionUI(data); } private void updateUI() { // select rating star _ratingStars.setSelection(_filterRatingStars); for (final String operator : _ratingStarOperatorsText) { _comboRatingStarOperators.add(operator); } // ensure array bounds if (_filterRatingStarOperatorIndex >= _ratingStarOperatorsText.length) { _filterRatingStarOperatorIndex = 0; } // select operator _comboRatingStarOperators.select(_filterRatingStarOperatorIndex); // image size _spinnerImageSize.setSelection(_imageSize); } }