This fixes/enables scrolling for JEditorPane. 2006-08-31 Roman Kennke <[EMAIL PROTECTED]>
* javax/swing/JEditorPane.java (getPreferredSize): Replace preferred size with minimum UI size only if the scrollable does _not_ track the viewport size and only if the viewport's size is smaller than the scrollable's size. (getScrollableTracksViewportWidth): Avoid unnecessary multiple method calls. * javax/swing/plaf/basic/BasicTextUI.java (getPreferredSize): Read-lock the document to avoid concurrency problems. (getMaximumSize): Return maximum size of the view. Read-lock the document to avoid concurrency problems. (getMinimumSize): Return minimum size of the view. Read-lock the document to avoid concurrency problems. /Roman
Index: javax/swing/plaf/basic/BasicTextUI.java =================================================================== RCS file: /cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicTextUI.java,v retrieving revision 1.93 diff -u -1 -2 -r1.93 BasicTextUI.java --- javax/swing/plaf/basic/BasicTextUI.java 29 Aug 2006 10:57:17 -0000 1.93 +++ javax/swing/plaf/basic/BasicTextUI.java 31 Aug 2006 15:24:13 -0000 @@ -364,25 +364,25 @@ /** * Returns the preferred span along the specified <code>axis</code>. * This is delegated to the real root view. * * @param axis the axis for which the preferred span is queried * * @return the preferred span along the axis */ public float getPreferredSpan(int axis) { if (view != null) - return view.getPreferredSpan(axis); + return view.getPreferredSpan(axis); return Integer.MAX_VALUE; } public void setSize(float w, float h) { if (view != null) view.setSize(w, h); } /** * Paints the view. This is delegated to the real root view. @@ -956,62 +956,112 @@ /** * Returns the preferred size of the text component. * * @param c not used here * * @return the preferred size of the text component */ public Dimension getPreferredSize(JComponent c) { Dimension d = c.getSize(); Insets i = c.getInsets(); - if (d.width > (i.left + i.right) && d.height > (i.top + i.bottom)) + // We need to lock here, since we require the view hierarchy to _not_ + // change in between. + float w; + float h; + Document doc = textComponent.getDocument(); + if (doc instanceof AbstractDocument) + ((AbstractDocument) doc).readLock(); + try { - rootView.setSize(d.width - i.left - i.right, - d.height - i.top - i.bottom); + if (d.width > (i.left + i.right) && d.height > (i.top + i.bottom)) + { + rootView.setSize(d.width - i.left - i.right, + d.height - i.top - i.bottom); + } + w = rootView.getPreferredSpan(View.X_AXIS); + h = rootView.getPreferredSpan(View.Y_AXIS); + } + finally + { + if (doc instanceof AbstractDocument) + ((AbstractDocument) doc).readUnlock(); } - float w = rootView.getPreferredSpan(View.X_AXIS); - float h = rootView.getPreferredSpan(View.Y_AXIS); - Dimension size = new Dimension((int) w + i.left + i.right, (int) h + i.top + i.bottom); return size; } /** * Returns the maximum size for text components that use this UI. * * This returns (Integer.MAX_VALUE, Integer.MAX_VALUE). * * @param c not used here * * @return the maximum size for text components that use this UI */ public Dimension getMaximumSize(JComponent c) { - // Sun's implementation returns Integer.MAX_VALUE here, so do we. - return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); + Dimension d = new Dimension(); + Document doc = textComponent.getDocument(); + // We need to lock here, since we require the view hierarchy to _not_ + // change in between. + if (doc instanceof AbstractDocument) + ((AbstractDocument) doc).readLock(); + try + { + d.width = (int) rootView.getMaximumSpan(View.X_AXIS); + d.height = (int) rootView.getMaximumSpan(View.Y_AXIS); + } + finally + { + if (doc instanceof AbstractDocument) + ((AbstractDocument) doc).readUnlock(); + } + Insets i = c.getInsets(); + d.width += i.left + i.right; + d.height += i.top + i.bottom; + return d; } /** * Returns the minimum size for text components. This returns the size * of the component's insets. * * @return the minimum size for text components */ public Dimension getMinimumSize(JComponent c) { + Dimension d = new Dimension(); + Document doc = textComponent.getDocument(); + // We need to lock here, since we require the view hierarchy to _not_ + // change in between. + if (doc instanceof AbstractDocument) + ((AbstractDocument) doc).readLock(); + try + { + d.width = (int) rootView.getMinimumSpan(View.X_AXIS); + d.height = (int) rootView.getMinimumSpan(View.Y_AXIS); + } + finally + { + if (doc instanceof AbstractDocument) + ((AbstractDocument) doc).readUnlock(); + } Insets i = c.getInsets(); - return new Dimension(i.left + i.right, i.top + i.bottom); + d.width += i.left + i.right; + d.height += i.top + i.bottom; + return d; } /** * Paints the text component. This acquires a read lock on the model and then * calls [EMAIL PROTECTED] #paintSafely(Graphics)} in order to actually perform the * painting. * * @param g the <code>Graphics</code> context to paint to * @param c not used here */ public final void paint(Graphics g, JComponent c) { Index: javax/swing/JEditorPane.java =================================================================== RCS file: /cvsroot/classpath/classpath/javax/swing/JEditorPane.java,v retrieving revision 1.34 diff -u -1 -2 -r1.34 JEditorPane.java --- javax/swing/JEditorPane.java 12 Aug 2006 22:16:12 -0000 1.34 +++ javax/swing/JEditorPane.java 31 Aug 2006 15:24:13 -0000 @@ -47,24 +47,25 @@ import java.io.StringReader; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import javax.accessibility.AccessibleContext; import javax.accessibility.AccessibleHyperlink; import javax.accessibility.AccessibleHypertext; import javax.accessibility.AccessibleStateSet; import javax.accessibility.AccessibleText; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; +import javax.swing.plaf.TextUI; import javax.swing.text.BadLocationException; import javax.swing.text.DefaultEditorKit; import javax.swing.text.Document; import javax.swing.text.EditorKit; import javax.swing.text.Element; import javax.swing.text.JTextComponent; import javax.swing.text.View; import javax.swing.text.ViewFactory; import javax.swing.text.WrappedPlainView; import javax.swing.text.html.HTML; import javax.swing.text.html.HTMLDocument; import javax.swing.text.html.HTMLEditorKit; @@ -686,48 +687,68 @@ * Returns the preferred size for the JEditorPane. This is implemented to * return the super's preferred size, unless one of * [EMAIL PROTECTED] #getScrollableTracksViewportHeight()} or * [EMAIL PROTECTED] #getScrollableTracksViewportWidth()} returns <code>true</code>, * in which case the preferred width and/or height is replaced by the UI's * minimum size. * * @return the preferred size for the JEditorPane */ public Dimension getPreferredSize() { Dimension pref = super.getPreferredSize(); - if (getScrollableTracksViewportWidth()) - pref.width = getUI().getMinimumSize(this).width; - if (getScrollableTracksViewportHeight()) - pref.height = getUI().getMinimumSize(this).height; + Container parent = getParent(); + if (parent instanceof JViewport) + { + JViewport vp = (JViewport) getParent(); + TextUI ui = getUI(); + Dimension min = null; + if (! getScrollableTracksViewportWidth()) + { + min = ui.getMinimumSize(this); + int vpWidth = vp.getWidth(); + if (vpWidth != 0 && vpWidth < min.width) + pref.width = min.width; + } + if (! getScrollableTracksViewportHeight()) + { + if (min == null) + min = ui.getMinimumSize(this); + int vpHeight = vp.getHeight(); + if (vpHeight != 0 && vpHeight < min.height) + pref.height = min.height; + } + } return pref; } /** * Returns <code>true</code> when a Viewport should force the height of * this component to match the viewport height. This is implemented to return * <code>true</code> when the parent is an instance of JViewport and * the viewport height > the UI's minimum height. * * @return <code>true</code> when a Viewport should force the height of * this component to match the viewport height */ public boolean getScrollableTracksViewportHeight() { // Tests show that this returns true when the parent is a JViewport // and has a height > minimum UI height. Container parent = getParent(); + int height = parent.getHeight(); + TextUI ui = getUI(); return parent instanceof JViewport - && parent.getHeight() >= getUI().getMinimumSize(this).height - && parent.getHeight() <= getUI().getMaximumSize(this).height; + && height >= ui.getMinimumSize(this).height + && height <= ui.getMaximumSize(this).height; } /** * Returns <code>true</code> when a Viewport should force the width of * this component to match the viewport width. This is implemented to return * <code>true</code> when the parent is an instance of JViewport and * the viewport width > the UI's minimum width. * * @return <code>true</code> when a Viewport should force the width of * this component to match the viewport width */ public boolean getScrollableTracksViewportWidth()