use of gov.sandia.n2a.ui.eq.tree.NodeEquation in project n2a by frothga.
the class ChangeEquation method apply.
public static void apply(List<String> path, String nameBefore, String nameAfter, String combinerAfter, String valueAfter) {
NodeBase parent = NodeBase.locateNode(path);
if (parent == null)
throw new CannotRedoException();
NodeBase nodeBefore = parent.child(nameBefore);
if (nodeBefore == null)
throw new CannotRedoException();
PanelModel mep = PanelModel.instance;
JTree tree = mep.panelEquations.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 the database
MPart mparent = parent.source;
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 = new NodeEquation(newPart);
model.insertNodeIntoUnfiltered(nodeAfter, parent, index);
}
if (nodeBefore.visible(model.filterLevel))
model.nodeChanged(nodeBefore);
else
parent.hide(nodeBefore, model, true);
}
}
if (parent.getChildCount() > 0) {
NodeBase firstChild = (NodeBase) parent.getChildAt(0);
if (firstChild.needsInitTabs())
firstChild.initTabs(fm);
}
if (!parent.source.get().equals(combinerAfter)) {
parent.source.set(combinerAfter);
parent.updateColumnWidths(fm);
NodeBase grandparent = (NodeBase) parent.getParent();
grandparent.updateTabStops(fm);
grandparent.allNodesChanged(model);
}
nodeAfter.updateColumnWidths(fm);
parent.updateTabStops(fm);
parent.allNodesChanged(model);
mep.panelEquations.updateVisibility(nodeAfter.getPath());
}
use of gov.sandia.n2a.ui.eq.tree.NodeEquation in project n2a by frothga.
the class PanelEquationTree method updateHighlights.
// For now, this is fast enough to run on EDT, but larger models could bog down the UI.
// TODO: run this on a separate thread, if the need arises
public void updateHighlights(NodeBase node, String name) {
// TODO: organize this code better, so that name is only stripped once.
name = Variable.stripContextPrefix(name);
int count = node.getChildCount();
for (int i = 0; i < count; i++) {
NodeBase n = (NodeBase) node.getChildAt(i);
if (!n.visible())
continue;
boolean needsRepaint = false;
if (n instanceof NodePart) {
updateHighlights(n, name);
} else if (n instanceof NodeVariable) {
needsRepaint = ((NodeVariable) n).findHighlights(name);
updateHighlights(n, name);
} else if (n instanceof NodeEquation) {
needsRepaint = ((NodeEquation) n).findHighlights(name);
}
if (!needsRepaint)
continue;
TreePath path = new TreePath(n.getPath());
Rectangle pathBounds = tree.getPathBounds(path);
if (pathBounds != null)
tree.repaint(pathBounds);
}
}
use of gov.sandia.n2a.ui.eq.tree.NodeEquation in project n2a by frothga.
the class PanelEquationTree method deleteSelected.
public void deleteSelected() {
if (container.locked)
return;
// Collect and convert selection.
TreePath[] paths = tree.getSelectionPaths();
if (paths == null)
return;
TreePath leadPath = tree.getLeadSelectionPath();
List<NodeBase> selection = new ArrayList<NodeBase>();
for (TreePath path : paths) selection.add((NodeBase) path.getLastPathComponent());
NodeBase leadNode = null;
if (leadPath != null)
leadNode = (NodeBase) leadPath.getLastPathComponent();
// Pre-process selection to enforce constraints.
// Detect if all equations under a variable are deleted. If so, ensure that the variable is marked for deletion.
Map<NodeVariable, List<NodeEquation>> equations = new HashMap<NodeVariable, List<NodeEquation>>();
for (NodeBase n : selection) {
if (!(n instanceof NodeEquation))
continue;
NodeVariable v = (NodeVariable) n.getParent();
List<NodeEquation> e = equations.get(v);
if (e == null) {
e = new ArrayList<NodeEquation>();
equations.put(v, e);
}
e.add((NodeEquation) n);
}
for (NodeVariable v : equations.keySet()) {
int count = 0;
Enumeration<?> children = v.childrenFiltered();
while (children.hasMoreElements()) {
if (children.nextElement() instanceof NodeEquation)
count++;
}
if (count == equations.get(v).size() && !selection.contains(v)) {
// Delete containing variable instead. Equations will be removed from selection later.
selection.add(v);
// Needs to actually be in tree selection for parent detection.
tree.addSelectionPath(new TreePath(v.getPath()));
}
}
// Eliminate any selected node that is beneath some other selected node.
NodeInherit inherit = null;
List<NodeBase> filteredSelection = new ArrayList<NodeBase>();
for (NodeBase n : selection) {
if (n.hasSelectedAncestor(tree))
continue;
filteredSelection.add(n);
if (n instanceof NodeInherit) {
if (inherit == null || inherit.getLevel() > n.getLevel())
inherit = (NodeInherit) n;
}
}
selection = filteredSelection;
if (// Since deleting $inherit rebuilds whole tree, don't allow any other deletes.
inherit != null) {
selection.clear();
selection.add(inherit);
} else if (leadNode != null) {
if (!selection.contains(leadNode) && leadNode instanceof NodeEquation)
leadNode = (NodeBase) leadNode.getParent();
if (selection.contains(leadNode)) {
// Ensure that leadNode is the final edit.
selection.remove(leadNode);
selection.add(leadNode);
} else {
leadNode = null;
}
}
// Create transaction
UndoManager um = MainFrame.instance.undoManager;
CompoundEditView compound = null;
int count = selection.size();
boolean multi = count > 1;
if (multi)
um.addEdit(compound = new CompoundEditView(CompoundEditView.CLEAR_TREE));
int i = 0;
for (NodeBase n : selection) {
i++;
Undoable u = n.makeDelete(false);
if (u == null)
continue;
if (u instanceof UndoableView) {
UndoableView uv = (UndoableView) u;
uv.setMulti(multi);
if (multi && i == count)
uv.setMultiLast(true);
}
if (multi && i == count)
compound.leadPath = n.getKeyPath();
um.apply(u);
}
um.endCompoundEdit();
}
use of gov.sandia.n2a.ui.eq.tree.NodeEquation in project n2a by frothga.
the class AddEquation method destroy.
public static void destroy(List<String> path, int equationCount, boolean canceled, String name, String combinerBefore, boolean setSelection) {
// Retrieve created node
NodeBase parent = NodeBase.locateNode(path);
if (parent == null)
throw new CannotUndoException();
NodeBase createdNode = parent.child(name);
PanelEquationTree pet = parent.getTree();
FilteredTreeModel model = (FilteredTreeModel) pet.tree.getModel();
TreeNode[] createdPath = createdNode.getPath();
int index = parent.getIndexFiltered(createdNode);
if (canceled)
index--;
// Update database
MPart mparent = parent.source;
mparent.clear(name);
boolean parentChanged = false;
if (!mparent.get().equals(combinerBefore)) {
// This value may be replaced below if we switch back to single-line.
mparent.set(combinerBefore);
parentChanged = true;
}
if (// There is no overridden value, so this node goes away completely.
mparent.child(name) == null) {
model.removeNodeFromParent(createdNode);
if (// The node used to be single-line, so fold the last equation back into it.
equationCount == 0) {
// The one remaining equation.
NodeEquation lastEquation = null;
// unfiltered
Enumeration<?> i = parent.children();
while (i.hasMoreElements()) {
Object o = i.nextElement();
if (o instanceof NodeEquation) {
lastEquation = (NodeEquation) o;
break;
}
}
String lastCondition = lastEquation.source.key();
String lastExpression = lastEquation.source.get();
mparent.clear(lastCondition);
if (lastCondition.equals("@"))
mparent.set(combinerBefore + lastExpression);
else
mparent.set(combinerBefore + lastExpression + lastCondition);
parentChanged = true;
model.removeNodeFromParent(lastEquation);
}
} else // Just exposed an overridden value, so update.
{
createdNode.setUserObject();
}
if (// Update tabs among this variable's siblings
parentChanged) {
parent.setUserObject();
NodeBase grandparent = (NodeBase) parent.getParent();
grandparent.invalidateColumns(model);
}
parent.invalidateColumns(null);
pet.updateOrder(createdPath);
pet.updateVisibility(createdPath, index, setSelection);
parent.allNodesChanged(model);
pet.animate();
}
use of gov.sandia.n2a.ui.eq.tree.NodeEquation in project n2a by frothga.
the class AddEquation method create.
public static NodeBase create(List<String> path, int equationCount, int index, String name, String combinerAfter, String value) {
NodeBase parent = NodeBase.locateNode(path);
if (parent == null)
throw new CannotRedoException();
PanelModel mep = PanelModel.instance;
JTree tree = mep.panelEquations.tree;
FilteredTreeModel model = (FilteredTreeModel) tree.getModel();
// Update the database
String parentValueBefore = parent.source.get();
Variable.ParsedValue parentPiecesBefore = new Variable.ParsedValue(parentValueBefore);
// The minimum number of equations is 2. There should never be exactly 1 equation, because that is single-line form, which should have no child equations at all.
if (// We are about to switch from single-line form to multi-conditional, so make a tree node for the existing equation.
equationCount == 0) {
MPart equation = (MPart) parent.source.set("@" + parentPiecesBefore.condition, parentPiecesBefore.expression);
model.insertNodeIntoUnfiltered(new NodeEquation(equation), parent, 0);
}
MPart createdPart = (MPart) parent.source.set(name, value == null ? "0" : value);
boolean parentChanged = false;
if (!combinerAfter.equals(parentValueBefore)) {
parent.source.set(combinerAfter);
parentChanged = true;
}
// Update the GUI
NodeBase createdNode = parent.child(name);
boolean alreadyExists = createdNode != null;
if (!alreadyExists)
createdNode = new NodeEquation(createdPart);
FontMetrics fm = createdNode.getFontMetrics(tree);
if (parent.getChildCount() > 0) {
NodeBase firstChild = (NodeBase) parent.getChildAt(0);
if (firstChild.needsInitTabs())
firstChild.initTabs(fm);
}
if (value == null)
createdNode.setUserObject("");
// preempt initialization
createdNode.updateColumnWidths(fm);
if (!alreadyExists)
model.insertNodeIntoUnfiltered(createdNode, parent, index);
if (parentChanged) {
parent.updateColumnWidths(fm);
NodeBase grandparent = (NodeBase) parent.getParent();
grandparent.updateTabStops(fm);
grandparent.allNodesChanged(model);
}
if (// create was merged with change name/value
value != null) {
parent.updateTabStops(fm);
parent.allNodesChanged(model);
mep.panelEquations.updateVisibility(createdNode.getPath());
}
return createdNode;
}
Aggregations