package org.geogebra.common.cas.view; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.Vector; import org.geogebra.common.kernel.StringTemplate; import org.geogebra.common.kernel.arithmetic.ValidExpression; import org.geogebra.common.kernel.geos.GeoCasCell; import org.geogebra.common.kernel.geos.GeoElement; /** * Common class for substitution dialogs * * @author balazs.bencze * */ public abstract class CASSubDialog { /** * Class containing row information */ protected static class SubstituteValue { private String variable; private String value; /** * @param var * old expression * @param val * new expression */ public SubstituteValue(String var, String val) { variable = var; value = val; } /** * @return old expression */ public String getVariable() { return variable; } /** * @param var * variable */ public void setVariable(String var) { variable = var; } /** * @return new expression */ public String getValue() { return value; } /** * @param val * value */ public void setValue(String val) { value = val; } } /** Editing row from CAS table */ protected int editRow; /** Evaluation prefix */ protected String prefix; /** Evaluation text */ protected String evalText; /** Evaluation postfix */ protected String postfix; /** Evaluation symbol */ protected static final String EVAL_SYM = "="; /** Numeric symbol */ protected static final String NUM_SYM = "\u2248"; /** Substitute symbol */ protected static final String SUB_SYM = "\u2713"; /** Evaluation action command */ protected static final String ACTION_EVALUATE = "Evaluate"; /** Numeric action command */ protected static final String ACTION_NUMERIC = "Numeric"; /** Substitute action command */ protected static final String ACTION_SUBSTITUTE = "Substitute"; /** Contains substitution values */ protected Vector<Vector<String>> data; /** * @param prefix * before selection, not effected by the substitution * @param evalText * the String which will be substituted * @param postfix * after selection, not effected by the substitution * @param editRow * row to edit */ public CASSubDialog(String prefix, String evalText, String postfix, int editRow) { this.prefix = prefix; this.evalText = evalText; this.postfix = postfix; this.editRow = editRow; } /** * @return casView */ protected abstract CASView getCASView(); /** * @param cell * initialize table with cell information */ protected void initData(GeoCasCell cell) { HashSet<GeoElement> vars = new HashSet<GeoElement>(); if (cell.getInputVE().getVariables() != null) { for (GeoElement var : cell.getInputVE().getVariables()) { addVariables(var, vars); } } // get the substitution list from cell ArrayList<Vector<String>> substList = cell.getSubstList(); Vector<String> row; data = new Vector<Vector<String>>(vars.size() + 1); Iterator<GeoElement> iter = vars.iterator(); while (iter.hasNext()) { row = new Vector<String>(2); GeoElement var = iter.next(); String nextVar = var.getLabel(StringTemplate.defaultTemplate); int i = 0; for (i = 0; i < data.size(); i++) { if (data.get(i).firstElement().compareTo(nextVar) >= 0) { break; } } if (i == data.size() || !data.get(i).firstElement().equals(nextVar)) { row.add(nextVar); boolean added = false; if (substList != null && !substList.isEmpty()) { // search for nextVar in subst list for (int k = 0; k < substList.size(); k++) { // case we found it if (substList.get(k).get(0).equals(nextVar)) { // add to substitution data row.add(substList.get(k).get(1)); added = true; break; } } } // case we didn't found if (!added) { row.add(""); } data.insertElementAt(row, i); } } row = new Vector<String>(2); row.add(""); row.add(""); data.add(row); } private static void addVariables(GeoElement var, HashSet<GeoElement> vars) { if (var instanceof GeoCasCell) { ValidExpression ve = ((GeoCasCell) var).getOutputValidExpression(); if (ve != null) { vars.addAll(ve.getVariables()); } } else { vars.add(var); } } /** * @param actionCommand * Evaluate || Numeric || Substitute * @return true iff any substitution applied */ protected boolean apply(String actionCommand) { CASTable table = getCASView().getConsoleTable(); // create substitution list StringBuilder substList = new StringBuilder("{"); StringBuilder substComment = new StringBuilder(); for (int i = 0; i < data.size(); i++) { String fromExpr = data.get(i).get(0).trim(); String toExpr = data.get(i).get(1).trim(); if (!"".equals(fromExpr) && !"".equals(toExpr)) { if (substList.length() > 1) { substList.append(','); substComment.append(','); } fromExpr = getCASView().resolveCASrowReferences(fromExpr, editRow); toExpr = getCASView().resolveCASrowReferences(toExpr, editRow); substList.append(fromExpr); substList.append('='); substList.append(toExpr); substComment.append(fromExpr); substComment.append('='); substComment.append(toExpr); } } substList.append('}'); if ("{}".equals(substList.toString())) { return false; } // make sure pure substitute is not evaluated boolean keepInput = false; // substitute command String subCmd = "Substitute[" + evalText + "," + substList + "]"; if ("Substitute".equals(actionCommand)) { subCmd = "Substitute[" + evalText + "," + substList + "]"; keepInput = true; } else if ("Numeric".equals(actionCommand)) { subCmd = "Numeric[" + subCmd + "]"; keepInput = false; } try { GeoCasCell currCell = table.getGeoCasCell(editRow); currCell.setProcessingInformation(prefix, subCmd, postfix); currCell.setEvalCommand("Substitute"); currCell.setEvalComment(substComment.toString()); // make sure pure substitute is not evaluated currCell.setKeepInputUsed(keepInput); getCASView().processRowThenEdit(editRow); // table.startEditingRow(editRow + 1); return true; } catch (Throwable e) { e.printStackTrace(); return false; } } }