/*******************************************************************************
* This file is part of logisim-evolution.
*
* logisim-evolution 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, either version 3 of the License, or
* (at your option) any later version.
*
* logisim-evolution 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 logisim-evolution. If not, see <http://www.gnu.org/licenses/>.
*
* Original code by Carl Burch (http://www.cburch.com), 2011.
* Subsequent modifications by :
* + Haute École Spécialisée Bernoise
* http://www.bfh.ch
* + Haute École du paysage, d'ingénierie et d'architecture de Genève
* http://hepia.hesge.ch/
* + Haute École d'Ingénierie et de Gestion du Canton de Vaud
* http://www.heig-vd.ch/
* The project is currently maintained by :
* + REDS Institute - HEIG-VD
* Yverdon-les-Bains, Switzerland
* http://reds.heig-vd.ch
*******************************************************************************/
package com.cburch.logisim.gui.generic;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JScrollPane;
import javax.swing.SwingConstants;
import com.cburch.logisim.util.MacCompatibility;
public class CanvasPane extends JScrollPane {
private class Listener implements ComponentListener, PropertyChangeListener {
public void componentHidden(ComponentEvent e) {
}
public void componentMoved(ComponentEvent e) {
}
//
// ComponentListener methods
//
public void componentResized(ComponentEvent e) {
contents.recomputeSize();
}
public void componentShown(ComponentEvent e) {
}
public void propertyChange(PropertyChangeEvent e) {
String prop = e.getPropertyName();
if (prop.equals(ZoomModel.ZOOM)) {
double oldZoom = ((Double) e.getOldValue()).doubleValue();
Rectangle r = getViewport().getViewRect();
double cx = (r.x + r.width / 2) / oldZoom;
double cy = (r.y + r.height / 2) / oldZoom;
double newZoom = ((Double) e.getNewValue()).doubleValue();
contents.recomputeSize();
r = getViewport().getViewRect();
int hv = (int) (cx * newZoom) - r.width / 2;
int vv = (int) (cy * newZoom) - r.height / 2;
getHorizontalScrollBar().setValue(hv);
getVerticalScrollBar().setValue(vv);
}
}
}
private static final long serialVersionUID = 1L;
private CanvasPaneContents contents;
private Listener listener;
private ZoomModel zoomModel;
public CanvasPane(CanvasPaneContents contents) {
super((Component) contents);
this.contents = contents;
this.listener = new Listener();
this.zoomModel = null;
if (MacCompatibility.mrjVersion >= 0.0) {
setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
}
addComponentListener(listener);
contents.setCanvasPane(this);
}
public Dimension getViewportSize() {
Dimension size = new Dimension();
getViewport().getSize(size);
return size;
}
public double getZoomFactor() {
ZoomModel model = zoomModel;
return model == null ? 1.0 : model.getZoomFactor();
}
public void setZoomModel(ZoomModel model) {
ZoomModel oldModel = zoomModel;
if (oldModel != null) {
oldModel.removePropertyChangeListener(ZoomModel.ZOOM, listener);
}
zoomModel = model;
if (model != null) {
model.addPropertyChangeListener(ZoomModel.ZOOM, listener);
}
}
public Dimension supportPreferredSize(int width, int height) {
double zoom = getZoomFactor();
if (zoom != 1.0) {
width = (int) Math.ceil(width * zoom);
height = (int) Math.ceil(height * zoom);
}
Dimension minSize = getViewportSize();
if (minSize.width > width)
width = minSize.width;
if (minSize.height > height)
height = minSize.height;
return new Dimension(width, height);
}
public int supportScrollableBlockIncrement(Rectangle visibleRect,
int orientation, int direction) {
int unit = supportScrollableUnitIncrement(visibleRect, orientation,
direction);
if (direction == SwingConstants.VERTICAL) {
return visibleRect.height / unit * unit;
} else {
return visibleRect.width / unit * unit;
}
}
public int supportScrollableUnitIncrement(Rectangle visibleRect,
int orientation, int direction) {
double zoom = getZoomFactor();
return (int) Math.round(10 * zoom);
}
}