// File: LayerDiagram.java // Classes: LayerDiagram // Original Author: Jason Robbins // $Id: LayerDiagram.java,v 1.1.1.1 1997/02/27 20:52:41 chandra Exp $ package uci.graphedit; import java.util.Vector; import java.util.Enumeration; import java.awt.Rectangle; import java.awt.Graphics; /** A Layer like found in many drawing applications. It contains a * collection of DiagramElement's, ordered from back to front. Each * LayerDiagram contains part of the overall picture that the user is * drawing. */ public class LayerDiagram extends Layer { /** The DiagramElement's that are contained in this layer */ private Vector _contents = new Vector(); /** A counter so that layers have default names like 'One', 'Two', ... */ private static int _nextLayerNumbered = 1; /** Construct a new LayerDiagram with a default name and do not put * it on the Layer's menu. */ public LayerDiagram() { this("Layer" + numberWordFor(_nextLayerNumbered++)); } /** Construct a new LayerDiagram with the given name, and add it to * the menu of layers. Needs-More-Work: I have not implemented a * menu of layers yet. I don't know if that is really the right user * interface */ public LayerDiagram(String name) { super(name); _onMenu = true; } /** A utility function to give the spelled-out word for numbers. */ protected static String numberWordFor(int n) { switch(n) { case 1: return "One"; case 2: return "Two"; case 3: return "Three"; case 4: return "Four"; case 5: return "Five"; case 6: return "Six"; case 7: return "Seven"; case 8: return "Eight"; case 9: return "Nine"; default: return "Layer " + n; } } /** Add a DiagramElement to the contents of this layer. Items are * added on top of all other items */ public void add(DiagramElement de) { _contents.removeElement(de); // act like a set _contents.addElement(de); de.addObserver(this); de.endTrans(); } /** remove the given DiagramElement from this layer */ public void remove(DiagramElement de) { _contents.removeElement(de); de.endTrans(); de.deleteObserver(this); } /** Enumerate over all DiagramElement's in this layer */ public Enumeration elements() { return _contents.elements(); } /** Reply the contents of this layer. Do I really want to do this? */ public Vector contents() { return _contents; } /** Reply the 'top' DiagramElement under the given (mouse) * coordinates. Needs-More-Work: For now, just do a linear search. * Later, optimize this routine using Quad Trees (or other) * techniques. */ public DiagramElement pick(int x, int y) { /* search backward so that highest item is found first */ for (int i = _contents.size() - 1; i >= 0; i--) { DiagramElement de = (DiagramElement) _contents.elementAt(i); if (de.inside(x, y)) return de; } return null; } public DiagramElement pick(int id) { for (int i = 0;i<_contents.size();i++) { DiagramElement de = (DiagramElement) _contents.elementAt(i); if (de.hasId(id)) return de; } return null; } /** Delete all DiagramElement's from this layer */ public void removeAll() { _contents.removeAllElements(); } /** Find the DiagramElement that is being used to visualize the * given NetPort, or null if there is none in this layer. */ /* public Perspective getPortPerspective(NetPort prt) { Enumeration prims = elements(); while (prims.hasMoreElements()) { DiagramElement de = (DiagramElement) prims.nextElement(); if (de instanceof Perspective) { Perspective cur_pers = (Perspective) de; Fig find_fig = cur_pers.getPortFig(prt); if (find_fig!=null) return cur_pers; } } return null; } */ /** Find the DiagramElement that visualized the given NetNode in * this layer, or null if there is none. */ public DiagramElement perspectiveFor(Object obj) { Enumeration prims = elements(); while (prims.hasMoreElements()) { DiagramElement de = (DiagramElement) prims.nextElement(); if (de.owner() == obj) return de; } return null; } /** Draw all the DiagramElement's that belong to this layer. */ public void drawContents(Graphics g) { Rectangle clip = g.getClipRect(); Enumeration prims = elements(); while (prims.hasMoreElements()) { DiagramElement de = (DiagramElement) prims.nextElement(); if (clip == null || de.getBoundingBox().intersects(clip)) { de.draw(g); } } } /** Reorder the given DiagramElement in this layer */ public void sendToBack(DiagramElement prim) { _contents.removeElement(prim); _contents.insertElementAt(prim, 0); } /** Reorder the given DiagramElement in this layer */ public void bringToFront(DiagramElement prim) { _contents.removeElement(prim); _contents.addElement(prim); } /** Reorder the given DiagramElement in this layer. Needs-more-work: should come backward/forward until they change positions with an object they overlap. Maybe... */ public void sendBackward(DiagramElement prim) { int i = _contents.indexOf(prim); if (i == -1 || i == 0) return; Object de = _contents.elementAt(i - 1); _contents.setElementAt(de, i); _contents.setElementAt(prim, i - 1); } /** Reorder the given DiagramElement in this layer */ public void bringForward(DiagramElement prim) { int i = _contents.indexOf(prim); if (i == -1 || i == _contents.size()-1) return; Object de = _contents.elementAt(i + 1); _contents.setElementAt(de, i); _contents.setElementAt(prim, i + 1); } /** Reorder the given DiagramElement in this layer */ public void reorder(DiagramElement prim, int function) { switch (function) { case ActionReorder.SEND_TO_BACK: sendToBack(prim); break; case ActionReorder.BRING_TO_FRONT: bringToFront(prim); break; case ActionReorder.SEND_BACKWARD: sendBackward(prim); break; case ActionReorder.BRING_FORWARD: bringForward(prim); break; } } } /* end class LayerDiagram */