4783068: Components with HTML text should gray out the text when disabled
authorpeterz
Mon, 23 Mar 2009 16:41:47 +0300
changeset 2493 93a357c96600
parent 2492 0ea97f5e5746
child 2494 f7cd4bd0674c
4783068: Components with HTML text should gray out the text when disabled Summary: Views fixed to use different colors when container is disabled Reviewed-by: gsm, rupashka
jdk/src/share/classes/javax/swing/text/GlyphView.java
jdk/src/share/classes/javax/swing/text/html/ImageView.java
jdk/src/share/classes/javax/swing/text/html/StyleSheet.java
jdk/test/javax/swing/text/html/Test4783068.java
--- a/jdk/src/share/classes/javax/swing/text/GlyphView.java	Mon Mar 23 14:09:32 2009 +0300
+++ b/jdk/src/share/classes/javax/swing/text/GlyphView.java	Mon Mar 23 16:41:47 2009 +0300
@@ -30,6 +30,7 @@
 import java.util.BitSet;
 import java.util.Locale;
 
+import javax.swing.UIManager;
 import sun.swing.SwingUtilities2;
 
 /**
@@ -382,11 +383,10 @@
         Color bg = getBackground();
         Color fg = getForeground();
 
-        if (c instanceof JTextComponent) {
-            JTextComponent tc = (JTextComponent) c;
-            if  (!tc.isEnabled()) {
-                fg = tc.getDisabledTextColor();
-            }
+        if (c != null && ! c.isEnabled()) {
+            fg = (c instanceof JTextComponent ?
+                ((JTextComponent)c).getDisabledTextColor() :
+                UIManager.getColor("textInactiveText"));
         }
         if (bg != null) {
             g.setColor(bg);
--- a/jdk/src/share/classes/javax/swing/text/html/ImageView.java	Mon Mar 23 14:09:32 2009 +0300
+++ b/jdk/src/share/classes/javax/swing/text/html/ImageView.java	Mon Mar 23 16:41:47 2009 +0300
@@ -25,9 +25,7 @@
 package javax.swing.text.html;
 
 import java.awt.*;
-import java.awt.event.*;
 import java.awt.image.ImageObserver;
-import java.io.*;
 import java.net.*;
 import java.util.Dictionary;
 import javax.swing.*;
@@ -97,6 +95,7 @@
 
     private AttributeSet attr;
     private Image image;
+    private Image disabledImage;
     private int width;
     private int height;
     /** Bitmask containing some of the above bitmask values. Because the
@@ -193,6 +192,17 @@
         return image;
     }
 
+    private Image getImage(boolean enabled) {
+        Image img = getImage();
+        if (! enabled) {
+            if (disabledImage == null) {
+                disabledImage = GrayFilter.createDisabledImage(img);
+            }
+            img = disabledImage;
+        }
+        return img;
+    }
+
     /**
      * Sets how the image is loaded. If <code>newValue</code> is true,
      * the image we be loaded when first asked for, otherwise it will
@@ -338,8 +348,6 @@
 
         Rectangle rect = (a instanceof Rectangle) ? (Rectangle)a :
                          a.getBounds();
-
-        Image image = getImage();
         Rectangle clip = g.getClipBounds();
 
         fBounds.setBounds(rect);
@@ -350,29 +358,29 @@
                        rect.width - leftInset - rightInset,
                        rect.height - topInset - bottomInset);
         }
-        if (image != null) {
-            if (!hasPixels(image)) {
+
+        Container host = getContainer();
+        Image img = getImage(host == null || host.isEnabled());
+        if (img != null) {
+            if (! hasPixels(img)) {
                 // No pixels yet, use the default
-                Icon icon = (image == null) ? getNoImageIcon() :
-                                               getLoadingImageIcon();
-
+                Icon icon = getLoadingImageIcon();
                 if (icon != null) {
-                    icon.paintIcon(getContainer(), g, rect.x + leftInset,
-                                   rect.y + topInset);
+                    icon.paintIcon(host, g,
+                            rect.x + leftInset, rect.y + topInset);
                 }
             }
             else {
                 // Draw the image
-                g.drawImage(image, rect.x + leftInset, rect.y + topInset,
+                g.drawImage(img, rect.x + leftInset, rect.y + topInset,
                             width, height, imageObserver);
             }
         }
         else {
             Icon icon = getNoImageIcon();
-
             if (icon != null) {
-                icon.paintIcon(getContainer(), g, rect.x + leftInset,
-                               rect.y + topInset);
+                icon.paintIcon(host, g,
+                        rect.x + leftInset, rect.y + topInset);
             }
             View view = getAltView();
             // Paint the view representing the alt text, if its non-null
@@ -855,7 +863,9 @@
         // it will pick up the new height/width, if necessary.
         public boolean imageUpdate(Image img, int flags, int x, int y,
                                    int newWidth, int newHeight ) {
-            if (image == null || image != img || getParent() == null) {
+            if (img != image && img != disabledImage ||
+                image == null || getParent() == null) {
+
                 return false;
             }
 
@@ -873,6 +883,8 @@
                         if ((state & HEIGHT_FLAG) != HEIGHT_FLAG) {
                             height = DEFAULT_HEIGHT;
                         }
+                    } else {
+                        disabledImage = null;
                     }
                     if ((state & LOADING_FLAG) == LOADING_FLAG) {
                         // No need to resize or repaint, still in the process
@@ -885,38 +897,37 @@
                 return false;
             }
 
-            // Resize image if necessary:
-            short changed = 0;
-            if ((flags & ImageObserver.HEIGHT) != 0 && !getElement().
-                  getAttributes().isDefined(HTML.Attribute.HEIGHT)) {
-                changed |= 1;
-            }
-            if ((flags & ImageObserver.WIDTH) != 0 && !getElement().
-                  getAttributes().isDefined(HTML.Attribute.WIDTH)) {
-                changed |= 2;
-            }
+            if (image == img) {
+                // Resize image if necessary:
+                short changed = 0;
+                if ((flags & ImageObserver.HEIGHT) != 0 && !getElement().
+                      getAttributes().isDefined(HTML.Attribute.HEIGHT)) {
+                    changed |= 1;
+                }
+                if ((flags & ImageObserver.WIDTH) != 0 && !getElement().
+                      getAttributes().isDefined(HTML.Attribute.WIDTH)) {
+                    changed |= 2;
+                }
 
-            synchronized(ImageView.this) {
-                if (image != img) {
-                    return false;
-                }
-                if ((changed & 1) == 1 && (state & WIDTH_FLAG) == 0) {
-                    width = newWidth;
+                synchronized(ImageView.this) {
+                    if ((changed & 1) == 1 && (state & WIDTH_FLAG) == 0) {
+                        width = newWidth;
+                    }
+                    if ((changed & 2) == 2 && (state & HEIGHT_FLAG) == 0) {
+                        height = newHeight;
+                    }
+                    if ((state & LOADING_FLAG) == LOADING_FLAG) {
+                        // No need to resize or repaint, still in the process of
+                        // loading.
+                        return true;
+                    }
                 }
-                if ((changed & 2) == 2 && (state & HEIGHT_FLAG) == 0) {
-                    height = newHeight;
-                }
-                if ((state & LOADING_FLAG) == LOADING_FLAG) {
-                    // No need to resize or repaint, still in the process of
-                    // loading.
+                if (changed != 0) {
+                    // May need to resize myself, asynchronously:
+                    safePreferenceChanged();
                     return true;
                 }
             }
-            if (changed != 0) {
-                // May need to resize myself, asynchronously:
-                safePreferenceChanged();
-                return true;
-            }
 
             // Repaint when done or when new pixels arrive:
             if ((flags & (FRAMEBITS|ALLBITS)) != 0) {
--- a/jdk/src/share/classes/javax/swing/text/html/StyleSheet.java	Mon Mar 23 14:09:32 2009 +0300
+++ b/jdk/src/share/classes/javax/swing/text/html/StyleSheet.java	Mon Mar 23 16:41:47 2009 +0300
@@ -31,6 +31,7 @@
 import java.net.*;
 import javax.swing.Icon;
 import javax.swing.ImageIcon;
+import javax.swing.UIManager;
 import javax.swing.border.*;
 import javax.swing.event.ChangeListener;
 import javax.swing.text.*;
@@ -2161,6 +2162,7 @@
          */
         public void paint(Graphics g, float x, float y, float w, float h, View v, int item) {
             View cv = v.getView(item);
+            Container host = v.getContainer();
             Object name = cv.getElement().getAttributes().getAttribute
                          (StyleConstants.NameAttribute);
             // Only draw something if the View is a list item. This won't
@@ -2171,7 +2173,7 @@
             }
             // deside on what side draw bullets, etc.
             isLeftToRight =
-                cv.getContainer().getComponentOrientation().isLeftToRight();
+                host.getComponentOrientation().isLeftToRight();
 
             // How the list indicator is aligned is not specified, it is
             // left up to the UA. IE and NS differ on this behavior.
@@ -2200,15 +2202,15 @@
             }
 
             // set the color of a decoration
-            if (ss != null) {
-                g.setColor(ss.getForeground(cv.getAttributes()));
-            } else {
-                g.setColor(Color.black);
-            }
+            Color c = (host.isEnabled()
+                ? (ss != null
+                    ? ss.getForeground(cv.getAttributes())
+                    : host.getForeground())
+                : UIManager.getColor("textInactiveText"));
+            g.setColor(c);
 
             if (img != null) {
-                drawIcon(g, (int) x, (int) y, (int) w, (int) h, align,
-                         v.getContainer());
+                drawIcon(g, (int) x, (int) y, (int) w, (int) h, align, host);
                 return;
             }
             CSS.Value childtype = getChildType(cv);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/text/html/Test4783068.java	Mon Mar 23 16:41:47 2009 +0300
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+   @bug 4783068
+   @summary Disabled components should render grayed-out HTML
+   @author Peter Zhelezniakov
+   @run main Test4783068
+*/
+
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import javax.swing.*;
+import javax.swing.plaf.metal.MetalLookAndFeel;
+
+public class Test4783068 {
+    final static Color TEST_COLOR = Color.WHITE;
+
+    final static String html = "<html>" +
+                  "This is a <font color='red'>colored</font> <b>text</b>" +
+                  "<p>with a <a href='http://ru.sun.com'>link</a>" +
+                  "<ul><li>an unordered<li>list</ul>" +
+                  "<ol><li>and an ordered<li>list</ol>" +
+                  "</html>";
+
+
+    void test() {
+        try {
+            UIManager.setLookAndFeel(new MetalLookAndFeel());
+        } catch (UnsupportedLookAndFeelException e) {
+            throw new Error("Cannot set Metal LAF");
+        }
+        // Render text using background color
+        UIManager.put("textInactiveText", TEST_COLOR);
+
+        test(new JLabel(html));
+        test(new JButton(html));
+
+        JEditorPane pane = new JEditorPane("text/html", html);
+        pane.setDisabledTextColor(TEST_COLOR);
+        test(pane);
+    }
+
+    void test(JComponent c) {
+        c.setEnabled(false);
+        c.setOpaque(true);
+        c.setBackground(TEST_COLOR);
+        c.setBorder(null);
+        Dimension size = c.getPreferredSize();
+        c.setBounds(0, 0, size.width, size.height);
+
+        BufferedImage image = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_ARGB);
+        c.paint(image.getGraphics());
+
+        int rgb = TEST_COLOR.getRGB();
+        for (int i = 0; i < size.height; i++) {
+            for (int j = 0; j < size.width; j++) {
+                if (image.getRGB(j, i) != rgb) {
+                    throw new RuntimeException(
+                            String.format("Color mismatch at [%d, %d]", j, i));
+                }
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        SwingUtilities.invokeAndWait(new Runnable() {
+            @Override public void run() {
+                new Test4783068().test();
+            }
+        });
+    }
+}