use of gov.sandia.n2a.ui.eq.PanelEquationTree in project n2a by frothga.
the class AddAnnotation method create.
public static NodeBase create(List<String> path, int index, String name, String value, String blockName, NodeFactory factory, NodeFactory factoryBlock) {
NodeBase parent = NodeBase.locateNode(path);
if (parent == null)
throw new CannotRedoException();
MPart block = (MPart) parent.source.childOrCreate(blockName);
PanelEquationTree pet = PanelModel.instance.panelEquations;
JTree tree = pet.tree;
FilteredTreeModel model = (FilteredTreeModel) tree.getModel();
// If this is a variable, then mix metadata with equations and references
NodeBase container = parent;
if (// If this is a part, then display special block
parent instanceof NodePart) {
if (// empty implies the node is absent
block.size() == 0) {
container = factoryBlock.create(block);
model.insertNodeIntoUnfiltered(container, parent, index);
index = 0;
} else // the node is present, so retrieve it
{
container = parent.child(blockName);
}
}
NodeBase createdNode = container.child(name);
boolean alreadyExists = createdNode != null;
MPart createdPart = (MPart) block.set(name, value);
if (!alreadyExists)
createdNode = factory.create(createdPart);
FontMetrics fm = createdNode.getFontMetrics(tree);
if (container.getChildCount() > 0) {
NodeBase firstChild = (NodeBase) container.getChildAt(0);
if (firstChild.needsInitTabs())
firstChild.initTabs(fm);
}
// 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 (value == null)
createdNode.setUserObject("");
// preempt initialization; uses actual name, not user value
createdNode.updateColumnWidths(fm);
if (!alreadyExists)
model.insertNodeIntoUnfiltered(createdNode, container, index);
if (// create was merged with change name/value
value != null) {
container.updateTabStops(fm);
container.allNodesChanged(model);
TreeNode[] createdPath = createdNode.getPath();
pet.updateOrder(createdPath);
pet.updateVisibility(createdPath);
if (path.size() == 1 && name.equals("lock"))
pet.updateLock();
}
return createdNode;
}
use of gov.sandia.n2a.ui.eq.PanelEquationTree in project n2a by frothga.
the class ChangeAnnotation method apply.
public static void apply(List<String> path, String nameBefore, String nameAfter, String valueAfter, String blockName, NodeFactory factory) {
NodeBase parent = NodeBase.locateNode(path);
if (parent == null)
throw new CannotRedoException();
NodeBase nodeBefore = parent.child(nameBefore);
if (nodeBefore == null)
throw new CannotRedoException();
PanelEquationTree pet = PanelModel.instance.panelEquations;
JTree tree = pet.tree;
FilteredTreeModel model = (FilteredTreeModel) tree.getModel();
FontMetrics fm = nodeBefore.getFontMetrics(tree);
NodeBase nodeAfter;
if (nameBefore.equals(nameAfter)) {
nodeAfter = nodeBefore;
nodeAfter.source.set(valueAfter);
} else {
// Update database
MPart mparent;
if (parent instanceof NodeVariable)
mparent = (MPart) parent.source.child(blockName);
else
mparent = parent.source;
// should directly change destinationNode if it exists
MPart newPart = (MPart) mparent.set(nameAfter, valueAfter);
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 = factory.create(newPart);
model.insertNodeIntoUnfiltered(nodeAfter, parent, index);
}
}
}
nodeAfter.updateColumnWidths(fm);
parent.updateTabStops(fm);
parent.allNodesChanged(model);
TreeNode[] nodePath = nodeAfter.getPath();
pet.updateOrder(nodePath);
pet.updateVisibility(nodePath);
// Only an inherited lock node can be touched by editing. It is possible to activate (make local) if the user assigns a specific value to it.
if (path.size() == 2 && path.get(1).equals("$metadata") && (nameBefore.equals("lock") || nameAfter.equals("lock")))
pet.updateLock();
}
use of gov.sandia.n2a.ui.eq.PanelEquationTree 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();
}
}
use of gov.sandia.n2a.ui.eq.PanelEquationTree in project n2a by frothga.
the class ChangeReferences method apply.
public void apply(MNode add, MNode remove) {
NodeBase parent = NodeBase.locateNode(path);
if (parent == null)
throw new CannotUndoException();
PanelEquationTree pet = parent.getTree();
FilteredTreeModel model = null;
StoredPath sp = null;
if (pet != null) {
model = (FilteredTreeModel) pet.tree.getModel();
sp = new StoredPath(pet.tree);
}
// The immediate container of reference items in the tree.
NodeContainer referenceNode;
// The $reference node under which all changes are made.
MNode referenceSource = null;
if (parent instanceof NodeVariable) {
referenceNode = (NodeContainer) parent;
referenceSource = referenceNode.source.child("$reference");
} else // NodePart is the default case
{
referenceNode = (NodeContainer) parent.child("$reference");
if (referenceNode != null)
referenceSource = referenceNode.source;
}
boolean needBuild = true;
if (// This is an undo, and $reference did not exist before, so remove it.
add == null) {
// We can safely assume that referenceSource is non-null, since we only get here during an undo.
referenceSource.parent().clear("$reference");
if (parent instanceof NodePart) {
if (model == null)
FilteredTreeModel.removeNodeFromParentStatic(referenceNode);
else
model.removeNodeFromParent(referenceNode);
needBuild = false;
}
} else // Update $reference node. Create if it doesn't exist.
{
if (referenceSource == null)
referenceSource = parent.source.childOrCreate("$reference");
if (// only happens when parent is NodePart
referenceNode == null) {
referenceNode = new NodeReferences((MPart) referenceSource);
if (model == null)
FilteredTreeModel.insertNodeIntoUnfilteredStatic(referenceNode, parent, index);
else
model.insertNodeIntoUnfiltered(referenceNode, parent, index);
}
if (remove != null)
referenceSource.uniqueNodes(remove);
referenceSource.merge(add);
}
if (needBuild) {
referenceNode.build();
referenceNode.filter();
if (model != null && referenceNode.visible()) {
model.nodeStructureChanged(referenceNode);
}
}
PanelEquationTree.updateVisibility(pet, referenceNode.getPath(), -1, false);
// This forces focus back to original location.
if (!multi && sp != null)
sp.restore(pet.tree, true);
if (pet != null)
pet.animate();
}
use of gov.sandia.n2a.ui.eq.PanelEquationTree 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();
}
}
Aggregations