// Copyright (c) 1996-98 The Regents of the University of California. All // Rights Reserved. Permission to use, copy, modify, and distribute this // software and its documentation for educational, research and non-profit // purposes, without fee, and without a written agreement is hereby granted, // provided that the above copyright notice and this paragraph appear in all // copies. Permission to incorporate this software into commercial products may // be obtained by contacting the University of California. David F. Redmiles // Department of Information and Computer Science (ICS) University of // California Irvine, California 92697-3425 Phone: 714-824-3823. This software // program and documentation are copyrighted by The Regents of the University // of California. The software program and documentation are supplied "as is", // without any accompanying services from The Regents. The Regents do not // warrant that the operation of the program will be uninterrupted or // error-free. The end-user understands that the program was developed for // research purposes and is advised not to rely exclusively on the program for // any reason. IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY // PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, // INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS // DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY // DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE // SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF // CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, // ENHANCEMENTS, OR MODIFICATIONS. // File: Perspective.java // Classes: Perspective // Original Author: ics125b spring 1996 // $Id: Perspective.java,v 1.25 1997/06/10 23:43:25 jrobbins Exp $ package uci.graphedit; import java.awt.*; import java.util.*; import java.io.*; import uci.util.*; import uci.ui.*; /** Class to display graphics for a NetNode in a diagram. * * FEATURE: graph_visualization_nodes * * FEATURE: graph_visualization_ports */ public class Perspective extends DiagramElement { //////////////////////////////////////////////////////////////// // instance variables /** Each Perspective keeps a collection of the NetPorts that are * shown in this Perspective. * * FEATURE: graph_visualization_ports */ public Vector portList; /** The NetNode that is being displayed. */ public NetNode parentNode; /** The Fig's that make up the look of this Perspective. */ public FigList figList; /** True if you want ports to highlight when the mouse moves in. */ public boolean _shouldHighlightPorts = false; /** True when we want to draw the user's attention to this Perspective. */ public boolean _highlight = false; //////////////////////////////////////////////////////////////// // constructors /** Constructs a new Perspective on the given NetNode with the * given Fig's. */ public Perspective(NetNode parent_node) { portList = new Vector(); parentNode = parent_node; parentNode.addPersistantObserver(this); } public Perspective(NetNode parent_node, FigList figs) { this(parent_node); setFigList(figs); } //////////////////////////////////////////////////////////////// // accessors /** Set the property of highlighting ports when the user moves the * mouse over this perspective. * * FEATURE: graph_visualization_ports */ public void shouldHighlightPorts(boolean b) { _shouldHighlightPorts = b; } /** Replys a rectangle that bounds all the Fig's in this perspective*/ public Rectangle getBoundingBox() { return figList.getBoundingBox(); } /** Move the Perspective to the given position. */ public void position(int x,int y) { int dx = x - position().x; int dy = y - position().y; translate(dx, dy); } /** The owner of a Perspective is an underlying NetNode */ public Object owner() { return parentNode; } /** Returns the fig list used by this perspective. This function is * essential for the perspective editor since the editor works on a * FigList. */ public FigList getFigList() { return figList; } /** Set the Figs that make up this Perspective */ public void setFigList(FigList figs) { Rectangle rect = figs.getBoundingBox(); figList = figs; position(rect.x, rect.y); } public Object get(String key) { if (owner() instanceof IProps) { IProps node = (IProps) owner(); Object res = node.get(key); if (res != null) return res; } return super.get(key); } public boolean put(String key, Object value) { boolean res = false; if (owner() instanceof IProps) { IProps node = (IProps) owner(); if (node != null) res = node.put(key, value); } return res || super.put(key, value); } public Enumeration keysIn(String cat) { if (owner() instanceof IProps) { IProps node = (IProps) owner(); if (node != null) return new EnumerationComposite(node.keysIn(cat), super.keysIn(cat)); } return super.keysIn(cat); } public boolean canPut(String key) { if (owner() instanceof IProps) { IProps node = (IProps) owner(); if (node != null) return node.canPut(key); } return super.canPut(key); } /** Reply a collection of ArcPerspective's for all the NetArcs that * are connected to NetPorts of the NetNode being displayed. Needs-More-Work: this code is really slow. */ protected Vector arcPerspectives(Editor ed) { Vector arcs = new Vector(); Vector arcPerspectives = new Vector(); Enumeration curPort = portList.elements(); while (curPort.hasMoreElements()) { NetPort p = (NetPort) curPort.nextElement(); Enumeration curArc = p.arcList.elements(); while (curArc.hasMoreElements()) { NetArc a = (NetArc) curArc.nextElement(); arcs.addElement(a); } } Enumeration curDE = ed.diagramElements(); while (curDE.hasMoreElements()) { DiagramElement de = (DiagramElement) curDE.nextElement(); Object owner = de.owner(); if (owner != null && arcs.contains(owner)) { arcPerspectives.addElement(de); } } return arcPerspectives; } //////////////////////////////////////////////////////////////// // DiagramElement API /** Move the Perspective by the given amount */ public void translate(int dx,int dy) { position().x += dx; position().y += dy; figList.translate(dx,dy); } //////////////////////////////////////////////////////////////// // Editor API /** When a Perspective is damaged, all of its arcs may need redrawing. */ public void damagedIn(Editor ed) { Enumeration arcPers = arcPerspectives(ed).elements(); while (arcPers.hasMoreElements()) { DiagramElement de = (DiagramElement) arcPers.nextElement(); de.damagedIn(ed); } super.damagedIn(ed); } public void removeFrom(Editor ed) { if (parentNode != null) { parentNode.deleteObserver(this); parentNode = null; } super.removeFrom(ed); } /** When a Perspective is removed, dispose all of the NetArcs and * the underlying NetNode. Needs-More-Work: is this right? Doesn't * ActionDelete call this method also? How is deletion of a * Perspective handled without disposing the underlying model? */ public void dispose(Editor ed) { Enumeration arcPers = arcPerspectives(ed).elements(); while (arcPers.hasMoreElements()) { DiagramElement de = (DiagramElement) arcPers.nextElement(); de.dispose(ed); } if (parentNode != null) parentNode.dispose(); super.dispose(ed); } /** Reply true iff the point is in any of the Fig's in the perspective. */ public boolean inside(int x, int y) { return (figList.pick(x, y) != null); } /** Reply true iff this Perspective intersects the given Rectangle. */ public boolean intersects(Rectangle rct) { return getBoundingBox().intersects(rct); } //////////////////////////////////////////////////////////////// // ports /** Adds a port into the current perspective. * * FEATURE: graph_visualization_ports */ public void addPort(NetPort prt, Fig rep) { Fig old_fig = getPortFig(prt); if (old_fig != null) old_fig.owner(null); rep.owner(prt); portList.addElement(prt); } /** Removes a port from the current perspective. * * FEATURE: graph_visualization_ports */ public void removePort(Fig rep) { if (rep.owner() != null) { portList.removeElement(rep.owner()); rep.owner(null); } } /** Reply the NetPort associated with the Fig under the mouse, or * null if there is none. * * FEATURE: graph_visualization_ports */ public final NetPort pickPort(Point p) { return pickPort(p.x, p.y); } /** Reply the port that "owns" the Fig under the given point, or * null if none. * * FEATURE: graph_visualization_ports */ public NetPort pickPort(int x, int y) { Fig ret = figList.pick(x, y); if (ret != null) return (NetPort) ret.owner(); else return null; } /** Reply the Fig that displays the given NetPort. * * FEATURE: graph_visualization_ports */ public Fig getPortFig(NetPort prt) { Fig ret = null; Vector list = figList.getFigList(); int size = list.size(); for (int i = 0; i < size; i++) { Fig cur_fig = (Fig) list.elementAt(i); if (cur_fig.owner() == prt) { ret = cur_fig; break; } } return ret; } //////////////////////////////////////////////////////////////// // drawing methods /** Draws the perspective to the given Graphics. */ public void draw(Graphics g) { Rectangle clip = g.getClipRect(); Rectangle bbox = getBoundingBox(); if (clip == null || bbox.intersects(clip)) { figList.draw(g); } if (_highlight) { g.setColor(Globals.prefs().highlightColor()); /* needs-more-work */ g.drawRect(bbox.x-3, bbox.y-3, bbox.width+6-1, bbox.height+6-1); g.drawRect(bbox.x-2, bbox.y-2, bbox.width+4-1, bbox.height+4-1); } } /** Needs-More-Work: Remove this, its logic has been moved to * SelectionBox. */ public void drawSelected(Graphics g) { } /** When a Perspective is selected the Editor should record that * fact in an instance of SelectionBox. */ public Selection selectionObject() { return new SelectionBox(this); } //////////////////////////////////////////////////////////////// // notifications and updates /** If I get a notification that I shuold be Highlighted or * Unhighlight, set a flag and mark my area as damaged. */ public void update(Observable o, Object arg) { if (Globals.HIGHLIGHT.equals(arg)) { startTrans(); _highlight = true; endTrans(); } else if (Globals.UNHIGHLIGHT.equals(arg)) { startTrans(); _highlight = false; endTrans(); } else if (arg instanceof Vector) { Vector v = (Vector) arg; String s = (String) v.elementAt(0); Object obj = v.elementAt(1); if (s.equals(Globals.REMOVE) && obj == parentNode) { removeFrom(null); } } } /** * FEATURE: graph_visualization_ports */ public void highlightPorts() { startTrans(); // Color c = Globals.prefs().highlightColor(); Vector list = figList.getFigList(); int size = list.size(); for (int i = 0; i < size; i++) { Fig cur_fig = (Fig) list.elementAt(i); if (cur_fig.owner() != null) { cur_fig.setLineWidth(1); cur_fig.setFilled(true); } } endTrans(); } /** * FEATURE: graph_visualization_ports */ public void unhighlightPorts() { startTrans(); Vector list = figList.getFigList(); int size = list.size(); for (int i = 0; i < size; i++) { Fig cur_fig = (Fig) list.elementAt(i); if (cur_fig.owner() != null) { cur_fig.setLineWidth(0); cur_fig.setFilled(false); } } endTrans(); } //////////////////////////////////////////////////////////////// // event handlers /** If the mouse enters this Perspective's bbox and the * shouldHighlightPorts flag is set, then highlight ports. */ public boolean mouseEnter(Event e, int x, int y) { if (_shouldHighlightPorts) highlightPorts(); return super.mouseEnter(e, x, y); } /** If the mouse exits this Perspective's bbox and the * shouldHighlightPorts flag is set, then unhighlight ports. */ public boolean mouseExit(Event e, int x, int y) { if (_shouldHighlightPorts) unhighlightPorts(); return super.mouseExit(e, x, y); } } /* end class Perspective */