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.beans.PropertyVetoException;
30 import java.util.Vector;
32 import javax.swing.DefaultDesktopManager;
33 import javax.swing.DesktopManager;
34 import javax.swing.JInternalFrame;
37 * Based on AquaInternalFrameManager
39 * DesktopManager implementation for Aqua
41 * Mac is more like Windows than it's like Motif/Basic
43 * From WindowsDesktopManager:
45 * This class implements a DesktopManager which more closely follows the MDI
46 * model than the DefaultDesktopManager. Unlike the DefaultDesktopManager
47 * policy, MDI requires that the selected and activated child frames are the
48 * same, and that that frame always be the top-most window.
50 * The maximized state is managed by the DesktopManager with MDI, instead of
51 * just being a property of the individual child frame. This means that if the
52 * currently selected window is maximized and another window is selected, that
53 * new window will be maximized.
56 * https://raw.githubusercontent.com/frohoff/jdk8u-jdk/master/src/macosx/classes/com/apple/laf/AquaInternalFrameManager.java
58 * Patch from Jim Procter - when the most recently opened frame is closed,
59 * correct behaviour is to go to the next most recent frame, rather than wrap
60 * around to the bottom of the window stack (as the original implementation
63 * see com.sun.java.swing.plaf.windows.WindowsDesktopManager
65 public class AquaInternalFrameManager extends DefaultDesktopManager
69 /* The frame which is currently selected/activated.
70 * We store this value to enforce Mac's single-selection model.
72 JInternalFrame fCurrentFrame;
74 JInternalFrame fInitialFrame;
76 /* The list of frames, sorted by order of creation.
77 * This list is necessary because by default the order of
78 * child frames in the JDesktopPane changes during frame
79 * activation (the activated frame is moved to index 0).
80 * We preserve the creation order so that "next" and "previous"
81 * frame actions make sense.
83 Vector<JInternalFrame> fChildFrames = new Vector<>(1);
86 * keep a reference to the original LAF manager so we can iconise/de-iconise
89 private DesktopManager ourManager;
91 public AquaInternalFrameManager(DesktopManager desktopManager)
93 ourManager = desktopManager;
97 public void closeFrame(final JInternalFrame f)
99 if (f == fCurrentFrame)
101 boolean mostRecentFrame = fChildFrames
102 .indexOf(f) == fChildFrames.size() - 1;
103 if (!mostRecentFrame)
109 activatePreviousFrame();
112 fChildFrames.removeElement(f);
117 public void deiconifyFrame(final JInternalFrame f)
119 JInternalFrame.JDesktopIcon desktopIcon;
121 desktopIcon = f.getDesktopIcon();
122 // If the icon moved, move the frame to that spot before expanding it
123 // reshape does delta checks for us
124 f.reshape(desktopIcon.getX(), desktopIcon.getY(), f.getWidth(),
126 ourManager.deiconifyFrame(f);
129 void addIcon(final Container c,
130 final JInternalFrame.JDesktopIcon desktopIcon)
136 * Removes the frame from its parent and adds its desktopIcon to the parent.
139 public void iconifyFrame(final JInternalFrame f)
141 ourManager.iconifyFrame(f);
144 // WindowsDesktopManager code
146 public void activateFrame(final JInternalFrame f)
152 super.activateFrame(f);
155 // add or relocate to top of stack
156 if (fChildFrames.indexOf(f) != -1)
158 fChildFrames.remove(f);
160 fChildFrames.addElement(f);
162 if (fCurrentFrame != null && f != fCurrentFrame)
164 if (fCurrentFrame.isSelected())
166 fCurrentFrame.setSelected(false);
170 if (f != null && !f.isSelected())
176 } catch (final PropertyVetoException e)
181 private void switchFrame(final boolean next)
183 if (fCurrentFrame == null)
185 // initialize first frame we find
186 if (fInitialFrame != null)
188 activateFrame(fInitialFrame);
193 final int count = fChildFrames.size();
196 // No other child frames.
200 final int currentIndex = fChildFrames.indexOf(fCurrentFrame);
201 if (currentIndex == -1)
203 // the "current frame" is no longer in the list
204 fCurrentFrame = null;
211 nextIndex = currentIndex + 1;
212 if (nextIndex == count)
219 nextIndex = currentIndex - 1;
222 nextIndex = count - 1;
225 final JInternalFrame f = fChildFrames.elementAt(nextIndex);
231 * Activate the next child JInternalFrame, as determined by the frames'
232 * Z-order. If there is only one child frame, it remains activated. If there
233 * are no child frames, nothing happens.
235 public void activateNextFrame()
241 * same as above but will activate a frame if none have been selected
243 public void activateNextFrame(final JInternalFrame f)
250 * Activate the previous child JInternalFrame, as determined by the frames'
251 * Z-order. If there is only one child frame, it remains activated. If there
252 * are no child frames, nothing happens.
254 public void activatePreviousFrame()