use of gov.sandia.n2a.ui.CompoundEdit in project n2a by frothga.
the class NodeVariable method applyEdit.
/**
* Enforces all the different use cases associated with editing of variables.
* This is the most complex node class, and does the most work. Some of the use cases include:
* Create a new variable.
* Move an existing variable tree, perhaps overriding an inherited one, perhaps also with a change of value.
* Insert an equation under ourselves.
* Insert an equation under another variable.
*/
@Override
public void applyEdit(JTree tree) {
String input = toString();
UndoManager um = MainFrame.instance.undoManager;
boolean canceled = um.getPresentationName().equals("AddVariable");
if (input.isEmpty()) {
delete(canceled);
return;
}
String[] parts = input.split("=", 2);
String nameAfter = parts[0].trim().replaceAll("[ \\n\\t]", "");
String valueAfter;
if (// Explicit assignment
parts.length > 1) {
valueAfter = parts[1].trim();
if (valueAfter.startsWith("$kill"))
valueAfter = valueAfter.substring(5).trim();
} else {
// Input was a variable name with no assignment.
valueAfter = "";
}
// What follows is a series of analyses, most having to do with enforcing constraints
// on name change (which implies moving the variable tree or otherwise modifying another variable).
// Handle a naked expression.
String nameBefore = source.key();
String valueBefore = getValue();
if (// Not a proper variable name. The user actually passed a naked expression, so resurrect the old (probably auto-assigned) variable name.
!isValidIdentifier(nameAfter)) {
nameAfter = nameBefore;
valueAfter = input;
}
// Handle creation of $inherit node.
FilteredTreeModel model = (FilteredTreeModel) tree.getModel();
boolean canInject = getChildCount() == 0 && source.isFromTopDocument();
// Only a heuristic. Could also be an existing variable with no equation.
boolean newlyCreated = canInject && valueBefore.isEmpty();
NodeBase parent = (NodeBase) getParent();
if (nameAfter.equals("$inherit")) {
if (parent.child(nameAfter) == null) {
if (newlyCreated) {
parent.source.clear(nameBefore);
// No need to update GUI, because AddInherit rebuilds parent.
um.apply(new AddInherit((NodePart) parent, valueAfter));
} else {
um.apply(new ChangeVariableToInherit(this, valueAfter));
}
return;
}
// Reject name change, because $inherit already exists. User should edit it directly.
nameAfter = nameBefore;
}
// Prevent illegal name change. (Don't override another top-level node. Don't overwrite a non-variable node.)
NodeBase nodeAfter = parent.child(nameAfter);
if (nodeAfter != null) {
boolean isVariable = nodeAfter instanceof NodeVariable;
boolean different = nodeAfter != this;
boolean topdoc = nodeAfter.source.isFromTopDocument();
boolean revoked = nodeAfter.source.get().equals("$kill");
if (!isVariable || (different && topdoc && !revoked && !canInject)) {
nameAfter = nameBefore;
nodeAfter = this;
}
}
// If there's nothing to do, then repaint the node and quit.
if (nameBefore.equals(nameAfter) && valueBefore.equals(valueAfter)) {
setUserObject();
model.nodeChanged(this);
return;
}
// Detect and handle special cases
if (// There exists a variable in the target location, so we may end up injecting an equation into a multiconditional expression.
nodeAfter != null) {
// In this section, "dest" refers to state of target node before it is overwritten, while "after" refers to newly input values from user.
Variable.ParsedValue piecesDest = new Variable.ParsedValue(((NodeVariable) nodeAfter).getValue());
Variable.ParsedValue piecesAfter = new Variable.ParsedValue(valueAfter);
boolean expressionAfter = !piecesAfter.expression.isEmpty() || !piecesAfter.condition.isEmpty();
// If the user doesn't specify a combiner, absorb it from our destination.
if (piecesAfter.combiner.isEmpty())
piecesAfter.combiner = piecesDest.combiner;
int equationCount = 0;
NodeEquation equationMatch = null;
Enumeration<?> childrenAfter = nodeAfter.children();
while (childrenAfter.hasMoreElements()) {
Object c = childrenAfter.nextElement();
if (c instanceof NodeEquation) {
equationCount++;
NodeEquation e = (NodeEquation) c;
if (e.source.key().substring(1).equals(piecesAfter.condition))
equationMatch = e;
}
}
if (nodeAfter == this) {
if (// Inject an equation into ourselves.
equationCount > 0 && expressionAfter) {
if (// New equation
equationMatch == null) {
// It is possible to add an equation revocation here without there being an existing equation to revoke.
um.apply(new AddEquation(this, piecesAfter.condition, piecesAfter.combiner, piecesAfter.expression));
} else // Overwrite an existing equation
{
Variable.ParsedValue piecesMatch = new Variable.ParsedValue(piecesDest.combiner + equationMatch.source.get() + equationMatch.source.key());
um.apply(new ChangeEquation(this, piecesMatch.condition, piecesMatch.combiner, piecesMatch.expression, piecesAfter.condition, piecesAfter.combiner, piecesAfter.expression));
}
return;
}
} else // Node has been renamed.
{
if (// Inject into/over an existing variable.
canInject) {
// Remove this variable, regardless of what we do to nodeAfter.
um.addEdit(new CompoundEdit());
um.apply(new DeleteVariable(this, canceled));
// Decide what change (if any) to apply to nodeAfter.
if (expressionAfter) {
NodeVariable nva = (NodeVariable) nodeAfter;
if (equationCount == 0) {
if (// Directly overwrite the target, since they share the say name and condition.
piecesAfter.condition.equals(piecesDest.condition)) {
um.apply(new ChangeVariable(nva, nameAfter, valueAfter, getKeyPath()));
} else // Inject new equation and change target into a multiconditional variable.
{
// Possible to revoke non-existent equation
um.apply(new AddEquation(nva, piecesAfter.condition, piecesAfter.combiner, piecesAfter.expression, getKeyPath()));
}
} else {
if (// Add new equation to an existing multiconditional.
equationMatch == null) {
// Possible to revoke non-existent equation
um.apply(new AddEquation(nva, piecesAfter.condition, piecesAfter.combiner, piecesAfter.expression, getKeyPath()));
} else // Overwrite an existing equation in a multiconditional
{
Variable.ParsedValue piecesMatch = new Variable.ParsedValue(piecesDest.combiner + equationMatch.source.get() + equationMatch.source.key());
um.apply(new ChangeEquation(nva, piecesMatch.condition, piecesMatch.combiner, piecesMatch.expression, piecesAfter.condition, piecesAfter.combiner, piecesAfter.expression, getKeyPath()));
}
}
}
um.endCompoundEdit();
return;
}
}
}
// The @ will be hidden most of the time, but it will distinguish a variable from a part.
if (valueAfter.isEmpty() && !hasEquations())
valueAfter = "@";
um.apply(new ChangeVariable(this, nameAfter, valueAfter));
}
use of gov.sandia.n2a.ui.CompoundEdit in project n2a by frothga.
the class PanelEquationTree method outsource.
/**
* Does two things:
* 1) Creates a new top-level model with contents of the given part.
* 2) Modifies the part to inherit from the new model.
*/
public static void outsource(NodePart part) {
if (!part.source.isFromTopDocument())
return;
// Prepare data
MVolatile data = new MVolatile();
// This takes all data, not just visible nodes.
data.merge(part.source);
data.clear("$metadata", "gui", "bounds");
// Create transaction
UndoManager um = MainFrame.instance.undoManager;
um.addEdit(new CompoundEdit());
AddDoc a = new AddDoc(part.source.key(), data);
// Necessary so that focus stays on part. Outsource ctor examines focus.
a.setSilent();
um.apply(a);
um.apply(new Outsource(part, a.name));
um.endCompoundEdit();
}
use of gov.sandia.n2a.ui.CompoundEdit in project n2a by frothga.
the class ImportNeuroML method process.
@Override
public void process(File source) {
if (PluginNeuroML.partMap == null)
PluginNeuroML.partMap = new PartMap();
ImportJob job = new ImportJob(PluginNeuroML.partMap);
job.process(source);
job.postprocess();
MNode mainModel = job.models.child(job.modelName);
job.models.clear(job.modelName);
UndoManager um = PanelModel.instance.undoManager;
um.addEdit(new CompoundEdit());
while (job.models.size() > 0) addModel(job.models.iterator().next(), job.models, um);
// after all add operations are completed.
if (mainModel != null)
um.add(new AddDoc(job.modelName, mainModel));
um.endCompoundEdit();
}
use of gov.sandia.n2a.ui.CompoundEdit in project n2a by frothga.
the class ImportNeuroML method process.
@Override
public void process(Path source) {
if (PluginNeuroML.partMap == null)
PluginNeuroML.partMap = new PartMap();
ImportJob job = new ImportJob(PluginNeuroML.partMap);
job.process(source);
job.postprocess();
MNode mainModel = job.models.child(job.modelName);
job.models.clear(job.modelName);
UndoManager um = MainFrame.instance.undoManager;
um.addEdit(new CompoundEdit());
while (job.models.size() > 0) addModel(job.models.iterator().next(), job.models, um);
// after all add operations are completed.
if (mainModel != null)
um.apply(new AddDoc(job.modelName, mainModel));
um.endCompoundEdit();
}
Aggregations