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
64 public class AquaInternalFrameManager extends DefaultDesktopManager
68 /* The frame which is currently selected/activated.
69 * We store this value to enforce Mac's single-selection model.
71 JInternalFrame fCurrentFrame;
73 JInternalFrame fInitialFrame;
75 /* The list of frames, sorted by order of creation.
76 * This list is necessary because by default the order of
77 * child frames in the JDesktopPane changes during frame
78 * activation (the activated frame is moved to index 0).
79 * We preserve the creation order so that "next" and "previous"
80 * frame actions make sense.
82 Vector<JInternalFrame> fChildFrames = new Vector<>(1);
85 * keep a reference to the original LAF manager so we can iconise/de-iconise
88 private DesktopManager ourManager;
90 public AquaInternalFrameManager(DesktopManager desktopManager)
92 ourManager = desktopManager;
96 public void closeFrame(final JInternalFrame f)
98 if (f == fCurrentFrame)
100 boolean mostRecentFrame = fChildFrames
101 .indexOf(f) == fChildFrames.size() - 1;
102 if (!mostRecentFrame)
108 activatePreviousFrame();
111 fChildFrames.removeElement(f);
116 public void deiconifyFrame(final JInternalFrame f)
118 JInternalFrame.JDesktopIcon desktopIcon;
120 desktopIcon = f.getDesktopIcon();
121 // If the icon moved, move the frame to that spot before expanding it
122 // reshape does delta checks for us
123 f.reshape(desktopIcon.getX(), desktopIcon.getY(), f.getWidth(),
125 ourManager.deiconifyFrame(f);
128 void addIcon(final Container c,
129 final JInternalFrame.JDesktopIcon desktopIcon)
135 * Removes the frame from its parent and adds its desktopIcon to the parent.
138 public void iconifyFrame(final JInternalFrame f)
140 ourManager.iconifyFrame(f);
143 // WindowsDesktopManager code
145 public void activateFrame(final JInternalFrame f)
151 super.activateFrame(f);
154 // If this is the first activation, add to child list.
155 if (fChildFrames.indexOf(f) == -1)
157 fChildFrames.addElement(f);
160 if (fCurrentFrame != null && f != fCurrentFrame)
162 if (fCurrentFrame.isSelected())
164 fCurrentFrame.setSelected(false);
168 if (f != null && !f.isSelected())
174 } catch (final PropertyVetoException e)
179 private void switchFrame(final boolean next)
181 if (fCurrentFrame == null)
183 // initialize first frame we find
184 if (fInitialFrame != null)
186 activateFrame(fInitialFrame);
191 final int count = fChildFrames.size();
194 // No other child frames.
198 final int currentIndex = fChildFrames.indexOf(fCurrentFrame);
199 if (currentIndex == -1)
201 // the "current frame" is no longer in the list
202 fCurrentFrame = null;
209 nextIndex = currentIndex + 1;
210 if (nextIndex == count)
217 nextIndex = currentIndex - 1;
220 nextIndex = count - 1;
223 final JInternalFrame f = fChildFrames.elementAt(nextIndex);
229 * Activate the next child JInternalFrame, as determined by the frames'
230 * Z-order. If there is only one child frame, it remains activated. If there
231 * are no child frames, nothing happens.
233 public void activateNextFrame()
239 * same as above but will activate a frame if none have been selected
241 public void activateNextFrame(final JInternalFrame f)
248 * Activate the previous child JInternalFrame, as determined by the frames'
249 * Z-order. If there is only one child frame, it remains activated. If there
250 * are no child frames, nothing happens.
252 public void activatePreviousFrame()