2 * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
28 import java.awt.Container;
29 import java.awt.Rectangle;
30 import java.beans.PropertyVetoException;
31 import java.util.Vector;
33 import javax.swing.DefaultDesktopManager;
34 import javax.swing.JInternalFrame;
36 import com.apple.laf.AquaInternalFramePaneUI;
39 * Based on AquaInternalFrameManager
41 * DesktopManager implementation for Aqua
43 * Mac is more like Windows than it's like Motif/Basic
45 * From WindowsDesktopManager:
47 * This class implements a DesktopManager which more closely follows the MDI
48 * model than the DefaultDesktopManager. Unlike the DefaultDesktopManager
49 * policy, MDI requires that the selected and activated child frames are the
50 * same, and that that frame always be the top-most window.
52 * The maximized state is managed by the DesktopManager with MDI, instead of
53 * just being a property of the individual child frame. This means that if the
54 * currently selected window is maximized and another window is selected, that
55 * new window will be maximized.
58 * https://raw.githubusercontent.com/frohoff/jdk8u-jdk/master/src/macosx/classes/com/apple/laf/AquaInternalFrameManager.java
60 * Patch from Jim Procter - when the most recently opened frame is closed,
61 * correct behaviour is to go to the next most recent frame, rather than wrap
62 * around to the bottom of the window stack (as the original implementation
65 * @see com.sun.java.swing.plaf.windows.WindowsDesktopManager
67 public class AquaInternalFrameManager extends DefaultDesktopManager
71 /* The frame which is currently selected/activated.
72 * We store this value to enforce Mac's single-selection model.
74 JInternalFrame fCurrentFrame;
76 JInternalFrame fInitialFrame;
78 AquaInternalFramePaneUI fCurrentPaneUI;
80 /* The list of frames, sorted by order of creation.
81 * This list is necessary because by default the order of
82 * child frames in the JDesktopPane changes during frame
83 * activation (the activated frame is moved to index 0).
84 * We preserve the creation order so that "next" and "previous"
85 * frame actions make sense.
87 Vector<JInternalFrame> fChildFrames = new Vector<>(1);
90 public void closeFrame(final JInternalFrame f)
92 if (f == fCurrentFrame)
94 boolean mostRecentFrame = fChildFrames
95 .indexOf(f) == fChildFrames.size() - 1;
102 activatePreviousFrame();
105 fChildFrames.removeElement(f);
110 public void deiconifyFrame(final JInternalFrame f)
112 JInternalFrame.JDesktopIcon desktopIcon;
114 desktopIcon = f.getDesktopIcon();
115 // If the icon moved, move the frame to that spot before expanding it
116 // reshape does delta checks for us
117 f.reshape(desktopIcon.getX(), desktopIcon.getY(), f.getWidth(),
119 super.deiconifyFrame(f);
122 void addIcon(final Container c,
123 final JInternalFrame.JDesktopIcon desktopIcon)
129 * Removes the frame from its parent and adds its desktopIcon to the parent.
132 public void iconifyFrame(final JInternalFrame f)
134 // Same as super except doesn't deactivate it
135 JInternalFrame.JDesktopIcon desktopIcon;
138 desktopIcon = f.getDesktopIcon();
139 // Position depends on *current* position of frame, unlike super which
140 // reuses the first position
141 final Rectangle r = getBoundsForIconOf(f);
142 desktopIcon.setBounds(r.x, r.y, r.width, r.height);
151 addIcon(c, desktopIcon);
152 c.repaint(f.getX(), f.getY(), f.getWidth(), f.getHeight());
155 // WindowsDesktopManager code
157 public void activateFrame(final JInternalFrame f)
163 super.activateFrame(f);
166 // If this is the first activation, add to child list.
167 if (fChildFrames.indexOf(f) == -1)
169 fChildFrames.addElement(f);
172 if (fCurrentFrame != null && f != fCurrentFrame)
174 if (fCurrentFrame.isSelected())
176 fCurrentFrame.setSelected(false);
180 if (f != null && !f.isSelected())
186 } catch (final PropertyVetoException e)
191 private void switchFrame(final boolean next)
193 if (fCurrentFrame == null)
195 // initialize first frame we find
196 if (fInitialFrame != null)
198 activateFrame(fInitialFrame);
203 final int count = fChildFrames.size();
206 // No other child frames.
210 final int currentIndex = fChildFrames.indexOf(fCurrentFrame);
211 if (currentIndex == -1)
213 // the "current frame" is no longer in the list
214 fCurrentFrame = null;
221 nextIndex = currentIndex + 1;
222 if (nextIndex == count)
229 nextIndex = currentIndex - 1;
232 nextIndex = count - 1;
235 final JInternalFrame f = fChildFrames.elementAt(nextIndex);
241 * Activate the next child JInternalFrame, as determined by the frames'
242 * Z-order. If there is only one child frame, it remains activated. If there
243 * are no child frames, nothing happens.
245 public void activateNextFrame()
251 * same as above but will activate a frame if none have been selected
253 public void activateNextFrame(final JInternalFrame f)
260 * Activate the previous child JInternalFrame, as determined by the frames'
261 * Z-order. If there is only one child frame, it remains activated. If there
262 * are no child frames, nothing happens.
264 public void activatePreviousFrame()