Example #1
0
 /**
  * Returns true if the given offset represents the boundary between two different elements with
  * the same name and parent. This is used to determine if the elements can be joined via
  * joinElementsAt.
  *
  * @param int offset The offset to check.
  */
 private boolean isBetweenMatchingElements(int offset) {
   if (offset <= 1 || offset >= this.getDocument().getLength() - 1) {
     return false;
   }
   VEXElement e1 = this.getDocument().getElementAt(offset - 1);
   VEXElement e2 = this.getDocument().getElementAt(offset + 1);
   return e1 != e2 && e1.getParent() == e2.getParent() && e1.getName().equals(e2.getName());
 }
Example #2
0
  /**
   * Iterate over all rows in the table containing the caret.
   *
   * @param vexWidget IVexWidget to iterate over.
   * @param callback Caller-provided callback that this method calls for each row in the current
   *     table.
   */
  public static void iterateTableRows(IVexWidget vexWidget, ElementOrRangeCallback callback) {

    final StyleSheet ss = vexWidget.getStyleSheet();
    final VEXDocument doc = vexWidget.getDocument();
    final int offset = vexWidget.getCaretOffset();

    // This may or may not be a table
    // In any case, it's the element that contains the top-level table
    // children
    VEXElement table = doc.getElementAt(offset);

    while (table != null && !LayoutUtils.isTableChild(ss, table)) {
      table = table.getParent();
    }

    while (table != null && LayoutUtils.isTableChild(ss, table)) {
      table = table.getParent();
    }

    if (table == null || table.getParent() == null) {
      return;
    }

    final List<Element> tableChildren = new ArrayList<Element>();
    final boolean[] found = new boolean[] {false};
    LayoutUtils.iterateChildrenByDisplayStyle(
        ss,
        LayoutUtils.TABLE_CHILD_STYLES,
        table,
        new ElementOrRangeCallback() {
          public void onElement(Element child, String displayStyle) {
            if (offset >= child.getStartOffset() && offset <= child.getEndOffset()) {
              found[0] = true;
            }
            tableChildren.add(child);
          }

          public void onRange(VEXElement parent, int startOffset, int endOffset) {
            if (!found[0]) {
              tableChildren.clear();
            }
          }
        });

    if (!found[0]) {
      return;
    }

    int startOffset = tableChildren.get(0).getStartOffset();
    int endOffset = tableChildren.get(tableChildren.size() - 1).getEndOffset() + 1;
    LayoutUtils.iterateTableRows(ss, table, startOffset, endOffset, callback);
  }
Example #3
0
  public String[] getValidMorphElements() {

    VEXDocument doc = this.getDocument();
    if (doc == null) return new String[0];

    Validator validator = doc.getValidator();
    if (validator == null) return new String[0];

    VEXElement element = doc.getElementAt(this.getCaretOffset());
    VEXElement parent = element.getParent();
    if (parent == null) {
      // can't morph the root
      return new String[0];
    }

    Set<String> validItems = validator.getValidItems(parent.getName());
    List<String> result = new ArrayList<String>(validItems);
    result.remove(Validator.PCDATA);
    result.remove(element.getName()); // exclude converting to the same

    // root out those that can't contain the current content
    EList<String> content = doc.getNodeNames(element.getStartOffset() + 1, element.getEndOffset());

    for (Iterator<String> iter = result.iterator(); iter.hasNext(); ) {
      String candidate = iter.next();
      if (!validator.isValidSequence(candidate, content, true)) {
        iter.remove();
      }
    }

    Collections.sort(result);
    return result.toArray(new String[result.size()]);
  }
Example #4
0
  public boolean canUnwrap() {
    VEXDocument doc = this.getDocument();
    if (doc == null) {
      return false;
    }

    Validator validator = doc.getValidator();
    if (validator == null) {
      return false;
    }

    VEXElement element = doc.getElementAt(this.getCaretOffset());
    VEXElement parent = element.getParent();
    if (parent == null) {
      // can't unwrap the root
      return false;
    }

    EList<String> seq1 = doc.getNodeNames(parent.getStartOffset() + 1, element.getStartOffset());

    EList<String> seq2 = doc.getNodeNames(element.getStartOffset() + 1, element.getEndOffset());

    EList<String> seq3 = doc.getNodeNames(element.getEndOffset() + 1, parent.getEndOffset());

    return validator.isValidSequence(parent.getName(), seq1, seq2, seq3, true);
  }
Example #5
0
  public void split() throws DocumentValidationException {

    long start = System.currentTimeMillis();

    VEXDocument doc = this.getDocument();
    VEXElement element = doc.getElementAt(this.getCaretOffset());
    Styles styles = this.getStyleSheet().getStyles(element);
    while (!styles.isBlock()) {
      element = element.getParent();
      styles = this.getStyleSheet().getStyles(element);
    }

    boolean success = false;
    try {
      this.beginWork();
      if (styles.getWhiteSpace().equals(CSS.PRE)) {
        // can't call this.insertText() or we'll get an infinite loop
        int offset = this.getCaretOffset();
        doc.insertText(offset, "\n");
        this.moveTo(offset + 1);
      } else {
        VEXDocumentFragment frag = null;
        int offset = this.getCaretOffset();
        boolean atEnd = (offset == element.getEndOffset());
        if (!atEnd) {
          this.moveTo(element.getEndOffset(), true);
          frag = this.getSelectedFragment();
          this.deleteSelection();
        }

        // either way, we are now at the end offset for the element
        // let's move just outside
        this.moveTo(this.getCaretOffset() + 1);

        this.insertElement(new Element(element.getName()));
        // TODO: clone attributes

        if (!atEnd) {
          offset = this.getCaretOffset();
          this.insertFragment(frag);
          this.moveTo(offset, false);
        }
      }
      success = true;
    } finally {
      this.endWork(success);
    }

    if (this.isDebugging()) {
      long end = System.currentTimeMillis();
      System.out.println("split() took " + (end - start) + "ms");
    }
  }
Example #6
0
  /**
   * Returns the innermost Element with style table-row containing the caret, or null if no such
   * element exists.
   *
   * @param vexWidget IVexWidget to use.
   */
  public static VEXElement getCurrentTableRow(IVexWidget vexWidget) {

    StyleSheet ss = vexWidget.getStyleSheet();
    VEXElement element = vexWidget.getCurrentElement();

    while (element != null) {
      if (ss.getStyles(element).getDisplay().equals(CSS.TABLE_ROW)) {
        return element;
      }
      element = element.getParent();
    }

    return null;
  }
Example #7
0
  public void moveTo(int offset, boolean select) {

    if (offset >= 1 && offset <= this.document.getLength() - 1) {

      // repaint the selection area, if any
      this.repaintCaret();
      this.repaintRange(this.getSelectionStart(), this.getSelectionEnd());

      VEXElement oldElement = this.currentElement;

      this.caretOffset = offset;

      this.currentElement = this.document.getElementAt(offset);

      if (select) {
        this.selectionStart = Math.min(this.mark, this.caretOffset);
        this.selectionEnd = Math.max(this.mark, this.caretOffset);

        // move selectionStart and selectionEnd to make sure we don't
        // select a partial element
        VEXElement commonElement =
            this.document.findCommonElement(this.selectionStart, this.selectionEnd);

        VEXElement element = this.document.getElementAt(this.selectionStart);
        while (element != commonElement) {
          this.selectionStart = element.getStartOffset();
          element = this.document.getElementAt(this.selectionStart);
        }

        element = this.document.getElementAt(this.selectionEnd);
        while (element != commonElement) {
          this.selectionEnd = element.getEndOffset() + 1;
          element = this.document.getElementAt(this.selectionEnd);
        }

      } else {
        this.mark = offset;
        this.selectionStart = offset;
        this.selectionEnd = offset;
      }

      if (this.beginWorkCount == 0) {
        this.relayout();
      }

      Graphics g = this.hostComponent.createDefaultGraphics();
      LayoutContext context = this.createLayoutContext(g);
      this.caret = this.rootBox.getCaret(context, offset);

      VEXElement element = this.getCurrentElement();
      if (element != oldElement) {
        this.caretColor = Color.BLACK;
        while (element != null) {
          Color bgColor = this.styleSheet.getStyles(element).getBackgroundColor();
          if (bgColor != null) {
            int red = ~bgColor.getRed() & 0xff;
            int green = ~bgColor.getGreen() & 0xff;
            int blue = ~bgColor.getBlue() & 0xff;
            this.caretColor = new Color(red, green, blue);
            break;
          }
          element = element.getParent();
        }
      }

      g.dispose();

      this.magicX = -1;

      this.scrollCaretVisible();

      this.hostComponent.fireSelectionChanged();

      this.caretVisible = true;

      this.repaintRange(this.getSelectionStart(), this.getSelectionEnd());
    }
  }