1 /* BasicInternalFrameTitlePane.java -- 2 Copyright (C) 2004, 2005 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.plaf.basic; 40 41 import java.awt.Color; 42 import java.awt.Component; 43 import java.awt.Container; 44 import java.awt.Dimension; 45 import java.awt.Font; 46 import java.awt.FontMetrics; 47 import java.awt.Graphics; 48 import java.awt.Insets; 49 import java.awt.LayoutManager; 50 import java.awt.Rectangle; 51 import java.awt.event.ActionEvent; 52 import java.awt.event.KeyEvent; 53 import java.beans.PropertyChangeEvent; 54 import java.beans.PropertyChangeListener; 55 import java.beans.PropertyVetoException; 56 57 import javax.swing.AbstractAction; 58 import javax.swing.Action; 59 import javax.swing.Icon; 60 import javax.swing.JButton; 61 import javax.swing.JComponent; 62 import javax.swing.JInternalFrame; 63 import javax.swing.JLabel; 64 import javax.swing.JMenu; 65 import javax.swing.JMenuBar; 66 import javax.swing.JMenuItem; 67 import javax.swing.SwingConstants; 68 import javax.swing.SwingUtilities; 69 import javax.swing.UIManager; 70 71 /** 72 * This class acts as a titlebar for JInternalFrames. 73 */ 74 public class BasicInternalFrameTitlePane extends JComponent 75 { 76 /** 77 * The Action responsible for closing the JInternalFrame. 78 * 79 * @specnote Apparently this class was intended to be protected, 80 * but was made public by a compiler bug and is now 81 * public for compatibility. 82 */ 83 public class CloseAction extends AbstractAction 84 { 85 /** 86 * Creates a new action. 87 */ CloseAction()88 public CloseAction() 89 { 90 super("Close"); 91 } 92 93 /** 94 * This method is called when something closes the JInternalFrame. 95 * 96 * @param e The ActionEvent. 97 */ actionPerformed(ActionEvent e)98 public void actionPerformed(ActionEvent e) 99 { 100 if (frame.isClosable()) 101 { 102 try 103 { 104 frame.setClosed(true); 105 } 106 catch (PropertyVetoException pve) 107 { 108 // We do nothing if the attempt has been vetoed. 109 } 110 } 111 } 112 } 113 114 /** 115 * This Action is responsible for iconifying the JInternalFrame. 116 * 117 * @specnote Apparently this class was intended to be protected, 118 * but was made public by a compiler bug and is now 119 * public for compatibility. 120 */ 121 public class IconifyAction extends AbstractAction 122 { 123 /** 124 * Creates a new action. 125 */ IconifyAction()126 public IconifyAction() 127 { 128 super("Minimize"); 129 } 130 131 /** 132 * This method is called when the user wants to iconify the 133 * JInternalFrame. 134 * 135 * @param e The ActionEvent. 136 */ actionPerformed(ActionEvent e)137 public void actionPerformed(ActionEvent e) 138 { 139 if (frame.isIconifiable() && ! frame.isIcon()) 140 { 141 try 142 { 143 frame.setIcon(true); 144 } 145 catch (PropertyVetoException pve) 146 { 147 // We do nothing if the attempt has been vetoed. 148 } 149 } 150 } 151 } 152 153 /** 154 * This Action is responsible for maximizing the JInternalFrame. 155 * 156 * @specnote Apparently this class was intended to be protected, 157 * but was made public by a compiler bug and is now 158 * public for compatibility. 159 */ 160 public class MaximizeAction extends AbstractAction 161 { 162 /** 163 * Creates a new action. 164 */ MaximizeAction()165 public MaximizeAction() 166 { 167 super("Maximize"); 168 } 169 /** 170 * This method is called when the user wants to maximize the 171 * JInternalFrame. 172 * 173 * @param e The ActionEvent. 174 */ actionPerformed(ActionEvent e)175 public void actionPerformed(ActionEvent e) 176 { 177 try 178 { 179 if (frame.isMaximizable() && ! frame.isMaximum()) 180 { 181 frame.setMaximum(true); 182 maxButton.setIcon(minIcon); 183 } 184 else if (frame.isMaximum()) 185 { 186 frame.setMaximum(false); 187 maxButton.setIcon(maxIcon); 188 } 189 } 190 catch (PropertyVetoException pve) 191 { 192 // We do nothing if the attempt has been vetoed. 193 } 194 } 195 } 196 197 /** 198 * This Action is responsible for dragging the JInternalFrame. 199 * 200 * @specnote Apparently this class was intended to be protected, 201 * but was made public by a compiler bug and is now 202 * public for compatibility. 203 */ 204 public class MoveAction extends AbstractAction 205 { 206 /** 207 * Creates a new action. 208 */ MoveAction()209 public MoveAction() 210 { 211 super("Move"); 212 } 213 /** 214 * This method is called when the user wants to drag the JInternalFrame. 215 * 216 * @param e The ActionEvent. 217 */ actionPerformed(ActionEvent e)218 public void actionPerformed(ActionEvent e) 219 { 220 // FIXME: Implement keyboard driven? move actions. 221 } 222 } 223 224 /** 225 * This Action is responsible for restoring the JInternalFrame. Restoring 226 * the JInternalFrame is the same as setting the maximum property to false. 227 * 228 * @specnote Apparently this class was intended to be protected, 229 * but was made public by a compiler bug and is now 230 * public for compatibility. 231 */ 232 public class RestoreAction extends AbstractAction 233 { 234 /** 235 * Creates a new action. 236 */ RestoreAction()237 public RestoreAction() 238 { 239 super("Restore"); 240 } 241 /** 242 * This method is called when the user wants to restore the 243 * JInternalFrame. 244 * 245 * @param e The ActionEvent. 246 */ actionPerformed(ActionEvent e)247 public void actionPerformed(ActionEvent e) 248 { 249 if (frame.isMaximum()) 250 { 251 try 252 { 253 frame.setMaximum(false); 254 } 255 catch (PropertyVetoException pve) 256 { 257 // We do nothing if the attempt has been vetoed. 258 } 259 } 260 } 261 } 262 263 /** 264 * This action is responsible for sizing the JInternalFrame. 265 * 266 * @specnote Apparently this class was intended to be protected, 267 * but was made public by a compiler bug and is now 268 * public for compatibility. 269 */ 270 public class SizeAction extends AbstractAction 271 { 272 /** 273 * Creates a new action. 274 */ SizeAction()275 public SizeAction() 276 { 277 super("Size"); 278 } 279 /** 280 * This method is called when the user wants to resize the JInternalFrame. 281 * 282 * @param e The ActionEvent. 283 */ actionPerformed(ActionEvent e)284 public void actionPerformed(ActionEvent e) 285 { 286 // FIXME: Not sure how size actions should be handled. 287 } 288 } 289 290 /** 291 * This class is responsible for handling property change events from the 292 * JInternalFrame and adjusting the Title Pane as necessary. 293 * 294 * @specnote Apparently this class was intended to be protected, 295 * but was made public by a compiler bug and is now 296 * public for compatibility. 297 */ 298 public class PropertyChangeHandler implements PropertyChangeListener 299 { 300 /** 301 * This method is called when a PropertyChangeEvent is received by the 302 * Title Pane. 303 * 304 * @param evt The PropertyChangeEvent. 305 */ propertyChange(PropertyChangeEvent evt)306 public void propertyChange(PropertyChangeEvent evt) 307 { 308 String propName = evt.getPropertyName(); 309 if (propName.equals("closable")) 310 { 311 if (evt.getNewValue().equals(Boolean.TRUE)) 312 closeButton.setVisible(true); 313 else 314 closeButton.setVisible(false); 315 } 316 else if (propName.equals("iconable")) 317 { 318 if (evt.getNewValue().equals(Boolean.TRUE)) 319 iconButton.setVisible(true); 320 else 321 iconButton.setVisible(false); 322 } 323 else if (propName.equals("maximizable")) 324 { 325 if (evt.getNewValue().equals(Boolean.TRUE)) 326 maxButton.setVisible(true); 327 else 328 maxButton.setVisible(false); 329 } 330 enableActions(); 331 } 332 } 333 334 /** 335 * This class acts as the MenuBar for the TitlePane. Clicking on the Frame 336 * Icon in the top left corner will activate it. 337 * 338 * @specnote Apparently this class was intended to be protected, 339 * but was made public by a compiler bug and is now 340 * public for compatibility. 341 */ 342 public class SystemMenuBar extends JMenuBar 343 { 344 /** 345 * This method returns true if it can receive focus. 346 * 347 * @return True if this Component can receive focus. 348 */ isFocusTraversable()349 public boolean isFocusTraversable() 350 { 351 return true; 352 } 353 354 /** 355 * This method returns true if this Component is expected to paint all of 356 * itself. 357 * 358 * @return True if this Component is expect to paint all of itself. 359 */ isOpaque()360 public boolean isOpaque() 361 { 362 return true; 363 } 364 365 /** 366 * This method paints this Component. 367 * 368 * @param g The Graphics object to paint with. 369 */ paint(Graphics g)370 public void paint(Graphics g) 371 { 372 Icon frameIcon = frame.getFrameIcon(); 373 if (frameIcon == null) 374 frameIcon = BasicDesktopIconUI.defaultIcon; 375 frameIcon.paintIcon(this, g, 0, 0); 376 } 377 378 /** 379 * This method requests that focus be given to this Component. 380 */ requestFocus()381 public void requestFocus() 382 { 383 super.requestFocus(); 384 } 385 } 386 387 /** 388 * This class acts as the Layout Manager for the TitlePane. 389 * 390 * @specnote Apparently this class was intended to be protected, 391 * but was made public by a compiler bug and is now 392 * public for compatibility. 393 */ 394 public class TitlePaneLayout implements LayoutManager 395 { 396 /** 397 * Creates a new <code>TitlePaneLayout</code> object. 398 */ TitlePaneLayout()399 public TitlePaneLayout() 400 { 401 // Do nothing. 402 } 403 404 /** 405 * This method is called when adding a Component to the Container. 406 * 407 * @param name The name to reference the added Component by. 408 * @param c The Component to add. 409 */ addLayoutComponent(String name, Component c)410 public void addLayoutComponent(String name, Component c) 411 { 412 // Do nothing. 413 } 414 415 /** 416 * This method is called to lay out the children of the Title Pane. 417 * 418 * @param c The Container to lay out. 419 */ layoutContainer(Container c)420 public void layoutContainer(Container c) 421 { 422 Dimension size = c.getSize(); 423 Insets insets = c.getInsets(); 424 int width = size.width - insets.left - insets.right; 425 int height = size.height - insets.top - insets.bottom; 426 427 // MenuBar is always present and located at the top left corner. 428 Dimension menupref = menuBar.getPreferredSize(); 429 menuBar.setBounds(insets.left, insets.top, menupref.width, height); 430 431 int loc = width + insets.left - 1; 432 int top = insets.top + 1; 433 int buttonHeight = height - 4; 434 if (closeButton.isVisible()) 435 { 436 int buttonWidth = closeIcon.getIconWidth(); 437 loc -= buttonWidth + 2; 438 closeButton.setBounds(loc, top, buttonWidth, buttonHeight); 439 } 440 441 if (maxButton.isVisible()) 442 { 443 int buttonWidth = maxIcon.getIconWidth(); 444 loc -= buttonWidth + 2; 445 maxButton.setBounds(loc, top, buttonWidth, buttonHeight); 446 } 447 448 if (iconButton.isVisible()) 449 { 450 int buttonWidth = iconIcon.getIconWidth(); 451 loc -= buttonWidth + 2; 452 iconButton.setBounds(loc, top, buttonWidth, buttonHeight); 453 } 454 455 if (title != null) 456 title.setBounds(insets.left + menupref.width, insets.top, 457 loc - menupref.width - insets.left, height); 458 } 459 460 /** 461 * This method returns the minimum size of the given Container given the 462 * children that it has. 463 * 464 * @param c The Container to get a minimum size for. 465 * 466 * @return The minimum size of the Container. 467 */ minimumLayoutSize(Container c)468 public Dimension minimumLayoutSize(Container c) 469 { 470 return preferredLayoutSize(c); 471 } 472 473 /** 474 * This method returns the preferred size of the given Container taking 475 * into account the children that it has. 476 * 477 * @param c The Container to lay out. 478 * 479 * @return The preferred size of the Container. 480 */ preferredLayoutSize(Container c)481 public Dimension preferredLayoutSize(Container c) 482 { 483 return new Dimension(22, 18); 484 } 485 486 /** 487 * This method is called when removing a Component from the Container. 488 * 489 * @param c The Component to remove. 490 */ removeLayoutComponent(Component c)491 public void removeLayoutComponent(Component c) 492 { 493 // Nothing to do here. 494 } 495 } 496 497 /** 498 * This helper class is used to create the minimize, maximize and close 499 * buttons in the top right corner of the Title Pane. These buttons are 500 * special since they cannot be given focus and have no border. 501 */ 502 private class PaneButton extends JButton 503 { 504 /** 505 * Creates a new PaneButton object with the given Action. 506 * 507 * @param a The Action that the button uses. 508 */ PaneButton(Action a)509 public PaneButton(Action a) 510 { 511 super(a); 512 setMargin(new Insets(0, 0, 0, 0)); 513 } 514 515 /** 516 * This method returns true if the Component can be focused. 517 * 518 * @return false. 519 */ isFocusable()520 public boolean isFocusable() 521 { 522 // These buttons cannot be given focus. 523 return false; 524 } 525 526 } 527 528 /** The action command for the Close action. */ 529 protected static final String CLOSE_CMD; 530 531 /** The action command for the Minimize action. */ 532 protected static final String ICONIFY_CMD; 533 534 /** The action command for the Maximize action. */ 535 protected static final String MAXIMIZE_CMD; 536 537 /** The action command for the Move action. */ 538 protected static final String MOVE_CMD; 539 540 /** The action command for the Restore action. */ 541 protected static final String RESTORE_CMD; 542 543 /** The action command for the Size action. */ 544 protected static final String SIZE_CMD; 545 546 /** The action associated with closing the JInternalFrame. */ 547 protected Action closeAction; 548 549 /** The action associated with iconifying the JInternalFrame. */ 550 protected Action iconifyAction; 551 552 /** The action associated with maximizing the JInternalFrame. */ 553 protected Action maximizeAction; 554 555 /** The action associated with moving the JInternalFrame. */ 556 protected Action moveAction; 557 558 /** The action associated with restoring the JInternalFrame. */ 559 protected Action restoreAction; 560 561 /** The action associated with resizing the JInternalFrame. */ 562 protected Action sizeAction; 563 564 /** The button that closes the JInternalFrame. */ 565 protected JButton closeButton; 566 567 /** The button that iconifies the JInternalFrame. */ 568 protected JButton iconButton; 569 570 /** The button that maximizes the JInternalFrame. */ 571 protected JButton maxButton; 572 573 /** The icon displayed in the restore button. */ 574 protected Icon minIcon = BasicIconFactory.createEmptyFrameIcon(); 575 576 /** The icon displayed in the maximize button. */ 577 protected Icon maxIcon = BasicIconFactory.createEmptyFrameIcon(); 578 579 /** The icon displayed in the iconify button. */ 580 protected Icon iconIcon = BasicIconFactory.createEmptyFrameIcon(); 581 582 /** The icon displayed in the close button. */ 583 protected Icon closeIcon; 584 585 /** The JInternalFrame that this TitlePane is used in. */ 586 protected JInternalFrame frame; 587 588 /** The JMenuBar that is located at the top left of the Title Pane. */ 589 protected JMenuBar menuBar; 590 591 /** The JMenu inside the menuBar. */ 592 protected JMenu windowMenu; 593 594 /** 595 * The text color of the TitlePane when the JInternalFrame is not selected. 596 */ 597 protected Color notSelectedTextColor; 598 599 /** 600 * The background color of the TitlePane when the JInternalFrame is not 601 * selected. 602 */ 603 protected Color notSelectedTitleColor; 604 605 /** The text color of the titlePane when the JInternalFrame is selected. */ 606 protected Color selectedTextColor; 607 608 /** 609 * The background color of the TitlePane when the JInternalFrame is 610 * selected. 611 */ 612 protected Color selectedTitleColor; 613 614 /** The Property Change listener that listens to the JInternalFrame. */ 615 protected PropertyChangeListener propertyChangeListener; 616 617 /** 618 * The label used to display the title. This label is not added to the 619 * TitlePane. 620 * This is package-private to avoid an accessor method. 621 */ 622 transient JLabel title; 623 624 static 625 { 626 // not constants in JDK 627 CLOSE_CMD = "Close"; 628 ICONIFY_CMD = "Minimize"; 629 MAXIMIZE_CMD = "Maximize"; 630 MOVE_CMD = "Move"; 631 RESTORE_CMD = "Restore"; 632 SIZE_CMD = "Size"; 633 } 634 635 /** 636 * Creates a new BasicInternalFrameTitlePane object that is used in the 637 * given JInternalFrame. 638 * 639 * @param f The JInternalFrame this BasicInternalFrameTitlePane will be used 640 * in. 641 */ BasicInternalFrameTitlePane(JInternalFrame f)642 public BasicInternalFrameTitlePane(JInternalFrame f) 643 { 644 frame = f; 645 setLayout(createLayout()); 646 title = new JLabel(); 647 title.setHorizontalAlignment(SwingConstants.LEFT); 648 title.setHorizontalTextPosition(SwingConstants.LEFT); 649 title.setOpaque(false); 650 setOpaque(true); 651 652 setBackground(Color.LIGHT_GRAY); 653 setOpaque(true); 654 655 installTitlePane(); 656 } 657 658 /** 659 * This method installs the TitlePane onto the JInternalFrameTitlePane. It 660 * also creates any children components that need to be created and adds 661 * listeners to the appropriate components. 662 */ installTitlePane()663 protected void installTitlePane() 664 { 665 installDefaults(); 666 installListeners(); 667 createActions(); 668 669 assembleSystemMenu(); 670 671 createButtons(); 672 setButtonIcons(); 673 addSubComponents(); 674 enableActions(); 675 } 676 677 /** 678 * This method adds the sub components to the TitlePane. 679 */ addSubComponents()680 protected void addSubComponents() 681 { 682 add(menuBar); 683 684 add(closeButton); 685 add(iconButton); 686 add(maxButton); 687 } 688 689 /** 690 * This method creates the actions that are used to manipulate the 691 * JInternalFrame. 692 */ createActions()693 protected void createActions() 694 { 695 closeAction = new CloseAction(); 696 closeAction.putValue(AbstractAction.ACTION_COMMAND_KEY, CLOSE_CMD); 697 698 iconifyAction = new IconifyAction(); 699 iconifyAction.putValue(AbstractAction.ACTION_COMMAND_KEY, ICONIFY_CMD); 700 701 maximizeAction = new MaximizeAction(); 702 maximizeAction.putValue(AbstractAction.ACTION_COMMAND_KEY, MAXIMIZE_CMD); 703 704 sizeAction = new SizeAction(); 705 sizeAction.putValue(AbstractAction.ACTION_COMMAND_KEY, SIZE_CMD); 706 707 restoreAction = new RestoreAction(); 708 restoreAction.putValue(AbstractAction.ACTION_COMMAND_KEY, RESTORE_CMD); 709 710 moveAction = new MoveAction(); 711 moveAction.putValue(AbstractAction.ACTION_COMMAND_KEY, MOVE_CMD); 712 } 713 714 /** 715 * This method is used to install the listeners. 716 */ installListeners()717 protected void installListeners() 718 { 719 propertyChangeListener = createPropertyChangeListener(); 720 frame.addPropertyChangeListener(propertyChangeListener); 721 } 722 723 /** 724 * This method is used to uninstall the listeners. 725 */ uninstallListeners()726 protected void uninstallListeners() 727 { 728 frame.removePropertyChangeListener(propertyChangeListener); 729 propertyChangeListener = null; 730 } 731 732 /** 733 * This method installs the defaults determined by the look and feel. 734 */ installDefaults()735 protected void installDefaults() 736 { 737 title.setFont(UIManager.getFont("InternalFrame.titleFont")); 738 selectedTextColor = UIManager.getColor("InternalFrame.activeTitleForeground"); 739 selectedTitleColor = UIManager.getColor("InternalFrame.activeTitleBackground"); 740 notSelectedTextColor = UIManager.getColor("InternalFrame.inactiveTitleForeground"); 741 notSelectedTitleColor = UIManager.getColor("InternalFrame.inactiveTitleBackground"); 742 743 closeIcon = UIManager.getIcon("InternalFrame.closeIcon"); 744 iconIcon = UIManager.getIcon("InternalFrame.iconifyIcon"); 745 maxIcon = UIManager.getIcon("InternalFrame.maximizeIcon"); 746 } 747 748 /** 749 * This method uninstalls the defaults. 750 */ uninstallDefaults()751 protected void uninstallDefaults() 752 { 753 setFont(null); 754 selectedTextColor = null; 755 selectedTitleColor = null; 756 notSelectedTextColor = null; 757 notSelectedTitleColor = null; 758 759 closeIcon = null; 760 iconIcon = null; 761 maxIcon = null; 762 } 763 764 /** 765 * This method creates the buttons used in the TitlePane. 766 */ createButtons()767 protected void createButtons() 768 { 769 closeButton = new PaneButton(closeAction); 770 closeButton.setText(null); 771 if (!frame.isClosable()) 772 closeButton.setVisible(false); 773 iconButton = new PaneButton(iconifyAction); 774 iconButton.setText(null); 775 if (!frame.isIconifiable()) 776 iconButton.setVisible(false); 777 maxButton = new PaneButton(maximizeAction); 778 maxButton.setText(null); 779 if (!frame.isMaximizable()) 780 maxButton.setVisible(false); 781 } 782 783 /** 784 * Set icons for the minimize-, maximize- and close-buttons. 785 */ setButtonIcons()786 protected void setButtonIcons() 787 { 788 if (closeIcon != null && closeButton != null) 789 closeButton.setIcon(closeIcon); 790 if (iconIcon != null && iconButton != null) 791 iconButton.setIcon(iconIcon); 792 if (maxIcon != null && maxButton != null) 793 maxButton.setIcon(maxIcon); 794 } 795 796 /** 797 * This method creates the MenuBar used in the TitlePane. 798 */ assembleSystemMenu()799 protected void assembleSystemMenu() 800 { 801 menuBar = createSystemMenuBar(); 802 windowMenu = createSystemMenu(); 803 804 menuBar.add(windowMenu); 805 806 addSystemMenuItems(windowMenu); 807 enableActions(); 808 } 809 810 /** 811 * This method adds the MenuItems to the given JMenu. 812 * 813 * @param systemMenu The JMenu to add MenuItems to. 814 */ addSystemMenuItems(JMenu systemMenu)815 protected void addSystemMenuItems(JMenu systemMenu) 816 { 817 JMenuItem tmp; 818 819 tmp = new JMenuItem(RESTORE_CMD); 820 tmp.addActionListener(restoreAction); 821 tmp.setMnemonic(KeyEvent.VK_R); 822 systemMenu.add(tmp); 823 824 tmp = new JMenuItem(MOVE_CMD); 825 tmp.addActionListener(moveAction); 826 tmp.setMnemonic(KeyEvent.VK_M); 827 systemMenu.add(tmp); 828 829 tmp = new JMenuItem(SIZE_CMD); 830 tmp.addActionListener(sizeAction); 831 tmp.setMnemonic(KeyEvent.VK_S); 832 systemMenu.add(tmp); 833 834 tmp = new JMenuItem(ICONIFY_CMD); 835 tmp.addActionListener(iconifyAction); 836 tmp.setMnemonic(KeyEvent.VK_N); 837 systemMenu.add(tmp); 838 839 tmp = new JMenuItem(MAXIMIZE_CMD); 840 tmp.addActionListener(maximizeAction); 841 tmp.setMnemonic(KeyEvent.VK_X); 842 systemMenu.add(tmp); 843 844 systemMenu.addSeparator(); 845 846 tmp = new JMenuItem(CLOSE_CMD); 847 tmp.addActionListener(closeAction); 848 tmp.setMnemonic(KeyEvent.VK_C); 849 systemMenu.add(tmp); 850 } 851 852 /** 853 * This method creates a new JMenubar. 854 * 855 * @return A new JMenuBar. 856 */ createSystemMenuBar()857 protected JMenuBar createSystemMenuBar() 858 { 859 if (menuBar == null) 860 menuBar = new SystemMenuBar(); 861 menuBar.removeAll(); 862 return menuBar; 863 } 864 865 /** 866 * This method creates a new JMenu. 867 * 868 * @return A new JMenu. 869 */ createSystemMenu()870 protected JMenu createSystemMenu() 871 { 872 if (windowMenu == null) 873 windowMenu = new JMenu(); 874 windowMenu.removeAll(); 875 return windowMenu; 876 } 877 878 /** 879 * This method programmatically shows the JMenu. 880 */ showSystemMenu()881 protected void showSystemMenu() 882 { 883 // FIXME: Untested as KeyEvents are not hooked up. 884 menuBar.getMenu(1).getPopupMenu().show(); 885 } 886 887 /** 888 * This method paints the TitlePane. 889 * 890 * @param g The Graphics object to paint with. 891 */ paintComponent(Graphics g)892 public void paintComponent(Graphics g) 893 { 894 paintTitleBackground(g); 895 if (frame.getTitle() != null && title != null) 896 { 897 Color saved = g.getColor(); 898 Font f = title.getFont(); 899 g.setFont(f); 900 FontMetrics fm = g.getFontMetrics(f); 901 if (frame.isSelected()) 902 g.setColor(selectedTextColor); 903 else 904 g.setColor(notSelectedTextColor); 905 title.setText(getTitle(frame.getTitle(), fm, title.getBounds().width)); 906 SwingUtilities.paintComponent(g, title, null, title.getBounds()); 907 g.setColor(saved); 908 } 909 } 910 911 /** 912 * This method paints the TitlePane's background. 913 * 914 * @param g The Graphics object to paint with. 915 */ paintTitleBackground(Graphics g)916 protected void paintTitleBackground(Graphics g) 917 { 918 if (!isOpaque()) 919 return; 920 921 Color saved = g.getColor(); 922 Dimension dims = getSize(); 923 924 Color bg = getBackground(); 925 if (frame.isSelected()) 926 bg = selectedTitleColor; 927 else 928 bg = notSelectedTitleColor; 929 g.setColor(bg); 930 g.fillRect(0, 0, dims.width, dims.height); 931 g.setColor(saved); 932 } 933 934 /** 935 * This method returns the title string based on the available width and the 936 * font metrics. 937 * 938 * @param text The desired title. 939 * @param fm The FontMetrics of the font used. 940 * @param availableWidth The available width. 941 * 942 * @return The allowable string. 943 */ getTitle(String text, FontMetrics fm, int availableWidth)944 protected String getTitle(String text, FontMetrics fm, int availableWidth) 945 { 946 Rectangle vr = new Rectangle(0, 0, availableWidth, fm.getHeight()); 947 Rectangle ir = new Rectangle(); 948 Rectangle tr = new Rectangle(); 949 String value = SwingUtilities.layoutCompoundLabel(this, fm, text, null, 950 SwingConstants.CENTER, 951 SwingConstants.LEFT, 952 SwingConstants.CENTER, 953 SwingConstants.LEFT, vr, 954 ir, tr, 0); 955 return value; 956 } 957 958 /** 959 * This method fires something similar to a WINDOW_CLOSING event. 960 * 961 * @param frame The JInternalFrame that is being closed. 962 */ postClosingEvent(JInternalFrame frame)963 protected void postClosingEvent(JInternalFrame frame) 964 { 965 // FIXME: Implement postClosingEvent when I figure out what 966 // it's supposed to do. 967 // It says that this fires an WINDOW_CLOSING like event. 968 // So the closest thing is some kind of InternalFrameEvent. 969 // But none is fired. 970 // Can't see it called or anything. 971 } 972 973 /** 974 * This method enables the actions for the TitlePane given the frame's 975 * properties. 976 */ enableActions()977 protected void enableActions() 978 { 979 closeAction.setEnabled(frame.isClosable()); 980 981 iconifyAction.setEnabled(frame.isIconifiable()); 982 // The maximize action is responsible for restoring it 983 // as well, if clicked from the button 984 maximizeAction.setEnabled(frame.isMaximizable()); 985 986 // The restoring action is only active when selected 987 // from the menu. 988 restoreAction.setEnabled(frame.isMaximum()); 989 990 sizeAction.setEnabled(frame.isResizable()); 991 992 // FIXME: Tie MoveAction enabled status to a variable. 993 moveAction.setEnabled(false); 994 } 995 996 /** 997 * This method creates a new PropertyChangeListener. 998 * 999 * @return A new PropertyChangeListener. 1000 */ createPropertyChangeListener()1001 protected PropertyChangeListener createPropertyChangeListener() 1002 { 1003 return new PropertyChangeHandler(); 1004 } 1005 1006 /** 1007 * This method creates a new LayoutManager for the TitlePane. 1008 * 1009 * @return A new LayoutManager. 1010 */ createLayout()1011 protected LayoutManager createLayout() 1012 { 1013 return new TitlePaneLayout(); 1014 } 1015 } 1016