/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * 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: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.graphviz.drawable; import java.awt.Canvas; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.RenderingHints; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.awt.image.VolatileImage; /** * A canvas showing a given Drawable. * * @author Hannu Niemist� */ public class ViewerCanvas extends Canvas { private static final long serialVersionUID = -1094658958968314511L; AffineTransform transform; Point prev; VolatileImage im; Drawable drawable; public ViewerCanvas(Drawable drawable) { this.drawable = drawable; setBackground(Color.WHITE); addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { if(e.getKeyChar()=='1') { fit(); repaint(); } } }); addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { prev = e.getPoint(); } }); addMouseMotionListener(new MouseAdapter() { @Override public void mouseDragged(MouseEvent e) { Point cur = e.getPoint(); double deltaX = cur.getX()-prev.getX(); double deltaY = cur.getY()-prev.getY(); transform.preConcatenate(AffineTransform.getTranslateInstance(deltaX, deltaY)); repaint(); prev = cur; } }); addMouseWheelListener(new MouseWheelListener() { @Override public void mouseWheelMoved(MouseWheelEvent e) { if(transform != null) { double scale = Math.exp(-0.1*e.getUnitsToScroll()); Point p = e.getPoint(); AffineTransform mod = new AffineTransform(); mod.translate(p.getX(), p.getY()); mod.scale(scale, scale); mod.translate(-p.getX(), -p.getY()); transform.preConcatenate(mod); repaint(); } } }); addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent e) { if(getWidth() > 0 && getHeight() > 0) { im = createVolatileImage(getWidth(), getHeight()); repaint(); } } }); } public void fit() { Rectangle2D bounds = drawable.getBounds(); Rectangle2D container = getBounds(); double scale = Math.min( container.getWidth() / bounds.getWidth(), container.getHeight() / bounds.getHeight()); transform = new AffineTransform( scale, 0.0, 0.0, scale, container.getX() + container.getWidth() * 0.5 - bounds.getCenterX() * scale, container.getY() + container.getHeight() * 0.5 - bounds.getCenterY() * scale ); } @Override public void paint(Graphics _g) { do { if (im == null || im.validate(getGraphicsConfiguration()) == VolatileImage.IMAGE_INCOMPATIBLE) { im = createVolatileImage(getWidth(), getHeight()); } Graphics2D g = (Graphics2D)im.getGraphics(); g.clearRect(0, 0, im.getWidth(null), im.getHeight(null)); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); if(transform == null) fit(); g.setTransform(transform); drawable.draw(g, null); g.dispose(); } while(im.contentsLost()); _g.drawImage(im, 0, 0, this); } @Override public void update(Graphics g) { paint(g); } public AffineTransform getTransform() { return transform; } }