Hi, the attached patch fixes PR 27393. As said in one comment one reason for the hang is that DefaultCaret will create a (zero-sized) selection (= highlight) as soon as someone sets the dot. This was once thought to be good for performance (less object instantiations) but triggered some problems in the javax.swing.text.View classes which occur when the allocation area is empty.
Getting the View (and related) classes to act in a proper way in Classpath is a
bit difficult as their behavior is not specified and I have to find out what
they should do by writing little BeanShell scripts, run them on the RI, call
various View class methods with funny arguments and note how they react. I did
such a try-and-error session for BasicTextUI and WrappedPlainView now and fixed
them according to my findings.
The result is that Audrius' earlier fix is not neccessary as this should be
handled by now in a different way: If the allocation area is empty (this would
trigger the endless loop) the method WrappedPlainView.WrappedLine.modelToView
throws a BadLocationException.
The patch contains a change to BasicTextUI.getVisibleEditorRect() to return null
instead of an empty Rectangle if the component's area is empty (width or width
being zero). This has some consequences: BasicTextUI.modelToView() should not
forward the call to the RootView but insertUpdate, removeUpdate and changeUpdate
should expect the allocation areas shape to be null.
Hm, these details might be useful for future work on these classes. I should
find a way to keep it ...
The ChangeLog:
2006-05-03 Robert Schuster <[EMAIL PROTECTED]>
* javax/swing/plaf/basic/BasicTextUI.java:
(changeUpdate): Added note.
(removeUpdate): Dito.
(insertUpdate): Dito.
(damageRange): Added if-block to return early.
(modelToView): Added check of getVisibleEditorRect's return value.
(getVisibleEditorRect): Return null instead of empty rectangle.
* javax/swing/text/DefaultCaret.java:
(clearHighlight): Removed if-clause to create a highlight entry if it
did not exist before.
* javax/swing/text/WrappedPlainView.java:
(WrappedLine.modelToView): Throw exception if allocation area is empty,
removed 2nd part of if-expression.
(WrappedLine.updateDamage): Added more documentation, added check
whether allocation area rectangle is null.
cya
Robert
Index: javax/swing/plaf/basic/BasicTextUI.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicTextUI.java,v
retrieving revision 1.81
diff -u -r1.81 BasicTextUI.java
--- javax/swing/plaf/basic/BasicTextUI.java 20 Apr 2006 19:21:08 -0000 1.81
+++ javax/swing/plaf/basic/BasicTextUI.java 3 May 2006 18:08:08 -0000
@@ -440,6 +440,9 @@
*/
public void changedUpdate(DocumentEvent ev)
{
+ // Updates are forwarded to the View even if 'getVisibleEditorRect'
+ // method returns null. This means the View classes have to be
+ // aware of that possibility.
rootView.changedUpdate(ev, getVisibleEditorRect(),
rootView.getViewFactory());
}
@@ -451,6 +454,9 @@
*/
public void insertUpdate(DocumentEvent ev)
{
+ // Updates are forwarded to the View even if 'getVisibleEditorRect'
+ // method returns null. This means the View classes have to be
+ // aware of that possibility.
rootView.insertUpdate(ev, getVisibleEditorRect(),
rootView.getViewFactory());
}
@@ -462,6 +468,9 @@
*/
public void removeUpdate(DocumentEvent ev)
{
+ // Updates are forwarded to the View even if 'getVisibleEditorRect'
+ // method returns null. This means the View classes have to be
+ // aware of that possibility.
rootView.removeUpdate(ev, getVisibleEditorRect(),
rootView.getViewFactory());
}
@@ -1015,6 +1024,10 @@
public void damageRange(JTextComponent t, int p0, int p1,
Position.Bias firstBias, Position.Bias secondBias)
{
+ // Do nothing if the component cannot be properly displayed.
+ if (t.getWidth() == 0 || t.getHeight() == 0)
+ return;
+
try
{
// Limit p0 and p1 to sane values to prevent unfriendly
@@ -1201,7 +1214,10 @@
public Rectangle modelToView(JTextComponent t, int pos, Position.Bias bias)
throws BadLocationException
{
- return rootView.modelToView(pos, getVisibleEditorRect(), bias).getBounds();
+ Rectangle r = getVisibleEditorRect();
+
+ return (r != null) ? rootView.modelToView(pos, r, bias).getBounds()
+ : null;
}
/**
@@ -1278,8 +1294,9 @@
int width = textComponent.getWidth();
int height = textComponent.getHeight();
+ // Return null if the component has no valid size.
if (width <= 0 || height <= 0)
- return new Rectangle(0, 0, 0, 0);
+ return null;
Insets insets = textComponent.getInsets();
return new Rectangle(insets.left, insets.top,
Index: javax/swing/text/DefaultCaret.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/DefaultCaret.java,v
retrieving revision 1.39
diff -u -r1.39 DefaultCaret.java
--- javax/swing/text/DefaultCaret.java 19 Apr 2006 19:20:44 -0000 1.39
+++ javax/swing/text/DefaultCaret.java 3 May 2006 18:08:08 -0000
@@ -721,9 +721,7 @@
{
try
{
- if (highlightEntry == null)
- highlightEntry = highlighter.addHighlight(0, 0, getSelectionPainter());
- else
+ if (highlightEntry != null)
highlighter.changeHighlight(highlightEntry, 0, 0);
// Free the global variable which stores the text component with an active
Index: javax/swing/text/WrappedPlainView.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/WrappedPlainView.java,v
retrieving revision 1.20
diff -u -r1.20 WrappedPlainView.java
--- javax/swing/text/WrappedPlainView.java 3 May 2006 08:27:40 -0000 1.20
+++ javax/swing/text/WrappedPlainView.java 3 May 2006 18:08:09 -0000
@@ -542,9 +542,15 @@
public Shape modelToView(int pos, Shape a, Bias b)
throws BadLocationException
{
+ Rectangle rect = a.getBounds();
+
+ // Throwing a BadLocationException is an observed behavior of the RI.
+ if (rect.isEmpty())
+ throw new BadLocationException("Unable to calculate view coordinates "
+ + "when allocation area is empty.", 5);
+
Segment s = getLineBuffer();
int lineHeight = metrics.getHeight();
- Rectangle rect = a.getBounds();
// Return a rectangle with width 1 and height equal to the height
// of the text
@@ -563,8 +569,7 @@
// If pos is between currLineStart and currLineEnd then just find
// the width of the text from currLineStart to pos and add that
// to rect.x
- if (pos >= currLineStart && pos < currLineEnd ||
- (currLineEnd==currLineStart) )
+ if (pos >= currLineStart && pos < currLineEnd)
{
try
{
@@ -666,11 +671,16 @@
}
/**
- * This method is called from insertUpdate and removeUpdate.
- * If the number of lines in the document has changed, just repaint
+ * <p>This method is called from insertUpdate and removeUpdate.</p>
+ *
+ * <p>If the number of lines in the document has changed, just repaint
* the whole thing (note, could improve performance by not repainting
* anything above the changes). If the number of lines hasn't changed,
- * just repaint the given Rectangle.
+ * just repaint the given Rectangle.</p>
+ *
+ * <p>Note that the <code>Rectangle</code> argument may be <code>null</code>
+ * when the allocation area is empty.</code>
+ *
* @param a the Rectangle to repaint if the number of lines hasn't changed
*/
void updateDamage (Rectangle a)
@@ -679,7 +689,7 @@
// As determining the number of lines is impossible in that state we
// reset it to an invalid value which can then be recalculated at a
// later point.
- if (a.isEmpty())
+ if (a == null || a.isEmpty())
{
numLines = 1;
return;
signature.asc
Description: OpenPGP digital signature
