1. /*
  2. * @(#)BasicInternalFrameTitlePane.java 1.29 01/11/29
  3. *
  4. * Copyright 2002 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 java.awt.*;
  9. import java.awt.event.*;
  10. import javax.swing.*;
  11. import javax.swing.border.*;
  12. import javax.swing.event.InternalFrameEvent;
  13. import java.util.EventListener;
  14. import java.beans.PropertyChangeListener;
  15. import java.beans.PropertyChangeEvent;
  16. import java.beans.VetoableChangeListener;
  17. import java.beans.PropertyVetoException;
  18. /**
  19. * The class that manages a basic title bar
  20. * <p>
  21. * <strong>Warning:</strong>
  22. * Serialized objects of this class will not be compatible with
  23. * future Swing releases. The current serialization support is appropriate
  24. * for short term storage or RMI between applications running the same
  25. * version of Swing. A future release of Swing will provide support for
  26. * long term persistence.
  27. *
  28. * @version 1.29 11/29/01
  29. * @author David Kloba
  30. * @author Steve Wilson
  31. */
  32. public class BasicInternalFrameTitlePane extends JComponent
  33. {
  34. protected JMenuBar menuBar;
  35. protected JButton iconButton;
  36. protected JButton maxButton;
  37. protected JButton closeButton;
  38. protected JMenu windowMenu;
  39. protected JInternalFrame frame;
  40. protected Color selectedTitleColor;
  41. protected Color selectedTextColor;
  42. protected Color notSelectedTitleColor;
  43. protected Color notSelectedTextColor;
  44. protected Icon maxIcon;
  45. protected Icon minIcon;
  46. protected Icon iconIcon;
  47. protected Icon closeIcon;
  48. protected PropertyChangeListener propertyChangeListener;
  49. protected Action closeAction;
  50. protected Action maximizeAction;
  51. protected Action iconifyAction;
  52. protected Action restoreAction;
  53. protected Action moveAction;
  54. protected Action sizeAction;
  55. protected static final String CLOSE_CMD = "Close";
  56. protected static final String ICONIFY_CMD = "Minimize";
  57. protected static final String RESTORE_CMD = "Restore";
  58. protected static final String MAXIMIZE_CMD = "Maximize";
  59. protected static final String MOVE_CMD = "Move";
  60. protected static final String SIZE_CMD = "Size";
  61. public BasicInternalFrameTitlePane(JInternalFrame f) {
  62. frame = f;
  63. installTitlePane();
  64. }
  65. protected void installTitlePane() {
  66. installDefaults();
  67. installListeners();
  68. createActions();
  69. enableActions();
  70. setLayout(createLayout());
  71. assembleSystemMenu();
  72. createButtons();
  73. addSubComponents();
  74. }
  75. protected void addSubComponents() {
  76. add(menuBar);
  77. add(iconButton);
  78. add(maxButton);
  79. add(closeButton);
  80. }
  81. protected void createActions() {
  82. maximizeAction = new MaximizeAction();
  83. iconifyAction = new IconifyAction();
  84. closeAction = new CloseAction();
  85. restoreAction = new RestoreAction();
  86. moveAction = new MoveAction();
  87. sizeAction = new SizeAction();
  88. }
  89. protected void installListeners() {
  90. propertyChangeListener = createPropertyChangeListener();
  91. frame.addPropertyChangeListener(propertyChangeListener);
  92. }
  93. protected void installDefaults() {
  94. maxIcon = UIManager.getIcon("InternalFrame.maximizeIcon");
  95. minIcon = UIManager.getIcon("InternalFrame.minimizeIcon");
  96. iconIcon = UIManager.getIcon("InternalFrame.iconifyIcon");
  97. closeIcon = UIManager.getIcon("InternalFrame.closeIcon");
  98. selectedTitleColor = UIManager.getColor("InternalFrame.activeTitleBackground");
  99. selectedTextColor = UIManager.getColor("InternalFrame.activeTitleForeground");
  100. notSelectedTitleColor = UIManager.getColor("InternalFrame.inactiveTitleBackground");
  101. notSelectedTextColor = UIManager.getColor("InternalFrame.inactiveTitleForeground");
  102. }
  103. protected void uninstallDefaults() {
  104. }
  105. public void addNotify() {
  106. super.addNotify();
  107. addSystemMenuItems(windowMenu);
  108. enableActions();
  109. }
  110. public void removeNotify() {
  111. super.removeNotify();
  112. if (windowMenu!=null) {
  113. windowMenu.removeAll();
  114. }
  115. uninstallDefaults();
  116. }
  117. protected void createButtons() {
  118. iconButton = new NoFocusButton();
  119. iconButton.addActionListener(iconifyAction);
  120. maxButton = new NoFocusButton();
  121. maxButton.addActionListener(maximizeAction);
  122. closeButton = new NoFocusButton();
  123. closeButton.addActionListener(closeAction);
  124. setButtonIcons();
  125. }
  126. protected void setButtonIcons() {
  127. if(frame.isIcon()) {
  128. iconButton.setIcon(minIcon);
  129. maxButton.setIcon(maxIcon);
  130. } else if (frame.isMaximum()) {
  131. iconButton.setIcon(iconIcon);
  132. maxButton.setIcon(minIcon);
  133. } else {
  134. iconButton.setIcon(iconIcon);
  135. maxButton.setIcon(maxIcon);
  136. }
  137. closeButton.setIcon(closeIcon);
  138. }
  139. protected void assembleSystemMenu() {
  140. menuBar = createSystemMenuBar();
  141. windowMenu = createSystemMenu();
  142. menuBar.add(windowMenu);
  143. // moved to addNotify - addSystemMenuItems(windowMenu);
  144. enableActions();
  145. }
  146. protected void addSystemMenuItems(JMenu systemMenu) {
  147. JMenuItem mi = (JMenuItem)systemMenu.add(restoreAction);
  148. mi.setMnemonic('R');
  149. mi = (JMenuItem)systemMenu.add(moveAction);
  150. mi.setMnemonic('M');
  151. mi = (JMenuItem)systemMenu.add(sizeAction);
  152. mi.setMnemonic('S');
  153. mi = (JMenuItem)systemMenu.add(iconifyAction);
  154. mi.setMnemonic('n');
  155. mi = (JMenuItem)systemMenu.add(maximizeAction);
  156. mi.setMnemonic('x');
  157. systemMenu.add(new JSeparator());
  158. mi = (JMenuItem)systemMenu.add(closeAction);
  159. mi.setMnemonic('C');
  160. }
  161. protected JMenu createSystemMenu() {
  162. return new JMenu(" ");
  163. }
  164. protected JMenuBar createSystemMenuBar() {
  165. menuBar = new SystemMenuBar();
  166. menuBar.setBorderPainted(false);
  167. return menuBar;
  168. }
  169. protected void showSystemMenu(){
  170. // windowMenu.setPopupMenuVisible(true);
  171. // windowMenu.setVisible(true);
  172. windowMenu.doClick();
  173. }
  174. public void paintComponent(Graphics g) {
  175. boolean isSelected = frame.isSelected();
  176. if(isSelected)
  177. g.setColor(selectedTitleColor);
  178. else
  179. g.setColor(notSelectedTitleColor);
  180. g.fillRect(0, 0, getWidth(), getHeight());
  181. if(frame.getTitle() != null) {
  182. Font f = g.getFont();
  183. g.setFont(UIManager.getFont("InternalFrame.titleFont"));
  184. if(isSelected)
  185. g.setColor(selectedTextColor);
  186. else
  187. g.setColor(notSelectedTextColor);
  188. // Center text vertically.
  189. FontMetrics fm = g.getFontMetrics();
  190. int fmHeight = fm.getHeight() - fm.getLeading();
  191. int baseline = (18 - fmHeight) / 2 +
  192. fm.getAscent() + fm.getLeading();
  193. g.drawString(frame.getTitle(),
  194. menuBar.getX() + menuBar.getWidth() + 2,
  195. baseline);
  196. g.setFont(f);
  197. }
  198. }
  199. /**
  200. * Post a WINDOW_CLOSING-like event to the frame, so that it can
  201. * be treated like a regular Frame.
  202. */
  203. protected void postClosingEvent(JInternalFrame frame) {
  204. InternalFrameEvent e = new InternalFrameEvent(
  205. frame, InternalFrameEvent.INTERNAL_FRAME_CLOSING);
  206. // Try posting event, unless there's a SecurityManager.
  207. if (JInternalFrame.class.getClassLoader() == null) {
  208. try {
  209. Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(e);
  210. return;
  211. } catch (SecurityException se) {
  212. // Use dispatchEvent instead.
  213. }
  214. }
  215. frame.dispatchEvent(e);
  216. }
  217. protected void enableActions() {
  218. restoreAction.setEnabled(frame.isMaximum() || frame.isIcon());
  219. maximizeAction.setEnabled(frame.isMaximizable() && !frame.isMaximum() );
  220. iconifyAction.setEnabled(frame.isIconifiable() && !frame.isIcon());
  221. closeAction.setEnabled(frame.isClosable());
  222. sizeAction.setEnabled(false);
  223. moveAction.setEnabled(false);
  224. }
  225. protected PropertyChangeListener createPropertyChangeListener() {
  226. return new PropertyChangeHandler();
  227. }
  228. protected LayoutManager createLayout() {
  229. return new TitlePaneLayout();
  230. }
  231. /**
  232. * This inner class is marked "public" due to a compiler bug.
  233. * This class should be treated as a "protected" inner class.
  234. * Instantiate it only within subclasses of <Foo>.
  235. */
  236. public class PropertyChangeHandler implements PropertyChangeListener {
  237. public void propertyChange(PropertyChangeEvent evt) {
  238. String prop = (String)evt.getPropertyName();
  239. if(JInternalFrame.IS_SELECTED_PROPERTY.equals(prop)) {
  240. repaint();
  241. return;
  242. }
  243. if(JInternalFrame.IS_ICON_PROPERTY.equals(prop) ||
  244. JInternalFrame.IS_MAXIMUM_PROPERTY.equals(prop)) {
  245. setButtonIcons();
  246. return;
  247. }
  248. enableActions();
  249. }
  250. } // end PropertyHandler class
  251. /**
  252. * This inner class is marked "public" due to a compiler bug.
  253. * This class should be treated as a "protected" inner class.
  254. * Instantiate it only within subclasses of <Foo>.
  255. */
  256. public class TitlePaneLayout implements LayoutManager {
  257. public void addLayoutComponent(String name, Component c) {}
  258. public void removeLayoutComponent(Component c) {}
  259. public Dimension preferredLayoutSize(Container c) {
  260. return new Dimension(100, 18);
  261. }
  262. public Dimension minimumLayoutSize(Container c) {
  263. return preferredLayoutSize(c);
  264. }
  265. public void layoutContainer(Container c) {
  266. int w = getWidth();
  267. int x = w - 16 - 2;
  268. menuBar.setBounds(2, 1, 16, 16);
  269. if(frame.isClosable()) {
  270. closeButton.setBounds(x, 2, 16, 14);
  271. x -= 16;
  272. } else if(closeButton.getParent() != null) {
  273. closeButton.getParent().remove(closeButton);
  274. }
  275. if(frame.isMaximizable()) {
  276. maxButton.setBounds(x - 2, 2, 16, 14);
  277. x -= 18;
  278. } else if(maxButton.getParent() != null) {
  279. maxButton.getParent().remove(maxButton);
  280. }
  281. if(frame.isIconifiable()) {
  282. iconButton.setBounds(x, 2, 16, 14);
  283. } else if(iconButton.getParent() != null) {
  284. iconButton.getParent().remove(iconButton);
  285. }
  286. }
  287. } // end TitlePaneLayout
  288. /**
  289. * This inner class is marked "public" due to a compiler bug.
  290. * This class should be treated as a "protected" inner class.
  291. * Instantiate it only within subclasses of <Foo>.
  292. */
  293. public class CloseAction extends AbstractAction {
  294. public CloseAction() {
  295. super(CLOSE_CMD);
  296. }
  297. public void actionPerformed(ActionEvent e) {
  298. if(frame.isClosable()) {
  299. try {
  300. frame.setClosed(true);
  301. } catch (PropertyVetoException e0) { }
  302. }
  303. }
  304. } // end CloseAction
  305. /**
  306. * This inner class is marked "public" due to a compiler bug.
  307. * This class should be treated as a "protected" inner class.
  308. * Instantiate it only within subclasses of <Foo>.
  309. */
  310. public class MaximizeAction extends AbstractAction {
  311. public MaximizeAction() {
  312. super(MAXIMIZE_CMD);
  313. }
  314. public void actionPerformed(ActionEvent e) {
  315. if(frame.isMaximizable()) {
  316. if(!frame.isMaximum()) {
  317. try { frame.setMaximum(true); } catch (PropertyVetoException e5) { }
  318. } else {
  319. try {
  320. frame.setMaximum(false);
  321. if (frame.isIconifiable() && frame.isIcon()) {
  322. frame.setIcon(false);
  323. }
  324. } catch (PropertyVetoException e6) { }
  325. }
  326. }
  327. }
  328. } // MaximizeAction
  329. /**
  330. * This inner class is marked "public" due to a compiler bug.
  331. * This class should be treated as a "protected" inner class.
  332. * Instantiate it only within subclasses of <Foo>.
  333. */
  334. public class IconifyAction extends AbstractAction {
  335. public IconifyAction() {
  336. super(ICONIFY_CMD);
  337. }
  338. public void actionPerformed(ActionEvent e) {
  339. if(frame.isIconifiable()) {
  340. if(!frame.isIcon())
  341. try { frame.setIcon(true); } catch (PropertyVetoException e1) { }
  342. else {
  343. try {
  344. frame.setIcon(false);
  345. if (frame.isMaximizable() && frame.isMaximum()) {
  346. frame.setMaximum(false);
  347. }
  348. } catch (PropertyVetoException e1) { }
  349. }
  350. }
  351. }
  352. } // end IconifyAction
  353. /**
  354. * This inner class is marked "public" due to a compiler bug.
  355. * This class should be treated as a "protected" inner class.
  356. * Instantiate it only within subclasses of <Foo>.
  357. */
  358. public class RestoreAction extends AbstractAction {
  359. public RestoreAction() {
  360. super(RESTORE_CMD);
  361. }
  362. public void actionPerformed(ActionEvent e) {
  363. if(frame.isMaximizable() && frame.isMaximum()) {
  364. try { frame.setMaximum(false); } catch (PropertyVetoException e4) { }
  365. }
  366. else if ( frame.isIconifiable() && frame.isIcon() ) {
  367. try { frame.setIcon(false); } catch (PropertyVetoException e4) { }
  368. }
  369. }
  370. } // end RestoreAction
  371. /**
  372. * This inner class is marked "public" due to a compiler bug.
  373. * This class should be treated as a "protected" inner class.
  374. * Instantiate it only within subclasses of <Foo>.
  375. */
  376. public class MoveAction extends AbstractAction {
  377. public MoveAction() {
  378. super(MOVE_CMD);
  379. }
  380. public void actionPerformed(ActionEvent e) {
  381. // This action is currently undefined
  382. }
  383. } // end MoveAction
  384. /**
  385. * This inner class is marked "public" due to a compiler bug.
  386. * This class should be treated as a "protected" inner class.
  387. * Instantiate it only within subclasses of <Foo>.
  388. */
  389. public class SizeAction extends AbstractAction {
  390. public SizeAction() {
  391. super(SIZE_CMD);
  392. }
  393. public void actionPerformed(ActionEvent e) {
  394. // This action is currently undefined
  395. }
  396. } // end SizeAction
  397. /**
  398. * This inner class is marked "public" due to a compiler bug.
  399. * This class should be treated as a "protected" inner class.
  400. * Instantiate it only within subclasses of <Foo>.
  401. */
  402. public class SystemMenuBar extends JMenuBar {
  403. public boolean isFocusTraversable() { return false; }
  404. public void requestFocus() {}
  405. public void paint(Graphics g) {
  406. Icon icon = frame.getFrameIcon();
  407. if (icon == null) {
  408. icon = UIManager.getIcon("InternalFrame.icon");
  409. }
  410. if (icon != null) {
  411. // Resize to 16x16 if necessary.
  412. if (icon instanceof ImageIcon && (icon.getIconWidth() > 16 || icon.getIconHeight() > 16)) {
  413. Image img = ((ImageIcon)icon).getImage();
  414. ((ImageIcon)icon).setImage(img.getScaledInstance(16, 16, Image.SCALE_SMOOTH));
  415. }
  416. icon.paintIcon(this, g, 0, 0);
  417. }
  418. }
  419. public boolean isOpaque() {
  420. return true;
  421. }
  422. } // end SystemMenuBar
  423. private class NoFocusButton extends JButton {
  424. public NoFocusButton() { setFocusPainted(false); }
  425. public boolean isFocusTraversable() { return false; }
  426. public void requestFocus() {};
  427. public boolean isOpaque() { return true; }
  428. }; // end NoFocusButton
  429. } // End Title Pane Class