annotate java/src/uk/ac/qmul/eecs/ccmi/gui/GraphToolbar.java @ 4:2c67ac862920

bug fix (correct haptic painting after renaming nodes and after nodes deletion with an edge with more than 2 nodes)
author Fiore Martin <fiore@eecs.qmul.ac.uk>
date Tue, 29 May 2012 15:32:19 +0100
parents 9418ab7b7f3f
children d66dd5880081
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@0 49 /**
fiore@0 50 Constructs a tool bar with no icons.
fiore@0 51 */
fiore@0 52 public GraphToolbar(Diagram diagram){
fiore@0 53 /* creates icon for select button */
fiore@0 54 Icon icon = new Icon(){
fiore@0 55 public int getIconHeight() { return BUTTON_SIZE; }
fiore@0 56 public int getIconWidth() { return BUTTON_SIZE; }
fiore@0 57 public void paintIcon(Component c, Graphics g,
fiore@0 58 int x, int y){
fiore@0 59 Graphics2D g2 = (Graphics2D)g;
fiore@0 60 GraphPanel.drawGrabber(g2, x + OFFSET, y + OFFSET);
fiore@0 61 GraphPanel.drawGrabber(g2, x + OFFSET, y + BUTTON_SIZE - OFFSET);
fiore@0 62 GraphPanel.drawGrabber(g2, x + BUTTON_SIZE - OFFSET, y + OFFSET);
fiore@0 63 GraphPanel.drawGrabber(g2, x + BUTTON_SIZE - OFFSET, y + BUTTON_SIZE - OFFSET);
fiore@0 64 }
fiore@0 65 };
fiore@0 66 /* add selection button */
fiore@0 67 ResourceBundle resources =
fiore@0 68 ResourceBundle.getBundle(EditorFrame.class.getName());
fiore@0 69 String text = resources.getString("grabber.text");
fiore@0 70 selectButton = new NodeButton(null,icon);
fiore@0 71 selectButton.setToolTipText(text);
fiore@0 72 nodeButtonsGroup = new ButtonGroup();
fiore@0 73 nodeButtonsGroup.add(selectButton);
fiore@0 74 add(selectButton);
fiore@0 75
fiore@0 76 /* add diagram buttons to the toolbar */
fiore@0 77 Node[] nodeTypes = diagram.getNodePrototypes();
fiore@0 78 for (int i = 0; i < nodeTypes.length; i++){
fiore@0 79 text = nodeTypes[i].getType();
fiore@0 80 add(nodeTypes[i], text );
fiore@0 81 }
fiore@0 82
fiore@0 83 /* select the select-button as default */
fiore@0 84 nodeButtonsGroup.setSelected(selectButton.getModel(), true);
fiore@0 85
fiore@0 86 /* separate node buttons from edge buttons */
fiore@0 87 addSeparator();
fiore@0 88
fiore@0 89 /* add diagram edges to the toolbar */
fiore@0 90 Edge[] edgeTypes = diagram.getEdgePrototypes();
fiore@0 91 for (int i = 0; i < edgeTypes.length; i++){
fiore@0 92 text = edgeTypes[i].getType();
fiore@0 93 add(edgeTypes[i], text );
fiore@0 94 }
fiore@0 95 }
fiore@0 96
fiore@0 97 /**
fiore@0 98 Gets the node prototype that is associated with
fiore@0 99 the currently selected button
fiore@0 100 @return a Node or Edge prototype
fiore@0 101 */
fiore@0 102 public Node getSelectedTool() {
fiore@0 103 @SuppressWarnings("rawtypes")
fiore@0 104 Enumeration elements = nodeButtonsGroup.getElements();
fiore@0 105 while (elements.hasMoreElements()) {
fiore@0 106 NodeButton b = (NodeButton)elements.nextElement();
fiore@0 107 if (b.isSelected()) {
fiore@0 108 /* switch back to the select-button */
fiore@0 109 nodeButtonsGroup.setSelected(selectButton.getModel(), true);
fiore@0 110 return b.getNode();
fiore@0 111 }
fiore@0 112 }
fiore@0 113 /* getting here means the selection button is selected */
fiore@0 114 return null;
fiore@0 115 }
fiore@0 116
fiore@0 117 /**
fiore@0 118 Adds a node to the tool bar.
fiore@0 119 @param n the node to add
fiore@0 120 @param tip the tool tip
fiore@0 121 */
fiore@0 122 public void add(final Node n, String text){
fiore@0 123 Icon icon = new Icon(){
fiore@0 124 public int getIconHeight() { return BUTTON_SIZE; }
fiore@0 125 public int getIconWidth() { return BUTTON_SIZE; }
fiore@0 126 public void paintIcon(Component c, Graphics g,
fiore@0 127 int x, int y){
fiore@0 128 double width = n.getBounds().getWidth();
fiore@0 129 double height = n.getBounds().getHeight();
fiore@0 130 Graphics2D g2 = (Graphics2D)g;
fiore@0 131 double scaleX = (BUTTON_SIZE - OFFSET)/ width;
fiore@0 132 double scaleY = (BUTTON_SIZE - OFFSET)/ height;
fiore@0 133 double scale = Math.min(scaleX, scaleY);
fiore@0 134
fiore@0 135 AffineTransform oldTransform = g2.getTransform();
fiore@0 136 g2.translate(x, y);
fiore@0 137 g2.translate(OFFSET/2*scaleX,OFFSET/2*scaleY);
fiore@0 138 g2.scale(scale, scale);
fiore@0 139 g2.setColor(Color.black);
fiore@0 140 n.draw(g2);
fiore@0 141 g2.setTransform(oldTransform);
fiore@0 142 }
fiore@0 143 };
fiore@0 144
fiore@0 145 NodeButton button = new NodeButton(n, icon);
fiore@0 146 button.setToolTipText(text);
fiore@0 147
fiore@0 148 add(button);
fiore@0 149 nodeButtonsGroup.add(button);
fiore@0 150 }
fiore@0 151
fiore@0 152 /**
fiore@0 153 Adds an edge to the tool bar.
fiore@0 154 @param n the node to add
fiore@0 155 @param tip the tool tip
fiore@0 156 */
fiore@0 157 public void add(final Edge e, String text){
fiore@0 158 Icon icon = new Icon(){
fiore@0 159 public int getIconHeight() { return BUTTON_SIZE; }
fiore@0 160 public int getIconWidth() { return BUTTON_SIZE; }
fiore@0 161 public void paintIcon(Component c, Graphics g,
fiore@0 162 int x, int y){
fiore@0 163 Graphics2D g2 = (Graphics2D)g;
fiore@0 164 /* create two points */
fiore@0 165 Point2D p = new Point2D.Double();
fiore@0 166 Point2D q = new Point2D.Double();
fiore@0 167 p.setLocation(OFFSET, OFFSET);
fiore@0 168 q.setLocation(BUTTON_SIZE - OFFSET, BUTTON_SIZE - OFFSET);
fiore@0 169
fiore@0 170 Line2D line = new Line2D.Double(p,q);
fiore@0 171 Rectangle2D bounds = new Rectangle2D.Double();
fiore@0 172 bounds.add(line.getBounds2D());
fiore@0 173
fiore@0 174 double width = bounds.getWidth();
fiore@0 175 double height = bounds.getHeight();
fiore@0 176 double scaleX = (BUTTON_SIZE - OFFSET)/ width;
fiore@0 177 double scaleY = (BUTTON_SIZE - OFFSET)/ height;
fiore@0 178 double scale = Math.min(scaleX, scaleY);
fiore@0 179
fiore@0 180 AffineTransform oldTransform = g2.getTransform();
fiore@0 181 g2.translate(x, y);
fiore@0 182 g2.scale(scale, scale);
fiore@0 183 g2.translate(Math.max((height - width) / 2, 0), Math.max((width - height) / 2, 0));
fiore@0 184
fiore@0 185 g2.setColor(Color.black);
fiore@0 186 g2.setStroke(e.getStyle().getStroke());
fiore@0 187 g2.draw(line);
fiore@0 188 g2.setTransform(oldTransform);
fiore@0 189 }
fiore@0 190 };
fiore@0 191 final JButton button = new JButton(icon);
fiore@0 192 button.setToolTipText(text);
fiore@0 193 button.setFocusable(false);
fiore@0 194
fiore@0 195 button.addActionListener(new ActionListener(){
fiore@0 196 @Override
fiore@0 197 public void actionPerformed(ActionEvent evt) {
fiore@0 198 edgeCreatedListener.edgeCreated((Edge)e.clone());
fiore@0 199 }});
fiore@0 200 add(button);
fiore@0 201 }
fiore@0 202
fiore@0 203 public void addEdgeCreatedListener(EdgeCreatedListener edgeCreatedListener){
fiore@0 204 this.edgeCreatedListener = edgeCreatedListener;
fiore@0 205 }
fiore@0 206
fiore@0 207 private class NodeButton extends JToggleButton{
fiore@0 208 public NodeButton(Node node, Icon icon){
fiore@0 209 super(icon);
fiore@0 210 setFocusable(false);
fiore@0 211 this.node = node;
fiore@0 212 }
fiore@0 213
fiore@0 214 public Node getNode(){
fiore@0 215 return node;
fiore@0 216 }
fiore@0 217 Node node;
fiore@0 218 }
fiore@0 219
fiore@0 220 public interface EdgeCreatedListener {
fiore@0 221 void edgeCreated(Edge e);
fiore@0 222 }
fiore@0 223
fiore@0 224 private ButtonGroup nodeButtonsGroup;
fiore@0 225 private EdgeCreatedListener edgeCreatedListener;
fiore@0 226 private NodeButton selectButton;
fiore@0 227
fiore@0 228 private static final int BUTTON_SIZE = 30;
fiore@0 229 private static final int OFFSET = 5;
fiore@0 230 }
fiore@0 231