use of gov.sandia.n2a.ui.eq.FilteredTreeModel 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.FilteredTreeModel 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.FilteredTreeModel 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.FilteredTreeModel 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.FilteredTreeModel 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