view java/src/uk/ac/qmul/eecs/ccmi/gui/GraphToolbar.java @ 5:d66dd5880081

Added support for Falcon Haptic device and Tablet/Mouse as haptic device
author Fiore Martin <fiore@eecs.qmul.ac.uk>
date Tue, 10 Jul 2012 22:39:37 +0100
parents 9418ab7b7f3f
children
line wrap: on
line source
/*  
 CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool
	  
 Copyright (C) 2002 Cay S. Horstmann (http://horstmann.com)
 Copyright (C) 2011  Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/)

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package uk.ac.qmul.eecs.ccmi.gui;

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.Enumeration;
import java.util.ResourceBundle;

import javax.swing.ButtonGroup;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;


/**
   A Toolbar that contains node and edge prototype icons. By using the toolbar 
   the user can create nodes and edges in the diagram out of clonation from the prototype.
*/
@SuppressWarnings("serial")
public class GraphToolbar extends JToolBar {
  /**
   * Constructs a tool bar with no icons.
   * 
   * @param diagram the diagram this toolbar is related to 
   */
   public GraphToolbar(Diagram diagram){
      /* creates icon for select button */
      Icon icon = new Icon(){
            public int getIconHeight() { return BUTTON_SIZE; }
            public int getIconWidth() { return BUTTON_SIZE; }
            public void paintIcon(Component c, Graphics g,
               int x, int y){
               Graphics2D g2 = (Graphics2D)g;
               GraphPanel.drawGrabber(g2, x + OFFSET, y + OFFSET);
               GraphPanel.drawGrabber(g2, x + OFFSET, y + BUTTON_SIZE - OFFSET);
               GraphPanel.drawGrabber(g2, x + BUTTON_SIZE - OFFSET, y + OFFSET);
               GraphPanel.drawGrabber(g2, x + BUTTON_SIZE - OFFSET, y + BUTTON_SIZE - OFFSET);
            }
         };
      /* add selection button */
      ResourceBundle resources = 
         ResourceBundle.getBundle(EditorFrame.class.getName());
      String text = resources.getString("grabber.text");
      selectButton = new NodeButton(null,icon);
      selectButton.setToolTipText(text);
      nodeButtonsGroup = new ButtonGroup();
      nodeButtonsGroup.add(selectButton);
      add(selectButton);

      /* add diagram buttons to the toolbar */
      Node[] nodeTypes = diagram.getNodePrototypes();
      for (int i = 0; i < nodeTypes.length; i++){
         text = nodeTypes[i].getType();
         add(nodeTypes[i], text );
      }
      
      /* select the select-button as default */
      nodeButtonsGroup.setSelected(selectButton.getModel(), true);

      /* separate node buttons from edge buttons */ 
      addSeparator();
      
      /* add diagram edges to the toolbar */
      Edge[] edgeTypes = diagram.getEdgePrototypes();
      for (int i = 0; i < edgeTypes.length; i++){
         text = edgeTypes[i].getType();
         add(edgeTypes[i], text );
      }          
   }

   /**
      Gets the node prototype that is associated with
      the currently selected button
      @return a {@code Node} prototype
   */
   public Node getSelectedTool() {
	   @SuppressWarnings("rawtypes")
	   Enumeration elements = nodeButtonsGroup.getElements();
	   while (elements.hasMoreElements()) {
		   NodeButton b = (NodeButton)elements.nextElement();
		   if (b.isSelected()) {
			   /* switch back to the select-button */
			   nodeButtonsGroup.setSelected(selectButton.getModel(), true);
			   return b.getNode();
		   }
	   }
	   /* getting here means the selection button is selected */
	   return null;
   }

   /**
      Adds a node to the tool bar.
      @param n the node to add
      @param tip the tool tip appearing when hovering on this edge button 
   */
   public void add(final Node n, String tip){
      Icon icon = new Icon(){
            public int getIconHeight() { return BUTTON_SIZE; }
            public int getIconWidth() { return BUTTON_SIZE; }
            public void paintIcon(Component c, Graphics g,
                  int x, int y){
               double width = n.getBounds().getWidth();
               double height = n.getBounds().getHeight();
               Graphics2D g2 = (Graphics2D)g;
               double scaleX = (BUTTON_SIZE - OFFSET)/ width;
               double scaleY = (BUTTON_SIZE - OFFSET)/ height;
               double scale = Math.min(scaleX, scaleY);

               AffineTransform oldTransform = g2.getTransform();
               g2.translate(x, y);
               g2.translate(OFFSET/2*scaleX,OFFSET/2*scaleY);
               g2.scale(scale, scale);
               g2.setColor(Color.black);
               n.draw(g2);
               g2.setTransform(oldTransform);
            }
         };

      NodeButton button = new NodeButton(n, icon);
      button.setToolTipText(tip);
      
      add(button);
      nodeButtonsGroup.add(button);
   }
   
   /**
      Adds an edge to the tool bar.
      @param e the edge to add
      @param tip the tool tip appearing when hovering on this edge button 
   */
   public void add(final Edge e, String tip){
       Icon icon = new Icon(){
            public int getIconHeight() { return BUTTON_SIZE; }
            public int getIconWidth() { return BUTTON_SIZE; }
            public void paintIcon(Component c, Graphics g,
               int x, int y){
               Graphics2D g2 = (Graphics2D)g;
               /* create two points */
               Point2D p = new Point2D.Double();
               Point2D q = new Point2D.Double();
               p.setLocation(OFFSET, OFFSET);
               q.setLocation(BUTTON_SIZE - OFFSET, BUTTON_SIZE - OFFSET);
               
               Line2D line = new Line2D.Double(p,q);
               Rectangle2D bounds = new Rectangle2D.Double();
               bounds.add(line.getBounds2D());
               
               double width = bounds.getWidth();
               double height = bounds.getHeight();
               double scaleX = (BUTTON_SIZE - OFFSET)/ width;
               double scaleY = (BUTTON_SIZE - OFFSET)/ height;
               double scale = Math.min(scaleX, scaleY);

               AffineTransform oldTransform = g2.getTransform();
               g2.translate(x, y);
               g2.scale(scale, scale);
               g2.translate(Math.max((height - width) / 2, 0), Math.max((width - height) / 2, 0));
                              
               g2.setColor(Color.black);
               g2.setStroke(e.getStyle().getStroke());
               g2.draw(line);
               g2.setTransform(oldTransform);
            }
         };
      final JButton button = new JButton(icon);               
      button.setToolTipText(tip);
      button.setFocusable(false);
      
      button.addActionListener(new ActionListener(){
		@Override
		public void actionPerformed(ActionEvent evt) {
			edgeCreatedListener.edgeCreated((Edge)e.clone());
		}});
      add(button);
   }
   
   /**
    * Sets the {@code EdgeCreatedListener} for this toolbar. Any previous set listener
    * will be overwritten. 
    * 
    * @param edgeCreatedListener the new {@code EdgeCreatedListener} for this toolbar  
    */
   public void setEdgeCreatedListener(EdgeCreatedListener edgeCreatedListener){
	   this.edgeCreatedListener = edgeCreatedListener;
   }
   
   private class NodeButton extends JToggleButton{
	   public NodeButton(Node node, Icon icon){
		   super(icon);
		   setFocusable(false);
		   this.node = node;
	   }
	   
	   public Node getNode(){
		   return node;
	   }
	   Node node;
   }
   
   /**
    * The listener interface receiving events when the user clicks on 
    * an {@code Edge} button. Unlike {@code Node} buttons which are {@code JTobbleButton}
    * objects to select the {@code Node} returned by {@code getSelectedTool()}, 
    * the {@code Edge} buttons just trigger the registered listener with an immediate effect.
    */
   public interface EdgeCreatedListener {
	   /**
	    * Invoked when an {@code Edge} button is pressed.
	    * @param e the {@code Edge} related to the pressed button
	    */
		void edgeCreated(Edge e);
   }
   
   private ButtonGroup nodeButtonsGroup;
   private EdgeCreatedListener edgeCreatedListener;
   private NodeButton selectButton;

   private static final int BUTTON_SIZE = 	30;
   private static final int OFFSET = 5;
}