Example #1
0
  // calc the current value of the arithmetic tree
  @Override
  public final void compute() {
    String col =
        GeoElementSpreadsheet.getSpreadsheetColumnName(
            geo.getLabel(StringTemplate.defaultTemplate));

    if (col == null) text.setUndefined();
    else text.setTextString(col);
  }
Example #2
0
  /**
   * Prepares a spreadsheet cell editor string for processing in the kernel and returns either (1) a
   * new GeoElement for the cell or (2) null.
   *
   * @param kernel kernel
   * @param app application
   * @param inputText string representation of the new GeoElement
   * @param oldValue current cell GeoElement
   * @param column cell column
   * @param row cell row
   * @return either (1) a new GeoElement for the cell or (2) null
   * @throws Exception
   */
  public static GeoElement prepareAddingValueToTableNoStoringUndoInfo(
      Kernel kernel, App app, String inputText, GeoElement oldValue, int column, int row)
      throws Exception {
    String text = inputText;
    // get the cell name
    String name = GeoElementSpreadsheet.getSpreadsheetCellName(column, row);

    // trim the text
    if (text != null) {
      text = text.trim();
      if (text.length() == 0) {
        text = null;
      }
    }

    // if "=" is required before commands and text is not a number
    // or does not begin with "=" then surround it with quotes.
    // This will force the cell to become GeoText.
    if (app.getSettings().getSpreadsheet().equalsRequired() && text != null) {

      if (!((text.charAt(0) == '=') || isNumber(text))) {
        text = "\"" + text + "\"";
      }
    }

    // if the cell is currently GeoText then prepare it for changes
    // make sure it can be changed to something else
    // eg (2,3 can be overwritten as (2,3)
    // if (oldValue != null && oldValue.isGeoText() &&
    // !oldValue.hasChildren()) {
    // oldValue.remove();
    // oldValue = null;
    // }

    // if the text is null then remove the current cell geo and return null
    if (text == null) {
      if (oldValue != null) {
        oldValue.remove();
      }
      return null;

      // else if the target cell is empty, try to create a new GeoElement
      // for this cell
    } else if (oldValue == null) {
      try {
        // this will be a new geo
        return prepareNewValue(kernel, name, text);
      } catch (Throwable t) {
        return prepareNewValue(kernel, name, "");
      }

      // else the target cell is an existing GeoElement, so redefine it
    } else {
      return updateOldValue(kernel, oldValue, name, text);
    }
  }
Example #3
0
  /**
   * Performs spreadsheet drag-copy operation.
   *
   * @param sx1 source minimum column
   * @param sy1 source minimum row
   * @param sx2 source maximum column
   * @param sy2 source maximum row
   * @param dx1 destination minimum column
   * @param dy1 destination minimum row
   * @param dx2 destination maximum column
   * @param dy2 destination maximum row
   * @return
   */
  public boolean doDragCopy(
      int sx1, int sy1, int sx2, int sy2, int dx1, int dy1, int dx2, int dy2) {
    // -|1|-
    // 2|-|3
    // -|4|-
    app.setWaitCursor();
    Construction cons = kernel.getConstruction();

    try {
      boolean success = false;

      // collect all redefine operations
      cons.startCollectingRedefineCalls();

      boolean patternOK = isPatternSource(new CellRange(app, sx1, sy1, sx2, sy2));

      // ==============================================
      // vertical drag
      // ==============================================
      if ((sx1 == dx1) && (sx2 == dx2)) {

        if (dy2 < sy1) { // 1 ----- drag up
          if (((sy1 + 1) == sy2) && patternOK) {
            // two row source, so drag copy a linear pattern
            for (int x = sx1; x <= sx2; ++x) {
              GeoElement v1 = getValue(app, x, sy1);
              GeoElement v2 = getValue(app, x, sy2);
              if ((v1 == null) || (v2 == null)) {
                continue;
              }
              for (int y = dy2; y >= dy1; --y) {
                GeoElement v3 = getValue(app, x, y + 2);
                GeoElement v4 = getValue(app, x, y + 1);
                String vs1 = v3.isGeoFunction() ? "(x)" : "";
                String vs2 = v4.isGeoFunction() ? "(x)" : "";
                String d0 = GeoElementSpreadsheet.getSpreadsheetCellName(x, y + 2) + vs1;
                String d1 = GeoElementSpreadsheet.getSpreadsheetCellName(x, y + 1) + vs2;
                String text = "=2*" + d1 + "-" + d0;
                doCopyNoStoringUndoInfo1(kernel, app, text, v4, x, y);
              }
            }
          } else { // not two row source, so drag-copy the first row
            // of the source
            doCopyVerticalNoStoringUndoInfo1(sx1, sx2, sy1, dy1, dy2);
          }
          success = true;
        } else if (dy1 > sy2) { // 4 ---- drag down
          if (((sy1 + 1) == sy2) && patternOK) {
            // two row source, so drag copy a linear pattern
            for (int x = sx1; x <= sx2; ++x) {
              GeoElement v1 = getValue(app, x, sy1);
              GeoElement v2 = getValue(app, x, sy2);
              if ((v1 == null) || (v2 == null)) {
                continue;
              }
              for (int y = dy1; y <= dy2; ++y) {
                GeoElement v3 = getValue(app, x, y - 2);
                GeoElement v4 = getValue(app, x, y - 1);
                String vs1 = v3.isGeoFunction() ? "(x)" : "";
                String vs2 = v4.isGeoFunction() ? "(x)" : "";
                String d0 = GeoElementSpreadsheet.getSpreadsheetCellName(x, y - 2) + vs1;
                String d1 = GeoElementSpreadsheet.getSpreadsheetCellName(x, y - 1) + vs2;
                String text = "=2*" + d1 + "-" + d0;
                doCopyNoStoringUndoInfo1(kernel, app, text, v4, x, y);
              }
            }
          } else {
            // not two row source, so drag-copy the last row of the
            // source
            doCopyVerticalNoStoringUndoInfo1(sx1, sx2, sy2, dy1, dy2);
          }
          success = true;
        }
      }

      // ==============================================
      // horizontal drag
      // ==============================================
      else if ((sy1 == dy1) && (sy2 == dy2)) {
        if (dx2 < sx1) { // 2 ---- drag left
          if (((sx1 + 1) == sx2) && patternOK) {
            // two column source, so drag copy a linear pattern
            for (int y = sy1; y <= sy2; ++y) {
              GeoElement v1 = getValue(app, sx1, y);
              GeoElement v2 = getValue(app, sx2, y);
              if ((v1 == null) || (v2 == null)) {
                continue;
              }
              for (int x = dx2; x >= dx1; --x) {
                GeoElement v3 = getValue(app, x + 2, y);
                GeoElement v4 = getValue(app, x + 1, y);
                String vs1 = v3.isGeoFunction() ? "(x)" : "";
                String vs2 = v4.isGeoFunction() ? "(x)" : "";
                String d0 = GeoElementSpreadsheet.getSpreadsheetCellName(x + 2, y) + vs1;
                String d1 = GeoElementSpreadsheet.getSpreadsheetCellName(x + 1, y) + vs2;
                String text = "=2*" + d1 + "-" + d0;
                doCopyNoStoringUndoInfo1(kernel, app, text, v4, x, y);
              }
            }
          } else {
            // not two column source, so drag-copy the first column
            // of the source
            doCopyHorizontalNoStoringUndoInfo1(sy1, sy2, sx1, dx1, dx2);
          }
          success = true;
        } else if (dx1 > sx2) { // 4 --- drag right
          if (((sx1 + 1) == sx2) && patternOK) {
            // two column source, so drag copy a linear pattern
            for (int y = sy1; y <= sy2; ++y) {
              GeoElement v1 = getValue(app, sx1, y);
              GeoElement v2 = getValue(app, sx2, y);
              if ((v1 == null) || (v2 == null)) {
                continue;
              }
              for (int x = dx1; x <= dx2; ++x) {
                GeoElement v3 = getValue(app, x - 2, y);
                GeoElement v4 = getValue(app, x - 1, y);
                String vs1 = v3.isGeoFunction() ? "(x)" : "";
                String vs2 = v4.isGeoFunction() ? "(x)" : "";
                String d0 = GeoElementSpreadsheet.getSpreadsheetCellName(x - 2, y) + vs1;
                String d1 = GeoElementSpreadsheet.getSpreadsheetCellName(x - 1, y) + vs2;
                String text = "=2*" + d1 + "-" + d0;
                doCopyNoStoringUndoInfo1(kernel, app, text, v4, x, y);
              }
            }
          } else {
            // not two column source, so drag-copy the last column
            // of the source
            doCopyHorizontalNoStoringUndoInfo1(sy1, sy2, sx2, dx1, dx2);
          }
          success = true;
        }
      }

      // now do all redefining and build new construction
      cons.processCollectedRedefineCalls();

      if (success) {
        return true;
      }

      String msg =
          "sx1 = " + sx1 + "\r\n" + "sy1 = " + sy1 + "\r\n" + "sx2 = " + sx2 + "\r\n" + "sy2 = "
              + sy2 + "\r\n" + "dx1 = " + dx1 + "\r\n" + "dy1 = " + dy1 + "\r\n" + "dx2 = " + dx2
              + "\r\n" + "dy2 = " + dy2 + "\r\n";
      throw new RuntimeException("Error from RelativeCopy.doCopy:\r\n" + msg);
    } catch (Exception ex) {
      // kernel.getApplication().showError(ex.getMessage());
      ex.printStackTrace();
      return false;
    } finally {
      cons.stopCollectingRedefineCalls();
      app.setDefaultCursor();
    }
  }
Example #4
0
  /**
   * Updates the cell references in text according to a relative copy in the spreadsheet of offset
   * (dx,dy) (changes only dependents of value) eg change A1 < 3 to A2 < 3 for a vertical copy
   */
  public static String updateCellReferences(GeoElement value, String inputText, int dx, int dy) {
    String text = inputText;
    StringBuilder before = new StringBuilder();
    StringBuilder after = new StringBuilder();

    GeoElement[] dependents = getDependentObjects(value);
    GeoElement[] dependents2 = new GeoElement[dependents.length + 1];
    for (int i = 0; i < dependents.length; ++i) {
      dependents2[i] = dependents[i];
    }
    dependents = dependents2;
    dependents[dependents.length - 1] = value;
    for (int i = 0; i < dependents.length; ++i) {
      String name = dependents[i].getLabel(StringTemplate.defaultTemplate);
      MatchResult matcher = GeoElementSpreadsheet.spreadsheetPatternPart.exec(name);
      int column = GeoElementSpreadsheet.getSpreadsheetColumn(matcher);
      int row = GeoElementSpreadsheet.getSpreadsheetRow(matcher);

      if ((column == -1) || (row == -1)) {
        continue;
      }
      String column1 = GeoElementSpreadsheet.getSpreadsheetColumnName(column);
      String row1 = "" + (row + 1);

      before.setLength(0);
      before.append('$');
      before.append(column1);
      before.append(row1);
      after.setLength(0);
      after.append('$');
      after.append(column1);
      after.append("::");
      after.append(row1);
      text =
          replaceAll(
              GeoElementSpreadsheet.spreadsheetPatternPart,
              text,
              before.toString(),
              after.toString());
      // text = replaceAll(AbstractGeoElementSpreadsheet.spreadsheetPatternPart, text,
      // "$" + column1 + row1, "$" + column1 + "::" + row1);

      before.setLength(0);
      before.append(column1);
      before.append('$');
      before.append(row1);
      after.setLength(0);
      after.append("::");
      after.append(column1);
      after.append('$');
      after.append(row1);
      text =
          replaceAll(
              GeoElementSpreadsheet.spreadsheetPatternPart,
              text,
              before.toString(),
              after.toString());
      // text = replaceAll(AbstractGeoElementSpreadsheet.spreadsheetPatternPart, text,
      // column1 + "$" + row1, "::" + column1 + "$" + row1);

      before.setLength(0);
      before.append(column1);
      before.append(row1);
      after.setLength(0);
      after.append("::");
      after.append(column1);
      after.append("::");
      after.append(row1);
      text =
          replaceAll(
              GeoElementSpreadsheet.spreadsheetPatternPart,
              text,
              before.toString(),
              after.toString());
      // text = replaceAll(AbstractGeoElementSpreadsheet.spreadsheetPatternPart, text,
      // column1 + row1, "::" + column1 + "::" + row1);

    }

    // TODO is this a bug in the regex?
    // needed for eg Mod[$A2, B$1] which gives Mod[$A2, ::::B$1]
    // =$B$1 BinomialCoefficient[B$2, $A3] gives BinomialCoefficient[::::::B$2, $A::3]
    text = text.replace("::::::", "::");
    text = text.replace("::::", "::");

    MatchResult matcher =
        GeoElementSpreadsheet.spreadsheetPatternPart.exec(
            value.getLabel(StringTemplate.defaultTemplate));
    for (int i = 0; i < dependents.length; ++i) {
      String name = dependents[i].getLabel(StringTemplate.defaultTemplate);
      matcher = GeoElementSpreadsheet.spreadsheetPatternPart.exec(name);
      int column = GeoElementSpreadsheet.getSpreadsheetColumn(matcher);
      int row = GeoElementSpreadsheet.getSpreadsheetRow(matcher);
      if ((column == -1) || (row == -1)) {
        continue;
      }
      String column1 = GeoElementSpreadsheet.getSpreadsheetColumnName(column);
      String row1 = "" + (row + 1);
      String column2 = GeoElementSpreadsheet.getSpreadsheetColumnName(column + dx);
      String row2 = "" + (row + dy + 1);

      before.setLength(0);
      before.append("::");
      before.append(column1);
      before.append("::");
      before.append(row1);
      after.setLength(0);
      after.append(' '); // space important eg 2 E2 not 2E2
      after.append(column2);
      after.append(row2);
      text = replaceAll(pattern2, text, before.toString(), after.toString());
      // text = replaceAll(pattern2, text, "::" + column1 + "::" + row1,
      // "("+ column2 + row2 + ")");

      before.setLength(0);
      before.append("$");
      before.append(column1);
      before.append("::");
      before.append(row1);
      after.setLength(0);
      after.append('$');
      after.append(column1);
      after.append(row2);
      text = replaceAll(pattern2, text, before.toString(), after.toString());
      // text = replaceAll(pattern2, text, "$" + column1 + "::" + row1,
      // "$" + column1 + row2);

      before.setLength(0);
      before.append("::");
      before.append(column1);
      before.append('$');
      before.append(row1);
      after.setLength(0);
      after.append(column2);
      after.append('$');
      after.append(row1);
      text = replaceAll(pattern2, text, before.toString(), after.toString());
      // text = replaceAll(pattern2, text, "::" + column1 + "$" + row1,
      // column2 + "$" + row1);

    }

    return text;
  }
Example #5
0
  public static GeoElement doCopyNoStoringUndoInfo0(
      Kernel kernel, App app, GeoElement value, GeoElement oldValue, int dx, int dy)
      throws Exception {
    if (value == null) {
      if (oldValue != null) {
        MatchResult matcher =
            GeoElementSpreadsheet.spreadsheetPatternPart.exec(
                oldValue.getLabel(StringTemplate.defaultTemplate));
        int column = GeoElementSpreadsheet.getSpreadsheetColumn(matcher);
        int row = GeoElementSpreadsheet.getSpreadsheetRow(matcher);

        prepareAddingValueToTableNoStoringUndoInfo(kernel, app, null, oldValue, column, row);
      }
      return null;
    }
    String text = null;

    // make sure a/0.001 doesn't become a/0

    StringTemplate highPrecision = StringTemplate.maxPrecision;
    if (value.isPointOnPath() || value.isPointInRegion()) {
      text = value.getCommandDescription(highPrecision);
    } else if (value.isChangeable()) {
      text = value.toValueString(highPrecision);
    } else {
      text = value.getCommandDescription(highPrecision);
    }

    // handle GeoText source value
    if (value.isGeoText() && !((GeoText) value).isTextCommand()) {
      // enclose text in quotes if we are copying an independent GeoText,
      // e.g. "2+3"
      if (value.isIndependent()) {
        text = "\"" + text + "\"";
      } else {

        // check if 'text' parses to a GeoText
        GeoText testGeoText = kernel.getAlgebraProcessor().evaluateToText(text, false, false);

        // if it doesn't then force it to by adding +"" on the end
        if (testGeoText == null) {
          text = text + "+\"\"";
        }
      }
    }

    // for E1 = Polynomial[D1] we need value.getCommandDescription();
    // even though it's a GeoFunction
    if (value.isGeoFunction() && text.equals("")) {
      // we need the definition without A1(x)= on the front
      text = ((GeoFunction) value).toSymbolicString(highPrecision);
    }

    boolean freeImage = false;

    if (value.isGeoImage()) {
      GeoImage image = (GeoImage) value;
      if (image.getParentAlgorithm() == null) {
        freeImage = true;
      }
    }

    // Application.debug("before:"+text);
    text = updateCellReferences(value, text, dx, dy);
    // Application.debug("after:"+text);

    // condition to show object
    GeoBoolean bool = value.getShowObjectCondition();
    String boolText = null, oldBoolText = null;
    if (bool != null) {
      if (bool.isChangeable()) {
        oldBoolText = bool.toValueString(highPrecision);
      } else {
        oldBoolText = bool.getCommandDescription(highPrecision);
      }
    }

    if (oldBoolText != null) {
      boolText = updateCellReferences(bool, oldBoolText, dx, dy);
    }

    String startPoints[] = null;
    if (value instanceof Locateable) {
      Locateable loc = (Locateable) value;

      GeoPointND[] pts = loc.getStartPoints();

      startPoints = new String[pts.length];

      for (int i = 0; i < pts.length; i++) {
        startPoints[i] = ((GeoElement) pts[i]).getLabel(highPrecision);
        startPoints[i] = updateCellReferences((GeoElement) pts[i], startPoints[i], dx, dy);
      }
    }

    // dynamic color function
    GeoList dynamicColorList = value.getColorFunction();
    String colorText = null, oldColorText = null;
    if (dynamicColorList != null) {
      if (dynamicColorList.isChangeable()) {
        oldColorText = dynamicColorList.toValueString(highPrecision);
      } else {
        oldColorText = dynamicColorList.getCommandDescription(highPrecision);
      }
    }

    if (oldColorText != null) {
      colorText = updateCellReferences(dynamicColorList, oldColorText, dx, dy);
    }

    // allow pasting blank strings
    if (text.equals("")) {
      text = "\"\"";
    }

    // make sure that non-GeoText elements are copied when the
    // equalsRequired option is set
    if (!value.isGeoText() && app.getSettings().getSpreadsheet().equalsRequired()) {
      text = "=" + text;
    }

    // Application.debug("add text = " + text + ", name = " + (char)('A' +
    // column + dx) + (row + dy + 1));

    // create the new cell geo
    MatchResult matcher =
        GeoElementSpreadsheet.spreadsheetPatternPart.exec(
            value.getLabel(StringTemplate.defaultTemplate));
    int column0 = GeoElementSpreadsheet.getSpreadsheetColumn(matcher);
    int row0 = GeoElementSpreadsheet.getSpreadsheetRow(matcher);
    GeoElement value2;
    if (freeImage || value.isGeoButton()) {
      value2 = value.copy();
      if (oldValue != null) {
        oldValue.remove();
      }
      // value2.setLabel(table.getModel().getColumnName(column0 + dx)
      //		+ (row0 + dy + 1));
      value2.setLabel(GeoElementSpreadsheet.getSpreadsheetCellName(column0 + dx, row0 + dy + 1));
      value2.updateRepaint();
    } else {
      value2 =
          prepareAddingValueToTableNoStoringUndoInfo(
              kernel, app, text, oldValue, column0 + dx, row0 + dy);
    }
    value2.setAllVisualProperties(value, false);

    value2.setAuxiliaryObject(true);

    // attempt to set updated condition to show object (if it's changed)
    if ((boolText != null)) {
      // removed as doesn't work for eg "random()<0.5" #388
      // && !boolText.equals(oldBoolText)) {
      try {
        // Application.debug("new condition to show object: "+boolText);
        GeoBoolean newConditionToShowObject =
            kernel.getAlgebraProcessor().evaluateToBoolean(boolText);
        value2.setShowObjectCondition(newConditionToShowObject);
        value2.update(); // needed to hide/show object as appropriate
      } catch (Exception e) {
        e.printStackTrace();
        return null;
      }
    }

    // attempt to set updated dynamic color function (if it's changed)
    if ((colorText != null)) {
      // removed as doesn't work for eg "random()" #388
      // && !colorText.equals(oldColorText)) {
      try {
        // Application.debug("new color function: "+colorText);
        GeoList newColorFunction = kernel.getAlgebraProcessor().evaluateToList(colorText);
        value2.setColorFunction(newColorFunction);
        // value2.update();
      } catch (Exception e) {
        e.printStackTrace();
        return null;
      }
    }

    if (startPoints != null) {
      for (int i = 0; i < startPoints.length; i++) {
        ((Locateable) value2)
            .setStartPoint(
                kernel.getAlgebraProcessor().evaluateToPoint(startPoints[i], false, true), i);
      }

      value2.update();
    }

    // Application.debug((row + dy) + "," + column);
    // Application.debug("isGeoFunction()=" + value2.isGeoFunction());
    // Application.debug("row0 ="+row0+" dy="+dy+" column0= "+column0+" dx="+dx);

    return value2;
  }
  public void onMouseMove(MouseMoveEvent e) {

    GPoint p = table.getIndexFromPixel(e.getClientX(), e.getClientY());
    if (p.getY() == 0 && p.getX() > 0) {
      table.scc.onMouseMove(e);
      return;
    } else if (p.getX() == 0 && p.getY() > 0) {
      table.srh.onMouseMove(e);
      return;
    }

    e.preventDefault();
    boolean eConsumed = false;

    // TODO: move the content of the mouseMoved method here

    // DRAG

    if (mouseIsDown) {

      if (table.getTableMode() == MyTable.TABLE_MODE_AUTOFUNCTION
          || table.getTableMode() == MyTable.TABLE_MODE_DROP) {
        // System.out.println("drop is dragging ");
        return;
      }

      // handle editing mode drag
      if (editor.isEditing()) {
        GPoint point = table.getIndexFromPixel(e.getClientX(), e.getClientY());
        if (point != null && selectedCellName != null) {
          int column2 = point.getX() - 1;
          int row2 = point.getY() - 1;

          MatchResult matcher = GeoElementSpreadsheet.spreadsheetPattern.exec(selectedCellName);
          int column1 = GeoElementSpreadsheet.getSpreadsheetColumn(matcher);
          int row1 = GeoElementSpreadsheet.getSpreadsheetRow(matcher);

          if (column1 > column2) {
            int temp = column1;
            column1 = column2;
            column2 = temp;
          }
          if (row1 > row2) {
            int temp = row1;
            row1 = row2;
            row2 = temp;
          }
          String name1 = GeoElementSpreadsheet.getSpreadsheetCellName(column1, row1);
          String name2 = GeoElementSpreadsheet.getSpreadsheetCellName(column2, row2);
          if (!name1.equals(name2)) {
            name1 += ":" + name2;
          }

          name1 = prefix0 + name1 + postfix0;
          editor.setLabel(name1);
          table.minColumn2 = column1;
          table.maxColumn2 = column2;
          table.minRow2 = row1;
          table.maxRow2 = row2;
          table.repaint();
        }
        return;
      }

      // handle dot drag
      if (table.isDragingDot) {

        eConsumed = true;
        int mouseX = e.getClientX();
        int mouseY = e.getClientY();
        GPoint mouseCell = table.getIndexFromPixel(mouseX, mouseY);

        // save the selected cell position so it can be re-selected if
        // needed
        CellRange oldSelection = table.getSelectedCellRanges().get(0);

        if (mouseCell == null) { // user has dragged outside the table, to
          // left or above
          table.dragingToRow = -1;
          table.dragingToColumn = -1;
        } else {
          table.dragingToRow = mouseCell.getY();
          table.dragingToColumn = mouseCell.getX();
          GRectangle selRect = table.getSelectionRect(true);

          // increase size if we're at the bottom of the spreadsheet
          if (table.dragingToRow + 1 == table.getRowCount()
              && table.dragingToRow < Kernel.MAX_SPREADSHEET_ROWS) {
            model.setRowCount(table.getRowCount() + 1);
          }

          // increase size if we go beyond the right edge
          if (table.dragingToColumn + 1 == table.getColumnCount()
              && table.dragingToColumn < Kernel.MAX_SPREADSHEET_COLUMNS) {
            model.setColumnCount(table.getColumnCount() + 1);
            view.columnHeaderRevalidate();
            // Java's addColumn method will clear selection, so
            // re-select our cell
            table.setSelection(oldSelection);
          }

          // scroll to show "highest" selected cell
          // TODO//table.scrollRectToVisible(table.getCellRect(mouseCell.y, mouseCell.x, true));

          if (!selRect.contains(e.getClientX(), e.getClientY())) {

            int rowOffset = 0, colOffset = 0;

            // get row distance
            if (table.minSelectionRow > 0 && table.dragingToRow < table.minSelectionRow) {
              rowOffset = mouseY - (int) selRect.getY();
              if (-rowOffset
                  < 0.5
                      * table
                          .getCellRect(table.minSelectionRow - 1, table.minSelectionColumn, true)
                          .getHeight()) rowOffset = 0;
            } else if (table.maxSelectionRow < Kernel.MAX_SPREADSHEET_ROWS
                && table.dragingToRow > table.maxSelectionRow) {
              rowOffset = mouseY - ((int) selRect.getY() + (int) selRect.getHeight());
              if (rowOffset
                  < 0.5
                      * table
                          .getCellRect(table.maxSelectionRow + 1, table.maxSelectionColumn, true)
                          .getHeight()) rowOffset = 0;
            }

            // get column distance
            if (table.minSelectionColumn > 0 && table.dragingToColumn < table.minSelectionColumn) {
              colOffset = mouseX - (int) selRect.getX();
              if (-colOffset
                  < 0.5
                      * table
                          .getCellRect(table.minSelectionRow, table.minSelectionColumn - 1, true)
                          .getWidth()) colOffset = 0;
            } else if (table.maxSelectionColumn < Kernel.MAX_SPREADSHEET_COLUMNS
                && table.dragingToColumn > table.maxSelectionColumn) {
              colOffset = mouseX - ((int) selRect.getX() + (int) selRect.getWidth());
              if (colOffset
                  < 0.5
                      * table
                          .getCellRect(table.maxSelectionRow, table.maxSelectionColumn + 1, true)
                          .getWidth()) colOffset = 0;
            }

            if (rowOffset == 0 && colOffset == 0) {
              table.dragingToColumn = -1;
              table.dragingToRow = -1;
            } else if (Math.abs(rowOffset) > Math.abs(colOffset)) {
              table.dragingToRow = mouseCell.y;
              table.dragingToColumn =
                  (colOffset > 0) ? table.maxSelectionColumn : table.minSelectionColumn;
            } else {
              table.dragingToColumn = mouseCell.x;
              table.dragingToRow = (rowOffset > 0) ? table.maxSelectionRow : table.minSelectionRow;
            }
            table.repaint();
          }

          // handle ctrl-select dragging of cell blocks
          else {
            /*TODO if (e.isControlDown()) {
            	table.handleControlDragSelect(e);
            }*/
          }
        }
      }

      if (eConsumed) return;

      // MyTable's default listeners follow, they should be simulated in Web e.g. here

      // change selection if right click is outside current selection
      if (p.getY() != table.leadSelectionRow + 1 || p.getX() != table.leadSelectionColumn + 1) {
        // switch to cell selection mode

        if (p.getY() > 0 && p.getX() > 0) {

          if (table.getSelectionType() != MyTable.CELL_SELECT) {
            table.setSelectionType(MyTable.CELL_SELECT);
          }

          // now change the selection
          table.changeSelection(p.getY() - 1, p.getX() - 1, false, true);
          table.repaint();
        }
      }
    } else {
      // MOVE, NO DRAG

      if (table.isEditing()) return;

      // get GeoElement at mouse location
      int row = p.getY(); // ?//table.rowAtPoint(e.getPoint());
      int col = p.getX(); // ?//table.columnAtPoint(e.getPoint());
      GeoElement geo = (GeoElement) model.getValueAt(row - 1, col - 1);

      // set tooltip with geo's description
      if (geo != null & view.getAllowToolTips()) {
        app.setTooltipFlag();
        // TODO//table.setToolTipText(geo.getLongDescriptionHTML(true, true));
        app.clearTooltipFlag();
      } else {
        // TODO//table.setToolTipText(null);
      }

      // check if over the dragging dot and update accordingly
      GPoint maxPoint = table.getMaxSelectionPixel();
      GPoint minPoint = table.getMinSelectionPixel();

      if (maxPoint != null) {
        int dotX = maxPoint.getX();
        int dotY = maxPoint.getY();
        int s = MyTableW.DOT_SIZE + 2;
        GRectangle2DW dotRect = new GRectangle2DW(dotX - s / 2, dotY - s / 2, s, s);
        boolean overDot = dotRect.contains(e.getClientX(), e.getClientY());
        if (table.isOverDot != overDot) {
          table.isOverDot = overDot;
          // TODO//setTableCursor();
          table.repaint();
        }
      }

      // check if over the DnD region and update accordingly
      GPoint testPoint = table.getMinSelectionPixel();
      if (testPoint != null) {
        int minX = minPoint.getX();
        int minY = minPoint.getY();
        int maxX = maxPoint.getX();
        int w = maxX - minX;
        GRectangle2DW dndRect = new GRectangle2DW(minX, minY - 2, w, 4);
        boolean overDnD = dndRect.contains(e.getClientX(), e.getClientY());
        if (table.isOverDnDRegion != overDnD) {
          table.isOverDnDRegion = overDnD;
          // TODO//setTableCursor();
        }
      }
    }
  }
  public void onMouseDown(MouseDownEvent e) {

    GPoint p = table.getIndexFromPixel(e.getClientX(), e.getClientY());
    if (p.getY() == 0 && p.getX() > 0) {
      if (table.isEditing()) editor.cancelCellEditing();
      table.scc.onMouseDown(e);
      return;
    } else if (p.getX() == 0 && p.getY() > 0) {
      if (table.isEditing()) editor.cancelCellEditing();
      table.srh.onMouseDown(e);
      return;
    }

    // if (!view.hasViewFocus())
    //	((LayoutW) app.getGuiManager().getLayout()).getDockManager()
    //			.setFocusedPanel(App.VIEW_SPREADSHEET);
    view.requestFocus();

    mouseIsDown = true;
    e.preventDefault();
    boolean eConsumed = false;

    boolean rightClick = (e.getNativeButton() == NativeEvent.BUTTON_RIGHT);

    // tell selection listener about click on GeoElement
    if (!rightClick && app.getMode() == EuclidianConstants.MODE_SELECTION_LISTENER) {
      int row = p.getY(); // ?//table.rowAtPoint(e.getPoint());
      int col = p.getX(); // ?//table.columnAtPoint(e.getPoint());
      GeoElement geo = (GeoElement) model.getValueAt(row - 1, col - 1);

      // double click or empty geo
      if (geo != null) {
        // tell selection listener about click
        app.geoElementSelected(geo, false);
        return;
      }
    }

    if (!rightClick) {

      // memory testing
      // Application.debug("", true, true, 0);

      if (table.getSelectionType() != MyTable.CELL_SELECT) {
        table.setSelectionType(MyTable.CELL_SELECT);
      }

      // force column selection
      if (view.isColumnSelect()) {
        GPoint point = table.getIndexFromPixel(e.getClientX(), e.getClientY());
        if (point != null) {
          int column = point.getX();
          table.setColumnSelectionInterval(column, column);
        }
      }

      /*
       * if (MyTable.this.getSelectionModel().getSelectionMode() !=
       * ListSelectionModel.SINGLE_INTERVAL_SELECTION) {
       * setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
       * setColumnSelectionAllowed(true); setRowSelectionAllowed(true); }
       */

      GPoint point1 = table.getMaxSelectionPixel();
      if (point1 == null) return;

      // Handle click in another cell while editing a cell:
      // if the edit string begins with "=" then the clicked cell name
      // is inserted into the edit text
      if (editor.isEditing()) {
        String text = editor.getEditingValue();
        if (text.startsWith("=")) {
          GPoint point = table.getIndexFromPixel(e.getClientX(), e.getClientY());
          if (point != null && (point.getX() != editor.column || point.getY() != editor.row)) {
            // in Web, it's necessary to distinguish the editor row and column
            // because the event is not catched and not taken by the textfield

            int column = point.getX();
            int row = point.getY();
            GeoElement geo = RelativeCopy.getValue(app, column - 1, row - 1);
            if (geo != null) {

              // get cell name
              String name = GeoElementSpreadsheet.getSpreadsheetCellName(column - 1, row - 1);
              if (geo.isGeoFunction()) name += "(x)";
              selectedCellName = name;

              // get prefix/post substrings for current text caret
              // position
              int caretPos = editor.getCaretPosition();
              prefix0 = text.substring(0, caretPos);
              postfix0 = text.substring(caretPos, text.length());

              table.isDragging2 = true;
              table.minColumn2 = column;
              table.maxColumn2 = column;
              table.minRow2 = row;
              table.maxRow2 = row;

              // insert the geo label into the editor string
              editor.addLabel(name);

              eConsumed = true;
              table.repaint();
            }
            eConsumed = true;
          }
        } else {

          // if text does not start with "=" then stop the editor
          // and allow it to create/redefine a geo here
          editor.setAllowProcessGeo(true);
          editor.stopCellEditing();
          editor.setAllowProcessGeo(false);
          table.finishEditing();
          // almost like MyCellEditorW.stopCellEditing(int,int)
        }
      } else if (table.isOverDot) {
        table.isDragingDot = true;
        eConsumed = true;
      }
    }

    if (eConsumed) return;

    // MyTable's default listeners follow, they should be simulated in Web e.g. here

    // change selection if right click is outside current selection
    if (p.getY() != table.anchorSelectionRow + 1 || p.getX() != table.anchorSelectionColumn + 1) {
      // switch to cell selection mode

      if (p.getY() > 0 && p.getX() > 0) {
        if (table.getSelectionType() != MyTable.CELL_SELECT) {
          table.setSelectionType(MyTable.CELL_SELECT);
        }

        // now change the selection
        table.changeSelection(p.getY() - 1, p.getX() - 1, false, false);
        table.repaint();
      }
    }
  }