blob: 4b38e865fa86c0b452542c18c3cbab33fbf4bfff [file] [log] [blame]
/*
* Copyright (c) 1997, 2006, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.swing.plaf.basic;
import javax.swing.*;
import javax.swing.plaf.*;
import java.beans.*;
import java.awt.event.*;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Graphics;
import java.awt.KeyboardFocusManager;
import java.awt.*;
import java.util.Vector;
import sun.swing.DefaultLookup;
import sun.swing.UIAction;
import sun.awt.AppContext;
/**
* Basic L&F for a desktop.
*
* @author Steve Wilson
*/
public class BasicDesktopPaneUI extends DesktopPaneUI {
// Old actions forward to an instance of this.
private static final Actions SHARED_ACTION = new Actions();
private static Dimension minSize = new Dimension(0,0);
private static Dimension maxSize = new Dimension(Integer.MAX_VALUE,
Integer.MAX_VALUE);
private Handler handler;
private PropertyChangeListener pcl;
protected JDesktopPane desktop;
protected DesktopManager desktopManager;
/**
* As of Java 2 platform v1.3 this previously undocumented field is no
* longer used.
* Key bindings are now defined by the LookAndFeel, please refer to
* the key bindings specification for further details.
*
* @deprecated As of 1.3.
*/
@Deprecated
protected KeyStroke minimizeKey;
/**
* As of Java 2 platform v1.3 this previously undocumented field is no
* longer used.
* Key bindings are now defined by the LookAndFeel, please refer to
* the key bindings specification for further details.
*
* @deprecated As of 1.3.
*/
@Deprecated
protected KeyStroke maximizeKey;
/**
* As of Java 2 platform v1.3 this previously undocumented field is no
* longer used.
* Key bindings are now defined by the LookAndFeel, please refer to
* the key bindings specification for further details.
*
* @deprecated As of 1.3.
*/
@Deprecated
protected KeyStroke closeKey;
/**
* As of Java 2 platform v1.3 this previously undocumented field is no
* longer used.
* Key bindings are now defined by the LookAndFeel, please refer to
* the key bindings specification for further details.
*
* @deprecated As of 1.3.
*/
@Deprecated
protected KeyStroke navigateKey;
/**
* As of Java 2 platform v1.3 this previously undocumented field is no
* longer used.
* Key bindings are now defined by the LookAndFeel, please refer to
* the key bindings specification for further details.
*
* @deprecated As of 1.3.
*/
@Deprecated
protected KeyStroke navigateKey2;
public static ComponentUI createUI(JComponent c) {
return new BasicDesktopPaneUI();
}
public BasicDesktopPaneUI() {
}
public void installUI(JComponent c) {
desktop = (JDesktopPane)c;
installDefaults();
installDesktopManager();
installListeners();
installKeyboardActions();
}
public void uninstallUI(JComponent c) {
uninstallKeyboardActions();
uninstallListeners();
uninstallDesktopManager();
uninstallDefaults();
desktop = null;
handler = null;
}
protected void installDefaults() {
if (desktop.getBackground() == null ||
desktop.getBackground() instanceof UIResource) {
desktop.setBackground(UIManager.getColor("Desktop.background"));
}
LookAndFeel.installProperty(desktop, "opaque", Boolean.TRUE);
}
protected void uninstallDefaults() { }
/**
* Installs the <code>PropertyChangeListener</code> returned from
* <code>createPropertyChangeListener</code> on the
* <code>JDesktopPane</code>.
*
* @since 1.5
* @see #createPropertyChangeListener
*/
protected void installListeners() {
pcl = createPropertyChangeListener();
desktop.addPropertyChangeListener(pcl);
}
/**
* Uninstalls the <code>PropertyChangeListener</code> returned from
* <code>createPropertyChangeListener</code> from the
* <code>JDesktopPane</code>.
*
* @since 1.5
* @see #createPropertyChangeListener
*/
protected void uninstallListeners() {
desktop.removePropertyChangeListener(pcl);
pcl = null;
}
protected void installDesktopManager() {
desktopManager = desktop.getDesktopManager();
if(desktopManager == null) {
desktopManager = new BasicDesktopManager();
desktop.setDesktopManager(desktopManager);
}
}
protected void uninstallDesktopManager() {
if(desktop.getDesktopManager() instanceof UIResource) {
desktop.setDesktopManager(null);
}
desktopManager = null;
}
protected void installKeyboardActions(){
InputMap inputMap = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
if (inputMap != null) {
SwingUtilities.replaceUIInputMap(desktop,
JComponent.WHEN_IN_FOCUSED_WINDOW, inputMap);
}
inputMap = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
if (inputMap != null) {
SwingUtilities.replaceUIInputMap(desktop,
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
inputMap);
}
LazyActionMap.installLazyActionMap(desktop, BasicDesktopPaneUI.class,
"DesktopPane.actionMap");
registerKeyboardActions();
}
protected void registerKeyboardActions(){
}
protected void unregisterKeyboardActions(){
}
InputMap getInputMap(int condition) {
if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) {
return createInputMap(condition);
}
else if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) {
return (InputMap)DefaultLookup.get(desktop, this,
"Desktop.ancestorInputMap");
}
return null;
}
InputMap createInputMap(int condition) {
if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) {
Object[] bindings = (Object[])DefaultLookup.get(desktop,
this, "Desktop.windowBindings");
if (bindings != null) {
return LookAndFeel.makeComponentInputMap(desktop, bindings);
}
}
return null;
}
static void loadActionMap(LazyActionMap map) {
map.put(new Actions(Actions.RESTORE));
map.put(new Actions(Actions.CLOSE));
map.put(new Actions(Actions.MOVE));
map.put(new Actions(Actions.RESIZE));
map.put(new Actions(Actions.LEFT));
map.put(new Actions(Actions.SHRINK_LEFT));
map.put(new Actions(Actions.RIGHT));
map.put(new Actions(Actions.SHRINK_RIGHT));
map.put(new Actions(Actions.UP));
map.put(new Actions(Actions.SHRINK_UP));
map.put(new Actions(Actions.DOWN));
map.put(new Actions(Actions.SHRINK_DOWN));
map.put(new Actions(Actions.ESCAPE));
map.put(new Actions(Actions.MINIMIZE));
map.put(new Actions(Actions.MAXIMIZE));
map.put(new Actions(Actions.NEXT_FRAME));
map.put(new Actions(Actions.PREVIOUS_FRAME));
map.put(new Actions(Actions.NAVIGATE_NEXT));
map.put(new Actions(Actions.NAVIGATE_PREVIOUS));
}
protected void uninstallKeyboardActions(){
unregisterKeyboardActions();
SwingUtilities.replaceUIInputMap(desktop, JComponent.
WHEN_IN_FOCUSED_WINDOW, null);
SwingUtilities.replaceUIInputMap(desktop, JComponent.
WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, null);
SwingUtilities.replaceUIActionMap(desktop, null);
}
public void paint(Graphics g, JComponent c) {}
public Dimension getPreferredSize(JComponent c) {return null;}
public Dimension getMinimumSize(JComponent c) {
return minSize;
}
public Dimension getMaximumSize(JComponent c){
return maxSize;
}
/**
* Returns the <code>PropertyChangeListener</code> to install on
* the <code>JDesktopPane</code>.
*
* @since 1.5
* @return The PropertyChangeListener that will be added to track
* changes in the desktop pane.
*/
protected PropertyChangeListener createPropertyChangeListener() {
return getHandler();
}
private Handler getHandler() {
if (handler == null) {
handler = new Handler();
}
return handler;
}
private class Handler implements PropertyChangeListener {
public void propertyChange(PropertyChangeEvent evt) {
String propertyName = evt.getPropertyName();
if ("desktopManager" == propertyName) {
installDesktopManager();
}
}
}
/**
* The default DesktopManager installed by the UI.
*/
private class BasicDesktopManager extends DefaultDesktopManager
implements UIResource {
}
private static class Actions extends UIAction {
private static String CLOSE = "close";
private static String ESCAPE = "escape";
private static String MAXIMIZE = "maximize";
private static String MINIMIZE = "minimize";
private static String MOVE = "move";
private static String RESIZE = "resize";
private static String RESTORE = "restore";
private static String LEFT = "left";
private static String RIGHT = "right";
private static String UP = "up";
private static String DOWN = "down";
private static String SHRINK_LEFT = "shrinkLeft";
private static String SHRINK_RIGHT = "shrinkRight";
private static String SHRINK_UP = "shrinkUp";
private static String SHRINK_DOWN = "shrinkDown";
private static String NEXT_FRAME = "selectNextFrame";
private static String PREVIOUS_FRAME = "selectPreviousFrame";
private static String NAVIGATE_NEXT = "navigateNext";
private static String NAVIGATE_PREVIOUS = "navigatePrevious";
private final int MOVE_RESIZE_INCREMENT = 10;
private static boolean moving = false;
private static boolean resizing = false;
private static JInternalFrame sourceFrame = null;
private static Component focusOwner = null;
Actions() {
super(null);
}
Actions(String name) {
super(name);
}
public void actionPerformed(ActionEvent e) {
JDesktopPane dp = (JDesktopPane)e.getSource();
String key = getName();
if (CLOSE == key || MAXIMIZE == key || MINIMIZE == key ||
RESTORE == key) {
setState(dp, key);
}
else if (ESCAPE == key) {
if (sourceFrame == dp.getSelectedFrame() &&
focusOwner != null) {
focusOwner.requestFocus();
}
moving = false;
resizing = false;
sourceFrame = null;
focusOwner = null;
}
else if (MOVE == key || RESIZE == key) {
sourceFrame = dp.getSelectedFrame();
if (sourceFrame == null) {
return;
}
moving = (key == MOVE) ? true : false;
resizing = (key == RESIZE) ? true : false;
focusOwner = KeyboardFocusManager.
getCurrentKeyboardFocusManager().getFocusOwner();
if (!SwingUtilities.isDescendingFrom(focusOwner, sourceFrame)) {
focusOwner = null;
}
sourceFrame.requestFocus();
}
else if (LEFT == key ||
RIGHT == key ||
UP == key ||
DOWN == key ||
SHRINK_RIGHT == key ||
SHRINK_LEFT == key ||
SHRINK_UP == key ||
SHRINK_DOWN == key) {
JInternalFrame c = dp.getSelectedFrame();
if (sourceFrame == null || c != sourceFrame ||
KeyboardFocusManager.
getCurrentKeyboardFocusManager().getFocusOwner() !=
sourceFrame) {
return;
}
Insets minOnScreenInsets =
UIManager.getInsets("Desktop.minOnScreenInsets");
Dimension size = c.getSize();
Dimension minSize = c.getMinimumSize();
int dpWidth = dp.getWidth();
int dpHeight = dp.getHeight();
int delta;
Point loc = c.getLocation();
if (LEFT == key) {
if (moving) {
c.setLocation(
loc.x + size.width - MOVE_RESIZE_INCREMENT <
minOnScreenInsets.right ?
-size.width + minOnScreenInsets.right :
loc.x - MOVE_RESIZE_INCREMENT,
loc.y);
} else if (resizing) {
c.setLocation(loc.x - MOVE_RESIZE_INCREMENT, loc.y);
c.setSize(size.width + MOVE_RESIZE_INCREMENT,
size.height);
}
} else if (RIGHT == key) {
if (moving) {
c.setLocation(
loc.x + MOVE_RESIZE_INCREMENT >
dpWidth - minOnScreenInsets.left ?
dpWidth - minOnScreenInsets.left :
loc.x + MOVE_RESIZE_INCREMENT,
loc.y);
} else if (resizing) {
c.setSize(size.width + MOVE_RESIZE_INCREMENT,
size.height);
}
} else if (UP == key) {
if (moving) {
c.setLocation(loc.x,
loc.y + size.height - MOVE_RESIZE_INCREMENT <
minOnScreenInsets.bottom ?
-size.height +
minOnScreenInsets.bottom :
loc.y - MOVE_RESIZE_INCREMENT);
} else if (resizing) {
c.setLocation(loc.x, loc.y - MOVE_RESIZE_INCREMENT);
c.setSize(size.width,
size.height + MOVE_RESIZE_INCREMENT);
}
} else if (DOWN == key) {
if (moving) {
c.setLocation(loc.x,
loc.y + MOVE_RESIZE_INCREMENT >
dpHeight - minOnScreenInsets.top ?
dpHeight - minOnScreenInsets.top :
loc.y + MOVE_RESIZE_INCREMENT);
} else if (resizing) {
c.setSize(size.width,
size.height + MOVE_RESIZE_INCREMENT);
}
} else if (SHRINK_LEFT == key && resizing) {
// Make sure we don't resize less than minimum size.
if (minSize.width < (size.width - MOVE_RESIZE_INCREMENT)) {
delta = MOVE_RESIZE_INCREMENT;
} else {
delta = size.width - minSize.width;
}
// Ensure that we keep the internal frame on the desktop.
if (loc.x + size.width - delta < minOnScreenInsets.left) {
delta = loc.x + size.width - minOnScreenInsets.left;
}
c.setSize(size.width - delta, size.height);
} else if (SHRINK_RIGHT == key && resizing) {
// Make sure we don't resize less than minimum size.
if (minSize.width < (size.width - MOVE_RESIZE_INCREMENT)) {
delta = MOVE_RESIZE_INCREMENT;
} else {
delta = size.width - minSize.width;
}
// Ensure that we keep the internal frame on the desktop.
if (loc.x + delta > dpWidth - minOnScreenInsets.right) {
delta = (dpWidth - minOnScreenInsets.right) - loc.x;
}
c.setLocation(loc.x + delta, loc.y);
c.setSize(size.width - delta, size.height);
} else if (SHRINK_UP == key && resizing) {
// Make sure we don't resize less than minimum size.
if (minSize.height <
(size.height - MOVE_RESIZE_INCREMENT)) {
delta = MOVE_RESIZE_INCREMENT;
} else {
delta = size.height - minSize.height;
}
// Ensure that we keep the internal frame on the desktop.
if (loc.y + size.height - delta <
minOnScreenInsets.bottom) {
delta = loc.y + size.height - minOnScreenInsets.bottom;
}
c.setSize(size.width, size.height - delta);
} else if (SHRINK_DOWN == key && resizing) {
// Make sure we don't resize less than minimum size.
if (minSize.height <
(size.height - MOVE_RESIZE_INCREMENT)) {
delta = MOVE_RESIZE_INCREMENT;
} else {
delta = size.height - minSize.height;
}
// Ensure that we keep the internal frame on the desktop.
if (loc.y + delta > dpHeight - minOnScreenInsets.top) {
delta = (dpHeight - minOnScreenInsets.top) - loc.y;
}
c.setLocation(loc.x, loc.y + delta);
c.setSize(size.width, size.height - delta);
}
}
else if (NEXT_FRAME == key || PREVIOUS_FRAME == key) {
dp.selectFrame((key == NEXT_FRAME) ? true : false);
}
else if (NAVIGATE_NEXT == key ||
NAVIGATE_PREVIOUS == key) {
boolean moveForward = true;
if (NAVIGATE_PREVIOUS == key) {
moveForward = false;
}
Container cycleRoot = dp.getFocusCycleRootAncestor();
if (cycleRoot != null) {
FocusTraversalPolicy policy =
cycleRoot.getFocusTraversalPolicy();
if (policy != null && policy instanceof
SortingFocusTraversalPolicy) {
SortingFocusTraversalPolicy sPolicy =
(SortingFocusTraversalPolicy)policy;
boolean idc = sPolicy.getImplicitDownCycleTraversal();
try {
sPolicy.setImplicitDownCycleTraversal(false);
if (moveForward) {
KeyboardFocusManager.
getCurrentKeyboardFocusManager().
focusNextComponent(dp);
} else {
KeyboardFocusManager.
getCurrentKeyboardFocusManager().
focusPreviousComponent(dp);
}
} finally {
sPolicy.setImplicitDownCycleTraversal(idc);
}
}
}
}
}
private void setState(JDesktopPane dp, String state) {
if (state == CLOSE) {
JInternalFrame f = dp.getSelectedFrame();
if (f == null) {
return;
}
f.doDefaultCloseAction();
} else if (state == MAXIMIZE) {
// maximize the selected frame
JInternalFrame f = dp.getSelectedFrame();
if (f == null) {
return;
}
if (!f.isMaximum()) {
if (f.isIcon()) {
try {
f.setIcon(false);
f.setMaximum(true);
} catch (PropertyVetoException pve) {}
} else {
try {
f.setMaximum(true);
} catch (PropertyVetoException pve) {
}
}
}
} else if (state == MINIMIZE) {
// minimize the selected frame
JInternalFrame f = dp.getSelectedFrame();
if (f == null) {
return;
}
if (!f.isIcon()) {
try {
f.setIcon(true);
} catch (PropertyVetoException pve) {
}
}
} else if (state == RESTORE) {
// restore the selected minimized or maximized frame
JInternalFrame f = dp.getSelectedFrame();
if (f == null) {
return;
}
try {
if (f.isIcon()) {
f.setIcon(false);
} else if (f.isMaximum()) {
f.setMaximum(false);
}
f.setSelected(true);
} catch (PropertyVetoException pve) {
}
}
}
public boolean isEnabled(Object sender) {
if (sender instanceof JDesktopPane) {
JDesktopPane dp = (JDesktopPane)sender;
String action = getName();
if (action == Actions.NEXT_FRAME ||
action == Actions.PREVIOUS_FRAME) {
return true;
}
JInternalFrame iFrame = dp.getSelectedFrame();
if (iFrame == null) {
return false;
} else if (action == Actions.CLOSE) {
return iFrame.isClosable();
} else if (action == Actions.MINIMIZE) {
return iFrame.isIconifiable();
} else if (action == Actions.MAXIMIZE) {
return iFrame.isMaximizable();
}
return true;
}
return false;
}
}
/**
* Handles restoring a minimized or maximized internal frame.
* @since 1.3
*/
protected class OpenAction extends AbstractAction {
public void actionPerformed(ActionEvent evt) {
JDesktopPane dp = (JDesktopPane)evt.getSource();
SHARED_ACTION.setState(dp, Actions.RESTORE);
}
public boolean isEnabled() {
return true;
}
}
/**
* Handles closing an internal frame.
*/
protected class CloseAction extends AbstractAction {
public void actionPerformed(ActionEvent evt) {
JDesktopPane dp = (JDesktopPane)evt.getSource();
SHARED_ACTION.setState(dp, Actions.CLOSE);
}
public boolean isEnabled() {
JInternalFrame iFrame = desktop.getSelectedFrame();
if (iFrame != null) {
return iFrame.isClosable();
}
return false;
}
}
/**
* Handles minimizing an internal frame.
*/
protected class MinimizeAction extends AbstractAction {
public void actionPerformed(ActionEvent evt) {
JDesktopPane dp = (JDesktopPane)evt.getSource();
SHARED_ACTION.setState(dp, Actions.MINIMIZE);
}
public boolean isEnabled() {
JInternalFrame iFrame = desktop.getSelectedFrame();
if (iFrame != null) {
return iFrame.isIconifiable();
}
return false;
}
}
/**
* Handles maximizing an internal frame.
*/
protected class MaximizeAction extends AbstractAction {
public void actionPerformed(ActionEvent evt) {
JDesktopPane dp = (JDesktopPane)evt.getSource();
SHARED_ACTION.setState(dp, Actions.MAXIMIZE);
}
public boolean isEnabled() {
JInternalFrame iFrame = desktop.getSelectedFrame();
if (iFrame != null) {
return iFrame.isMaximizable();
}
return false;
}
}
/**
* Handles navigating to the next internal frame.
*/
protected class NavigateAction extends AbstractAction {
public void actionPerformed(ActionEvent evt) {
JDesktopPane dp = (JDesktopPane)evt.getSource();
dp.selectFrame(true);
}
public boolean isEnabled() {
return true;
}
}
}