/**
* This file is part of VisiCut.
* Copyright (C) 2011 - 2013 Thomas Oster <thomas.oster@rwth-aachen.de>
* RWTH Aachen University - 52062 Aachen, Germany
*
* VisiCut 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.
*
* VisiCut 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 VisiCut. If not, see <http://www.gnu.org/licenses/>.
**/
package com.t_oster.uicomponents;
import com.t_oster.liblasercut.platform.Util;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import javax.swing.JPanel;
/**
* A JPanel with Support for rendering Graphic Objects.
* This Panel supports Zoom etc.
*
* @author Thomas Oster <thomas.oster@rwth-aachen.de>
*/
public class ZoomablePanel extends JPanel implements MouseWheelListener
{
private Point2D.Double areaSize = new Point2D.Double(600d, 300d);
/**
* Get the value of AreaSize
*
* @return the value of AreaSize
*/
public Point2D.Double getAreaSize()
{
return areaSize;
}
public void setOneToOneZoom()
{
double dpmm = Util.dpi2dpmm(this.getToolkit().getScreenResolution());
double w = this.getAreaSize().x;
double h = this.getAreaSize().y;
double pw = this.getParent().getWidth();
double ph = this.getParent().getHeight();
this.setZoom(pw/ph <= w/h ? 100 * w/pw * dpmm : 100*h/ph*dpmm);
}
public void setZoomToFillParent()
{
double w = this.getAreaSize().x;
double h = this.getAreaSize().y;
double pw = this.getParent().getWidth();
double ph = this.getParent().getHeight();
this.setZoom(w/h > pw/ph ? 100*ph/pw*w/h : 100*pw/ph*h/w);
}
/**
* Set the value of AreaSize
* This ist the area in mm, which will be visible
* when the Zoom is 100%
*
* @param AreaSize new value of AreaSize
*/
public void setAreaSize(Point2D.Double AreaSize)
{
this.areaSize = AreaSize;
this.resizeToFitZoomAndArea();
}
public ZoomablePanel()
{
this.addMouseWheelListener(this);
}
protected double zoom = 100;
public static final String PROP_ZOOM = "zoom";
/**
* Get the value of zoom
*
* @return the value of zoom
*/
public double getZoom()
{
return zoom;
}
/**
* Set the value of zoom in %. 100
*
* @param zoom new value of zoom
*/
public void setZoom(double zoom)
{
this.setZoom(zoom, null);
}
public void resizeToFitZoomAndArea()
{
this.mm2pxCache = null;
if (this.getParent() != null)
{
double w = this.getAreaSize().x;
double h = this.getAreaSize().y;
double pw = this.getParent().getWidth();
double ph = this.getParent().getHeight();
double fullw = pw/ph <= w/h ? pw*zoom/100d : w*ph*zoom/100d/h;
double fullh = pw/ph > w/h ? ph*zoom/100d : h*fullw/w;
this.setPreferredSize(new Dimension((int) (fullw), (int) (fullh)));
this.revalidate();
}
}
public void setZoom(double zoom, Point stablePoint)
{
if (zoom < 100)
{
zoom = 100;
}
double oldZoom = this.zoom;
this.zoom = zoom;
if (oldZoom != zoom)
{
this.resizeToFitZoomAndArea();
if (stablePoint != null)
{
double factor = (double) zoom/ (double) oldZoom;
Point loc = this.getLocation();
loc.setLocation(loc.x-(stablePoint.x*factor - stablePoint.x), loc.y-(stablePoint.y*factor - stablePoint.y));
this.setLocation(loc);
}
}
firePropertyChange(PROP_ZOOM, oldZoom, zoom);
}
private AffineTransform mm2pxCache = null;
/**
* returns the transformation, which transforms coordinates in mm
* of the AreaSize to pixels of the preview panel. Taking into account
* zoom and position.
* @return
*/
public AffineTransform getMmToPxTransform()
{
if (mm2pxCache == null)
{
Dimension d = this.getPreferredSize();
double factor = Math.min(d.width/this.areaSize.x, d.height/this.areaSize.y);
mm2pxCache = AffineTransform.getScaleInstance(factor, factor);
}
return mm2pxCache;
}
public void mouseWheelMoved(MouseWheelEvent mwe)
{
if (mwe.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL)
{
this.setZoom(this.getZoom() - (mwe.getUnitsToScroll() * this.getZoom() / 32), mwe.getPoint());
}
}
}