/** adds a new node to the tree */ public void add(GeoElement geo) { cancelEditing(); if (geo.isLabelSet() && geo.showInAlgebraView() && geo.isSetAlgebraVisible()) { // don't add auxiliary objects if the tree is categorized by type if (!getTreeMode().equals(SortMode.DEPENDENCY) && !showAuxiliaryObjects() && geo.isAuxiliaryObject()) { return; } DefaultMutableTreeNode parent, node; node = new DefaultMutableTreeNode(geo); parent = getParentNode(geo); // add node to model (alphabetically ordered) int pos = getInsertPosition(parent, geo, treeMode); model.insertNodeInto(node, parent, pos); nodeTable.put(geo, node); // ensure that the leaf with the new object is visible expandPath(new TreePath(new Object[] {model.getRoot(), parent})); } }
/** * Performs a linear search for geo among the children of parent. * * @return -1 when not found */ public static final int linearSearchGeo(DefaultMutableTreeNode parent, String geoLabel) { int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) parent.getChildAt(i); GeoElement g = (GeoElement) node.getUserObject(); if (geoLabel.equals(g.getLabel())) return i; } return -1; }
private static boolean compare(GeoElement geo1, GeoElement geo2, SortMode mode) { switch (mode) { case ORDER: return geo1.getConstructionIndex() > geo2.getConstructionIndex(); default: // alphabetical return GeoElement.compareLabels(geo1.getLabel(), geo2.getLabel()) > 0; } }
/** * Returns the tree path of geo * * @return returns null if geo is not in tree */ private TreePath getTreePath(GeoElement geo) { DefaultMutableTreeNode typeNode = typeNodesMap.get(geo.getObjectType()); if (typeNode == null) return null; // find pos of geo int pos = AlgebraView.binarySearchGeo(typeNode, geo.getLabel()); if (pos == -1) return null; return new TreePath(((DefaultMutableTreeNode) typeNode.getChildAt(pos)).getPath()); }
public int getDefaultType(GeoElement geo) { switch (geo.getGeoClassType()) { case POINT3D: if (geo.isIndependent()) { return DEFAULT_POINT3D_FREE; } else { GeoPoint3D p = (GeoPoint3D) geo; if (p.hasPath()) return DEFAULT_POINT3D_ON_PATH; else if (p.hasRegion()) return DEFAULT_POINT3D_IN_REGION; else return DEFAULT_POINT3D_DEPENDENT; } case ANGLE3D: return DEFAULT_ANGLE3D; case LINE3D: if (((GeoLine3D) geo).isIntersection()) return DEFAULT_LINE3D_INTERSECTION; else return DEFAULT_LINE3D; case SEGMENT3D: if (((GeoSegment3D) geo).isIntersection()) return DEFAULT_SEGMENT3D_INTERSECTION; else return DEFAULT_SEGMENT3D; case RAY3D: if (((GeoRay3D) geo).isIntersection()) return DEFAULT_RAY3D_INTERSECTION; else return DEFAULT_RAY3D; case AXIS3D: return DEFAULT_AXIS3D; case VECTOR3D: return DEFAULT_VECTOR3D; case CONIC3D: if (((GeoConic3D) geo).isIntersection()) return DEFAULT_CONIC3D_INTERSECTION; else return DEFAULT_CONIC3D; case CURVECARTESIAN3D: return DEFAULT_CURVECARTESIAN3D; case PLANE3D: return DEFAULT_PLANE3D; case POLYGON3D: return DEFAULT_POLYGON3D; case POLYHEDRON: return DEFAULT_POLYHEDRON; case QUADRIC: case QUADRIC_PART: return DEFAULT_QUADRIC; case QUADRIC_LIMITED: return DEFAULT_QUADRIC_LIMITED; case FUNCTION_NVAR: return DEFAULT_FUNCTION_NVAR; case SURFACECARTESIAN3D: return DEFAULT_SURFACECARTESIAN3D; default: return super.getDefaultType(geo); } }
/** * Reset the visual style of the selected elements. * * <p>TODO Does not work with lists (F.S.) */ private void applyDefaults() { GeoElement geo; ConstructionDefaults defaults = kernel.getConstruction().getConstructionDefaults(); for (int i = 0; i < selectionList.size(); ++i) { geo = (GeoElement) selectionList.get(i); defaults.setDefaultVisualStyles(geo, true); geo.updateRepaint(); } propPanel.updateSelection(selectionList.toArray()); }
/** * for AlgebraView changes in the tree selection and redefine dialog * * @return changed geo */ public GeoElement changeGeoElementNoExceptionHandling( GeoElement geo, ValidExpression newValue, boolean redefineIndependent, boolean storeUndoInfo) throws Exception { String oldLabel, newLabel; GeoElement[] result; try { oldLabel = geo.getLabel(); newLabel = newValue.getLabel(); if (newLabel == null) { newLabel = oldLabel; newValue.setLabel(newLabel); } // make sure that points stay points and vectors stay vectors if (newValue instanceof ExpressionNode) { ExpressionNode n = (ExpressionNode) newValue; if (geo.isGeoPoint()) n.setForcePoint(); else if (geo.isGeoVector()) n.setForceVector(); else if (geo.isGeoFunction()) n.setForceFunction(); } if (newLabel.equals(oldLabel)) { // try to overwrite result = processValidExpression(newValue, redefineIndependent); if (result != null && storeUndoInfo) app.storeUndoInfo(); return result[0]; } else if (cons.isFreeLabel(newLabel)) { newValue.setLabel(oldLabel); // rename to oldLabel to enable overwriting result = processValidExpression(newValue, redefineIndependent); result[0].setLabel(newLabel); // now we rename if (storeUndoInfo) app.storeUndoInfo(); return result[0]; } else { String str[] = {"NameUsed", newLabel}; throw new MyError(app, str); } } catch (CircularDefinitionException e) { Application.debug("CircularDefinition"); throw e; } catch (Exception e) { e.printStackTrace(); throw new Exception(app.getError("InvalidInput") + ":\n" + newValue); } catch (MyError e) { e.printStackTrace(); throw new Exception(e.getLocalizedMessage()); } catch (Error e) { e.printStackTrace(); throw new Exception(app.getError("InvalidInput") + ":\n" + newValue); } }
@Override public final void compute() { // validate size = inputList.size(); if (!inputList.isDefined() || size == 0) { outputList.setUndefined(); return; } // convert geoList to sorted array of double sortedData = new double[size]; for (int i = 0; i < size; i++) { GeoElement geo = inputList.get(i); if (geo.isNumberValue()) { NumberValue num = (NumberValue) geo; sortedData[i] = num.getDouble(); } else { outputList.setUndefined(); return; } } Arrays.sort(sortedData); // create the z values calculateZValues(size); // prepare output list. Pre-existing geos will be recycled, // but extra geos are removed when outputList is too long outputList.setDefined(true); for (int i = outputList.size() - 1; i >= size; i--) { GeoElement extraGeo = outputList.get(i); extraGeo.remove(); outputList.remove(extraGeo); } int oldListSize = outputList.size(); // iterate through the sorted data and create the normal quantile points boolean suppressLabelCreation = cons.isSuppressLabelsActive(); cons.setSuppressLabelCreation(true); for (int i = 0; i < sortedData.length; i++) { if (i < oldListSize) ((GeoPoint) outputList.get(i)).setCoords(sortedData[i], zValues[i], 1.0); else outputList.add(new GeoPoint(cons, null, sortedData[i], zValues[i], 1.0)); } // create qq line segment and add it to the list outputList.add(getQQLineSegment()); cons.setSuppressLabelCreation(suppressLabelCreation); }
public void mouseMoved(MouseEvent e) { Point loc = e.getPoint(); GeoElement geo = AlgebraView.getGeoElementForLocation(this, loc.x, loc.y); EuclidianView ev = app.getEuclidianView(); // tell EuclidianView to handle mouse over ev.mouseMovedOver(geo); if (geo != null) { app.setTooltipFlag(); setToolTipText(geo.getLongDescriptionHTML(true, true)); app.clearTooltipFlag(); } else { setToolTipText(null); } }
/** returns geo's TreePath */ private TreePath getGeoPath(GeoElement geo) { String typeString = geo.getObjectType(); DefaultMutableTreeNode typeNode = typeNodesMap.get(typeString); if (typeNode == null) return null; int pos = AlgebraView.binarySearchGeo(typeNode, geo.getLabel()); if (pos == -1) return null; else { // add to selection DefaultMutableTreeNode node = (DefaultMutableTreeNode) typeNode.getChildAt(pos); // expand typenode TreePath tp = new TreePath(node.getPath()); return tp; } }
private GeoElement[] processList(ExpressionNode n, MyList evalList) { String label = n.getLabel(); GeoElement[] ret = new GeoElement[1]; // no operations or no variables are present, e.g. // { a, b, 7 } or { 2, 3, 5 } + {1, 2, 4} if (!n.hasOperations() || n.isConstant()) { // PROCESS list items to generate a list of geoElements ArrayList<GeoElement> geoElements = new ArrayList<GeoElement>(); boolean isIndependent = true; // make sure we don't create any labels for the list elements boolean oldMacroMode = cons.isSuppressLabelsActive(); cons.setSuppressLabelCreation(true); int size = evalList.size(); for (int i = 0; i < size; i++) { ExpressionNode en = (ExpressionNode) evalList.getListElement(i); // we only take one resulting object GeoElement[] results = processExpressionNode(en); GeoElement geo = results[0]; // add to list geoElements.add(geo); if (geo.isLabelSet() || !geo.isIndependent()) isIndependent = false; } cons.setSuppressLabelCreation(oldMacroMode); // Create GeoList object ret[0] = kernel.List(label, geoElements, isIndependent); } // operations and variables are present // e.g. {3, 2, 1} + {a, b, 2} else { ret[0] = kernel.ListExpression(label, n); } return ret; }
/** @param binarySearch true for binary, false for linear search */ public void remove(GeoElement geo, boolean binarySearch) { // get type node DefaultMutableTreeNode typeNode = typeNodesMap.get(geo.getObjectType()); if (typeNode == null) return; int pos = binarySearch ? AlgebraView.binarySearchGeo(typeNode, geo.getLabel()) : AlgebraView.linearSearchGeo(typeNode, geo.getLabel()); if (pos > -1) { DefaultMutableTreeNode child = (DefaultMutableTreeNode) typeNode.getChildAt(pos); treeModel.removeNodeFromParent(child); if (typeNode.getChildCount() == 0) { // last child typeNodesMap.remove(geo.getObjectType()); treeModel.removeNodeFromParent(typeNode); } } }
/** deletes all selected GeoElements from Kernel */ private void deleteSelectedGeos() { ArrayList selGeos = selectionList; if (selGeos.size() > 0) { Object[] geos = selGeos.toArray(); for (int i = 0; i < geos.length - 1; i++) { ((GeoElement) geos[i]).removeOrSetUndefinedIfHasFixedDescendent(); } // select element above last to delete GeoElement geo = (GeoElement) geos[geos.length - 1]; TreePath tp = geoTree.getTreePath(geo); if (tp != null) { int row = geoTree.getRowForPath(tp); tp = geoTree.getPathForRow(row - 1); geo.removeOrSetUndefinedIfHasFixedDescendent(); if (tp != null) geoTree.setSelectionPath(tp); } } }
/** adds a new element to the list */ public final void add(GeoElement geo) { if (!geo.isLabelSet() || !geo.hasProperties()) return; // get type node String typeString = geo.getObjectType(); DefaultMutableTreeNode typeNode = typeNodesMap.get(typeString); // init type node boolean initing = typeNode == null; if (initing) { String transTypeString = geo.translatedTypeString(); typeNode = new DefaultMutableTreeNode(transTypeString); typeNodesMap.put(typeString, typeNode); // find insert pos int pos = root.getChildCount(); for (int i = 0; i < pos; i++) { DefaultMutableTreeNode child = (DefaultMutableTreeNode) root.getChildAt(i); if (transTypeString.compareTo(child.toString()) < 0) { pos = i; break; } } treeModel.insertNodeInto(typeNode, root, pos); } // check if already present in type node int pos = AlgebraView.binarySearchGeo(typeNode, geo.getLabel()); if (pos >= 0) return; // add geo to type node DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(geo); pos = AlgebraView.getInsertPosition(typeNode, geo, AlgebraView.SortMode.DEPENDENCY); treeModel.insertNodeInto(newNode, typeNode, pos); // make sure something is selected if (getSelectionModel().isSelectionEmpty()) { selectFirstElement(); } }
/** * Resolves arguments, creates local variables and fills the vars and overlists * * @param c * @return list of arguments */ protected final GeoElement[] resArgsForZip(Command c) { // check if there is a local variable in arguments int numArgs = c.getArgumentNumber(); vars = new GeoElement[numArgs / 2]; over = new GeoList[numArgs / 2]; Construction cmdCons = (Construction) c.getKernel().getConstruction(); for (int varPos = 1; varPos < numArgs; varPos += 2) { String localVarName = c.getVariableName(varPos); if (localVarName == null) { throw argErr(app, c.getName(), c.getArgument(varPos)); } // add local variable name to construction GeoElement num = null; // initialize first value of local numeric variable from initPos boolean oldval = cons.isSuppressLabelsActive(); cons.setSuppressLabelCreation(true); GeoList gl = (GeoList) resArg(c.getArgument(varPos + 1))[0]; cons.setSuppressLabelCreation(oldval); num = gl.get(0).copyInternal(cons); cmdCons.addLocalVariable(localVarName, num); // set local variable as our varPos argument c.setArgument(varPos, new ExpressionNode(c.getKernel(), num)); vars[varPos / 2] = num.toGeoElement(); over[varPos / 2] = gl; // resolve all command arguments including the local variable just // created // remove local variable name from kernel again } GeoElement[] arg = resArgs(c); for (GeoElement localVar : vars) cmdCons.removeLocalVariable(localVar.getLabel()); return arg; }
/** Handles clicks on the show/hide icon to toggle the show-object status. */ public void mouseClicked(MouseEvent e) { if (Application.isControlDown(e) || e.isShiftDown()) return; // get GeoElement at mouse location TreePath tp = getPathForLocation(e.getX(), e.getY()); GeoElement geo = AlgebraView.getGeoElementForPath(tp); if (geo != null) { // check if we clicked on the 16x16 show/hide icon Rectangle rect = getPathBounds(tp); boolean iconClicked = rect != null && e.getX() - rect.x < 13; // distance from left border if (iconClicked) { // icon clicked: toggle show/hide geo.setEuclidianVisible(!geo.isSetEuclidianVisible()); geo.update(); kernel.notifyRepaint(); // update properties dialog by selecting this geo again geoElementSelected(geo, false); } } }
/** Open Editor textfield for geo. */ public void startEditing(GeoElement geo, boolean shiftDown) { if (geo == null) return; // open Object Properties for eg GeoImages if (!geo.isAlgebraViewEditable()) { ArrayList<GeoElement> geos = new ArrayList<GeoElement>(); geos.add(geo); app.getGuiManager().getDialogManager().showPropertiesDialog(geos); return; } if (!shiftDown || !geo.isPointOnPath() && !geo.isPointInRegion()) { if (!geo.isIndependent() || !attached) // needed for F2 when Algebra // View closed { if (geo.isRedefineable()) { app.getGuiManager().getDialogManager().showRedefineDialog(geo, true); } return; } if (!geo.isChangeable()) { if (geo.isFixed()) { // app.showMessage(app.getError("AssignmentToFixed")); } else if (geo.isRedefineable()) { app.getGuiManager().getDialogManager().showRedefineDialog(geo, true); } return; } } DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodeTable.get(geo); if (node != null) { cancelEditing(); // select and show node TreePath tp = new TreePath(node.getPath()); setSelectionPath(tp); // select expandPath(tp); makeVisible(tp); scrollPathToVisible(tp); startEditingAtPath(tp); // opend editing text field } }
/** * Performs a binary search for geo among the children of parent. All children of parent have to * be instances of GeoElement sorted alphabetically by their names. * * @return -1 when not found */ public static final int binarySearchGeo(DefaultMutableTreeNode parent, String geoLabel) { int left = 0; int right = parent.getChildCount() - 1; if (right == -1) return -1; // binary search for geo's label while (left <= right) { int middle = (left + right) / 2; DefaultMutableTreeNode node = (DefaultMutableTreeNode) parent.getChildAt(middle); String nodeLabel = ((GeoElement) node.getUserObject()).getLabel(); int compare = GeoElement.compareLabels(geoLabel, nodeLabel); if (compare < 0) right = middle - 1; else if (compare > 0) left = middle + 1; else return middle; } return -1; }
/** * processes valid expression. * * @param ve * @param redefineIndependent == true: independent objects are redefined too * @throws MyError * @throws Exception * @return */ public GeoElement[] processValidExpression(ValidExpression ve, boolean redefineIndependent) throws MyError, Exception { // check for existing labels String[] labels = ve.getLabels(); GeoElement replaceable = null; if (labels != null && labels.length > 0) { boolean firstTime = true; for (int i = 0; i < labels.length; i++) { GeoElement geo = kernel.lookupLabel(labels[i]); if (geo != null) { if (geo.isFixed()) { String[] strs = { "IllegalAssignment", "AssignmentToFixed", ":\n", geo.getLongDescription() }; throw new MyError(app, strs); } else { // replace (overwrite or redefine) geo if (firstTime) { // only one geo can be replaced replaceable = geo; firstTime = false; } } } } } GeoElement[] ret; boolean oldMacroMode = cons.isSuppressLabelsActive(); if (replaceable != null) cons.setSuppressLabelCreation(true); // we have to make sure that the macro mode is // set back at the end try { ret = doProcessValidExpression(ve); if (ret == null) { // eg (1,2,3) running in 2D Application.debug("Unhandled ValidExpression : " + ve); throw new MyError(app, app.getError("InvalidInput") + ":\n" + ve); } } finally { cons.setSuppressLabelCreation(oldMacroMode); } // try to replace replaceable geo by ret[0] if (replaceable != null && ret != null && ret.length > 0) { // a changeable replaceable is not redefined: // it gets the value of ret[0] // (note: texts are always redefined) if (!redefineIndependent && replaceable.isChangeable() && !(replaceable.isGeoText())) { try { replaceable.set(ret[0]); replaceable.updateRepaint(); ret[0] = replaceable; } catch (Exception e) { String errStr = app.getError("IllegalAssignment") + "\n" + replaceable.getLongDescription() + " = " + ret[0].getLongDescription(); throw new MyError(app, errStr); } } // redefine else { try { // SPECIAL CASE: set value // new and old object are both independent and have same type: // simply assign value and don't redefine if (replaceable.isIndependent() && ret[0].isIndependent() && replaceable.getGeoClassType() == ret[0].getGeoClassType()) { replaceable.set(ret[0]); replaceable.updateRepaint(); ret[0] = replaceable; } // STANDARD CASE: REDFINED else { GeoElement newGeo = ret[0]; cons.replace(replaceable, newGeo); // now all objects have changed // get the new object with same label as our result String newLabel = newGeo.isLabelSet() ? newGeo.getLabel() : replaceable.getLabel(); ret[0] = kernel.lookupLabel(newLabel, false); } } catch (CircularDefinitionException e) { throw e; } catch (Exception e) { e.printStackTrace(); throw new MyError(app, "ReplaceFailed"); } catch (MyError e) { e.printStackTrace(); throw new MyError(app, "ReplaceFailed"); } } } return ret; }
/** * @param geo * @return parent node of this geo */ protected DefaultMutableTreeNode getParentNode(GeoElement geo) { DefaultMutableTreeNode parent; switch (treeMode) { case DEPENDENCY: if (geo.isAuxiliaryObject()) { parent = auxiliaryNode; } else if (geo.isIndependent()) { parent = indNode; } else { parent = depNode; } break; case TYPE: // get type node String typeString = geo.getObjectType(); parent = (DefaultMutableTreeNode) typeNodesMap.get(typeString); // do we have to create the parent node? if (parent == null) { String transTypeString = geo.translatedTypeString(); parent = new DefaultMutableTreeNode(transTypeString); typeNodesMap.put(typeString, parent); // find insert pos int pos = rootType.getChildCount(); for (int i = 0; i < pos; i++) { DefaultMutableTreeNode child = (DefaultMutableTreeNode) rootType.getChildAt(i); if (transTypeString.compareTo(child.toString()) < 0) { pos = i; break; } } model.insertNodeInto(parent, rootType, pos); } break; case LAYER: // get type node int layer = geo.getLayer(); parent = (DefaultMutableTreeNode) layerNodesMap.get(layer); // do we have to create the parent node? if (parent == null) { String layerStr = layer + ""; parent = new DefaultMutableTreeNode(layer); layerNodesMap.put(layer, parent); // find insert pos int pos = rootLayer.getChildCount(); for (int i = 0; i < pos; i++) { DefaultMutableTreeNode child = (DefaultMutableTreeNode) rootLayer.getChildAt(i); if (layerStr.compareTo(child.toString()) < 0) { pos = i; break; } } model.insertNodeInto(parent, rootLayer, pos); } break; case ORDER: parent = rootOrder; break; default: parent = null; } return parent; }