1. /*
  2. * @(#)MotifInternalFrameTitlePane.java 1.26 03/07/24
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.java.swing.plaf.motif;
  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. * Class that manages a Motif title bar
  20. * @version 1.26 07/24/03
  21. *
  22. * @since 1.3
  23. */
  24. public class MotifInternalFrameTitlePane
  25. extends JComponent implements LayoutManager, ActionListener, PropertyChangeListener
  26. {
  27. SystemButton systemButton;
  28. MinimizeButton minimizeButton;
  29. MaximizeButton maximizeButton;
  30. JPopupMenu systemMenu;
  31. Title title;
  32. JInternalFrame iFrame;
  33. Color color;
  34. Color highlight;
  35. Color shadow;
  36. static final Font defaultTitleFont = new Font("SansSerif", Font.PLAIN, 12);
  37. // The width and height of a title pane button
  38. public final static int BUTTON_SIZE = 19; // 17 + 1 pixel border
  39. private static final String CLOSE_CMD =
  40. UIManager.getString("InternalFrameTitlePane.closeButtonText");
  41. private static final String ICONIFY_CMD =
  42. UIManager.getString("InternalFrameTitlePane.minimizeButtonText");
  43. private static final String RESTORE_CMD =
  44. UIManager.getString("InternalFrameTitlePane.restoreButtonText");
  45. private static final String MAXIMIZE_CMD =
  46. UIManager.getString("InternalFrameTitlePane.maximizeButtonText");
  47. private static final String MOVE_CMD =
  48. UIManager.getString("InternalFrameTitlePane.moveButtonText");
  49. private static final String SIZE_CMD =
  50. UIManager.getString("InternalFrameTitlePane.sizeButtonText");
  51. final int RESTORE_MENU_ITEM = 0;
  52. final int MOVE_MENU_ITEM = 1;
  53. final int SIZE_MENU_ITEM = 2;
  54. final int MINIMIZE_MENU_ITEM = 3;
  55. final int MAXIMIZE_MENU_ITEM = 4;
  56. final int SEPARATOR_MENU_ITEM = 5;
  57. final int CLOSE_MENU_ITEM = 6;
  58. public MotifInternalFrameTitlePane(JInternalFrame f) {
  59. iFrame = f;
  60. setPreferredSize(new Dimension(100, BUTTON_SIZE));
  61. systemMenu = new JPopupMenu() {
  62. public void show(Component invoker, int x, int y) {
  63. if(!iFrame.isIconifiable())
  64. systemMenu.getComponentAtIndex(MINIMIZE_MENU_ITEM).setEnabled(false);
  65. if(!iFrame.isMaximizable())
  66. systemMenu.getComponentAtIndex(MAXIMIZE_MENU_ITEM).setEnabled(false);
  67. if(!iFrame.isMaximizable() && !iFrame.isIconifiable())
  68. systemMenu.getComponentAtIndex(RESTORE_MENU_ITEM).setEnabled(false);
  69. if(!iFrame.isClosable())
  70. systemMenu.getComponentAtIndex(CLOSE_MENU_ITEM).setEnabled(false);
  71. super.show(invoker, x, y);
  72. }
  73. };
  74. JMenuItem mi = (JMenuItem) systemMenu.add(new JMenuItem(RESTORE_CMD));
  75. mi.setEnabled(iFrame.isIcon());
  76. mi.addActionListener(this);
  77. /// PENDING(klobad) Move/Size actions on InternalFrame need to be determined
  78. mi = (JMenuItem) systemMenu.add(new JMenuItem(MOVE_CMD));
  79. mi.setEnabled(false);
  80. mi.addActionListener(this);
  81. mi = (JMenuItem) systemMenu.add(new JMenuItem(SIZE_CMD));
  82. mi.setEnabled(false);
  83. mi.addActionListener(this);
  84. mi = (JMenuItem) systemMenu.add(new JMenuItem(ICONIFY_CMD));
  85. mi.setEnabled(!iFrame.isIcon());
  86. mi.addActionListener(this);
  87. mi = (JMenuItem) systemMenu.add(new JMenuItem(MAXIMIZE_CMD));
  88. mi.addActionListener(this);
  89. systemMenu.add(new JSeparator());
  90. mi = (JMenuItem) systemMenu.add(new JMenuItem(CLOSE_CMD));
  91. mi.addActionListener(this);
  92. systemButton = new SystemButton();
  93. systemButton.addActionListener(new ActionListener() {
  94. public void actionPerformed(ActionEvent e) {
  95. systemMenu.show(systemButton, 0, BUTTON_SIZE);
  96. }
  97. });
  98. systemButton.addMouseListener(new MouseAdapter() {
  99. public void mousePressed(MouseEvent e) {
  100. if ((e.getClickCount() == 2)){
  101. if (iFrame.isClosable()) {
  102. iFrame.doDefaultCloseAction();
  103. }
  104. systemMenu.setVisible(false);
  105. }
  106. }
  107. });
  108. minimizeButton = new MinimizeButton();
  109. minimizeButton.addActionListener(this);
  110. minimizeButton.setActionCommand(ICONIFY_CMD);
  111. maximizeButton = new MaximizeButton();
  112. maximizeButton.addActionListener(this);
  113. maximizeButton.setActionCommand(MAXIMIZE_CMD);
  114. title = new Title(iFrame.getTitle());
  115. title.setFont(defaultTitleFont);
  116. setLayout(this);
  117. add(systemButton);
  118. add(title);
  119. add(minimizeButton);
  120. add(maximizeButton);
  121. // Make sure these are ok to leave on?
  122. iFrame.addPropertyChangeListener(this);
  123. }
  124. void setColors(Color c, Color h, Color s) {
  125. color = c;
  126. highlight = h;
  127. shadow = s;
  128. }
  129. JPopupMenu getSystemMenu() {
  130. return systemMenu;
  131. }
  132. public void actionPerformed(ActionEvent e) {
  133. try {
  134. if (CLOSE_CMD.equals(e.getActionCommand()) && iFrame.isClosable()) {
  135. iFrame.doDefaultCloseAction();
  136. } else if (ICONIFY_CMD.equals(e.getActionCommand()) &&
  137. iFrame.isIconifiable()) { //4118140
  138. if (!iFrame.isIcon()) {
  139. iFrame.setIcon(true);
  140. } else {
  141. iFrame.setIcon(false);
  142. }
  143. } else if (MAXIMIZE_CMD.equals(e.getActionCommand()) &&
  144. iFrame.isMaximizable()) {
  145. if (!iFrame.isMaximum()) {
  146. iFrame.setMaximum(true);
  147. } else {
  148. iFrame.setMaximum(false);
  149. }
  150. } else if (RESTORE_CMD.equals(e.getActionCommand()) &&
  151. iFrame.isMaximizable() && iFrame.isMaximum()) {
  152. iFrame.setMaximum(false);
  153. } else if (RESTORE_CMD.equals(e.getActionCommand()) &&
  154. iFrame.isIconifiable() && iFrame.isIcon()) {
  155. iFrame.setIcon(false);
  156. }
  157. } catch (PropertyVetoException e0) { }
  158. // Dismiss popup menu if it's displayed
  159. if (systemMenu.isVisible()) {
  160. systemMenu.setVisible(false);
  161. }
  162. }
  163. public void propertyChange(PropertyChangeEvent evt) {
  164. String prop = (String)evt.getPropertyName();
  165. JInternalFrame f = (JInternalFrame)evt.getSource();
  166. boolean value = false;
  167. if(JInternalFrame.IS_SELECTED_PROPERTY.equals(prop)) {
  168. repaint();
  169. } else if(JInternalFrame.IS_MAXIMUM_PROPERTY.equals(prop)) {
  170. value = ((Boolean)evt.getNewValue()).booleanValue();
  171. systemMenu.getComponentAtIndex(RESTORE_MENU_ITEM).setEnabled(value);
  172. systemMenu.getComponentAtIndex(MAXIMIZE_MENU_ITEM).setEnabled(!value);
  173. } else if(JInternalFrame.IS_ICON_PROPERTY.equals(prop)) {
  174. value = ((Boolean)evt.getNewValue()).booleanValue();
  175. systemMenu.getComponentAtIndex(RESTORE_MENU_ITEM).setEnabled(value);
  176. if (f.isMaximizable())
  177. systemMenu.getComponentAtIndex(MAXIMIZE_MENU_ITEM).setEnabled(true);
  178. else
  179. systemMenu.getComponentAtIndex(MAXIMIZE_MENU_ITEM).setEnabled(false);
  180. systemMenu.getComponentAtIndex(MINIMIZE_MENU_ITEM).setEnabled(!value);
  181. } else if( prop.equals("maximizable") ) {
  182. if( (Boolean)evt.getNewValue() == Boolean.TRUE )
  183. add(maximizeButton);
  184. else
  185. remove(maximizeButton);
  186. revalidate();
  187. repaint();
  188. } else if( prop.equals("iconable") ) {
  189. if( (Boolean)evt.getNewValue() == Boolean.TRUE )
  190. add(minimizeButton);
  191. else
  192. remove(minimizeButton);
  193. revalidate();
  194. repaint();
  195. } else if (prop.equals(JInternalFrame.TITLE_PROPERTY)) {
  196. repaint();
  197. }
  198. }
  199. public void addLayoutComponent(String name, Component c) {}
  200. public void removeLayoutComponent(Component c) {}
  201. public Dimension preferredLayoutSize(Container c) {
  202. return new Dimension(c.getSize().width, BUTTON_SIZE);
  203. }
  204. public Dimension minimumLayoutSize(Container c) {
  205. return new Dimension(c.getSize().width, BUTTON_SIZE);
  206. }
  207. public void layoutContainer(Container c) {
  208. int w = getWidth();
  209. systemButton.setBounds(0, 0, BUTTON_SIZE, BUTTON_SIZE);
  210. int x = w - BUTTON_SIZE;
  211. if(iFrame.isMaximizable()) {
  212. maximizeButton.setBounds(x, 0, BUTTON_SIZE, BUTTON_SIZE);
  213. x -= BUTTON_SIZE;
  214. } else if(maximizeButton.getParent() != null) {
  215. maximizeButton.getParent().remove(maximizeButton);
  216. }
  217. if(iFrame.isIconifiable()) {
  218. minimizeButton.setBounds(x, 0, BUTTON_SIZE, BUTTON_SIZE);
  219. x -= BUTTON_SIZE;
  220. } else if(minimizeButton.getParent() != null) {
  221. minimizeButton.getParent().remove(minimizeButton);
  222. }
  223. title.setBounds(BUTTON_SIZE, 0, x, BUTTON_SIZE);
  224. }
  225. protected void showSystemMenu(){
  226. systemMenu.show(systemButton, 0, BUTTON_SIZE);
  227. }
  228. protected void hideSystemMenu(){
  229. systemMenu.setVisible(false);
  230. }
  231. static Dimension buttonDimension = new Dimension(BUTTON_SIZE, BUTTON_SIZE);
  232. private abstract class FrameButton extends JButton {
  233. FrameButton() {
  234. super();
  235. setFocusPainted(false);
  236. setBorderPainted(false);
  237. }
  238. public boolean isFocusTraversable() {
  239. return false;
  240. }
  241. public void requestFocus() {
  242. // ignore request.
  243. }
  244. public Dimension getMinimumSize() {
  245. return buttonDimension;
  246. }
  247. public Dimension getPreferredSize() {
  248. return buttonDimension;
  249. }
  250. public void paint(Graphics g) {
  251. Dimension d = getSize();
  252. int maxX = d.width - 1;
  253. int maxY = d.height - 1;
  254. // draw background
  255. g.setColor(color);
  256. g.fillRect(1, 1, d.width, d.height);
  257. // draw border
  258. boolean pressed = getModel().isPressed();
  259. g.setColor(pressed ? shadow : highlight);
  260. g.drawLine(0, 0, maxX, 0);
  261. g.drawLine(0, 0, 0, maxY);
  262. g.setColor(pressed ? highlight : shadow);
  263. g.drawLine(1, maxY, maxX, maxY);
  264. g.drawLine(maxX, 1, maxX, maxY);
  265. }
  266. }
  267. private class MinimizeButton extends FrameButton {
  268. public void paint(Graphics g) {
  269. super.paint(g);
  270. g.setColor(highlight);
  271. g.drawLine(7, 8, 7, 11);
  272. g.drawLine(7, 8, 10, 8);
  273. g.setColor(shadow);
  274. g.drawLine(8, 11, 10, 11);
  275. g.drawLine(11, 9, 11, 11);
  276. }
  277. }
  278. private class MaximizeButton extends FrameButton {
  279. public void paint(Graphics g) {
  280. super.paint(g);
  281. int max = BUTTON_SIZE - 5;
  282. boolean isMaxed = iFrame.isMaximum();
  283. g.setColor(isMaxed ? shadow : highlight);
  284. g.drawLine(4, 4, 4, max);
  285. g.drawLine(4, 4, max, 4);
  286. g.setColor(isMaxed ? highlight : shadow);
  287. g.drawLine(5, max, max, max);
  288. g.drawLine(max, 5, max, max);
  289. }
  290. }
  291. private class SystemButton extends FrameButton {
  292. public boolean isFocusTraversable() { return false; }
  293. public void requestFocus() {}
  294. public void paint(Graphics g) {
  295. super.paint(g);
  296. g.setColor(highlight);
  297. g.drawLine(4, 8, 4, 11);
  298. g.drawLine(4, 8, BUTTON_SIZE - 5, 8);
  299. g.setColor(shadow);
  300. g.drawLine(5, 11, BUTTON_SIZE - 5, 11);
  301. g.drawLine(BUTTON_SIZE - 5, 9, BUTTON_SIZE - 5, 11);
  302. }
  303. }
  304. private class Title extends FrameButton {
  305. Title(String title) {
  306. super();
  307. setText(title);
  308. setHorizontalAlignment(SwingConstants.CENTER);
  309. setBorder(BorderFactory.createBevelBorder(
  310. BevelBorder.RAISED,
  311. UIManager.getColor("activeCaptionBorder"),
  312. UIManager.getColor("inactiveCaptionBorder")));
  313. // Forward mouse events to titlebar for moves.
  314. addMouseMotionListener(new MouseMotionListener() {
  315. public void mouseDragged(MouseEvent e) {
  316. forwardEventToParent(e);
  317. }
  318. public void mouseMoved(MouseEvent e) {
  319. forwardEventToParent(e);
  320. }
  321. });
  322. addMouseListener(new MouseListener() {
  323. public void mouseClicked(MouseEvent e) {
  324. forwardEventToParent(e);
  325. }
  326. public void mousePressed(MouseEvent e) {
  327. forwardEventToParent(e);
  328. }
  329. public void mouseReleased(MouseEvent e) {
  330. forwardEventToParent(e);
  331. }
  332. public void mouseEntered(MouseEvent e) {
  333. forwardEventToParent(e);
  334. }
  335. public void mouseExited(MouseEvent e) {
  336. forwardEventToParent(e);
  337. }
  338. });
  339. }
  340. void forwardEventToParent(MouseEvent e) {
  341. getParent().dispatchEvent(new MouseEvent(
  342. getParent(), e.getID(), e.getWhen(), e.getModifiers(),
  343. e.getX(), e.getY(), e.getClickCount(), e.isPopupTrigger()));
  344. }
  345. public void paint(Graphics g) {
  346. super.paint(g);
  347. if (iFrame.isSelected()) {
  348. g.setColor(UIManager.getColor("activeCaptionText"));
  349. } else {
  350. g.setColor(UIManager.getColor("inactiveCaptionText"));
  351. }
  352. Dimension d = getSize();
  353. String frameTitle = iFrame.getTitle();
  354. if (frameTitle != null) {
  355. MotifGraphicsUtils.drawStringInRect(g, frameTitle,
  356. 0, 0, d.width, d.height,
  357. SwingConstants.CENTER);
  358. }
  359. }
  360. }
  361. } /// End Title Pane Class