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

Floating JToolBar: the drag window sometimes has a wrong orientation

    XMLWordPrintable

Details

    • b03
    • generic, x86
    • generic, windows_xp
    • Verified

    Backports

      Description

        java version: 1.5 or later

        The JToolBar's drag window sometimes has a wrong orientation. Use the following test case:

        === Source begin ===
        import javax.swing.*;
        import java.awt.BorderLayout;
        import java.awt.Dimension;

        public class JToolBarTest extends JPanel {

            public static void main(String[] args) throws Exception {
                SwingUtilities.invokeAndWait(new Runnable() {
                    public void run() {
                        createAndShowGUI();
                    }
                });
            }

            private static void createAndShowGUI() {
                JFrame frame = new JFrame("JToolBarTest");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setContentPane(new JToolBarTest());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }

            public JToolBarTest() {
                super(new BorderLayout());

                //Create the toolbar.
                JToolBar toolBar = new JToolBar("Still draggable");
                addButtons(toolBar);

                //Lay out the main panel.
                setPreferredSize(new Dimension(800, 600));
                add(toolBar, BorderLayout.NORTH);
            }

            private void addButtons(JToolBar toolBar) {
                JButton button;
                for (int i = 0; i < 5; i++) {
                    //first button
                    button = new JButton("Item " + i);
                    toolBar.add(button);
                }
            }
        }
        === Source end ===

        Steps to reproduce the problem:
        1. Run the test
        2. Try to drag the toolbar to every side of the frame holding the mouse button pressed. Note, that the drag window changes its orientation when it is near a frame side.
        3. Make the toolbar floating in the special manner:
             - If the toolbar has horizontal orientation, achieve the vertical orientation for the drag window and release the mouse button. The toolbar must become floating.
             - If the toolbar has vertical orientation, achieve the horizontal orientation for the drag window and release the mouse button.
        4. Try to drag the toolbar to every side of the frame holding pressed the mouse button. Note, that the drag window changes its orientation in the wrong way: it is horizontal at the left or right frame side and it is vertical at the top or bottom frame side (see the attached screenshots).

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        The drag window orientation should be HORIZONTAL when the drag window is near the TOP and BOTTOM frame sides and VERTICAL for the LEFT and RIGHT sides.

        ACTUAL -
        The drag window orientation can be VERTICAL for the TOP and BOTTOM frame sides and HORIZONTAL for the LEFT and RIGHT sides.
        There is a bug, which is solved by the fix for this CR: 6729827. The description of 6729827 is below:

        FULL PRODUCT VERSION :
        Java version "1.6.0_05"
        Java(TM) SE Runtime Environment (build 1.6.0_05-b13)
        Java HotSpot(TM) Client VM (build 10.0-b19, mixed mode, sharing)

        ADDITIONAL OS VERSION INFORMATION :
        Microsoft Windows XP [Version 5.1.2600]

        A DESCRIPTION OF THE PROBLEM :
        On Windows XP and System Look and Feel, it is possible to drag a floatable JToolBar outside of the desktop area. By this, the JToolBar disappears completely and cannot be retreived again, even not with the Cascading/Titling Windows options of the desktop.
        The problem is related to the fact that when grabbing the toolbar with the mouse, it centers the floating toolbar at the mouse location, but it later positions the toolbar at its top left corner. Therefore, if the toolbar changes its orientation at the drop point, it can be completely outside the desktop.

        In default look and feel, this effect does not happen so easily, since the default look and feel does not center the floating toolbar at the mouse location but rather keeps the top left corner of the toolbar close to the mouse location.

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        Run the attached sample on Windows XP.
        Start dragging the toolbar.
        When the toolbar is close to the left or right border of the window, it changes to vertical mode.
        Drag it carefully to the left away from the left border, or to the right away from the right border, so that it stays in vertical mode.
        (Avoid that you come to close to the top border, to avoid that it changes to horizontal mode).
        Now drag the toolbar so that the mouse is at the top border of the desktop.
        If it is now in vertical mode and you drop it, it switches to horizontal mode and is placed outside the desktop, i.e. at negative y location on the screen. It disappears.

        After it disappeared, it seems not to exist anymore, because it cannot be retrieved.


        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        The toolbar should always stay inside the desktop area.

        ACTUAL -
        The toolbar disappears, obviosuly because it is located completely outside the desktop area.


        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        import java.awt.*;
        import java.awt.event.*;
        import java.net.*;
        import javax.swing.*;

        public class Test
        {
          public static final void main(String[] arg)
          {
            try {
              UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (Throwable e1) {
              e1.printStackTrace();
            }

            final JFrame frame = new JFrame("Test Sample");

            JToolBar controlBar = new JToolBar();
            controlBar.add(new JButton ("A"));
            controlBar.add(new JButton ("B"));
            controlBar.add(new JButton ("C"));
            controlBar.add(new JButton ("D"));
            controlBar.add(new JButton ("E"));
            controlBar.add(new JButton ("testing testig testing testing testing"));
            controlBar.add(new JButton ("testing testig2 testing testin"));

            frame.getContentPane().add(controlBar, BorderLayout.NORTH);
            frame.getContentPane().add(new JPanel(), BorderLayout.CENTER);

            SwingUtilities.invokeLater(new Runnable() {
              public void run() {
                frame.setSize(600, 600);
                frame.setVisible(true);
              }
            });
          }
        }

        ---------- END SOURCE ----------

        CUSTOMER SUBMITTED WORKAROUND :
        One workaround is to avoid using the system look and feel.

        The attached program illustrates another workaround:


        public class Test2
        {
          private static boolean fixToolBar = true;


          public static final void main(String[] arg)
          {
            try {
              UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (Throwable e1) {
              e1.printStackTrace();
            }

            // only needed when fixToolBar = true;
            final ComponentListener listener = new ComponentListener () {
              public void componentResized(ComponentEvent e) {
                Component c = e.getComponent();
                if (c != null) {
                  Point p = c.getLocation();
                  if (p.x < 0 || p.y < 0) {
                    if (p.x < 0) p.x = 0;
                    if (p.y < 0) p.y = 0;
                    c.setLocation(p);
                  }
                }
              }
              public void componentMoved(ComponentEvent e) {
                Component c = e.getComponent();
                if (c != null) {
                  Point p = c.getLocation();
                  if (p.x < 0 || p.y < 0) {
                    if (p.x < 0) p.x = 0;
                    if (p.y < 0) p.y = 0;
                    c.setLocation(p);
                  }
                }
              }
              public void componentShown(ComponentEvent e) {}
              public void componentHidden(ComponentEvent e) {}
            };

            final JFrame frame = new JFrame("Test2 Sample");

            JToolBar controlBar = new JToolBar() {
              public void setBounds(int x, int y, int width, int height) {
                Component parent = getParent();
                while (fixToolBar && parent != null) {
                  if (parent instanceof JDialog) {
                    Point p = parent.getLocation();
                    ComponentListener[] listeners = parent.getComponentListeners();
                    boolean found = false;
                    if (listeners != null) {
                      for (int i = 0; i < listeners.length; i++)
                        if (listeners[i] == listener)
                          found = true;
                    }
                    if (!found) {
                      parent.addComponentListener(listener);
                    }
                  }
                  parent = parent.getParent();
                }
                super.setBounds(x, y, width, height);
              }
            };
            controlBar.add(new JButton ("A"));
            controlBar.add(new JButton ("B"));
            controlBar.add(new JButton ("C"));
            controlBar.add(new JButton ("D"));
            controlBar.add(new JButton ("E"));
            controlBar.add(new JButton ("testing testig testing testing testing"));
            controlBar.add(new JButton ("testing testig2 testing testin"));

            frame.getContentPane().add(controlBar, BorderLayout.NORTH);
            frame.getContentPane().add(new JPanel(), BorderLayout.CENTER);

            SwingUtilities.invokeLater(new Runnable() {
              public void run() {
                frame.setSize(600, 600);
                frame.setVisible(true);
              }
            });
          }
        }

        Attachments

          Issue Links

            Activity

              People

                mlapshin Mikhail Lapshin (Inactive)
                mlapshin Mikhail Lapshin (Inactive)
                Votes:
                0 Vote for this issue
                Watchers:
                0 Start watching this issue

                Dates

                  Created:
                  Updated:
                  Resolved:
                  Imported:
                  Indexed: