Hi, as mentioned in PR 26157[0] I observed that the JDK's JTextArea adjusts its size automatically when the characters leave the allocation area of the component. Our JTextArea did not have this functionality until now.
It took me a while to find out where to place the code that could do the neccessary checks which should prevent unneeded revalidate() calls. While implementing this I found and fixed two problems in PlainView: 1) The switch statement in getPreferredSpan always fell into the Y_AXIS case. 2) In changeUpdate() the maxLineLength value could never shrink when characters are removed on one line only. I added a check whether the characters are removed from the current longest line and update the maxLineLength value if that is the case. Please comment. 2006-02-21 Robert Schuster <[EMAIL PROTECTED]> * javax/swing/text/PlainDocument.java: (getPreferredSpan): Removed variable, use 'return' in switch statement which corrects an unwanted fall through. (changeUpdate): Update maxLineLength correctly when text is removed. * javax/swing/plaf/basic/BasicTextUI.java: (BasicTextUI.RootView): Made class package private. * javax/swing/plaf/basic/BasicTextAreaUI.java: (BasicTextAreaUI.TextAreaRootView): New class. (BasicTextAreaUI): Set new rootView instance. cya Robert [0] - http://gcc.gnu.org/bugzilla/show_bug.cgi?id=26157
Index: javax/swing/text/PlainView.java =================================================================== RCS file: /cvsroot/classpath/classpath/javax/swing/text/PlainView.java,v retrieving revision 1.36 diff -u -r1.36 PlainView.java --- javax/swing/text/PlainView.java 8 Feb 2006 15:57:41 -0000 1.36 +++ javax/swing/text/PlainView.java 22 Feb 2006 07:56:57 -0000 @@ -307,19 +307,16 @@ // make sure we have the metrics updateMetrics(); - float span = 0; Element el = getElement(); switch (axis) { case X_AXIS: - span = determineMaxLineLength(); + return determineMaxLineLength(); case Y_AXIS: default: - span = metrics.getHeight() * el.getElementCount(); - break; + return metrics.getHeight() * el.getElementCount(); } - return span; } /** @@ -383,7 +380,18 @@ // repaint the changed line if (ec == null) { - int line = getElement().getElementIndex(changes.getOffset()); + int line = el.getElementIndex(changes.getOffset()); + + // If characters have been removed from the current longest line + // we have to find out which one is the longest now otherwise + // the preferred x-axis span will not shrink. + if (changes.getType() == DocumentEvent.EventType.REMOVE + && el.getElement(line) == longestLine) + { + maxLineLength = -1; + determineMaxLineLength(); + } + damageLineRange(line, line, a, getContainer()); return; } @@ -396,6 +404,7 @@ if (removed == null && newElements == null) { int line = getElement().getElementIndex(changes.getOffset()); + damageLineRange(line, line, a, getContainer()); return; } @@ -410,7 +419,9 @@ // reset maxLineLength and search through all lines for longest one maxLineLength = -1; determineMaxLineLength(); + ((JTextComponent)getContainer()).repaint(); + return; } } @@ -420,6 +431,7 @@ { // No lines were added, just repaint the container and exit ((JTextComponent)getContainer()).repaint(); + return; } @@ -468,6 +480,7 @@ maxLineLength = longestNewLength; longestLine = longestNewLine; } + // Repaint the container ((JTextComponent)getContainer()).repaint(); } Index: javax/swing/plaf/basic/BasicTextUI.java =================================================================== RCS file: /cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicTextUI.java,v retrieving revision 1.71 diff -u -r1.71 BasicTextUI.java --- javax/swing/plaf/basic/BasicTextUI.java 21 Feb 2006 14:03:19 -0000 1.71 +++ javax/swing/plaf/basic/BasicTextUI.java 22 Feb 2006 07:56:57 -0000 @@ -125,7 +125,7 @@ * calls like [EMAIL PROTECTED] #preferenceChanged}, [EMAIL PROTECTED] #getViewFactory} and * [EMAIL PROTECTED] #getContainer}. */ - private class RootView extends View + class RootView extends View { /** The real root view. */ private View view; Index: javax/swing/plaf/basic/BasicTextAreaUI.java =================================================================== RCS file: /cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicTextAreaUI.java,v retrieving revision 1.6 diff -u -r1.6 BasicTextAreaUI.java --- javax/swing/plaf/basic/BasicTextAreaUI.java 31 Oct 2005 21:29:52 -0000 1.6 +++ javax/swing/plaf/basic/BasicTextAreaUI.java 22 Feb 2006 07:56:57 -0000 @@ -39,19 +39,73 @@ package javax.swing.plaf.basic; +import java.awt.FontMetrics; +import java.awt.Rectangle; +import java.awt.Shape; import java.beans.PropertyChangeEvent; import javax.swing.JComponent; import javax.swing.JTextArea; import javax.swing.UIDefaults; +import javax.swing.event.DocumentEvent; import javax.swing.plaf.ComponentUI; import javax.swing.text.Element; import javax.swing.text.PlainView; import javax.swing.text.View; +import javax.swing.text.ViewFactory; import javax.swing.text.WrappedPlainView; public class BasicTextAreaUI extends BasicTextUI { + /** Extends the RootView of BasicTextUI with the ability to adjust the size + * of the component after text was inserted, removed or changed. + */ + class TextAreaRootView extends BasicTextUI.RootView + { + public void changedUpdate(DocumentEvent ev, Shape shape, ViewFactory vf) + { + super.changedUpdate(ev, shape, vf); + checkBounds(shape); + } + + public void removeUpdate(DocumentEvent ev, Shape shape, ViewFactory vf) + { + super.removeUpdate(ev, shape, vf); + checkBounds(shape); + } + + public void insertUpdate(DocumentEvent ev, Shape shape, ViewFactory vf) + { + super.insertUpdate(ev, shape, vf); + checkBounds(shape); + } + + private void checkBounds(Shape allocation) + { + Rectangle a = allocation.getBounds(); + int neededWidth = (int) getPreferredSpan(View.HORIZONTAL); + int neededHeight = (int) getPreferredSpan(View.VERTICAL); + + JTextArea ta = (JTextArea) textComponent; + if (a.width != neededWidth) + { + FontMetrics metrics = ta.getFontMetrics(ta.getFont()); + int reqWidth = ta.getColumns() * metrics.charWidth('m'); + if (reqWidth < neededWidth) + ta.revalidate(); + } + else if (a.height != neededHeight) + { + FontMetrics metrics = ta.getFontMetrics(ta.getFont()); + int reqHeight = ta.getRows() * metrics.getHeight(); + + if (reqHeight < neededHeight) + ta.revalidate(); + } + } + + } + public static ComponentUI createUI(JComponent comp) { return new BasicTextAreaUI(); @@ -59,7 +113,10 @@ public BasicTextAreaUI() { - // Nothing to do here. + // Cannot use special constructor for this as TextAreaRootView is a + // non-static inner class. The assignment displaces the instance + // that was created in BasicTextUI. + rootView = new TextAreaRootView(); } /**
signature.asc
Description: OpenPGP digital signature