1 /* JToolBar.java -- 2 Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc. 3 4 This file is part of GNU Classpath. 5 6 GNU Classpath is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 GNU Classpath is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GNU Classpath; see the file COPYING. If not, write to the 18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 02110-1301 USA. 20 21 Linking this library statically or dynamically with other modules is 22 making a combined work based on this library. Thus, the terms and 23 conditions of the GNU General Public License cover the whole 24 combination. 25 26 As a special exception, the copyright holders of this library give you 27 permission to link this library with independent modules to produce an 28 executable, regardless of the license terms of these independent 29 modules, and to copy and distribute the resulting executable under 30 terms of your choice, provided that you also meet, for each linked 31 independent module, the terms and conditions of the license of that 32 module. An independent module is a module which is not derived from 33 or based on this library. If you modify this library, you may extend 34 this exception to your version of the library, but you are not 35 obligated to do so. If you do not wish to do so, delete this 36 exception statement from your version. */ 37 38 39 package javax.swing; 40 41 import gnu.java.lang.CPStringBuilder; 42 43 import java.awt.Component; 44 import java.awt.Container; 45 import java.awt.Dimension; 46 import java.awt.Graphics; 47 import java.awt.Insets; 48 import java.awt.LayoutManager; 49 import java.beans.PropertyChangeListener; 50 51 import javax.accessibility.Accessible; 52 import javax.accessibility.AccessibleContext; 53 import javax.accessibility.AccessibleRole; 54 import javax.accessibility.AccessibleStateSet; 55 import javax.swing.plaf.ToolBarUI; 56 57 /** 58 * JToolBar is a component that provides a toolbar to Swing programs. Users 59 * can add buttons (or actions that will be represented by JButtons) as well 60 * as other components to the JToolBar. JToolBars can be dragged in and out 61 * of their parent components. If the JToolBar is dragged out of the parent, 62 * then it will be displayed in its own RootPaneContainer. For dragging to 63 * work properly, JToolBars need to be placed in a Container that has a 64 * BorderLayout. That parent Container cannot have components in the NORTH, 65 * EAST, SOUTH, or WEST components (that is not the JToolBar). 66 */ 67 public class JToolBar extends JComponent implements SwingConstants, Accessible 68 { 69 /** 70 * Provides the accessibility features for the <code>JToolBar</code> 71 * component. 72 */ 73 protected class AccessibleJToolBar extends AccessibleJComponent 74 { 75 private static final long serialVersionUID = -5516888265903814215L; 76 77 /** 78 * Creates a new <code>AccessibleJToolBar</code> instance. 79 */ AccessibleJToolBar()80 protected AccessibleJToolBar() 81 { 82 // Nothing to do here. 83 } 84 85 /** 86 * Returns a set containing the current state of the {@link JToolBar} 87 * component. The current implementation simply calls the superclass. 88 * 89 * @return The accessible state set. 90 */ getAccessibleStateSet()91 public AccessibleStateSet getAccessibleStateSet() 92 { 93 // running tests against the reference implementation, I was unable 94 // to find any state information that is set specifically by the 95 // tool bar... 96 return super.getAccessibleStateSet(); 97 } 98 99 /** 100 * Returns the accessible role for the <code>JToolBar</code> component. 101 * 102 * @return {@link AccessibleRole#TOOL_BAR}. 103 */ getAccessibleRole()104 public AccessibleRole getAccessibleRole() 105 { 106 return AccessibleRole.TOOL_BAR; 107 } 108 } 109 110 /** 111 * This is the private JToolBar layout manager. 112 */ 113 private class DefaultToolBarLayout implements LayoutManager 114 { 115 /** 116 * This method is called when a new component is added to the container. 117 * 118 * @param name The name of the component added. 119 * @param comp The component that was added. 120 */ addLayoutComponent(String name, Component comp)121 public void addLayoutComponent(String name, Component comp) 122 { 123 // Do nothing. 124 } 125 126 /** 127 * This method is called to lay out the given container to position and 128 * size the child components. 129 * 130 * @param c The container to lay out. 131 * 132 * @throws Error DOCUMENT ME! 133 */ layoutContainer(Container c)134 public void layoutContainer(Container c) 135 { 136 if (! (c instanceof JToolBar)) 137 throw new Error("DefaultToolBarLayout can only be used on JToolBars."); 138 Insets insets = getInsets(); 139 Insets margin = getMargin(); 140 int middle; 141 if (margin != null) 142 { 143 insets.left += margin.left; 144 insets.top += margin.top; 145 insets.bottom += margin.bottom; 146 insets.right += margin.right; 147 } 148 Component[] components = c.getComponents(); 149 Dimension tdims = c.getSize(); 150 int start = 0; 151 Dimension pref; 152 153 if (getOrientation() == SwingUtilities.HORIZONTAL) 154 { 155 start += insets.left; 156 for (int i = 0; i < components.length; i++) 157 { 158 if (components[i] != null && components[i].isVisible()) 159 { 160 pref = components[i].getPreferredSize(); 161 if (pref != null) 162 { 163 middle = (tdims.height - pref.height) / 2; 164 components[i].setBounds(start, middle, pref.width, 165 pref.height); 166 start += pref.width; 167 } 168 } 169 } 170 } 171 else 172 { 173 start += insets.top; 174 for (int i = 0; i < components.length; i++) 175 { 176 if (components[i] != null && components[i].isVisible()) 177 { 178 pref = components[i].getPreferredSize(); 179 if (pref != null) 180 { 181 middle = (tdims.width - pref.width) / 2; 182 components[i].setBounds(middle, start, pref.width, 183 pref.height); 184 start += pref.height; 185 } 186 } 187 } 188 } 189 } 190 191 /** 192 * This method returns the minimum size of the given container given the 193 * child components. 194 * 195 * @param parent The container to measure. 196 * 197 * @return The minimum size of the given container. 198 */ minimumLayoutSize(Container parent)199 public Dimension minimumLayoutSize(Container parent) 200 { 201 return preferredLayoutSize(parent); 202 } 203 204 /** 205 * This method returns the preferred size of the given container given the 206 * child components. 207 * 208 * @param parent The container to measure. 209 * 210 * @return The preferred size of the given container. 211 */ preferredLayoutSize(Container parent)212 public Dimension preferredLayoutSize(Container parent) 213 { 214 int orientation = getOrientation(); 215 Component[] components = getComponents(); 216 217 int limit = 0; 218 int total = 0; 219 Dimension dims; 220 221 int w = 0; 222 int h = 0; 223 224 if (orientation == SwingConstants.HORIZONTAL) 225 { 226 for (int i = 0; i < components.length; i++) 227 { 228 dims = components[i].getPreferredSize(); 229 if (dims != null) 230 { 231 if (dims.height > limit) 232 limit = dims.height; 233 total += dims.width; 234 } 235 } 236 w = total; 237 h = limit; 238 } 239 else 240 { 241 for (int i = 0; i < components.length; i++) 242 { 243 dims = components[i].getPreferredSize(); 244 if (dims != null) 245 { 246 if (dims.width > limit) 247 limit = dims.width; 248 total += dims.height; 249 } 250 } 251 w = limit; 252 h = total; 253 } 254 255 Insets insets = getInsets(); 256 w += insets.left + insets.right; 257 h += insets.top + insets.bottom; 258 259 Insets margin = getMargin(); 260 if (margin != null) 261 { 262 w += margin.left + margin.right; 263 h += margin.top + margin.bottom; 264 } 265 266 return new Dimension(w, h); 267 } 268 269 /** 270 * This method is called when the given component is removed from the 271 * container. 272 * 273 * @param comp The component removed. 274 */ removeLayoutComponent(Component comp)275 public void removeLayoutComponent(Component comp) 276 { 277 // Do nothing. 278 } 279 } 280 281 /** 282 * This is an extension of JSeparator used in toolbars. Unlike JSeparator, 283 * nothing is painted for this Separator, it is only blank space that 284 * separates components. 285 */ 286 public static class Separator extends JSeparator 287 { 288 /** DOCUMENT ME! */ 289 private static final long serialVersionUID = -1656745644823105219L; 290 291 /** 292 * Creates a new Separator object. 293 */ Separator()294 public Separator() 295 { 296 super(); 297 } // Separator() 298 299 /** 300 * Creates a new Separator object with the given size. 301 * 302 * @param size The size of the separator. 303 */ Separator(Dimension size)304 public Separator(Dimension size) 305 { 306 setPreferredSize(size); 307 } // Separator() 308 309 /** 310 * This method returns the String ID of the UI class of Separator. 311 * 312 * @return The UI class' String ID. 313 */ getUIClassID()314 public String getUIClassID() 315 { 316 return "ToolBarSeparatorUI"; 317 } // getUIClassID() 318 319 /** 320 * This method returns the preferred size of the Separator. 321 * 322 * @return The preferred size of the Separator. 323 */ getPreferredSize()324 public Dimension getPreferredSize() 325 { 326 return super.getPreferredSize(); 327 } // getPreferredSize() 328 329 /** 330 * This method returns the maximum size of the Separator. 331 * 332 * @return The maximum size of the Separator. 333 */ getMaximumSize()334 public Dimension getMaximumSize() 335 { 336 return super.getPreferredSize(); 337 } // getMaximumSize() 338 339 /** 340 * This method returns the minimum size of the Separator. 341 * 342 * @return The minimum size of the Separator. 343 */ getMinimumSize()344 public Dimension getMinimumSize() 345 { 346 return super.getPreferredSize(); 347 } // getMinimumSize() 348 349 /** 350 * This method returns the size of the Separator. 351 * 352 * @return The size of the Separator. 353 */ getSeparatorSize()354 public Dimension getSeparatorSize() 355 { 356 return super.getPreferredSize(); 357 } // getSeparatorSize() 358 359 /** 360 * This method sets the size of the Separator. 361 * 362 * @param size The new size of the Separator. 363 */ setSeparatorSize(Dimension size)364 public void setSeparatorSize(Dimension size) 365 { 366 setPreferredSize(size); 367 } // setSeparatorSize() 368 } // Separator 369 370 /** DOCUMENT ME! */ 371 private static final long serialVersionUID = -1269915519555129643L; 372 373 /** Whether the JToolBar paints its border. */ 374 private transient boolean paintBorder = true; 375 376 /** The extra insets around the JToolBar. */ 377 private transient Insets margin; 378 379 /** Whether the JToolBar can float (and be dragged around). */ 380 private transient boolean floatable = true; 381 382 /** Whether the buttons will have rollover borders. */ 383 private transient boolean rollover; 384 385 /** The orientation of the JToolBar. */ 386 private int orientation = HORIZONTAL; 387 388 /** 389 * This method creates a new JToolBar object with horizontal orientation 390 * and no name. 391 */ JToolBar()392 public JToolBar() 393 { 394 this(null, HORIZONTAL); 395 } // JToolBar() 396 397 /** 398 * This method creates a new JToolBar with the given orientation and no 399 * name. 400 * 401 * @param orientation JToolBar orientation (HORIZONTAL or VERTICAL) 402 */ JToolBar(int orientation)403 public JToolBar(int orientation) 404 { 405 this(null, orientation); 406 } // JToolBar() 407 408 /** 409 * This method creates a new JToolBar object with the given name and 410 * horizontal orientation. 411 * 412 * @param name Name assigned to undocked tool bar. 413 */ JToolBar(String name)414 public JToolBar(String name) 415 { 416 this(name, HORIZONTAL); 417 } // JToolBar() 418 419 /** 420 * This method creates a new JToolBar object with the given name and 421 * orientation. 422 * 423 * @param name Name assigned to undocked tool bar. 424 * @param orientation JToolBar orientation (HORIZONTAL or VERTICAL) 425 */ JToolBar(String name, int orientation)426 public JToolBar(String name, int orientation) 427 { 428 setName(name); 429 setOrientation(orientation); 430 setLayout(new DefaultToolBarLayout()); 431 revalidate(); 432 setOpaque(true); 433 updateUI(); 434 } 435 436 /** 437 * This method adds a new JButton that performs the given Action to the 438 * JToolBar. 439 * 440 * @param action The Action to add to the JToolBar. 441 * 442 * @return The JButton that wraps the Action. 443 */ add(Action action)444 public JButton add(Action action) 445 { 446 JButton b = createActionComponent(action); 447 add(b); 448 return b; 449 } // add() 450 451 /** 452 * This method paints the border if the borderPainted property is true. 453 * 454 * @param graphics The graphics object to paint with. 455 */ paintBorder(Graphics graphics)456 protected void paintBorder(Graphics graphics) 457 { 458 if (paintBorder && isFloatable()) 459 super.paintBorder(graphics); 460 } // paintBorder() 461 462 /** 463 * This method returns the UI class used to paint this JToolBar. 464 * 465 * @return The UI class for this JToolBar. 466 */ getUI()467 public ToolBarUI getUI() 468 { 469 return (ToolBarUI) ui; 470 } // getUI() 471 472 /** 473 * This method sets the UI used with the JToolBar. 474 * 475 * @param ui The UI used with the JToolBar. 476 */ setUI(ToolBarUI ui)477 public void setUI(ToolBarUI ui) 478 { 479 super.setUI(ui); 480 } // setUI() 481 482 /** 483 * This method resets the UI used to the Look and Feel defaults. 484 */ updateUI()485 public void updateUI() 486 { 487 setUI((ToolBarUI) UIManager.getUI(this)); 488 } 489 490 /** 491 * This method returns the String identifier for the UI class to the used 492 * with the JToolBar. 493 * 494 * @return The String identifier for the UI class. 495 */ getUIClassID()496 public String getUIClassID() 497 { 498 return "ToolBarUI"; 499 } // getUIClassID() 500 501 /** 502 * This method sets the rollover property for the JToolBar. In rollover 503 * mode, JButtons inside the JToolBar will only display their borders when 504 * the mouse is moving over them. 505 * 506 * @param b The new rollover property. 507 */ setRollover(boolean b)508 public void setRollover(boolean b) 509 { 510 if (b != rollover) 511 { 512 rollover = b; 513 firePropertyChange("rollover", ! rollover, rollover); 514 revalidate(); 515 repaint(); 516 } 517 } 518 519 /** 520 * This method returns the rollover property. 521 * 522 * @return The rollover property. 523 */ isRollover()524 public boolean isRollover() 525 { 526 return rollover; 527 } 528 529 /** 530 * This method returns the index of the given component. 531 * 532 * @param component The component to find. 533 * 534 * @return The index of the given component. 535 */ getComponentIndex(Component component)536 public int getComponentIndex(Component component) 537 { 538 Component[] components = getComponents(); 539 if (components == null) 540 return -1; 541 542 for (int i = 0; i < components.length; i++) 543 if (components[i] == component) 544 return i; 545 546 return -1; 547 } // getComponentIndex() 548 549 /** 550 * This method returns the component at the given index. 551 * 552 * @param index The index of the component. 553 * 554 * @return The component at the given index. 555 */ getComponentAtIndex(int index)556 public Component getComponentAtIndex(int index) 557 { 558 return getComponent(index); 559 } // getComponentAtIndex() 560 561 /** 562 * This method returns the margin property. 563 * 564 * @return The margin property. 565 */ getMargin()566 public Insets getMargin() 567 { 568 return margin; 569 } // getMargin() 570 571 /** 572 * This method sets the margin property. The margin property determines the 573 * extra space between the children components of the JToolBar and the 574 * border. 575 * 576 * @param margin The margin property. 577 */ setMargin(Insets margin)578 public void setMargin(Insets margin) 579 { 580 if ((this.margin != null && margin == null) 581 || (this.margin == null && margin != null) 582 || (margin != null && this.margin != null 583 && (margin.left != this.margin.left 584 || margin.right != this.margin.right || margin.top != this.margin.top 585 || margin.bottom != this.margin.bottom))) 586 { 587 Insets oldMargin = this.margin; 588 this.margin = margin; 589 firePropertyChange("margin", oldMargin, this.margin); 590 revalidate(); 591 repaint(); 592 } 593 } // setMargin() 594 595 /** 596 * This method returns the borderPainted property. 597 * 598 * @return The borderPainted property. 599 */ isBorderPainted()600 public boolean isBorderPainted() 601 { 602 return paintBorder; 603 } // isBorderPainted() 604 605 /** 606 * This method sets the borderPainted property. If set to false, the border 607 * will not be painted. 608 * 609 * @param painted Whether the border will be painted. 610 */ setBorderPainted(boolean painted)611 public void setBorderPainted(boolean painted) 612 { 613 if (painted != paintBorder) 614 { 615 paintBorder = painted; 616 firePropertyChange("borderPainted", ! paintBorder, 617 paintBorder); 618 repaint(); 619 } 620 } // setBorderPainted() 621 622 /** 623 * This method returns the floatable property. 624 * 625 * @return The floatable property. 626 */ isFloatable()627 public boolean isFloatable() 628 { 629 return floatable; 630 } // isFloatable() 631 632 /** 633 * This method sets the floatable property. If set to false, the JToolBar 634 * cannot be dragged. 635 * 636 * @param floatable Whether the JToolBar can be dragged. 637 */ setFloatable(boolean floatable)638 public void setFloatable(boolean floatable) 639 { 640 if (floatable != this.floatable) 641 { 642 this.floatable = floatable; 643 firePropertyChange("floatable", ! floatable, floatable); 644 } 645 } // setFloatable() 646 647 /** 648 * This method returns the orientation of the JToolBar. 649 * 650 * @return The orientation of the JToolBar. 651 */ getOrientation()652 public int getOrientation() 653 { 654 return orientation; 655 } // getOrientation() 656 657 /** 658 * This method sets the layout manager to be used with the JToolBar. 659 * 660 * @param mgr The Layout Manager used with the JToolBar. 661 */ setLayout(LayoutManager mgr)662 public void setLayout(LayoutManager mgr) 663 { 664 super.setLayout(mgr); 665 revalidate(); 666 repaint(); 667 } // setLayout() 668 669 /** 670 * This method sets the orientation property for JToolBar. 671 * 672 * @param orientation The new orientation for JToolBar. 673 * 674 * @throws IllegalArgumentException If the orientation is not HORIZONTAL or 675 * VERTICAL. 676 */ setOrientation(int orientation)677 public void setOrientation(int orientation) 678 { 679 if (orientation != HORIZONTAL && orientation != VERTICAL) 680 throw new IllegalArgumentException(orientation 681 + " is not a legal orientation"); 682 if (orientation != this.orientation) 683 { 684 int oldOrientation = this.orientation; 685 this.orientation = orientation; 686 firePropertyChange("orientation", oldOrientation, this.orientation); 687 revalidate(); 688 repaint(); 689 } 690 } // setOrientation() 691 692 /** 693 * This method adds a Separator of default size to the JToolBar. 694 */ addSeparator()695 public void addSeparator() 696 { 697 add(new Separator()); 698 } // addSeparator() 699 700 /** 701 * This method adds a Separator with the given size to the JToolBar. 702 * 703 * @param size The size of the Separator. 704 */ addSeparator(Dimension size)705 public void addSeparator(Dimension size) 706 { 707 add(new Separator(size)); 708 } // addSeparator() 709 710 /** 711 * This method is used to create JButtons which can be added to the JToolBar 712 * for the given action. 713 * 714 * @param action The action to create a JButton for. 715 * 716 * @return The JButton created from the action. 717 */ createActionComponent(Action action)718 protected JButton createActionComponent(Action action) 719 { 720 return new JButton(action); 721 } // createActionComponent() 722 723 /** 724 * This method creates a pre-configured PropertyChangeListener which updates 725 * the control as changes are made to the Action. However, this is no 726 * longer the recommended way of adding Actions to Containers. As such, 727 * this method returns null. 728 * 729 * @param button The JButton to configure a PropertyChangeListener for. 730 * 731 * @return null. 732 */ createActionChangeListener(JButton button)733 protected PropertyChangeListener createActionChangeListener(JButton button) 734 { 735 // XXX: As specified, this returns null. But seems kind of strange, usually deprecated methods don't just return null, verify! 736 return null; 737 } // createActionChangeListener() 738 739 /** 740 * This method overrides Container's addImpl method. If a JButton is added, 741 * it is disabled. 742 * 743 * @param component The Component to add. 744 * @param constraints The Constraints placed on the component. 745 * @param index The index to place the Component at. 746 */ addImpl(Component component, Object constraints, int index)747 protected void addImpl(Component component, Object constraints, int index) 748 { 749 // XXX: Sun says disable button but test cases show otherwise. 750 super.addImpl(component, constraints, index); 751 752 // if we added a Swing Button then adjust this a little 753 if (component instanceof AbstractButton) 754 { 755 AbstractButton b = (AbstractButton) component; 756 b.setRolloverEnabled(rollover); 757 } 758 759 } // addImpl() 760 761 /** 762 * Returns a string describing the attributes for the <code>JToolBar</code> 763 * component, for use in debugging. The return value is guaranteed to be 764 * non-<code>null</code>, but the format of the string may vary between 765 * implementations. 766 * 767 * @return A string describing the attributes of the <code>JToolBar</code>. 768 */ paramString()769 protected String paramString() 770 { 771 CPStringBuilder sb = new CPStringBuilder(super.paramString()); 772 sb.append(",floatable=").append(floatable); 773 sb.append(",margin="); 774 if (margin != null) 775 sb.append(margin); 776 sb.append(",orientation="); 777 if (orientation == HORIZONTAL) 778 sb.append("HORIZONTAL"); 779 else 780 sb.append(VERTICAL); 781 sb.append(",paintBorder=").append(paintBorder); 782 return sb.toString(); 783 } 784 785 /** 786 * Returns the object that provides accessibility features for this 787 * <code>JToolBar</code> component. 788 * 789 * @return The accessible context (an instance of {@link AccessibleJToolBar}). 790 */ getAccessibleContext()791 public AccessibleContext getAccessibleContext() 792 { 793 if (accessibleContext == null) 794 accessibleContext = new AccessibleJToolBar(); 795 796 return accessibleContext; 797 } 798 } 799