diff options
Diffstat (limited to 'libjava/classpath/javax/swing/plaf/basic/BasicToolBarUI.java')
-rw-r--r-- | libjava/classpath/javax/swing/plaf/basic/BasicToolBarUI.java | 1610 |
1 files changed, 1610 insertions, 0 deletions
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicToolBarUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicToolBarUI.java new file mode 100644 index 000000000..f5b2b2d1e --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicToolBarUI.java @@ -0,0 +1,1610 @@ +/* BasicToolBarUI.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.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ContainerEvent; +import java.awt.event.ContainerListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.MouseEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Hashtable; + +import javax.swing.AbstractAction; +import javax.swing.AbstractButton; +import javax.swing.Action; +import javax.swing.ActionMap; +import javax.swing.InputMap; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JToolBar; +import javax.swing.KeyStroke; +import javax.swing.LookAndFeel; +import javax.swing.RootPaneContainer; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.border.Border; +import javax.swing.border.CompoundBorder; +import javax.swing.event.MouseInputListener; +import javax.swing.plaf.ActionMapUIResource; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.ToolBarUI; +import javax.swing.plaf.UIResource; +import javax.swing.plaf.basic.BasicBorders.ButtonBorder; + +/** + * This is the Basic Look and Feel UI class for JToolBar. + */ +public class BasicToolBarUI extends ToolBarUI implements SwingConstants +{ + + /** + * Implements the keyboard actions for JToolBar. + */ + static class ToolBarAction + extends AbstractAction + { + /** + * Performs the action. + */ + public void actionPerformed(ActionEvent event) + { + Object cmd = getValue("__command__"); + JToolBar toolBar = (JToolBar) event.getSource(); + BasicToolBarUI ui = (BasicToolBarUI) toolBar.getUI(); + + if (cmd.equals("navigateRight")) + ui.navigateFocusedComp(EAST); + else if (cmd.equals("navigateLeft")) + ui.navigateFocusedComp(WEST); + else if (cmd.equals("navigateUp")) + ui.navigateFocusedComp(NORTH); + else if (cmd.equals("navigateDown")) + ui.navigateFocusedComp(SOUTH); + else + assert false : "Shouldn't reach here"; + } + } + + /** Static owner of all DragWindows. + * This is package-private to avoid an accessor method. */ + static JFrame owner = new JFrame(); + + /** The border used when the JToolBar is in nonrollover mode. */ + private static Border nonRolloverBorder; + + /** The border used when the JToolBar is in rollover mode. */ + private static Border rolloverBorder; + + /** The last known BorderLayout constraint before floating. */ + protected String constraintBeforeFloating; + + /** The last known orientation of the JToolBar before floating. + * This is package-private to avoid an accessor method. */ + int lastGoodOrientation; + + /** The color of the border when it is dockable. */ + protected Color dockingBorderColor; + + /** The background color of the JToolBar when it is dockable. */ + protected Color dockingColor; + + /** The docking listener responsible for mouse events on the JToolBar. */ + protected MouseInputListener dockingListener; + + /** The window used for dragging the JToolBar. */ + protected BasicToolBarUI.DragWindow dragWindow; + + /** The color of the border when it is not dockable. */ + protected Color floatingBorderColor; + + /** The background color of the JToolBar when it is not dockable. */ + protected Color floatingColor; + + /** The index of the focused component. */ + protected int focusedCompIndex; + + /** The PropertyChangeListener for the JToolBar. */ + protected PropertyChangeListener propertyListener; + + /** The JToolBar this UI delegate is responsible for. */ + protected JToolBar toolBar; + + /** The Container listener for the JToolBar. */ + protected ContainerListener toolBarContListener; + + /** The Focus listener for the JToolBar. */ + protected FocusListener toolBarFocusListener; + + /** + * @deprecated since JDK1.3. + */ + protected KeyStroke leftKey; + + /** + * @deprecated since JDK1.3. + */ + protected KeyStroke rightKey; + + /** + * @deprecated since JDK1.3. + */ + protected KeyStroke upKey; + + /** + * @deprecated since JDK1.3. + */ + protected KeyStroke downKey; + + /** + * The floating window that is responsible for holding the JToolBar when it + * is dragged outside of its original parent. + */ + private transient Window floatFrame; + + /** The original parent of the JToolBar. + * This is package-private to avoid an accessor method. */ + transient Container origParent; + + /** A hashtable of components and their original borders. + * This is package-private to avoid an accessor method. */ + transient Hashtable borders; + + /** A window listener for the floatable frame. */ + private transient WindowListener windowListener; + + /** A set of cached bounds of the JToolBar. + * This is package-private to avoid an accessor method. */ + transient Dimension cachedBounds; + + /** The cached orientation of the JToolBar. + * This is package-private to avoid an accessor method. */ + transient int cachedOrientation; + + /** + * This method creates a new <code>BasicToolBarUI</code> object for the given JToolBar. + */ + public BasicToolBarUI() + { + // Do nothing here. + } + + /** + * This method returns whether the JToolBar can dock at the given position. + * + * @param c The component to try to dock in. + * @param p The position of the mouse cursor relative to the given + * component. + * + * @return Whether the JToolBar can dock. + */ + public boolean canDock(Component c, Point p) + { + return areaOfClick(c, p) != -1; + } + + /** + * This helper method returns the position of the JToolBar if it can dock. + * + * @param c The component to try to dock in. + * @param p The position of the mouse cursor relative to the given + * component. + * + * @return One of the SwingConstants directions or -1 if the JToolBar can't + * dock. + */ + private int areaOfClick(Component c, Point p) + { + // Has to dock in immediate parent, not eventual root container. + Rectangle pBounds = c.getBounds(); + + // XXX: In Sun's implementation, the space the toolbar has to dock is dependent on the size it had last. + Dimension d = toolBar.getSize(); + int limit = Math.min(d.width, d.height); + + // The order of checking is 1. top 2. bottom 3. left 4. right + if (! pBounds.contains(p)) + return -1; + + if (p.y < limit) + return SwingConstants.NORTH; + + if (p.y > (pBounds.height - limit)) + return SwingConstants.SOUTH; + + if (p.x < limit) + return SwingConstants.WEST; + + if (p.x > (pBounds.width - limit)) + return SwingConstants.EAST; + + return -1; + } + + /** + * This method creates a new DockingListener for the JToolBar. + * + * @return A new DockingListener for the JToolBar. + */ + protected MouseInputListener createDockingListener() + { + return new DockingListener(toolBar); + } + + /** + * This method creates a new DragWindow for the given JToolBar. + * + * @param toolbar The JToolBar to create a DragWindow for. + * + * @return A new DragWindow. + */ + protected BasicToolBarUI.DragWindow createDragWindow(JToolBar toolbar) + { + return new DragWindow(); + } + + /** + * This method creates a new floating frame for the JToolBar. By default, + * this UI uses createFloatingWindow instead. This method of creating a + * floating frame is deprecated. + * + * @param toolbar The JToolBar to create a floating frame for. + * + * @return A new floating frame. + */ + protected JFrame createFloatingFrame(JToolBar toolbar) + { + // FIXME: Though deprecated, this should still work. + return null; + } + + /** + * This method creates a new floating window for the JToolBar. This is the + * method used by default to create a floating container for the JToolBar. + * + * @param toolbar The JToolBar to create a floating window for. + * + * @return A new floating window. + */ + protected RootPaneContainer createFloatingWindow(JToolBar toolbar) + { + // This one is used by default though. + return new ToolBarDialog(); + } + + /** + * This method creates a new WindowListener for the JToolBar. + * + * @return A new WindowListener. + */ + protected WindowListener createFrameListener() + { + return new FrameListener(); + } + + /** + * This method creates a new nonRolloverBorder for JButtons when the + * JToolBar's rollover property is set to false. + * + * @return A new NonRolloverBorder. + */ + protected Border createNonRolloverBorder() + { + Border b = UIManager.getBorder("ToolBar.nonrolloverBorder"); + + if (b == null) + { + b = new CompoundBorder( + new ButtonBorder(UIManager.getColor("Button.shadow"), + UIManager.getColor("Button.darkShadow"), + UIManager.getColor("Button.light"), + UIManager.getColor("Button.highlight")), + BasicBorders.getMarginBorder()); + } + + return b; } + + /** + * This method creates a new PropertyChangeListener for the JToolBar. + * + * @return A new PropertyChangeListener. + */ + protected PropertyChangeListener createPropertyListener() + { + return new PropertyListener(); + } + + /** + * This method creates a new rollover border for JButtons when the + * JToolBar's rollover property is set to true. + * + * @return A new rollover border. + */ + protected Border createRolloverBorder() + { + Border b = UIManager.getBorder("ToolBar.rolloverBorder"); + + if (b == null) + { + b = new CompoundBorder( + new ButtonBorder(UIManager.getColor("Button.shadow"), + UIManager.getColor("Button.darkShadow"), + UIManager.getColor("Button.light"), + UIManager.getColor("Button.highlight")), + BasicBorders.getMarginBorder()); + } + + return b; + } + + /** + * This method creates a new Container listener for the JToolBar. + * + * @return A new Container listener. + */ + protected ContainerListener createToolBarContListener() + { + return new ToolBarContListener(); + } + + /** + * This method creates a new FocusListener for the JToolBar. + * + * @return A new FocusListener for the JToolBar. + */ + protected FocusListener createToolBarFocusListener() + { + return new ToolBarFocusListener(); + } + + /** + * This method creates a new UI delegate for the given JComponent. + * + * @param c The JComponent to create a UI delegate for. + * + * @return A new UI delegate. + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicToolBarUI(); + } + + /** + * This method is called to drag the DragWindow around when the JToolBar is + * being dragged around. + * + * @param position The mouse cursor coordinates relative to the JToolBar. + * @param origin The screen position of the JToolBar. + */ + protected void dragTo(Point position, Point origin) + { + int loc = areaOfClick(origParent, + SwingUtilities.convertPoint(toolBar, position, + origParent)); + + if (loc != -1) + { + dragWindow.setBorderColor(dockingBorderColor); + dragWindow.setBackground(dockingColor); + } + else + { + dragWindow.setBorderColor(floatingBorderColor); + dragWindow.setBackground(floatingColor); + } + + int w = 0; + int h = 0; + + boolean tmp = (loc == SwingConstants.NORTH) + || (loc == SwingConstants.SOUTH) || (loc == -1); + + cachedOrientation = toolBar.getOrientation(); + cachedBounds = toolBar.getSize(); + if (((cachedOrientation == SwingConstants.HORIZONTAL) && tmp) + || ((cachedOrientation == VERTICAL) && ! tmp)) + { + w = cachedBounds.width; + h = cachedBounds.height; + } + else + { + w = cachedBounds.height; + h = cachedBounds.width; + } + + Point p = dragWindow.getOffset(); + Insets insets = toolBar.getInsets(); + + dragWindow.setBounds((origin.x + position.x) - p.x + - ((insets.left + insets.right) / 2), + (origin.y + position.y) - p.y + - ((insets.top + insets.bottom) / 2), w, h); + + if (! dragWindow.isVisible()) + dragWindow.show(); + } + + /** + * This method is used at the end of a drag session to place the frame in + * either its original parent as a docked JToolBar or in its floating + * frame. + * + * @param position The position of the mouse cursor relative to the + * JToolBar. + * @param origin The screen position of the JToolBar before the drag session + * started. + */ + protected void floatAt(Point position, Point origin) + { + Point p = new Point(position); + int aoc = areaOfClick(origParent, + SwingUtilities.convertPoint(toolBar, p, origParent)); + + Container oldParent = toolBar.getParent(); + + oldParent.remove(toolBar); + oldParent.doLayout(); + oldParent.repaint(); + + Container newParent; + + if (aoc == -1) + newParent = ((RootPaneContainer) floatFrame).getContentPane(); + else + { + floatFrame.hide(); + newParent = origParent; + } + + String constraint; + switch (aoc) + { + case SwingConstants.EAST: + constraint = BorderLayout.EAST; + break; + case SwingConstants.NORTH: + constraint = BorderLayout.NORTH; + break; + case SwingConstants.SOUTH: + constraint = BorderLayout.SOUTH; + break; + case SwingConstants.WEST: + constraint = BorderLayout.WEST; + break; + default: + constraint = BorderLayout.CENTER; + break; + } + + int newOrientation = SwingConstants.HORIZONTAL; + if ((aoc != -1) + && ((aoc == SwingConstants.EAST) || (aoc == SwingConstants.WEST))) + newOrientation = SwingConstants.VERTICAL; + + if (aoc != -1) + { + constraintBeforeFloating = constraint; + lastGoodOrientation = newOrientation; + } + + newParent.add(toolBar, constraint); + + setFloating(aoc == -1, null); + toolBar.setOrientation(newOrientation); + + Insets insets = floatFrame.getInsets(); + Dimension dims = toolBar.getPreferredSize(); + p = dragWindow.getOffset(); + setFloatingLocation((position.x + origin.x) - p.x + - ((insets.left + insets.right) / 2), + (position.y + origin.y) - p.y + - ((insets.top + insets.bottom) / 2)); + + if (aoc == -1) + { + floatFrame.pack(); + floatFrame.setSize(dims.width + insets.left + insets.right, + dims.height + insets.top + insets.bottom); + floatFrame.show(); + } + + newParent.invalidate(); + newParent.validate(); + newParent.repaint(); + } + + /** + * This method returns the docking color. + * + * @return The docking color. + */ + public Color getDockingColor() + { + return dockingColor; + } + + /** + * This method returns the Color which is displayed when over a floating + * area. + * + * @return The color which is displayed when over a floating area. + */ + public Color getFloatingColor() + { + return floatingColor; + } + + /** + * This method returns the maximum size of the given JComponent for this UI. + * + * @param c The JComponent to find the maximum size for. + * + * @return The maximum size for this UI. + */ + public Dimension getMaximumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the minimum size of the given JComponent for this UI. + * + * @param c The JComponent to find a minimum size for. + * + * @return The minimum size for this UI. + */ + public Dimension getMinimumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method installs the needed components for the JToolBar. + */ + protected void installComponents() + { + floatFrame = (Window) createFloatingWindow(toolBar); + + dragWindow = createDragWindow(toolBar); + + nonRolloverBorder = createNonRolloverBorder(); + rolloverBorder = createRolloverBorder(); + + borders = new Hashtable(); + setRolloverBorders(toolBar.isRollover()); + + fillHashtable(); + } + + /** + * This method installs the defaults as specified by the look and feel. + */ + protected void installDefaults() + { + LookAndFeel.installBorder(toolBar, "ToolBar.border"); + LookAndFeel.installColorsAndFont(toolBar, "ToolBar.background", + "ToolBar.foreground", "ToolBar.font"); + + dockingBorderColor = UIManager.getColor("ToolBar.dockingForeground"); + dockingColor = UIManager.getColor("ToolBar.dockingBackground"); + + floatingBorderColor = UIManager.getColor("ToolBar.floatingForeground"); + floatingColor = UIManager.getColor("ToolBar.floatingBackground"); + } + + /** + * This method installs the keyboard actions for the JToolBar as specified + * by the look and feel. + */ + protected void installKeyboardActions() + { + // Install the input map. + InputMap inputMap = + (InputMap) SharedUIDefaults.get("ToolBar.ancestorInputMap"); + SwingUtilities.replaceUIInputMap(toolBar, + JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, + inputMap); + + // FIXME: The JDK uses a LazyActionMap for parentActionMap + SwingUtilities.replaceUIActionMap(toolBar, getActionMap()); + } + + /** + * Fetches the action map from the UI defaults, or create a new one + * if the action map hasn't been initialized. + * + * @return the action map + */ + private ActionMap getActionMap() + { + ActionMap am = (ActionMap) UIManager.get("ToolBar.actionMap"); + if (am == null) + { + am = createDefaultActions(); + UIManager.getLookAndFeelDefaults().put("ToolBar.actionMap", am); + } + return am; + } + + private ActionMap createDefaultActions() + { + ActionMapUIResource am = new ActionMapUIResource(); + Action action = new ToolBarAction(); + + am.put("navigateLeft", action); + am.put("navigateRight", action); + am.put("navigateUp", action); + am.put("navigateDown", action); + + return am; + } + + /** + * This method installs listeners for the JToolBar. + */ + protected void installListeners() + { + dockingListener = createDockingListener(); + toolBar.addMouseListener(dockingListener); + toolBar.addMouseMotionListener(dockingListener); + + propertyListener = createPropertyListener(); + toolBar.addPropertyChangeListener(propertyListener); + + toolBarContListener = createToolBarContListener(); + toolBar.addContainerListener(toolBarContListener); + + windowListener = createFrameListener(); + floatFrame.addWindowListener(windowListener); + + toolBarFocusListener = createToolBarFocusListener(); + if (toolBarFocusListener != null) + { + int count = toolBar.getComponentCount(); + for (int i = 0; i < count; i++) + toolBar.getComponent(i).addFocusListener(toolBarFocusListener); + } + } + + /** + * This method installs non rollover borders for each component inside the + * given JComponent. + * + * @param c The JComponent whose children need to have non rollover borders + * installed. + */ + protected void installNonRolloverBorders(JComponent c) + { + Component[] components = toolBar.getComponents(); + + for (int i = 0; i < components.length; i++) + setBorderToNonRollover(components[i]); + } + + /** + * This method installs normal (or their original) borders for each + * component inside the given JComponent. + * + * @param c The JComponent whose children need to have their original + * borders installed. + */ + protected void installNormalBorders(JComponent c) + { + Component[] components = toolBar.getComponents(); + + for (int i = 0; i < components.length; i++) + setBorderToNormal(components[i]); + } + + /** + * This method install rollover borders for each component inside the given + * JComponent. + * + * @param c The JComponent whose children need to have rollover borders + * installed. + */ + protected void installRolloverBorders(JComponent c) + { + Component[] components = toolBar.getComponents(); + + for (int i = 0; i < components.length; i++) + setBorderToRollover(components[i]); + } + + /** + * This method fills the borders hashtable with a list of components that + * are JButtons and their borders. + */ + private void fillHashtable() + { + Component[] c = toolBar.getComponents(); + + for (int i = 0; i < c.length; i++) + { + if (c[i] instanceof JButton) + { + // Don't really care about anything other than JButtons + JButton b = (JButton) c[i]; + + if (b.getBorder() != null) + borders.put(b, b.getBorder()); + } + } + } + + /** + * This method installs the UI for the given JComponent. + * + * @param c The JComponent to install a UI for. + */ + public void installUI(JComponent c) + { + super.installUI(c); + + if (c instanceof JToolBar) + { + toolBar = (JToolBar) c; + installDefaults(); + installComponents(); + installListeners(); + installKeyboardActions(); + } + } + + /** + * This method returns whether the JToolBar is floating. + * + * @return Whether the JToolBar is floating. + */ + public boolean isFloating() + { + return floatFrame.isVisible(); + } + + /** + * This method returns whether rollover borders have been set. + * + * @return Whether rollover borders have been set. + */ + public boolean isRolloverBorders() + { + return toolBar.isRollover(); + } + + /** + * This method navigates in the given direction giving focus to the next + * component in the given direction. + * + * @param direction The direction to give focus to. + */ + protected void navigateFocusedComp(int direction) + { + int count = toolBar.getComponentCount(); + switch (direction) + { + case EAST: + case SOUTH: + if (focusedCompIndex >= 0 && focusedCompIndex < count) + { + int i = focusedCompIndex + 1; + boolean focusRequested = false; + // Find component to focus and request focus on it. + while (i != focusedCompIndex && ! focusRequested) + { + if (i >= count) + i = 0; + Component comp = toolBar.getComponentAtIndex(i++); + if (comp != null && comp.isFocusable() + && comp.isEnabled()) + { + comp.requestFocus(); + focusRequested = true; + } + } + } + break; + case WEST: + case NORTH: + if (focusedCompIndex >= 0 && focusedCompIndex < count) + { + int i = focusedCompIndex - 1; + boolean focusRequested = false; + // Find component to focus and request focus on it. + while (i != focusedCompIndex && ! focusRequested) + { + if (i < 0) + i = count - 1; + Component comp = toolBar.getComponentAtIndex(i--); + if (comp != null && comp.isFocusable() + && comp.isEnabled()) + { + comp.requestFocus(); + focusRequested = true; + } + } + } + break; + default: + break; + } + } + + /** + * This method sets the border of the given component to a non rollover + * border. + * + * @param c The Component whose border needs to be set. + */ + protected void setBorderToNonRollover(Component c) + { + if (c instanceof AbstractButton) + { + AbstractButton b = (AbstractButton) c; + b.setRolloverEnabled(false); + + // Save old border in hashtable. + if (b.getBorder() != null) + borders.put(b, b.getBorder()); + + b.setBorder(nonRolloverBorder); + } + } + + /** + * This method sets the border of the given component to its original value. + * + * @param c The Component whose border needs to be set. + */ + protected void setBorderToNormal(Component c) + { + if (c instanceof AbstractButton) + { + AbstractButton b = (AbstractButton) c; + b.setRolloverEnabled(true); + b.setBorder((Border) borders.remove(b)); + } + } + + /** + * This method sets the border of the given component to a rollover border. + * + * @param c The Component whose border needs to be set. + */ + protected void setBorderToRollover(Component c) + { + if (c instanceof AbstractButton) + { + AbstractButton b = (AbstractButton) c; + b.setRolloverEnabled(false); + + // Save old border in hashtable. + if (b.getBorder() != null) + borders.put(b, b.getBorder()); + + b.setBorder(rolloverBorder); + } + } + + /** + * This method sets the docking color. + * + * @param c The docking color. + */ + public void setDockingColor(Color c) + { + dockingColor = c; + } + + /** + * This method sets the floating property for the JToolBar. + * + * @param b Whether the JToolBar is floating. + * @param p FIXME + */ + public void setFloating(boolean b, Point p) + { + // FIXME: use p for something. It's not location + // since we already have setFloatingLocation. + floatFrame.setVisible(b); + } + + /** + * This method sets the color displayed when the JToolBar is not in a + * dockable area. + * + * @param c The floating color. + */ + public void setFloatingColor(Color c) + { + floatingColor = c; + } + + /** + * This method sets the floating location of the JToolBar. + * + * @param x The x coordinate for the floating frame. + * @param y The y coordinate for the floating frame. + */ + public void setFloatingLocation(int x, int y) + { + // x,y are the coordinates of the new JFrame created to store the toolbar + // XXX: The floating location is bogus is not floating. + floatFrame.setLocation(x, y); + floatFrame.invalidate(); + floatFrame.validate(); + floatFrame.repaint(); + } + + /** + * This is a convenience method for changing the orientation of the + * JToolBar. + * + * @param orientation The new orientation. + */ + public void setOrientation(int orientation) + { + toolBar.setOrientation(orientation); + } + + /** + * This method changes the child components to have rollover borders if the + * given parameter is true. Otherwise, the components are set to have non + * rollover borders. + * + * @param rollover Whether the children will have rollover borders. + */ + public void setRolloverBorders(boolean rollover) + { + if (rollover) + installRolloverBorders(toolBar); + else + installNonRolloverBorders(toolBar); + } + + /** + * This method uninstall UI installed components from the JToolBar. + */ + protected void uninstallComponents() + { + installNormalBorders(toolBar); + borders = null; + cachedBounds = null; + + floatFrame = null; + dragWindow = null; + } + + /** + * This method removes the defaults installed by the Look and Feel. + */ + protected void uninstallDefaults() + { + toolBar.setBackground(null); + toolBar.setForeground(null); + toolBar.setFont(null); + + dockingBorderColor = null; + dockingColor = null; + floatingBorderColor = null; + floatingColor = null; + } + + /** + * This method uninstalls keyboard actions installed by the UI. + */ + protected void uninstallKeyboardActions() + { + SwingUtilities.replaceUIInputMap(toolBar, JComponent. + WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, null); + SwingUtilities.replaceUIActionMap(toolBar, null); + } + + /** + * This method uninstalls listeners installed by the UI. + */ + protected void uninstallListeners() + { + if (toolBarFocusListener != null) + { + int count = toolBar.getComponentCount(); + for (int i = 0; i < count; i++) + toolBar.getComponent(i).removeFocusListener(toolBarFocusListener); + toolBarFocusListener = null; + } + + floatFrame.removeWindowListener(windowListener); + windowListener = null; + + toolBar.removeContainerListener(toolBarContListener); + toolBarContListener = null; + + toolBar.removeMouseMotionListener(dockingListener); + toolBar.removeMouseListener(dockingListener); + dockingListener = null; + } + + /** + * This method uninstalls the UI. + * + * @param c The JComponent that is having this UI removed. + */ + public void uninstallUI(JComponent c) + { + uninstallKeyboardActions(); + uninstallListeners(); + uninstallComponents(); + uninstallDefaults(); + toolBar = null; + } + + /** + * This is the MouseHandler class that allows the user to drag the JToolBar + * in and out of the parent and dock it if it can. + */ + public class DockingListener implements MouseInputListener + { + /** Whether the JToolBar is being dragged. */ + protected boolean isDragging; + + /** + * The origin point. This point is saved from the beginning press and is + * used until the end of the drag session. + */ + protected Point origin; + + /** The JToolBar being dragged. */ + protected JToolBar toolBar; + + /** + * Creates a new DockingListener object. + * + * @param t The JToolBar this DockingListener is being used for. + */ + public DockingListener(JToolBar t) + { + toolBar = t; + } + + /** + * This method is called when the mouse is clicked. + * + * @param e The MouseEvent. + */ + public void mouseClicked(MouseEvent e) + { + // Nothing to do here. + } + + /** + * This method is called when the mouse is dragged. It delegates the drag + * painting to the dragTo method. + * + * @param e The MouseEvent. + */ + public void mouseDragged(MouseEvent e) + { + if (isDragging) + dragTo(e.getPoint(), origin); + } + + /** + * This method is called when the mouse enters the JToolBar. + * + * @param e The MouseEvent. + */ + public void mouseEntered(MouseEvent e) + { + // Nothing to do here. + } + + /** + * This method is called when the mouse exits the JToolBar. + * + * @param e The MouseEvent. + */ + public void mouseExited(MouseEvent e) + { + // Nothing to do here. + } + + /** + * This method is called when the mouse is moved in the JToolBar. + * + * @param e The MouseEvent. + */ + public void mouseMoved(MouseEvent e) + { + // Nothing to do here. + } + + /** + * This method is called when the mouse is pressed in the JToolBar. If the + * press doesn't occur in a place where it causes the JToolBar to be + * dragged, it returns. Otherwise, it starts a drag session. + * + * @param e The MouseEvent. + */ + public void mousePressed(MouseEvent e) + { + if (! toolBar.isFloatable()) + return; + + Point ssd = e.getPoint(); + Insets insets = toolBar.getInsets(); + + // Verify that this click occurs in the top inset. + if (toolBar.getOrientation() == SwingConstants.HORIZONTAL) + { + if (e.getX() > insets.left) + return; + } + else + { + if (e.getY() > insets.top) + return; + } + + origin = new Point(0, 0); + if (toolBar.isShowing()) + SwingUtilities.convertPointToScreen(ssd, toolBar); + + if (! (SwingUtilities.getAncestorOfClass(Window.class, toolBar) instanceof UIResource)) + // Need to know who keeps the toolBar if it gets dragged back into it. + origParent = toolBar.getParent(); + + if (toolBar.isShowing()) + SwingUtilities.convertPointToScreen(origin, toolBar); + + isDragging = true; + + if (dragWindow != null) + dragWindow.setOffset(new Point(cachedBounds.width / 2, + cachedBounds.height / 2)); + + dragTo(e.getPoint(), origin); + } + + /** + * This method is called when the mouse is released from the JToolBar. + * + * @param e The MouseEvent. + */ + public void mouseReleased(MouseEvent e) + { + if (! isDragging || ! toolBar.isFloatable()) + return; + + isDragging = false; + floatAt(e.getPoint(), origin); + dragWindow.hide(); + } + } + + /** + * This is the window that appears when the JToolBar is being dragged + * around. + */ + protected class DragWindow extends Window + { + /** + * The current border color. It changes depending on whether the JToolBar + * is over a place that allows it to dock. + */ + private Color borderColor; + + /** The between the mouse and the top left corner of the window. */ + private Point offset; + + /** + * Creates a new DragWindow object. + * This is package-private to avoid an accessor method. + */ + DragWindow() + { + super(owner); + } + + /** + * The color that the border should be. + * + * @return The border color. + */ + public Color getBorderColor() + { + if (borderColor == null) + return Color.BLACK; + + return borderColor; + } + + /** + * This method returns the insets for the DragWindow. + * + * @return The insets for the DragWindow. + */ + public Insets getInsets() + { + // This window has no decorations, so insets are empty. + return new Insets(0, 0, 0, 0); + } + + /** + * This method returns the mouse offset from the top left corner of the + * DragWindow. + * + * @return The mouse offset. + */ + public Point getOffset() + { + return offset; + } + + /** + * This method paints the DragWindow. + * + * @param g The Graphics object to paint with. + */ + public void paint(Graphics g) + { + // No visiting children necessary. + Color saved = g.getColor(); + Rectangle b = getBounds(); + + g.setColor(getBorderColor()); + g.drawRect(0, 0, b.width - 1, b.height - 1); + + g.setColor(saved); + } + + /** + * This method changes the border color. + * + * @param c The new border color. + */ + public void setBorderColor(Color c) + { + borderColor = c; + } + + /** + * This method changes the mouse offset. + * + * @param p The new mouse offset. + */ + public void setOffset(Point p) + { + offset = p; + } + + /** + * Sets the orientation of the toolbar and the + * drag window. + * + * @param o - the new orientation of the toolbar and drag + * window. + */ + public void setOrientation(int o) + { + toolBar.setOrientation(o); + if (dragWindow != null) + dragWindow.setOrientation(o); + } + } + + /** + * This helper class listens for Window events from the floatable window and + * if it is closed, returns the JToolBar to the last known good location. + */ + protected class FrameListener extends WindowAdapter + { + /** + * This method is called when the floating window is closed. + * + * @param e The WindowEvent. + */ + public void windowClosing(WindowEvent e) + { + Container parent = toolBar.getParent(); + parent.remove(toolBar); + + if (origParent != null) + { + origParent.add(toolBar, + (constraintBeforeFloating != null) + ? constraintBeforeFloating : BorderLayout.NORTH); + toolBar.setOrientation(lastGoodOrientation); + } + + origParent.invalidate(); + origParent.validate(); + origParent.repaint(); + } + } + + /** + * This helper class listens for PropertyChangeEvents from the JToolBar. + */ + protected class PropertyListener implements PropertyChangeListener + { + /** + * This method is called when a property from the JToolBar is changed. + * + * @param e The PropertyChangeEvent. + */ + public void propertyChange(PropertyChangeEvent e) + { + // FIXME: need name properties so can change floatFrame title. + if (e.getPropertyName().equals("rollover") && toolBar != null) + setRolloverBorders(toolBar.isRollover()); + } + } + + /** + * This helper class listens for components added to and removed from the + * JToolBar. + */ + protected class ToolBarContListener implements ContainerListener + { + /** + * This method is responsible for setting rollover or non rollover for new + * buttons added to the JToolBar. + * + * @param e The ContainerEvent. + */ + public void componentAdded(ContainerEvent e) + { + if (e.getChild() instanceof JButton) + { + JButton b = (JButton) e.getChild(); + + if (b.getBorder() != null) + borders.put(b, b.getBorder()); + } + + if (isRolloverBorders()) + setBorderToRollover(e.getChild()); + else + setBorderToNonRollover(e.getChild()); + + cachedBounds = toolBar.getPreferredSize(); + cachedOrientation = toolBar.getOrientation(); + + Component c = e.getChild(); + if (toolBarFocusListener != null) + c.addFocusListener(toolBarFocusListener); + } + + /** + * This method is responsible for giving the child components their + * original borders when they are removed. + * + * @param e The ContainerEvent. + */ + public void componentRemoved(ContainerEvent e) + { + setBorderToNormal(e.getChild()); + cachedBounds = toolBar.getPreferredSize(); + cachedOrientation = toolBar.getOrientation(); + + Component c = e.getChild(); + if (toolBarFocusListener != null) + c.removeFocusListener(toolBarFocusListener); + } + } + + /** + * This is the floating window that is returned when getFloatingWindow is + * called. + */ + private class ToolBarDialog extends JDialog implements UIResource + { + /** + * Creates a new ToolBarDialog object with the name given by the JToolBar. + */ + public ToolBarDialog() + { + super(); + setName((toolBar.getName() != null) ? toolBar.getName() : ""); + } + } + + /** + * DOCUMENT ME! + */ + protected class ToolBarFocusListener implements FocusListener + { + /** + * Creates a new ToolBarFocusListener object. + */ + protected ToolBarFocusListener() + { + // Nothing to do here. + } + + /** + * Receives notification when the toolbar or one of it's component + * receives the keyboard input focus. + * + * @param e the focus event + */ + public void focusGained(FocusEvent e) + { + Component c = e.getComponent(); + focusedCompIndex = toolBar.getComponentIndex(c); + } + + /** + * Receives notification when the toolbar or one of it's component + * looses the keyboard input focus. + * + * @param e the focus event + */ + public void focusLost(FocusEvent e) + { + // Do nothing here. + } + } + + /** + * This helper class acts as the border for the JToolBar. + */ + private static class ToolBarBorder implements Border + { + /** The size of the larger, draggable side of the border. */ + private static final int offset = 10; + + /** The other sides. */ + private static final int regular = 2; + + /** + * This method returns the border insets for the JToolBar. + * + * @param c The Component to find insets for. + * + * @return The border insets. + */ + public Insets getBorderInsets(Component c) + { + if (c instanceof JToolBar) + { + JToolBar tb = (JToolBar) c; + int orientation = tb.getOrientation(); + + if (! tb.isFloatable()) + return new Insets(regular, regular, regular, regular); + else if (orientation == SwingConstants.HORIZONTAL) + return new Insets(regular, offset, regular, regular); + else + return new Insets(offset, regular, regular, regular); + } + + return new Insets(0, 0, 0, 0); + } + + /** + * This method returns whether the border is opaque. + * + * @return Whether the border is opaque. + */ + public boolean isBorderOpaque() + { + return false; + } + + /** + * This method paints the ribbed area of the border. + * + * @param g The Graphics object to paint with. + * @param x The x coordinate of the area. + * @param y The y coordinate of the area. + * @param w The width of the area. + * @param h The height of the area. + * @param size The size of the bump. + * @param c The color of the bumps. + */ + private void paintBumps(Graphics g, int x, int y, int w, int h, int size, + Color c) + { + Color saved = g.getColor(); + g.setColor(c); + + int hgap = 2 * size; + int vgap = 4 * size; + int count = 0; + + for (int i = x; i < (w + x); i += hgap) + for (int j = ((count++ % 2) == 0) ? y : (y + (2 * size)); j < (h + y); + j += vgap) + g.fillRect(i, j, size, size); + + g.setColor(saved); + } + + /** + * This method paints the border around the given Component. + * + * @param c The Component whose border is being painted. + * @param g The Graphics object to paint with. + * @param x The x coordinate of the component. + * @param y The y coordinate of the component. + * @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) + { + if (c instanceof JToolBar) + { + JToolBar tb = (JToolBar) c; + + int orientation = tb.getOrientation(); + + if (orientation == SwingConstants.HORIZONTAL) + { + paintBumps(g, x, y, offset, height, 1, Color.WHITE); + paintBumps(g, x + 1, y + 1, offset - 1, height - 1, 1, Color.GRAY); + } + else + { + paintBumps(g, x, y, width, offset, 1, Color.WHITE); + paintBumps(g, x + 1, y + 1, width - 1, offset - 1, 1, Color.GRAY); + } + } + } + } +} |