diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java | |
download | cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2 cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java')
-rw-r--r-- | libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java | 1786 |
1 files changed, 1786 insertions, 0 deletions
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java new file mode 100644 index 000000000..da37e2bd8 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java @@ -0,0 +1,1786 @@ +/* BasicInternalFrameUI.java -- + Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.LayoutManager2; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyVetoException; + +import javax.swing.AbstractAction; +import javax.swing.ActionMap; +import javax.swing.DefaultDesktopManager; +import javax.swing.DesktopManager; +import javax.swing.JComponent; +import javax.swing.JDesktopPane; +import javax.swing.JInternalFrame; +import javax.swing.KeyStroke; +import javax.swing.LookAndFeel; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.border.AbstractBorder; +import javax.swing.event.InternalFrameEvent; +import javax.swing.event.InternalFrameListener; +import javax.swing.event.MouseInputAdapter; +import javax.swing.event.MouseInputListener; +import javax.swing.plaf.ActionMapUIResource; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.InternalFrameUI; +import javax.swing.plaf.UIResource; + +/** + * This is the UI delegate for the Basic look and feel for JInternalFrames. + */ +public class BasicInternalFrameUI extends InternalFrameUI +{ + /** + * This is a helper class that listens to the JInternalFrame for + * InternalFrameEvents. + */ + protected class BasicInternalFrameListener implements InternalFrameListener + { + /** + * This method is called when the JInternalFrame is activated. + * + * @param e The InternalFrameEvent. + */ + public void internalFrameActivated(InternalFrameEvent e) + { + frame.getGlassPane().setVisible(false); + } + + /** + * This method is called when the JInternalFrame is closed. + * + * @param e The InternalFrameEvent. + */ + public void internalFrameClosed(InternalFrameEvent e) + { + // FIXME: Implement. + } + + /** + * This method is called when the JInternalFrame is closing. + * + * @param e The InternalFrameEvent. + */ + public void internalFrameClosing(InternalFrameEvent e) + { + // FIXME: Implement. + } + + /** + * This method is called when the JInternalFrame is deactivated. + * + * @param e The InternalFrameEvent. + */ + public void internalFrameDeactivated(InternalFrameEvent e) + { + frame.getGlassPane().setVisible(true); + } + + /** + * This method is called when the JInternalFrame is deiconified. + * + * @param e The InternalFrameEvent. + */ + public void internalFrameDeiconified(InternalFrameEvent e) + { + // FIXME: Implement. + } + + /** + * This method is called when the JInternalFrame is iconified. + * + * @param e The InternalFrameEvent. + */ + public void internalFrameIconified(InternalFrameEvent e) + { + // FIXME: Implement. + } + + /** + * This method is called when the JInternalFrame is opened. + * + * @param e The InternalFrameEvent. + */ + public void internalFrameOpened(InternalFrameEvent e) + { + // FIXME: Implement. + } + } + + /** + * This helper class listens to the edges of the JInternalFrame and the + * TitlePane for mouse events. It is responsible for dragging and resizing + * the JInternalFrame in response to the MouseEvents. + */ + protected class BorderListener extends MouseInputAdapter + implements SwingConstants + { + /** + * The current shape of the cursor. + */ + transient int showingCursor; + + /** FIXME: Use for something. */ + protected final int RESIZE_NONE = 0; + + /** The x offset from the top left corner of the JInternalFrame. */ + private transient int xOffset; + + /** The y offset from the top left corner of the JInternalFrame. */ + private transient int yOffset; + + /** The direction that the resize is occuring in. */ + private transient int direction = -1; + + /** Cache rectangle that can be reused. */ + private transient Rectangle cacheRect = new Rectangle(); + + /** + * This method is called when the mouse is clicked. + * + * @param e The MouseEvent. + */ + public void mouseClicked(MouseEvent e) + { + // Do minimization/maximization when double-clicking in the title pane. + if (e.getSource() == titlePane && e.getClickCount() == 2) + try + { + if (frame.isMaximizable() && ! frame.isMaximum()) + frame.setMaximum(true); + else if (frame.isMaximum()) + frame.setMaximum(false); + } + catch (PropertyVetoException pve) + { + // We do nothing if the attempt has been vetoed. + } + + // There is nothing to do when the mouse is clicked + // on the border. + } + + /** + * This method is called when the mouse is dragged. This method is + * responsible for resizing or dragging the JInternalFrame. + * + * @param e The MouseEvent. + */ + public void mouseDragged(MouseEvent e) + { + // If the frame is maximized, there is nothing that + // can be dragged around. + if (frame.isMaximum()) + return; + DesktopManager dm = getDesktopManager(); + Rectangle b = frame.getBounds(); + Dimension min = frame.getMinimumSize(); + if (min == null) + min = new Dimension(0, 0); + Insets insets = frame.getInsets(); + int x = e.getX(); + int y = e.getY(); + if (e.getSource() == frame && frame.isResizable()) + { + switch (direction) + { + case Cursor.N_RESIZE_CURSOR: + cacheRect.setBounds(b.x, Math.min(b.y + y, b.y + b.height + - min.height), + b.width, b.height - y); + break; + case Cursor.NE_RESIZE_CURSOR: + cacheRect.setBounds(b.x, Math.min(b.y + y, b.y + b.height + - min.height), x + 1, + b.height - y); + break; + case Cursor.E_RESIZE_CURSOR: + cacheRect.setBounds(b.x, b.y, x + 1, b.height); + break; + case Cursor.SE_RESIZE_CURSOR: + cacheRect.setBounds(b.x, b.y, x + 1, y + 1); + break; + case Cursor.S_RESIZE_CURSOR: + cacheRect.setBounds(b.x, b.y, b.width, y + 1); + break; + case Cursor.SW_RESIZE_CURSOR: + cacheRect.setBounds(Math.min(b.x + x, b.x + b.width - min.width), + b.y, b.width - x, y + 1); + break; + case Cursor.W_RESIZE_CURSOR: + cacheRect.setBounds(Math.min(b.x + x, b.x + b.width - min.width), + b.y, b.width - x, b.height); + break; + case Cursor.NW_RESIZE_CURSOR: + cacheRect.setBounds( + Math.min(b.x + x, b.x + b.width - min.width), + Math.min(b.y + y, b.y + b.height - min.height), + b.width - x, b.height - y); + break; + } + dm.resizeFrame(frame, cacheRect.x, cacheRect.y, + Math.max(min.width, cacheRect.width), + Math.max(min.height, cacheRect.height)); + setCursor(e); + } + else if (e.getSource() == titlePane) + { + Rectangle fBounds = frame.getBounds(); + frame.putClientProperty("bufferedDragging", Boolean.TRUE); + dm.dragFrame(frame, e.getX() - xOffset + b.x, e.getY() - yOffset + + b.y); + } + } + + /** + * This method is called when the mouse exits the JInternalFrame. + * + * @param e The MouseEvent. + */ + public void mouseExited(MouseEvent e) + { + if (showingCursor != Cursor.DEFAULT_CURSOR) + { + frame.setCursor(Cursor.getDefaultCursor()); + showingCursor = Cursor.DEFAULT_CURSOR; + } + } + + /** + * This method is called when the mouse is moved inside the JInternalFrame. + * + * @param e The MouseEvent. + */ + public void mouseMoved(MouseEvent e) + { + // Turn off the resize cursor if we are in the frame header. + if (showingCursor != Cursor.DEFAULT_CURSOR && e.getSource() != frame) + { + frame.setCursor(Cursor.getDefaultCursor()); + showingCursor = Cursor.DEFAULT_CURSOR; + } + else if (e.getSource() == frame && frame.isResizable()) + { + setCursor(e); + } + } + + /** + * Set the mouse cursor, how applicable. + * + * @param e the current mouse event. + */ + void setCursor(MouseEvent e) + { + int cursor = sectionOfClick(e.getX(), e.getY()); + if (cursor != showingCursor) + { + Cursor resize = Cursor.getPredefinedCursor(cursor); + frame.setCursor(resize); + showingCursor = cursor; + } + } + + /** + * This method is called when the mouse is pressed. + * + * @param e The MouseEvent. + */ + public void mousePressed(MouseEvent e) + { + activateFrame(frame); + DesktopManager dm = getDesktopManager(); + int x = e.getX(); + int y = e.getY(); + Insets insets = frame.getInsets(); + + if (e.getSource() == frame && frame.isResizable()) + { + direction = sectionOfClick(x, y); + dm.beginResizingFrame(frame, direction); + } + else if (e.getSource() == titlePane) + { + Rectangle tBounds = titlePane.getBounds(); + + xOffset = e.getX() - tBounds.x + insets.left; + yOffset = e.getY() - tBounds.y + insets.top; + + dm.beginDraggingFrame(frame); + } + } + + /** + * This method is called when the mouse is released. + * + * @param e The MouseEvent. + */ + public void mouseReleased(MouseEvent e) + { + DesktopManager dm = getDesktopManager(); + xOffset = 0; + yOffset = 0; + if (e.getSource() == frame && frame.isResizable()) + dm.endResizingFrame(frame); + else if (e.getSource() == titlePane) + { + dm.endDraggingFrame(frame); + frame.putClientProperty("bufferedDragging", null); + } + + setCursor(e); + } + + /** + * This method determines the direction of the resize based on the + * coordinates and the size of the JInternalFrame. + * + * @param x The x coordinate of the MouseEvent. + * @param y The y coordinate of the MouseEvent. + * + * @return The cursor constant, determining the resizing direction. + */ + private int sectionOfClick(int x, int y) + { + Rectangle b = frame.getBounds(); + int corner = InternalFrameBorder.cornerSize; + + if (x < corner && y < corner) + return Cursor.NW_RESIZE_CURSOR; + else if (x > b.width - corner && y < corner) + return Cursor.NE_RESIZE_CURSOR; + else if (x > b.width - corner && y > b.height - corner) + return Cursor.SE_RESIZE_CURSOR; + else if (x < corner && y > b.height - corner) + return Cursor.SW_RESIZE_CURSOR; + else if (y < corner) + return Cursor.N_RESIZE_CURSOR; + else if (x < corner) + return Cursor.W_RESIZE_CURSOR; + else if (y > b.height - corner) + return Cursor.S_RESIZE_CURSOR; + else if (x > b.width - corner) + return Cursor.E_RESIZE_CURSOR; + + return Cursor.DEFAULT_CURSOR; + } + } + + /** + * This helper class listens to the JDesktopPane that parents this + * JInternalFrame and listens for resize events and resizes the + * JInternalFrame appropriately. + */ + protected class ComponentHandler implements ComponentListener + { + /** + * This method is called when the JDesktopPane is hidden. + * + * @param e + * The ComponentEvent fired. + */ + public void componentHidden(ComponentEvent e) + { + // Do nothing. + } + + /** + * This method is called when the JDesktopPane is moved. + * + * @param e + * The ComponentEvent fired. + */ + public void componentMoved(ComponentEvent e) + { + // Do nothing. + } + + /** + * This method is called when the JDesktopPane is resized. + * + * @param e + * The ComponentEvent fired. + */ + public void componentResized(ComponentEvent e) + { + if (frame.isMaximum()) + { + Container parent = frame.getParent(); + Insets i = parent.getInsets(); + int width = parent.getWidth() - i.left - i.right; + int height = parent.getHeight() - i.top - i.bottom; + frame.setBounds(0, 0, width, height); + } + } + + /** + * This method is called when the JDesktopPane is shown. + * + * @param e + * The ComponentEvent fired. + */ + public void componentShown(ComponentEvent e) + { + // Do nothing. + } + } + + /** + * This helper class acts as the LayoutManager for JInternalFrames. + */ + public class InternalFrameLayout implements LayoutManager + { + /** + * This method is called when the given Component is added to the + * JInternalFrame. + * + * @param name + * The name of the Component. + * @param c + * The Component added. + */ + public void addLayoutComponent(String name, Component c) + { + // Nothing to do here. + } + + /** + * This method is used to set the bounds of the children of the + * JInternalFrame. + * + * @param c + * The Container to lay out. + */ + public void layoutContainer(Container c) + { + Dimension dims = frame.getSize(); + Insets insets = frame.getInsets(); + + dims.width -= insets.left + insets.right; + dims.height -= insets.top + insets.bottom; + + int nh = 0; + int sh = 0; + int ew = 0; + int ww = 0; + + if (northPane != null) + { + Dimension nDims = northPane.getPreferredSize(); + nh = Math.min(nDims.height, dims.height); + + northPane.setBounds(insets.left, insets.top, dims.width, nh); + } + + if (southPane != null) + { + Dimension sDims = southPane.getPreferredSize(); + sh = Math.min(sDims.height, dims.height - nh); + + southPane.setBounds(insets.left, insets.top + dims.height - sh, + dims.width, sh); + } + + int remHeight = dims.height - sh - nh; + + if (westPane != null) + { + Dimension wDims = westPane.getPreferredSize(); + ww = Math.min(dims.width, wDims.width); + + westPane.setBounds(insets.left, insets.top + nh, ww, remHeight); + } + + if (eastPane != null) + { + Dimension eDims = eastPane.getPreferredSize(); + ew = Math.min(eDims.width, dims.width - ww); + + eastPane.setBounds(insets.left + dims.width - ew, insets.top + nh, + ew, remHeight); + } + + int remWidth = dims.width - ww - ew; + + frame.getRootPane().setBounds(insets.left + ww, insets.top + nh, + remWidth, remHeight); + } + + /** + * This method returns the minimum layout size. + * + * @param c + * The Container to find a minimum layout size for. + * @return The minimum dimensions for the JInternalFrame. + */ + public Dimension minimumLayoutSize(Container c) + { + return getSize(c, true); + } + + /** + * Th8is method returns the preferred layout size. + * + * @param c + * The Container to find a preferred layout size for. + * @return The preferred dimensions for the JInternalFrame. + */ + public Dimension preferredLayoutSize(Container c) + { + return getSize(c, false); + } + + /** + * DOCUMENT ME! + * + * @param c + * DOCUMENT ME! + * @param min + * DOCUMENT ME! + * @return DOCUMENT ME! + */ + private Dimension getSize(Container c, boolean min) + { + Insets insets = frame.getInsets(); + + Dimension contentDims = frame.getContentPane().getPreferredSize(); + if (min) + contentDims.width = contentDims.height = 0; + int nWidth = 0; + int nHeight = 0; + int sWidth = 0; + int sHeight = 0; + int eWidth = 0; + int eHeight = 0; + int wWidth = 0; + int wHeight = 0; + Dimension dims; + + if (northPane != null) + { + dims = northPane.getPreferredSize(); + if (dims != null) + { + nWidth = dims.width; + nHeight = dims.height; + } + } + + if (southPane != null) + { + dims = southPane.getPreferredSize(); + if (dims != null) + { + sWidth = dims.width; + sHeight = dims.height; + } + } + + if (eastPane != null) + { + dims = eastPane.getPreferredSize(); + if (dims != null) + { + sWidth = dims.width; + sHeight = dims.height; + } + } + + if (westPane != null) + { + dims = westPane.getPreferredSize(); + if (dims != null) + { + wWidth = dims.width; + wHeight = dims.height; + } + } + + int width = Math.max(sWidth, nWidth); + width = Math.max(width, contentDims.width + eWidth + wWidth); + + int height = Math.max(eHeight, wHeight); + height = Math.max(height, contentDims.height); + height += nHeight + sHeight; + + width += insets.left + insets.right; + height += insets.top + insets.bottom; + + return new Dimension(width, height); + } + + /** + * This method is called when a Component is removed from the + * JInternalFrame. + * + * @param c The Component that was removed. + */ + public void removeLayoutComponent(Component c) + { + // Nothing to do here. + } + } + + /** + * This helper class is used to listen to the JDesktopPane's glassPane for + * MouseEvents. The JInternalFrame can then be selected if a click is + * detected on its children. + */ + protected class GlassPaneDispatcher implements MouseInputListener + { + /** The MouseEvent target. */ + private transient Component mouseEventTarget; + + private Component dragTarget; + + /** + * Indicates if we are currently in a dragging operation or not. + */ + private boolean isDragging; + + /** + * This method is called when the mouse enters the glass pane. + * + * @param e + * The MouseEvent. + */ + public void mouseEntered(MouseEvent e) + { + handleEvent(e); + } + + /** + * This method is called when the mouse is clicked on the glass pane. + * + * @param e + * The MouseEvent. + */ + public void mouseClicked(MouseEvent e) + { + handleEvent(e); + } + + /** + * This method is called when the mouse is dragged in the glass pane. + * + * @param e + * The MouseEvent. + */ + public void mouseDragged(MouseEvent e) + { + handleEvent(e); + } + + /** + * This method is called when the mouse exits the glass pane. + * + * @param e + * The MouseEvent. + */ + public void mouseExited(MouseEvent e) + { + handleEvent(e); + } + + /** + * This method is called when the mouse is moved in the glass pane. + * + * @param e + * The MouseEvent. + */ + public void mouseMoved(MouseEvent e) + { + handleEvent(e); + } + + /** + * This method is called when the mouse is pressed in the glass pane. + * + * @param e + * The MouseEvent. + */ + public void mousePressed(MouseEvent e) + { + // Experiments show that this seems to call the + // borderListener.mousePressed() method to activate the frame. + if (borderListener != null) + borderListener.mousePressed(e); + handleEvent(e); + } + + /** + * This method is called when the mouse is released in the glass pane. + * + * @param e + * The MouseEvent. + */ + public void mouseReleased(MouseEvent e) + { + handleEvent(e); + } + + /** + * This is a helper method that dispatches the GlassPane MouseEvents to the + * proper component. + * + * @param e the mouse event to be dispatched + */ + private void handleEvent(MouseEvent e) + { + // Find candidate component inside the JInternalFrame. + Component target = frame.getLayeredPane().findComponentAt(e.getX(), + e.getY()); + + // Now search upwards to find a component that actually has + // a MouseListener attached. + while (target != null + && target.getMouseListeners().length == 0 + && target.getMouseMotionListeners().length == 0 + && target.getMouseWheelListeners().length == 0) + { + target = target.getParent(); + } + + if (target != null) + { + int id = e.getID(); + switch (id) + { + case MouseEvent.MOUSE_ENTERED: + // Now redispatch the thing. + if (! isDragging || frame.isSelected()) + { + mouseEventTarget = target; + redispatch(id, e, mouseEventTarget); + } + break; + case MouseEvent.MOUSE_EXITED: + if (! isDragging || frame.isSelected()) + { + redispatch(id, e, mouseEventTarget); + } + break; + case MouseEvent.MOUSE_PRESSED: + mouseEventTarget = target; + redispatch(id, e, mouseEventTarget); + // Start dragging. + dragTarget = target; + break; + case MouseEvent.MOUSE_RELEASED: + if (isDragging) + { + redispatch(id, e, dragTarget); + isDragging = false; + } + else + redispatch(id, e, mouseEventTarget); + break; + case MouseEvent.MOUSE_CLICKED: + redispatch(id, e, mouseEventTarget); + break; + case MouseEvent.MOUSE_MOVED: + if (target != mouseEventTarget) + { + // Create additional MOUSE_EXITED/MOUSE_ENTERED pairs. + redispatch(MouseEvent.MOUSE_EXITED, e, mouseEventTarget); + mouseEventTarget = target; + redispatch(MouseEvent.MOUSE_ENTERED, e, mouseEventTarget); + } + redispatch(id, e, mouseEventTarget); + break; + case MouseEvent.MOUSE_DRAGGED: + if (! isDragging) + isDragging = true; + redispatch(id, e, mouseEventTarget); + break; + case MouseEvent.MOUSE_WHEEL: + redispatch(id, e, mouseEventTarget); + break; + default: + assert false : "Must not reach here"; + } + } + } + + /** + * Redispatches the event to the real target with the specified id. + * + * @param id the new event ID + * @param e the original event + * @param target the real event target + */ + private void redispatch(int id, MouseEvent e, Component target) + { + Point p = SwingUtilities.convertPoint(frame.getLayeredPane(), e.getX(), + e.getY(), target); + MouseEvent ev = new MouseEvent(target, id, e.getWhen(), + e.getModifiers() | e.getModifiersEx(), + p.x, p.y, e.getClickCount(), + e.isPopupTrigger()); + target.dispatchEvent(ev); + } + } + + /** + * This helper class listens for PropertyChangeEvents from the + * JInternalFrame. + */ + public class InternalFramePropertyChangeListener + implements PropertyChangeListener + { + + /** + * This method is called when one of the JInternalFrame's properties change. + * + * @param evt + * The PropertyChangeEvent. + */ + public void propertyChange(PropertyChangeEvent evt) + { + String property = evt.getPropertyName(); + if (property.equals(JInternalFrame.IS_MAXIMUM_PROPERTY)) + { + if (frame.isMaximum()) + maximizeFrame(frame); + else + minimizeFrame(frame); + } + else if (property.equals(JInternalFrame.IS_ICON_PROPERTY)) + { + if (frame.isIcon()) + iconifyFrame(frame); + else + deiconifyFrame(frame); + } + else if (property.equals(JInternalFrame.IS_SELECTED_PROPERTY)) + { + Component glassPane = frame.getGlassPane(); + if (frame.isSelected()) + { + activateFrame(frame); + glassPane.setVisible(false); + } + else + { + deactivateFrame(frame); + glassPane.setVisible(true); + } + } + else if (property.equals(JInternalFrame.ROOT_PANE_PROPERTY) + || property.equals(JInternalFrame.GLASS_PANE_PROPERTY)) + { + Component old = (Component) evt.getOldValue(); + if (old != null) + { + old.removeMouseListener(glassPaneDispatcher); + old.removeMouseMotionListener(glassPaneDispatcher); + } + + Component newPane = (Component) evt.getNewValue(); + if (newPane != null) + { + newPane.addMouseListener(glassPaneDispatcher); + newPane.addMouseMotionListener(glassPaneDispatcher); + } + + frame.revalidate(); + } + else if (property.equals(JInternalFrame.IS_CLOSED_PROPERTY)) + { + if (evt.getNewValue() == Boolean.TRUE) + { + Container parent = frame.getParent(); + if (parent != null) + parent.removeComponentListener(componentListener); + closeFrame(frame); + } + } + else if (property.equals("ancestor")) + { + Container newParent = (Container) evt.getNewValue(); + Container oldParent = (Container) evt.getOldValue(); + if (newParent != null) + { + newParent.addComponentListener(componentListener); + } + else if (oldParent != null) + { + oldParent.removeComponentListener(componentListener); + } + } + } + } + + /** + * This helper class is the border for the JInternalFrame. + */ + class InternalFrameBorder extends AbstractBorder implements + UIResource + { + /** + * The width of the border. + */ + static final int bSize = 5; + + /** + * The size of the corners (also used by the mouse listener). + */ + static final int cornerSize = 10; + + /** + * This method returns whether the border is opaque. + * + * @return Whether the border is opaque. + */ + public boolean isBorderOpaque() + { + return true; + } + + /** + * This method returns the insets of the border. + * + * @param c + * The Component to find border insets for. + * @return The border insets. + */ + public Insets getBorderInsets(Component c) + { + return new Insets(bSize, bSize, bSize, bSize); + } + + /** + * This method paints the border. + * + * @param c + * The Component that owns the border. + * @param g + * The Graphics object to paint with. + * @param x + * The x coordinate to paint at. + * @param y + * The y coordinate to paint at. + * @param width + * The width of the Component. + * @param height + * The height of the Component. + */ + public void paintBorder(Component c, Graphics g, int x, int y, int width, + int height) + { + g.translate(x, y); + Color saved = g.getColor(); + Rectangle b = frame.getBounds(); + + Color d = c.getBackground(); + g.setColor(d); + g.fillRect(0, 0, bSize, b.height); + g.fillRect(0, 0, b.width, bSize); + g.fillRect(0, b.height - bSize, b.width, bSize); + g.fillRect(b.width - bSize, 0, bSize, b.height); + + int x1 = 0; + int x2 = bSize; + int x3 = b.width - bSize; + int x4 = b.width; + + int y1 = 0; + int y2 = bSize; + int y3 = b.height - bSize; + int y4 = b.height; + + g.setColor(Color.GRAY); + g.fillRect(0, 0, bSize, y4); + g.fillRect(0, 0, x4, bSize); + g.fillRect(0, y3, b.width, bSize); + g.fillRect(x3, 0, bSize, b.height); + + g.fill3DRect(0, cornerSize, bSize, b.height - 2 * cornerSize, false); + g.fill3DRect(cornerSize, 0, b.width - 2 * cornerSize, bSize, false); + g.fill3DRect(cornerSize, b.height - bSize, b.width - 2 * cornerSize, + bSize, false); + g.fill3DRect(b.width - bSize, cornerSize, bSize, + b.height - 2 * cornerSize, false); + + g.translate(-x, -y); + g.setColor(saved); + } + } + + /** + * This action triggers the system menu. + * + * @author Roman Kennke (kennke@aicas.com) + */ + private class ShowSystemMenuAction + extends AbstractAction + { + public void actionPerformed(ActionEvent e) + { + if (titlePane != null) + { + titlePane.showSystemMenu(); + } + } + } + + /** + * The MouseListener that is responsible for dragging and resizing the + * JInternalFrame in response to MouseEvents. + */ + protected MouseInputAdapter borderListener; + + /** + * The ComponentListener that is responsible for resizing the JInternalFrame + * in response to ComponentEvents from the JDesktopPane. + */ + protected ComponentListener componentListener; + + /** + * The MouseListener that is responsible for activating the JInternalFrame + * when the mouse press activates one of its descendents. + */ + protected MouseInputListener glassPaneDispatcher; + + /** + * The PropertyChangeListener that is responsible for listening to + * PropertyChangeEvents from the JInternalFrame. + */ + protected PropertyChangeListener propertyChangeListener; + + /** The InternalFrameListener that listens to the JInternalFrame. */ + private transient BasicInternalFrameListener internalFrameListener; + + /** The JComponent placed at the east region of the JInternalFrame. */ + protected JComponent eastPane; + + /** The JComponent placed at the north region of the JInternalFrame. */ + protected JComponent northPane; + + /** The JComponent placed at the south region of the JInternalFrame. */ + protected JComponent southPane; + + /** The JComponent placed at the west region of the JInternalFrame. */ + protected JComponent westPane; + + /** + * The Keystroke bound to open the menu. + * @deprecated + */ + protected KeyStroke openMenuKey; + + /** The TitlePane displayed at the top of the JInternalFrame. */ + protected BasicInternalFrameTitlePane titlePane; + + /** The JInternalFrame this UI is responsible for. */ + protected JInternalFrame frame; + + /** The LayoutManager used in the JInternalFrame. */ + protected LayoutManager internalFrameLayout; + + /** The JDesktopPane that is the parent of the JInternalFrame. */ + private transient JDesktopPane desktopPane; + + /** + * Creates a new BasicInternalFrameUI object. + * + * @param b The JInternalFrame this UI will represent. + */ + public BasicInternalFrameUI(JInternalFrame b) + { + // Nothing to do here. + } + + /** + * This method will create a new BasicInternalFrameUI for the given + * JComponent. + * + * @param b The JComponent to create a BasicInternalFrameUI for. + * + * @return A new BasicInternalFrameUI. + */ + public static ComponentUI createUI(JComponent b) + { + return new BasicInternalFrameUI((JInternalFrame) b); + } + + /** + * This method installs a UI for the JInternalFrame. + * + * @param c The JComponent to install this UI on. + */ + public void installUI(JComponent c) + { + if (c instanceof JInternalFrame) + { + frame = (JInternalFrame) c; + + installDefaults(); + installListeners(); + installComponents(); + installKeyboardActions(); + + if (! frame.isSelected()) + frame.getGlassPane().setVisible(true); + } + } + + /** + * This method reverses the work done by installUI. + * + * @param c The JComponent to uninstall this UI for. + */ + public void uninstallUI(JComponent c) + { + uninstallKeyboardActions(); + uninstallComponents(); + uninstallListeners(); + uninstallDefaults(); + + frame.getRootPane().getGlassPane().setVisible(false); + frame = null; + } + + /** + * This method installs the defaults specified by the look and feel. + */ + protected void installDefaults() + { + internalFrameLayout = createLayoutManager(); + frame.setLayout(internalFrameLayout); + LookAndFeel.installBorder(frame, "InternalFrame.border"); + frame.setFrameIcon(UIManager.getIcon("InternalFrame.icon")); + + // Let the content pane inherit the background color from its + // frame by setting the background to null. + Component contentPane = frame.getContentPane(); + if (contentPane != null + && contentPane.getBackground() instanceof UIResource) + { + contentPane.setBackground(null); + } + } + + /** + * This method installs the keyboard actions for the JInternalFrame. + */ + protected void installKeyboardActions() + { + ActionMapUIResource am = new ActionMapUIResource(); + am.put("showSystemMenu", new ShowSystemMenuAction()); + + // The RI impl installs the audio actions as parent of the UI action map, + // so do we. + BasicLookAndFeel blaf = (BasicLookAndFeel) UIManager.getLookAndFeel(); + ActionMap audioActionMap = blaf.getAudioActionMap(); + am.setParent(audioActionMap); + + SwingUtilities.replaceUIActionMap(frame, am); + } + + /** + * This method installs the Components for the JInternalFrame. + */ + protected void installComponents() + { + setNorthPane(createNorthPane(frame)); + setSouthPane(createSouthPane(frame)); + setEastPane(createEastPane(frame)); + setWestPane(createWestPane(frame)); + } + + /** + * This method installs the listeners for the JInternalFrame. + */ + protected void installListeners() + { + glassPaneDispatcher = createGlassPaneDispatcher(); + createInternalFrameListener(); + borderListener = createBorderListener(frame); + componentListener = createComponentListener(); + propertyChangeListener = createPropertyChangeListener(); + + frame.addMouseListener(borderListener); + frame.addMouseMotionListener(borderListener); + frame.addInternalFrameListener(internalFrameListener); + frame.addPropertyChangeListener(propertyChangeListener); + frame.getRootPane().getGlassPane().addMouseListener(glassPaneDispatcher); + frame.getRootPane().getGlassPane().addMouseMotionListener(glassPaneDispatcher); + + Container parent = frame.getParent(); + if (parent != null) + { + parent.addComponentListener(componentListener); + } + } + + /** + * This method uninstalls the defaults for the JInternalFrame. + */ + protected void uninstallDefaults() + { + frame.setBorder(null); + frame.setLayout(null); + internalFrameLayout = null; + } + + /** + * This method uninstalls the Components for the JInternalFrame. + */ + protected void uninstallComponents() + { + setNorthPane(null); + setSouthPane(null); + setEastPane(null); + setWestPane(null); + } + + /** + * This method uninstalls the listeners for the JInternalFrame. + */ + protected void uninstallListeners() + { + + Container parent = frame.getParent(); + if (parent != null) + { + parent.removeComponentListener(componentListener); + } + componentListener = null; + + frame.getRootPane().getGlassPane().removeMouseMotionListener(glassPaneDispatcher); + frame.getRootPane().getGlassPane().removeMouseListener(glassPaneDispatcher); + + frame.removePropertyChangeListener(propertyChangeListener); + frame.removeInternalFrameListener(internalFrameListener); + frame.removeMouseMotionListener(borderListener); + frame.removeMouseListener(borderListener); + + propertyChangeListener = null; + + borderListener = null; + internalFrameListener = null; + glassPaneDispatcher = null; + } + + /** + * This method uninstalls the keyboard actions for the JInternalFrame. + */ + protected void uninstallKeyboardActions() + { + SwingUtilities.replaceUIActionMap(frame, null); + SwingUtilities.replaceUIInputMap(frame, JComponent.WHEN_IN_FOCUSED_WINDOW, + null); + } + + /** + * This method creates a new LayoutManager for the JInternalFrame. + * + * @return A new LayoutManager for the JInternalFrame. + */ + protected LayoutManager createLayoutManager() + { + return new InternalFrameLayout(); + } + + /** + * This method creates a new PropertyChangeListener for the JInternalFrame. + * + * @return A new PropertyChangeListener for the JInternalFrame. + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new InternalFramePropertyChangeListener(); + } + + /** + * This method returns the preferred size of the given JComponent. + * + * @param x The JComponent to find a preferred size for. + * + * @return The preferred size. + */ + public Dimension getPreferredSize(JComponent x) + { + Dimension pref = null; + LayoutManager layout = frame.getLayout(); + if (frame == x && layout != null) + pref = layout.preferredLayoutSize(frame); + else + pref = new Dimension(100, 100); + return pref; + } + + /** + * This method returns the minimum size of the given JComponent. + * + * @param x The JComponent to find a minimum size for. + * + * @return The minimum size. + */ + public Dimension getMinimumSize(JComponent x) + { + Dimension min = null; + LayoutManager layout = frame.getLayout(); + if (frame == x && layout != null) + min = layout.minimumLayoutSize(frame); + else + min = new Dimension(0, 0); + return min; + } + + /** + * This method returns the maximum size of the given JComponent. + * + * @param x The JComponent to find a maximum size for. + * + * @return The maximum size. + */ + public Dimension getMaximumSize(JComponent x) + { + Dimension max = null; + LayoutManager layout = frame.getLayout(); + if (frame == x && layout != null && layout instanceof LayoutManager2) + max = ((LayoutManager2) layout).maximumLayoutSize(frame); + else + max = new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); + return max; + } + + /** + * This method replaces the currentPane with the newPane. When replacing it + * also removes the MouseHandlers for the old pane and installs them on + * the new pane. + * + * @param currentPane The old pane to remove. + * @param newPane The new pane to install. + */ + protected void replacePane(JComponent currentPane, JComponent newPane) + { + if (currentPane != null) + { + deinstallMouseHandlers(currentPane); + frame.remove(currentPane); + } + + if (newPane != null) + { + installMouseHandlers(newPane); + frame.add(newPane); + } + } + + /** + * This method removes the necessary MouseListeners from the given + * JComponent. + * + * @param c The JComponent to remove MouseListeners from. + */ + protected void deinstallMouseHandlers(JComponent c) + { + c.removeMouseListener(borderListener); + c.removeMouseMotionListener(borderListener); + } + + /** + * This method installs the necessary MouseListeners from the given + * JComponent. + * + * @param c The JComponent to install MouseListeners on. + */ + protected void installMouseHandlers(JComponent c) + { + c.addMouseListener(borderListener); + c.addMouseMotionListener(borderListener); + } + + /** + * This method creates the north pane used in the JInternalFrame. + * + * @param w The JInternalFrame to create a north pane for. + * + * @return The north pane. + */ + protected JComponent createNorthPane(JInternalFrame w) + { + titlePane = new BasicInternalFrameTitlePane(w); + return titlePane; + } + + /** + * This method creates the west pane used in the JInternalFrame. + * + * @param w The JInternalFrame to create a west pane for. + * + * @return The west pane. + */ + protected JComponent createWestPane(JInternalFrame w) + { + return null; + } + + /** + * This method creates the south pane used in the JInternalFrame. + * + * @param w The JInternalFrame to create a south pane for. + * + * @return The south pane. + */ + protected JComponent createSouthPane(JInternalFrame w) + { + return null; + } + + /** + * This method creates the east pane used in the JInternalFrame. + * + * @param w The JInternalFrame to create an east pane for. + * + * @return The east pane. + */ + protected JComponent createEastPane(JInternalFrame w) + { + return null; + } + + /** + * This method returns a new BorderListener for the given JInternalFrame. + * + * @param w The JIntenalFrame to create a BorderListener for. + * + * @return A new BorderListener. + */ + protected MouseInputAdapter createBorderListener(JInternalFrame w) + { + return new BorderListener(); + } + + /** + * This method creates a new InternalFrameListener for the JInternalFrame. + */ + protected void createInternalFrameListener() + { + internalFrameListener = new BasicInternalFrameListener(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected final boolean isKeyBindingRegistered() + { + // FIXME: Implement. + return false; + } + + /** + * DOCUMENT ME! + * + * @param b DOCUMENT ME! + */ + protected final void setKeyBindingRegistered(boolean b) + { + // FIXME: Implement. + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public final boolean isKeyBindingActive() + { + // FIXME: Implement. + return false; + } + + /** + * DOCUMENT ME! + * + * @param b DOCUMENT ME! + */ + protected final void setKeyBindingActive(boolean b) + { + // FIXME: Implement. + } + + /** + * DOCUMENT ME! + */ + protected void setupMenuOpenKey() + { + // FIXME: Implement. + } + + /** + * DOCUMENT ME! + */ + protected void setupMenuCloseKey() + { + // FIXME: Implement. + } + + /** + * This method returns the north pane. + * + * @return The north pane. + */ + public JComponent getNorthPane() + { + return northPane; + } + + /** + * This method sets the north pane to be the given JComponent. + * + * @param c The new north pane. + */ + public void setNorthPane(JComponent c) + { + replacePane(northPane, c); + northPane = c; + // the following is needed to make internal frames draggable when using + // the JGoodies PlasticLookAndFeel, because it overrides the + // createNorthPane() method and doesn't assign anything to the titlePane + // field. It is possible there is another way to make this work, but + // I didn't find it... + if (c instanceof BasicInternalFrameTitlePane) + titlePane = (BasicInternalFrameTitlePane) c; + } + + /** + * This method returns the south pane. + * + * @return The south pane. + */ + public JComponent getSouthPane() + { + return southPane; + } + + /** + * This method sets the south pane to be the given JComponent. + * + * @param c The new south pane. + */ + public void setSouthPane(JComponent c) + { + replacePane(southPane, c); + southPane = c; + } + + /** + * This method sets the east pane to be the given JComponent. + * + * @param c The new east pane. + */ + public void setEastPane(JComponent c) + { + replacePane(eastPane, c); + eastPane = c; + } + + /** + * This method returns the east pane. + * + * @return The east pane. + */ + public JComponent getEastPane() + { + return eastPane; + } + + /** + * This method sets the west pane to be the given JComponent. + * + * @param c The new west pane. + */ + public void setWestPane(JComponent c) + { + replacePane(westPane, c); + westPane = c; + } + + /** + * This method returns the west pane. + * + * @return The west pane. + */ + public JComponent getWestPane() + { + return westPane; + } + + /** + * This method returns the DesktopManager to use with the JInternalFrame. + * + * @return The DesktopManager to use with the JInternalFrame. + */ + protected DesktopManager getDesktopManager() + { + DesktopManager value = null; + JDesktopPane pane = frame.getDesktopPane(); + if (pane != null) + value = frame.getDesktopPane().getDesktopManager(); + if (value == null) + value = createDesktopManager(); + return value; + } + + /** + * This method returns a default DesktopManager that can be used with this + * JInternalFrame. + * + * @return A default DesktopManager that can be used with this + * JInternalFrame. + */ + protected DesktopManager createDesktopManager() + { + return new DefaultDesktopManager(); + } + + /** + * This is a convenience method that closes the JInternalFrame. + * + * @param f The JInternalFrame to close. + */ + protected void closeFrame(JInternalFrame f) + { + getDesktopManager().closeFrame(f); + } + + /** + * This is a convenience method that maximizes the JInternalFrame. + * + * @param f The JInternalFrame to maximize. + */ + protected void maximizeFrame(JInternalFrame f) + { + getDesktopManager().maximizeFrame(f); + } + + /** + * This is a convenience method that minimizes the JInternalFrame. + * + * @param f The JInternalFrame to minimize. + */ + protected void minimizeFrame(JInternalFrame f) + { + getDesktopManager().minimizeFrame(f); + } + + /** + * This is a convenience method that iconifies the JInternalFrame. + * + * @param f The JInternalFrame to iconify. + */ + protected void iconifyFrame(JInternalFrame f) + { + getDesktopManager().iconifyFrame(f); + } + + /** + * This is a convenience method that deiconifies the JInternalFrame. + * + * @param f The JInternalFrame to deiconify. + */ + protected void deiconifyFrame(JInternalFrame f) + { + getDesktopManager().deiconifyFrame(f); + } + + /** + * This is a convenience method that activates the JInternalFrame. + * + * @param f The JInternalFrame to activate. + */ + protected void activateFrame(JInternalFrame f) + { + getDesktopManager().activateFrame(f); + } + + /** + * This is a convenience method that deactivates the JInternalFrame. + * + * @param f the JInternalFrame to deactivate + */ + protected void deactivateFrame(JInternalFrame f) + { + getDesktopManager().deactivateFrame(f); + } + + /** + * This method returns a new ComponentListener for the JDesktopPane. + * + * @return A new ComponentListener. + */ + protected ComponentListener createComponentListener() + { + return new ComponentHandler(); + } + + /** + * This method returns a new GlassPaneDispatcher. + * + * @return A new GlassPaneDispatcher. + */ + protected MouseInputListener createGlassPaneDispatcher() + { + return new GlassPaneDispatcher(); + } +} |