Example #1
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 #2
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 #3
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);
    }
  }
Example #4
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 #5
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);
  }
Example #6
0
  /**
   * Joins the elements at the given offset. Only works if isBetweenMatchingElements returns true
   * for the same offset. Afterwards, the caret is left at the point where the join occurred.
   *
   * @param offset Offset where the two elements meet.
   */
  private void joinElementsAt(int offset) throws DocumentValidationException {

    if (!isBetweenMatchingElements(offset)) {
      throw new DocumentValidationException("Cannot join elements at offset " + offset);
    }

    boolean success = false;
    try {
      this.beginWork();
      this.moveTo(offset + 1);
      VEXElement element = this.getCurrentElement();
      boolean moveContent = !element.isEmpty();
      VEXDocumentFragment frag = null;
      if (moveContent) {
        this.moveTo(element.getEndOffset(), true);
        frag = this.getSelectedFragment();
        this.deleteSelection();
      }
      this.moveBy(-1);
      this.moveBy(2, true);
      this.deleteSelection();
      this.moveBy(-1);
      if (moveContent) {
        int savedOffset = this.getCaretOffset();
        this.insertFragment(frag);
        this.moveTo(savedOffset, false);
      }
      success = true;
    } finally {
      this.endWork(success);
    }
  }
Example #7
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()]);
  }
Example #8
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());
    }
  }