# HG changeset patch # User mlapshin # Date 1215435383 -14400 # Node ID 61e297d244250b8303b1c789127c39002998de5a # Parent 5c7b6c8a2378a6c92ba6a1ac736794222c32e51b 6647340: Minimized JInternalFrame icons appear in incorrect positions if the main frame is resized Summary: Now BasicInternalFrameUI and BasicDesktopIconUI both recalculate frame icon position Reviewed-by: peterz diff -r 5c7b6c8a2378 -r 61e297d24425 jdk/src/share/classes/javax/swing/plaf/basic/BasicDesktopIconUI.java --- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicDesktopIconUI.java Wed Jul 02 18:17:56 2008 +0400 +++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicDesktopIconUI.java Mon Jul 07 16:56:23 2008 +0400 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2008 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 @@ -47,6 +47,7 @@ protected JInternalFrame.JDesktopIcon desktopIcon; protected JInternalFrame frame; + private DesktopIconMover desktopIconMover; /** * The title pane component used in the desktop icon. @@ -127,12 +128,21 @@ mouseInputListener = createMouseInputListener(); desktopIcon.addMouseMotionListener(mouseInputListener); desktopIcon.addMouseListener(mouseInputListener); + getDesktopIconMover().installListeners(); } protected void uninstallListeners() { desktopIcon.removeMouseMotionListener(mouseInputListener); desktopIcon.removeMouseListener(mouseInputListener); mouseInputListener = null; + getDesktopIconMover().uninstallListeners(); + } + + private DesktopIconMover getDesktopIconMover() { + if (desktopIconMover == null) { + desktopIconMover = new DesktopIconMover(desktopIcon); + } + return desktopIconMover; } protected void installDefaults() { diff -r 5c7b6c8a2378 -r 61e297d24425 jdk/src/share/classes/javax/swing/plaf/basic/BasicInternalFrameUI.java --- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicInternalFrameUI.java Wed Jul 02 18:17:56 2008 +0400 +++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicInternalFrameUI.java Mon Jul 07 16:56:23 2008 +0400 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2008 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 @@ -55,7 +55,6 @@ protected MouseInputAdapter borderListener; protected PropertyChangeListener propertyChangeListener; protected LayoutManager internalFrameLayout; - protected ComponentListener componentListener; protected MouseInputListener glassPaneDispatcher; private InternalFrameListener internalFrameListener; @@ -67,9 +66,9 @@ protected BasicInternalFrameTitlePane titlePane; // access needs this private static DesktopManager sharedDesktopManager; - private boolean componentListenerAdded = false; private Rectangle parentBounds; + private DesktopIconMover desktopIconMover; private boolean dragging = false; private boolean resizing = false; @@ -210,14 +209,17 @@ frame.getGlassPane().addMouseListener(glassPaneDispatcher); frame.getGlassPane().addMouseMotionListener(glassPaneDispatcher); } - componentListener = createComponentListener(); if (frame.getParent() != null) { parentBounds = frame.getParent().getBounds(); } - if ((frame.getParent() != null) && !componentListenerAdded) { - frame.getParent().addComponentListener(componentListener); - componentListenerAdded = true; + getDesktopIconMover().installListeners(); + } + + private DesktopIconMover getDesktopIconMover() { + if (desktopIconMover == null) { + desktopIconMover = new DesktopIconMover(frame); } + return desktopIconMover; } // Provide a FocusListener to listen for a WINDOW_LOST_FOCUS event, @@ -288,11 +290,7 @@ * @since 1.3 */ protected void uninstallListeners() { - if ((frame.getParent() != null) && componentListenerAdded) { - frame.getParent().removeComponentListener(componentListener); - componentListenerAdded = false; - } - componentListener = null; + getDesktopIconMover().uninstallListeners(); if (glassPaneDispatcher != null) { frame.getGlassPane().removeMouseListener(glassPaneDispatcher); frame.getGlassPane().removeMouseMotionListener(glassPaneDispatcher); @@ -1230,15 +1228,6 @@ } } - // Relocate the icon base on the new parent bounds. - if (icon != null) { - Rectangle iconBounds = icon.getBounds(); - int y = iconBounds.y + - (parentNewBounds.height - parentBounds.height); - icon.setBounds(iconBounds.x, y, - iconBounds.width, iconBounds.height); - } - // Update the new parent bounds for next resize. if (!parentBounds.equals(parentNewBounds)) { parentBounds = parentNewBounds; @@ -1413,10 +1402,6 @@ // Cancel a resize in progress if the internal frame // gets a setClosed(true) or dispose(). cancelResize(); - if ((frame.getParent() != null) && componentListenerAdded) { - frame.getParent().removeComponentListener( - componentListener); - } closeFrame(f); } } else if (JInternalFrame.IS_MAXIMUM_PROPERTY == prop) { @@ -1449,16 +1434,6 @@ } else { parentBounds = null; } - if ((frame.getParent() != null) && !componentListenerAdded) { - f.getParent().addComponentListener(componentListener); - componentListenerAdded = true; - } else if ((newValue == null) && componentListenerAdded) { - if (f.getParent() != null) { - f.getParent().removeComponentListener( - componentListener); - } - componentListenerAdded = false; - } } else if (JInternalFrame.TITLE_PROPERTY == prop || prop == "closable" || prop == "iconable" || prop == "maximizable") { diff -r 5c7b6c8a2378 -r 61e297d24425 jdk/src/share/classes/javax/swing/plaf/basic/DesktopIconMover.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/javax/swing/plaf/basic/DesktopIconMover.java Mon Jul 07 16:56:23 2008 +0400 @@ -0,0 +1,168 @@ +/* + * Copyright 1997-2008 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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. + */ + +package javax.swing.plaf.basic; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.beans.*; + +/** + * DesktopIconMover is intended to move desktop icon + * when parent window is resized. + */ +class DesktopIconMover implements ComponentListener, PropertyChangeListener { + private Component parent; + private JInternalFrame frame; // if not null, DesktopIconMover(frame) + // constructor was used + private JInternalFrame.JDesktopIcon icon; + private Rectangle parentBounds; + private boolean componentListenerAdded = false; + + public DesktopIconMover(JInternalFrame frame) { + if (frame == null) { + throw new NullPointerException("Frame cannot be null"); + } + this.frame = frame; + this.icon = frame.getDesktopIcon(); + if (icon == null) { + throw new NullPointerException( + "frame.getDesktopIcon() cannot be null"); + } + this.parent = frame.getParent(); + if (this.parent != null) { + parentBounds = this.parent.getBounds(); + } + } + + public DesktopIconMover(JInternalFrame.JDesktopIcon icon) { + if (icon == null) { + throw new NullPointerException("Icon cannot be null"); + } + this.icon = icon; + this.parent = icon.getParent(); + if (this.parent != null) { + parentBounds = this.parent.getBounds(); + } + } + + public void installListeners() { + if (frame != null) { + frame.addPropertyChangeListener(this); + } else { + icon.addPropertyChangeListener(this); + } + addComponentListener(); + } + + public void uninstallListeners() { + if (frame != null) { + frame.removePropertyChangeListener(this); + } else { + icon.removePropertyChangeListener(this); + } + removeComponentListener(); + } + + public void propertyChange(PropertyChangeEvent evt) { + String propName = evt.getPropertyName(); + if ("ancestor".equals(propName)) { + Component newAncestor = (Component) evt.getNewValue(); + + // Remove component listener if parent is changing + Component probablyNewParent = getCurrentParent(); + if ((probablyNewParent != null) && + (!probablyNewParent.equals(parent))) { + removeComponentListener(); + parent = probablyNewParent; + } + + if (newAncestor == null) { + removeComponentListener(); + } else { + addComponentListener(); + } + + // Update parentBounds + if (parent != null) { + parentBounds = parent.getBounds(); + } else { + parentBounds = null; + } + } else if (JInternalFrame.IS_CLOSED_PROPERTY.equals(propName)) { + removeComponentListener(); + } + } + + private void addComponentListener() { + if (!componentListenerAdded && (parent != null)) { + parent.addComponentListener(this); + componentListenerAdded = true; + } + } + + private void removeComponentListener() { + if ((parent != null) && componentListenerAdded) { + parent.removeComponentListener(this); + componentListenerAdded = false; + } + } + + private Component getCurrentParent() { + if (frame != null) { + return frame.getParent(); + } else { + return icon.getParent(); + } + } + + public void componentResized(ComponentEvent e) { + if ((parent == null) || (parentBounds == null)) { + return; + } + + Rectangle parentNewBounds = parent.getBounds(); + if ((parentNewBounds == null) || parentNewBounds.equals(parentBounds)) { + return; + } + + // Move desktop icon only in up-down direction + int newIconY = icon.getLocation().y + + (parentNewBounds.height - parentBounds.height); + icon.setLocation(icon.getLocation().x, newIconY); + + parentBounds = parentNewBounds; + } + + public void componentMoved(ComponentEvent e) { + } + + public void componentShown(ComponentEvent e) { + } + + public void componentHidden(ComponentEvent e) { + } +} diff -r 5c7b6c8a2378 -r 61e297d24425 jdk/test/javax/swing/JInternalFrame/6647340/bug6647340.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JInternalFrame/6647340/bug6647340.java Mon Jul 07 16:56:23 2008 +0400 @@ -0,0 +1,146 @@ +/* + * Copyright 2008 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 6647340 + * @summary Checks that iconified internal frame follows + * the main frame borders properly. + * @author Mikhail Lapshin + */ + +import sun.awt.SunToolkit; + +import javax.swing.*; +import java.awt.*; +import java.beans.PropertyVetoException; + +public class bug6647340 { + private JFrame frame; + private Point location; + private JInternalFrame jif; + + public static void main(String[] args) throws Exception { + final bug6647340 test = new bug6647340(); + try { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + test.setupUI(); + } + }); + test.test(); + } finally { + if (test.frame != null) { + test.frame.dispose(); + } + } + } + + private void setupUI() { + frame = new JFrame(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + JDesktopPane desktop = new JDesktopPane(); + frame.add(desktop); + + jif = new JInternalFrame("Internal Frame", true, true, true, true); + jif.setBounds(20, 20, 200, 100); + desktop.add(jif); + jif.setVisible(true); + + Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); + frame.setBounds((screen.width - 400) / 2, (screen.height - 400) / 2, 400, 400); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private void test() throws Exception { + realSync(); + test1(); + realSync(); + check1(); + realSync(); + test2(); + realSync(); + check2(); + } + + private void test1() throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + setIcon(true); + location = jif.getDesktopIcon().getLocation(); + Dimension size = frame.getSize(); + frame.setSize(size.width + 100, size.height + 100); + } + }); + } + + private void test2() throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + setIcon(false); + } + }); + realSync(); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + Dimension size = frame.getSize(); + frame.setSize(size.width - 100, size.height - 100); + } + }); + realSync(); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + setIcon(true); + } + }); + } + + private void check1() { + if (!jif.getDesktopIcon().getLocation().equals(location)) { + System.out.println("First test passed"); + } else { + throw new RuntimeException("Icon isn't shifted with the frame bounds"); + } + } + + private void check2() { + if (jif.getDesktopIcon().getLocation().equals(location)) { + System.out.println("Second test passed"); + } else { + throw new RuntimeException("Icon isn't located near the frame bottom"); + } + } + + private static void realSync() { + ((SunToolkit) (Toolkit.getDefaultToolkit())).realSync(); + } + + private void setIcon(boolean b) { + try { + jif.setIcon(b); + } catch (PropertyVetoException e) { + e.printStackTrace(); + } + } +}