Beispiel #1
0
  public void morph(Element element) throws DocumentValidationException {

    VEXDocument doc = this.getDocument();
    int offset = this.getCaretOffset();
    VEXElement currentElement = doc.getElementAt(offset);

    if (currentElement == doc.getRootElement()) {
      throw new DocumentValidationException("Cannot morph the root element.");
    }

    boolean success = false;
    try {
      this.beginWork();
      this.moveTo(currentElement.getStartOffset() + 1, false);
      this.moveTo(currentElement.getEndOffset(), true);
      VEXDocumentFragment frag = this.getSelectedFragment();
      this.deleteSelection();
      this.moveBy(-1, false);
      this.moveBy(2, true);
      this.deleteSelection();
      this.insertElement(element);
      if (frag != null) {
        this.insertFragment(frag);
      }
      this.moveTo(offset, false);
      success = true;
    } finally {
      this.endWork(success);
    }
  }
Beispiel #2
0
  public void deleteNextChar() throws DocumentValidationException {
    if (this.hasSelection()) {
      this.deleteSelection();
    } else {
      int offset = this.getCaretOffset();
      VEXDocument doc = this.getDocument();
      int n = doc.getLength() - 1;
      VEXElement element = doc.getElementAt(offset);

      if (offset == n) {
        // nop
      } else if (this.isBetweenMatchingElements(offset)) {
        this.joinElementsAt(offset);
      } else if (this.isBetweenMatchingElements(offset + 1)) {
        this.joinElementsAt(offset + 1);
      } else if (element.isEmpty()) {
        // deleting the right sentinel of an empty element
        // so just delete the whole element an move on
        this.moveTo(offset - 1, false);
        this.moveTo(offset + 1, true);
        this.deleteSelection();
      } else if (doc.getElementAt(offset + 1).isEmpty()) {
        // deleting the left sentinel of an empty element
        // so just delete the whole element an move on
        this.moveTo(offset + 2, true);
        this.deleteSelection();
      } else {
        if (doc.getCharacterAt(offset) != 0) {
          this.moveTo(offset, false);
          this.moveTo(offset + 1, true);
          this.deleteSelection();
        }
      }
    }
  }
Beispiel #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()]);
  }
Beispiel #4
0
  /** Returns true if text can be inserted at the current position. */
  public boolean canInsertText() {

    VEXDocument doc = this.getDocument();
    if (doc == null) {
      return false;
    }

    Validator validator = this.document.getValidator();
    if (validator == null) {
      return true;
    }

    int startOffset = this.getCaretOffset();
    int endOffset = this.getCaretOffset();
    if (this.hasSelection()) {
      startOffset = this.getSelectionStart();
      endOffset = this.getSelectionEnd();
    }

    VEXElement parent = this.getDocument().getElementAt(startOffset);
    EList<String> seq1 = doc.getNodeNames(parent.getStartOffset() + 1, startOffset);

    EList<String> seq2 = new BasicEList<String>();
    seq2.add(Validator.PCDATA);

    EList<String> seq3 = doc.getNodeNames(endOffset, parent.getEndOffset());

    return validator.isValidSequence(parent.getName(), seq1, seq2, seq3, true);
  }
Beispiel #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");
    }
  }
Beispiel #6
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);
  }
Beispiel #7
0
  public void moveToPreviousWord(boolean select) {
    VEXDocument doc = this.getDocument();
    int offset = this.getCaretOffset();
    while (offset > 1 && !Character.isLetterOrDigit(doc.getCharacterAt(offset - 1))) {
      offset--;
    }

    while (offset > 1 && Character.isLetterOrDigit(doc.getCharacterAt(offset - 1))) {
      offset--;
    }

    this.moveTo(offset, select);
  }
Beispiel #8
0
  public void moveToNextWord(boolean select) {
    VEXDocument doc = this.getDocument();
    int n = doc.getLength() - 1;
    int offset = this.getCaretOffset();
    while (offset < n && !Character.isLetterOrDigit(doc.getCharacterAt(offset))) {
      offset++;
    }

    while (offset < n && Character.isLetterOrDigit(doc.getCharacterAt(offset))) {
      offset++;
    }

    this.moveTo(offset, select);
  }
Beispiel #9
0
  public void selectWord() {
    VEXDocument doc = this.getDocument();
    int startOffset = this.getCaretOffset();
    int endOffset = this.getCaretOffset();
    while (startOffset > 1 && Character.isLetterOrDigit(doc.getCharacterAt(startOffset - 1))) {
      startOffset--;
    }
    int n = doc.getLength() - 1;
    while (endOffset < n && Character.isLetterOrDigit(doc.getCharacterAt(endOffset))) {
      endOffset++;
    }

    if (startOffset < endOffset) {
      this.moveTo(startOffset, false);
      this.moveTo(endOffset, true);
    }
  }
Beispiel #10
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);
  }
Beispiel #11
0
  public String[] getValidInsertElements() {

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

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

    int startOffset = this.getCaretOffset();
    int endOffset = this.getCaretOffset();
    if (this.hasSelection()) {
      startOffset = this.getSelectionStart();
      endOffset = this.getSelectionEnd();
    }

    VEXElement parent = doc.getElementAt(startOffset);

    Set<String> validItems = validator.getValidItems(parent.getName());
    List<String> candidates = new ArrayList<String>(validItems);
    candidates.remove(Validator.PCDATA);

    // filter invalid sequences
    EList<String> nodesBefore = doc.getNodeNames(parent.getStartOffset() + 1, startOffset);
    EList<String> nodesAfter = doc.getNodeNames(endOffset, parent.getEndOffset());
    int sequenceLength = nodesBefore.size() + 1 + nodesAfter.size();
    for (Iterator<String> iter = candidates.iterator(); iter.hasNext(); ) {
      String candidate = iter.next();
      EList<String> sequence = new BasicEList<String>(sequenceLength);
      sequence.addAll(nodesBefore);
      sequence.add(candidate);
      sequence.addAll(nodesAfter);
      if (!validator.isValidSequence(parent.getName(), sequence, true)) {
        iter.remove();
      }
    }

    // If there's a selection, root out those candidates that can't
    // contain it.
    if (hasSelection()) {
      EList<String> selectedNodes = doc.getNodeNames(startOffset, endOffset);

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

    Collections.sort(candidates);
    return (String[]) candidates.toArray(new String[candidates.size()]);
  }