Here come a couple of fixes for the (styled) text rendering in Swing, which should greatly improve stability for styled text using apps like BeanShell.

Next thing I'm working on right now is CSS processing and fixing up the HTML rendering to use this, and finish up HTML in general.

2006-08-13  Roman Kennke  <[EMAIL PROTECTED]>

        * javax/swing/JEditorPane.java
        (getScrollableTracksViewportHeight): Also check maximum size.
        * javax/swing/JTextPane.java
        (insertIcon): Use input attributes for adding the icon
        attribute.
        * javax/swing/plaf/basic/BasicTextUI.java
        (RootView.setSize): Overridden to forward to real view.
        (getPreferredSize): Trigger setSize() on the view.
        (viewToModel(JTextComponent,Point)): Pass Position.Bias array
        to viewToModel() call, rather then null.
        * javax/swing/text/ParagraphView.java
        (changedUpdate): Invalide layout. Call super.
        * javax/swing/text/SimpleAttributeSet.java
        (clone): Use super's clone method to create clone.
        * javax/swing/text/StyleConstants.java
        (setIcon): Also set element name attribute.
        * javax/swing/text/StyledEditorKit.java
        (BoldAction.actionPerformed): Actually set the bold attribute,
        not italic.
        (setCharacterAttributes): Replaced with more straightforward
        impl.
        * javax/swing/text/TextAction.java
        (getFocusedComponent): Implemented.
        * javax/swing/text/Utilities.java
        (getNextVisualPositionFrom): Pass Position.Bias arrays instead
        of null.
        * javax/swing/text/View.java
        (changedUpdate): Nullify element change when updateChildren
        says so.

/Roman
Index: javax/swing/JEditorPane.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/JEditorPane.java,v
retrieving revision 1.33
diff -u -1 -2 -r1.33 JEditorPane.java
--- javax/swing/JEditorPane.java	1 Jun 2006 04:38:49 -0000	1.33
+++ javax/swing/JEditorPane.java	12 Aug 2006 22:15:00 -0000
@@ -708,25 +708,26 @@
    * <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();
     return parent instanceof JViewport
-           && parent.getHeight() > getUI().getMinimumSize(this).height;
+           && parent.getHeight() >= getUI().getMinimumSize(this).height
+           && parent.getHeight() <= getUI().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()
Index: javax/swing/JTextPane.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/JTextPane.java,v
retrieving revision 1.15
diff -u -1 -2 -r1.15 JTextPane.java
--- javax/swing/JTextPane.java	7 Feb 2006 11:40:56 -0000	1.15
+++ javax/swing/JTextPane.java	12 Aug 2006 22:15:01 -0000
@@ -205,38 +205,29 @@
         err.initCause(ex);
         throw err;
       }
   }
 
   /**
    * Inserts an <code>Icon</code> into the text at the current caret position.
    *
    * @param icon the <code>Icon</code> to be inserted
    */
   public void insertIcon(Icon icon)
   {
-    SimpleAttributeSet atts = new SimpleAttributeSet();
-    atts.addAttribute(StyleConstants.IconAttribute, icon);
-    atts.addAttribute(StyleConstants.NameAttribute,
-                      StyleConstants.IconElementName);
-    try
-      {
-        getDocument().insertString(getCaret().getDot(), " ", atts);
-      }
-    catch (BadLocationException ex)
-      {
-        AssertionError err = new AssertionError("Unexpected bad location");
-        err.initCause(ex);
-        throw err;
-      }
+    MutableAttributeSet inputAtts = getInputAttributes();
+    inputAtts.removeAttributes(inputAtts);
+    StyleConstants.setIcon(inputAtts, icon);
+    replaceSelection(" ");
+    inputAtts.removeAttributes(inputAtts);
   }
 
   /**
    * Adds a style into the style hierarchy. Unspecified style attributes
    * can be resolved in the <code>parent</code> style, if one is specified.
    *
    * While it is legal to add nameless styles (<code>nm == null</code),
    * you must be aware that the client application is then responsible
    * for managing the style hierarchy, since unnamed styles cannot be
    * looked up by their name.
    *
    * @param nm the name of the style or <code>null</code> if the style should
Index: javax/swing/plaf/basic/BasicTextUI.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicTextUI.java,v
retrieving revision 1.89
diff -u -1 -2 -r1.89 BasicTextUI.java
--- javax/swing/plaf/basic/BasicTextUI.java	7 Aug 2006 11:16:10 -0000	1.89
+++ javax/swing/plaf/basic/BasicTextUI.java	12 Aug 2006 22:15:01 -0000
@@ -232,24 +232,30 @@
      * @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 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.
      *
      * @param g the <code>Graphics</code> context to paint to
      * @param s the allocation for the View
      */
     public void paint(Graphics g, Shape s)
     {
       if (view != null)
         {
           Rectangle b = s.getBounds();
           view.setSize(b.width, b.height);
@@ -882,32 +888,37 @@
    */
   protected abstract String getPropertyPrefix();
 
   /**
    * 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)
   {
-    View v = getRootView(textComponent);
-
-    float w = v.getPreferredSpan(View.X_AXIS);
-    float h = v.getPreferredSpan(View.Y_AXIS);
-
+    Dimension d = c.getSize();
     Insets i = c.getInsets();
-    return new Dimension((int) w + i.left + i.right,
+    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);
+      }
+    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)
@@ -1215,25 +1226,25 @@
   /**
    * Maps a point in the <code>View</code> coordinate space to a position
    * inside a document model.
    *
    * @param t the text component
    * @param pt the point to be mapped
    *
    * @return the position inside the document model that corresponds to
    *     <code>pt</code>
    */
   public int viewToModel(JTextComponent t, Point pt)
   {
-    return viewToModel(t, pt, null);
+    return viewToModel(t, pt, new Position.Bias[1]);
   }
 
   /**
    * Maps a point in the <code>View</code> coordinate space to a position
    * inside a document model.
    *
    * @param t the text component
    * @param pt the point to be mapped
    * @param biasReturn filled in by the method to indicate the bias of the
    *        return value
    *
    * @return the position inside the document model that corresponds to
Index: javax/swing/text/ParagraphView.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/ParagraphView.java,v
retrieving revision 1.9
diff -u -1 -2 -r1.9 ParagraphView.java
--- javax/swing/text/ParagraphView.java	7 Aug 2006 11:16:11 -0000	1.9
+++ javax/swing/text/ParagraphView.java	12 Aug 2006 22:15:01 -0000
@@ -183,29 +183,32 @@
     else
       align = 0.5F;
     return align;
   }
 
   /**
    * Receives notification when some attributes of the displayed element
    * changes. This triggers a refresh of the cached attributes of this
    * paragraph.
    *
    * @param ev the document event
    * @param a the allocation of this view
-   * @param fv the view factory to use for creating new child views
+   * @param vf the view factory to use for creating new child views
    */
-  public void changedUpdate(DocumentEvent ev, Shape a, ViewFactory fv)
+  public void changedUpdate(DocumentEvent ev, Shape a, ViewFactory vf)
   {
     setPropertiesFromAttributes();
+    layoutChanged(X_AXIS);
+    layoutChanged(Y_AXIS);
+    super.changedUpdate(ev, a, vf);
   }
 
   /**
    * Fetches the cached properties from the element's attributes.
    */
   protected void setPropertiesFromAttributes()
   {
     Element el = getElement();
     AttributeSet atts = el.getAttributes();
     setFirstLineIndent(StyleConstants.getFirstLineIndent(atts));
     setLineSpacing(StyleConstants.getLineSpacing(atts));
     setJustification(StyleConstants.getAlignment(atts));
Index: javax/swing/text/SimpleAttributeSet.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/SimpleAttributeSet.java,v
retrieving revision 1.15
diff -u -1 -2 -r1.15 SimpleAttributeSet.java
--- javax/swing/text/SimpleAttributeSet.java	27 Jul 2006 14:37:47 -0000	1.15
+++ javax/swing/text/SimpleAttributeSet.java	12 Aug 2006 22:15:02 -0000
@@ -114,27 +114,35 @@
         Object val = attributes.getAttribute(name);
         tab.put(name, val);
       }
   }
 
   /**
    * Returns a clone of the attribute set.
    * 
    * @return A clone of the attribute set.
    */
   public Object clone()
   {
-    SimpleAttributeSet s = new SimpleAttributeSet();
-    s.tab = (Hashtable) tab.clone();
-    return s;
+    SimpleAttributeSet attr = null;
+    try
+      {
+        attr = (SimpleAttributeSet) super.clone();
+        attr.tab = (Hashtable) tab.clone();
+      }
+    catch (CloneNotSupportedException ex)
+      {
+        assert false;
+      }
+    return attr;
   }
 
   /**
    * Returns true if the given name and value represent an attribute
    * found either in this AttributeSet or in its resolve parent hierarchy.
    * @param name the key for the attribute
    * @param value the value for the attribute
    * @return true if the attribute is found here or in this set's resolve
    * parent hierarchy
    */
   public boolean containsAttribute(Object name, Object value)
   {
Index: javax/swing/text/StyleConstants.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/StyleConstants.java,v
retrieving revision 1.11
diff -u -1 -2 -r1.11 StyleConstants.java
--- javax/swing/text/StyleConstants.java	4 Mar 2006 05:52:39 -0000	1.11
+++ javax/swing/text/StyleConstants.java	12 Aug 2006 22:15:02 -0000
@@ -720,24 +720,25 @@
   /**
    * Adds an icon attribute to the specified set.
    * 
    * @param a  the attribute set (<code>null</code> not permitted).
    * @param c  the icon (<code>null</code> not permitted).
    * 
    * @throws NullPointerException if either argument is <code>null</code>.
    * 
    * @see #getIcon(AttributeSet)
    */
   public static void setIcon(MutableAttributeSet a, Icon c)
   {
+    a.addAttribute(AbstractDocument.ElementNameAttribute, IconElementName);
     a.addAttribute(IconAttribute, c);
   }
  
   /**
    * Adds an italic attribute to the specified set.
    * 
    * @param a  the attribute set (<code>null</code> not permitted).
    * @param b  the new value of the italic attribute.
    * 
    * @throws NullPointerException if <code>a</code> is <code>null</code>.
    * 
    * @see #isItalic(AttributeSet)
Index: javax/swing/text/StyledEditorKit.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/StyledEditorKit.java,v
retrieving revision 1.19
diff -u -1 -2 -r1.19 StyledEditorKit.java
--- javax/swing/text/StyledEditorKit.java	19 Dec 2005 17:30:18 -0000	1.19
+++ javax/swing/text/StyledEditorKit.java	12 Aug 2006 22:15:02 -0000
@@ -133,25 +133,25 @@
     /**
      * Performs the action.
      *
      * @param event the <code>ActionEvent</code> that describes the action
      */
     public void actionPerformed(ActionEvent event)
     {
       JEditorPane editor = getEditor(event);
       StyledDocument doc = getStyledDocument(editor);
       Element el = doc.getCharacterElement(editor.getSelectionStart());
       boolean isBold = StyleConstants.isBold(el.getAttributes());
       SimpleAttributeSet atts = new SimpleAttributeSet();
-      StyleConstants.setItalic(atts, ! isBold);
+      StyleConstants.setBold(atts, ! isBold);
       setCharacterAttributes(editor, atts, false);
     }
   }
 
   /**
    * Sets the alignment attribute on the selected text.
    */
   public static class AlignmentAction extends StyledEditorKit.StyledTextAction
   {
     /**
      * The aligment to set.
      */
@@ -326,53 +326,39 @@
      * a selection, then the attributes are used as input attributes
      * for newly inserted content.
      *
      * @param editor the <code>JEditorPane</code> component
      * @param atts the text attributes to set
      * @param replace if <code>true</code> the current attributes of the
      *        selection are replaces, otherwise they are merged
      */
     protected final void setCharacterAttributes(JEditorPane editor,
                                                 AttributeSet atts,
                                                 boolean replace)
     {
-      Document doc = editor.getDocument();
-      if (doc instanceof StyledDocument)
-	{
-	  StyledDocument styleDoc = (StyledDocument) editor.getDocument();
-	  EditorKit kit = editor.getEditorKit();
-	  if (!(kit instanceof StyledEditorKit))
-	    {
-	      StyledEditorKit styleKit = (StyledEditorKit) kit;
-	      int start = editor.getSelectionStart();
-	      int end = editor.getSelectionEnd();
-	      int dot = editor.getCaret().getDot();
-	      if (start == dot && end == dot)
-		{
-		  // If there is no selection, then we only update the
-		  // input attributes.
-		  MutableAttributeSet inputAttributes =
-		    styleKit.getInputAttributes();
-		  inputAttributes.addAttributes(atts);
-		}
-	      else
-		styleDoc.setCharacterAttributes(start, end, atts, replace);
-	    }
-	  else
-	    throw new AssertionError("The EditorKit for StyledTextActions "
-				     + "is expected to be a StyledEditorKit");
-	}
-      else
-	throw new AssertionError("The Document for StyledTextActions is "
-				 + "expected to be a StyledDocument.");
+      int p0 = editor.getSelectionStart();
+      int p1 = editor.getSelectionEnd();
+      if (p0 != p1)
+        {
+          StyledDocument doc = getStyledDocument(editor);
+          doc.setCharacterAttributes(p0, p1 - p0, atts, replace);
+        }
+      // Update input attributes.
+      StyledEditorKit kit = getStyledEditorKit(editor);
+      MutableAttributeSet inputAtts = kit.getInputAttributes();
+      if (replace)
+        {
+          inputAtts.removeAttributes(inputAtts);
+        }
+      inputAtts.addAttributes(atts);
     }
 
     /**
      * Returns the [EMAIL PROTECTED] StyledDocument} that is used by <code>editor</code>.
      *
      * @param editor the <code>JEditorPane</code> from which to get the
      *        <code>StyledDocument</code>
      *
      * @return the [EMAIL PROTECTED] StyledDocument} that is used by <code>editor</code>
      */
     protected final StyledDocument getStyledDocument(JEditorPane editor)
     {
Index: javax/swing/text/TextAction.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/TextAction.java,v
retrieving revision 1.9
diff -u -1 -2 -r1.9 TextAction.java
--- javax/swing/text/TextAction.java	13 May 2006 12:23:37 -0000	1.9
+++ javax/swing/text/TextAction.java	12 Aug 2006 22:15:02 -0000
@@ -29,32 +29,33 @@
 modules, and to copy and distribute the resulting executable under
 terms of your choice, provided that you also meet, for each linked
 independent module, the terms and conditions of the license of that
 module.  An independent module is a module which is not derived from
 or based on this library.  If you modify this library, you may extend
 this exception to your version of the library, but you are not
 obligated to do so.  If you do not wish to do so, delete this
 exception statement from your version. */
 
 
 package javax.swing.text;
 
+import java.awt.Component;
+import java.awt.KeyboardFocusManager;
 import java.awt.Point;
 import java.awt.event.ActionEvent;
 import java.util.ArrayList;
 import java.util.HashSet;
 
 import javax.swing.AbstractAction;
 import javax.swing.Action;
-import javax.swing.SwingConstants;
 
 /**
  * TextAction
  * @author Andrew Selkirk
  */
 public abstract class TextAction extends AbstractAction
 {
   /**
    * Constructor TextAction
    * @param name TODO
    */
   public TextAction(String name)
@@ -99,25 +100,31 @@
 
     ArrayList list = new ArrayList(actionSet);
     return (Action[]) list.toArray(new Action[actionSet.size()]);
   }
 
   /**
    * Returns the current focused <code>JTextComponent</code> object.
    * 
    * @return the <code>JTextComponent</code>
    */
   protected final JTextComponent getFocusedComponent()
   {
-    return null; // TODO
+    KeyboardFocusManager kfm =
+      KeyboardFocusManager.getCurrentKeyboardFocusManager();
+    Component focused = kfm.getPermanentFocusOwner();
+    JTextComponent textComp = null;
+    if (focused instanceof JTextComponent)
+      textComp = (JTextComponent) focused;
+    return textComp;
   }
   
   /** Abstract helper class which implements everything needed for an
    * Action implementation in <code>DefaultEditorKit</code> which
    * does horizontal movement (and selection).  
    */
   abstract static class HorizontalMovementAction extends TextAction
   {
     int dir;
     
     HorizontalMovementAction(String name, int direction)
     {
Index: javax/swing/text/Utilities.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/Utilities.java,v
retrieving revision 1.34
diff -u -1 -2 -r1.34 Utilities.java
--- javax/swing/text/Utilities.java	11 Aug 2006 12:06:59 -0000	1.34
+++ javax/swing/text/Utilities.java	12 Aug 2006 22:15:03 -0000
@@ -697,27 +697,27 @@
    */
   static int getNextVisualPositionFrom(JTextComponent t, int offset, int direction)
   {
     NavigationFilter nf = t.getNavigationFilter();
     
     try
       {
         return (nf != null) 
           ? nf.getNextVisualPositionFrom(t,
                                          offset,
                                          Bias.Forward,
                                          direction,
-                                         null)
+                                         new Position.Bias[1])
           : t.getUI().getNextVisualPositionFrom(t,
                                                 offset,
                                                 Bias.Forward,
                                                 direction,
-                                                null);
+                                                new Position.Bias[1]);
       }
     catch (BadLocationException ble)
     {
       return offset;
     }
     
   }
   
 }
Index: javax/swing/text/View.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/View.java,v
retrieving revision 1.34
diff -u -1 -2 -r1.34 View.java
--- javax/swing/text/View.java	7 Aug 2006 11:16:11 -0000	1.34
+++ javax/swing/text/View.java	12 Aug 2006 22:15:03 -0000
@@ -420,30 +420,36 @@
    * <li>Call [EMAIL PROTECTED] #forwardUpdate}. This forwards the DocumentEvent to
    * the child views.<li>
    * <li>Call [EMAIL PROTECTED] #updateLayout}. Gives the view a chance to either
    * repair its layout, reschedule layout or do nothing at all.</li>
    * </ul>
    *
    * @param ev the DocumentEvent that describes the change
    * @param shape the shape of the view
    * @param vf the ViewFactory for creating child views
    */
   public void changedUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
   {
-    Element el = getElement();
-    DocumentEvent.ElementChange ec = ev.getChange(el);
-    if (ec != null)
-      updateChildren(ec, ev, vf);
-    forwardUpdate(ec, ev, shape, vf);
-    updateLayout(ec, ev, shape);
+    if (getViewCount() > 0)
+      {
+        Element el = getElement();
+        DocumentEvent.ElementChange ec = ev.getChange(el);
+        if (ec != null)
+          {
+            if (! updateChildren(ec, ev, vf))
+              ec = null;
+          }
+        forwardUpdate(ec, ev, shape, vf);
+        updateLayout(ec, ev, shape);
+      }
   }
 
   /**
    * Updates the list of children that is returned by [EMAIL PROTECTED] #getView}
    * and [EMAIL PROTECTED] #getViewCount}.
    *
    * Element that are specified as beeing added in the ElementChange record are
    * assigned a view for using the ViewFactory. Views of Elements that
    * are specified as beeing removed are removed from the list.
    *
    * @param ec the ElementChange record that describes the change of the
    *           element

Reply via email to