/******************************************************************************* * Copyright (c) 2016 Weasis Team and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Nicolas Roduit - initial API and implementation *******************************************************************************/ package org.weasis.core.ui.editor.image; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.MouseEvent; import java.awt.geom.Rectangle2D; import javax.swing.event.MouseInputAdapter; import org.weasis.core.api.gui.util.JMVUtils; import org.weasis.core.api.image.OpManager; import org.weasis.core.api.media.data.ImageElement; import org.weasis.core.api.media.data.MediaElement; import org.weasis.core.api.media.data.Thumbnail; /** * * * @author Nicolas Roduit */ public final class Panner<E extends ImageElement> extends Thumbnail { private MouseClickHandler mouseClickHandler = new MouseClickHandler(); private PopUpMenuOnThumb popup = null; private final DefaultView2d<E> view; private Rectangle slider; private Rectangle panArea; private boolean updatingImageDisplay; public Panner(DefaultView2d<E> view) { super(156); this.view = view; setForeground(JMVUtils.TREE_SELECTION_BACKROUND); slider = new Rectangle(0, 0, 0, 0); panArea = new Rectangle(0, 0, 0, 0); } @Override protected void init(MediaElement media, boolean keepMediaCache, OpManager opManager) { super.init(media, keepMediaCache, opManager); } @Override public void registerListeners() { super.registerListeners(); popup = new PopUpMenuOnThumb(this); popup.setInvoker(this); addMouseListener(mouseClickHandler); addMouseMotionListener(mouseClickHandler); } @Override public void doLayout() { super.doLayout(); updateImageSize(); } public boolean isUpdatingImageDisplay() { return updatingImageDisplay; } public void setSlider(Rectangle slider) { Rectangle oldSlider = this.slider; this.slider = new Rectangle(slider); firePropertyChange("slider", oldSlider, this.slider); //$NON-NLS-1$ } private void updateImageDisplay() { if (view != null) { final Rectangle2D ma = view.getViewModel().getModelArea(); double mpX = ma.getX() + (slider.getX() - panArea.getX()) * ma.getWidth() / panArea.getWidth(); double mpY = ma.getY() + (slider.getY() - panArea.getY()) * ma.getHeight() / panArea.getHeight(); updatingImageDisplay = true; view.setOrigin(mpX, mpY); updatingImageDisplay = false; } } public void updateImage() { if (view != null) { E img = view.getImage(); if (img != null) { thumbnailPath = null; readable = true; buildThumbnail(img, false, view.getImageLayer().getPreprocessing()); updateImageSize(); } } } public void updateImageSize() { if (view != null) { final Insets insets = getInsets(); int imageWidth = getWidth() - (insets.left + insets.right); int imageHeight = getHeight() - (insets.top + insets.bottom); final double imageRatio = (double) imageWidth / (double) imageHeight; final Rectangle2D ma = view.getViewModel().getModelArea(); final double modelRatio = ma.getWidth() / ma.getHeight(); if (imageRatio < modelRatio) { imageHeight = (int) Math.round(imageWidth / modelRatio); } else { imageWidth = (int) Math.round(imageHeight * modelRatio); } if (imageWidth > 0 && imageHeight > 0) { panArea.setRect(0, 0, imageWidth, imageHeight); if (imageWidth < getWidth()) { panArea.x = (getWidth() - imageWidth) / 2; } if (imageHeight < getHeight()) { panArea.y = (getHeight() - imageHeight) / 2; } updateSlider(); } } } public void updateSlider() { if (updatingImageDisplay || view == null) { return; } final Rectangle2D ma = view.getViewModel().getModelArea(); final double vs = view.getViewModel().getViewScale(); int width = view.getWidth() - 1; int height = view.getHeight() - 1; final Rectangle2D va = new Rectangle2D.Double(view.getViewModel().getModelOffsetX(), view.getViewModel().getModelOffsetY(), width / vs, height / vs); slider.x = panArea.x + (int) Math.round(panArea.width * (va.getX() - ma.getX()) / ma.getWidth()); slider.y = panArea.y + (int) Math.round(panArea.height * (va.getY() - ma.getY()) / ma.getHeight()); slider.width = (int) Math.round(panArea.width * va.getWidth() / ma.getWidth()); slider.height = (int) Math.round(panArea.height * va.getHeight() / ma.getHeight()); repaint(); } public void moveToOrigin() { if (view != null) { view.setOrigin(0d, 0d); } } public void moveToCenter() { if (view != null) { view.center(); } } public void moveSlider(int x, int y) { if (view != null) { view.moveOrigin(x * 10, y * 10); } } @Override protected void drawOverIcon(Graphics2D g2d, int x, int y, int width, int height) { g2d.setColor(new Color(getForeground().getRed(), getForeground().getGreen(), getForeground().getBlue(), 40)); g2d.fillRect(slider.x, slider.y, slider.width, slider.height); g2d.setColor(getForeground()); g2d.draw3DRect(slider.x - 1, slider.y - 1, slider.width + 2, slider.height + 2, true); g2d.draw3DRect(slider.x, slider.y, slider.width, slider.height, false); } class MouseClickHandler extends MouseInputAdapter { private Point pickPoint; private Point sliderPoint; @Override public void mousePressed(MouseEvent e) { pickPoint = e.getPoint(); if (!slider.contains(pickPoint)) { slider.x = pickPoint.x - slider.width / 2; slider.y = pickPoint.y - slider.height / 2; repaint(); } sliderPoint = slider.getLocation(); if (e.isPopupTrigger()) { popup.show(e.getComponent(), e.getX(), e.getY()); } } @Override public void mouseReleased(MouseEvent mouseevent) { if (mouseevent.isPopupTrigger()) { popup.show(mouseevent.getComponent(), mouseevent.getX(), mouseevent.getY()); } updateImageDisplay(); repaint(); } @Override public void mouseDragged(MouseEvent e) { if (pickPoint != null) { slider.x = sliderPoint.x + (e.getX() - pickPoint.x); slider.y = sliderPoint.y + (e.getY() - pickPoint.y); updateImageDisplay(); repaint(); } } } }