package org.geogebra.common.kernel.statistics; import java.util.ArrayList; import org.geogebra.common.awt.GPoint; import org.geogebra.common.gui.view.spreadsheet.RelativeCopy; import org.geogebra.common.kernel.Kernel; import org.geogebra.common.kernel.MyPoint; import org.geogebra.common.kernel.StringTemplate; import org.geogebra.common.kernel.arithmetic.Command; import org.geogebra.common.kernel.commands.CommandProcessor; import org.geogebra.common.kernel.commands.EvalInfo; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.geos.GeoElementSpreadsheet; import org.geogebra.common.kernel.geos.GeoList; import org.geogebra.common.kernel.geos.GeoLocus; import org.geogebra.common.kernel.geos.GeoNumeric; import org.geogebra.common.main.MyError; import org.geogebra.common.util.debug.Log; import com.google.gwt.regexp.shared.MatchResult; /** * FillCells */ public class CmdFillCells extends CommandProcessor { /** * Create new command processor * * @param kernel * kernel */ public CmdFillCells(Kernel kernel) { super(kernel); } @Override final public GeoElement[] process(Command c, EvalInfo info) throws MyError { if (!info.isScripting()) { return new GeoElement[0]; } int n = c.getArgumentNumber(); GeoElement[] arg; switch (n) { case 2: app.setScrollToShow(false); arg = resArgs(c); if (arg[0].isGeoList()) { GeoList cellRange = (GeoList) arg[0]; if (!(cellRange .getParentAlgorithm() instanceof AlgoCellRange)) { Log.debug("not cell range"); throw argErr(app, c, arg[0]); } AlgoCellRange algo = (AlgoCellRange) cellRange .getParentAlgorithm(); GPoint[] points = algo.getRectangle(); GPoint startCoords = points[0]; GPoint endCoords = points[1]; int minCol = Math.min(startCoords.x, endCoords.x); int maxCol = Math.max(startCoords.x, endCoords.x); int minRow = Math.min(startCoords.y, endCoords.y); int maxRow = Math.max(startCoords.y, endCoords.y); // Application.debug(minCol+" "+maxCol+" "+minRow+" "+maxRow); GeoElement geo = arg[1]; GeoElement[] ret = {}; if (geo.isGeoLocus()) { if (!geo.isDefined()) { throw argErr(app, c, arg[1]); } if (minCol + 1 != maxCol) { throw argErr(app, c, arg[0]); } GeoLocus locus = (GeoLocus) geo; ArrayList<MyPoint> al = locus.getPoints(); int length = Math.min(al.size(), maxRow - minRow); for (int i = 0; i < length; i++) { int row = i + minRow; try { // cell will have been autocreated by eg A1:A3 in // command, so delete removePossibleGeo(GeoElementSpreadsheet .getSpreadsheetCellName(minCol, row)); removePossibleGeo(GeoElementSpreadsheet .getSpreadsheetCellName(minCol + 1, row)); MyPoint p = al.get(i); kernelA.getGeoElementSpreadsheet() .setSpreadsheetCell(app, row, minCol, new GeoNumeric(cons, p.x)); kernelA.getGeoElementSpreadsheet() .setSpreadsheetCell(app, row, minCol + 1, new GeoNumeric(cons, p.y)); } catch (Exception e) { e.printStackTrace(); app.setScrollToShow(true); throw argErr(app, c, arg[1]); } } app.setScrollToShow(true); return ret; } if (!geo.isGeoList()) { for (int row = minRow; row <= maxRow; row++) { for (int col = minCol; col <= maxCol; col++) { try { // cell will have been autocreated by eg A1:A3 // in command, so delete // in case it's being filled by eg GeoText removePossibleGeo(GeoElementSpreadsheet .getSpreadsheetCellName(col, row)); // eg FillCells[B1:B7,A1+1] // change to eg A2+1, A3+1, A4+1 etc // FillCells[B1:B7,A1] doesn't change A1 // use FillCells[B1:B7,A1+0] for that RelativeCopy.doCopyNoStoringUndoInfo0(kernelA, app, geo, null, col - minCol, row - minRow, minRow, minCol); // old code // kernelA.getGeoElementSpreadsheet() // .setSpreadsheetCell(app, row, col, geo); } catch (Exception e) { app.setScrollToShow(true); e.printStackTrace(); throw argErr(app, c, arg[1]); } } } app.setScrollToShow(true); return ret; } GeoList list = (GeoList) geo; if (list.isMatrix()) { int countX = 0; for (int row = minRow; row <= maxRow; row++) { GeoList rowList = (GeoList) list .get(countX % list.size()); countX++; int countY = 0; for (int col = minCol; col <= maxCol; col++) { try { // cell will have been autocreated by eg A1:A3 // in command, so delete // in case it's being filled by eg GeoText removePossibleGeo(GeoElementSpreadsheet .getSpreadsheetCellName(col, row)); kernelA.getGeoElementSpreadsheet() .setSpreadsheetCell(app, row, col, rowList.get(countY % rowList.size())); countY++; } catch (Exception e) { app.setScrollToShow(true); e.printStackTrace(); throw argErr(app, c, arg[1]); } } } } else { // not matrix, just use each list value in turn int count = 0; for (int row = minRow; row <= maxRow; row++) { for (int col = minCol; col <= maxCol; col++) { try { // cell will have been autocreated by eg A1:A3 // in command, so delete // in case it's being filled by eg GeoText removePossibleGeo(GeoElementSpreadsheet .getSpreadsheetCellName(col, row)); kernelA.getGeoElementSpreadsheet() .setSpreadsheetCell(app, row, col, list.get(count % list.size())); count++; } catch (Exception e) { app.setScrollToShow(true); e.printStackTrace(); throw argErr(app, c, arg[1]); } } } } app.storeUndoInfo(); app.setScrollToShow(true); return ret; } // arg[0] not list { if (GeoElementSpreadsheet.hasSpreadsheetLabel(arg[0])) { if (!arg[1].isGeoList()) { app.setScrollToShow(true); throw argErr(app, c, arg[1]); } GeoList list = (GeoList) arg[1]; MatchResult matcher = GeoElementSpreadsheet.spreadsheetPattern .exec(arg[0].getLabel(StringTemplate.defaultTemplate)); int column = GeoElementSpreadsheet .getSpreadsheetColumn(matcher); int row = GeoElementSpreadsheet.getSpreadsheetRow(matcher); if (row == -1 || column == -1) { app.setScrollToShow(true); throw argErr(app, c, arg[0]); } if (list.isMatrix()) { // 2D fill // FillCells[B3,{"a","b"}] will autocreate B3=0 so we // need to remove B3 if (arg[0] != null) { arg[0].remove(); } try { int rows = list.size(); int cols = ((GeoList) list.get(0)).size(); for (int r = 0; r < rows; r++) { GeoList rowList = (GeoList) list.get(r); for (int c1 = 0; c1 < cols; c1++) { kernelA.getGeoElementSpreadsheet() .setSpreadsheetCell(app, row + r, column + c1, rowList.get(c1).copy()); } } } catch (Exception e) { app.setScrollToShow(true); throw argErr(app, c, list); } } else { // 1D fill // FillCells[B3,{"a","b"}] will autocreate B3=0 so we // need to remove B3 if (arg[0] != null) { arg[0].remove(); } for (int i = list.size() - 1; i >= 0; i--) { try { // Application.debug("setting "+row+" "+(column+i)+" // to "+list.get(i).toString()); kernelA.getGeoElementSpreadsheet() .setSpreadsheetCell(app, row, column + i, list.get(i).copy()); } catch (Exception e) { e.printStackTrace(); app.setScrollToShow(true); throw argErr(app, c, arg[1]); } } } } else { app.setScrollToShow(true); throw argErr(app, c, arg[0]); } } GeoElement[] ret = {}; app.storeUndoInfo(); app.setScrollToShow(true); return ret; default: throw argNumErr(app, c, n); } } private void removePossibleGeo(String label) { GeoElement geo = kernelA.lookupLabel(label); if (geo != null) { geo.remove(); } } }