/**
* eAdventure (formerly <e-Adventure> and <e-Game>) is a research project of the
* <e-UCM> research group.
*
* Copyright 2005-2010 <e-UCM> research group.
*
* You can access a list of all the contributors to eAdventure at:
* http://e-adventure.e-ucm.es/contributors
*
* <e-UCM> is a research group of the Department of Software Engineering
* and Artificial Intelligence at the Complutense University of Madrid
* (School of Computer Science).
*
* C Profesor Jose Garcia Santesmases sn,
* 28040 Madrid (Madrid), Spain.
*
* For more info please visit: <http://e-adventure.e-ucm.es> or
* <http://www.e-ucm.es>
*
* ****************************************************************************
*
* This file is part of eAdventure, version 2.0
*
* eAdventure is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* eAdventure 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with eAdventure. If not, see <http://www.gnu.org/licenses/>.
*/
package es.eucm.ead.editor.view.components;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import javax.swing.JPanel;
import javax.swing.JViewport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A zoomable JPanel. Catches mouse scrolling and translates it into zooming
* (x-axis, y-axis or both) + translation within the containing JScrollPane
* to keep the center point always centered.
*
* @author mfreire
*/
public class ZoomablePanel extends JPanel {
static private Logger logger = LoggerFactory.getLogger(ZoomablePanel.class);
private double zoomFactor = 1.08;
private boolean zoomXAxis = true;
private boolean zoomYAxis = true;
protected int width;
protected int height;
protected int baseWidth;
protected int baseHeight;
private Point last = new Point();
private boolean dragging = false;
private Component maxSizeReference;
public ZoomablePanel(boolean zoomXAxis, boolean zoomYAxis) {
this.zoomXAxis = zoomXAxis;
this.zoomYAxis = zoomYAxis;
// mouse listener to detect scrollwheel events
addMouseWheelListener(new MouseWheelListener() {
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
updatePreferredSize(e.getWheelRotation(), e.getPoint());
}
});
this.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
MouseAdapter listener = new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
dragging = false;
}
@Override
public void mousePressed(MouseEvent e) {
dragging = true;
last = e.getPoint();
}
@Override
public void mouseDragged(MouseEvent e) {
if (dragging) {
Point p = e.getPoint();
int offX = p.x - last.x;
int offY = p.y - last.y;
Point next = new Point(((JViewport) getParent())
.getViewPosition());
next.x += offX;
next.y += offY;
// clamp
next.x = Math.max(0, next.x);
next.x = Math.min(width - getParent().getWidth(), next.x);
next.y = Math.max(0, next.y);
next.y = Math.min(height - getParent().getHeight(), next.y);
((JViewport) getParent()).setViewPosition(next);
last = p;
}
}
};
addMouseListener(listener);
addMouseMotionListener(listener);
}
public void setMaxSizeReference(Component maxSizeReference) {
this.maxSizeReference = maxSizeReference;
}
public void resetZoom() {
int pw = maxSizeReference.getWidth() - 4;
int ph = maxSizeReference.getHeight() - 4;
double zoomX = pw * 1.0 / baseWidth;
double zoomY = ph * 1.0 / baseHeight;
double z = Math.min(zoomX, zoomY);
last = new Point();
updateZoom(z);
}
public void resetZoomNative() {
updateZoom(1);
}
private void updateZoom(double zoom) {
width = (int) (baseWidth * zoom);
height = (int) (baseHeight * zoom);
zoom(last, 1, 1);
}
private void updatePreferredSize(int n, Point p) {
double dx = (double) n * zoomFactor;
double dy = (double) n * zoomFactor;
dx = (n > 0) ? 1 / dx : -dx;
dy = (n > 0) ? 1 / dy : -dy;
if (!zoomXAxis) {
dx = 1;
}
if (!zoomYAxis) {
dy = 1;
}
width = (int) (getWidth() * dx);
height = (int) (getHeight() * dy);
zoom(p, dx, dy);
}
private void zoom(Point p, double dx, double dy) {
logger.debug("ZoomablePanel requesting {}x{}", new Object[] { width,
height });
setPreferredSize(new Dimension(width, height));
if (p != null) {
int offX = (int) (p.x * dx) - p.x;
int offY = (int) (p.y * dy) - p.y;
setLocation(getLocation().x - offX, getLocation().y - offY);
}
getParent().doLayout();
last = p;
}
}