/* * * MouseDrawingUI.java version 0.1 * * Copyright (C) 2008 Piet Blok. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Created on 3 aug 2008 */ package org.pbjar.jxlayer.test; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.MouseEvent; import java.awt.geom.AffineTransform; import java.awt.geom.Line2D; import java.awt.geom.NoninvertibleTransformException; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.List; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JColorChooser; import javax.swing.JComponent; import javax.swing.SwingUtilities; import org.jdesktop.jxlayer.JXLayer; /** * TODO Program description * * @author Piet Blok */ public class MouseDrawingUI extends GeneralLayerUI { private static class ColoredLine { public final List path = new ArrayList(); public final Color color; public ColoredLine(Color color) { this.color = color; } public void addPoint(Point2D point) { path.add(point); } } private class MyState extends StateObject { public Color lineColor = Color.RED; public ColoredLine coloredLine = null; public List lineList = new ArrayList(); public Dimension preferred = null; public Rectangle innerArea = new Rectangle(); public Rectangle newInnerArea = new Rectangle(); public AffineTransform transform = new AffineTransform(); public AffineTransform inverseTransform = new AffineTransform(); private final JXLayer layer; private double scale = 1.0; public MyState(JXLayer layer) { this.layer = layer; } public void addPoint(Point2D point) { if (coloredLine == null) { coloredLine = new ColoredLine(lineColor); lineList.add(coloredLine); } updateSize(); coloredLine.addPoint(inverseTransform.transform(point, point)); } public void clear() { lineList.clear(); } public Color getLineColor() { return lineColor; } public void setLineColor(Color color) { this.lineColor = color; } public void terminateLine() { coloredLine = null; } public void updateSize() { /* * This is for future use and meant to ensure that the drawing * scales with the scaling of the underlying component. But it * interferes a bit with the current testing on other types of * components. */ // updateSizeImpl(); } protected void updateSizeImpl() { boolean dirty = false; SwingUtilities.calculateInnerArea(layer, newInnerArea); if (!newInnerArea.equals(innerArea)) { innerArea.setRect(newInnerArea); dirty = true; } Dimension newPreferred = layer.getPreferredSize(); if (!newPreferred.equals(preferred)) { preferred = newPreferred; dirty = true; } if (dirty) { transform.setToIdentity(); scale = Math.min(innerArea.getWidth() / preferred.getWidth(), innerArea.getHeight() / preferred.getHeight()); transform.scale(scale, scale); transform.translate(getOffset(scale, preferred.getWidth(), innerArea.getCenterX()), getOffset(scale, preferred .getHeight(), innerArea.getCenterY())); try { inverseTransform = transform.createInverse(); } catch (NoninvertibleTransformException e) { e.printStackTrace(); } } } private double getOffset(double scale, double imageSize, double center) { return (center - (imageSize * scale / 2.0)) / scale; } } public List getActions(final JXLayer layer) { ArrayList actionList = new ArrayList(); actionList.addAll(super.getActions(layer)); /* * Clear */ actionList.add(new AbstractAction("Clear") { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent event) { ((MyState) MouseDrawingUI.this.getStateObject(layer)).clear(); setDirty(true); } }); /* * Set line color */ actionList.add(new AbstractAction("Set line color") { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent event) { MyState state = (MyState) MouseDrawingUI.this .getStateObject(layer); Color color = state.getLineColor(); color = JColorChooser.showDialog(layer, "Choose a new line color", color); if (color != null) { state.setLineColor(color); } } }); return actionList; } @Override protected GeneralLayerUI.StateObject createStateObject( JXLayer layer) { return new MyState(layer); } protected void paintLayer(Graphics2D g2, JXLayer layer) { super.paintLayer(g2, layer); MyState state = (MyState) getStateObject(layer); state.updateSize(); g2.transform(state.transform); g2.setStroke(new BasicStroke(4f / (float) state.scale)); Line2D line = new Line2D.Double(); for (ColoredLine coloredLine : state.lineList) { g2.setColor(coloredLine.color); Point2D oldPoint = null; for (Point2D point : coloredLine.path) { if (oldPoint != null) { line.setLine(oldPoint, point); g2.draw(line); } oldPoint = point; } } } @Override protected void processMouseEvent(MouseEvent e, JXLayer layer) { if (e.getID() == MouseEvent.MOUSE_RELEASED) { MyState state = (MyState) getStateObject(layer); state.terminateLine(); setDirty(true); } } @Override protected void processMouseMotionEvent(MouseEvent e, JXLayer layer) { if (e.getID() == MouseEvent.MOUSE_DRAGGED) { MyState state = (MyState) getStateObject(layer); state.addPoint(SwingUtilities.convertPoint(e.getComponent(), e .getPoint(), layer)); setDirty(true); } } }