// 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 */