annotate java/src/uk/ac/qmul/eecs/ccmi/gui/GraphToolbar.java @ 8:ea7885bd9bff tip

fixed bug : render solid line as dotted/dashed when moving the stylus from dotted/dashed to solid
author ccmi-guest
date Thu, 03 Jul 2014 16:12:20 +0100
parents d66dd5880081
children
rev   line source
fiore@0 1 /*
fiore@0 2 CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool
fiore@0 3
fiore@0 4 Copyright (C) 2002 Cay S. Horstmann (http://horstmann.com)
fiore@0 5 Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/)
fiore@0 6
fiore@0 7 This program is free software: you can redistribute it and/or modify
fiore@0 8 it under the terms of the GNU General Public License as published by
fiore@0 9 the Free Software Foundation, either version 3 of the License, or
fiore@0 10 (at your option) any later version.
fiore@0 11
fiore@0 12 This program is distributed in the hope that it will be useful,
fiore@0 13 but WITHOUT ANY WARRANTY; without even the implied warranty of
fiore@0 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
fiore@0 15 GNU General Public License for more details.
fiore@0 16
fiore@0 17 You should have received a copy of the GNU General Public License
fiore@0 18 along with this program. If not, see <http://www.gnu.org/licenses/>.
fiore@0 19 */
fiore@0 20
fiore@0 21 package uk.ac.qmul.eecs.ccmi.gui;
fiore@0 22
fiore@0 23 import java.awt.Color;
fiore@0 24 import java.awt.Component;
fiore@0 25 import java.awt.Graphics;
fiore@0 26 import java.awt.Graphics2D;
fiore@0 27 import java.awt.event.ActionEvent;
fiore@0 28 import java.awt.event.ActionListener;
fiore@0 29 import java.awt.geom.AffineTransform;
fiore@0 30 import java.awt.geom.Line2D;
fiore@0 31 import java.awt.geom.Point2D;
fiore@0 32 import java.awt.geom.Rectangle2D;
fiore@0 33 import java.util.Enumeration;
fiore@0 34 import java.util.ResourceBundle;
fiore@0 35
fiore@0 36 import javax.swing.ButtonGroup;
fiore@0 37 import javax.swing.Icon;
fiore@0 38 import javax.swing.JButton;
fiore@0 39 import javax.swing.JToggleButton;
fiore@0 40 import javax.swing.JToolBar;
fiore@0 41
fiore@0 42
fiore@0 43 /**
fiore@0 44 A Toolbar that contains node and edge prototype icons. By using the toolbar
fiore@0 45 the user can create nodes and edges in the diagram out of clonation from the prototype.
fiore@0 46 */
fiore@0 47 @SuppressWarnings("serial")
fiore@0 48 public class GraphToolbar extends JToolBar {
fiore@5 49 /**
fiore@5 50 * Constructs a tool bar with no icons.
fiore@5 51 *
fiore@5 52 * @param diagram the diagram this toolbar is related to
fiore@0 53 */
fiore@0 54 public GraphToolbar(Diagram diagram){
fiore@0 55 /* creates icon for select button */
fiore@0 56 Icon icon = new Icon(){
fiore@0 57 public int getIconHeight() { return BUTTON_SIZE; }
fiore@0 58 public int getIconWidth() { return BUTTON_SIZE; }
fiore@0 59 public void paintIcon(Component c, Graphics g,
fiore@0 60 int x, int y){
fiore@0 61 Graphics2D g2 = (Graphics2D)g;
fiore@0 62 GraphPanel.drawGrabber(g2, x + OFFSET, y + OFFSET);
fiore@0 63 GraphPanel.drawGrabber(g2, x + OFFSET, y + BUTTON_SIZE - OFFSET);
fiore@0 64 GraphPanel.drawGrabber(g2, x + BUTTON_SIZE - OFFSET, y + OFFSET);
fiore@0 65 GraphPanel.drawGrabber(g2, x + BUTTON_SIZE - OFFSET, y + BUTTON_SIZE - OFFSET);
fiore@0 66 }
fiore@0 67 };
fiore@0 68 /* add selection button */
fiore@0 69 ResourceBundle resources =
fiore@0 70 ResourceBundle.getBundle(EditorFrame.class.getName());
fiore@0 71 String text = resources.getString("grabber.text");
fiore@0 72 selectButton = new NodeButton(null,icon);
fiore@0 73 selectButton.setToolTipText(text);
fiore@0 74 nodeButtonsGroup = new ButtonGroup();
fiore@0 75 nodeButtonsGroup.add(selectButton);
fiore@0 76 add(selectButton);
fiore@0 77
fiore@0 78 /* add diagram buttons to the toolbar */
fiore@0 79 Node[] nodeTypes = diagram.getNodePrototypes();
fiore@0 80 for (int i = 0; i < nodeTypes.length; i++){
fiore@0 81 text = nodeTypes[i].getType();
fiore@0 82 add(nodeTypes[i], text );
fiore@0 83 }
fiore@0 84
fiore@0 85 /* select the select-button as default */
fiore@0 86 nodeButtonsGroup.setSelected(selectButton.getModel(), true);
fiore@0 87
fiore@0 88 /* separate node buttons from edge buttons */
fiore@0 89 addSeparator();
fiore@0 90
fiore@0 91 /* add diagram edges to the toolbar */
fiore@0 92 Edge[] edgeTypes = diagram.getEdgePrototypes();
fiore@0 93 for (int i = 0; i < edgeTypes.length; i++){
fiore@0 94 text = edgeTypes[i].getType();
fiore@0 95 add(edgeTypes[i], text );
fiore@0 96 }
fiore@0 97 }
fiore@0 98
fiore@0 99 /**
fiore@0 100 Gets the node prototype that is associated with
fiore@0 101 the currently selected button
fiore@5 102 @return a {@code Node} prototype
fiore@0 103 */
fiore@0 104 public Node getSelectedTool() {
fiore@0 105 @SuppressWarnings("rawtypes")
fiore@0 106 Enumeration elements = nodeButtonsGroup.getElements();
fiore@0 107 while (elements.hasMoreElements()) {
fiore@0 108 NodeButton b = (NodeButton)elements.nextElement();
fiore@0 109 if (b.isSelected()) {
fiore@0 110 /* switch back to the select-button */
fiore@0 111 nodeButtonsGroup.setSelected(selectButton.getModel(), true);
fiore@0 112 return b.getNode();
fiore@0 113 }
fiore@0 114 }
fiore@0 115 /* getting here means the selection button is selected */
fiore@0 116 return null;
fiore@0 117 }
fiore@0 118
fiore@0 119 /**
fiore@0 120 Adds a node to the tool bar.
fiore@0 121 @param n the node to add
fiore@5 122 @param tip the tool tip appearing when hovering on this edge button
fiore@0 123 */
fiore@5 124 public void add(final Node n, String tip){
fiore@0 125 Icon icon = new Icon(){
fiore@0 126 public int getIconHeight() { return BUTTON_SIZE; }
fiore@0 127 public int getIconWidth() { return BUTTON_SIZE; }
fiore@0 128 public void paintIcon(Component c, Graphics g,
fiore@0 129 int x, int y){
fiore@0 130 double width = n.getBounds().getWidth();
fiore@0 131 double height = n.getBounds().getHeight();
fiore@0 132 Graphics2D g2 = (Graphics2D)g;
fiore@0 133 double scaleX = (BUTTON_SIZE - OFFSET)/ width;
fiore@0 134 double scaleY = (BUTTON_SIZE - OFFSET)/ height;
fiore@0 135 double scale = Math.min(scaleX, scaleY);
fiore@0 136
fiore@0 137 AffineTransform oldTransform = g2.getTransform();
fiore@0 138 g2.translate(x, y);
fiore@0 139 g2.translate(OFFSET/2*scaleX,OFFSET/2*scaleY);
fiore@0 140 g2.scale(scale, scale);
fiore@0 141 g2.setColor(Color.black);
fiore@0 142 n.draw(g2);
fiore@0 143 g2.setTransform(oldTransform);
fiore@0 144 }
fiore@0 145 };
fiore@0 146
fiore@0 147 NodeButton button = new NodeButton(n, icon);
fiore@5 148 button.setToolTipText(tip);
fiore@0 149
fiore@0 150 add(button);
fiore@0 151 nodeButtonsGroup.add(button);
fiore@0 152 }
fiore@0 153
fiore@0 154 /**
fiore@0 155 Adds an edge to the tool bar.
fiore@5 156 @param e the edge to add
fiore@5 157 @param tip the tool tip appearing when hovering on this edge button
fiore@0 158 */
fiore@5 159 public void add(final Edge e, String tip){
fiore@0 160 Icon icon = new Icon(){
fiore@0 161 public int getIconHeight() { return BUTTON_SIZE; }
fiore@0 162 public int getIconWidth() { return BUTTON_SIZE; }
fiore@0 163 public void paintIcon(Component c, Graphics g,
fiore@0 164 int x, int y){
fiore@0 165 Graphics2D g2 = (Graphics2D)g;
fiore@0 166 /* create two points */
fiore@0 167 Point2D p = new Point2D.Double();
fiore@0 168 Point2D q = new Point2D.Double();
fiore@0 169 p.setLocation(OFFSET, OFFSET);
fiore@0 170 q.setLocation(BUTTON_SIZE - OFFSET, BUTTON_SIZE - OFFSET);
fiore@0 171
fiore@0 172 Line2D line = new Line2D.Double(p,q);
fiore@0 173 Rectangle2D bounds = new Rectangle2D.Double();
fiore@0 174 bounds.add(line.getBounds2D());
fiore@0 175
fiore@0 176 double width = bounds.getWidth();
fiore@0 177 double height = bounds.getHeight();
fiore@0 178 double scaleX = (BUTTON_SIZE - OFFSET)/ width;
fiore@0 179 double scaleY = (BUTTON_SIZE - OFFSET)/ height;
fiore@0 180 double scale = Math.min(scaleX, scaleY);
fiore@0 181
fiore@0 182 AffineTransform oldTransform = g2.getTransform();
fiore@0 183 g2.translate(x, y);
fiore@0 184 g2.scale(scale, scale);
fiore@0 185 g2.translate(Math.max((height - width) / 2, 0), Math.max((width - height) / 2, 0));
fiore@0 186
fiore@0 187 g2.setColor(Color.black);
fiore@0 188 g2.setStroke(e.getStyle().getStroke());
fiore@0 189 g2.draw(line);
fiore@0 190 g2.setTransform(oldTransform);
fiore@0 191 }
fiore@0 192 };
fiore@0 193 final JButton button = new JButton(icon);
fiore@5 194 button.setToolTipText(tip);
fiore@0 195 button.setFocusable(false);
fiore@0 196
fiore@0 197 button.addActionListener(new ActionListener(){
fiore@0 198 @Override
fiore@0 199 public void actionPerformed(ActionEvent evt) {
fiore@0 200 edgeCreatedListener.edgeCreated((Edge)e.clone());
fiore@0 201 }});
fiore@0 202 add(button);
fiore@0 203 }
fiore@0 204
fiore@5 205 /**
fiore@5 206 * Sets the {@code EdgeCreatedListener} for this toolbar. Any previous set listener
fiore@5 207 * will be overwritten.
fiore@5 208 *
fiore@5 209 * @param edgeCreatedListener the new {@code EdgeCreatedListener} for this toolbar
fiore@5 210 */
fiore@5 211 public void setEdgeCreatedListener(EdgeCreatedListener edgeCreatedListener){
fiore@0 212 this.edgeCreatedListener = edgeCreatedListener;
fiore@0 213 }
fiore@0 214
fiore@0 215 private class NodeButton extends JToggleButton{
fiore@0 216 public NodeButton(Node node, Icon icon){
fiore@0 217 super(icon);
fiore@0 218 setFocusable(false);
fiore@0 219 this.node = node;
fiore@0 220 }
fiore@0 221
fiore@0 222 public Node getNode(){
fiore@0 223 return node;
fiore@0 224 }
fiore@0 225 Node node;
fiore@0 226 }
fiore@0 227
fiore@5 228 /**
fiore@5 229 * The listener interface receiving events when the user clicks on
fiore@5 230 * an {@code Edge} button. Unlike {@code Node} buttons which are {@code JTobbleButton}
fiore@5 231 * objects to select the {@code Node} returned by {@code getSelectedTool()},
fiore@5 232 * the {@code Edge} buttons just trigger the registered listener with an immediate effect.
fiore@5 233 */
fiore@0 234 public interface EdgeCreatedListener {
fiore@5 235 /**
fiore@5 236 * Invoked when an {@code Edge} button is pressed.
fiore@5 237 * @param e the {@code Edge} related to the pressed button
fiore@5 238 */
fiore@0 239 void edgeCreated(Edge e);
fiore@0 240 }
fiore@0 241
fiore@0 242 private ButtonGroup nodeButtonsGroup;
fiore@0 243 private EdgeCreatedListener edgeCreatedListener;
fiore@0 244 private NodeButton selectButton;
fiore@0 245
fiore@0 246 private static final int BUTTON_SIZE = 30;
fiore@0 247 private static final int OFFSET = 5;
fiore@0 248 }
fiore@0 249