/** * @(#)PaletteToolBarUI.java * * Copyright (c) 2008 The authors and contributors of JHotDraw. * You may not use, copy or modify this file, except in compliance with the * accompanying license terms. */ package org.jhotdraw.gui.plaf.palette; import javax.annotation.Nullable; import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.beans.*; import java.util.HashMap; import javax.swing.border.*; import javax.swing.plaf.*; /** * ToolBarUI for palette components. * <p> * This UI differs from BasicToolBarUI, in that the component holding the toolbar * is supposed to use BoxLayout instead of BorderLayout. This allows to have * multiple toolbars in the same component. The toolbars can be reorderd in the * component, but they are not allowed to float in their own floating window. * <p> * The JToolBar starts dragging only, if the drag starts over the insets of * its border. * * @author Werner Randelshofer * @version $Id$ */ public class PaletteToolBarUI extends ToolBarUI implements SwingConstants { private static final boolean isFloatingAllowed = false; protected JToolBar toolBar; private boolean floating; private int floatingX; private int floatingY; private JFrame floatingFrame; @Nullable private RootPaneContainer floatingToolBar; @Nullable protected DragWindow dragWindow; @Nullable private Container dockingSource; private int dockingSensitivity = 0; protected int focusedCompIndex = -1; @Nullable protected Color dockingColor = null; @Nullable protected Color floatingColor = null; @Nullable protected Color dockingBorderColor = null; @Nullable protected Color floatingBorderColor = null; @Nullable protected MouseInputListener dockingListener; @Nullable protected PropertyChangeListener propertyListener; @Nullable protected ContainerListener toolBarContListener; @Nullable protected FocusListener toolBarFocusListener; @Nullable private Handler handler; protected Integer constraintBeforeFloating = 0; // Rollover button implementation. private static String IS_ROLLOVER = "JToolBar.isRollover"; /*private*/ static String IS_DIVIDER_DRAWN = "Palette.ToolBar.isDividerDrawn"; // client properties /* The value of this client property must be an Icon or null. */ public static final String TOOLBAR_ICON_PROPERTY = "Palette.ToolBar.icon"; /* The value of this client property must be an Integer or null, if it is null, the value 2 is used. */ public static final String TOOLBAR_TEXT_ICON_GAP_PROPERTY = "Palette.ToolBar.textIconGap"; /* The value of this client property must be an Insets object or null, if it is null, the insets of the toolbar border are used */ public static final String TOOLBAR_INSETS_OVERRIDE_PROPERTY = "Palette.ToolBar.insetsOverride"; private static Border rolloverBorder; private static Border nonRolloverBorder; private static Border nonRolloverToggleBorder; private boolean rolloverBorders = false; private HashMap<AbstractButton, Border> borderTable = new HashMap<>(); private HashMap<AbstractButton, Boolean> rolloverTable = new HashMap<>(); /** * 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 Java 2 platform v1.3. */ @Deprecated protected KeyStroke upKey; /** * 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 Java 2 platform v1.3. */ @Deprecated protected KeyStroke downKey; /** * 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 Java 2 platform v1.3. */ @Deprecated protected KeyStroke leftKey; /** * 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 Java 2 platform v1.3. */ @Deprecated protected KeyStroke rightKey; private static String FOCUSED_COMP_INDEX = "JToolBar.focusedCompIndex"; public static ComponentUI createUI(JComponent c) { return new PaletteToolBarUI(); } @Override public void installUI(JComponent c) { toolBar = (JToolBar) c; // Set defaults installDefaults(); installComponents(); installListeners(); installKeyboardActions(); // Initialize instance vars dockingSensitivity = 0; floating = false; floatingX = floatingY = 0; floatingToolBar = null; setOrientation(toolBar.getOrientation()); LookAndFeel.installProperty(c, "opaque", Boolean.TRUE); if (c.getClientProperty(FOCUSED_COMP_INDEX) != null) { focusedCompIndex = ((Integer) (c.getClientProperty(FOCUSED_COMP_INDEX))); } } @Override public void uninstallUI(JComponent c) { // Clear defaults uninstallDefaults(); uninstallComponents(); uninstallListeners(); uninstallKeyboardActions(); // Clear instance vars if (isFloating() == true) { setFloating(false, null); } floatingToolBar = null; dragWindow = null; dockingSource = null; c.putClientProperty(FOCUSED_COMP_INDEX, focusedCompIndex); } protected void installDefaults() { PaletteLookAndFeel.installBorder(toolBar, "ToolBar.border"); PaletteLookAndFeel.installColorsAndFont(toolBar, "ToolBar.background", "ToolBar.foreground", "ToolBar.font"); // Toolbar specific defaults if (dockingColor == null || dockingColor instanceof UIResource) { dockingColor = UIManager.getColor("ToolBar.dockingBackground"); } if (floatingColor == null || floatingColor instanceof UIResource) { floatingColor = UIManager.getColor("ToolBar.floatingBackground"); } if (dockingBorderColor == null || dockingBorderColor instanceof UIResource) { dockingBorderColor = UIManager.getColor("ToolBar.dockingForeground"); } if (floatingBorderColor == null || floatingBorderColor instanceof UIResource) { floatingBorderColor = UIManager.getColor("ToolBar.floatingForeground"); // ToolBar rollover button borders } Object rolloverProp = toolBar.getClientProperty(IS_ROLLOVER); if (rolloverProp == null) { rolloverProp = UIManager.get("ToolBar.isRollover"); } if (rolloverProp != null) { rolloverBorders = ((Boolean) rolloverProp); } if (rolloverBorder == null) { rolloverBorder = createRolloverBorder(); } if (nonRolloverBorder == null) { nonRolloverBorder = createNonRolloverBorder(); } if (nonRolloverToggleBorder == null) { nonRolloverToggleBorder = createNonRolloverToggleBorder(); } setRolloverBorders(isRolloverBorders()); } protected void uninstallDefaults() { LookAndFeel.uninstallBorder(toolBar); dockingColor = null; floatingColor = null; dockingBorderColor = null; floatingBorderColor = null; installNormalBorders(toolBar); rolloverBorder = null; nonRolloverBorder = null; nonRolloverToggleBorder = null; } protected void installComponents() { } protected void uninstallComponents() { } protected void installListeners() { dockingListener = createDockingListener(); if (dockingListener != null) { toolBar.addMouseMotionListener(dockingListener); toolBar.addMouseListener(dockingListener); } propertyListener = createPropertyListener(); // added in setFloating if (propertyListener != null) { toolBar.addPropertyChangeListener(propertyListener); } toolBarContListener = createToolBarContListener(); if (toolBarContListener != null) { toolBar.addContainerListener(toolBarContListener); } toolBarFocusListener = createToolBarFocusListener(); if (toolBarFocusListener != null) { // Put focus listener on all components in toolbar Component[] components = toolBar.getComponents(); for (int i = 0; i < components.length; ++i) { components[i].addFocusListener(toolBarFocusListener); } } } protected void uninstallListeners() { if (dockingListener != null) { toolBar.removeMouseMotionListener(dockingListener); toolBar.removeMouseListener(dockingListener); dockingListener = null; } if (propertyListener != null) { toolBar.removePropertyChangeListener(propertyListener); propertyListener = null; // removed in setFloating } if (toolBarContListener != null) { toolBar.removeContainerListener(toolBarContListener); toolBarContListener = null; } if (toolBarFocusListener != null) { // Remove focus listener from all components in toolbar Component[] components = toolBar.getComponents(); for (int i = 0; i < components.length; ++i) { components[i].removeFocusListener(toolBarFocusListener); } toolBarFocusListener = null; } handler = null; } protected void installKeyboardActions() { InputMap km = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); SwingUtilities.replaceUIInputMap(toolBar, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, km); PaletteLazyActionMap.installLazyActionMap(toolBar, PaletteToolBarUI.class, "ToolBar.actionMap"); } @Nullable InputMap getInputMap(int condition) { if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) { return (InputMap) PaletteLookAndFeel.getInstance().get( "ToolBar.ancestorInputMap"); } return null; } static void loadActionMap(PaletteLazyActionMap map) { map.put(new Actions(Actions.NAVIGATE_RIGHT)); map.put(new Actions(Actions.NAVIGATE_LEFT)); map.put(new Actions(Actions.NAVIGATE_UP)); map.put(new Actions(Actions.NAVIGATE_DOWN)); } protected void uninstallKeyboardActions() { SwingUtilities.replaceUIActionMap(toolBar, null); SwingUtilities.replaceUIInputMap(toolBar, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, null); } protected void navigateFocusedComp(int direction) { int nComp = toolBar.getComponentCount(); int j; switch (direction) { case EAST: case SOUTH: if (focusedCompIndex < 0 || focusedCompIndex >= nComp) { break; } j = focusedCompIndex + 1; while (j != focusedCompIndex) { if (j >= nComp) { j = 0; } Component comp = toolBar.getComponentAtIndex(j++); if (comp != null && comp.isFocusable() && comp.isEnabled()) { comp.requestFocus(); break; } } break; case WEST: case NORTH: if (focusedCompIndex < 0 || focusedCompIndex >= nComp) { break; } j = focusedCompIndex - 1; while (j != focusedCompIndex) { if (j < 0) { j = nComp - 1; } Component comp = toolBar.getComponentAtIndex(j--); if (comp != null && comp.isFocusable() && comp.isEnabled()) { comp.requestFocus(); break; } } break; default: break; } } /** * Creates a rollover border for toolbar components. The * rollover border will be installed if rollover borders are * enabled. * <p> * Override this method to provide an alternate rollover border. * * @since 1.4 */ protected Border createRolloverBorder() { Object border = UIManager.get("ToolBar.rolloverBorder"); if (border != null) { return (Border) border; } return new EmptyBorder(0, 0, 0, 0); } /** * Creates the non rollover border for toolbar components. This * border will be installed as the border for components added * to the toolbar if rollover borders are not enabled. * <p> * Override this method to provide an alternate rollover border. * * @since 1.4 */ protected Border createNonRolloverBorder() { Object border = UIManager.get("ToolBar.nonrolloverBorder"); if (border != null) { return (Border) border; } return new EmptyBorder(0, 0, 0, 0); } /** * Creates a non rollover border for Toggle buttons in the toolbar. */ private Border createNonRolloverToggleBorder() { return new EmptyBorder(0, 0, 0, 0); } /** * No longer used, use PaletteToolBarUI.createFloatingWindow(JToolBar) * @see #createFloatingWindow */ protected JFrame createFloatingFrame(JToolBar toolbar) { Window window = SwingUtilities.getWindowAncestor(toolbar); JFrame frame = new JFrame(toolbar.getName(), (window != null) ? window.getGraphicsConfiguration() : null) { private static final long serialVersionUID = 1L; // Override createRootPane() to automatically resize // the frame when contents change @Override protected JRootPane createRootPane() { JRootPane rootPane = new JRootPane() { private static final long serialVersionUID = 1L; private boolean packing = false; @Override public void validate() { super.validate(); if (!packing) { packing = true; pack(); packing = false; } } }; rootPane.setOpaque(true); return rootPane; } }; frame.getRootPane().setName("ToolBar.FloatingFrame"); frame.setResizable(false); WindowListener wl = createFrameListener(); frame.addWindowListener(wl); return frame; } /** * Creates a window which contains the toolbar after it has been * dragged out from its container * @return a <code>RootPaneContainer</code> object, containing the toolbar. */ protected RootPaneContainer createFloatingWindow(JToolBar toolbar) { class ToolBarDialog extends JDialog { private static final long serialVersionUID = 1L; public ToolBarDialog(@Nullable Frame owner, String title, boolean modal) { super(owner, title, modal); } public ToolBarDialog(@Nullable Dialog owner, String title, boolean modal) { super(owner, title, modal); } // Override createRootPane() to automatically resize // the frame when contents change @Override protected JRootPane createRootPane() { JRootPane rootPane = new JRootPane() { private static final long serialVersionUID = 1L; private boolean packing = false; @Override public void validate() { super.validate(); if (!packing) { packing = true; pack(); packing = false; } } }; rootPane.setOpaque(true); return rootPane; } } JDialog dialog; Window window = SwingUtilities.getWindowAncestor(toolbar); if (window instanceof Frame) { dialog = new ToolBarDialog((Frame) window, toolbar.getName(), false); } else if (window instanceof Dialog) { dialog = new ToolBarDialog((Dialog) window, toolbar.getName(), false); } else { dialog = new ToolBarDialog((Frame) null, toolbar.getName(), false); } dialog.getRootPane().setName("ToolBar.FloatingWindow"); dialog.setTitle(toolbar.getName()); dialog.setResizable(false); WindowListener wl = createFrameListener(); dialog.addWindowListener(wl); return dialog; } protected DragWindow createDragWindow(JToolBar toolbar) { Window frame = null; if (toolBar != null) { Container p; for (p = toolBar.getParent(); p != null && !(p instanceof Window); p = p.getParent()) { } frame = (Window) p; } if (floatingToolBar == null) { floatingToolBar = createFloatingWindow(toolBar); } if (floatingToolBar instanceof Window) { frame = (Window) floatingToolBar; } DragWindow w = new DragWindow(frame); JRootPane rp = ((RootPaneContainer) w).getRootPane(); rp.putClientProperty("Window.alpha", 0.6f); return w; } /** * Returns a flag to determine whether rollover button borders * are enabled. * * @return true if rollover borders are enabled; false otherwise * @see #setRolloverBorders * @since 1.4 */ public boolean isRolloverBorders() { return rolloverBorders; } /** * Sets the flag for enabling rollover borders on the toolbar and it will * also install the apropriate border depending on the state of the flag. * * @param rollover if true, rollover borders are installed. * Otherwise non-rollover borders are installed * @see #isRolloverBorders * @since 1.4 */ public void setRolloverBorders(boolean rollover) { rolloverBorders = rollover; if (rolloverBorders) { installRolloverBorders(toolBar); } else { installNonRolloverBorders(toolBar); } } /** * Installs rollover borders on all the child components of the JComponent. * <p> * This is a convenience method to call <code>setBorderToRollover</code> * for each child component. * * @param c container which holds the child components (usally a JToolBar) * @see #setBorderToRollover * @since 1.4 */ protected void installRolloverBorders(JComponent c) { // Put rollover borders on buttons Component[] components = c.getComponents(); for (int i = 0; i < components.length; ++i) { if (components[i] instanceof JComponent) { ((JComponent) components[i]).updateUI(); setBorderToRollover(components[i]); } } } /** * Installs non-rollover borders on all the child components of the JComponent. * A non-rollover border is the border that is installed on the child component * while it is in the toolbar. * <p> * This is a convenience method to call <code>setBorderToNonRollover</code> * for each child component. * * @param c container which holds the child components (usally a JToolBar) * @see #setBorderToNonRollover * @since 1.4 */ protected void installNonRolloverBorders(JComponent c) { // Put non-rollover borders on buttons. These borders reduce the margin. Component[] components = c.getComponents(); for (int i = 0; i < components.length; ++i) { if (components[i] instanceof JComponent) { ((JComponent) components[i]).updateUI(); setBorderToNonRollover(components[i]); } } } /** * Installs normal borders on all the child components of the JComponent. * A normal border is the original border that was installed on the child * component before it was added to the toolbar. * <p> * This is a convenience method to call <code>setBorderNormal</code> * for each child component. * * @param c container which holds the child components (usally a JToolBar) * @see #setBorderToNonRollover * @since 1.4 */ protected void installNormalBorders(JComponent c) { // Put back the normal borders on buttons Component[] components = c.getComponents(); for (int i = 0; i < components.length; ++i) { setBorderToNormal(components[i]); } } /** * Sets the border of the component to have a rollover border which * was created by <code>createRolloverBorder</code>. * * @param c component which will have a rollover border installed * @see #createRolloverBorder * @since 1.4 */ protected void setBorderToRollover(Component c) { if (true) { return; } if (c instanceof AbstractButton) { AbstractButton b = (AbstractButton) c; Border border = borderTable.get(b); if (border == null || border instanceof UIResource) { borderTable.put(b, b.getBorder()); } // Only set the border if its the default border if (b.getBorder() instanceof UIResource) { b.setBorder(getRolloverBorder(b)); } rolloverTable.put(b, b.isRolloverEnabled() ); b.setRolloverEnabled(true); } } @Nullable private Border getRolloverBorder(AbstractButton b) { Object borderProvider = UIManager.get("ToolBar.rolloverBorderProvider"); if (borderProvider == null) { return rolloverBorder; } //return ((BorderProvider) borderProvider).getRolloverBorder(b); return null; } /** * Sets the border of the component to have a non-rollover border which * was created by <code>createNonRolloverBorder</code>. * * @param c component which will have a non-rollover border installed * @see #createNonRolloverBorder * @since 1.4 */ protected void setBorderToNonRollover(Component c) { if (true) { return; } if (c instanceof AbstractButton) { AbstractButton b = (AbstractButton) c; Border border = borderTable.get(b); if (border == null || border instanceof UIResource) { borderTable.put(b, b.getBorder()); } // Only set the border if its the default border if (b.getBorder() instanceof UIResource) { if (b instanceof JToggleButton) { ((JToggleButton) b).setBorder(nonRolloverToggleBorder); } else { b.setBorder(nonRolloverBorder); } } rolloverTable.put(b, b.isRolloverEnabled() ? Boolean.TRUE : Boolean.FALSE); b.setRolloverEnabled(false); } } /** * Sets the border of the component to have a normal border. * A normal border is the original border that was installed on the child * component before it was added to the toolbar. * * @param c component which will have a normal border re-installed * @see #createNonRolloverBorder * @since 1.4 */ protected void setBorderToNormal(Component c) { if (true) { return; } if (c instanceof AbstractButton) { AbstractButton b = (AbstractButton) c; Border border = borderTable.remove(b); b.setBorder(border); Boolean value = rolloverTable.remove(b); if (value != null) { b.setRolloverEnabled(value); } } } public void setFloatingLocation(int x, int y) { floatingX = x; floatingY = y; } public boolean isFloating() { return floating; } public void setFloating(boolean b, @Nullable Point p) { if (toolBar.isFloatable() == true) { if (dragWindow != null) { dragWindow.setVisible(false); } this.floating = b; if (b && isFloatingAllowed) { if (dockingSource == null) { dockingSource = toolBar.getParent(); dockingSource.remove(toolBar); } constraintBeforeFloating = calculateConstraint(); if (propertyListener != null) { UIManager.addPropertyChangeListener(propertyListener); } if (floatingToolBar == null) { floatingToolBar = createFloatingWindow(toolBar); } floatingToolBar.getContentPane().add(toolBar, BorderLayout.CENTER); if (floatingToolBar instanceof Window) { ((Window) floatingToolBar).pack(); } if (floatingToolBar instanceof Window) { ((Window) floatingToolBar).setLocation(floatingX, floatingY); } if (floatingToolBar instanceof Window) { ((Window) floatingToolBar).setVisible(true); } } else { if (floatingToolBar == null) { floatingToolBar = createFloatingWindow(toolBar); } if (floatingToolBar instanceof Window) { ((Window) floatingToolBar).setVisible(false); } floatingToolBar.getContentPane().remove(toolBar); Integer constraint = getDockingConstraint(dockingSource, p); if (constraint == null) { constraint = 0; } int orientation = mapConstraintToOrientation(constraint); setOrientation(orientation); if (dockingSource == null) { dockingSource = toolBar.getParent(); } if (propertyListener != null) { UIManager.removePropertyChangeListener(propertyListener); } dockingSource.add(toolBar, constraint.intValue()); } dockingSource.invalidate(); Container dockingSourceParent = dockingSource.getParent(); if (dockingSourceParent != null) { dockingSourceParent.validate(); } dockingSource.repaint(); } } private int mapConstraintToOrientation(Object constraint) { int orientation = toolBar.getOrientation(); if (constraint != null) { if (constraint.equals(BorderLayout.EAST) || constraint.equals(BorderLayout.WEST)) { orientation = JToolBar.VERTICAL; } else if (constraint.equals(BorderLayout.NORTH) || constraint.equals(BorderLayout.SOUTH)) { orientation = JToolBar.HORIZONTAL; } } return orientation; } public void setOrientation(int orientation) { toolBar.setOrientation(orientation); if (dragWindow != null) { dragWindow.setOrientation(orientation); } } /** * Gets the color displayed when over a docking area */ public Color getDockingColor() { return dockingColor; } /** * Sets the color displayed when over a docking area */ public void setDockingColor(Color c) { this.dockingColor = c; } /** * Gets the color displayed when over a floating area */ public Color getFloatingColor() { return floatingColor; } /** * Sets the color displayed when over a floating area */ public void setFloatingColor(Color c) { this.floatingColor = c; } private boolean isBlocked(Component comp, Object constraint) { if (comp instanceof Container) { Container cont = (Container) comp; LayoutManager lm = cont.getLayout(); if (lm instanceof BorderLayout) { BorderLayout blm = (BorderLayout) lm; Component c = blm.getLayoutComponent(cont, constraint); return (c != null && c != toolBar); } } return false; } public boolean canDock(Component c, Point p) { return (p != null && getDockingConstraint(c, p) != null); } private Integer calculateConstraint() { Integer constraint = null; LayoutManager lm = dockingSource.getLayout(); if (lm instanceof BoxLayout) { for (int i = 0, n = dockingSource.getComponentCount(); i < n; i++) { if (dockingSource.getComponent(i) == toolBar) { constraint = i; break; } } } return (constraint != null) ? constraint : constraintBeforeFloating; } @Nullable private Integer getDockingConstraint(Component c, Point p) { if (p == null) { return constraintBeforeFloating; } if (c.contains(p)) { for (int i = 0, n = dockingSource.getComponentCount(); i < n; i++) { Component child = dockingSource.getComponent(i); Point childP = new Point(p.x - child.getX(), p.y - child.getY()); if (child.contains(childP)) { return Math.min(n - 1, (childP.x <= child.getWidth()) ? i : i + 1); } } if (dockingSource.getComponentCount() == 0 || p.x < dockingSource.getComponent(0).getX()) { return 0; } return dockingSource.getComponentCount() - 1; } return null; } protected void dragTo(Point position, Point origin) { if (toolBar.isFloatable() == true) { try { if (dragWindow == null) { dragWindow = createDragWindow(toolBar); } Point offset = dragWindow.getOffset(); if (offset == null) { //Dimension size = toolBar.getPreferredSize(); Dimension size = toolBar.getSize(); offset = new Point(size.width / 2, size.height / 2); dragWindow.setOffset(offset); } Point global = new Point(origin.x + position.x, origin.y + position.y); Point dragPoint = new Point(global.x - offset.x, global.y - offset.y); if (dockingSource == null) { dockingSource = toolBar.getParent(); } constraintBeforeFloating = calculateConstraint(); Point dockingPosition = dockingSource.getLocationOnScreen(); Point comparisonPoint = new Point(global.x - dockingPosition.x, global.y - dockingPosition.y); if (canDock(dockingSource, comparisonPoint)) { dragWindow.setBackground(getDockingColor()); Object constraint = getDockingConstraint(dockingSource, comparisonPoint); int orientation = mapConstraintToOrientation(constraint); dragWindow.setOrientation(orientation); dragWindow.setBorderColor(dockingBorderColor); } else { dragWindow.setBackground(getFloatingColor()); dragWindow.setBorderColor(floatingBorderColor); } dragWindow.setLocation(dragPoint.x, dragPoint.y); if (dragWindow.isVisible() == false) { //Dimension size = toolBar.getPreferredSize(); Dimension size = toolBar.getSize(); dragWindow.setSize(size.width, size.height); dragWindow.setVisible(true); } } catch (IllegalComponentStateException e) { } } } protected void floatAt(Point position, Point origin) { if (toolBar.isFloatable() == true) { try { Point offset = dragWindow.getOffset(); if (offset == null) { offset = position; dragWindow.setOffset(offset); } Point global = new Point(origin.x + position.x, origin.y + position.y); setFloatingLocation(global.x - offset.x, global.y - offset.y); if (dockingSource != null) { Point dockingPosition = dockingSource.getLocationOnScreen(); Point comparisonPoint = new Point(global.x - dockingPosition.x, global.y - dockingPosition.y); if (canDock(dockingSource, comparisonPoint)) { setFloating(false, comparisonPoint); } else { setFloating(true, null); } } else { setFloating(true, null); } dragWindow.setOffset(null); } catch (IllegalComponentStateException e) { } } } private Handler getHandler() { if (handler == null) { handler = new Handler(); } return handler; } protected ContainerListener createToolBarContListener() { return getHandler(); } protected FocusListener createToolBarFocusListener() { return getHandler(); } protected PropertyChangeListener createPropertyListener() { return getHandler(); } protected MouseInputListener createDockingListener() { getHandler().tb = toolBar; return getHandler(); } protected WindowListener createFrameListener() { return new FrameListener(); } /** * Paints the contents of the window used for dragging. * * @param g Graphics to paint to. * @throws NullPointerException is <code>g</code> is null * @since 1.5 */ protected void paintDragWindow(Graphics g) { int w = dragWindow.getWidth(); int h = dragWindow.getHeight(); g.setColor(dragWindow.getBackground()); g.fillRect(0, 0, w, h); boolean wasDoubleBuffered = false; if (toolBar.isDoubleBuffered()) { wasDoubleBuffered = true; toolBar.setDoubleBuffered(false); } Graphics g2 = g.create(); toolBar.paintAll(g2); g2.dispose(); g.setColor(dragWindow.getBorderColor()); g.drawRect(0, 0, w - 1, h - 1); if (wasDoubleBuffered) { toolBar.setDoubleBuffered(true); } } private static class Actions extends /*UI*/ AbstractAction { private static final long serialVersionUID = 1L; private static final String NAVIGATE_RIGHT = "navigateRight"; private static final String NAVIGATE_LEFT = "navigateLeft"; private static final String NAVIGATE_UP = "navigateUp"; private static final String NAVIGATE_DOWN = "navigateDown"; public Actions(String name) { super(name); } public String getName() { return (String) getValue(Action.NAME); } @Override public void actionPerformed(ActionEvent evt) { String key = getName(); JToolBar toolBar = (JToolBar) evt.getSource(); PaletteToolBarUI ui = (PaletteToolBarUI) PaletteLookAndFeel.getUIOfType( toolBar.getUI(), PaletteToolBarUI.class); if (NAVIGATE_RIGHT == key) { ui.navigateFocusedComp(EAST); } else if (NAVIGATE_LEFT == key) { ui.navigateFocusedComp(WEST); } else if (NAVIGATE_UP == key) { ui.navigateFocusedComp(NORTH); } else if (NAVIGATE_DOWN == key) { ui.navigateFocusedComp(SOUTH); } } } private class Handler implements ContainerListener, FocusListener, MouseInputListener, PropertyChangeListener { // // ContainerListener // @Override public void componentAdded(ContainerEvent evt) { Component c = evt.getChild(); if (toolBarFocusListener != null) { c.addFocusListener(toolBarFocusListener); } if (isRolloverBorders()) { setBorderToRollover(c); } else { setBorderToNonRollover(c); } } @Override public void componentRemoved(ContainerEvent evt) { Component c = evt.getChild(); if (toolBarFocusListener != null) { c.removeFocusListener(toolBarFocusListener); } // Revert the button border setBorderToNormal(c); } // // FocusListener // @Override public void focusGained(FocusEvent evt) { Component c = evt.getComponent(); focusedCompIndex = toolBar.getComponentIndex(c); } @Override public void focusLost(FocusEvent evt) { } // // MouseInputListener (DockingListener) // JToolBar tb; boolean isDragging = false; @Nullable Point origin = null; boolean isArmed = false; @Override public void mousePressed(MouseEvent evt) { if (!tb.isEnabled()) { return; } isDragging = false; if (evt.getSource() instanceof JToolBar) { JComponent c = (JComponent) evt.getSource(); Insets insets; if (c.getBorder() instanceof PaletteToolBarBorder) { insets = ((PaletteToolBarBorder) c.getBorder()).getDragInsets(c); } else { insets = c.getInsets(); } isArmed = !(evt.getX() > insets.left && evt.getX() < c.getWidth() - insets.right && evt.getY() > insets.top && evt.getY() < c.getHeight() - insets.bottom); } } @Override public void mouseReleased(MouseEvent evt) { if (!tb.isEnabled()) { return; } if (isDragging == true) { Point position = evt.getPoint(); if (origin == null) { origin = evt.getComponent().getLocationOnScreen(); } floatAt(position, origin); } origin = null; isDragging = false; } @Override public void mouseDragged(MouseEvent evt) { if (!tb.isEnabled()) { return; } if (!isArmed) { return; } isDragging = true; Point position = evt.getPoint(); if (origin == null) { origin = evt.getComponent().getLocationOnScreen(); } dragTo(position, origin); } @Override public void mouseClicked(MouseEvent evt) { } @Override public void mouseEntered(MouseEvent evt) { } @Override public void mouseExited(MouseEvent evt) { } @Override public void mouseMoved(MouseEvent evt) { } // // PropertyChangeListener // @Override public void propertyChange(PropertyChangeEvent evt) { String propertyName = evt.getPropertyName(); if (propertyName == "lookAndFeel") { toolBar.updateUI(); } else if (propertyName == "orientation") { // Search for JSeparator components and change it's orientation // to match the toolbar and flip it's orientation. Component[] components = toolBar.getComponents(); int orientation = ((Integer) evt.getNewValue()); JToolBar.Separator separator; for (int i = 0; i < components.length; ++i) { if (components[i] instanceof JToolBar.Separator) { separator = (JToolBar.Separator) components[i]; if ((orientation == JToolBar.HORIZONTAL)) { separator.setOrientation(JSeparator.VERTICAL); } else { separator.setOrientation(JSeparator.HORIZONTAL); } Dimension size = separator.getSeparatorSize(); if (size != null && size.width != size.height) { // Flip the orientation. Dimension newSize = new Dimension(size.height, size.width); separator.setSeparatorSize(newSize); } } } } else if (propertyName == IS_ROLLOVER) { installNormalBorders(toolBar); setRolloverBorders(((Boolean) evt.getNewValue())); } } } protected class FrameListener extends WindowAdapter { @Override public void windowClosing(WindowEvent w) { if (toolBar.isFloatable() == true) { if (dragWindow != null) { dragWindow.setVisible(false); } floating = false; if (floatingToolBar == null) { floatingToolBar = createFloatingWindow(toolBar); } if (floatingToolBar instanceof Window) { ((Window) floatingToolBar).setVisible(false); } floatingToolBar.getContentPane().remove(toolBar); Integer constraint = constraintBeforeFloating; if (dockingSource == null) { dockingSource = toolBar.getParent(); } if (propertyListener != null) { UIManager.removePropertyChangeListener(propertyListener); } dockingSource.add(toolBar, constraint.intValue()); dockingSource.invalidate(); Container dockingSourceParent = dockingSource.getParent(); if (dockingSourceParent != null) { dockingSourceParent.validate(); } dockingSource.repaint(); } } } protected class ToolBarContListener implements ContainerListener { // NOTE: This class exists only for backward compatability. All // its functionality has been moved into Handler. If you need to add // new functionality add it to the Handler, but make sure this // class calls into the Handler. @Override public void componentAdded(ContainerEvent e) { getHandler().componentAdded(e); } @Override public void componentRemoved(ContainerEvent e) { getHandler().componentRemoved(e); } } protected class ToolBarFocusListener implements FocusListener { // NOTE: This class exists only for backward compatability. All // its functionality has been moved into Handler. If you need to add // new functionality add it to the Handler, but make sure this // class calls into the Handler. @Override public void focusGained(FocusEvent e) { getHandler().focusGained(e); } @Override public void focusLost(FocusEvent e) { getHandler().focusLost(e); } } protected class PropertyListener implements PropertyChangeListener { // NOTE: This class exists only for backward compatability. All // its functionality has been moved into Handler. If you need to add // new functionality add it to the Handler, but make sure this // class calls into the Handler. @Override public void propertyChange(PropertyChangeEvent e) { getHandler().propertyChange(e); } } /** * This class should be treated as a "protected" inner class. * Instantiate it only within subclasses of PaletteToolBarUI. */ public class DockingListener implements MouseInputListener { // NOTE: This class exists only for backward compatability. All // its functionality has been moved into Handler. If you need to add // new functionality add it to the Handler, but make sure this // class calls into the Handler. protected JToolBar toolBar; protected boolean isDragging = false; @Nullable protected Point origin = null; public DockingListener(JToolBar t) { this.toolBar = t; getHandler().tb = t; } @Override public void mouseClicked(MouseEvent e) { getHandler().mouseClicked(e); } @Override public void mousePressed(MouseEvent e) { getHandler().tb = toolBar; getHandler().mousePressed(e); isDragging = getHandler().isDragging; } @Override public void mouseReleased(MouseEvent e) { getHandler().tb = toolBar; getHandler().isDragging = isDragging; getHandler().origin = origin; getHandler().mouseReleased(e); isDragging = getHandler().isDragging; origin = getHandler().origin; } @Override public void mouseEntered(MouseEvent e) { getHandler().mouseEntered(e); } @Override public void mouseExited(MouseEvent e) { getHandler().mouseExited(e); } @Override public void mouseDragged(MouseEvent e) { getHandler().tb = toolBar; getHandler().origin = origin; getHandler().mouseDragged(e); isDragging = getHandler().isDragging; origin = getHandler().origin; } @Override public void mouseMoved(MouseEvent e) { getHandler().mouseMoved(e); } } protected class DragWindow extends JWindow { private static final long serialVersionUID = 1L; Color borderColor = Color.gray; int orientation = toolBar.getOrientation(); @Nullable Point offset; // offset of the mouse cursor inside the DragWindow DragWindow(Window w) { super(w); getContentPane().add(new JPanel() { private static final long serialVersionUID = 1L; @Override public void paintComponent(Graphics g) { paintDragWindow(g); } }); } public void setOrientation(int o) { if (isShowing()) { if (o == this.orientation) { return; } this.orientation = o; Dimension size = getSize(); setSize(new Dimension(size.height, size.width)); if (offset != null) { if (toolBar.getComponentOrientation().isLeftToRight()) { setOffset(new Point(offset.y, offset.x)); } else if (o == JToolBar.HORIZONTAL) { setOffset(new Point(size.height - offset.y, offset.x)); } else { setOffset(new Point(offset.y, size.width - offset.x)); } } repaint(); } } @Nullable public Point getOffset() { return offset; } public void setOffset(@Nullable Point p) { this.offset = p; } public void setBorderColor(Color c) { if (this.borderColor == c) { return; } this.borderColor = c; repaint(); } public Color getBorderColor() { return this.borderColor; } @Override public Insets getInsets() { return new Insets(1, 1, 1, 1); } } }