Search in sources :

Example 1 with Variable

use of gov.sandia.n2a.eqset.Variable in project n2a by frothga.

the class AccessVariable method simplify.

public Operator simplify(Variable from) {
    // unresolved!
    if (reference == null || reference.variable == null)
        return this;
    Variable v = reference.variable;
    // specifically prevent $init and $live from being replaced by a Constant
    if (v.name.equals("$init") || v.name.equals("$live"))
        return this;
    // A variable may locally evaluate to a constant, yet be subject to change from outside equations.
    if (v.hasAttribute("externalWrite"))
        return this;
    if (v.equations.size() != 1)
        return this;
    EquationEntry e = v.equations.first();
    if (e.expression == null)
        return this;
    if (e.condition != null) {
        if (!(e.condition instanceof Constant))
            return this;
        // Check for nonzero constant
        Type value = ((Constant) e.condition).value;
        // This second condition should be eliminated by Variable.simplify(), but until it is, don't do anything here.
        if (!(value instanceof Scalar) || ((Scalar) value).value == 0)
            return this;
    }
    if (e.expression instanceof Constant) {
        from.removeDependencyOn(v);
        from.changed = true;
        return e.expression;
    }
    // Attempt to simplify expression, and maybe get a Constant
    Variable p = from;
    while (p != null) {
        // can't simplify, because we've already visited this variable
        if (p == v)
            return this;
        p = p.visited;
    }
    v.visited = from;
    e.expression = e.expression.simplify(v);
    if (e.expression instanceof Constant) {
        from.removeDependencyOn(v);
        from.changed = true;
        return e.expression;
    }
    if (// Our variable is simply an alias for another variable, so grab the other variable instead.
    e.expression instanceof AccessVariable) {
        AccessVariable av = (AccessVariable) e.expression;
        Variable v2 = av.reference.variable;
        if (v2 == v)
            return this;
        // Can't reference a temporary outside the current equation set.
        if (v2.hasAttribute("temporary") && v2.container != from.container)
            return this;
        // Note: Folding an aliased variable will very likely remove one or more steps of delay in the movement of values through an equation set.
        // This might go against the user's intention. The folding can be blocked by adding a condition
        reference = av.reference;
        name = av.reference.variable.nameString();
        from.removeDependencyOn(v);
        from.addDependencyOn(v2);
        from.changed = true;
    }
    return this;
}
Also used : Variable(gov.sandia.n2a.eqset.Variable) EquationEntry(gov.sandia.n2a.eqset.EquationEntry) Scalar(gov.sandia.n2a.language.type.Scalar)

Example 2 with Variable

use of gov.sandia.n2a.eqset.Variable in project n2a by frothga.

the class NodeVariable method add.

@Override
public NodeBase add(String type, JTree tree, MNode data) {
    FilteredTreeModel model = (FilteredTreeModel) tree.getModel();
    if (type.isEmpty()) {
        if (model.getChildCount(this) == 0 || tree.isCollapsed(new TreePath(getPath())))
            return ((NodeBase) getParent()).add("Variable", tree, data);
        type = "Equation";
    }
    if (isBinding)
        return ((NodeBase) getParent()).add(type, tree, data);
    if (type.equals("Equation")) {
        // Determine if pasting over an existing equation
        if (data != null) {
            // includes @
            String key = data.key();
            NodeBase existingEquation = child(key);
            if (existingEquation != null) {
                // remove the @, since ChangeEquation expects strings from ParsedValue
                key = key.substring(1);
                String combiner = new Variable.ParsedValue(source.get()).combiner;
                PanelModel.instance.undoManager.add(new ChangeEquation(this, key, combiner, existingEquation.source.get(), key, combiner, data.get()));
                // Somewhat of a cheat, since we didn't really add it. OTOH, a paste operation should not be followed by edit mode.
                return existingEquation;
            }
        }
        // Determine index for new equation
        int index = 0;
        NodeBase child = (NodeBase) tree.getLastSelectedPathComponent();
        if (child != null && child.getParent() == this)
            index = getIndex(child);
        while (index > 0 && !(getChildAt(index) instanceof NodeEquation)) index--;
        if (index < getChildCount() && getChildAt(index) instanceof NodeEquation)
            index++;
        // Create an AddEquation action
        AddEquation ae = new AddEquation(this, index, data);
        PanelModel.instance.undoManager.add(ae);
        return ae.createdNode;
    } else if (type.equals("Annotation")) {
        // Determine index at which to insert new annotation
        int index = 0;
        int count = getChildCount();
        while (index < count && !(children.get(index) instanceof NodeReference)) index++;
        AddAnnotation aa = new AddAnnotation(this, index, data);
        PanelModel.instance.undoManager.add(aa);
        return aa.createdNode;
    } else if (type.equals("Reference")) {
        AddReference ar = new AddReference(this, getChildCount(), data);
        PanelModel.instance.undoManager.add(ar);
        return ar.createdNode;
    }
    // refer all other requests up the tree
    return ((NodeBase) getParent()).add(type, tree, data);
}
Also used : Variable(gov.sandia.n2a.eqset.Variable) ChangeVariable(gov.sandia.n2a.ui.eq.undo.ChangeVariable) DeleteVariable(gov.sandia.n2a.ui.eq.undo.DeleteVariable) AddReference(gov.sandia.n2a.ui.eq.undo.AddReference) AddEquation(gov.sandia.n2a.ui.eq.undo.AddEquation) ChangeEquation(gov.sandia.n2a.ui.eq.undo.ChangeEquation) AddAnnotation(gov.sandia.n2a.ui.eq.undo.AddAnnotation) TreePath(javax.swing.tree.TreePath) FilteredTreeModel(gov.sandia.n2a.ui.eq.FilteredTreeModel)

Example 3 with Variable

use of gov.sandia.n2a.eqset.Variable in project n2a by frothga.

the class JobC method generateStatic.

public void generateStatic(final EquationSet s, final StringBuilder result) {
    for (EquationSet p : s.parts) generateStatic(p, result);
    // Generate static definitions
    final BackendDataC bed = (BackendDataC) s.backendData;
    class CheckStatic extends Visitor {

        public boolean global;

        public boolean visit(Operator op) {
            if (op instanceof Constant) {
                Type m = ((Constant) op).value;
                if (m instanceof Matrix) {
                    Matrix A = (Matrix) m;
                    int rows = A.rows();
                    int cols = A.columns();
                    String matrixName = "Matrix" + matrixNames.size();
                    matrixNames.put(op, matrixName);
                    if (rows == 3 && cols == 1)
                        result.append("Vector3 " + matrixName + " = Matrix<float>");
                    else
                        result.append("Matrix<float> " + matrixName);
                    result.append(" (\"" + A + "\");\n");
                }
                // Don't try to descend tree from here
                return false;
            }
            if (op instanceof Function) {
                Function f = (Function) op;
                if (// We need to auto-generate the column name.
                f instanceof Output && f.operands.length < 3) {
                    String stringName = "columnName" + stringNames.size();
                    stringNames.put(op, stringName);
                    if (global) {
                        bed.setGlobalNeedPath(s);
                        bed.globalColumns.add(stringName);
                    } else {
                        bed.setLocalNeedPath(s);
                        bed.localColumns.add(stringName);
                    }
                }
                // Detect functions that need static handles
                if (f.operands.length > 0) {
                    Operator operand0 = f.operands[0];
                    if (operand0 instanceof Constant) {
                        Constant c = (Constant) operand0;
                        Type o = c.value;
                        if (o instanceof Text) {
                            String fileName = ((Text) o).value;
                            if (op instanceof ReadMatrix) {
                                if (!matrixNames.containsKey(fileName)) {
                                    String matrixName = "Matrix" + matrixNames.size();
                                    matrixNames.put(fileName, matrixName);
                                    result.append("MatrixInput * " + matrixName + " = matrixHelper (\"" + fileName + "\");\n");
                                }
                            } else if (f instanceof Input) {
                                if (!inputNames.containsKey(fileName)) {
                                    String inputName = "Input" + inputNames.size();
                                    inputNames.put(fileName, inputName);
                                    result.append("InputHolder * " + inputName + " = inputHelper (\"" + fileName + "\");\n");
                                }
                            } else if (f instanceof Output) {
                                if (!outputNames.containsKey(fileName)) {
                                    String outputName = "Output" + outputNames.size();
                                    outputNames.put(fileName, outputName);
                                    result.append("OutputHolder * " + outputName + " = outputHelper (\"" + fileName + "\");\n");
                                }
                            }
                        }
                    } else // Dynamic file name (no static handle)
                    {
                        if (f instanceof ReadMatrix) {
                            matrixNames.put(op, "Matrix" + matrixNames.size());
                            stringNames.put(operand0, "fileName" + stringNames.size());
                        } else if (f instanceof Input) {
                            inputNames.put(op, "Input" + inputNames.size());
                            stringNames.put(operand0, "fileName" + stringNames.size());
                        } else if (f instanceof Output) {
                            outputNames.put(op, "Output" + outputNames.size());
                            stringNames.put(operand0, "fileName" + stringNames.size());
                        }
                    }
                }
                // Functions could be nested, so continue descent.
                return true;
            }
            return true;
        }
    }
    CheckStatic checkStatic = new CheckStatic();
    for (Variable v : s.ordered) {
        checkStatic.global = v.hasAttribute("global");
        v.visit(checkStatic);
    }
}
Also used : Operator(gov.sandia.n2a.language.Operator) EquationSet(gov.sandia.n2a.eqset.EquationSet) Variable(gov.sandia.n2a.eqset.Variable) AccessVariable(gov.sandia.n2a.language.AccessVariable) Visitor(gov.sandia.n2a.language.Visitor) Constant(gov.sandia.n2a.language.Constant) Text(gov.sandia.n2a.language.type.Text) ReadMatrix(gov.sandia.n2a.language.function.ReadMatrix) Function(gov.sandia.n2a.language.Function) Type(gov.sandia.n2a.language.Type) Input(gov.sandia.n2a.language.function.Input) ReadMatrix(gov.sandia.n2a.language.function.ReadMatrix) BuildMatrix(gov.sandia.n2a.language.BuildMatrix) Matrix(gov.sandia.n2a.language.type.Matrix) Output(gov.sandia.n2a.language.function.Output)

Example 4 with Variable

use of gov.sandia.n2a.eqset.Variable in project n2a by frothga.

the class InternalBackendData method analyzeEvents.

public static void analyzeEvents(final EquationSet s, final List<EventTarget> eventTargets, final List<Variable> eventReferences) {
    class EventVisitor extends Visitor {

        public boolean found;

        public boolean visit(Operator op) {
            if (op instanceof Event) {
                found = true;
                Event de = (Event) op;
                if (// this event has not yet been analyzed
                de.eventType == null) {
                    final EventTarget et = new EventTarget(de);
                    int targetIndex = eventTargets.indexOf(et);
                    if (// event target already exists
                    targetIndex >= 0) {
                        de.eventType = eventTargets.get(targetIndex);
                    } else // we must create a new event target, or more properly, fill in the event target we just used as a query object
                    {
                        // Create an entry and save the index
                        targetIndex = eventTargets.size();
                        eventTargets.add(et);
                        de.eventType = et;
                        et.container = s;
                        // Determine edge type
                        if (de.operands.length < 3) {
                            et.edge = EventTarget.RISE;
                        } else if (de.operands[2] instanceof Constant) {
                            Constant c = (Constant) de.operands[2];
                            if (c.value instanceof Text) {
                                Text t = (Text) c.value;
                                if (t.value.equalsIgnoreCase("nonzero"))
                                    et.edge = EventTarget.NONZERO;
                                else if (t.value.equalsIgnoreCase("change"))
                                    et.edge = EventTarget.CHANGE;
                                else if (t.value.equalsIgnoreCase("fall"))
                                    et.edge = EventTarget.FALL;
                                else
                                    et.edge = EventTarget.RISE;
                            } else {
                                Backend.err.get().println("ERROR: event() edge type must be a string.");
                                throw new Backend.AbortRun();
                            }
                        } else {
                            Backend.err.get().println("ERROR: event() edge type must be constant.");
                            throw new Backend.AbortRun();
                        }
                        // Allocate auxiliary variable
                        if (de.operands[0] instanceof AccessVariable) {
                            AccessVariable av = (AccessVariable) de.operands[0];
                            VariableReference reference = av.reference;
                            Variable v = reference.variable;
                            // then the user has broken the rule that we can't see temporaries in other parts.
                            if (v.hasAttribute("temporary") && v.container != s) {
                                Backend.err.get().println("WARNING: Cannot be temporary due to event monitor: " + v.container.name + "." + v.nameString() + " from " + s.name);
                                v.removeAttribute("temporary");
                            }
                            // so fall through to the !trackOne case below.
                            if (!v.hasAttribute("temporary")) {
                                // ensure it's buffered, so we can detect change
                                v.addAttribute("externalRead");
                                et.trackOne = true;
                                // just a holder for the reference
                                et.track = new Variable();
                                et.track.reference = reference;
                            }
                        }
                        if (// Expression, so create auxiliary variable. Aux not needed for NONZERO, because no change detection.
                        !et.trackOne && et.edge != EventTarget.NONZERO) {
                            et.track = new Variable("eventAux" + targetIndex, 0);
                            et.track.type = new Scalar(0);
                            et.track.reference = new VariableReference();
                            et.track.reference.variable = et.track;
                        }
                        // Locate any temporaries for evaluation. TODO: for more efficiency, we could have separate lists of temporaries for the condition and delay operands
                        // Tie into the dependency graph using a phantom variable (which can go away afterward without damaging the graph).
                        final Variable phantom = new Variable("event");
                        phantom.uses = new IdentityHashMap<Variable, Integer>();
                        for (int i = 0; i < et.event.operands.length; i++) et.event.operands[i].visit(new Visitor() {

                            public boolean visit(Operator op) {
                                if (op instanceof AccessVariable) {
                                    AccessVariable av = (AccessVariable) op;
                                    Variable v = av.reference.variable;
                                    if (!phantom.uses.containsKey(v))
                                        phantom.uses.put(v, 1);
                                    return false;
                                }
                                return true;
                            }
                        });
                        // Scan all variables in equation set to see if we need them
                        for (Variable t : s.variables) {
                            if (t.hasAttribute("temporary") && phantom.dependsOn(t) != null)
                                et.dependencies.add(t);
                        }
                        // Note the default is already set to -1 (no care)
                        class DelayVisitor extends Visitor {

                            TreeSet<EquationSet> containers = new TreeSet<EquationSet>();

                            public boolean visit(Operator op) {
                                if (op instanceof AccessVariable) {
                                    AccessVariable av = (AccessVariable) op;
                                    // could include the target part itself, if in fact we use local variables
                                    containers.add(av.reference.variable.container);
                                    return false;
                                }
                                return true;
                            }
                        }
                        DelayVisitor dv = new DelayVisitor();
                        if (de.operands.length >= 2) {
                            if (de.operands[1] instanceof Constant) {
                                Constant c = (Constant) de.operands[1];
                                et.delay = (float) ((Scalar) c.value).value;
                                if (et.delay < 0)
                                    et.delay = -1;
                            } else {
                                // indicates that we need to evaluate delay at run time
                                et.delay = -2;
                                de.operands[1].visit(dv);
                            }
                        }
                        // Set up monitors in source parts
                        class ConditionVisitor extends Visitor {

                            TreeSet<EquationSet> containers = new TreeSet<EquationSet>();

                            public boolean visit(Operator op) {
                                if (op instanceof AccessVariable) {
                                    AccessVariable av = (AccessVariable) op;
                                    Variable v = av.reference.variable;
                                    EquationSet sourceContainer = v.container;
                                    containers.add(sourceContainer);
                                    // Set up monitors for values that can vary during update.
                                    if (!v.hasAttribute("constant") && !v.hasAttribute("initOnly") && !et.monitors(sourceContainer)) {
                                        EventSource es = new EventSource(sourceContainer, et);
                                        // null means self-reference, a special case handled in Part
                                        if (sourceContainer != s)
                                            es.reference = av.reference;
                                        et.sources.add(es);
                                    }
                                    return false;
                                }
                                return true;
                            }
                        }
                        ConditionVisitor cv = new ConditionVisitor();
                        de.operands[0].visit(cv);
                        // Special case for event with no references that vary
                        if (et.sources.isEmpty()) {
                            // We can avoid creating a self monitor if we know for certain that the event will never fire
                            boolean neverFires = false;
                            if (de.operands[0] instanceof Constant) {
                                if (et.edge == EventTarget.NONZERO) {
                                    Type op0 = ((Constant) de.operands[0]).value;
                                    if (op0 instanceof Scalar) {
                                        neverFires = ((Scalar) op0).value == 0;
                                    } else {
                                        Backend.err.get().println("ERROR: Condition for event() must resolve to a number.");
                                        throw new Backend.AbortRun();
                                    }
                                } else {
                                    neverFires = true;
                                }
                            }
                            if (!neverFires) {
                                EventSource es = new EventSource(s, et);
                                // This is a self-reference, so es.reference should be null.
                                et.sources.add(es);
                            }
                        }
                        // Determine if monitor needs to test every target, or if one representative target is sufficient
                        for (EventSource source : et.sources) {
                            // associated with any given source instance, so every target must be evaluated separately.
                            if (cv.containers.size() > 1)
                                source.testEach = true;
                            if (dv.containers.size() > 1 || (dv.containers.size() == 1 && dv.containers.first() != source.container))
                                source.delayEach = true;
                        }
                    }
                }
            }
            return true;
        }
    }
    EventVisitor eventVisitor = new EventVisitor();
    for (Variable v : s.variables) {
        eventVisitor.found = false;
        v.visit(eventVisitor);
        if ((eventVisitor.found || v.dependsOnEvent()) && v.reference.variable != v)
            eventReferences.add(v);
    }
}
Also used : Operator(gov.sandia.n2a.language.Operator) AccessVariable(gov.sandia.n2a.language.AccessVariable) Variable(gov.sandia.n2a.eqset.Variable) Visitor(gov.sandia.n2a.language.Visitor) Constant(gov.sandia.n2a.language.Constant) Scalar(gov.sandia.n2a.language.type.Scalar) TreeSet(java.util.TreeSet) EquationSet(gov.sandia.n2a.eqset.EquationSet) AccessVariable(gov.sandia.n2a.language.AccessVariable) VariableReference(gov.sandia.n2a.eqset.VariableReference) Text(gov.sandia.n2a.language.type.Text) Backend(gov.sandia.n2a.plugins.extpoints.Backend) Type(gov.sandia.n2a.language.Type) Event(gov.sandia.n2a.language.function.Event)

Example 5 with Variable

use of gov.sandia.n2a.eqset.Variable 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)

Aggregations

Variable (gov.sandia.n2a.eqset.Variable)63 AccessVariable (gov.sandia.n2a.language.AccessVariable)38 EquationSet (gov.sandia.n2a.eqset.EquationSet)25 EquationEntry (gov.sandia.n2a.eqset.EquationEntry)20 Scalar (gov.sandia.n2a.language.type.Scalar)18 Operator (gov.sandia.n2a.language.Operator)17 ArrayList (java.util.ArrayList)17 Type (gov.sandia.n2a.language.Type)12 Visitor (gov.sandia.n2a.language.Visitor)12 ConnectionBinding (gov.sandia.n2a.eqset.EquationSet.ConnectionBinding)11 MNode (gov.sandia.n2a.db.MNode)9 VariableReference (gov.sandia.n2a.eqset.VariableReference)9 Constant (gov.sandia.n2a.language.Constant)9 MPart (gov.sandia.n2a.eqset.MPart)7 EventTarget (gov.sandia.n2a.backend.internal.InternalBackendData.EventTarget)6 Output (gov.sandia.n2a.language.function.Output)6 FilteredTreeModel (gov.sandia.n2a.ui.eq.FilteredTreeModel)6 List (java.util.List)6 IncommensurableException (javax.measure.IncommensurableException)6 UnconvertibleException (javax.measure.UnconvertibleException)6