Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6817933

Setting the background of an HTML Widget changes the native Windows JFileChooser

    XMLWordPrintable

Details

    • b75
    • x86
    • windows_2000

    Description

      FULL PRODUCT VERSION :
      java version "1.6.0_12"
      Java(TM) SE Runtime Environment (build 1.6.0_12-b04)
      Java HotSpot(TM) Client VM (build 11.2-b01, mixed mode, sharing)
      Also
      java version "1.5.0_17"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_17-b04)
      Java HotSpot(TM) Client VM (build 1.5.0_17-b04, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 5.2.3790]
      Microsoft Windows [Version 6.0.6001]

      A DESCRIPTION OF THE PROBLEM :
      Using style sheets to set the background color of the html widget also sets the background
      of the JToggleButton in the Windows Places Bar in the Windows
      native file chooser (WindowsFileChooserUI). The Windows Places Bar is the area on the
      left that has text for "My Recent Documents", "Desktop", "My Documents",
      "My Computer" etc. When we set the html "body" style, this affects the background
      of the text. It looks like this is a bug in the WindowsPlacesBar code,

      http://sun.calstatela.edu/~cysun/documentation/java/1.5.0-source/j2se/src/share/classes/sun/swing/WindowsPlacesBar.java
      looks like:

                  if (isXPPlatform) {
                      buttons[i].setIconTextGap(2);
                      buttons[i].setMargin(new Insets(2, 2, 2, 2));
                      buttons[i].setText("<html><center>"+folderName+"</center></html>");
                  }


      So, the problem is that the text in the Windows Places Bar is html and setting
      the body background color affects it.
      The text of the button in the Windows Places Bar defaults to white, so if the
      background is set to white, then white boxes appear in the Windows native browser.

      One possible fix would be to not use <html>...</html> in this context.
      It is not clear to me where the white color for the text is comming from


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Under Windows 2000 Server, or Windows Vista, create a stylesheet file called
      HTMLCSSWindowsFileChooserBug.css that contains:
      --start--
      BODY {
         background: #ff0000;
      }
      --end--
      Compile the test case:
      bash-3.2 c:/Program\ Files/Java/jdk1.6.0_12/bin/javac HTMLCSSWindowsFileChooserBug.java

      Then run the test case:
      bash-3.2$ c:/Program\ Files/Java/jdk1.6.0_12/bin/java -classpath . HTMLCSSWindowsFileChooserBug

      Select File -> Open

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Setting the background of an HTMLEditorKit should not cause the native Windows File
      Chooser to have red boxes in the Windows File Places Bar.

      ACTUAL -
      On the left hand side of the native Window File Chooser, there are red boxes behind
      the white lettering describing the Windows Places such as "My Documents". If the
      background was set to white in the .css file, then the boxes would be white and the text
      would be invisible.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      // Illustrates bug
      // http://bugzilla.ecoinformatics.org/show_bug.cgi?id=3801
      // where setting the stylesheet of an HTMLEditorKit changes
      // the Windows native look and feel JFileChooser.
      // What happens is that the text of the Windows Places Bar,
      // which usually has icons and text for "My Recent Documents"
      // "Desktop", "My Documents", "My Computer" etc. gets changed
      // so that the text background is the same as the HTML body background
      // which is set the same as the style sheet.

      // Based on code from http://www.cusc.ctu.edu.vn/forum/index.php?PHPSESSID=0020d8bc5a9edaa9a320d7aae1f81df4&topic=167.msg458

      import java.awt.*;
      import java.awt.event.*;
      import java.io.*;
      import java.net.URL;
      import java.util.*;

      import javax.swing.*;
      import javax.swing.text.*;
      import javax.swing.event.*;
      import javax.swing.border.*;
      import javax.swing.text.html.*;

      public class HTMLCSSWindowsFileChooserBug extends JFrame {

         protected JTextPane editor;
         protected HTMLDocument doc;
         protected HTMLEditorKit kit;
         protected JFileChooser chooser;

         public HTMLCSSWindowsFileChooserBug() throws Exception {
            super("HTMLEditorKit/JFileChooser/Stylesheet bug");
            setSize(650, 400);

            editor = new JTextPane();
            kit = new HTMLEditorKit();
            editor.setEditorKit(kit);

            // Set the style sheet
            HTMLDocument doc = (HTMLDocument) editor.getDocument();
            StyleSheet styleSheet = doc.getStyleSheet();
            Class refClass = Class.forName("HTMLCSSWindowsFileChooserBug");
            String styleSheetFileName = "HTMLCSSWindowsFileChooserBug.css";
            URL _styleSheetURL = refClass.getClassLoader().getResource(
                    styleSheetFileName);
            if (_styleSheetURL == null) {
                throw new Exception("Failed to read " + styleSheetFileName);
            }
            styleSheet.importStyleSheet(_styleSheetURL);
            kit.setStyleSheet(styleSheet);

            JScrollPane ps = new JScrollPane(editor);
            getContentPane().add(ps, BorderLayout.CENTER);

            JMenuBar menuBar = createMenuBar();
            setJMenuBar(menuBar);

            chooser = new JFileChooser();

            doc = (HTMLDocument)kit.createDefaultDocument();

            editor.setDocument(doc);

            WindowListener wndCloser = new WindowAdapter() {
               public void windowClosing(WindowEvent e) {
                  System.exit(0);
               }
            };
            addWindowListener(wndCloser);
         }

         protected JMenuBar createMenuBar() {
            JMenuBar menuBar = new JMenuBar();

            JMenu mFile = new JMenu("File");

            Action actionOpen = new AbstractAction("Open...") {
               public void actionPerformed(ActionEvent e) {
                   chooser.showOpenDialog(HTMLCSSWindowsFileChooserBug.this);
               }
            };
            JMenuItem item = new JMenuItem(actionOpen);
            mFile.add(item);

            menuBar.add(mFile);
            return menuBar;
         }

         public static void main(String argv[]) {
              SwingUtilities.invokeLater(new Runnable() {
                  public void run() {
                      try {
                          UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

                          HTMLCSSWindowsFileChooserBug frame = new HTMLCSSWindowsFileChooserBug();
                          frame.setVisible(true);
                      } catch (Exception e) {
                          e.printStackTrace();
                      }
      }
      });
         }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      1. The most obvious workaround is to not set the background to white.
      This is not acceptable to the customer as some of the pages rendered by the
      application have non-white backgrounds.

      2. Disabling the Windows Places Bar is another possibility, though users expect
      this functionality in the FileChooser.

      http://java.sun.com/j2se/1.5.0/docs/guide/swing/1.5/ suggests:

      > 4723745: Metal & Windows FileChooserUI classes cannot be used without
      > ShellFolder
      > Description:
      >
      > Since 1.4, the JFileChooser code has too strong a dependence on the native
      > layer. An attempt was made to bypass this class for programs that use a
      > customized "virtual" filesystem, but the algorithm is not 100% reliable.
      > To toggle this behavior, use the client property FileChooser.useShellFolder,
      > for example, to turn off use of the native set this to false:
      >
      > jFileChooser.putClientProperty("FileChooser.useShellFolder",
      > Boolean.FALSE);

      My solution was to modify the class that sets renders the HTML so that
      before JFileChooser is called, the background is saved, then the background is
      set to the value of a property, "ToolBar.shadow", and then original background
      is restored.

      My hacky code is:
       Color background = null;
              try {
                  // Get the background color of the HTML widget.
                  AttributeSet bodyAttribute = (AttributeSet) styleSheet.getStyle("body")
                      .getAttribute(javax.swing.text.StyleConstants.ResolveAttribute);
                  background = styleSheet.getBackground(bodyAttribute);
              } catch (Exception ex) {
                  System.err.println("Problem getting background color");
                  ex.printStackTrace();
              }

      try {
                  try {
                      // Get the color of the ToolBar shadow and use it.
                      Color shadow = UIManager.getColor("ToolBar.shadow");
                      String rgb = Integer.toHexString(shadow.getRGB());
                      styleSheet.addRule("BODY {background: #"
                              + rgb.substring(2, rgb.length())
                              + ";}");
                      _HTMLEditorKit.setStyleSheet(styleSheet);
      } catch (Exception ex) {
                      System.err.println("Problem setting background color");
                      ex.printStackTrace();
                  }
                 // The line below is what actually invokes JFileChooser
      super._open();
      } finally {
                  try {
                      if (background != null) {
                          // Restore the background color.
                          String rgb = Integer.toHexString(background.getRGB());
                          styleSheet.addRule("BODY {background: #"
                                  + rgb.substring(2, rgb.length())
                                  + ";}");
                          _HTMLEditorKit.setStyleSheet(styleSheet);
                      }
      } catch (Exception ex) {
                      System.out.println("Problem restoring background color.");
                      ex.printStackTrace();
                  }
      }

      Attachments

        Activity

          People

            malenkov Sergey Malenkov (Inactive)
            igor Igor Nekrestyanov (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: