/*
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.ArrayList;
import org.geogebra.common.euclidian.EuclidianConstants;
import org.geogebra.common.kernel.Construction;
import org.geogebra.common.kernel.StringTemplate;
import org.geogebra.common.kernel.arithmetic.ExpressionNode;
import org.geogebra.common.kernel.geos.GeoElement;
import org.geogebra.common.kernel.geos.GeoList;
import org.geogebra.common.kernel.kernelND.GeoElementND;
/**
* Algorithm that takes a list of GeoElement objects to build a Geolist with
* them.
*
* @author Markus Hohenwarter
*/
public class AlgoDependentList extends AlgoElement implements DependentAlgo {
private ArrayList<? extends GeoElementND> listItems; // input GeoElements
private GeoList geoList; // output
private boolean isCellRange;
/**
* Creates a new algorithm that takes a list of GeoElements to build a
* Geolist with them.
*
* @param cons
* construction
* @param label
* label for new list
* @param listItems
* list of GeoElement objects
*/
public AlgoDependentList(Construction cons, String label,
ArrayList<? extends GeoElementND> listItems) {
this(cons, listItems, false);
geoList.setLabel(label);
}
/**
* Creates an unlabeled algorithm that takes a list of GeoElements to build
* a Geolist with them.
*
* @param cons
* construction
* @param listItems
* list of GeoElement objects
* @param isCellRange
* true for A1:A10
*/
public AlgoDependentList(Construction cons,
ArrayList<? extends GeoElementND> listItems, boolean isCellRange) {
super(cons);
this.listItems = listItems;
this.isCellRange = isCellRange;
// create output object
geoList = new GeoList(cons);
setInputOutput();
// compute value of dependent number
compute();
}
@Override
public Algos getClassName() {
return Algos.Expression;
}
// for AlgoElement
@Override
protected void setInputOutput() {
// create input array from listItems array-list
// and fill the geoList with these objects
int size = listItems.size();
input = new GeoElement[size];
for (int i = 0; i < size; i++) {
input[i] = listItems.get(i).toGeoElement();
if (!input[i].isLabelSet()) {
input[i].setLabelWanted(false);
}
}
setOutputLength(1);
setOutput(0, geoList);
if (isCellRange) {
setDependenciesOutputOnly();
} else {
setDependencies(); // done by AlgoElement
}
}
/**
* Call super.remove() to remove the list. Then remove all unlabeled input
* objects (= list elements)
*/
@Override
public void remove() {
if (removed) {
return;
}
super.remove();
// removing unlabeled input
for (int i = 0; i < input.length; i++) {
if (!input[i].isLabelSet()) {
input[i].remove();
}
}
}
/**
* Returns the list
*
* @return the list as geo
*/
public GeoList getGeoList() {
return geoList;
}
@Override
public int getRelatedModeID() {
return EuclidianConstants.MODE_CREATE_LIST;
}
@Override
public final void compute() {
geoList.clear();
for (int i = 0; i < input.length; i++) {
// add input and its siblings to the list
// if the siblings are of the same type
AlgoElement algo = input[i].getParentAlgorithm();
if (algo != null && algo.getOutputLength() > 1
&& algo.hasSingleOutputType()) {
// all siblings have same type: add them all
for (int k = 0; k < algo.getOutputLength(); k++) {
GeoElement geo = algo.getOutput(k);
if ((geo == input[i] || geo.isDefined())
&& !geoList.listContains(geo)) {
geoList.add(geo);
}
}
} else {
// independent or mixed sibling types:
// add only this element
geoList.add(input[i]);
}
}
}
private StringBuilder sb;
@Override
final public String toString(StringTemplate tpl) {
if (sb == null) {
sb = new StringBuilder();
} else {
sb.setLength(0);
}
tpl.leftCurlyBracket(sb);
if (input.length > 0) {
for (int i = 0; i < input.length - 1; i++) {
sb.append(input[i].getLabel(tpl));
sb.append(", ");
}
sb.append(input[input.length - 1].getLabel(tpl));
}
tpl.rightCurlyBracket(sb);
return sb.toString();
}
@Override
public ExpressionNode getExpression() {
return geoList.wrap();
}
}