1. /*
  2. * @(#)SynthInternalFrameTitlePane.java 1.21 04/04/16
  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.synth;
  8. import java.awt.*;
  9. import java.awt.event.*;
  10. import javax.swing.*;
  11. import javax.swing.plaf.*;
  12. import javax.swing.plaf.basic.BasicInternalFrameTitlePane;
  13. import javax.swing.border.*;
  14. import javax.swing.event.InternalFrameEvent;
  15. import java.util.EventListener;
  16. import java.beans.PropertyChangeListener;
  17. import java.beans.PropertyChangeEvent;
  18. import java.beans.VetoableChangeListener;
  19. import java.beans.PropertyVetoException;
  20. import sun.swing.plaf.synth.SynthUI;
  21. /**
  22. * The class that manages a synth title bar
  23. *
  24. * @version 1.21 04/16/04
  25. * @author David Kloba
  26. * @author Joshua Outwater
  27. * @author Steve Wilson
  28. */
  29. class SynthInternalFrameTitlePane extends BasicInternalFrameTitlePane
  30. implements SynthUI, PropertyChangeListener {
  31. protected JPopupMenu systemPopupMenu;
  32. protected JButton menuButton;
  33. private SynthStyle style;
  34. public SynthInternalFrameTitlePane(JInternalFrame f) {
  35. super(f);
  36. }
  37. public String getUIClassID() {
  38. return "InternalFrameTitlePaneUI";
  39. }
  40. public SynthContext getContext(JComponent c) {
  41. return getContext(c, getComponentState(c));
  42. }
  43. public SynthContext getContext(JComponent c, int state) {
  44. return SynthContext.getContext(SynthContext.class, c,
  45. SynthLookAndFeel.getRegion(c), style, state);
  46. }
  47. private Region getRegion(JComponent c) {
  48. return SynthLookAndFeel.getRegion(c);
  49. }
  50. private int getComponentState(JComponent c) {
  51. if (frame != null) {
  52. if (frame.isSelected()) {
  53. return SELECTED;
  54. }
  55. }
  56. return SynthLookAndFeel.getComponentState(c);
  57. }
  58. protected void addSubComponents() {
  59. menuButton.setName("InternalFrameTitlePane.menuButton");
  60. iconButton.setName("InternalFrameTitlePane.iconifyButton");
  61. maxButton.setName("InternalFrameTitlePane.maximizeButton");
  62. closeButton.setName("InternalFrameTitlePane.closeButton");
  63. add(menuButton);
  64. add(iconButton);
  65. add(maxButton);
  66. add(closeButton);
  67. }
  68. protected void installListeners() {
  69. super.installListeners();
  70. frame.addPropertyChangeListener(this);
  71. }
  72. protected void uninstallListeners() {
  73. frame.removePropertyChangeListener(this);
  74. super.uninstallListeners();
  75. }
  76. private void updateStyle(JComponent c) {
  77. SynthContext context = getContext(this, ENABLED);
  78. SynthStyle oldStyle = style;
  79. style = SynthLookAndFeel.updateStyle(context, this);
  80. if (style != oldStyle) {
  81. maxIcon =
  82. style.getIcon(context,"InternalFrameTitlePane.maximizeIcon");
  83. minIcon =
  84. style.getIcon(context,"InternalFrameTitlePane.minimizeIcon");
  85. iconIcon =
  86. style.getIcon(context,"InternalFrameTitlePane.iconifyIcon");
  87. closeIcon =
  88. style.getIcon(context,"InternalFrameTitlePane.closeIcon");
  89. }
  90. context.dispose();
  91. }
  92. protected void installDefaults() {
  93. super.installDefaults();
  94. updateStyle(this);
  95. }
  96. protected void uninstallDefaults() {
  97. SynthContext context = getContext(this, ENABLED);
  98. style.uninstallDefaults(context);
  99. context.dispose();
  100. style = null;
  101. JInternalFrame.JDesktopIcon di = frame.getDesktopIcon();
  102. if(di != null && di.getComponentPopupMenu() == systemPopupMenu) {
  103. // Release link to systemMenu from the JInternalFrame
  104. di.setComponentPopupMenu(null);
  105. }
  106. super.uninstallDefaults();
  107. }
  108. private static class JPopupMenuUIResource extends JPopupMenu implements UIResource { }
  109. protected void assembleSystemMenu() {
  110. systemPopupMenu = new JPopupMenuUIResource();
  111. addSystemMenuItems(systemPopupMenu);
  112. enableActions();
  113. menuButton = createNoFocusButton();
  114. menuButton.setIcon(frame.getFrameIcon());
  115. menuButton.addMouseListener(new MouseAdapter() {
  116. public void mousePressed(MouseEvent e) {
  117. Dimension dim = new Dimension();
  118. Border border = frame.getBorder();
  119. if (border != null) {
  120. dim.width += border.getBorderInsets(frame).left +
  121. border.getBorderInsets(frame).right;
  122. dim.height += border.getBorderInsets(frame).bottom +
  123. border.getBorderInsets(frame).top;
  124. }
  125. if (!frame.isIcon()) {
  126. systemPopupMenu.show(e.getComponent(),
  127. getX() - dim.width,
  128. getY() + getHeight() - dim.height);
  129. } else {
  130. systemPopupMenu.show(e.getComponent(),
  131. getX() - dim.width,
  132. getY() - systemPopupMenu.getPreferredSize().height -
  133. dim.height);
  134. }
  135. }
  136. });
  137. JPopupMenu p = frame.getComponentPopupMenu();
  138. if (p == null || p instanceof UIResource) {
  139. frame.setComponentPopupMenu(systemPopupMenu);
  140. }
  141. if (frame.getDesktopIcon() != null) {
  142. p = frame.getDesktopIcon().getComponentPopupMenu();
  143. if (p == null || p instanceof UIResource) {
  144. frame.getDesktopIcon().setComponentPopupMenu(systemPopupMenu);
  145. }
  146. }
  147. setInheritsPopupMenu(true);
  148. }
  149. protected void addSystemMenuItems(JPopupMenu menu) {
  150. // PENDING: this should all be localizable!
  151. JMenuItem mi = (JMenuItem)menu.add(restoreAction);
  152. mi.setMnemonic('R');
  153. mi = (JMenuItem)menu.add(moveAction);
  154. mi.setMnemonic('M');
  155. mi = (JMenuItem)menu.add(sizeAction);
  156. mi.setMnemonic('S');
  157. mi = (JMenuItem)menu.add(iconifyAction);
  158. mi.setMnemonic('n');
  159. mi = (JMenuItem)menu.add(maximizeAction);
  160. mi.setMnemonic('x');
  161. menu.add(new JSeparator());
  162. mi = (JMenuItem)menu.add(closeAction);
  163. mi.setMnemonic('C');
  164. }
  165. // SynthInternalFrameTitlePane has no UI, we'll invoke paint on it.
  166. public void paintComponent(Graphics g) {
  167. SynthContext context = getContext(this);
  168. SynthLookAndFeel.update(context, g);
  169. context.getPainter().paintInternalFrameTitlePaneBackground(context,
  170. g, 0, 0, getWidth(), getHeight());
  171. paint(context, g);
  172. context.dispose();
  173. }
  174. public void paint(Graphics g, JComponent c) {
  175. SynthContext context = getContext(c);
  176. paint(context, g);
  177. context.dispose();
  178. }
  179. protected void paint(SynthContext context, Graphics g) {
  180. }
  181. public void paintBorder(SynthContext context, Graphics g, int x,
  182. int y, int w, int h) {
  183. context.getPainter().paintInternalFrameTitlePaneBorder(context,
  184. g, x, y, w, h);
  185. }
  186. protected LayoutManager createLayout() {
  187. SynthContext context = getContext(this);
  188. LayoutManager lm =
  189. (LayoutManager)style.get(context, "InternalFrameTitlePane.titlePaneLayout");
  190. context.dispose();
  191. return (lm != null) ? lm : new SynthTitlePaneLayout();
  192. }
  193. public void propertyChange(PropertyChangeEvent evt) {
  194. if (SynthLookAndFeel.shouldUpdateStyle(evt)) {
  195. updateStyle(SynthInternalFrameTitlePane.this);
  196. }
  197. }
  198. class SynthTitlePaneLayout implements LayoutManager {
  199. public void addLayoutComponent(String name, Component c) {}
  200. public void removeLayoutComponent(Component c) {}
  201. public Dimension preferredLayoutSize(Container c) {
  202. return minimumLayoutSize(c);
  203. }
  204. public Dimension minimumLayoutSize(Container c) {
  205. // Calculate width.
  206. int width = 22;
  207. if (frame.isClosable()) {
  208. width += 19;
  209. }
  210. if (frame.isMaximizable()) {
  211. width += 19;
  212. }
  213. if (frame.isIconifiable()) {
  214. width += 19;
  215. }
  216. FontMetrics fm = frame.getFontMetrics(getFont());
  217. SynthContext context = getContext(frame);
  218. SynthGraphicsUtils graphicsUtils = context.getStyle().
  219. getGraphicsUtils(context);
  220. String frameTitle = frame.getTitle();
  221. int title_w = frameTitle != null ? graphicsUtils.
  222. computeStringWidth(context, fm.getFont(),
  223. fm, frameTitle) : 0;
  224. int title_length = frameTitle != null ? frameTitle.length() : 0;
  225. // Leave room for three characters in the title.
  226. if (title_length > 3) {
  227. int subtitle_w = graphicsUtils.computeStringWidth(context,
  228. fm.getFont(), fm, frameTitle.substring(0, 3) + "...");
  229. width += (title_w < subtitle_w) ? title_w : subtitle_w;
  230. } else {
  231. width += title_w;
  232. }
  233. // Calculate height.
  234. Icon icon = frame.getFrameIcon();
  235. int fontHeight = fm.getHeight();
  236. fontHeight += 2;
  237. int iconHeight = 0;
  238. if (icon != null) {
  239. // SystemMenuBar forces the icon to be 16x16 or less.
  240. iconHeight = Math.min(icon.getIconHeight(), 16);
  241. }
  242. iconHeight += 2;
  243. int height = Math.max( fontHeight, iconHeight );
  244. Dimension dim = new Dimension(width, height);
  245. // Take into account the border insets if any.
  246. if (getBorder() != null) {
  247. Insets insets = getBorder().getBorderInsets(c);
  248. dim.height += insets.top + insets.bottom;
  249. dim.width += insets.left + insets.right;
  250. }
  251. context.dispose();
  252. return dim;
  253. }
  254. public void layoutContainer(Container c) {
  255. boolean leftToRight = SynthLookAndFeel.isLeftToRight(frame);
  256. int w = getWidth();
  257. int h = getHeight();
  258. int x;
  259. Icon closeIcon = closeButton.getIcon();
  260. int buttonHeight = (closeIcon != null) ? closeIcon.getIconHeight(): 12;
  261. if (buttonHeight == 0) {
  262. buttonHeight = 12;
  263. }
  264. //int buttonWidth = closeButton.getIcon().getIconWidth();
  265. Icon icon = frame.getFrameIcon();
  266. int iconHeight = (icon != null) ? icon.getIconHeight() : buttonHeight;
  267. Insets insets = frame.getInsets();
  268. x = (leftToRight) ? insets.left : w - 16 - insets.right;
  269. menuButton.setBounds(x, (h - iconHeight) / 2, 16, 14);
  270. x = (leftToRight) ? w - 16 - insets.right : insets.left;
  271. if (frame.isClosable()) {
  272. closeButton.setBounds(x, (h - buttonHeight) / 2, 16, 14);
  273. x += (leftToRight) ? -(16 + 2) : 16 + 2;
  274. }
  275. if (frame.isMaximizable()) {
  276. maxButton.setBounds(x, (h - buttonHeight) / 2, 16, 14);
  277. x += (leftToRight) ? -(16 + 2) : 16 + 2;
  278. }
  279. if (frame.isIconifiable()) {
  280. iconButton.setBounds(x, (h - buttonHeight) / 2, 16, 14);
  281. }
  282. }
  283. }
  284. private JButton createNoFocusButton() {
  285. JButton button = new JButton();
  286. button.setFocusable(false);
  287. button.setMargin(new Insets(0,0,0,0));
  288. return button;
  289. }
  290. }