/** 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); } } } }
/** * Gives notification from the document that attributes were changed in a location that this view * is responsible for. To reduce the burden to subclasses, this functionality is spread out into * the following calls that subclasses can reimplement: * * <ol> * <li><a href="#updateChildren">updateChildren</a> is called if there were any changes to the * element this view is responsible for. If this view has child views that are represent the * child elements, then this method should do whatever is necessary to make sure the child * views correctly represent the model. * <li><a href="#forwardUpdate">forwardUpdate</a> is called to forward the DocumentEvent to the * appropriate child views. * <li><a href="#updateLayout">updateLayout</a> is called to give the view a chance to either * repair its layout, to reschedule layout, or do nothing. * </ol> * * @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 View#changedUpdate */ public void changedUpdate(DocumentEvent e, Shape a, ViewFactory f) { if (getViewCount() > 0) { Element elem = getElement(); DocumentEvent.ElementChange ec = e.getChange(elem); if (ec != null) { if (!updateChildren(ec, e, f)) { // don't consider the element changes they // are for a view further down. ec = null; } } forwardUpdate(ec, e, a, f); updateLayout(ec, e, a); } }
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(); } }