Search in sources :

Example 1 with PanelEquationGraph

use of gov.sandia.n2a.ui.eq.PanelEquationGraph in project n2a by frothga.

the class ChangePart method apply.

public void apply(String nameBefore, String nameAfter) {
    NodePart parent = (NodePart) NodeBase.locateNode(path);
    if (parent == null)
        throw new CannotRedoException();
    NodeBase temp = parent.child(nameBefore);
    if (!(temp instanceof NodePart))
        throw new CannotRedoException();
    NodePart nodeBefore = (NodePart) temp;
    // Update the database
    // Move the subtree
    MPart mparent = parent.source;
    mparent.clear(nameBefore);
    mparent.set(savedTree, nameAfter);
    MPart oldPart = (MPart) mparent.child(nameBefore);
    MPart newPart = (MPart) mparent.child(nameAfter);
    // Change connection bindings to this part.
    // See ChangeVariable.apply() for a similar procedure. More detailed comments appear there.
    // We make use of static functions in that class to do the heavy work of emitting code with name changes.
    // TODO: This approach will probably fail on parts that contain references to themselves.
    PanelEquations pe = PanelModel.instance.panelEquations;
    List<List<String>> references = new ArrayList<List<String>>();
    try {
        MPart doc = pe.root.source;
        EquationSet compiled = new EquationSet(doc);
        List<String> keypath = new ArrayList<String>(path.subList(1, path.size()));
        EquationSet eold;
        EquationSet enew;
        if (oldPart == null) {
            EquationSet p = (EquationSet) compiled.getObject(keypath);
            eold = new EquationSet(p, nameBefore);
            p.parts.add(eold);
            keypath.add(nameAfter);
        } else {
            keypath.add(nameBefore);
            eold = (EquationSet) compiled.getObject(keypath);
            keypath.set(keypath.size() - 1, nameAfter);
        }
        enew = (EquationSet) compiled.getObject(keypath);
        try {
            compiled.resolveConnectionBindings();
        } catch (Exception e) {
        }
        try {
            compiled.resolveLHS();
            compiled.resolveRHS();
        } catch (Exception e) {
        }
        ChangeVariable.prepareConnections(compiled);
        // Collect variables that might have changed.
        List<Variable> users = collectVariables(compiled, eold);
        if (eold.dependentConnections != null) {
            // The variable associated with such a connection binding could explicitly mention the part name.
            for (ConnectionBinding cb : eold.dependentConnections) users.add(cb.variable);
        }
        eold.name = enew.name;
        for (Variable v : users) {
            List<String> ref = v.getKeyPath();
            MNode n = doc.child(ref.toArray());
            String oldKey = n.key();
            String newKey = ChangeVariable.changeReferences(eold, n, v);
            if (// Handle a change in variable name.
            !newKey.equals(oldKey)) {
                NodeBase nb = pe.root.locateNodeFromHere(ref);
                n.parent().move(oldKey, newKey);
                ref.set(ref.size() - 1, newKey);
                nb.source = (MPart) doc.child(ref.toArray());
            }
            // Queue GUI updates for nodes other than the primary ones.
            if (v.container != enew && v.container != eold)
                references.add(ref);
        }
    } catch (Exception e) {
    }
    // Change pin links to this part.
    // Scan peer parts (which is the only place a pin link can be declared) and check for "bind" keys that reference nameBefore.
    // for updating GUI later
    Map<NodePart, List<String>> rebind = new HashMap<NodePart, List<String>>();
    Enumeration<?> siblings = parent.children();
    while (siblings.hasMoreElements()) {
        Object o = siblings.nextElement();
        if (!(o instanceof NodePart))
            continue;
        NodePart sibling = (NodePart) o;
        MNode pins;
        if (// because the old source is no longer attached to document
        sibling == nodeBefore)
            // because the old source is no longer attached to document
            pins = parent.source.child(nameAfter, "$metadata", "gui", "pin", "in");
        else
            pins = sibling.source.child("$metadata", "gui", "pin", "in");
        if (pins == null)
            continue;
        List<String> bound = null;
        for (MNode pin : pins) {
            if (pin.get("bind").equals(nameBefore)) {
                pin.set(nameAfter, "bind");
                // Also set the new name in collated pin data.
                sibling.pinIn.set(nameAfter, pin.key(), "bind");
                if (bound == null)
                    bound = new ArrayList<String>();
                bound.add(pin.key());
            }
        }
        if (bound != null)
            rebind.put(sibling, bound);
    }
    // Check parent for pin exports.
    MNode pins = parent.source.child("$metadata", "gui", "pin", "out");
    if (pins != null) {
        List<String> bound = null;
        for (MNode pin : pins) {
            if (pin.get("bind").equals(nameBefore)) {
                pin.set(nameAfter, "bind");
                if (bound == null)
                    bound = new ArrayList<String>();
                bound.add(pin.key());
            }
        }
        if (bound != null)
            rebind.put(parent, bound);
    }
    // Update GUI
    boolean graphParent = parent == pe.part;
    PanelEquationTree pet = graphParent ? null : parent.getTree();
    FilteredTreeModel model = null;
    if (pet != null)
        model = (FilteredTreeModel) pet.tree.getModel();
    // Only used if graphParent is true.
    PanelEquationGraph peg = pe.panelEquationGraph;
    // It's either a NodePart or it's null. Any other case should be blocked by GUI constraints.
    NodePart nodeAfter = (NodePart) parent.child(nameAfter);
    boolean addGraphNode = false;
    if (// Only one node will remain when we are done.
    oldPart == null) {
        pe.renameFocus(nodeBefore.getKeyPath(), nameAfter);
        if (// This is a simple rename, with no restructuring. Keep nodeBefore.
        nodeAfter == null) {
            nodeAfter = nodeBefore;
            nodeAfter.source = newPart;
            if (graphParent)
                peg.updatePart(nodeAfter);
        } else // Use existing nodeAfter, so get rid of nodeBefore.
        {
            if (model == null)
                FilteredTreeModel.removeNodeFromParentStatic(nodeBefore);
            else
                model.removeNodeFromParent(nodeBefore);
            if (graphParent)
                peg.removePart(nodeBefore, true);
        }
    } else // Need two nodes
    {
        if (// Need a node to hold the new part.
        nodeAfter == null) {
            int index = parent.getIndex(nodeBefore);
            nodeAfter = new NodePart(newPart);
            nodeAfter.hide = graphParent;
            if (model == null)
                FilteredTreeModel.insertNodeIntoUnfilteredStatic(nodeAfter, parent, index);
            else
                model.insertNodeIntoUnfiltered(nodeAfter, parent, index);
            addGraphNode = true;
        }
        nodeBefore.build();
        nodeBefore.findConnections();
        nodeBefore.rebuildPins();
        nodeBefore.filter();
        if (nodeBefore.visible()) {
            if (// Need to update entire model under fake root.
            graphParent) {
                PanelEquationTree subpet = nodeBefore.getTree();
                if (subpet != null) {
                    FilteredTreeModel submodel = (FilteredTreeModel) subpet.tree.getModel();
                    submodel.nodeStructureChanged(nodeBefore);
                    subpet.animate();
                }
            } else if (model != null) {
                model.nodeStructureChanged(nodeBefore);
            }
        } else {
            parent.hide(nodeBefore, model);
        }
    }
    nodeAfter.build();
    if (graphParent)
        parent.findConnections();
    else
        nodeAfter.findConnections();
    nodeAfter.rebuildPins();
    nodeAfter.filter();
    pe.resetBreadcrumbs();
    TreeNode[] nodePath = nodeAfter.getPath();
    Set<PanelEquationTree> needAnimate = new HashSet<PanelEquationTree>();
    if (pet == null) {
        PanelEquationTree.updateOrder(null, nodePath);
        PanelEquationTree.updateVisibility(null, nodePath, -2, false);
    } else {
        pet.updateOrder(nodePath);
        // Will include nodeStructureChanged(), if necessary.
        pet.updateVisibility(nodePath);
        needAnimate.add(pet);
    }
    for (List<String> ref : references) {
        NodeVariable n = (NodeVariable) pe.root.locateNodeFromHere(ref);
        if (n == null)
            continue;
        // Rebuild n, because equations and/or their conditions may have changed.
        n.build();
        n.findConnections();
        n.filter();
        if (// n's visibility won't change
        n.visible()) {
            PanelEquationTree subpet = n.getTree();
            if (subpet == null)
                continue;
            JTree subtree = subpet.tree;
            FilteredTreeModel submodel = (FilteredTreeModel) subtree.getModel();
            NodeBase subparent = (NodeBase) n.getParent();
            // Node will collapse if it was open. Don't worry about this.
            submodel.nodeStructureChanged(n);
            subparent.invalidateColumns(submodel);
            needAnimate.add(subpet);
        }
    }
    for (NodePart peer : rebind.keySet()) {
        PanelEquationTree subpet = peer.getTree();
        // also works for parent
        NodeBase metadata = peer.child("$metadata");
        for (String pinKey : rebind.get(peer)) {
            // Retrieve GUI metadata node so it can be updated to match DB.
            NodeBase nodeBind;
            if (peer == parent)
                nodeBind = (NodeAnnotation) AddAnnotation.findExact(metadata, false, "gui", "pin", "out", pinKey, "bind");
            else
                nodeBind = (NodeAnnotation) AddAnnotation.findExact(metadata, false, "gui", "pin", "in", pinKey, "bind");
            nodeBind.setUserObject();
            // Update display tree.
            if (subpet != null) {
                // For simplicity, look up subtree, submodel and subparent each time,
                // even though they could be done just once per peer part.
                JTree subtree = subpet.tree;
                FilteredTreeModel submodel = (FilteredTreeModel) subtree.getModel();
                NodeBase subparent = (NodeBase) nodeBind.getParent();
                submodel.nodeChanged(nodeBind);
                subparent.invalidateColumns(submodel);
                needAnimate.add(subpet);
            }
        }
    }
    for (PanelEquationTree ap : needAnimate) ap.animate();
    if (graphParent) {
        if (addGraphNode) {
            // builds tree
            peg.addPart(nodeAfter);
        } else {
            PanelEquationTree subpet = nodeAfter.getTree();
            if (subpet != null) {
                FilteredTreeModel submodel = (FilteredTreeModel) subpet.tree.getModel();
                submodel.nodeStructureChanged(nodeAfter);
                FocusCacheEntry fce = pe.createFocus(nodeAfter);
                if (fce.sp != null)
                    fce.sp.restore(subpet.tree, false);
                subpet.animate();
            }
        }
        nodeAfter.hide = false;
        nodeAfter.graph.takeFocusOnTitle();
        peg.updatePins();
        peg.reconnect();
        peg.repaint();
    }
}
Also used : MPart(gov.sandia.n2a.eqset.MPart) AccessVariable(gov.sandia.n2a.language.AccessVariable) NodeVariable(gov.sandia.n2a.ui.eq.tree.NodeVariable) Variable(gov.sandia.n2a.eqset.Variable) HashMap(java.util.HashMap) PanelEquationGraph(gov.sandia.n2a.ui.eq.PanelEquationGraph) ConnectionBinding(gov.sandia.n2a.eqset.EquationSet.ConnectionBinding) ArrayList(java.util.ArrayList) PanelEquations(gov.sandia.n2a.ui.eq.PanelEquations) MNode(gov.sandia.n2a.db.MNode) NodeBase(gov.sandia.n2a.ui.eq.tree.NodeBase) NodeAnnotation(gov.sandia.n2a.ui.eq.tree.NodeAnnotation) TreeNode(javax.swing.tree.TreeNode) ArrayList(java.util.ArrayList) List(java.util.List) PanelEquationTree(gov.sandia.n2a.ui.eq.PanelEquationTree) FilteredTreeModel(gov.sandia.n2a.ui.eq.FilteredTreeModel) HashSet(java.util.HashSet) EquationSet(gov.sandia.n2a.eqset.EquationSet) CannotRedoException(javax.swing.undo.CannotRedoException) NodeVariable(gov.sandia.n2a.ui.eq.tree.NodeVariable) CannotRedoException(javax.swing.undo.CannotRedoException) JTree(javax.swing.JTree) FocusCacheEntry(gov.sandia.n2a.ui.eq.PanelEquations.FocusCacheEntry) NodePart(gov.sandia.n2a.ui.eq.tree.NodePart)

Example 2 with PanelEquationGraph

use of gov.sandia.n2a.ui.eq.PanelEquationGraph in project n2a by frothga.

the class ChangeVariableToInherit method undo.

public void undo() {
    super.undo();
    NodePart parent = (NodePart) NodeBase.locateNode(path);
    if (parent == null)
        throw new CannotUndoException();
    NodePart grandparent = (NodePart) parent.getTrueParent();
    // Update the database
    MPart mparent = parent.source;
    mparent.clear("$inherit");
    String nameBefore = treeBefore.key();
    mparent.set(treeBefore, nameBefore);
    // Update the GUI
    PanelEquations pe = PanelModel.instance.panelEquations;
    PanelEquationTree pet = parent.getTree();
    FilteredTreeModel model = (FilteredTreeModel) pet.tree.getModel();
    PanelEquationGraph peg = pe.panelEquationGraph;
    parent.build();
    if (grandparent == null)
        parent.findConnections();
    else
        grandparent.findConnections();
    parent.rebuildPins();
    parent.filter();
    if (parent == pe.part) {
        peg.reloadPart();
        parent.filter();
    }
    model.nodeStructureChanged(parent);
    TreeNode[] nodePath = parent.child(nameBefore).getPath();
    pet.updateOrder(nodePath);
    pet.updateVisibility(nodePath);
    pet.animate();
    if (parent != pe.part) {
        peg.updatePins();
        peg.reconnect();
        peg.repaint();
    }
    if (// root node, so update categories in search list
    parent.getTrueParent() == null) {
        PanelModel.instance.panelSearch.search();
    }
}
Also used : MPart(gov.sandia.n2a.eqset.MPart) PanelEquationGraph(gov.sandia.n2a.ui.eq.PanelEquationGraph) TreeNode(javax.swing.tree.TreeNode) CannotUndoException(javax.swing.undo.CannotUndoException) PanelEquations(gov.sandia.n2a.ui.eq.PanelEquations) NodePart(gov.sandia.n2a.ui.eq.tree.NodePart) PanelEquationTree(gov.sandia.n2a.ui.eq.PanelEquationTree) FilteredTreeModel(gov.sandia.n2a.ui.eq.FilteredTreeModel)

Example 3 with PanelEquationGraph

use of gov.sandia.n2a.ui.eq.PanelEquationGraph in project n2a by frothga.

the class AddPart method destroy.

public static void destroy(List<String> path, boolean canceled, String name, boolean setSelected, boolean multiShared, boolean touchesPin) {
    // Retrieve created node
    NodePart parent = (NodePart) NodeBase.locateNode(path);
    if (parent == null)
        throw new CannotUndoException();
    NodePart createdNode = (NodePart) parent.child(name);
    PanelEquations pe = PanelModel.instance.panelEquations;
    boolean graphParent = parent == pe.part;
    // Only use tree if it is not the graph parent, since graph parent hides its sub-parts.
    PanelEquationTree pet = graphParent ? null : parent.getTree();
    FilteredTreeModel model = null;
    if (pet != null)
        model = (FilteredTreeModel) pet.tree.getModel();
    // only used if graphParent is true
    PanelEquationGraph peg = pe.panelEquationGraph;
    TreeNode[] createdPath = createdNode.getPath();
    // returns -1 if createdNode is filtered out of parent
    int index = parent.getIndexFiltered(createdNode);
    if (canceled)
        index--;
    MPart mparent = parent.source;
    mparent.clear(name);
    if (// Node is fully deleted
    mparent.child(name) == null) {
        pe.deleteFocus(createdNode);
        if (model == null)
            FilteredTreeModel.removeNodeFromParentStatic(createdNode);
        else
            model.removeNodeFromParent(createdNode);
        if (graphParent)
            peg.removePart(createdNode, setSelected && !multiShared);
        parent.findConnections();
        parent.updatePins();
    } else // Just exposed an overridden node
    {
        // Does not change the fake-root status of this node.
        createdNode.build();
        parent.findConnections();
        createdNode.rebuildPins();
        createdNode.filter();
        if (// Need to update entire model under fake root.
        graphParent) {
            PanelEquationTree subpet = createdNode.getTree();
            if (subpet != null) {
                FilteredTreeModel submodel = (FilteredTreeModel) subpet.tree.getModel();
                submodel.nodeStructureChanged(createdNode);
                subpet.animate();
            }
            // Implicitly, the title of the node was focused when the part was deleted, so ensure it gets the focus back.
            if (setSelected && !multiShared)
                createdNode.graph.takeFocusOnTitle();
        }
    }
    pe.resetBreadcrumbs();
    if (pet == null) {
        PanelEquationTree.updateOrder(null, createdPath);
        PanelEquationTree.updateVisibility(null, createdPath, index, false);
    } else {
        pet.updateOrder(createdPath);
        // includes nodeStructureChanged(), if necessary
        pet.updateVisibility(createdPath, index, setSelected);
        pet.animate();
    }
    if (graphParent || touchesPin) {
        peg.updatePins();
        peg.reconnect();
        peg.repaint();
    }
    if (graphParent) {
        if (pe.view == PanelEquations.NODE && peg.isEmpty())
            pe.panelParent.setOpen(true);
        if (setSelected && multiShared)
            pe.switchFocus(false, false);
    }
}
Also used : MPart(gov.sandia.n2a.eqset.MPart) PanelEquationGraph(gov.sandia.n2a.ui.eq.PanelEquationGraph) TreeNode(javax.swing.tree.TreeNode) CannotUndoException(javax.swing.undo.CannotUndoException) PanelEquations(gov.sandia.n2a.ui.eq.PanelEquations) NodePart(gov.sandia.n2a.ui.eq.tree.NodePart) PanelEquationTree(gov.sandia.n2a.ui.eq.PanelEquationTree) FilteredTreeModel(gov.sandia.n2a.ui.eq.FilteredTreeModel) Point(java.awt.Point)

Example 4 with PanelEquationGraph

use of gov.sandia.n2a.ui.eq.PanelEquationGraph in project n2a by frothga.

the class AddPart method centerOf.

/**
 *        Determine the anchor position for a set of new parts.
 *        The main approach is to approximate the center of the viewport when the parent part is displayed.
 *        If that is not possible, the fallback is the average position of existing parts.
 *        If there are no existing parts, the position is set arbitrarily to (100,100). This gives a small
 *        margin from the edge for nice appearance, while not straying far from (0,0).
 */
public static Point centerOf(NodePart parent) {
    PanelEquations pe = PanelModel.instance.panelEquations;
    PanelEquationGraph peg = pe.panelEquationGraph;
    Dimension d = peg.getExtentSize();
    Point location = new Point(d.width / 2, d.height / 2);
    // Base on active viewport.
    if (parent == pe.part) {
        Point vp = peg.getViewPosition();
        Point offset = peg.getOffset();
        location.x += vp.x - offset.x;
        location.y += vp.y - offset.y;
        return location;
    }
    // Base on stored position of viewport.
    MNode boundsParent = parent.source.child("$metadata", "gui", "bounds", "parent");
    if (boundsParent != null) {
        location.x += boundsParent.getInt("x");
        location.y += boundsParent.getInt("y");
        return location;
    }
    // Base on average position of existing parts.
    Point center = new Point();
    int count = 0;
    Enumeration<?> children = parent.children();
    while (children.hasMoreElements()) {
        Object o = children.nextElement();
        if (!(o instanceof NodePart))
            continue;
        NodePart p = (NodePart) o;
        MNode bounds = p.source.child("$metadata", "gui", "bounds");
        if (bounds == null)
            continue;
        count++;
        center.x += bounds.getInt("x");
        center.y += bounds.getInt("y");
    }
    if (count == 1) {
        location.x = center.x + 100;
        location.y = center.y + 100;
    } else if (count > 1) {
        location.x = center.x / count;
        location.y = center.y / count;
    }
    return new Point(100, 100);
}
Also used : PanelEquationGraph(gov.sandia.n2a.ui.eq.PanelEquationGraph) PanelEquations(gov.sandia.n2a.ui.eq.PanelEquations) Dimension(java.awt.Dimension) Point(java.awt.Point) NodePart(gov.sandia.n2a.ui.eq.tree.NodePart) MNode(gov.sandia.n2a.db.MNode) Point(java.awt.Point)

Example 5 with PanelEquationGraph

use of gov.sandia.n2a.ui.eq.PanelEquationGraph in project n2a by frothga.

the class AddInherit method create.

public static void create(List<String> path, String value) {
    NodePart parent = (NodePart) NodeBase.locateNode(path);
    if (parent == null)
        throw new CannotRedoException();
    NodePart grandparent = (NodePart) parent.getTrueParent();
    PanelEquations pe = PanelModel.instance.panelEquations;
    PanelEquationTree pet = parent.getTree();
    FilteredTreeModel model = (FilteredTreeModel) pet.tree.getModel();
    PanelEquationGraph peg = pe.panelEquationGraph;
    parent.source.set(value, "$inherit");
    parent.build();
    if (grandparent == null)
        parent.findConnections();
    else
        grandparent.findConnections();
    parent.rebuildPins();
    parent.filter();
    if (parent == pe.part) {
        peg.reloadPart();
        parent.filter();
    }
    // Since $inherit is being added, parent will almost certainly become visible, if it's not already.
    model.nodeStructureChanged(parent);
    TreeNode[] createdPath = parent.child("$inherit").getPath();
    pet.updateOrder(createdPath);
    pet.updateVisibility(createdPath);
    pet.animate();
    if (parent != pe.part) {
        peg.updatePins();
        peg.reconnect();
        peg.repaint();
    }
    if (// root node, so update categories in search list
    parent.getTrueParent() == null) {
        PanelModel.instance.panelSearch.search();
    }
}
Also used : PanelEquationGraph(gov.sandia.n2a.ui.eq.PanelEquationGraph) TreeNode(javax.swing.tree.TreeNode) CannotRedoException(javax.swing.undo.CannotRedoException) PanelEquations(gov.sandia.n2a.ui.eq.PanelEquations) NodePart(gov.sandia.n2a.ui.eq.tree.NodePart) PanelEquationTree(gov.sandia.n2a.ui.eq.PanelEquationTree) FilteredTreeModel(gov.sandia.n2a.ui.eq.FilteredTreeModel)

Aggregations

PanelEquationGraph (gov.sandia.n2a.ui.eq.PanelEquationGraph)10 PanelEquations (gov.sandia.n2a.ui.eq.PanelEquations)10 NodePart (gov.sandia.n2a.ui.eq.tree.NodePart)10 FilteredTreeModel (gov.sandia.n2a.ui.eq.FilteredTreeModel)9 PanelEquationTree (gov.sandia.n2a.ui.eq.PanelEquationTree)9 TreeNode (javax.swing.tree.TreeNode)9 MPart (gov.sandia.n2a.eqset.MPart)7 CannotRedoException (javax.swing.undo.CannotRedoException)6 NodeBase (gov.sandia.n2a.ui.eq.tree.NodeBase)5 CannotUndoException (javax.swing.undo.CannotUndoException)4 MNode (gov.sandia.n2a.db.MNode)3 EquationSet (gov.sandia.n2a.eqset.EquationSet)2 Variable (gov.sandia.n2a.eqset.Variable)2 AccessVariable (gov.sandia.n2a.language.AccessVariable)2 NodeVariable (gov.sandia.n2a.ui.eq.tree.NodeVariable)2 Point (java.awt.Point)2 ArrayList (java.util.ArrayList)2 HashSet (java.util.HashSet)2 List (java.util.List)2 JTree (javax.swing.JTree)2