All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.api.visual.graph.GraphPinScene Maven / Gradle / Ivy

There is a newer version: RELEASE230
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.netbeans.api.visual.graph;

import org.netbeans.api.visual.model.ObjectScene;
import org.netbeans.api.visual.widget.Widget;
import org.netbeans.modules.visual.util.GeomUtil;

import java.util.*;

/**
 * This class holds and manages graph-oriented model.
 * 

* In comparison with the GraphScene class, in this class the graph consists of nodes, edges and pins. Each pin is assigned to a node (the assigned cannot be change at any time. * Each edge could be attach to a single source and target pin. *

* The class is abstract and manages only data model and mapping with widgets. The graphics (widgets) has to be supplied * by a developer by overriding the attachNodeWidget, attachPinWidget, attachEdgeWidget, attachEdgeSourceAnchor and attachEdgeTargetAnchor abstract methods. *

* This class is using generics and allows you to specify type representation for nodes and edges in the graph model. Example: *

 * class MyGraph extends GraphScene<MyNode, MyEdge, MyPin> { ... }
 * 
* Since the type of nodes, edges and pins could be the same, all node, edge and pin instances have to be unique within the whole scene. * * @author David Kaspar */ // TODO - is it asserted that removing a node removes all its pins // TODO - is it asserted that removing a pin disconnects all the attached edges public abstract class GraphPinScene extends ObjectScene { private HashSet nodes = new HashSet (); private Set nodesUm = Collections.unmodifiableSet (nodes); private HashSet edges = new HashSet (); private Set edgesUm = Collections.unmodifiableSet (edges); private HashSet

pins = new HashSet

(); private Set

pinsUm = Collections.unmodifiableSet (pins); private HashMap> nodePins = new HashMap> (); private HashMap pinNodes = new HashMap (); private HashMap edgeSourcePins = new HashMap (); private HashMap edgeTargetPins = new HashMap (); private HashMap> pinInputEdges = new HashMap> (); private HashMap> pinOutputEdges = new HashMap> (); /** * Creates a graph scene. */ public GraphPinScene () { } /** * Adds a node. * @param node the node to be added; the node must not be null, must not be already in the model, must be unique in the model * (means: there is no other node, edge or pin in the model has is equal to this node) * and must not be a Widget * @return the widget that is created by attachNodeWidget; null if the node is non-visual */ public final Widget addNode (N node) { assert node != null : "Null parameter"; assert ! nodes.contains (node) : "Node (" + node + ") already added"; Widget widget = attachNodeWidget (node); nodes.add (node); nodePins.put (node, new HashSet

()); addObject (node, widget); notifyNodeAdded (node, widget); return widget; } /** * Removes a node with all pins that are assigned to the node. * @param node the node to be removed; the node must not be null and must be already in the model */ public final void removeNode (N node) { assert node != null && nodes.contains (node); for (P pin : new HashSet

(nodePins.get (node))) removePin (pin); nodes.remove (node); nodePins.remove (node); Widget widget = findWidget (node); detachNodeWidget (node, widget); removeObject (node); } /** * Removes a node with all pins that are assign to the node and with all edges that are connected to the pins. * @param node the node to be removed; the node must not be null and must be already in the model */ public final void removeNodeWithEdges (N node) { assert node != null && nodes.contains (node); for (P pin : nodePins.get (node)) for (E edge : findPinEdges (pin, true, true)) if (isEdge (edge)) removeEdge (edge); removeNode (node); } /** * Returns a collection of all nodes registered in the graph model. * @return the collection of all nodes registered in the graph model */ public final Collection getNodes () { return nodesUm; } /** * Adds an edge. * @param edge the edge to be added; the edge must not be null, must not be already in the model, must be unique in the model * (means: there is no other node, edge or pin in the model has is equal to this edge) * and must not be a Widget * @return the widget that is created by attachEdgeWidget; null if the edge is non-visual */ public final Widget addEdge (E edge) { assert edge != null && ! edges.contains (edge); Widget widget = attachEdgeWidget (edge); edges.add (edge); addObject (edge, widget); notifyEdgeAdded (edge, widget); return widget; } /** * Removes an edge and detaches it from its source and target pins. * @param edge the edge to be removed; the edge must not be null and must be already in the model */ public final void removeEdge (E edge) { assert edge != null && edges.contains (edge); setEdgeSource (edge, null); setEdgeTarget (edge, null); edges.remove (edge); edgeSourcePins.remove (edge); edgeTargetPins.remove (edge); Widget widget = findWidget (edge); detachEdgeWidget (edge, widget); removeObject (edge); } /** * Returns a collection of all edges registered in the graph model. * @return the collection of all edges registered in the graph model */ public final Collection getEdges () { return edgesUm; } /** * Adds a pin and assigns it to a specified node. * @param node the node where the pin is assigned to * @param pin the pin to be added; the pin must not be null, must not be already in the model, must be unique in the model * (means: there is no other node, edge or pin in the model has is equal to this pin) * and must not be a Widget * @return the widget that is created by attachPinWidget; null if the pin is non-visual */ public final Widget addPin (N node, P pin) { assert node != null && pin != null && ! pins.contains (pin); Widget widget = attachPinWidget (node, pin); pins.add (pin); nodePins.get (node).add (pin); pinNodes.put (pin, node); pinInputEdges.put (pin, new ArrayList ()); pinOutputEdges.put (pin, new ArrayList ()); addObject (pin, widget); notifyPinAdded (node, pin, widget); return widget; } /** * Removes an pin and detaches all edges that are connected to it. * @param pin the pin to be removed; the pin must not be null and must be already in the model */ public final void removePin (P pin) { assert pin != null && pins.contains (pin); for (E edge : findPinEdges (pin, true, false)) setEdgeSource (edge, null); for (E edge : findPinEdges (pin, false, true)) setEdgeTarget (edge, null); pins.remove (pin); N node = pinNodes.remove (pin); nodePins.get (node).remove (pin); pinInputEdges.remove (pin); pinOutputEdges.remove (pin); Widget widget = findWidget (pin); detachPinWidget (pin, widget); removeObject (pin); } /** * Removes a pin with all edges that are connected to the pin. * @param pin the pin to be removed; the pin must not be null and must be already in the model */ public final void removePinWithEdges (P pin) { assert pin != null && pins.contains (pin); for (E edge : findPinEdges (pin, true, true)) if (isEdge (edge)) removeEdge (edge); removePin (pin); } /** * Returns a node where the pin assigned to. * @param pin the pin * @return the node where the pin assigned to. */ public final N getPinNode (P pin) { return pinNodes.get (pin); } /** * Returns all pins registered in the graph model. * @return the collection of all pins registered in the graph model */ public final Collection

getPins () { return pinsUm; } /** * Returns a collection of pins that are assigned to a specified node * @param node the node * @return the collection of pins; null if node does not exist in the scene */ public final Collection

getNodePins (N node) { if (node == null) return null; HashSet

ps = nodePins.get (node); if (ps == null) return null; return Collections.unmodifiableCollection (ps); } /** * Sets an edge source. * @param edge the edge which source is going to be changed * @param sourcePin the source pin; if null, then the edge source will be detached */ public final void setEdgeSource (E edge, P sourcePin) { assert edge != null && edges.contains (edge); if (sourcePin != null) assert pins.contains (sourcePin); P oldPin = edgeSourcePins.put (edge, sourcePin); if (GeomUtil.equals (oldPin, sourcePin)) return; if (oldPin != null) pinOutputEdges.get (oldPin).remove (edge); if (sourcePin != null) pinOutputEdges.get (sourcePin).add (edge); attachEdgeSourceAnchor (edge, oldPin, sourcePin); } /** * Sets an edge target. * @param edge the edge which target is going to be changed * @param targetPin the target pin; if null, then the edge target will be detached */ public final void setEdgeTarget (E edge, P targetPin) { assert edge != null && edges.contains (edge); if (targetPin != null) assert pins.contains (targetPin); P oldPin = edgeTargetPins.put (edge, targetPin); if (GeomUtil.equals (oldPin, targetPin)) return; if (oldPin != null) pinInputEdges.get (oldPin).remove (edge); if (targetPin != null) pinInputEdges.get (targetPin).add (edge); attachEdgeTargetAnchor (edge, oldPin, targetPin); } /** * Returns an edge source. * @param edge the edge * @return the edge source; null, if edge does not have source attached */ public final P getEdgeSource (E edge) { return edgeSourcePins.get (edge); } /** * Returns an edge target. * @param edge the edge * @return the edge target; null, if edge does not have target attached */ public final P getEdgeTarget (E edge) { return edgeTargetPins.get (edge); } /** * Returns a collection of edges that are attached to a specified pin. * @param pin the pin which edges connections are searched for * @param allowOutputEdges if true, the output edges are included in the collection; if false, the output edges are not included * @param allowInputEdges if true, the input edges are included in the collection; if false, the input edges are not included * @return the collection of edges */ public final Collection findPinEdges (P pin, boolean allowOutputEdges, boolean allowInputEdges) { assert isPin (pin) : "Pin " + pin + " is not in the scene"; ArrayList list = new ArrayList (); if (allowInputEdges) list.addAll (pinInputEdges.get (pin)); if (allowOutputEdges) list.addAll (pinOutputEdges.get (pin)); return list; } /** * Returns a collection of edges that are between a source and a target pin. * @param sourcePin the source pin * @param targetPin the target pin * @return the collection of edges */ public final Collection findEdgesBetween (P sourcePin, P targetPin) { assert isPin (sourcePin) : "Source pin " + sourcePin + " is not in the scene"; assert isPin (targetPin) : "Target pin " + targetPin + " is not in the scene"; HashSet list = new HashSet (); List inputEdges = pinInputEdges.get (targetPin); List outputEdges = pinOutputEdges.get (sourcePin); for (E edge : inputEdges) if (outputEdges.contains (edge)) list.add (edge); return list; } /** * Checks whether an object is registered as a node in the graph model. * @param object the object; must not be a Widget * @return true, if the object is registered as a node */ public boolean isNode (Object object) { assert ! (object instanceof Widget) : "Use findObject method for getting an object assigned to a specific Widget"; // NOI18N return nodes.contains (object); } /** * Checks whether an object is registered as an edge in the graph model. * @param object the object; must not be a Widget * @return true, if the object is registered as a edge */ public boolean isEdge (Object object) { assert ! (object instanceof Widget) : "Use findObject method for getting an object assigned to a specific Widget"; // NOI18N return edges.contains (object); } /** * Checks whether an object is registered as a pin in the graph model. * @param object the object; must not be a Widget * @return true, if the object is registered as a pin */ public boolean isPin (Object object) { assert ! (object instanceof Widget) : "Use findObject method for getting an object assigned to a specific Widget"; // NOI18N return pins.contains (object); } /** * Called by the addNode method to notify that a node is added into the graph model. * @param node the added node * @param widget the widget created by the attachNodeWidget method as a visual representation of the node */ protected void notifyNodeAdded (N node, Widget widget) { } /** * Called by the addEdge method to notify that an edge is added into the graph model. * @param edge the added node * @param widget the widget created by the attachEdgeWidget method as a visual representation of the edge */ protected void notifyEdgeAdded (E edge, Widget widget) { } /** * Called by the addPin method to notify that a pin is added into the graph model. * @param node the node where the pin is assigned to * @param pin the added pin * @param widget the widget created by the attachPinWidget method as a visual representation of the pin */ protected void notifyPinAdded (N node, P pin, Widget widget) { } /** * Called by the removeNode method to notify that a node is removed from the graph model. * The default implementation removes the node widget from its parent widget. * @param node the removed node * @param widget the removed node widget; null if the node is non-visual */ protected void detachNodeWidget (N node, Widget widget) { if (widget != null) widget.removeFromParent (); } /** * Called by the removeEdge method to notify that an edge is removed from the graph model. * The default implementation removes the edge widget from its parent widget. * @param edge the removed edge * @param widget the removed edge widget; null if the edge is non-visual */ protected void detachEdgeWidget (E edge, Widget widget) { if (widget != null) widget.removeFromParent (); } /** * Called by the removePin method to notify that a pin is removed from the graph model. * The default implementation removes the pin widget from its parent widget. * @param pin the removed pin * @param widget the removed pin widget; null if the pin is non-visual */ protected void detachPinWidget (P pin, Widget widget) { if (widget != null) widget.removeFromParent (); } /** * Called by the addNode method before the node is registered to acquire a widget that is going to represent the node in the scene. * The method is responsible for creating the widget, adding it into the scene and returning it from the method. * @param node the node that is going to be added * @return the widget representing the node; null, if the node is non-visual */ protected abstract Widget attachNodeWidget (N node); /** * Called by the addEdge method before the edge is registered to acquire a widget that is going to represent the edge in the scene. * The method is responsible for creating the widget, adding it into the scene and returning it from the method. * @param edge the edge that is going to be added * @return the widget representing the edge; null, if the edge is non-visual */ protected abstract Widget attachEdgeWidget (E edge); /** * Called by the addPin method before the pin is registered to acquire a widget that is going to represent the pin in the scene. * The method is responsible for creating the widget, adding it into the scene and returning it from the method. * @param node the node where the pin is assigned to * @param pin the pin that is going to be added * @return the widget representing the pin; null, if the pin is non-visual */ protected abstract Widget attachPinWidget (N node, P pin); /** * Called by the setEdgeSource method to notify about the changing the edge source in the graph model. * The method is responsible for attaching a new source pin to the edge in the visual representation. *

* Usually it is implemented as: *

     * Widget sourcePinWidget = findWidget (sourcePin);
     * Anchor sourceAnchor = AnchorFactory.createRectangularAnchor (sourcePinWidget)
     * ConnectionWidget edgeWidget = (ConnectionWidget) findWidget (edge);
     * edgeWidget.setSourceAnchor (sourceAnchor);
     * 
* @param edge the edge which source is changed in graph model * @param oldSourcePin the old source pin * @param sourcePin the new source pin */ protected abstract void attachEdgeSourceAnchor (E edge, P oldSourcePin, P sourcePin); /** * Called by the setEdgeTarget method to notify about the changing the edge target in the graph model. * The method is responsible for attaching a new target pin to the edge in the visual representation. *

* Usually it is implemented as: *

     * Widget targetPinWidget = findWidget (targetPin);
     * Anchor targetAnchor = AnchorFactory.createRectangularAnchor (targetPinWidget)
     * ConnectionWidget edgeWidget = (ConnectionWidget) findWidget (edge);
     * edgeWidget.setTargetAnchor (targetAnchor);
     * 
* @param edge the edge which target is changed in graph model * @param oldTargetPin the old target pin * @param targetPin the new target pin */ protected abstract void attachEdgeTargetAnchor (E edge, P oldTargetPin, P targetPin); /** * This class is a particular GraphPinScene where nodes, edges and pins are represented with String class. */ public abstract static class StringGraph extends GraphPinScene { } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy