use of gov.sandia.n2a.ui.eq.PanelEquationTree in project n2a by frothga.
the class ChangeAnnotation method apply.
public void apply(String nameBefore, String nameAfter, String prefixBefore) {
NodeContainer parent = (NodeContainer) NodeBase.locateNode(path);
if (parent == null)
throw new CannotRedoException();
MPart mparent = parent.source;
if (parent instanceof NodeVariable)
mparent = (MPart) mparent.child("$metadata");
// Update database
String[] names = nameAfter.split("\\.");
if (nameAfter.equals(nameBefore)) {
// If name is unchanged, then node should already exist,
// and we only need to change the direct value, not the subtree.
String valueBefore = mparent.get(names);
String valueAfter = savedTree.get();
MPart partBefore = (MPart) mparent.child(names);
MPart partAfter = (MPart) mparent.set(valueAfter, names);
// If there was no change in value, then toggle override state.
if (partBefore != null && valueAfter.equals(valueBefore)) {
if (partAfter.isOverridden())
partAfter.clearPath();
else
partAfter.override();
}
} else {
if (!prefixBefore.isEmpty()) {
String[] prefixes = prefixBefore.split("\\.");
mparent.clear(prefixes);
}
MPart partAfter = (MPart) mparent.childOrCreate(names);
if (valueBeforeRebase == null)
valueBeforeRebase = partAfter.get();
// saveTree may have children, or it might be a simple value with no children.
partAfter.merge(savedTree);
}
// Update GUI
PanelEquationTree pet = parent.getTree();
FilteredTreeModel model = null;
if (pet != null)
model = (FilteredTreeModel) pet.tree.getModel();
List<String> expanded = null;
if (model != null)
expanded = AddAnnotation.saveExpandedNodes(pet.tree, parent);
parent.build();
parent.filter();
if (model != null && parent.visible()) {
model.nodeStructureChanged(parent);
AddAnnotation.restoreExpandedNodes(pet.tree, parent, expanded);
}
NodeBase nodeAfter = AddAnnotation.findClosest(parent, names);
if (pet != null) {
TreeNode[] afterPath = nodeAfter.getPath();
TreeNode[] parentPath = parent.getPath();
if (selectVariable)
pet.updateVisibility(parentPath, -2, !multi);
else
pet.updateVisibility(afterPath, -2, !multi);
if (multi) {
if (// Assumes nodeAfter is directly under a NodeVariable.
selectVariable)
// Assumes nodeAfter is directly under a NodeVariable.
pet.tree.addSelectionPath(new TreePath(parentPath));
else
pet.tree.addSelectionPath(new TreePath(afterPath));
}
pet.animate();
}
AddAnnotation.update(parent, touchesPin, touchesCategory);
}
use of gov.sandia.n2a.ui.eq.PanelEquationTree in project n2a by frothga.
the class ChangeEquation method apply.
public void apply(String nameBefore, String nameAfter, String combinerAfter, String valueAfter, boolean multi, boolean multiLast) {
NodeBase parent = NodeBase.locateNode(path);
if (parent == null)
throw new CannotRedoException();
NodeBase nodeBefore = parent.child(nameBefore);
if (nodeBefore == null)
throw new CannotRedoException();
PanelEquationTree pet = parent.getTree();
FilteredTreeModel model = (FilteredTreeModel) pet.tree.getModel();
NodeBase nodeAfter;
if (nameBefore.equals(nameAfter)) {
nodeAfter = nodeBefore;
nodeAfter.source.set(valueAfter);
} else {
// Update the database
MPart mparent = parent.source;
MPart newPart = (MPart) mparent.set(valueAfter, nameAfter);
mparent.clear(nameBefore);
MPart oldPart = (MPart) mparent.child(nameBefore);
// Update GUI
nodeAfter = parent.child(nameAfter);
if (oldPart == null) {
if (nodeAfter == null) {
nodeAfter = nodeBefore;
nodeAfter.source = newPart;
} else {
model.removeNodeFromParent(nodeBefore);
}
} else {
if (nodeAfter == null) {
int index = parent.getIndex(nodeBefore);
nodeAfter = new NodeEquation(newPart);
model.insertNodeIntoUnfiltered(nodeAfter, parent, index);
}
if (nodeBefore.visible())
model.nodeChanged(nodeBefore);
else
parent.hide(nodeBefore, model);
}
}
if (!parent.source.get().equals(combinerAfter)) {
parent.source.set(combinerAfter);
parent.setUserObject();
NodeBase grandparent = (NodeBase) parent.getParent();
grandparent.invalidateColumns(model);
}
nodeAfter.setUserObject();
parent.invalidateColumns(null);
TreeNode[] afterPath = nodeAfter.getPath();
boolean killed = valueAfter.isEmpty();
boolean setSelection;
if (// Revoke, which hides the node, so like delete.
killed)
// Revoke, which hides the node, so like delete.
setSelection = !multi || multiLast;
else
setSelection = !multi;
pet.updateVisibility(afterPath, -2, setSelection);
if (multi && !killed)
pet.tree.addSelectionPath(new TreePath(afterPath));
parent.allNodesChanged(model);
pet.animate();
}
use of gov.sandia.n2a.ui.eq.PanelEquationTree 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);
}
}
use of gov.sandia.n2a.ui.eq.PanelEquationTree in project n2a by frothga.
the class CompoundEditView method selectLead.
public void selectLead() {
if (leadPath == null)
return;
NodeBase n = NodeBase.locateNode(leadPath);
if (n == null)
return;
if (clearSelection == CLEAR_GRAPH) {
// CLEAR_GRAPH should only be used for compound operations on parts, so this should be a safe cast.
NodePart p = (NodePart) n;
if (p.graph != null) {
p.graph.takeFocusOnTitle();
return;
}
}
// Otherwise, assume this is a compound operation on tree nodes.
PanelEquationTree pet = n.getTree();
if (pet != null)
pet.tree.setLeadSelectionPath(new TreePath(n.getPath()));
}
use of gov.sandia.n2a.ui.eq.PanelEquationTree in project n2a by frothga.
the class ChangeInherit method apply.
public void apply(String value) {
NodeBase node = NodeBase.locateNode(path);
if (node == null)
throw new CannotRedoException();
NodePart parent = (NodePart) node.getParent();
NodePart grandparent = (NodePart) parent.getTrueParent();
PanelEquations pe = PanelModel.instance.panelEquations;
PanelEquationTree pet = node.getTree();
FilteredTreeModel model = (FilteredTreeModel) pet.tree.getModel();
PanelEquationGraph peg = pe.panelEquationGraph;
// Complex restructuring happens here.
node.source.set(value);
parent.build();
if (grandparent == null)
parent.findConnections();
else
grandparent.findConnections();
parent.rebuildPins();
parent.filter();
if (parent == pe.part) {
peg.reloadPart();
// Ensure that parts are not visible in parent panel.
parent.filter();
}
model.nodeStructureChanged(parent);
TreeNode[] nodePath = parent.child("$inherit").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();
}
}
Aggregations