// 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: LayerDiagram.java // Classes: LayerDiagram // Original Author: jrobbins@ics.uci.edu // $Id: LayerDiagram.java,v 1.13 1997/06/10 23:42:57 jrobbins Exp $ package uci.graphedit; import java.util.*; import java.awt.*; /** 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. Needs-More-Work: eventually add a "Layers" menu to the * Editor. * * FEATURE: graph_visualization */ public class LayerDiagram extends Layer { //////////////////////////////////////////////////////////////// // instance variables /** The DiagramElement's that are contained in this layer. */ protected Vector _contents = new Vector(); /** A counter so that layers have default names like 'One', 'Two', ... */ protected static int _nextLayerNumbered = 1; //////////////////////////////////////////////////////////////// // constuctors and related methods /** 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; } } //////////////////////////////////////////////////////////////// // accessors /** 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); // needs-more-work: old? de.setLayer(this); de.endTrans(); } /** Remove the given DiagramElement from this layer. */ public void remove(DiagramElement de) { _contents.removeElement(de); de.endTrans(); de.deleteObserver(this); de.setLayer(null); } /** 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; } /** Delete all DiagramElement's from this layer. */ public void removeAll() { for (int i = _contents.size() - 1; i >= 0; i--) { DiagramElement de = (DiagramElement) _contents.elementAt(i); de.setLayer(null); } _contents.removeAllElements(); //notify? } /** 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; } //////////////////////////////////////////////////////////////// // drawing methods /** 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); } } } //////////////////////////////////////////////////////////////// // ordering of DiagramElements /** 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 */