4632N/A/*
4632N/A * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
4632N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4632N/A *
4632N/A * This code is free software; you can redistribute it and/or modify it
4632N/A * under the terms of the GNU General Public License version 2 only, as
4632N/A * published by the Free Software Foundation. Oracle designates this
4632N/A * particular file as subject to the "Classpath" exception as provided
4632N/A * by Oracle in the LICENSE file that accompanied this code.
4632N/A *
4632N/A * This code is distributed in the hope that it will be useful, but WITHOUT
4632N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
4632N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
4632N/A * version 2 for more details (a copy is included in the LICENSE file that
4632N/A * accompanied this code).
4632N/A *
4632N/A * You should have received a copy of the GNU General Public License version
4632N/A * 2 along with this work; if not, write to the Free Software Foundation,
4632N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
4632N/A *
4632N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
4632N/A * or visit www.oracle.com if you need additional information or have any
4632N/A * questions.
4632N/A */
4632N/A
4632N/Apackage com.apple.laf;
4632N/A
4632N/Aimport java.awt.*;
4632N/Aimport java.beans.PropertyVetoException;
4632N/Aimport java.util.Vector;
4632N/A
4632N/Aimport javax.swing.*;
4632N/A
4632N/A/**
4632N/A * Based on AquaInternalFrameManager
4632N/A *
4632N/A * DesktopManager implementation for Aqua
4632N/A *
4632N/A * Mac is more like Windows than it's like Motif/Basic
4632N/A *
4632N/A * From WindowsDesktopManager:
4632N/A *
4632N/A * This class implements a DesktopManager which more closely follows
4632N/A * the MDI model than the DefaultDesktopManager. Unlike the
4632N/A * DefaultDesktopManager policy, MDI requires that the selected
4632N/A * and activated child frames are the same, and that that frame
4632N/A * always be the top-most window.
4632N/A * <p>
4632N/A * The maximized state is managed by the DesktopManager with MDI,
4632N/A * instead of just being a property of the individual child frame.
4632N/A * This means that if the currently selected window is maximized
4632N/A * and another window is selected, that new window will be maximized.
4632N/A *
4632N/A * @see com.sun.java.swing.plaf.windows.WindowsDesktopManager
4632N/A */
4632N/Apublic class AquaInternalFrameManager extends DefaultDesktopManager {
4632N/A // Variables
4632N/A
4632N/A /* The frame which is currently selected/activated.
4632N/A * We store this value to enforce Mac's single-selection model.
4632N/A */
4632N/A JInternalFrame fCurrentFrame;
4632N/A JInternalFrame fInitialFrame;
4632N/A AquaInternalFramePaneUI fCurrentPaneUI;
4632N/A
4632N/A /* The list of frames, sorted by order of creation.
4632N/A * This list is necessary because by default the order of
4632N/A * child frames in the JDesktopPane changes during frame
4632N/A * activation (the activated frame is moved to index 0).
4632N/A * We preserve the creation order so that "next" and "previous"
4632N/A * frame actions make sense.
4632N/A */
4632N/A Vector<JInternalFrame> fChildFrames = new Vector<JInternalFrame>(1);
4632N/A
4632N/A public void closeFrame(final JInternalFrame f) {
4632N/A if (f == fCurrentFrame) {
4632N/A activateNextFrame();
4632N/A }
4632N/A fChildFrames.removeElement(f);
4632N/A super.closeFrame(f);
4632N/A }
4632N/A
4632N/A public void deiconifyFrame(final JInternalFrame f) {
4632N/A JInternalFrame.JDesktopIcon desktopIcon;
4632N/A
4632N/A desktopIcon = f.getDesktopIcon();
4632N/A // If the icon moved, move the frame to that spot before expanding it
4632N/A // reshape does delta checks for us
4632N/A f.reshape(desktopIcon.getX(), desktopIcon.getY(), f.getWidth(), f.getHeight());
4632N/A super.deiconifyFrame(f);
4632N/A }
4632N/A
4632N/A void addIcon(final Container c, final JInternalFrame.JDesktopIcon desktopIcon) {
4632N/A c.add(desktopIcon);
4632N/A }
4632N/A
4632N/A /** Removes the frame from its parent and adds its desktopIcon to the parent. */
4632N/A public void iconifyFrame(final JInternalFrame f) {
4632N/A // Same as super except doesn't deactivate it
4632N/A JInternalFrame.JDesktopIcon desktopIcon;
4632N/A Container c;
4632N/A
4632N/A desktopIcon = f.getDesktopIcon();
4632N/A // Position depends on *current* position of frame, unlike super which reuses the first position
4632N/A final Rectangle r = getBoundsForIconOf(f);
4632N/A desktopIcon.setBounds(r.x, r.y, r.width, r.height);
4632N/A
4632N/A c = f.getParent();
4632N/A if (c == null) return;
4632N/A
4632N/A c.remove(f);
4632N/A addIcon(c, desktopIcon);
4632N/A c.repaint(f.getX(), f.getY(), f.getWidth(), f.getHeight());
4632N/A }
4632N/A
4632N/A // WindowsDesktopManager code
4632N/A public void activateFrame(final JInternalFrame f) {
4632N/A try {
4632N/A if (f != null) super.activateFrame(f);
4632N/A
4632N/A // If this is the first activation, add to child list.
4632N/A if (fChildFrames.indexOf(f) == -1) {
4632N/A fChildFrames.addElement(f);
4632N/A }
4632N/A
4632N/A if (fCurrentFrame != null && f != fCurrentFrame) {
4632N/A if (fCurrentFrame.isSelected()) {
4632N/A fCurrentFrame.setSelected(false);
4632N/A }
4632N/A }
4632N/A
4632N/A if (f != null && !f.isSelected()) {
4632N/A f.setSelected(true);
4632N/A }
4632N/A
4632N/A fCurrentFrame = f;
4632N/A } catch(final PropertyVetoException e) {}
4632N/A }
4632N/A
4632N/A private void switchFrame(final boolean next) {
4632N/A if (fCurrentFrame == null) {
4632N/A // initialize first frame we find
4632N/A if (fInitialFrame != null) activateFrame(fInitialFrame);
4632N/A return;
4632N/A }
4632N/A
4632N/A final int count = fChildFrames.size();
4632N/A if (count <= 1) {
4632N/A // No other child frames.
4632N/A return;
4632N/A }
4632N/A
4632N/A final int currentIndex = fChildFrames.indexOf(fCurrentFrame);
4632N/A if (currentIndex == -1) {
4632N/A // the "current frame" is no longer in the list
4632N/A fCurrentFrame = null;
4632N/A return;
4632N/A }
4632N/A
4632N/A int nextIndex;
4632N/A if (next) {
4632N/A nextIndex = currentIndex + 1;
4632N/A if (nextIndex == count) {
4632N/A nextIndex = 0;
4632N/A }
4632N/A } else {
4632N/A nextIndex = currentIndex - 1;
4632N/A if (nextIndex == -1) {
4632N/A nextIndex = count - 1;
4632N/A }
4632N/A }
4632N/A final JInternalFrame f = fChildFrames.elementAt(nextIndex);
4632N/A activateFrame(f);
4632N/A fCurrentFrame = f;
4632N/A }
4632N/A
4632N/A /**
4632N/A * Activate the next child JInternalFrame, as determined by
4632N/A * the frames' Z-order. If there is only one child frame, it
4632N/A * remains activated. If there are no child frames, nothing
4632N/A * happens.
4632N/A */
4632N/A public void activateNextFrame() {
4632N/A switchFrame(true);
4632N/A }
4632N/A
4632N/A /** same as above but will activate a frame if none
4632N/A * have been selected
4632N/A */
4632N/A public void activateNextFrame(final JInternalFrame f) {
4632N/A fInitialFrame = f;
4632N/A switchFrame(true);
4632N/A }
4632N/A
4632N/A /**
4632N/A * Activate the previous child JInternalFrame, as determined by
4632N/A * the frames' Z-order. If there is only one child frame, it
4632N/A * remains activated. If there are no child frames, nothing
4632N/A * happens.
4632N/A */
4632N/A public void activatePreviousFrame() {
4632N/A switchFrame(false);
4632N/A }
4632N/A}