Search in sources :

Example 61 with FontMetrics

use of java.awt.FontMetrics in project n2a by frothga.

the class PanelEquationTree method updateOrder.

/**
 *        Records the current order of nodes in "gui.order", provided that metadata field exists.
 *        Otherwise, we assume the user doesn't care.
 *        @param path To the node that changed (added, deleted, moved). In general, this node's
 *        parent will be the part that is tracking the order of its children.
 */
public void updateOrder(TreeNode[] path) {
    NodePart parent = null;
    for (int i = path.length - 2; i >= 0; i--) {
        if (path[i] instanceof NodePart) {
            parent = (NodePart) path[i];
            break;
        }
    }
    // This should never happen, because root of tree is a NodePart.
    if (parent == null)
        return;
    // Find $metadata/gui.order for the currently selected node. If it exists, update it.
    // Note that this is a modified version of moveSelected() which does not actually move
    // anything, and which only modifies an existing $metadata/gui.order, not create a new one.
    NodeAnnotations metadataNode = null;
    String order = null;
    Enumeration<?> i = parent.children();
    while (i.hasMoreElements()) {
        NodeBase c = (NodeBase) i.nextElement();
        String key = c.source.key();
        if (order == null)
            order = key;
        else
            order = order + "," + key;
        if (key.equals("$metadata"))
            metadataNode = (NodeAnnotations) c;
    }
    if (metadataNode == null)
        return;
    i = metadataNode.children();
    while (i.hasMoreElements()) {
        NodeAnnotation a = (NodeAnnotation) i.nextElement();
        if (a.source.key().equals("gui.order")) {
            a.source.set(order);
            FontMetrics fm = a.getFontMetrics(tree);
            metadataNode.updateTabStops(fm);
            model.nodeChanged(a);
            break;
        }
    }
}
Also used : NodeBase(gov.sandia.n2a.ui.eq.tree.NodeBase) NodeAnnotations(gov.sandia.n2a.ui.eq.tree.NodeAnnotations) NodeAnnotation(gov.sandia.n2a.ui.eq.tree.NodeAnnotation) FontMetrics(java.awt.FontMetrics) NodePart(gov.sandia.n2a.ui.eq.tree.NodePart) ExtensionPoint(gov.sandia.n2a.plugins.ExtensionPoint)

Example 62 with FontMetrics

use of java.awt.FontMetrics in project n2a by frothga.

the class NodeReference method applyEdit.

@Override
public void applyEdit(JTree tree) {
    String input = (String) getUserObject();
    if (input.isEmpty()) {
        delete(tree, true);
        return;
    }
    String[] parts = input.split("=", 2);
    String name = parts[0].trim().replaceAll("[ \\n\\t]", "");
    String value;
    if (parts.length > 1)
        value = parts[1].trim();
    else
        value = "";
    NodeBase parent = (NodeBase) getParent();
    String oldName = source.key();
    String oldValue = source.get();
    if (!name.equals(oldName)) {
        // Check if name change is forbidden
        if (name.isEmpty()) {
            name = oldName;
        } else {
            MPart mparent = source.getParent();
            MPart partAfter = (MPart) mparent.child(name);
            if (partAfter != null && partAfter.isFromTopDocument())
                name = oldName;
        }
    }
    if (name.equals(oldName) && value.equals(oldValue)) {
        FilteredTreeModel model = (FilteredTreeModel) tree.getModel();
        FontMetrics fm = getFontMetrics(tree);
        parent.updateTabStops(fm);
        // Our siblings should not change, because we did not really change. Just repaint in non-edit mode.
        model.nodeChanged(this);
        return;
    }
    PanelModel.instance.undoManager.add(new ChangeReference(parent, oldName, oldValue, name, value));
}
Also used : MPart(gov.sandia.n2a.eqset.MPart) FontMetrics(java.awt.FontMetrics) ChangeReference(gov.sandia.n2a.ui.eq.undo.ChangeReference) FilteredTreeModel(gov.sandia.n2a.ui.eq.FilteredTreeModel)

Example 63 with FontMetrics

use of java.awt.FontMetrics 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 = (String) getUserObject();
    if (input.isEmpty()) {
        delete(tree, true);
        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 {
        // Assume input was a variable name with no assignment. Note: an explicit assignment is required to revoke a variable.
        valueAfter = "0";
    }
    // 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.
    PanelModel mep = PanelModel.instance;
    FilteredTreeModel model = (FilteredTreeModel) tree.getModel();
    // Only a heuristic
    boolean newlyCreated = getChildCount() == 0 && 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.
                mep.undoManager.add(new AddInherit((NodePart) parent, valueAfter));
            } else {
                mep.undoManager.add(new ChangeVariableToInherit(this, valueAfter));
            }
            return;
        }
        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) {
        if (!(nodeAfter instanceof NodeVariable) || (nodeAfter != this && nodeAfter.source.isFromTopDocument() && !newlyCreated)) {
            nameAfter = nameBefore;
            nodeAfter = this;
        }
    }
    // If there's nothing to do, then repaint the node and quit.
    FontMetrics fm = getFontMetrics(tree);
    if (nameBefore.equals(nameAfter) && valueBefore.equals(valueAfter)) {
        parent.updateTabStops(fm);
        parent.allNodesChanged(model);
        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.
                    mep.undoManager.add(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());
                    mep.undoManager.add(new ChangeEquation(this, piecesMatch.condition, piecesMatch.combiner, piecesMatch.expression, piecesAfter.condition, piecesAfter.combiner, piecesAfter.expression));
                }
                parent.updateTabStops(fm);
                parent.allNodesChanged(model);
                return;
            }
        } else {
            if (// The newly created node has been renamed such that it will inject into/over an existing variable.
            newlyCreated) {
                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)) {
                        if (valueAfter.isEmpty())
                            valueAfter = "$kill";
                        mep.undoManager.add(new ChangeVariable(nva, nameAfter, valueAfter, getKeyPath()));
                    } else // Inject new equation and change target into a multiconditional variable.
                    {
                        // Possible to revoke non-existent equation
                        mep.undoManager.add(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
                        mep.undoManager.add(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());
                        mep.undoManager.add(new ChangeEquation(nva, piecesMatch.condition, piecesMatch.combiner, piecesMatch.expression, piecesAfter.condition, piecesAfter.combiner, piecesAfter.expression, getKeyPath()));
                    }
                }
                // commit suicide
                parent.source.clear(nameBefore);
                model.removeNodeFromParent(this);
                return;
            }
        }
    }
    // The default action
    if (valueAfter.isEmpty()) {
        if (newlyCreated) {
            valueAfter = "0";
        } else {
            if (!hasEquations())
                valueAfter = "$kill";
        }
    }
    mep.undoManager.add(new ChangeVariable(this, nameAfter, valueAfter));
}
Also used : AddInherit(gov.sandia.n2a.ui.eq.undo.AddInherit) Variable(gov.sandia.n2a.eqset.Variable) ChangeVariable(gov.sandia.n2a.ui.eq.undo.ChangeVariable) DeleteVariable(gov.sandia.n2a.ui.eq.undo.DeleteVariable) ChangeVariable(gov.sandia.n2a.ui.eq.undo.ChangeVariable) AddEquation(gov.sandia.n2a.ui.eq.undo.AddEquation) ChangeVariableToInherit(gov.sandia.n2a.ui.eq.undo.ChangeVariableToInherit) ChangeEquation(gov.sandia.n2a.ui.eq.undo.ChangeEquation) PanelModel(gov.sandia.n2a.ui.eq.PanelModel) FontMetrics(java.awt.FontMetrics) FilteredTreeModel(gov.sandia.n2a.ui.eq.FilteredTreeModel)

Example 64 with FontMetrics

use of java.awt.FontMetrics 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;
}
Also used : NodeBase(gov.sandia.n2a.ui.eq.tree.NodeBase) MPart(gov.sandia.n2a.eqset.MPart) JTree(javax.swing.JTree) FontMetrics(java.awt.FontMetrics) TreeNode(javax.swing.tree.TreeNode) CannotRedoException(javax.swing.undo.CannotRedoException) NodePart(gov.sandia.n2a.ui.eq.tree.NodePart) PanelEquationTree(gov.sandia.n2a.ui.eq.PanelEquationTree) FilteredTreeModel(gov.sandia.n2a.ui.eq.FilteredTreeModel)

Example 65 with FontMetrics

use of java.awt.FontMetrics 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) {
    // Retrieve created node
    NodeBase parent = NodeBase.locateNode(path);
    if (parent == null)
        throw new CannotUndoException();
    NodeBase createdNode = parent.child(name);
    PanelModel mep = PanelModel.instance;
    JTree tree = mep.panelEquations.tree;
    FilteredTreeModel model = (FilteredTreeModel) tree.getModel();
    FontMetrics fm = createdNode.getFontMetrics(tree);
    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) {
            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 display.
    {
        createdNode.updateColumnWidths(fm);
    }
    if (// Update tabs among this variable's siblings
    parentChanged) {
        parent.updateColumnWidths(fm);
        NodeBase grandparent = (NodeBase) parent.getParent();
        grandparent.updateTabStops(fm);
        grandparent.allNodesChanged(model);
    }
    parent.updateTabStops(fm);
    parent.allNodesChanged(model);
    mep.panelEquations.updateOrder(createdPath);
    mep.panelEquations.updateVisibility(createdPath, index);
}
Also used : MPart(gov.sandia.n2a.eqset.MPart) NodeBase(gov.sandia.n2a.ui.eq.tree.NodeBase) PanelModel(gov.sandia.n2a.ui.eq.PanelModel) NodeEquation(gov.sandia.n2a.ui.eq.tree.NodeEquation) JTree(javax.swing.JTree) FontMetrics(java.awt.FontMetrics) TreeNode(javax.swing.tree.TreeNode) CannotUndoException(javax.swing.undo.CannotUndoException) FilteredTreeModel(gov.sandia.n2a.ui.eq.FilteredTreeModel)

Aggregations

FontMetrics (java.awt.FontMetrics)179 Font (java.awt.Font)61 Graphics2D (java.awt.Graphics2D)35 Point (java.awt.Point)34 Dimension (java.awt.Dimension)29 Color (java.awt.Color)23 Rectangle (java.awt.Rectangle)21 Rectangle2D (java.awt.geom.Rectangle2D)21 Insets (java.awt.Insets)20 Graphics (java.awt.Graphics)16 FilteredTreeModel (gov.sandia.n2a.ui.eq.FilteredTreeModel)14 GradientPaint (java.awt.GradientPaint)14 MPart (gov.sandia.n2a.eqset.MPart)13 NodeBase (gov.sandia.n2a.ui.eq.tree.NodeBase)12 Paint (java.awt.Paint)10 JTree (javax.swing.JTree)10 BasicStroke (java.awt.BasicStroke)9 BufferedImage (java.awt.image.BufferedImage)9 PanelModel (gov.sandia.n2a.ui.eq.PanelModel)8 JLabel (javax.swing.JLabel)8