use of gov.sandia.n2a.ui.eq.tree.NodePart in project n2a by frothga.
the class AddReference method destroy.
public static void destroy(List<String> path, boolean canceled, String name, boolean setSelection) {
// Retrieve created node
NodeBase parent = NodeBase.locateNode(path);
if (parent == null)
throw new CannotUndoException();
NodeBase container = parent;
if (parent instanceof NodePart)
container = parent.child("$reference");
NodeBase createdNode = container.child(name);
PanelEquationTree pet = parent.getTree();
FilteredTreeModel model = (FilteredTreeModel) pet.tree.getModel();
boolean containerIsVisible = true;
TreeNode[] createdPath = createdNode.getPath();
int index = container.getIndexFiltered(createdNode);
if (canceled)
index--;
MPart block = (MPart) parent.source.child("$reference");
block.clear(name);
if (// There is no overridden value, so this node goes away completely.
block.child(name) == null) {
model.removeNodeFromParent(createdNode);
if (block.size() == 0) {
// commit suicide
parent.source.clear("$reference");
if (parent instanceof NodePart) {
model.removeNodeFromParent(container);
pet.updateOrder(createdPath);
// No need to update tab stops in grandparent, because block nodes don't offer any tab stops.
containerIsVisible = false;
}
}
} else // Just exposed an overridden value, so update display.
{
if (// We are always visible, but our parent could disappear.
container.visible()) {
createdNode.setUserObject();
} else {
containerIsVisible = false;
}
}
if (containerIsVisible)
container.invalidateColumns(null);
pet.updateVisibility(createdPath, index, setSelection);
if (containerIsVisible)
container.allNodesChanged(model);
pet.animate();
}
use of gov.sandia.n2a.ui.eq.tree.NodePart in project n2a by frothga.
the class AddVariable method destroy.
public static void destroy(List<String> path, boolean canceled, String name, boolean setSelection) {
// Retrieve created node
NodePart parent = (NodePart) NodeBase.locateNode(path);
if (parent == null)
throw new CannotUndoException();
NodeVariable createdNode = (NodeVariable) parent.child(name);
PanelEquationTree pet = parent.getTree();
FilteredTreeModel model = null;
if (pet != null)
model = (FilteredTreeModel) pet.tree.getModel();
TreeNode[] createdPath = createdNode.getPath();
int index = parent.getIndexFiltered(createdNode);
if (canceled)
index--;
MPart mparent = parent.source;
mparent.clear(name);
if (// Node is fully deleted
mparent.child(name) == null) {
if (createdNode.isBinding) {
if (parent.graph != null)
parent.graph.killEdge(name);
if (mparent.root() == mparent)
PanelModel.instance.panelSearch.updateConnectors(mparent);
}
if (model == null)
FilteredTreeModel.removeNodeFromParentStatic(createdNode);
else
model.removeNodeFromParent(createdNode);
parent.findConnections();
} else // Just exposed an overridden node
{
boolean wasBinding = createdNode.isBinding;
createdNode.build();
createdNode.findConnections();
createdNode.filter();
if (createdNode.isBinding != wasBinding) {
parent.updateSubpartConnections();
if (parent.graph != null) {
if (createdNode.isBinding)
parent.graph.updateEdge(name, parent.connectionBindings.get(name));
else
parent.graph.killEdge(name);
}
if (mparent.root() == mparent)
PanelModel.instance.panelSearch.updateConnectors(mparent);
}
}
// Actually, this could start at grandparent, because parent's pin structure hasn't changed. However, this is convenient and simple.
parent.updatePins();
if (pet != null) {
parent.invalidateColumns(model);
pet.updateOrder(createdPath);
// includes nodeStructureChanged(), if necessary
pet.updateVisibility(createdPath, index, setSelection);
pet.animate();
}
}
use of gov.sandia.n2a.ui.eq.tree.NodePart in project n2a by frothga.
the class AddVariable method create.
public static NodeBase create(List<String> path, int index, String name, MNode newPart, boolean nameIsGenerated, boolean multi) {
NodePart parent = (NodePart) NodeBase.locateNode(path);
if (parent == null)
throw new CannotRedoException();
NodeBase n = parent.child(name);
// Should be blocked by GUI constraints, but this defends against ill-formed model on clipboard.
if (n != null && !(n instanceof NodeVariable))
throw new CannotRedoException();
NodeVariable createdNode = (NodeVariable) n;
// Update database
MPart createdPart = (MPart) parent.source.childOrCreate(name);
createdPart.merge(newPart);
// Update GUI
PanelEquationTree pet = parent.getTree();
FilteredTreeModel model = null;
if (pet != null)
model = (FilteredTreeModel) pet.tree.getModel();
boolean alreadyExists = createdNode != null;
boolean wasBinding = alreadyExists && createdNode.isBinding;
if (!alreadyExists)
createdNode = new NodeVariable(createdPart);
// pure create, so about to go into edit mode. This should only happen on first application of the create action, and should only be possible if visibility is already correct.
if (nameIsGenerated)
createdNode.setUserObject("");
if (!alreadyExists) {
if (model == null)
FilteredTreeModel.insertNodeIntoUnfilteredStatic(createdNode, parent, index);
else
model.insertNodeIntoUnfiltered(createdNode, parent, index);
}
TreeNode[] createdPath = createdNode.getPath();
if (!nameIsGenerated) {
createdNode.build();
createdNode.filter();
if (pet != null) {
pet.updateOrder(createdPath);
parent.invalidateColumns(model);
}
if (parent.updateVariableConnections())
parent.updateSubpartConnections();
if (createdNode.isBinding != wasBinding) {
if (parent.graph != null) {
if (createdNode.isBinding)
parent.graph.updateEdge(name, parent.connectionBindings.get(name));
else
parent.graph.killEdge(name);
}
MPart mparent = parent.source;
if (mparent.root() == mparent)
PanelModel.instance.panelSearch.updateConnectors(mparent);
}
parent.updatePins();
}
if (pet != null) {
pet.updateVisibility(createdPath, -2, !multi);
if (multi)
pet.tree.addSelectionPath(new TreePath(createdPath));
pet.animate();
}
return createdNode;
}
use of gov.sandia.n2a.ui.eq.tree.NodePart in project n2a by frothga.
the class AddPart method create.
public static NodeBase create(List<String> path, int index, String name, MNode newPart, boolean nameIsGenerated, boolean multi, boolean multiLast, boolean multiShared, boolean touchesPin) {
NodePart parent = (NodePart) NodeBase.locateNode(path);
if (parent == null)
throw new CannotRedoException();
NodeBase n = parent.child(name);
// Should be blocked by GUI constraints, but this defends against ill-formed model on clipboard.
if (n != null && !(n instanceof NodePart))
throw new CannotUndoException();
NodePart createdNode = (NodePart) n;
// Update database
MPart createdPart = (MPart) parent.source.childOrCreate(name);
createdPart.merge(newPart);
// Update GUI
PanelEquations pe = PanelModel.instance.panelEquations;
boolean graphParent = parent == pe.part;
PanelEquationTree pet = graphParent ? null : parent.getTree();
FilteredTreeModel model = null;
if (pet != null)
model = (FilteredTreeModel) pet.tree.getModel();
PanelEquationGraph peg = pe.panelEquationGraph;
boolean addGraphNode = false;
if (createdNode == null) {
addGraphNode = true;
createdNode = new NodePart(createdPart);
createdNode.hide = graphParent;
if (index < 0)
index = parent.getChildCount();
if (model == null)
FilteredTreeModel.insertNodeIntoUnfilteredStatic(createdNode, parent, index);
else
model.insertNodeIntoUnfiltered(createdNode, parent, index);
}
createdNode.build();
// Other nodes besides immediate siblings can also refer to us, so to be strictly correct, should run findConnectins() on root of tree.
parent.findConnections();
createdNode.rebuildPins();
createdNode.filter();
// pure create, so about to go into edit mode. This should only happen on first application of the create action, and should only be possible if visibility is already correct.
if (nameIsGenerated)
createdNode.setUserObject("");
TreeNode[] createdPath = createdNode.getPath();
if (pet == null) {
if (!nameIsGenerated)
PanelEquationTree.updateOrder(null, createdPath);
PanelEquationTree.updateVisibility(null, createdPath, -2, false);
} else {
if (!nameIsGenerated)
pet.updateOrder(createdPath);
pet.updateVisibility(createdPath, -2, !multi);
if (multi)
pet.tree.addSelectionPath(new TreePath(createdPath));
pet.animate();
}
if (graphParent) {
if (addGraphNode) {
peg.addPart(createdNode);
} else // Existing graph node; content needs to be restructured.
{
PanelEquationTree subpet = createdNode.getTree();
if (subpet != null) {
FilteredTreeModel submodel = (FilteredTreeModel) subpet.tree.getModel();
submodel.nodeStructureChanged(createdNode);
subpet.animate();
}
}
createdNode.hide = false;
if (multi) {
if (!multiShared)
createdNode.graph.setSelected(true);
} else {
peg.clearSelection();
createdNode.graph.takeFocusOnTitle();
}
}
if (graphParent || touchesPin) {
if (!multi || multiLast) {
peg.updatePins();
peg.reconnect();
peg.repaint();
}
}
return createdNode;
}
use of gov.sandia.n2a.ui.eq.tree.NodePart in project n2a by frothga.
the class ChangeVariable method apply.
public void apply(String nameBefore, String nameAfter, boolean multi, boolean multiLast) {
NodePart parent = (NodePart) NodeBase.locateNode(path);
if (parent == null)
throw new CannotRedoException();
NodeVariable nodeBefore = (NodeVariable) parent.child(nameBefore);
if (nodeBefore == null)
throw new CannotRedoException();
PanelEquations pe = PanelModel.instance.panelEquations;
PanelEquationTree pet = parent.getTree();
FilteredTreeModel model = null;
if (pet != null)
model = (FilteredTreeModel) pet.tree.getModel();
NodeVariable nodeAfter;
boolean touchedBindings = false;
// Key paths to each variable that references this one.
List<List<String>> references = new ArrayList<List<String>>();
if (nameBefore.equals(nameAfter)) {
nodeAfter = nodeBefore;
// Same as valueAfter. Sub-tree is not relevant here.
nodeAfter.source.set(savedTree.get());
} else {
// Update database
// Move the subtree
MPart mparent = parent.source;
mparent.clear(nameBefore);
// Removes any reference changes in target node.
mparent.clear(nameAfter);
mparent.set(savedTree, nameAfter);
MPart newPart = (MPart) mparent.child(nameAfter);
MPart oldPart = (MPart) mparent.child(nameBefore);
// See ChangePart.apply() for a similar procedure.
try {
// "doc" is a collated model, so changes will also be made to references from inherited nodes.
// Such changes will be saved as an override.
MPart doc = pe.root.source;
// TODO: this is a potentially lengthy operation. For very large models, need to reduce load on EDT. Either maintain incremental compilation, or compile on separate thread.
EquationSet compiled = new EquationSet(doc);
compiled.name = doc.key();
List<String> vkeypath = new ArrayList<String>(path.subList(1, path.size()));
Variable vold;
Variable vnew;
if (oldPart == null) {
EquationSet p = (EquationSet) compiled.getObject(vkeypath);
vold = Variable.fromLHS(nameBefore);
vold.equations = new TreeSet<EquationEntry>();
if (nodeBefore.isBinding)
vold.equations.add(new EquationEntry(newPart.get()));
p.add(vold);
vkeypath.add(Variable.stripContextPrefix(nameAfter));
} else {
vkeypath.add(Variable.stripContextPrefix(nameBefore));
vold = (Variable) compiled.getObject(vkeypath);
vkeypath.set(vkeypath.size() - 1, nameAfter);
}
vnew = (Variable) compiled.getObject(vkeypath);
try {
// This will throw an AbortRun if any connection is not properly bound.
// However, not every connection binding necessarily leads to this variable.
compiled.resolveConnectionBindings();
} catch (Exception e) {
}
try {
compiled.resolveLHS();
} catch (Exception e) {
}
try {
// This will very likely throw an AbortRun exception to report unresolved variables.
// This will do no harm. All we need is that other equations resolve to this variable.
compiled.resolveRHS();
} catch (Exception e) {
}
prepareConnections(compiled);
List<Variable> users = new ArrayList<Variable>();
if (vold.usedBy != null) {
for (Object o : vold.usedBy) {
if (!(o instanceof Variable))
continue;
// On undo, don't touch savedTree or exposed node. They should return to their exact previous values.
if ((o == vnew || o == vold) && nameAfter.equals(this.nameBefore))
continue;
users.add((Variable) o);
}
}
// This kind of relationship is not generally reciprocal, so we must check uses as well as usedBy.
if (vold.uses != null) {
for (Variable v : vold.uses.keySet()) {
if (v.reference.variable == vold)
users.add(v);
}
}
vold.name = vnew.name;
vold.order = vnew.order;
for (Variable v : users) {
// Don't modify expression on variable line itself. Instead, assume the user edited it exactly as intended.
if (v == vnew && v.equations.size() == 1)
continue;
List<String> ref = v.getKeyPath();
MNode n = doc.child(ref.toArray());
String oldKey = n.key();
String newKey = changeReferences(vold, 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 != vnew && v != vold)
references.add(ref);
}
} catch (Exception e) {
}
// Update GUI
nodeAfter = (NodeVariable) parent.child(nameAfter);
if (oldPart == null) {
if (nodeBefore.isBinding) {
if (parent.graph != null)
parent.connectionBindings.remove(nameBefore);
touchedBindings = true;
}
if (nodeAfter == null) {
nodeAfter = nodeBefore;
nodeAfter.source = newPart;
} else {
if (model == null)
FilteredTreeModel.removeNodeFromParentStatic(nodeBefore);
else
model.removeNodeFromParent(nodeBefore);
}
} else {
if (nodeAfter == null) {
int index = parent.getIndex(nodeBefore);
nodeAfter = new NodeVariable(newPart);
if (model == null)
FilteredTreeModel.insertNodeIntoUnfilteredStatic(nodeAfter, parent, index);
else
model.insertNodeIntoUnfiltered(nodeAfter, parent, index);
}
nodeBefore.build();
nodeBefore.filter();
if (nodeBefore.visible()) {
if (model != null)
model.nodeStructureChanged(nodeBefore);
} else {
parent.hide(nodeBefore, model);
}
}
}
nodeAfter.build();
nodeAfter.filter();
Set<PanelEquationTree> needAnimate = new HashSet<PanelEquationTree>();
if (pet != null) {
needAnimate.add(pet);
// Must be done before invalidateColumns(), because that function causes new columns to be fetched for renderer sizing.
pet.updateHighlights(pet.root, nameAfter);
parent.invalidateColumns(model);
TreeNode[] nodePath = nodeAfter.getPath();
pet.updateOrder(nodePath);
boolean killed = savedTree.get().equals("$kill");
boolean setSelection;
if (killed)
setSelection = !multi || multiLast;
else
setSelection = !multi;
pet.updateVisibility(nodePath, -2, setSelection);
if (multi && !killed)
pet.tree.addSelectionPath(new TreePath(nodePath));
}
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();
boolean added = needAnimate.add(subpet);
if (added)
subpet.updateHighlights(subpet.root, nameAfter);
else
subpet.updateHighlights(n, nameAfter);
subparent.invalidateColumns(null);
// Node will collapse if it was open. Don't worry about this.
submodel.nodeStructureChanged(n);
subpet.updateVisibility(n.getPath(), -2, false);
subparent.allNodesChanged(submodel);
}
}
for (PanelEquationTree ap : needAnimate) ap.animate();
if (parent.updateVariableConnections())
touchedBindings = true;
if (touchedBindings) {
parent.updateSubpartConnections();
// Update edges to pins, if present.
PanelEquationGraph peg = pe.panelEquationGraph;
if (parent.source.child("$metadata", "gui", "pin") != null) {
parent.updatePins();
peg.updatePins();
}
// Rebuild all edges on canvas, whether regular connection or pin.
peg.reconnect();
peg.repaint();
MPart mparent = parent.source;
if (mparent.root() == mparent)
PanelModel.instance.panelSearch.updateConnectors(mparent);
}
}
Aggregations