1/*
2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package javax.swing.plaf.basic;
27
28import javax.swing.*;
29import javax.swing.event.*;
30import java.awt.*;
31import java.awt.event.*;
32
33import java.beans.*;
34
35import java.util.Hashtable;
36import java.util.HashMap;
37
38import javax.swing.border.*;
39import javax.swing.plaf.*;
40import sun.swing.DefaultLookup;
41import sun.swing.UIAction;
42
43
44/**
45 * A Basic L&F implementation of ToolBarUI.  This implementation
46 * is a "combined" view/controller.
47 *
48 * @author Georges Saab
49 * @author Jeff Shapiro
50 */
51public class BasicToolBarUI extends ToolBarUI implements SwingConstants
52{
53    /**
54     * The instance of {@code JToolBar}.
55     */
56    protected JToolBar toolBar;
57    private boolean floating;
58    private int floatingX;
59    private int floatingY;
60    private JFrame floatingFrame;
61    private RootPaneContainer floatingToolBar;
62    /**
63     * The instance of {@code DragWindow}.
64     */
65    protected DragWindow dragWindow;
66    private Container dockingSource;
67    private int dockingSensitivity = 0;
68    /**
69     * The index of the focused component.
70     */
71    protected int focusedCompIndex = -1;
72
73    /**
74     * The background color of the docking border.
75     */
76    protected Color dockingColor = null;
77    /**
78     * The background color of the not docking border.
79     */
80    protected Color floatingColor = null;
81    /**
82     * The color of the docking border.
83     */
84    protected Color dockingBorderColor = null;
85    /**
86     * The color of the not docking border.
87     */
88    protected Color floatingBorderColor = null;
89
90    /**
91     * The instance of a {@code MouseInputListener}.
92     */
93    protected MouseInputListener dockingListener;
94    /**
95     * The instance of a {@code PropertyChangeListener}.
96     */
97    protected PropertyChangeListener propertyListener;
98
99    /**
100     * The instance of a {@code ContainerListener}.
101     */
102    protected ContainerListener toolBarContListener;
103    /**
104     * The instance of a {@code FocusListener}.
105     */
106    protected FocusListener toolBarFocusListener;
107    private Handler handler;
108
109    /**
110     * The layout before floating.
111     */
112    protected String constraintBeforeFloating = BorderLayout.NORTH;
113
114    // Rollover button implementation.
115    private static String IS_ROLLOVER = "JToolBar.isRollover";
116    private static Border rolloverBorder;
117    private static Border nonRolloverBorder;
118    private static Border nonRolloverToggleBorder;
119    private boolean rolloverBorders = false;
120
121    private HashMap<AbstractButton, Border> borderTable = new HashMap<AbstractButton, Border>();
122    private Hashtable<AbstractButton, Boolean> rolloverTable = new Hashtable<AbstractButton, Boolean>();
123
124
125    /**
126     * As of Java 2 platform v1.3 this previously undocumented field is no
127     * longer used.
128     * Key bindings are now defined by the LookAndFeel, please refer to
129     * the key bindings specification for further details.
130     *
131     * @deprecated As of Java 2 platform v1.3.
132     */
133    @Deprecated
134    protected KeyStroke upKey;
135    /**
136     * As of Java 2 platform v1.3 this previously undocumented field is no
137     * longer used.
138     * Key bindings are now defined by the LookAndFeel, please refer to
139     * the key bindings specification for further details.
140     *
141     * @deprecated As of Java 2 platform v1.3.
142     */
143    @Deprecated
144    protected KeyStroke downKey;
145    /**
146     * As of Java 2 platform v1.3 this previously undocumented field is no
147     * longer used.
148     * Key bindings are now defined by the LookAndFeel, please refer to
149     * the key bindings specification for further details.
150     *
151     * @deprecated As of Java 2 platform v1.3.
152     */
153    @Deprecated
154    protected KeyStroke leftKey;
155    /**
156     * As of Java 2 platform v1.3 this previously undocumented field is no
157     * longer used.
158     * Key bindings are now defined by the LookAndFeel, please refer to
159     * the key bindings specification for further details.
160     *
161     * @deprecated As of Java 2 platform v1.3.
162     */
163    @Deprecated
164    protected KeyStroke rightKey;
165
166
167    private static String FOCUSED_COMP_INDEX = "JToolBar.focusedCompIndex";
168
169    /**
170     * Constructs a new instance of {@code BasicToolBarUI}.
171     *
172     * @param c a component
173     * @return a new instance of {@code BasicToolBarUI}
174     */
175    public static ComponentUI createUI( JComponent c )
176    {
177        return new BasicToolBarUI();
178    }
179
180    public void installUI( JComponent c )
181    {
182        toolBar = (JToolBar) c;
183
184        // Set defaults
185        installDefaults();
186        installComponents();
187        installListeners();
188        installKeyboardActions();
189
190        // Initialize instance vars
191        dockingSensitivity = 0;
192        floating = false;
193        floatingX = floatingY = 0;
194        floatingToolBar = null;
195
196        setOrientation( toolBar.getOrientation() );
197        LookAndFeel.installProperty(c, "opaque", Boolean.TRUE);
198
199        if ( c.getClientProperty( FOCUSED_COMP_INDEX ) != null )
200        {
201            focusedCompIndex = ( (Integer) ( c.getClientProperty( FOCUSED_COMP_INDEX ) ) ).intValue();
202        }
203    }
204
205    public void uninstallUI( JComponent c )
206    {
207
208        // Clear defaults
209        uninstallDefaults();
210        uninstallComponents();
211        uninstallListeners();
212        uninstallKeyboardActions();
213
214        // Clear instance vars
215        if (isFloating())
216            setFloating(false, null);
217
218        floatingToolBar = null;
219        dragWindow = null;
220        dockingSource = null;
221
222        c.putClientProperty( FOCUSED_COMP_INDEX, Integer.valueOf( focusedCompIndex ) );
223    }
224
225    /**
226     * Installs default properties.
227     */
228    protected void installDefaults( )
229    {
230        LookAndFeel.installBorder(toolBar,"ToolBar.border");
231        LookAndFeel.installColorsAndFont(toolBar,
232                                              "ToolBar.background",
233                                              "ToolBar.foreground",
234                                              "ToolBar.font");
235        // Toolbar specific defaults
236        if ( dockingColor == null || dockingColor instanceof UIResource )
237            dockingColor = UIManager.getColor("ToolBar.dockingBackground");
238        if ( floatingColor == null || floatingColor instanceof UIResource )
239            floatingColor = UIManager.getColor("ToolBar.floatingBackground");
240        if ( dockingBorderColor == null ||
241             dockingBorderColor instanceof UIResource )
242            dockingBorderColor = UIManager.getColor("ToolBar.dockingForeground");
243        if ( floatingBorderColor == null ||
244             floatingBorderColor instanceof UIResource )
245            floatingBorderColor = UIManager.getColor("ToolBar.floatingForeground");
246
247        // ToolBar rollover button borders
248        Object rolloverProp = toolBar.getClientProperty( IS_ROLLOVER );
249        if (rolloverProp == null) {
250            rolloverProp = UIManager.get("ToolBar.isRollover");
251        }
252        if ( rolloverProp != null ) {
253            rolloverBorders = ((Boolean)rolloverProp).booleanValue();
254        }
255
256        if (rolloverBorder == null) {
257            rolloverBorder = createRolloverBorder();
258        }
259        if (nonRolloverBorder == null) {
260            nonRolloverBorder = createNonRolloverBorder();
261        }
262        if (nonRolloverToggleBorder == null) {
263            nonRolloverToggleBorder = createNonRolloverToggleBorder();
264        }
265
266
267        setRolloverBorders( isRolloverBorders() );
268    }
269
270    /**
271     * Uninstalls default properties.
272     */
273    protected void uninstallDefaults( )
274    {
275        LookAndFeel.uninstallBorder(toolBar);
276        dockingColor = null;
277        floatingColor = null;
278        dockingBorderColor = null;
279        floatingBorderColor = null;
280
281        installNormalBorders(toolBar);
282
283        rolloverBorder = null;
284        nonRolloverBorder = null;
285        nonRolloverToggleBorder = null;
286    }
287
288    /**
289     * Registers components.
290     */
291    protected void installComponents( )
292    {
293    }
294
295    /**
296     * Unregisters components.
297     */
298    protected void uninstallComponents( )
299    {
300    }
301
302    /**
303     * Registers listeners.
304     */
305    protected void installListeners( )
306    {
307        dockingListener = createDockingListener( );
308
309        if ( dockingListener != null )
310        {
311            toolBar.addMouseMotionListener( dockingListener );
312            toolBar.addMouseListener( dockingListener );
313        }
314
315        propertyListener = createPropertyListener();  // added in setFloating
316        if (propertyListener != null) {
317            toolBar.addPropertyChangeListener(propertyListener);
318        }
319
320        toolBarContListener = createToolBarContListener();
321        if ( toolBarContListener != null ) {
322            toolBar.addContainerListener( toolBarContListener );
323        }
324
325        toolBarFocusListener = createToolBarFocusListener();
326
327        if ( toolBarFocusListener != null )
328        {
329            // Put focus listener on all components in toolbar
330            Component[] components = toolBar.getComponents();
331
332            for (Component component : components) {
333                component.addFocusListener(toolBarFocusListener);
334            }
335        }
336    }
337
338    /**
339     * Unregisters listeners.
340     */
341    protected void uninstallListeners( )
342    {
343        if ( dockingListener != null )
344        {
345            toolBar.removeMouseMotionListener(dockingListener);
346            toolBar.removeMouseListener(dockingListener);
347
348            dockingListener = null;
349        }
350
351        if ( propertyListener != null )
352        {
353            toolBar.removePropertyChangeListener(propertyListener);
354            propertyListener = null;  // removed in setFloating
355        }
356
357        if ( toolBarContListener != null )
358        {
359            toolBar.removeContainerListener( toolBarContListener );
360            toolBarContListener = null;
361        }
362
363        if ( toolBarFocusListener != null )
364        {
365            // Remove focus listener from all components in toolbar
366            Component[] components = toolBar.getComponents();
367
368            for (Component component : components) {
369                component.removeFocusListener(toolBarFocusListener);
370            }
371
372            toolBarFocusListener = null;
373        }
374        handler = null;
375    }
376
377    /**
378     * Registers keyboard actions.
379     */
380    protected void installKeyboardActions( )
381    {
382        InputMap km = getInputMap(JComponent.
383                                  WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
384
385        SwingUtilities.replaceUIInputMap(toolBar, JComponent.
386                                         WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
387                                         km);
388
389    LazyActionMap.installLazyActionMap(toolBar, BasicToolBarUI.class,
390            "ToolBar.actionMap");
391    }
392
393    InputMap getInputMap(int condition) {
394        if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) {
395            return (InputMap)DefaultLookup.get(toolBar, this,
396                    "ToolBar.ancestorInputMap");
397        }
398        return null;
399    }
400
401    static void loadActionMap(LazyActionMap map) {
402        map.put(new Actions(Actions.NAVIGATE_RIGHT));
403        map.put(new Actions(Actions.NAVIGATE_LEFT));
404        map.put(new Actions(Actions.NAVIGATE_UP));
405        map.put(new Actions(Actions.NAVIGATE_DOWN));
406    }
407
408    /**
409     * Unregisters keyboard actions.
410     */
411    protected void uninstallKeyboardActions( )
412    {
413        SwingUtilities.replaceUIActionMap(toolBar, null);
414        SwingUtilities.replaceUIInputMap(toolBar, JComponent.
415                                         WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
416                                         null);
417    }
418
419    /**
420     * Navigates the focused component.
421     *
422     * @param direction a direction
423     */
424    @SuppressWarnings("deprecation")
425    protected void navigateFocusedComp(int direction)
426    {
427        int nComp = toolBar.getComponentCount();
428        int j;
429
430        switch ( direction )
431        {
432            case EAST:
433            case SOUTH:
434
435                if ( focusedCompIndex < 0 || focusedCompIndex >= nComp ) break;
436
437                j = focusedCompIndex + 1;
438
439                while ( j != focusedCompIndex )
440                {
441                    if ( j >= nComp ) j = 0;
442                    Component comp = toolBar.getComponentAtIndex( j++ );
443
444                    if ( comp != null && comp.isFocusTraversable() && comp.isEnabled() )
445                    {
446                        comp.requestFocus();
447                        break;
448                    }
449                }
450
451                break;
452
453            case WEST:
454            case NORTH:
455
456                if ( focusedCompIndex < 0 || focusedCompIndex >= nComp ) break;
457
458                j = focusedCompIndex - 1;
459
460                while ( j != focusedCompIndex )
461                {
462                    if ( j < 0 ) j = nComp - 1;
463                    Component comp = toolBar.getComponentAtIndex( j-- );
464
465                    if ( comp != null && comp.isFocusTraversable() && comp.isEnabled() )
466                    {
467                        comp.requestFocus();
468                        break;
469                    }
470                }
471
472                break;
473
474            default:
475                break;
476        }
477    }
478
479    /**
480     * Creates a rollover border for toolbar components. The
481     * rollover border will be installed if rollover borders are
482     * enabled.
483     * <p>
484     * Override this method to provide an alternate rollover border.
485     *
486     * @return a rollover border for toolbar components
487     * @since 1.4
488     */
489    protected Border createRolloverBorder() {
490        Object border = UIManager.get("ToolBar.rolloverBorder");
491        if (border != null) {
492            return (Border)border;
493        }
494        UIDefaults table = UIManager.getLookAndFeelDefaults();
495        return new CompoundBorder(new BasicBorders.RolloverButtonBorder(
496                                           table.getColor("controlShadow"),
497                                           table.getColor("controlDkShadow"),
498                                           table.getColor("controlHighlight"),
499                                           table.getColor("controlLtHighlight")),
500                                  new BasicBorders.RolloverMarginBorder());
501    }
502
503    /**
504     * Creates the non rollover border for toolbar components. This
505     * border will be installed as the border for components added
506     * to the toolbar if rollover borders are not enabled.
507     * <p>
508     * Override this method to provide an alternate rollover border.
509     *
510     * @return the non rollover border for toolbar components
511     * @since 1.4
512     */
513    protected Border createNonRolloverBorder() {
514        Object border = UIManager.get("ToolBar.nonrolloverBorder");
515        if (border != null) {
516            return (Border)border;
517        }
518        UIDefaults table = UIManager.getLookAndFeelDefaults();
519        return new CompoundBorder(new BasicBorders.ButtonBorder(
520                                           table.getColor("Button.shadow"),
521                                           table.getColor("Button.darkShadow"),
522                                           table.getColor("Button.light"),
523                                           table.getColor("Button.highlight")),
524                                  new BasicBorders.RolloverMarginBorder());
525    }
526
527    /**
528     * Creates a non rollover border for Toggle buttons in the toolbar.
529     */
530    private Border createNonRolloverToggleBorder() {
531        UIDefaults table = UIManager.getLookAndFeelDefaults();
532        return new CompoundBorder(new BasicBorders.RadioButtonBorder(
533                                           table.getColor("ToggleButton.shadow"),
534                                           table.getColor("ToggleButton.darkShadow"),
535                                           table.getColor("ToggleButton.light"),
536                                           table.getColor("ToggleButton.highlight")),
537                                  new BasicBorders.RolloverMarginBorder());
538    }
539
540    /**
541     * No longer used, use BasicToolBarUI.createFloatingWindow(JToolBar)
542     *
543     * @param toolbar an instance of {@code JToolBar}
544     * @return an instance of {@code JFrame}
545     * @see #createFloatingWindow
546     */
547    protected JFrame createFloatingFrame(JToolBar toolbar) {
548        Window window = SwingUtilities.getWindowAncestor(toolbar);
549        @SuppressWarnings("serial") // anonymous class
550        JFrame frame = new JFrame(toolbar.getName(),
551                                  (window != null) ? window.getGraphicsConfiguration() : null) {
552            // Override createRootPane() to automatically resize
553            // the frame when contents change
554            protected JRootPane createRootPane() {
555                @SuppressWarnings("serial") // anonymous class
556                JRootPane rootPane = new JRootPane() {
557                    private boolean packing = false;
558
559                    public void validate() {
560                        super.validate();
561                        if (!packing) {
562                            packing = true;
563                            pack();
564                            packing = false;
565                        }
566                    }
567                };
568                rootPane.setOpaque(true);
569                return rootPane;
570            }
571        };
572        frame.getRootPane().setName("ToolBar.FloatingFrame");
573        frame.setResizable(false);
574        WindowListener wl = createFrameListener();
575        frame.addWindowListener(wl);
576        return frame;
577    }
578
579    /**
580     * Creates a window which contains the toolbar after it has been
581     * dragged out from its container
582     *
583     * @param toolbar an instance of {@code JToolBar}
584     * @return a {@code RootPaneContainer} object, containing the toolbar
585     * @since 1.4
586     */
587    protected RootPaneContainer createFloatingWindow(JToolBar toolbar) {
588        @SuppressWarnings("serial") // Superclass is not serializable across versions
589        class ToolBarDialog extends JDialog {
590            public ToolBarDialog(Frame owner, String title, boolean modal) {
591                super(owner, title, modal);
592            }
593
594            public ToolBarDialog(Dialog owner, String title, boolean modal) {
595                super(owner, title, modal);
596            }
597
598            // Override createRootPane() to automatically resize
599            // the frame when contents change
600            protected JRootPane createRootPane() {
601                @SuppressWarnings("serial") // anonymous class
602                JRootPane rootPane = new JRootPane() {
603                    private boolean packing = false;
604
605                    public void validate() {
606                        super.validate();
607                        if (!packing) {
608                            packing = true;
609                            pack();
610                            packing = false;
611                        }
612                    }
613                };
614                rootPane.setOpaque(true);
615                return rootPane;
616            }
617        }
618
619        JDialog dialog;
620        Window window = SwingUtilities.getWindowAncestor(toolbar);
621        if (window instanceof Frame) {
622            dialog = new ToolBarDialog((Frame)window, toolbar.getName(), false);
623        } else if (window instanceof Dialog) {
624            dialog = new ToolBarDialog((Dialog)window, toolbar.getName(), false);
625        } else {
626            dialog = new ToolBarDialog((Frame)null, toolbar.getName(), false);
627        }
628
629        dialog.getRootPane().setName("ToolBar.FloatingWindow");
630        dialog.setTitle(toolbar.getName());
631        dialog.setResizable(false);
632        WindowListener wl = createFrameListener();
633        dialog.addWindowListener(wl);
634        return dialog;
635    }
636
637    /**
638     * Returns an instance of {@code DragWindow}.
639     *
640     * @param toolbar an instance of {@code JToolBar}
641     * @return an instance of {@code DragWindow}
642     */
643    protected DragWindow createDragWindow(JToolBar toolbar) {
644        Window frame = null;
645        if(toolBar != null) {
646            Container p;
647            for(p = toolBar.getParent() ; p != null && !(p instanceof Window) ;
648                p = p.getParent());
649            if(p != null && p instanceof Window)
650                frame = (Window) p;
651        }
652        if(floatingToolBar == null) {
653            floatingToolBar = createFloatingWindow(toolBar);
654        }
655        if (floatingToolBar instanceof Window) frame = (Window) floatingToolBar;
656        DragWindow dragWindow = new DragWindow(frame);
657        return dragWindow;
658    }
659
660    /**
661     * Returns a flag to determine whether rollover button borders
662     * are enabled.
663     *
664     * @return true if rollover borders are enabled; false otherwise
665     * @see #setRolloverBorders
666     * @since 1.4
667     */
668    public boolean isRolloverBorders() {
669        return rolloverBorders;
670    }
671
672    /**
673     * Sets the flag for enabling rollover borders on the toolbar and it will
674     * also install the appropriate border depending on the state of the flag.
675     *
676     * @param rollover if true, rollover borders are installed.
677     *        Otherwise non-rollover borders are installed
678     * @see #isRolloverBorders
679     * @since 1.4
680     */
681    public void setRolloverBorders( boolean rollover ) {
682        rolloverBorders = rollover;
683
684        if ( rolloverBorders )  {
685            installRolloverBorders( toolBar );
686        } else  {
687            installNonRolloverBorders( toolBar );
688        }
689    }
690
691    /**
692     * Installs rollover borders on all the child components of the JComponent.
693     * <p>
694     * This is a convenience method to call <code>setBorderToRollover</code>
695     * for each child component.
696     *
697     * @param c container which holds the child components (usually a JToolBar)
698     * @see #setBorderToRollover
699     * @since 1.4
700     */
701    protected void installRolloverBorders ( JComponent c )  {
702        // Put rollover borders on buttons
703        Component[] components = c.getComponents();
704
705        for (Component component : components) {
706            if (component instanceof JComponent) {
707                ((JComponent) component).updateUI();
708                setBorderToRollover(component);
709            }
710        }
711    }
712
713    /**
714     * Installs non-rollover borders on all the child components of the JComponent.
715     * A non-rollover border is the border that is installed on the child component
716     * while it is in the toolbar.
717     * <p>
718     * This is a convenience method to call <code>setBorderToNonRollover</code>
719     * for each child component.
720     *
721     * @param c container which holds the child components (usually a JToolBar)
722     * @see #setBorderToNonRollover
723     * @since 1.4
724     */
725    protected void installNonRolloverBorders ( JComponent c )  {
726        // Put non-rollover borders on buttons. These borders reduce the margin.
727        Component[] components = c.getComponents();
728
729        for (Component component : components) {
730            if (component instanceof JComponent) {
731                ((JComponent) component).updateUI();
732                setBorderToNonRollover(component);
733            }
734        }
735    }
736
737    /**
738     * Installs normal borders on all the child components of the JComponent.
739     * A normal border is the original border that was installed on the child
740     * component before it was added to the toolbar.
741     * <p>
742     * This is a convenience method to call <code>setBorderNormal</code>
743     * for each child component.
744     *
745     * @param c container which holds the child components (usually a JToolBar)
746     * @see #setBorderToNonRollover
747     * @since 1.4
748     */
749    protected void installNormalBorders ( JComponent c )  {
750        // Put back the normal borders on buttons
751        Component[] components = c.getComponents();
752
753        for (Component component : components) {
754            setBorderToNormal(component);
755        }
756    }
757
758    /**
759     * Sets the border of the component to have a rollover border which
760     * was created by the {@link #createRolloverBorder} method.
761     *
762     * @param c component which will have a rollover border installed
763     * @see #createRolloverBorder
764     * @since 1.4
765     */
766    protected void setBorderToRollover(Component c) {
767        if (c instanceof AbstractButton) {
768            AbstractButton b = (AbstractButton)c;
769
770            Border border = borderTable.get(b);
771            if (border == null || border instanceof UIResource) {
772                borderTable.put(b, b.getBorder());
773            }
774
775            // Only set the border if its the default border
776            if (b.getBorder() instanceof UIResource) {
777                b.setBorder(getRolloverBorder(b));
778            }
779
780            rolloverTable.put(b, b.isRolloverEnabled()?
781                              Boolean.TRUE: Boolean.FALSE);
782            b.setRolloverEnabled(true);
783        }
784    }
785
786    /**
787     * Returns a rollover border for the button.
788     *
789     * @param b the button to calculate the rollover border for
790     * @return the rollover border
791     * @see #setBorderToRollover
792     * @since 1.6
793     */
794    protected Border getRolloverBorder(AbstractButton b) {
795        return rolloverBorder;
796    }
797
798    /**
799     * Sets the border of the component to have a non-rollover border which
800     * was created by the {@link #createNonRolloverBorder} method.
801     *
802     * @param c component which will have a non-rollover border installed
803     * @see #createNonRolloverBorder
804     * @since 1.4
805     */
806    protected void setBorderToNonRollover(Component c) {
807        if (c instanceof AbstractButton) {
808            AbstractButton b = (AbstractButton)c;
809
810            Border border = borderTable.get(b);
811            if (border == null || border instanceof UIResource) {
812                borderTable.put(b, b.getBorder());
813            }
814
815            // Only set the border if its the default border
816            if (b.getBorder() instanceof UIResource) {
817                b.setBorder(getNonRolloverBorder(b));
818            }
819            rolloverTable.put(b, b.isRolloverEnabled()?
820                              Boolean.TRUE: Boolean.FALSE);
821            b.setRolloverEnabled(false);
822        }
823    }
824
825    /**
826     * Returns a non-rollover border for the button.
827     *
828     * @param b the button to calculate the non-rollover border for
829     * @return the non-rollover border
830     * @see #setBorderToNonRollover
831     * @since 1.6
832     */
833    protected Border getNonRolloverBorder(AbstractButton b) {
834        if (b instanceof JToggleButton) {
835            return nonRolloverToggleBorder;
836        } else {
837            return nonRolloverBorder;
838        }
839    }
840
841    /**
842     * Sets the border of the component to have a normal border.
843     * A normal border is the original border that was installed on the child
844     * component before it was added to the toolbar.
845     *
846     * @param c component which will have a normal border re-installed
847     * @see #createNonRolloverBorder
848     * @since 1.4
849     */
850    protected void setBorderToNormal(Component c) {
851        if (c instanceof AbstractButton) {
852            AbstractButton b = (AbstractButton)c;
853
854            Border border = borderTable.remove(b);
855            b.setBorder(border);
856
857            Boolean value = rolloverTable.remove(b);
858            if (value != null) {
859                b.setRolloverEnabled(value.booleanValue());
860            }
861        }
862    }
863
864    /**
865     * Sets the floating location.
866     *
867     * @param x an X coordinate
868     * @param y an Y coordinate
869     */
870    public void setFloatingLocation(int x, int y) {
871        floatingX = x;
872        floatingY = y;
873    }
874
875    /**
876     * Returns {@code true} if the {@code JToolBar} is floating
877     *
878     * @return {@code true} if the {@code JToolBar} is floating
879     */
880    public boolean isFloating() {
881        return floating;
882    }
883
884    /**
885     * Sets the floating property.
886     *
887     * @param b {@code true} if the {@code JToolBar} is floating
888     * @param p the position
889     */
890    @SuppressWarnings("deprecation")
891    public void setFloating(boolean b, Point p) {
892        if (toolBar.isFloatable()) {
893            boolean visible = false;
894            Window ancestor = SwingUtilities.getWindowAncestor(toolBar);
895            if (ancestor != null) {
896                visible = ancestor.isVisible();
897            }
898            if (dragWindow != null)
899                dragWindow.setVisible(false);
900            this.floating = b;
901            if (floatingToolBar == null) {
902                floatingToolBar = createFloatingWindow(toolBar);
903            }
904            if (b == true)
905            {
906                if (dockingSource == null)
907                {
908                    dockingSource = toolBar.getParent();
909                    dockingSource.remove(toolBar);
910                }
911                constraintBeforeFloating = calculateConstraint();
912                if ( propertyListener != null )
913                    UIManager.addPropertyChangeListener( propertyListener );
914                floatingToolBar.getContentPane().add(toolBar,BorderLayout.CENTER);
915                if (floatingToolBar instanceof Window) {
916                    ((Window)floatingToolBar).pack();
917                    ((Window)floatingToolBar).setLocation(floatingX, floatingY);
918                    if (visible) {
919                        ((Window)floatingToolBar).show();
920                    } else {
921                        ancestor.addWindowListener(new WindowAdapter() {
922                            public void windowOpened(WindowEvent e) {
923                                ((Window)floatingToolBar).show();
924                            }
925                        });
926                    }
927                }
928            } else {
929                if (floatingToolBar == null)
930                    floatingToolBar = createFloatingWindow(toolBar);
931                if (floatingToolBar instanceof Window) ((Window)floatingToolBar).setVisible(false);
932                floatingToolBar.getContentPane().remove(toolBar);
933                String constraint = getDockingConstraint(dockingSource,
934                                                         p);
935                if (constraint == null) {
936                    constraint = BorderLayout.NORTH;
937                }
938                int orientation = mapConstraintToOrientation(constraint);
939                setOrientation(orientation);
940                if (dockingSource== null)
941                    dockingSource = toolBar.getParent();
942                if ( propertyListener != null )
943                    UIManager.removePropertyChangeListener( propertyListener );
944                dockingSource.add(constraint, toolBar);
945            }
946            dockingSource.invalidate();
947            Container dockingSourceParent = dockingSource.getParent();
948            if (dockingSourceParent != null)
949                dockingSourceParent.validate();
950            dockingSource.repaint();
951        }
952    }
953
954    private int mapConstraintToOrientation(String constraint)
955    {
956        int orientation = toolBar.getOrientation();
957
958        if ( constraint != null )
959        {
960            if ( constraint.equals(BorderLayout.EAST) || constraint.equals(BorderLayout.WEST) )
961                orientation = JToolBar.VERTICAL;
962            else if ( constraint.equals(BorderLayout.NORTH) || constraint.equals(BorderLayout.SOUTH) )
963                orientation = JToolBar.HORIZONTAL;
964        }
965
966        return orientation;
967    }
968
969    /**
970     * Sets the tool bar's orientation.
971     *
972     * @param orientation the new orientation
973     */
974    public void setOrientation(int orientation)
975    {
976        toolBar.setOrientation( orientation );
977
978        if (dragWindow !=null)
979            dragWindow.setOrientation(orientation);
980    }
981
982    /**
983     * Gets the color displayed when over a docking area
984     *
985     * @return the color displayed when over a docking area
986     */
987    public Color getDockingColor() {
988        return dockingColor;
989    }
990
991    /**
992     * Sets the color displayed when over a docking area
993     *
994     * @param c the new color
995     */
996   public void setDockingColor(Color c) {
997        this.dockingColor = c;
998    }
999
1000    /**
1001     * Gets the color displayed when over a floating area
1002     *
1003     * @return the color displayed when over a floating area
1004     */
1005    public Color getFloatingColor() {
1006        return floatingColor;
1007    }
1008
1009    /**
1010     * Sets the color displayed when over a floating area
1011     *
1012     * @param c the new color
1013     */
1014    public void setFloatingColor(Color c) {
1015        this.floatingColor = c;
1016    }
1017
1018    private boolean isBlocked(Component comp, Object constraint) {
1019        if (comp instanceof Container) {
1020            Container cont = (Container)comp;
1021            LayoutManager lm = cont.getLayout();
1022            if (lm instanceof BorderLayout) {
1023                BorderLayout blm = (BorderLayout)lm;
1024                Component c = blm.getLayoutComponent(cont, constraint);
1025                return (c != null && c != toolBar);
1026            }
1027        }
1028        return false;
1029    }
1030
1031    /**
1032     * Returns {@code true} if the {@code JToolBar} can dock at the given position.
1033     *
1034     * @param c a component
1035     * @param p a position
1036     * @return {@code true} if the {@code JToolBar} can dock at the given position
1037     */
1038    public boolean canDock(Component c, Point p) {
1039        return (p != null && getDockingConstraint(c, p) != null);
1040    }
1041
1042    private String calculateConstraint() {
1043        String constraint = null;
1044        LayoutManager lm = dockingSource.getLayout();
1045        if (lm instanceof BorderLayout) {
1046            constraint = (String)((BorderLayout)lm).getConstraints(toolBar);
1047        }
1048        return (constraint != null) ? constraint : constraintBeforeFloating;
1049    }
1050
1051
1052
1053    private String getDockingConstraint(Component c, Point p) {
1054        if (p == null) return constraintBeforeFloating;
1055        if (c.contains(p)) {
1056            dockingSensitivity = (toolBar.getOrientation() == JToolBar.HORIZONTAL)
1057                                                ? toolBar.getSize().height
1058                                                : toolBar.getSize().width;
1059            // North  (Base distance on height for now!)
1060            if (p.y < dockingSensitivity && !isBlocked(c, BorderLayout.NORTH)) {
1061                return BorderLayout.NORTH;
1062            }
1063            // East  (Base distance on height for now!)
1064            if (p.x >= c.getWidth() - dockingSensitivity && !isBlocked(c, BorderLayout.EAST)) {
1065                return BorderLayout.EAST;
1066            }
1067            // West  (Base distance on height for now!)
1068            if (p.x < dockingSensitivity && !isBlocked(c, BorderLayout.WEST)) {
1069                return BorderLayout.WEST;
1070            }
1071            if (p.y >= c.getHeight() - dockingSensitivity && !isBlocked(c, BorderLayout.SOUTH)) {
1072                return BorderLayout.SOUTH;
1073            }
1074        }
1075        return null;
1076    }
1077
1078    /**
1079     * The method is used to drag {@code DragWindow} during the {@code JToolBar}
1080     * is being dragged.
1081     *
1082     * @param position the relative to the {@code JTollBar} position
1083     * @param origin the screen position of {@code JToolBar} before dragging
1084     */
1085    @SuppressWarnings("deprecation")
1086    protected void dragTo(Point position, Point origin)
1087    {
1088        if (toolBar.isFloatable())
1089        {
1090          try
1091          {
1092            if (dragWindow == null)
1093                dragWindow = createDragWindow(toolBar);
1094            Point offset = dragWindow.getOffset();
1095            if (offset == null) {
1096                Dimension size = toolBar.getPreferredSize();
1097                offset = new Point(size.width/2, size.height/2);
1098                dragWindow.setOffset(offset);
1099            }
1100            Point global = new Point(origin.x+ position.x,
1101                                     origin.y+position.y);
1102            Point dragPoint = new Point(global.x- offset.x,
1103                                        global.y- offset.y);
1104            if (dockingSource == null)
1105                dockingSource = toolBar.getParent();
1106                constraintBeforeFloating = calculateConstraint();
1107            Point dockingPosition = dockingSource.getLocationOnScreen();
1108            Point comparisonPoint = new Point(global.x-dockingPosition.x,
1109                                              global.y-dockingPosition.y);
1110            if (canDock(dockingSource, comparisonPoint)) {
1111                dragWindow.setBackground(getDockingColor());
1112                String constraint = getDockingConstraint(dockingSource,
1113                                                         comparisonPoint);
1114                int orientation = mapConstraintToOrientation(constraint);
1115                dragWindow.setOrientation(orientation);
1116                dragWindow.setBorderColor(dockingBorderColor);
1117            } else {
1118                dragWindow.setBackground(getFloatingColor());
1119                dragWindow.setBorderColor(floatingBorderColor);
1120                dragWindow.setOrientation(toolBar.getOrientation());
1121            }
1122
1123            dragWindow.setLocation(dragPoint.x, dragPoint.y);
1124            if (dragWindow.isVisible() == false) {
1125                Dimension size = toolBar.getPreferredSize();
1126                dragWindow.setSize(size.width, size.height);
1127                dragWindow.show();
1128            }
1129          }
1130          catch ( IllegalComponentStateException e )
1131          {
1132          }
1133        }
1134    }
1135
1136    /**
1137     * The method is called at end of dragging to place the frame in either
1138     * its original place or in its floating frame.
1139     *
1140     * @param position the relative to the {@code JTollBar} position
1141     * @param origin the screen position of {@code JToolBar} before dragging
1142     */
1143    protected void floatAt(Point position, Point origin)
1144    {
1145        if(toolBar.isFloatable())
1146        {
1147          try
1148          {
1149            Point offset = dragWindow.getOffset();
1150            if (offset == null) {
1151                offset = position;
1152                dragWindow.setOffset(offset);
1153            }
1154            Point global = new Point(origin.x+ position.x,
1155                                     origin.y+position.y);
1156            setFloatingLocation(global.x-offset.x,
1157                                global.y-offset.y);
1158            if (dockingSource != null) {
1159                Point dockingPosition = dockingSource.getLocationOnScreen();
1160                Point comparisonPoint = new Point(global.x-dockingPosition.x,
1161                                                  global.y-dockingPosition.y);
1162                if (canDock(dockingSource, comparisonPoint)) {
1163                    setFloating(false, comparisonPoint);
1164                } else {
1165                    setFloating(true, null);
1166                }
1167            } else {
1168                setFloating(true, null);
1169            }
1170            dragWindow.setOffset(null);
1171          }
1172          catch ( IllegalComponentStateException e )
1173          {
1174          }
1175        }
1176    }
1177
1178    private Handler getHandler() {
1179        if (handler == null) {
1180            handler = new Handler();
1181        }
1182        return handler;
1183    }
1184
1185    /**
1186     * Returns an instance of {@code ContainerListener}.
1187     *
1188     * @return an instance of {@code ContainerListener}
1189     */
1190    protected ContainerListener createToolBarContListener( )
1191    {
1192        return getHandler();
1193    }
1194
1195    /**
1196     * Returns an instance of {@code FocusListener}.
1197     *
1198     * @return an instance of {@code FocusListener}
1199     */
1200    protected FocusListener createToolBarFocusListener( )
1201    {
1202        return getHandler();
1203    }
1204
1205    /**
1206     * Returns an instance of {@code PropertyChangeListener}.
1207     *
1208     * @return an instance of {@code PropertyChangeListener}
1209     */
1210    protected PropertyChangeListener createPropertyListener()
1211    {
1212        return getHandler();
1213    }
1214
1215    /**
1216     * Returns an instance of {@code MouseInputListener}.
1217     *
1218     * @return an instance of {@code MouseInputListener}
1219     */
1220    protected MouseInputListener createDockingListener( ) {
1221        getHandler().tb = toolBar;
1222        return getHandler();
1223    }
1224
1225    /**
1226     * Constructs a new instance of {@code WindowListener}.
1227     *
1228     * @return a new instance of {@code WindowListener}
1229     */
1230    protected WindowListener createFrameListener() {
1231        return new FrameListener();
1232    }
1233
1234    /**
1235     * Paints the contents of the window used for dragging.
1236     *
1237     * @param g Graphics to paint to.
1238     * @throws NullPointerException is <code>g</code> is null
1239     * @since 1.5
1240     */
1241    protected void paintDragWindow(Graphics g) {
1242        g.setColor(dragWindow.getBackground());
1243        int w = dragWindow.getWidth();
1244        int h = dragWindow.getHeight();
1245        g.fillRect(0, 0, w, h);
1246        g.setColor(dragWindow.getBorderColor());
1247        g.drawRect(0, 0, w - 1, h - 1);
1248    }
1249
1250
1251    private static class Actions extends UIAction {
1252        private static final String NAVIGATE_RIGHT = "navigateRight";
1253        private static final String NAVIGATE_LEFT = "navigateLeft";
1254        private static final String NAVIGATE_UP = "navigateUp";
1255        private static final String NAVIGATE_DOWN = "navigateDown";
1256
1257        public Actions(String name) {
1258            super(name);
1259        }
1260
1261        public void actionPerformed(ActionEvent evt) {
1262            String key = getName();
1263            JToolBar toolBar = (JToolBar)evt.getSource();
1264            BasicToolBarUI ui = (BasicToolBarUI)BasicLookAndFeel.getUIOfType(
1265                     toolBar.getUI(), BasicToolBarUI.class);
1266
1267            if (NAVIGATE_RIGHT == key) {
1268                ui.navigateFocusedComp(EAST);
1269            } else if (NAVIGATE_LEFT == key) {
1270                ui.navigateFocusedComp(WEST);
1271            } else if (NAVIGATE_UP == key) {
1272                ui.navigateFocusedComp(NORTH);
1273            } else if (NAVIGATE_DOWN == key) {
1274                ui.navigateFocusedComp(SOUTH);
1275            }
1276        }
1277    }
1278
1279
1280    private class Handler implements ContainerListener,
1281            FocusListener, MouseInputListener, PropertyChangeListener {
1282
1283        //
1284        // ContainerListener
1285        //
1286        public void componentAdded(ContainerEvent evt) {
1287            Component c = evt.getChild();
1288
1289            if (toolBarFocusListener != null) {
1290                c.addFocusListener(toolBarFocusListener);
1291            }
1292
1293            if (isRolloverBorders()) {
1294                setBorderToRollover(c);
1295            } else {
1296                setBorderToNonRollover(c);
1297            }
1298        }
1299
1300        public void componentRemoved(ContainerEvent evt) {
1301            Component c = evt.getChild();
1302
1303            if (toolBarFocusListener != null) {
1304                c.removeFocusListener(toolBarFocusListener);
1305            }
1306
1307            // Revert the button border
1308            setBorderToNormal(c);
1309        }
1310
1311
1312        //
1313        // FocusListener
1314        //
1315        public void focusGained(FocusEvent evt) {
1316            Component c = evt.getComponent();
1317            focusedCompIndex = toolBar.getComponentIndex(c);
1318        }
1319
1320        public void focusLost(FocusEvent evt) { }
1321
1322
1323        //
1324        // MouseInputListener (DockingListener)
1325        //
1326        JToolBar tb;
1327        boolean isDragging = false;
1328        Point origin = null;
1329
1330        public void mousePressed(MouseEvent evt) {
1331            if (!tb.isEnabled()) {
1332                return;
1333            }
1334            isDragging = false;
1335        }
1336
1337        public void mouseReleased(MouseEvent evt) {
1338            if (!tb.isEnabled()) {
1339                return;
1340            }
1341            if (isDragging) {
1342                Point position = evt.getPoint();
1343                if (origin == null)
1344                    origin = evt.getComponent().getLocationOnScreen();
1345                floatAt(position, origin);
1346            }
1347            origin = null;
1348            isDragging = false;
1349        }
1350
1351        public void mouseDragged(MouseEvent evt) {
1352            if (!tb.isEnabled()) {
1353                return;
1354            }
1355            isDragging = true;
1356            Point position = evt.getPoint();
1357            if (origin == null) {
1358                origin = evt.getComponent().getLocationOnScreen();
1359            }
1360            dragTo(position, origin);
1361        }
1362
1363        public void mouseClicked(MouseEvent evt) {}
1364        public void mouseEntered(MouseEvent evt) {}
1365        public void mouseExited(MouseEvent evt) {}
1366        public void mouseMoved(MouseEvent evt) {}
1367
1368
1369        //
1370        // PropertyChangeListener
1371        //
1372        public void propertyChange(PropertyChangeEvent evt) {
1373            String propertyName = evt.getPropertyName();
1374            if (propertyName == "lookAndFeel") {
1375                toolBar.updateUI();
1376            } else if (propertyName == "orientation") {
1377                // Search for JSeparator components and change it's orientation
1378                // to match the toolbar and flip it's orientation.
1379                Component[] components = toolBar.getComponents();
1380                int orientation = ((Integer)evt.getNewValue()).intValue();
1381                JToolBar.Separator separator;
1382
1383                for (int i = 0; i < components.length; ++i) {
1384                    if (components[i] instanceof JToolBar.Separator) {
1385                        separator = (JToolBar.Separator)components[i];
1386                        if ((orientation == JToolBar.HORIZONTAL)) {
1387                            separator.setOrientation(JSeparator.VERTICAL);
1388                        } else {
1389                            separator.setOrientation(JSeparator.HORIZONTAL);
1390                        }
1391                        Dimension size = separator.getSeparatorSize();
1392                        if (size != null && size.width != size.height) {
1393                            // Flip the orientation.
1394                            Dimension newSize =
1395                                new Dimension(size.height, size.width);
1396                            separator.setSeparatorSize(newSize);
1397                        }
1398                    }
1399                }
1400            } else if (propertyName == IS_ROLLOVER) {
1401                installNormalBorders(toolBar);
1402                setRolloverBorders(((Boolean)evt.getNewValue()).booleanValue());
1403            }
1404        }
1405    }
1406
1407    /**
1408     * The class listens for window events.
1409     */
1410    protected class FrameListener extends WindowAdapter {
1411        public void windowClosing(WindowEvent w) {
1412            if (toolBar.isFloatable()) {
1413                if (dragWindow != null)
1414                    dragWindow.setVisible(false);
1415                floating = false;
1416                if (floatingToolBar == null)
1417                    floatingToolBar = createFloatingWindow(toolBar);
1418                if (floatingToolBar instanceof Window) ((Window)floatingToolBar).setVisible(false);
1419                floatingToolBar.getContentPane().remove(toolBar);
1420                String constraint = constraintBeforeFloating;
1421                if (toolBar.getOrientation() == JToolBar.HORIZONTAL) {
1422                    if (constraint == "West" || constraint == "East") {
1423                        constraint = "North";
1424                    }
1425                } else {
1426                    if (constraint == "North" || constraint == "South") {
1427                        constraint = "West";
1428                    }
1429                }
1430                if (dockingSource == null)
1431                    dockingSource = toolBar.getParent();
1432                if (propertyListener != null)
1433                    UIManager.removePropertyChangeListener(propertyListener);
1434                dockingSource.add(toolBar, constraint);
1435                dockingSource.invalidate();
1436                Container dockingSourceParent = dockingSource.getParent();
1437                if (dockingSourceParent != null)
1438                        dockingSourceParent.validate();
1439                dockingSource.repaint();
1440            }
1441        }
1442
1443    }
1444
1445    /**
1446     * The class listens for component events.
1447     */
1448    protected class ToolBarContListener implements ContainerListener {
1449        // NOTE: This class exists only for backward compatibility. All
1450        // its functionality has been moved into Handler. If you need to add
1451        // new functionality add it to the Handler, but make sure this
1452        // class calls into the Handler.
1453        public void componentAdded( ContainerEvent e )  {
1454            getHandler().componentAdded(e);
1455        }
1456
1457        public void componentRemoved( ContainerEvent e ) {
1458            getHandler().componentRemoved(e);
1459        }
1460
1461    }
1462
1463    /**
1464     * The class listens for focus events.
1465     */
1466    protected class ToolBarFocusListener implements FocusListener {
1467        // NOTE: This class exists only for backward compatibility. All
1468        // its functionality has been moved into Handler. If you need to add
1469        // new functionality add it to the Handler, but make sure this
1470        // class calls into the Handler.
1471        public void focusGained( FocusEvent e ) {
1472            getHandler().focusGained(e);
1473            }
1474
1475        public void focusLost( FocusEvent e ) {
1476            getHandler().focusLost(e);
1477            }
1478    }
1479
1480    /**
1481     * The class listens for property changed events.
1482     */
1483    protected class PropertyListener implements PropertyChangeListener {
1484        // NOTE: This class exists only for backward compatibility. All
1485        // its functionality has been moved into Handler. If you need to add
1486        // new functionality add it to the Handler, but make sure this
1487        // class calls into the Handler.
1488        public void propertyChange( PropertyChangeEvent e ) {
1489            getHandler().propertyChange(e);
1490            }
1491    }
1492
1493    /**
1494     * This class should be treated as a &quot;protected&quot; inner class.
1495     * Instantiate it only within subclasses of BasicToolBarUI.
1496     */
1497    public class DockingListener implements MouseInputListener {
1498        // NOTE: This class exists only for backward compatibility. All
1499        // its functionality has been moved into Handler. If you need to add
1500        // new functionality add it to the Handler, but make sure this
1501        // class calls into the Handler.
1502        /**
1503         * The instance of {@code JToolBar}.
1504         */
1505        protected JToolBar toolBar;
1506        /**
1507         * {@code true} if the {@code JToolBar} is being dragged.
1508         */
1509        protected boolean isDragging = false;
1510        /**
1511         * The origin point.
1512         */
1513        protected Point origin = null;
1514
1515        /**
1516         * Constructs a new instance of {@code DockingListener}.
1517         *
1518         * @param t an instance of {@code JToolBar}
1519         */
1520        public DockingListener(JToolBar t) {
1521            this.toolBar = t;
1522            getHandler().tb = t;
1523        }
1524
1525        public void mouseClicked(MouseEvent e) {
1526        getHandler().mouseClicked(e);
1527    }
1528
1529        public void mousePressed(MouseEvent e) {
1530        getHandler().tb = toolBar;
1531        getHandler().mousePressed(e);
1532        isDragging = getHandler().isDragging;
1533        }
1534
1535        public void mouseReleased(MouseEvent e) {
1536        getHandler().tb = toolBar;
1537        getHandler().isDragging = isDragging;
1538        getHandler().origin = origin;
1539        getHandler().mouseReleased(e);
1540        isDragging = getHandler().isDragging;
1541        origin = getHandler().origin;
1542        }
1543
1544        public void mouseEntered(MouseEvent e) {
1545        getHandler().mouseEntered(e);
1546    }
1547
1548        public void mouseExited(MouseEvent e) {
1549        getHandler().mouseExited(e);
1550    }
1551
1552        public void mouseDragged(MouseEvent e) {
1553        getHandler().tb = toolBar;
1554        getHandler().origin = origin;
1555        getHandler().mouseDragged(e);
1556        isDragging = getHandler().isDragging;
1557        origin = getHandler().origin;
1558        }
1559
1560        public void mouseMoved(MouseEvent e) {
1561        getHandler().mouseMoved(e);
1562        }
1563    }
1564
1565    /**
1566     * The window which appears during dragging the {@code JToolBar}.
1567     */
1568    @SuppressWarnings("serial") // Same-version serialization only
1569    protected class DragWindow extends Window
1570    {
1571        Color borderColor = Color.gray;
1572        int orientation = toolBar.getOrientation();
1573        Point offset; // offset of the mouse cursor inside the DragWindow
1574
1575        DragWindow(Window w) {
1576            super(w);
1577        }
1578
1579    /**
1580     * Returns the orientation of the toolbar window when the toolbar is
1581     * floating. The orientation is either one of <code>JToolBar.HORIZONTAL</code>
1582     * or <code>JToolBar.VERTICAL</code>.
1583     *
1584     * @return the orientation of the toolbar window
1585     * @since 1.6
1586     */
1587    public int getOrientation() {
1588        return orientation;
1589    }
1590
1591        /**
1592         * Sets the orientation.
1593         *
1594         * @param o the new orientation
1595         */
1596        public void setOrientation(int o) {
1597            if(isShowing()) {
1598                if (o == this.orientation)
1599                    return;
1600                this.orientation = o;
1601                Dimension size = getSize();
1602                setSize(new Dimension(size.height, size.width));
1603                if (offset!=null) {
1604                    if( BasicGraphicsUtils.isLeftToRight(toolBar) ) {
1605                        setOffset(new Point(offset.y, offset.x));
1606                    } else if( o == JToolBar.HORIZONTAL ) {
1607                        setOffset(new Point( size.height-offset.y, offset.x));
1608                    } else {
1609                        setOffset(new Point(offset.y, size.width-offset.x));
1610                    }
1611                }
1612                repaint();
1613            }
1614        }
1615
1616        /**
1617         * Returns the offset.
1618         *
1619         * @return the offset
1620         */
1621        public Point getOffset() {
1622            return offset;
1623        }
1624
1625        /**
1626         * Sets the offset.
1627         *
1628         * @param p the new offset
1629         */
1630        public void setOffset(Point p) {
1631            this.offset = p;
1632        }
1633
1634        /**
1635         * Sets the border color.
1636         *
1637         * @param c the new border color
1638         */
1639        public void setBorderColor(Color c) {
1640            if (this.borderColor == c)
1641                return;
1642            this.borderColor = c;
1643            repaint();
1644        }
1645
1646        /**
1647         * Returns the border color.
1648         *
1649         * @return the border color
1650         */
1651        public Color getBorderColor() {
1652            return this.borderColor;
1653        }
1654
1655        public void paint(Graphics g) {
1656            paintDragWindow(g);
1657            // Paint the children
1658            super.paint(g);
1659        }
1660        public Insets getInsets() {
1661            return new Insets(1,1,1,1);
1662        }
1663    }
1664}
1665