/* * Created on 04-Mar-2004 * Author is Michael Camacho */ package pipe.views; import pipe.constants.GUIConstants; import pipe.controllers.PetriNetController; import uk.ac.imperial.pipe.models.petrinet.Annotation; import uk.ac.imperial.pipe.models.petrinet.AnnotationImpl; import javax.swing.event.MouseInputAdapter; import java.awt.*; import java.awt.event.MouseEvent; import java.awt.geom.AffineTransform; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.List; /** * View representation of the annotation Petri net component */ @SuppressWarnings("serial") public final class AnnotationView extends Note { /** * The number of points defined that can be dragged on the annotation to increase * its size */ public static final int NO_DRAG_POINTS = 8; /** * Drag point locations on the annotation */ private final List<ResizePoint> dragPoints = new ArrayList<>(NO_DRAG_POINTS); /** * Affine transform for drawing purposes. This transform is applied * to the rectange and can be used to rotate, stretch etc the annotation */ private AffineTransform prova = new AffineTransform(); /** * Constructor * @param annotation underlying annotation model * @param controller Petri net controller for the Petri net the annotation belongs to * @param parent parent container of this view * @param handler how the annotation will handle mouse events */ public AnnotationView(Annotation annotation, PetriNetController controller, Container parent, MouseInputAdapter handler) { super(annotation, controller, parent); addChangeListener(annotation); setDragPoints(); setMouseHandler(handler); updateBounds(); } /** * Registers the handler to this view * @param handler how the annotation will handle mouse events */ private void setMouseHandler(MouseInputAdapter handler) { addMouseListener(handler); addMouseMotionListener(handler); noteText.addMouseListener(handler); noteText.addMouseMotionListener(handler); } /** * Update the (x,y) and width height boundary of this view * * Implemented because the canvas has no layout manager */ @Override public void updateBounds() { super.updateBounds(); // TOP-LEFT dragPoints.get(0).setLocation(noteRect.getMinX(), noteRect.getMinY()); // TOP-MIDDLE dragPoints.get(1).setLocation(noteRect.getCenterX(), noteRect.getMinY()); // TOP-RIGHT dragPoints.get(2).setLocation(noteRect.getMaxX(), noteRect.getMinY()); // MIDDLE-RIGHT dragPoints.get(3).setLocation(noteRect.getMaxX(), noteRect.getCenterY()); // BOTTOM-RIGHT dragPoints.get(4).setLocation(noteRect.getMaxX(), noteRect.getMaxY()); // BOTTOM-MIDDLE dragPoints.get(5).setLocation(noteRect.getCenterX(), noteRect.getMaxY()); // BOTTOM-LEFT dragPoints.get(6).setLocation(noteRect.getMinX(), noteRect.getMaxY()); // MIDDLE-LEFT dragPoints.get(7).setLocation(noteRect.getMinX(), noteRect.getCenterY()); } /** * @param x coordinate * @param y coordinate * @return true if (x, y) intersect annotation location */ @Override public boolean contains(int x, int y) { boolean pointContains = false; for (ResizePoint dragPoint : dragPoints) { pointContains |= dragPoint.contains(x - dragPoint.getX(), y - dragPoint.getY()); } return super.contains(x, y) || pointContains; } /** * Listens for changes to the annotation model * * @param annotation model to register changes to */ private void addChangeListener(Annotation annotation) { annotation.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent propertyChangeEvent) { String name = propertyChangeEvent.getPropertyName(); if (name.equals(AnnotationImpl.TEXT_CHANGE_MESSAGE)) { String text = (String) propertyChangeEvent.getNewValue(); setText(text); } else if (name.equals(Annotation.X_CHANGE_MESSAGE) || name.equals(Annotation.Y_CHANGE_MESSAGE)) { updateBounds(); } } }); } /** * Creates drag points for all the corners and half way along * each edge */ private void setDragPoints() { dragPoints.add(new ResizePoint(ResizePoint.TOP | ResizePoint.LEFT)); dragPoints.add(new ResizePoint(ResizePoint.TOP)); dragPoints.add(new ResizePoint(ResizePoint.TOP | ResizePoint.RIGHT)); dragPoints.add(new ResizePoint(ResizePoint.RIGHT)); dragPoints.add(new ResizePoint(ResizePoint.BOTTOM | ResizePoint.RIGHT)); dragPoints.add(new ResizePoint(ResizePoint.BOTTOM)); dragPoints.add(new ResizePoint(ResizePoint.BOTTOM | ResizePoint.LEFT)); dragPoints.add(new ResizePoint(ResizePoint.LEFT)); for (ResizePoint dragPoint : dragPoints) { ResizePointHandler handler = new ResizePointHandler(dragPoint); dragPoint.addMouseListener(handler); dragPoint.addMouseMotionListener(handler); add(dragPoint); } } /** * Paints the annotation and its text using the graphics * @param g graphics */ @Override public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D) g; prova = g2.getTransform(); g2.setStroke(new BasicStroke(1.0f)); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE); if (isSelected() && !ignoreSelection) { g2.setPaint(GUIConstants.SELECTION_FILL_COLOUR); g2.fill(noteRect); if (drawBorder) { g2.setPaint(GUIConstants.SELECTION_LINE_COLOUR); g2.draw(noteRect); } } else { g2.setPaint(GUIConstants.ELEMENT_FILL_COLOUR); /* */ boolean fillNote = true; if (fillNote) { g2.fill(noteRect); } if (drawBorder) { g2.setPaint(GUIConstants.ELEMENT_LINE_COLOUR); g2.draw(noteRect); } } for (ResizePoint dragPoint : dragPoints) { dragPoint.paintOnCanvas(g); } } /** * Noop * @param container to add itself to */ @Override public void addToContainer(Container container) { //Noop } /** * Noop */ @Override public void componentSpecificDelete() { //Noop } /** * Deals with resizing of the annotation by handling mouse events */ private class ResizePointHandler extends javax.swing.event.MouseInputAdapter { /** * Point to perform actions to */ private final ResizePoint point; /** * Start point of resizing */ private Point start; /** * Constructor * @param point the point to perform the resize to */ public ResizePointHandler(ResizePoint point) { this.point = point; } /** * When the mouse is pressed on the point repaint it and set the start location * @param e mouse event */ @Override public void mousePressed(MouseEvent e) { point.isPressed = true; point.repaint(); start = e.getPoint(); } /** * When the mouse is pressed on the point repaint it * @param e mouse event */ @Override public void mouseReleased(MouseEvent e) { point.isPressed = false; updateBounds(); point.repaint(); } /** * When the mouse is dragged, drag the point using the set start point when the mouse was pressed * @param e mouse event */ @Override public void mouseDragged(MouseEvent e) { point.drag(e.getX() - start.x, e.getY() - start.y); updateBounds(); point.repaint(); } } /** * Resizable point for changing the size of the annotation * These appear on the boarder of the annotation */ public class ResizePoint extends javax.swing.JComponent { /** * Top horizontal of the annotation box */ private static final int TOP = 1; /** * Bottom horizontal of the annotation box */ private static final int BOTTOM = 2; /** * Left vertical of the annotation box */ private static final int LEFT = 4; /** * Right vertical of the annotation box */ private static final int RIGHT = 8; public final int typeMask; /** * Size of the point */ private static final int SIZE = 3; /** * Graphical representation of each point */ private Rectangle shape; /** * True if the point has been pressed */ private boolean isPressed = false; /** * Constructor * @param type of point */ public ResizePoint(int type) { setOpaque(false); setBounds(-SIZE - 1, -SIZE - 1, 2 * SIZE + GUIConstants.ANNOTATION_SIZE_OFFSET + 1, 2 * SIZE + GUIConstants.ANNOTATION_SIZE_OFFSET + 1); typeMask = type; } /** * Set the x,y location of the point * @param x coordinate * @param y coordinate */ public void setLocation(double x, double y) { super.setLocation((int) (x - SIZE), (int) (y - SIZE)); } /** * Drag the point by x, y * @param x coordinate * @param y coordinate */ private void drag(int x, int y) { if ((typeMask & TOP) == TOP) { adjustTop(y); } if ((typeMask & BOTTOM) == BOTTOM) { adjustBottom(y); } if ((typeMask & LEFT) == LEFT) { adjustLeft(x); } if ((typeMask & RIGHT) == RIGHT) { adjustRight(x); } } /** * Paint the point on the canvas * @param g graphics */ public void paintOnCanvas(Graphics g) { Graphics2D g2 = (Graphics2D) g; g2.setTransform(prova); if (isSelected() && !AbstractPetriNetViewComponent.ignoreSelection) { g2.translate(this.getLocation().x, this.getLocation().y); shape = new Rectangle(0, 0, 2 * SIZE, 2 * SIZE); g2.fill(shape); g2.setStroke(new BasicStroke(1.0f)); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); if (isPressed) { g2.setPaint(GUIConstants.RESIZE_POINT_DOWN_COLOUR); } else { g2.setPaint(GUIConstants.ELEMENT_FILL_COLOUR); } g2.fill(shape); g2.setPaint(GUIConstants.ELEMENT_LINE_COLOUR); g2.draw(shape); g2.setTransform(prova); } } } }