/** * Causes an {@link SmallStepNodeComponent#update() on all * nodes that have changed.<br> * <br> * When all updates are done relayouts the View. * * @see #relayout() */ @Override protected void nodesChanged(TreeModelEvent event) { boolean relayout = false; Object[] children = event.getChildren(); if (children == null) { // if the children are null and the path only contains one element // this element is the root node. if (event.getPath().length == 1) { SmallStepProofNode proofNode = (SmallStepProofNode) event.getPath()[0]; SmallStepNodeComponent nodeComponent = (SmallStepNodeComponent) proofNode.getUserObject(); if (nodeComponent != null) { nodeComponent.update(); relayout = true; } } } else { for (int i = 0; i < children.length; i++) { if (children[i] instanceof ProofNode) { SmallStepProofNode proofNode = (SmallStepProofNode) children[i]; SmallStepNodeComponent nodeComponent = (SmallStepNodeComponent) proofNode.getUserObject(); if (nodeComponent != null) { nodeComponent.update(); relayout = true; } } } } if (relayout) { relayout(); } }
/** * Returns the first child of the given node.<br> * <br> * If the node has no children, <i>null</i> is returned. * * @param node * @return */ private SmallStepProofNode getFirstChild(SmallStepProofNode node) { try { return node.getFirstChild(); } catch (Exception e) { // nothing } return null; }
/** * Removes all userobjects from the nodes that will be removed by the {@link SmallStepProofModel} * later. */ @Override protected void nodesRemoved(TreeModelEvent event) { Object[] children = event.getChildren(); if (children == null) { return; } for (int i = 0; i < children.length; i++) { if (children[i] instanceof ProofNode) { SmallStepProofNode proofNode = (SmallStepProofNode) children[i]; SmallStepNodeComponent nodeComponent = (SmallStepNodeComponent) proofNode.getUserObject(); if (nodeComponent != null) { remove(nodeComponent); proofNode.setUserObject(null); } } } }
/** * If <code>advanced</code> is <code>true</code>, the small step component will display only axiom * rules in the rule menu, otherwise, in beginner mode, meta rules will also be displayed. * * @param pAdvanced <code>true</code> to display only axiom rules. * @see #isAdvanced() */ void setAdvanced(boolean pAdvanced) { // check if we have a new setting if (this.advanced != pAdvanced) { // remember the new setting this.advanced = pAdvanced; // make sure all nodes have valid user objects checkForUserObject((SmallStepProofNode) this.proofModel.getRoot()); // update all active nodes Enumeration<ProofNode> enumeration = this.proofModel.getRoot().postorderEnumeration(); while (enumeration.hasMoreElements()) { // tell the component belonging to this node, that we have a new advanced state SmallStepProofNode node = (SmallStepProofNode) enumeration.nextElement(); SmallStepNodeComponent component = (SmallStepNodeComponent) node.getUserObject(); component.setAdvanced(pAdvanced); } } }
/** * Traverses the ProofTree recursivly and checks the size of the expression for every node. * * @param node When calling this method: the rootNode of the tree. */ void checkExpressionSize(SmallStepProofNode node) { if (node == null) { return; } SmallStepNodeComponent nodeComponent = (SmallStepNodeComponent) node.getUserObject(); nodeComponent.checkNeededExpressionSize(this.availableWidth - this.border); // proceed with the next child checkExpressionSize(getFirstChild(node)); }
/** * Traverses the ProofTree recursivly and informing every node for the maximum size of the rule * combo on the left-hand-side. * * @param node When calling this method: the rootNode of the tree. * @param maxRuleWidth The maximum Width of the rules. */ void updateMaxRuleWidth(SmallStepProofNode node, int maxRuleWidth) { if (node == null) { return; } // inform the node of the max rule width SmallStepNodeComponent nodeComponent = (SmallStepNodeComponent) node.getUserObject(); nodeComponent.setMaxRuleWidth(maxRuleWidth); // proceed with the next child node updateMaxRuleWidth(getFirstChild(node), maxRuleWidth); }
/** * Traversing the ProofTree recursivly and adds a SmallStepNodeComponent where none is.<br> * <br> * Usualy only at newly added nodes the SmallStepNodeComponent is missing. * * @param node When calling this method: the rootNode of the tree. */ void checkForUserObject(SmallStepProofNode node) { if (node == null) { return; } SmallStepNodeComponent nodeComponent = (SmallStepNodeComponent) node.getUserObject(); if (nodeComponent == null) { // create the noded that has not been there yet nodeComponent = new SmallStepNodeComponent( node, this.model, this.translator, this.spacing, this.advanced); // add the needed listener nodeComponent.addSmallStepNodeListener( new SmallStepNodeListener() { public void nodeChanged(SmallStepNodeComponent pNode) { SmallStepComponent.this.relayout(); } public void repaintAll() { SmallStepComponent.this.repaint(); } public void requestJumpToNode(ProofNode pNode) { SmallStepComponent.this.setJumpNode(pNode); } }); nodeComponent.update(); // save it to the node node.setUserObject(nodeComponent); // and add the SmallStepNodeComponent to the gui add(nodeComponent); } checkForUserObject(getFirstChild(node)); }
/** * Causes all userobject from all nodes to reset the layout.<br> * <br> * Resetting means that every {@link PrettyStringRenderer} and {@link EnvironmentRenderer} * recalculates their needed font sizes. */ private void resetUserObject(SmallStepProofNode node) { if (node == null) { return; } SmallStepNodeComponent nodeComponent = (SmallStepNodeComponent) node.getUserObject(); if (nodeComponent == null) { return; } nodeComponent.reset(); resetUserObject(getFirstChild(node)); }
/** * Traverses the ProofTree recursivly and checks the needed size for the rule combo on the * left-hand-side.<br> * <br> * The <i>currentWidth</i> is the current maximum width that has been evaluated. When calling this * function this should be somthing small. Just set it to <b>0</b>. * * @param node When calling this method: the rootNode of the tree. * @param pCurrentWidth Used internaly. Should be set to <b>0</b>. * @return */ int checkMaxRuleWidth(SmallStepProofNode node, int pCurrentWidth) { int currentWidth = pCurrentWidth; if (node == null) { return currentWidth; } // get the size of the current node SmallStepNodeComponent nodeComponent = (SmallStepNodeComponent) node.getUserObject(); int nodeWidth = nodeComponent.getMinRuleSize().width; // only the maximum width is of interest currentWidth = Math.max(currentWidth, nodeWidth); // return the recursive result of the next node return checkMaxRuleWidth(getFirstChild(node), currentWidth); }
/** * Iterates through the entire tree an places every node.<br> * <br> * There are some things to take care of, when the nodes get placed:<br> * <br> * The expression and the rules of the parent node are in one row so when the nodes get placed the * actualHeight of each node must be the maximum of both. They are placed together in on step. So * the rules of each node are placed together with the expression of its child node, if there is * one.<br> * If there is no parent node (that would be the first node, the root node), only the expression * needs to get places.<br> * If the node has no child (that would be the last node in the tree), the rules must be placed * directly because there is no child node that would place them. * * @param node The rootNode * @param pX The horizontal start position * @param pY Ther vertical start position * @return The size needed to show all the nodes. */ Dimension placeNode(SmallStepProofNode pNode, int pX, int pY) { int x = pX; int y = pY; this.actualPageSpaceCounter = y; SmallStepProofNode node = pNode; Dimension size = new Dimension(0, 0); // save the space the next node will be moved down int movedDown = 0; int lastNodeHeight = this.actualPageSpaceCounter; while (node != null) { SmallStepNodeComponent nodeComponent = (SmallStepNodeComponent) node.getUserObject(); // set the origin of this node nodeComponent.setOrigion(new Point(x, y)); // if the node has no parent node it appears to be the rootNode // // the expression of the rootNode can be placed without checking anything if (node.getParent() == null) { nodeComponent.placeExpression(); // move the positioning y += nodeComponent.getRuleTop(); this.actualPageSpaceCounter = y; // evaluate the new dimensions size.height = y; } else { // evaluate the max size of this nodes expression and the parent // nodes rules SmallStepProofNode parentNode = node.getParent(); SmallStepNodeComponent parentNodeComponent = (SmallStepNodeComponent) parentNode.getUserObject(); Dimension expSize = nodeComponent.getExpressionSize(); Dimension ruleSize = parentNodeComponent.getRuleSize(); int maxHeight = Math.max(expSize.height, ruleSize.height); // provide printing // if the actualPageSpaceCounter has not enough space for the next node perform a pagebrak if (this.actualPageSpaceCounter + maxHeight + lastNodeHeight > this.availableHeight) { { // save the space the node is moved down movedDown = (this.availableHeight - this.actualPageSpaceCounter) / 2; // Wäää? // move the next node down y += movedDown; // restart the actualPageSpaceCounter this.actualPageSpaceCounter = -movedDown; // Wäää? // inform both component about the actual height they should use to // place them parentNodeComponent.setActualRuleHeight(maxHeight); nodeComponent.setActualExpressionHeight(maxHeight); // let both components place theire elements parentNodeComponent.placeRules(); nodeComponent.placeExpression(); // this finishes the parentNode so it can be placed parentNodeComponent.setBounds(); // the additional height come from the actual node y += nodeComponent.getRuleTop(); this.actualPageSpaceCounter += nodeComponent.getRuleTop(); // System.out.println(maxHeight+" - "+nodeComponent.getRuleTop()); // evaluate the new dimensions size.height = y; // the actual width of the entire component can now be checked // on the finshed node. the parent node size.width = Math.max(size.width, x + parentNodeComponent.getSize().width); } } else { // inform both component about the actual height they should use to // place them parentNodeComponent.setActualRuleHeight(maxHeight); nodeComponent.setActualExpressionHeight(maxHeight); // let both components place theire elements // the movedDown saves the information how far the the parent-Rules must be moved down... parentNodeComponent.placeRules(movedDown); nodeComponent.placeExpression(); // this finishes the parentNode so it can be placed parentNodeComponent.setBounds(movedDown); movedDown = 0; // the additional height come from the actual node y += nodeComponent.getRuleTop(); this.actualPageSpaceCounter += nodeComponent.getRuleTop(); // System.out.println(maxHeight+" - "+nodeComponent.getRuleTop()); // evaluate the new dimensions size.height = y; // the actual width of the entire component can now be checked // on the finshed node. the parent node size.width = Math.max(size.width, x + parentNodeComponent.getSize().width); } lastNodeHeight = maxHeight; // tmpPaper += maxHeight; } // if the node has no children the rules need to get // placed here with the expression if (getFirstChild(node) == null) { if (this.model.isFinished()) { nodeComponent.hideRules(); nodeComponent.setBounds(); size.width = Math.max(size.width, x + nodeComponent.getSize().width); } else { // the rules can savely be positioned nodeComponent.placeRules(); // and the node itself can be placed nodeComponent.setBounds(); // evaluate the new dimension size.height += nodeComponent.getActualRuleHeight(); // the actual width of the entire component can now be checked // on the finshed node. size.width = Math.max(size.width, x + nodeComponent.getSize().width); } return size; } node = node.getFirstChild(); } return size; }