/******************************************************************************** * * * (c) Copyright 2010 Verizon Communications USA and The Open University UK * * * * This software is freely distributed in accordance with * * the GNU Lesser General Public (LGPL) license, version 3 or later * * as published by the Free Software Foundation. * * For details see LGPL: http://www.fsf.org/licensing/licenses/lgpl.html * * and GPL: http://www.fsf.org/licensing/licenses/gpl-3.0.html * * * * This software is provided by the copyright holders and contributors "as is" * * and any express or implied warranties, including, but not limited to, the * * implied warranties of merchantability and fitness for a particular purpose * * are disclaimed. In no event shall the copyright owner or contributors be * * liable for any direct, indirect, incidental, special, exemplary, or * * consequential damages (including, but not limited to, procurement of * * substitute goods or services; loss of use, data, or profits; or business * * interruption) however caused and on any theory of liability, whether in * * contract, strict liability, or tort (including negligence or otherwise) * * arising in any way out of the use of this software, even if advised of the * * possibility of such damage. * * * ********************************************************************************/ package com.compendium.ui.plaf; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.util.Vector; import javax.swing.JComponent; import javax.swing.RepaintManager; import javax.swing.SwingUtilities; import javax.swing.plaf.ComponentUI; import com.compendium.ui.UIScribblePad; import com.compendium.ui.UIShape; import com.compendium.ui.UIUtilities; import com.compendium.ui.UIViewPane; import com.compendium.ui.edits.DrawEdit; /** * The UI class for the UIScribblePad Component * THE CLASS IS STILL UNDER DEVELOPMENT * * @author Michelle Bachler */ public class ScribblePadUI extends ComponentUI implements MouseListener, MouseMotionListener, KeyListener { /** The UIScribblePad instance associated with this UI.*/ protected UIScribblePad oScribblePad; /** The UIViewPane instance associated with this UI.*/ protected UIViewPane oViewPane; /** The MouseListener used by this UI.*/ private MouseListener oMouseListener; /** The MouseMotionListener used by this UI.*/ private MouseMotionListener oMouseMotionListener; /** The KeyListener use by this UI.*/ private KeyListener oKeyListener; /** The data of the pencil scribble drawn so far.*/ private Vector data = new Vector(51); /** The data of the shapes scribble drawn so far.*/ private Vector shapes = new Vector(51); private Vector lastScribble = null; /** The mouse pressed x position of the mouse pointer.*/ private int start_x; /** The mouse Pressed y position of the mouse pointer.*/ private int start_y; /** The last x position of the mouse pointer.*/ private int last_x; /** The last y position of the mouse pointer.*/ private int last_y; /** Indicates if the mouse is currently being dragged.*/ private boolean bDragging = false; /** The color to draw the scribble.*/ private Color current_colour = Color.black; // Store the current color. /** The tool to use to draw the scribble.*/ private int current_tool = UIScribblePad.PENCIL; /** The thickness of the lines being drawn.*/ private int current_thickness = 1; /** * Constructor. * @param c, the component this is the ui. */ public ScribblePadUI(JComponent c) { super(); oScribblePad = (UIScribblePad)c; oViewPane = oScribblePad.getViewPane(); } /** * Create a new ScribblePadUI instance. * @param c, the component this is the ui to install for. */ public static ComponentUI createUI(JComponent c) { ScribblePadUI scribbleui = new ScribblePadUI(c); return scribbleui; } /** * Run any install instructions for installing this UI. * @param c, the component this is the ui for. */ public void installUI(JComponent c) { super.installUI(c); oScribblePad = (UIScribblePad)c; installListeners(c); } /** * Install any Listener classes required by this UI. * @param c, the component to install the listeners for. */ protected void installListeners(JComponent c) { if ( (oMouseListener = createMouseListener( c )) != null ) { c.addMouseListener( oMouseListener ); } if ( (oMouseMotionListener = createMouseMotionListener( c )) != null ) { c.addMouseMotionListener( oMouseMotionListener ); } if ( (oKeyListener = createKeyListener( c )) != null ) { c.addKeyListener( oKeyListener ); } } /** * Just returns this class as the MouseListener. * @param c, the component to create the MouseLisener for. * @return MouseListener, the listener to use. */ protected MouseListener createMouseListener( JComponent c ) { return this; } /** * Just returns this class as the MouseMotionListener. * @param c, the component to create the MouseMotionLisener for. * @return MouseMotionListener, the listener to use. */ protected MouseMotionListener createMouseMotionListener( JComponent c ) { return this; } /** * Just returns this class as the KeyListener. * @param c, the component to create the KeyLisener for. * @return KeyListener, the listener to use. */ protected KeyListener createKeyListener(JComponent c) { return this; } /** * Run any uninstall instructions for uninstalling this UI. * @param c, the component this is the ui to uninstall for. */ public void uninstallUI(JComponent c) { uninstallListeners(c); oScribblePad = null; super.uninstallUI(c); } /** * Uninstall any Listener classes used by this UI. * @param c, the component to uninstall the listeners for. */ protected void uninstallListeners(JComponent c) { if ( oMouseMotionListener!= null ) { c.removeMouseMotionListener( oMouseMotionListener ); } if ( oMouseListener!= null ) { c.removeMouseListener( oMouseListener ); } oMouseListener = null; oMouseMotionListener = null; } /** * Undo the last paint operation - if a pencil scribble. */ public void undo(Vector vtShapes) { UIShape test = (UIShape)vtShapes.elementAt(0); // SHOULD BE THE LAST THING ADDED SO TEST THIS FIRST Vector last = (Vector)data.lastElement(); UIShape shape = (UIShape)last.elementAt(0); if (shape.equals(test)) { data.removeElement(last); } else { int count = data.size(); for (int i=0; i<count; i++) { Vector next = (Vector)data.elementAt(i); shape = (UIShape)next.elementAt(0); if (shape.equals(test)) { data.removeElement(next); break; } } } oScribblePad.repaint(); } /** * Redo the last undo - if a pencil scribble. */ public void redo(Vector vtShapes) { data.addElement(vtShapes); oScribblePad.repaint(); } /** * Undo the last paint operation - if other tool. */ public void undo(UIShape shape) { shapes.removeElement(shape); oScribblePad.repaint(); } /** * Redo the last undo - if other tool. */ public void redo(UIShape shape) { shapes.addElement(shape); oScribblePad.repaint(); } /** * Set the pencil data. * @param data, the pencil data. */ public void setPencilData(Vector data) { this.data = data; } /** * Get the pencil data. * @param Vector, the pencil data. */ public Vector getPencilData() { return this.data; } /** * Set the shapes data. * @param data, the shapes data. */ public void setShapesData(Vector data) { this.shapes = data; } /** * Get the shapes data. * @return Vector, the shapes data. */ public Vector getShapesData() { return this.shapes; } /** * Set the currently selected tool. * @param tool, the tool to use. */ public void setTool(int tool) { current_tool = tool; } /** * Set the currently selected colour. * @param colour, the colour to draw. */ public void setColour(Color colour) { this.current_colour = colour; } /** * Set the current line thickness. * @param thickness, the thickness to draw lines. */ public void setThickness(int thickness) { this.current_thickness = thickness; } /** * Draws the scribble line / or shapes on the given graphics context. * * @param g, the Graphics object for this pain method to use. * @param c, the component to paint. */ public void paint(Graphics g, JComponent c) { double scale = oViewPane.getScale(); Graphics2D g2d = (Graphics2D)g; // DRAW POINTS int count = data.size(); Point prev = null; Point current = null; for (int i=0; i<count; i++) { Vector next = (Vector)data.elementAt(i); prev = null; int jcount = next.size(); for (int j=0; j<jcount; j++) { UIShape shape = (UIShape)next.elementAt(j); g.setColor(shape.getColour()); int thickness = shape.getThickness(); //g2d.setStroke(new BasicStroke(thickness)); Point thicknessScaled = UIUtilities.transformPoint(thickness, thickness, scale); g2d.setStroke(new BasicStroke(thicknessScaled.x)); if (j==0) prev = UIUtilities.transformPoint(shape.getX(), shape.getY(), scale); //prev = new Point(shape.getX(), shape.getY()); else { current = UIUtilities.transformPoint(shape.getX(), shape.getY(), scale); //current = new Point(shape.getX(), shape.getY()); g.drawLine(prev.x, prev.y, current.x, current.y); prev = current; } } } // DRAW SHAPES int jcount = shapes.size(); for (int j=0; j<jcount; j++) { UIShape shape = (UIShape)shapes.elementAt(j); int type = shape.getType(); g.setColor(shape.getColour()); int thickness = shape.getThickness(); //g2d.setStroke(new BasicStroke(thickness)); Point thicknessScaled = UIUtilities.transformPoint(thickness, thickness, scale); g2d.setStroke(new BasicStroke(thicknessScaled.x)); Point pos = UIUtilities.transformPoint(shape.getX(), shape.getY(), scale); Point width = UIUtilities.transformPoint(shape.getWidth(), shape.getWidth(), scale); Point height = UIUtilities.transformPoint(shape.getHeight(), shape.getHeight(), scale); if (type == UIScribblePad.OVAL) { g.drawOval(pos.x, pos.y, width.x, height.x); //g.drawOval(shape.getX(), shape.getY(), shape.getWidth(), shape.getHeight()); } else if (type == UIScribblePad.RECTANGLE) { g.drawRect(pos.x, pos.y, width.x, height.x); //g.drawRect(shape.getX(), shape.getY(), shape.getWidth(), shape.getHeight()); } else if (type == UIScribblePad.LINE) { g.drawLine(pos.x, pos.y, width.x, height.x); //g.drawLine(shape.getX(), shape.getY(), shape.getWidth(), shape.getHeight()); } } } /** * Clear all the data elements used to draw the scribble. */ public void clear() { data.removeAllElements(); shapes.removeAllElements(); } // EVENT HANDLERS /** * Handles the initiation of drag and drop events. * @param evt, the MouseEvent generated. */ public void mousePressed(MouseEvent evt) { /* if (current_tool == UIScribblePad.NO_TOOL) { UINode node = oViewPane.getUI().isMouseOnANode(evt); if (node != null) { ((NodeUI)node.getUI()).mousePressed(evt); } else { UILink link = oViewPane.getUI().isMouseOnALink(evt); if (link != null) { ((LinkUI)link.getUI()).mousePressed(evt); } else { ((ViewPaneUI)oViewPane.getUI()).mousePressed(evt); } } return; }*/ if (oViewPane.isScribblePadBack()) { ((ViewPaneUI)oViewPane.getUI()).mousePressed(evt); return; } last_x = -1; last_y = -1; // start dragging if left or right mouse button is pressed boolean isLeftMouse = SwingUtilities.isLeftMouseButton(evt); if (isLeftMouse) { int x = evt.getX(); int y = evt.getY(); start_x = x; start_y = y; last_x = x; last_y = y; bDragging = true; if (current_tool == UIScribblePad.PENCIL) { UIShape shape = new UIShape(x, y, 0, 0, current_tool, current_colour, current_thickness); lastScribble = new Vector(51); lastScribble.addElement(shape); } } evt.consume(); } /** * Handles mouse click operations. * @param evt, the MouseEvent generated. */ public void mouseClicked(MouseEvent evt) { /* if (current_tool == UIScribblePad.NO_TOOL) { UINode node = oViewPane.getUI().isMouseOnANode(evt); if (node != null) { ((NodeUI)node.getUI()).mouseClicked(evt); } else { UILink link = oViewPane.getUI().isMouseOnALink(evt); if (link != null) { ((LinkUI)link.getUI()).mouseClicked(evt); } else { ((ViewPaneUI)oViewPane.getUI()).mouseClicked(evt); } } return; } */ if (oViewPane.isScribblePadBack()) { ((ViewPaneUI)oViewPane.getUI()).mouseClicked(evt); return; } else { evt.consume(); } } /** * Handles drag and drop finish operations. * @param evt, the MouseEvent generated. */ public void mouseReleased(MouseEvent evt) { /* if (current_tool == UIScribblePad.NO_TOOL) { UINode node = oViewPane.getUI().isMouseOnANode(evt); if (node != null) { ((NodeUI)node.getUI()).mouseReleased(evt); } else { UILink link = oViewPane.getUI().isMouseOnALink(evt); if (link != null) { ((LinkUI)link.getUI()).mouseReleased(evt); } else { ((ViewPaneUI)oViewPane.getUI()).mouseReleased(evt); } } return; }*/ if (oViewPane.isScribblePadBack()) { ((ViewPaneUI)oViewPane.getUI()).mouseReleased(evt); return; } boolean isLeftMouse = SwingUtilities.isLeftMouseButton(evt); if (isLeftMouse && bDragging) { bDragging = false; int stop_x = evt.getX(); int stop_y = evt.getY(); if (current_tool == UIScribblePad.PENCIL) { UIShape shape = new UIShape(stop_x, stop_y, 0, 0, current_tool, current_colour, current_thickness); lastScribble.addElement(shape); data.addElement((Vector)lastScribble.clone()); DrawEdit edit = new DrawEdit(oScribblePad, (Vector)lastScribble.clone()); lastScribble.removeAllElements(); oViewPane.getViewFrame().getUndoListener().postEdit(edit); oViewPane.getViewFrame().refreshUndoRedo(); } else if (current_tool == UIScribblePad.OVAL || current_tool == UIScribblePad.RECTANGLE) { int width = 0; int height = 0; int draw_x = 0; int draw_y = 0; if (start_x > stop_x) { width = start_x-stop_x; draw_x = stop_x; } else { width = stop_x-start_x; draw_x = start_x; } if (start_y > stop_y) { height = start_y-stop_y; draw_y = stop_y; } else { height = stop_y-start_y; draw_y = start_y; } UIShape shape = new UIShape(draw_x, draw_y, width, height, current_tool, current_colour, current_thickness); shapes.addElement(shape); DrawEdit edit = new DrawEdit(oScribblePad, shape); oViewPane.getViewFrame().getUndoListener().postEdit(edit); oViewPane.getViewFrame().refreshUndoRedo(); } else if (current_tool == UIScribblePad.LINE) { UIShape shape = new UIShape(start_x, start_y, stop_x, stop_y, current_tool, current_colour, current_thickness); shapes.addElement(shape); DrawEdit edit = new DrawEdit(oScribblePad, shape); oViewPane.getViewFrame().getUndoListener().postEdit(edit); oViewPane.getViewFrame().refreshUndoRedo(); } } last_x = 0; last_y = 0; evt.consume(); } /** * Invoked when a mouse is dragged (pressed and moved). * @param evt, the MouseEvent generated. */ public void mouseDragged(MouseEvent evt) { /*if (current_tool == UIScribblePad.NO_TOOL) { UINode node = oViewPane.getUI().isMouseOnANode(evt); if (node != null) { ((NodeUI)node.getUI()).mouseDragged(evt); } else { UILink link = oViewPane.getUI().isMouseOnALink(evt); if (link != null) { ((LinkUI)link.getUI()).mouseDragged(evt); } else { ((ViewPaneUI)oViewPane.getUI()).mouseDragged(evt); } } return; }*/ if (oViewPane.isScribblePadBack()) { ((ViewPaneUI)oViewPane.getUI()).mouseDragged(evt); return; } boolean isLeftMouse = SwingUtilities.isLeftMouseButton(evt); if (isLeftMouse && bDragging) { Graphics g = oScribblePad.getGraphics(); Graphics2D g2d = (Graphics2D)g; g2d.setStroke(new BasicStroke(current_thickness)); g.setColor(current_colour); int x = evt.getX(); int y = evt.getY(); if (current_tool == UIScribblePad.PENCIL && last_x != -1 && last_y != -1) { g.drawLine(last_x, last_y, x, y); UIShape shape = new UIShape(x, y, 0, 0, current_tool, current_colour, current_thickness); lastScribble.addElement(shape); } else if (current_tool == UIScribblePad.OVAL || current_tool == UIScribblePad.RECTANGLE) { if (oScribblePad != null) { RepaintManager mgr = RepaintManager.currentManager(oScribblePad); mgr.addDirtyRegion(oScribblePad,0,0, oScribblePad.getWidth(),oScribblePad.getHeight()); mgr.paintDirtyRegions(); } int width = 0; int height = 0; int draw_x = 0; int draw_y = 0; if (start_x > x) { width = start_x-x; draw_x = x; } else { width = x-start_x; draw_x = start_x; } if (start_y > y) { height = start_y-y; draw_y = y; } else { height = y-start_y; draw_y = start_y; } if (current_tool == UIScribblePad.OVAL) { g.drawOval(draw_x, draw_y, width, height); } else if (current_tool == UIScribblePad.RECTANGLE) { g.drawRect(draw_x, draw_y, width, height); } } else if (current_tool == UIScribblePad.LINE) { if (oScribblePad != null) { RepaintManager mgr = RepaintManager.currentManager(oScribblePad); mgr.addDirtyRegion(oScribblePad,0,0, oScribblePad.getWidth(),oScribblePad.getHeight()); mgr.paintDirtyRegions(); } g.drawLine(start_x, start_y, x, y); } last_x = x; last_y = y; } evt.consume(); } /** * Invoked when a mouse is moved in a component. * Does nothing. * @param evt, the MouseEvent generated. */ public void mouseMoved(MouseEvent evt) { /*if (current_tool == UIScribblePad.NO_TOOL) { UINode node = oViewPane.getUI().isMouseOnANode(evt); if (node != null) { ((NodeUI)node.getUI()).mouseMoved(evt); } else { UILink link = oViewPane.getUI().isMouseOnALink(evt); if (link != null) { ((LinkUI)link.getUI()).mouseMoved(evt); } else { ((ViewPaneUI)oViewPane.getUI()).mouseMoved(evt); } } return; }*/ if (oViewPane.isScribblePadBack()) { ((ViewPaneUI)oViewPane.getUI()).mouseMoved(evt); return; } else { evt.consume(); } } /** * Invoked when a mouse is entered. * Does nothing. * @param evt, the MouseEvent generated. */ public void mouseEntered(MouseEvent evt) { /*if (current_tool == UIScribblePad.NO_TOOL) { UINode node = oViewPane.getUI().isMouseOnANode(evt); if (node != null) { ((NodeUI)node.getUI()).mouseEntered(evt); } else { UILink link = oViewPane.getUI().isMouseOnALink(evt); if (link != null) { ((LinkUI)link.getUI()).mouseEntered(evt); } else { ((ViewPaneUI)oViewPane.getUI()).mouseEntered(evt); } } return; }*/ if (oViewPane.isScribblePadBack()) { ((ViewPaneUI)oViewPane.getUI()).mouseEntered(evt); return; } else { evt.consume(); } } /** * Invoked when a mouse is exited. * Does nothing. * @param evt, the MouseEvent generated. */ public void mouseExited(MouseEvent evt) { /* if (current_tool == UIScribblePad.NO_TOOL) { UINode node = oViewPane.getUI().isMouseOnANode(evt); if (node != null) { ((NodeUI)node.getUI()).mouseExited(evt); } else { UILink link = oViewPane.getUI().isMouseOnALink(evt); if (link != null) { ((LinkUI)link.getUI()).mouseExited(evt); } else { ((ViewPaneUI)oViewPane.getUI()).mouseExited(evt); } } return; }*/ if (oViewPane.isScribblePadBack()) { ((ViewPaneUI)oViewPane.getUI()).mouseExited(evt); return; } else { evt.consume(); } } /** * Invoked when a key is pressed in a component. * Does nothing. * @param evt, the MouseEvent generated. */ public void keyPressed(KeyEvent evt) { //if (oViewPane.isScribblePadBack()) { if (current_tool == UIScribblePad.NO_TOOL) { ((ViewPaneUI)oViewPane.getUI()).keyPressed(evt); } else { evt.consume(); } } /** * Invoked when a key is released in a component. * Does nothing. * @param evt, the MouseEvent generated. */ public void keyReleased(KeyEvent evt) { //if (oViewPane.isScribblePadBack()) { if (current_tool == UIScribblePad.NO_TOOL) { ((ViewPaneUI)oViewPane.getUI()).keyReleased(evt); } else { evt.consume(); } } /** * Invoked when a key is typed in a component. * Does nothing. * @param evt, the MouseEvent generated. */ public void keyTyped(KeyEvent evt) { //if (oViewPane.isScribblePadBack()) { if (current_tool == UIScribblePad.NO_TOOL) { ((ViewPaneUI)oViewPane.getUI()).keyTyped(evt); } else { evt.consume(); } } }