Beispiel #1
0
  /** Update the child views in response to a document event. */
  void updateChildren(DocumentEvent e, Shape a) {

    Element elem = getElement();
    DocumentEvent.ElementChange ec = e.getChange(elem);

    // This occurs when syntax highlighting only changes on lines
    // (i.e. beginning a multiline comment).
    if (e.getType() == DocumentEvent.EventType.CHANGE) {
      // System.err.println("Updating the damage due to a CHANGE event...");
      // FIXME:  Make me repaint more intelligently.
      getContainer().repaint();
      // damageLineRange(startLine,endLine, a, host);
    } else if (ec != null) {

      // the structure of this element changed.
      Element[] removedElems = ec.getChildrenRemoved();
      Element[] addedElems = ec.getChildrenAdded();
      View[] added = new View[addedElems.length];

      for (int i = 0; i < addedElems.length; i++) added[i] = new WrappedLine(addedElems[i]);
      // System.err.println("Replacing " + removedElems.length +
      // " children with " + addedElems.length);
      replace(ec.getIndex(), removedElems.length, added);

      // should damge a little more intelligently.
      if (a != null) {
        preferenceChanged(null, true, true);
        getContainer().repaint();
      }
    }

    // update font metrics which may be used by the child views
    updateMetrics();
  }
  /**
   * Repaint the region of change covered by the given document event. Damages the line that begins
   * the range to cover the case when the insert/remove is only on one line. If lines are added or
   * removed, damages the whole view. The longest line is checked to see if it has changed.
   */
  protected void updateDamage(DocumentEvent changes, Shape a, ViewFactory f) {
    Component host = getContainer();
    updateMetrics();
    Element elem = getElement();
    DocumentEvent.ElementChange ec = changes.getChange(elem);
    Element[] added = (ec != null) ? ec.getChildrenAdded() : null;
    Element[] removed = (ec != null) ? ec.getChildrenRemoved() : null;
    if (((added != null) && (added.length > 0)) || ((removed != null) && (removed.length > 0))) {
      // lines were added or removed...
      if (added != null) {
        int addedAt = ec.getIndex(); // FIXME: Is this correct?????
        for (int i = 0; i < added.length; i++) possiblyUpdateLongLine(added[i], addedAt + i);
      }
      if (removed != null) {
        for (int i = 0; i < removed.length; i++) {
          if (removed[i] == longLine) {
            longLineWidth = -1; // Must do this!!
            calculateLongestLine();
            break;
          }
        }
      }
      preferenceChanged(null, true, true);
      host.repaint();
    }

    // This occurs when syntax highlighting only changes on lines
    // (i.e. beginning a multiline comment).
    else if (changes.getType() == DocumentEvent.EventType.CHANGE) {
      // System.err.println("Updating the damage due to a CHANGE event...");
      int startLine = changes.getOffset();
      int endLine = changes.getLength();
      damageLineRange(startLine, endLine, a, host);
    } else {
      Element map = getElement();
      int line = map.getElementIndex(changes.getOffset());
      damageLineRange(line, line, a, host);
      if (changes.getType() == DocumentEvent.EventType.INSERT) {
        // check to see if the line is longer than current
        // longest line.
        Element e = map.getElement(line);
        if (e == longLine) {
          // We must recalculate longest line's width here
          // because it has gotten longer.
          longLineWidth = getLineWidth(line);
          preferenceChanged(null, true, false);
        } else {
          // If long line gets updated, update the status bars too.
          if (possiblyUpdateLongLine(e, line)) preferenceChanged(null, true, false);
        }
      } else if (changes.getType() == DocumentEvent.EventType.REMOVE) {
        if (map.getElement(line) == longLine) {
          // removed from longest line... recalc
          longLineWidth = -1; // Must do this!
          calculateLongestLine();
          preferenceChanged(null, true, false);
        }
      }
    }
  }
  /**
   * Alerts all listeners to this document of an insertion. This is overridden so we can update our
   * syntax highlighting stuff.
   *
   * <p>The syntax highlighting stuff has to be here instead of in <code>insertUpdate</code> because
   * <code>insertUpdate</code> is not called by the undo/redo actions, but this method is.
   *
   * @param e The change.
   */
  protected void fireInsertUpdate(DocumentEvent e) {

    /*
     * Now that the text is actually inserted into the content and
     * element structure, we can update our token elements and "last
     * tokens on lines" structure.
     */

    Element lineMap = getDefaultRootElement();
    DocumentEvent.ElementChange change = e.getChange(lineMap);
    Element[] added = change == null ? null : change.getChildrenAdded();

    int numLines = lineMap.getElementCount();
    int line = lineMap.getElementIndex(e.getOffset());
    int previousLine = line - 1;
    int previousTokenType = (previousLine > -1 ? lastTokensOnLines.get(previousLine) : Token.NULL);

    // If entire lines were added...
    if (added != null && added.length > 0) {

      Element[] removed = change.getChildrenRemoved();
      int numRemoved = removed != null ? removed.length : 0;

      int endBefore = line + added.length - numRemoved;
      // System.err.println("... adding lines: " + line + " - " + (endBefore-1));
      // System.err.println("... ... added: " + added.length + ", removed:" + numRemoved);
      for (int i = line; i < endBefore; i++) {

        setSharedSegment(i); // Loads line i's text into s.

        int tokenType = tokenMaker.getLastTokenTypeOnLine(s, previousTokenType);
        lastTokensOnLines.add(i, tokenType);
        // System.err.println("--------- lastTokensOnLines.size() == " +
        // lastTokensOnLines.getSize());

        previousTokenType = tokenType;
      } // End of for (int i=line; i<endBefore; i++).

      // Update last tokens for lines below until they stop changing.
      updateLastTokensBelow(endBefore, numLines, previousTokenType);

    } // End of if (added!=null && added.length>0).

    // Otherwise, text was inserted on a single line...
    else {

      // Update last tokens for lines below until they stop changing.
      updateLastTokensBelow(line, numLines, previousTokenType);
    } // End of else.

    // Let all listeners know about the insertion.
    super.fireInsertUpdate(e);
  }
  /**
   * This method is called AFTER the content has been inserted into the document and the element
   * structure has been updated.
   *
   * <p>The syntax-highlighting updates need to be done here (as opposed to an override of <code>
   * postRemoveUpdate</code>) as this method is called in response to undo/redo events, whereas
   * <code>postRemoveUpdate</code> is not.
   *
   * <p>Now that the text is actually inserted into the content and element structure, we can update
   * our token elements and "last tokens on lines" structure.
   *
   * @param chng The change that occurred.
   * @see #removeUpdate
   */
  protected void fireRemoveUpdate(DocumentEvent chng) {

    Element lineMap = getDefaultRootElement();
    int numLines = lineMap.getElementCount();

    DocumentEvent.ElementChange change = chng.getChange(lineMap);
    Element[] removed = change == null ? null : change.getChildrenRemoved();

    // If entire lines were removed...
    if (removed != null && removed.length > 0) {

      int line = change.getIndex(); // First line entirely removed.
      int previousLine = line - 1; // Line before that.
      int previousTokenType =
          (previousLine > -1 ? lastTokensOnLines.get(previousLine) : Token.NULL);

      Element[] added = change.getChildrenAdded();
      int numAdded = added == null ? 0 : added.length;

      // Remove the cached last-token values for the removed lines.
      int endBefore = line + removed.length - numAdded;
      // System.err.println("... removing lines: " + line + " - " + (endBefore-1));
      // System.err.println("... added: " + numAdded + ", removed: " + removed.length);

      lastTokensOnLines.removeRange(
          line, endBefore); // Removing values for lines [line-(endBefore-1)].
      // System.err.println("--------- lastTokensOnLines.size() == " + lastTokensOnLines.getSize());

      // Update last tokens for lines below until they've stopped changing.
      updateLastTokensBelow(line, numLines, previousTokenType);

    } // End of if (removed!=null && removed.size()>0).

    // Otherwise, text was removed from just one line...
    else {

      int line = lineMap.getElementIndex(chng.getOffset());
      if (line >= lastTokensOnLines.getSize())
        return; // If we're editing the last line in a document...

      int previousLine = line - 1;
      int previousTokenType =
          (previousLine > -1 ? lastTokensOnLines.get(previousLine) : Token.NULL);
      // System.err.println("previousTokenType for line : " + previousLine + " is " +
      // previousTokenType);
      // Update last tokens for lines below until they've stopped changing.
      updateLastTokensBelow(line, numLines, previousTokenType);
    }

    // Let all of our listeners know about the removal.
    super.fireRemoveUpdate(chng);
  }
Beispiel #5
0
  /**
   * Forwards the given <code>DocumentEvent</code> to the child views that need to be notified of
   * the change to the model. If there were changes to the element this view is responsible for,
   * that should be considered when forwarding (i.e. new child views should not get notified).
   *
   * @param ec changes to the element this view is responsible for (may be <code>null</code> if
   *     there were no changes).
   * @param e the change information from the associated document
   * @param a the current allocation of the view
   * @param f the factory to use to rebuild if the view has children
   * @see #insertUpdate
   * @see #removeUpdate
   * @see #changedUpdate
   * @since 1.3
   */
  protected void forwardUpdate(
      DocumentEvent.ElementChange ec, DocumentEvent e, Shape a, ViewFactory f) {
    Element elem = getElement();
    int pos = e.getOffset();
    int index0 = getViewIndex(pos, Position.Bias.Forward);
    if (index0 == -1 && e.getType() == DocumentEvent.EventType.REMOVE && pos >= getEndOffset()) {
      // Event beyond our offsets. We may have represented this, that is
      // the remove may have removed one of our child Elements that
      // represented this, so, we should foward to last element.
      index0 = getViewCount() - 1;
    }
    int index1 = index0;
    View v = (index0 >= 0) ? getView(index0) : null;
    if (v != null) {
      if ((v.getStartOffset() == pos) && (pos > 0)) {
        // If v is at a boundary, forward the event to the previous
        // view too.
        index0 = Math.max(index0 - 1, 0);
      }
    }
    if (e.getType() != DocumentEvent.EventType.REMOVE) {
      index1 = getViewIndex(pos + e.getLength(), Position.Bias.Forward);
      if (index1 < 0) {
        index1 = getViewCount() - 1;
      }
    }
    int hole0 = index1 + 1;
    int hole1 = hole0;
    Element[] addedElems = (ec != null) ? ec.getChildrenAdded() : null;
    if ((addedElems != null) && (addedElems.length > 0)) {
      hole0 = ec.getIndex();
      hole1 = hole0 + addedElems.length - 1;
    }

    // forward to any view not in the forwarding hole
    // formed by added elements (i.e. they will be updated
    // by initialization.
    index0 = Math.max(index0, 0);
    for (int i = index0; i <= index1; i++) {
      if (!((i >= hole0) && (i <= hole1))) {
        v = getView(i);
        if (v != null) {
          Shape childAlloc = getChildAllocation(i, a);
          forwardUpdateToView(v, e, childAlloc, f);
        }
      }
    }
  }
Beispiel #6
0
 /**
  * Updates the child views in response to receiving notification that the model changed, and there
  * is change record for the element this view is responsible for. This is implemented to assume
  * the child views are directly responsible for the child elements of the element this view
  * represents. The <code>ViewFactory</code> is used to create child views for each element
  * specified as added in the <code>ElementChange</code>, starting at the index specified in the
  * given <code>ElementChange</code>. The number of child views representing the removed elements
  * specified are removed.
  *
  * @param ec the change information for the element this view is responsible for. This should not
  *     be <code>null</code> if this method gets called
  * @param e the change information from the associated document
  * @param f the factory to use to build child views
  * @return whether or not the child views represent the child elements of the element this view is
  *     responsible for. Some views create children that represent a portion of the element they
  *     are responsible for, and should return false. This information is used to determine if
  *     views in the range of the added elements should be forwarded to or not
  * @see #insertUpdate
  * @see #removeUpdate
  * @see #changedUpdate
  * @since 1.3
  */
 protected boolean updateChildren(DocumentEvent.ElementChange ec, DocumentEvent e, ViewFactory f) {
   Element[] removedElems = ec.getChildrenRemoved();
   Element[] addedElems = ec.getChildrenAdded();
   View[] added = null;
   if (addedElems != null) {
     added = new View[addedElems.length];
     for (int i = 0; i < addedElems.length; i++) {
       added[i] = f.create(addedElems[i]);
     }
   }
   int nremoved = 0;
   int index = ec.getIndex();
   if (removedElems != null) {
     nremoved = removedElems.length;
   }
   replace(index, nremoved, added);
   return true;
 }
Beispiel #7
0
  protected void documentChanged(DocumentEvent evt) {
    DocumentEvent.ElementChange ch = evt.getChange(document.getDefaultRootElement());

    int count;
    if (ch == null) count = 0;
    else count = ch.getChildrenAdded().length - ch.getChildrenRemoved().length;

    int line = getLineOfOffset(evt.getOffset());
    if (count == 0) {
      painter.invalidateLine(line);
    }
    // do magic stuff
    else if (line < firstLine) {
      setFirstLine(firstLine + count);
    }
    // end of magic stuff
    else {
      painter.invalidateLineRange(line, firstLine + visibleLines);
      updateScrollBars();
    }
  }
  /** Implementation */
  @Override
  public void insertUpdate(DocumentEvent e) {
    // handle new lines,  Enter hit at end of line changes
    // the line element instance
    // XXX Actually NB document implementation triggers this method two times
    //  - first time with one removed and two added lines
    //  - second time with two removed and two added lines
    if (!elementAnnotations.isEmpty()) {
      Element[] elements = e.getDocument().getRootElements();
      synchronized (elementAnnotations) { // atomic change
        for (int i = 0; i < elements.length; i++) {
          Element element = elements[i];
          DocumentEvent.ElementChange change = e.getChange(element);
          if (change == null) continue;
          Element[] removed = change.getChildrenRemoved();
          Element[] added = change.getChildrenAdded();

          if (removed.length == added.length) {
            for (int c = 0; c < removed.length; c++) {
              AnnotateLine recent = elementAnnotations.get(removed[c]);
              if (recent != null) {
                elementAnnotations.remove(removed[c]);
                elementAnnotations.put(added[c], recent);
              }
            }
          } else if (removed.length == 1 && added.length > 0) {
            Element key = removed[0];
            AnnotateLine recent = elementAnnotations.get(key);
            if (recent != null) {
              elementAnnotations.remove(key);
              elementAnnotations.put(added[0], recent);
            }
          }
        }
      }
    }
    repaint();
  }
 /*     */ void updateChildren(DocumentEvent paramDocumentEvent, Shape paramShape) /*     */ {
   /* 277 */ Element localElement = getElement();
   /* 278 */ DocumentEvent.ElementChange localElementChange =
       paramDocumentEvent.getChange(localElement);
   /* 279 */ if (localElementChange != null)
   /*     */ {
     /* 281 */ Element[] arrayOfElement1 = localElementChange.getChildrenRemoved();
     /* 282 */ Element[] arrayOfElement2 = localElementChange.getChildrenAdded();
     /* 283 */ View[] arrayOfView = new View[arrayOfElement2.length];
     /* 284 */ for (int i = 0; i < arrayOfElement2.length; i++) {
       /* 285 */ arrayOfView[i] = new WrappedLine(arrayOfElement2[i]);
       /*     */ }
     /* 287 */ replace(localElementChange.getIndex(), arrayOfElement1.length, arrayOfView);
     /*     */
     /* 290 */ if (paramShape != null) {
       /* 291 */ preferenceChanged(null, true, true);
       /* 292 */ getContainer().repaint();
       /*     */ }
     /*     */
     /*     */ }
   /*     */
   /* 297 */ updateMetrics();
   /*     */ }