/* GeoGebra - Dynamic Mathematics for Everyone http://www.geogebra.org This file is part of GeoGebra. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. */ package org.geogebra.common.kernel.algos; import java.util.Iterator; import org.geogebra.common.kernel.Construction; import org.geogebra.common.kernel.commands.Commands; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.geos.GeoText; /** * Returns the GeoElement from an object's label. * * @author Michael, Markus */ public class AlgoObject extends AlgoElement { private GeoElement geo; // output private GeoText text; // input private String currentLabel; private GeoElement refObject; // referenced object private GeoElement[] inputForUpdateSetPropagation; /** * Creates new algorithm for Object[name]. * * @param cons * construction * @param label * label * @param text * object name */ public AlgoObject(Construction cons, String label, GeoText text) { super(cons); this.text = text; // Object["A" + d] might gives "A2.00" if significant figures used // globally // want it to give "A2" if (!text.isLabelSet()) { text.setPrintDecimals(0, true); } setInputOutput(); // for AlgoElement // compute value of dependent number compute(); // register as rename listener algorithm kernel.registerRenameListenerAlgo(this); geo.setLabel(label); } @Override public Commands getClassName() { return Commands.Object; } // for AlgoElement @Override protected void setInputOutput() { // input is the text input = new GeoElement[1]; input[0] = text; // input for updateSet propagation is text and reference object inputForUpdateSetPropagation = new GeoElement[2]; inputForUpdateSetPropagation[0] = text; // get referenced object updateReferencedObject(); // create output object as copy of referenced object if (refObject != null) { geo = refObject.copyInternal(cons); geo.setVisualStyle(refObject); geo.setUseVisualDefaults(false); } else { geo = cons.getOutputGeo(); geo.setUndefined(); } // output is a copy of the referenced object super.setOutputLength(1); super.setOutput(0, geo); setDependencies(); } /** * @return object with given name */ public GeoElement getResult() { return geo; } @Override public final void compute() { // did name of object change? // removed - doesn't update when referenced object deleted // if (currentLabel != text.getTextString() || refObject == null) { updateReferencedObject(); // } // check if updateInput has same type if (refObject != null && refObject.getGeoClassType() == geo.getGeoClassType()) { geo.set(refObject); } else { geo.setUndefined(); } } private void updateReferencedObject() { // get new object currentLabel = text.getTextString(); /* * Do not remove this algorithm from update set of old referenced * object: This will speed up the calls to * refObject.addToUpdateSetOnly() below, because it will always stop * propagating up at refObject. * * if (refObject != null) { refObject.getAlgoUpdateSet().remove(this); } */ // lookup new object for new label refObject = kernel.lookupLabel(currentLabel); inputForUpdateSetPropagation[1] = refObject; // change dependencies for this newly referenced object if (refObject != null) { // add this algorithm and all its dependent algos to the update set // of the newly referenced geo refObject.addToUpdateSetOnly(this); if (geo != null) { Iterator<AlgoElement> it = geo.getAlgoUpdateSet().getIterator(); while (it.hasNext()) { refObject.addToUpdateSetOnly(it.next()); } } } } /** * Returns an input array with the text and the referenced geo */ @Override public GeoElement[] getInputForUpdateSetPropagation() { if (refObject == null) { return input; } return inputForUpdateSetPropagation; } }