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