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