1. /*
  2. * @(#)MetacityCrux.java 1.7 03/01/23
  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.gtk;
  8. import java.awt.*;
  9. import java.io.*;
  10. import java.net.*;
  11. import java.security.*;
  12. import java.util.*;
  13. import javax.swing.*;
  14. import javax.swing.border.*;
  15. /**
  16. * @version 1.7, 01/23/03
  17. */
  18. class MetacityCrux extends Metacity {
  19. protected MetacityCrux(String themeDir) {
  20. super(themeDir, normalFrameGeometry);
  21. }
  22. // Constants from Metacity 2.4.1 Crux/metacity-theme-1.xml (use same variable names)
  23. /*
  24. <constant name="IconTitleSpacing" value="2"/> <!-- Space between menu button and title -->
  25. <constant name="CenterTitlePieceWidth" value="48"/> <!-- Width of center title piece -->
  26. <constant name="ButtonWidth" value="16"/> <!-- Button width -->
  27. */
  28. private static final int IconTitleSpacing = 2;
  29. private static final int CenterTitlePieceWidth = 48;
  30. private static final int ButtonWidth = 16;
  31. /*
  32. <frame_geometry name="normal">
  33. <distance name="left_width" value="5"/>
  34. <distance name="right_width" value="6"/>
  35. <distance name="bottom_height" value="6"/>
  36. <distance name="left_titlebar_edge" value="5"/>
  37. <distance name="right_titlebar_edge" value="6"/>
  38. <aspect_ratio name="button" value="1.0"/>
  39. <distance name="title_vertical_pad" value="0"/>
  40. <border name="title_border" left="0" right="0" top="3" bottom="3"/>
  41. <border name="button_border" left="0" right="0" top="3" bottom="3"/>
  42. </frame_geometry>
  43. */
  44. private static class NormalFrameGeometry extends FrameGeometry {
  45. NormalFrameGeometry() {
  46. left_width = 5;
  47. right_width = 6;
  48. bottom_height = 6;
  49. left_titlebar_edge = 5;
  50. right_titlebar_edge = 6;
  51. aspect_ratio = 1.0F;
  52. title_vertical_pad = 0;
  53. title_border = new Insets(3, 0, 3, 0);
  54. button_border = new Insets(3, 0, 3, 0);
  55. }
  56. };
  57. private static final FrameGeometry normalFrameGeometry = new NormalFrameGeometry();
  58. // draw_ops
  59. // <!-- Buttons -->
  60. private void active_button(Graphics g, int width, int height) {
  61. /*
  62. <image filename="active-button.png" x="0" y="0" width="width" height="height"/>
  63. */
  64. g.drawImage(getImage("active-button"), 0, 0, width, height, null);
  65. }
  66. private void active_button_pressed(Graphics g, int width, int height) {
  67. /*
  68. <image filename="active-button-pressed.png" x="0" y="0" width="width" height="height"/>
  69. */
  70. g.drawImage(getImage("active-button-pressed"), 0, 0, width, height, null);
  71. }
  72. private void active_button_prelight(Graphics g, int width, int height) {
  73. /*
  74. <image filename="active-button-prelight.png" x="0" y="0" width="width" height="height"/>
  75. */
  76. g.drawImage(getImage("active-button-prelight"), 0, 0, width, height, null);
  77. }
  78. private void inactive_button(Graphics g, int width, int height) {
  79. /*
  80. <image filename="inactive-button.png" x="0" y="0" width="width" height="height"/>
  81. */
  82. g.drawImage(getImage("inactive-button"), 0, 0, width, height, null);
  83. }
  84. private void inactive_button_pressed(Graphics g, int width, int height) {
  85. /*
  86. <image filename="inactive-button-pressed.png" x="0" y="0" width="width" height="height"/>
  87. */
  88. g.drawImage(getImage("inactive-button-pressed"), 0, 0, width, height, null);
  89. }
  90. private void inactive_button_prelight(Graphics g, int width, int height) {
  91. /*
  92. <image filename="inactive-button-prelight.png" x="0" y="0" width="width" height="height"/>
  93. */
  94. g.drawImage(getImage("inactive-button-prelight"), 0, 0, width, height, null);
  95. }
  96. void paintButtonBackground(SynthContext context, Graphics g, int x, int y, int w,int h) {
  97. this.context = context;
  98. JButton button = (JButton)context.getComponent();
  99. String buttonName = button.getName();
  100. int buttonState = context.getComponentState();
  101. JComponent titlePane = (JComponent)button.getParent();
  102. Container titlePaneParent = titlePane.getParent();
  103. JInternalFrame frame;
  104. if (titlePaneParent instanceof JInternalFrame) {
  105. frame = (JInternalFrame)titlePaneParent;
  106. } else if (titlePaneParent instanceof JInternalFrame.JDesktopIcon) {
  107. frame = ((JInternalFrame.JDesktopIcon)titlePaneParent).getInternalFrame();
  108. } else {
  109. return;
  110. }
  111. boolean active = frame.isSelected();
  112. setFrameGeometry(titlePane, normalFrameGeometry);
  113. if (!active) {
  114. if (buttonName.equals("InternalFrameTitlePane.menuButton")) {
  115. if ((buttonState & SynthConstants.PRESSED) != 0) {
  116. /*
  117. <image filename="inactive-menu-button-pressed.png" x="0" y="0" width="width" height="height"/>
  118. */
  119. g.drawImage(getImage("inactive-menu-button-pressed"), x, y, w, h, null);
  120. } else if ((buttonState & SynthConstants.MOUSE_OVER) != 0) {
  121. /*
  122. <image filename="inactive-menu-button-prelight.png" x="0" y="0" width="width" height="height"/>
  123. */
  124. g.drawImage(getImage("inactive-menu-button-prelight"), x, y, w, h, null);
  125. } else {
  126. /*
  127. <image filename="inactive-menu-button.png" x="0" y="0" width="width" height="height"/>
  128. */
  129. g.drawImage(getImage("inactive-menu-button"), x, y, w, h, null);
  130. }
  131. } else if (buttonName.equals("InternalFrameTitlePane.iconifyButton")) {
  132. if ((buttonState & SynthConstants.PRESSED) != 0) {
  133. /*
  134. <include name="inactive_button_pressed"/>
  135. <image filename="inactive-minimize-button.png" x="2" y="2" width="width-4" height="height-4"/>
  136. */
  137. inactive_button_pressed(g, w, h);
  138. g.drawImage(getImage("inactive-minimize-button"), x+2, y+2, w-4, h-4, null);
  139. } else if ((buttonState & SynthConstants.MOUSE_OVER) != 0) {
  140. /*
  141. <include name="inactive_button_prelight"/>
  142. <image filename="inactive-minimize-button.png" x="2" y="2" width="width-4" height="height-4"/>
  143. */
  144. inactive_button_prelight(g, w, h);
  145. g.drawImage(getImage("inactive-minimize-button"), x+2, y+2, w-4, h-4, null);
  146. } else {
  147. /*
  148. <include name="inactive_button"/>
  149. <image filename="inactive-minimize-button.png" x="2" y="2" width="width-4" height="height-4"/>
  150. */
  151. inactive_button(g, w, h);
  152. g.drawImage(getImage("inactive-minimize-button"), x+2, y+2, w-4, h-4, null);
  153. }
  154. } else if (buttonName.equals("InternalFrameTitlePane.maximizeButton")) {
  155. if ((buttonState & SynthConstants.PRESSED) != 0) {
  156. /*
  157. <include name="inactive_button_pressed"/>
  158. <image filename="inactive-maximize-button.png" x="2" y="2" width="width-4" height="height-4"/>
  159. */
  160. inactive_button_pressed(g, w, h);
  161. g.drawImage(getImage("inactive-maximize-button"), x+2, y+2, w-4, h-4, null);
  162. } else if ((buttonState & SynthConstants.MOUSE_OVER) != 0) {
  163. /*
  164. <include name="inactive_button_prelight"/>
  165. <image filename="inactive-maximize-button.png" x="2" y="2" width="width-4" height="height-4"/>
  166. */
  167. inactive_button_prelight(g, w, h);
  168. g.drawImage(getImage("inactive-maximize-button"), x+2, y+2, w-4, h-4, null);
  169. } else {
  170. /*
  171. <include name="inactive_button"/>
  172. <image filename="inactive-maximize-button.png" x="2" y="2" width="width-4" height="height-4"/>
  173. */
  174. inactive_button(g, w, h);
  175. g.drawImage(getImage("inactive-maximize-button"), x+2, y+2, w-4, h-4, null);
  176. }
  177. } else if (buttonName.equals("InternalFrameTitlePane.closeButton")) {
  178. if ((buttonState & SynthConstants.PRESSED) != 0) {
  179. /*
  180. <include name="inactive_button_pressed"/>
  181. <image filename="inactive-close-button.png" x="2" y="2" width="width-4" height="height-4"/>
  182. */
  183. inactive_button_pressed(g, w, h);
  184. g.drawImage(getImage("inactive-close-button"), x+2, y+2, w-4, h-4, null);
  185. } else if ((buttonState & SynthConstants.MOUSE_OVER) != 0) {
  186. /*
  187. <include name="inactive_button_prelight"/>
  188. <image filename="inactive-close-button.png" x="2" y="2" width="width-4" height="height-4"/>
  189. */
  190. inactive_button_prelight(g, w, h);
  191. g.drawImage(getImage("inactive-close-button"), x+2, y+2, w-4, h-4, null);
  192. } else {
  193. /*
  194. <include name="inactive_button"/>
  195. <image filename="inactive-close-button.png" x="2" y="2" width="width-4" height="height-4"/>
  196. */
  197. inactive_button(g, w, h);
  198. g.drawImage(getImage("inactive-close-button"), x+2, y+2, w-4, h-4, null);
  199. }
  200. }
  201. } else {
  202. if (buttonName.equals("InternalFrameTitlePane.menuButton")) {
  203. if ((buttonState & SynthConstants.PRESSED) != 0) {
  204. /*
  205. <image colorize="gtk:bg[SELECTED]" filename="active-menu-button-pressed.png" x="0" y="0" width="width" height="height"/>
  206. */
  207. g.drawImage(getImage("active-menu-button-pressed",
  208. getColor(SELECTED, GTKColorType.BACKGROUND)),
  209. x, y, w, h, null);
  210. } else if ((buttonState & SynthConstants.MOUSE_OVER) != 0) {
  211. /*
  212. <image colorize="gtk:bg[SELECTED]" filename="active-menu-button-prelight.png" x="0" y="0" width="width" height="height"/>
  213. */
  214. g.drawImage(getImage("active-menu-button-prelight",
  215. getColor(SELECTED, GTKColorType.BACKGROUND)),
  216. x, y, w, h, null);
  217. } else {
  218. /*
  219. <image colorize="gtk:bg[SELECTED]" filename="active-menu-button.png" x="0" y="0" width="width" height="height"/>
  220. */
  221. g.drawImage(getImage("active-menu-button",
  222. getColor(SELECTED, GTKColorType.BACKGROUND)),
  223. x, y, w, h, null);
  224. }
  225. } else if (buttonName.equals("InternalFrameTitlePane.iconifyButton")) {
  226. if ((buttonState & SynthConstants.PRESSED) != 0) {
  227. /*
  228. <include name="active_button_pressed"/>
  229. <image filename="active-minimize-button.png" x="2" y="2" width="width-4" height="height-4"/>
  230. */
  231. active_button_pressed(g, w, h);
  232. g.drawImage(getImage("active-minimize-button"), x+2, y+2, w-4, h-4, null);
  233. } else if ((buttonState & SynthConstants.MOUSE_OVER) != 0) {
  234. /*
  235. <include name="active_button_prelight"/>
  236. <image filename="active-minimize-button.png" x="2" y="2" width="width-4" height="height-4"/>
  237. */
  238. active_button_prelight(g, w, h);
  239. g.drawImage(getImage("active-minimize-button"), x+2, y+2, w-4, h-4, null);
  240. } else {
  241. /*
  242. <include name="active_button"/>
  243. <image filename="active-minimize-button.png" x="2" y="2" width="width-4" height="height-4"/>
  244. */
  245. active_button(g, w, h);
  246. g.drawImage(getImage("active-minimize-button"), x+2, y+2, w-4, h-4, null);
  247. }
  248. } else if (buttonName.equals("InternalFrameTitlePane.maximizeButton")) {
  249. if ((buttonState & SynthConstants.PRESSED) != 0) {
  250. /*
  251. <include name="active_button_pressed"/>
  252. <image filename="active-maximize-button.png" x="2" y="2" width="width-4" height="height-4"/>
  253. */
  254. active_button_pressed(g, w, h);
  255. g.drawImage(getImage("active-maximize-button"), x+2, y+2, w-4, h-4, null);
  256. } else if ((buttonState & SynthConstants.MOUSE_OVER) != 0) {
  257. /*
  258. <include name="active_button_prelight"/>
  259. <image filename="active-maximize-button.png" x="2" y="2" width="width-4" height="height-4"/>
  260. */
  261. active_button_prelight(g, w, h);
  262. g.drawImage(getImage("active-maximize-button"), x+2, y+2, w-4, h-4, null);
  263. } else {
  264. /*
  265. <include name="active_button"/>
  266. <image filename="active-maximize-button.png" x="2" y="2" width="width-4" height="height-4"/>
  267. */
  268. active_button(g, w, h);
  269. g.drawImage(getImage("active-maximize-button"), x+2, y+2, w-4, h-4, null);
  270. }
  271. } else if (buttonName.equals("InternalFrameTitlePane.closeButton")) {
  272. if ((buttonState & SynthConstants.PRESSED) != 0) {
  273. /*
  274. <include name="active_button_pressed"/>
  275. <image filename="active-close-button.png" x="2" y="2" width="width-4" height="height-4"/>
  276. */
  277. active_button_pressed(g, w, h);
  278. g.drawImage(getImage("active-close-button"), x+2, y+2, w-4, h-4, null);
  279. } else if ((buttonState & SynthConstants.MOUSE_OVER) != 0) {
  280. /*
  281. <include name="active_button_prelight"/>
  282. <image filename="active-close-button.png" x="2" y="2" width="width-4" height="height-4"/>
  283. */
  284. active_button_prelight(g, w, h);
  285. g.drawImage(getImage("active-close-button"), x+2, y+2, w-4, h-4, null);
  286. } else {
  287. /*
  288. <include name="active_button"/>
  289. <image filename="active-close-button.png" x="2" y="2" width="width-4" height="height-4"/>
  290. */
  291. active_button(g, w, h);
  292. g.drawImage(getImage("active-close-button"), x+2, y+2, w-4, h-4, null);
  293. }
  294. }
  295. }
  296. }
  297. private void paintTitleBar(Graphics g, int width, int height,
  298. boolean active, JInternalFrame frame, JComponent titlePane) {
  299. Image leftTopBorder = getImage("left-top-border", active);
  300. Image topCenterLeft = getImage("top-center-left", active);
  301. Image topCenterRight = getImage("top-center-right", active);
  302. Image rightTopBorder = getImage("right-top-border", active);
  303. Image topCenterMidLeft = getImage("top-center-mid-left", active);
  304. Image topCenterMidRight = getImage("top-center-mid-right", active);
  305. Image topCenterMid = getImage("top-center-mid", active);
  306. FrameGeometry gm = getFrameGeometry();
  307. FontMetrics fm = g.getFontMetrics();
  308. int title_width = calculateTitleWidth(frame, titlePane, fm);
  309. int x, y, w, h;
  310. Image object;
  311. if (!active) {
  312. /*
  313. <image filename="inactive-left-top-border.png"
  314. x="0" y="0" width="object_width" height="height"/>
  315. */
  316. object = leftTopBorder;
  317. x = 0; y = 0; w = object.getWidth(null); h = height;
  318. g.drawImage(object, x, y, w, h, null);
  319. /*
  320. <image filename="inactive-right-top-border.png"
  321. x="width - object_width" y="0" width="object_width" height="height"/>
  322. */
  323. object = rightTopBorder;
  324. x = width - object.getWidth(null); y = 0; w = object.getWidth(null); h = height;
  325. g.drawImage(object, x, y, w, h, null);
  326. /*
  327. <image filename="inactive-top-center-left.png"
  328. x="4" y="0"
  329. width="(left_width + ButtonWidth + IconTitleSpacing + title_width) `min`
  330. (width - right_width - 3 * ButtonWidth
  331. - CenterTitlePieceWidth * height / 22 - 3)"
  332. height="height"/>
  333. */
  334. object = topCenterLeft;
  335. x = 4; y = 0;
  336. w = Math.min(gm.left_width + ButtonWidth + IconTitleSpacing + title_width,
  337. width - gm.right_width - 3 * ButtonWidth
  338. - CenterTitlePieceWidth * height / 22 - 3);
  339. h = height;
  340. g.drawImage(object, x, y, w, h, null);
  341. /*
  342. <image filename="inactive-top-center-mid.png"
  343. x="((left_width + ButtonWidth + IconTitleSpacing + title_width) `min`
  344. (width - object_width * height / 22 - right_width - 3 * ButtonWidth)) + 1"
  345. y="0" width="object_width * height / 22" height="height"/>
  346. */
  347. object = topCenterMid;
  348. if (topCenterMid == null) {
  349. object = topCenterMidLeft;
  350. }
  351. x = Math.min(gm.left_width + ButtonWidth + IconTitleSpacing + title_width,
  352. width - object.getWidth(null) * height / 22 - gm.right_width
  353. - 3 * ButtonWidth) + 1;
  354. y = 0; w = object.getWidth(null) * height / 22; h = height;
  355. g.drawImage(object, x, y, w, h, null);
  356. if (topCenterMid == null) {
  357. object = topCenterMidRight;
  358. g.drawImage(object, x, y, w, h, null);
  359. }
  360. /*
  361. <image filename="inactive-top-center-right.png"
  362. x="((left_width + ButtonWidth + IconTitleSpacing + title_width
  363. + CenterTitlePieceWidth * height / 22) `min`
  364. (width - 3 * ButtonWidth - right_width)) + 1"
  365. y="0"
  366. width="(width - title_width - left_width - ButtonWidth - IconTitleSpacing
  367. - CenterTitlePieceWidth * height / 22 - right_width) `max`
  368. (3 * ButtonWidth)"
  369. height="height"/>
  370. */
  371. object = topCenterRight;
  372. x = Math.min(gm.left_width + ButtonWidth + IconTitleSpacing + title_width
  373. + CenterTitlePieceWidth * height / 22,
  374. width - 3 * ButtonWidth - gm.right_width) + 1;
  375. y = 0;
  376. w = Math.max(width - title_width - gm.left_width - ButtonWidth - IconTitleSpacing
  377. - CenterTitlePieceWidth * height / 22 - gm.right_width,
  378. 3 * ButtonWidth);
  379. h = height;
  380. g.drawImage(object, x, y, w, h, null);
  381. } else {
  382. /*
  383. <image filename="active-left-top-border.png"
  384. colorize="gtk:bg[SELECTED]"
  385. x="0" y="0" width="object_width" height="height"/>
  386. */
  387. object = getImage("active-left-top-border", getColor(SELECTED, GTKColorType.BACKGROUND));
  388. x = 0; y = 0; w = object.getWidth(null); h = height;
  389. g.drawImage(object, x, y, w, h, null);
  390. /*
  391. <image filename="active-right-top-border.png"
  392. x="width - object_width" y="0" width="object_width" height="height"/>
  393. */
  394. object = rightTopBorder;
  395. x = width - object.getWidth(null); y = 0; w = object.getWidth(null); h = height;
  396. g.drawImage(object, x, y, w, h, null);
  397. /*
  398. <image filename="active-top-center-left.png"
  399. colorize="gtk:bg[SELECTED]"
  400. x="4" y="0"
  401. width="(left_width + ButtonWidth + IconTitleSpacing + title_width) `min`
  402. (width - right_width - 3 * ButtonWidth
  403. - CenterTitlePieceWidth * height / 22 - 3)"
  404. height="height"/>
  405. */
  406. object = getImage("active-top-center-left", getColor(SELECTED, GTKColorType.BACKGROUND));
  407. x = 4; y = 0;
  408. w = Math.min(gm.left_width + ButtonWidth + IconTitleSpacing + title_width,
  409. width - gm.right_width - 3 * ButtonWidth
  410. - CenterTitlePieceWidth * height / 22 - 3);
  411. h = height;
  412. g.drawImage(object, x, y, w, h, null);
  413. /*
  414. <image filename="active-top-center-mid-left.png"
  415. colorize="gtk:bg[SELECTED]"
  416. x="((left_width + ButtonWidth + IconTitleSpacing + title_width) `min`
  417. (width - object_width * height / 22 - right_width - 3 * ButtonWidth)) + 1"
  418. y="0" width="object_width * height / 22" height="height"/>
  419. */
  420. object = getImage("active-top-center-mid-left", getColor(SELECTED, GTKColorType.BACKGROUND));
  421. x = Math.min(gm.left_width + ButtonWidth + IconTitleSpacing + title_width,
  422. width - object.getWidth(null) * height / 22 - gm.right_width - 3 * ButtonWidth) + 1;
  423. y = 0; w = object.getWidth(null) * height / 22; h = height;
  424. g.drawImage(object, x, y, w, h, null);
  425. /*
  426. <image filename="active-top-center-mid-right.png"
  427. x="((left_width + ButtonWidth + IconTitleSpacing + title_width) `min`
  428. (width - object_width * height / 22 - right_width - 3 * ButtonWidth)) + 1"
  429. y="0" width="object_width * height / 22" height="height"/>
  430. */
  431. object = topCenterMidRight;
  432. x = Math.min(gm.left_width + ButtonWidth + IconTitleSpacing + title_width,
  433. width - object.getWidth(null) * height / 22 - gm.right_width - 3 * ButtonWidth) + 1;
  434. y = 0; w = object.getWidth(null) * height / 22; h = height;
  435. g.drawImage(object, x, y, w, h, null);
  436. /*
  437. <image filename="active-top-center-right.png"
  438. x="((left_width + ButtonWidth + IconTitleSpacing + title_width
  439. + CenterTitlePieceWidth * height / 22) `min`
  440. (width - 3 * ButtonWidth - right_width)) + 1"
  441. y="0"
  442. width="(width - title_width - left_width - ButtonWidth - IconTitleSpacing
  443. - CenterTitlePieceWidth * height / 22 - right_width) `max`
  444. (3 * ButtonWidth)"
  445. height="height"/>
  446. */
  447. object = topCenterRight;
  448. x = Math.min(gm.left_width + ButtonWidth + IconTitleSpacing + title_width
  449. + CenterTitlePieceWidth * height / 22,
  450. width - 3 * ButtonWidth - gm.right_width) + 1;
  451. y = 0;
  452. w = Math.max(width - title_width - gm.left_width - ButtonWidth - IconTitleSpacing
  453. - CenterTitlePieceWidth * height / 22 - gm.right_width,
  454. 3 * ButtonWidth);
  455. h = height;
  456. g.drawImage(object, x, y, w, h, null);
  457. }
  458. Color textColor;
  459. if (!active) {
  460. /*
  461. <piece position="title">
  462. <draw_ops>
  463. <title color="white" x="IconTitleSpacing" y="0"/>
  464. </draw_ops>
  465. </piece>
  466. */
  467. textColor = Color.white;
  468. } else {
  469. /*
  470. <piece position="title">
  471. <draw_ops>
  472. <title color="white" x="IconTitleSpacing" y="((height - title_height) / 2) `max` 0"/>
  473. </draw_ops>
  474. </piece>
  475. */
  476. textColor = Color.white;
  477. }
  478. String title = frame.getTitle();
  479. if (title != null) {
  480. // Center text vertically.
  481. int baseline = (height + fm.getAscent() - fm.getLeading() - fm.getDescent()) / 2;
  482. int titleX;
  483. if (frame.getComponentOrientation().isLeftToRight()) {
  484. title = getTitle(title, fm, title_width);
  485. titleX = gm.left_width + ButtonWidth + IconTitleSpacing;
  486. } else {
  487. titleX = width - gm.right_width - ButtonWidth - 2 - SwingUtilities.computeStringWidth(fm, title);
  488. }
  489. g.setColor(textColor);
  490. g.drawString(title, titleX, baseline);
  491. }
  492. }
  493. private int calculateTitleWidth(JInternalFrame frame, JComponent titlePane, FontMetrics fm) {
  494. FrameGeometry gm = getFrameGeometry();
  495. String title = frame.getTitle();
  496. if (title != null) {
  497. JComponent button = null;
  498. if (frame.isIconifiable()) {
  499. button = findChild(titlePane, "InternalFrameTitlePane.iconifyButton");
  500. }
  501. if (button == null && frame.isMaximizable()) {
  502. button = findChild(titlePane, "InternalFrameTitlePane.maximizeButton");
  503. }
  504. if (button == null && frame.isClosable()) {
  505. button = findChild(titlePane, "InternalFrameTitlePane.closeButton");
  506. }
  507. int buttonX = (button != null) ? button.getX() : (titlePane.getWidth() - gm.right_titlebar_edge);
  508. return Math.min(SwingUtilities.computeStringWidth(fm, title),
  509. buttonX - (gm.left_width + ButtonWidth + IconTitleSpacing) - 3);
  510. }
  511. return 0;
  512. }
  513. private String getTitle(String text, FontMetrics fm, int availTextWidth) {
  514. if ((text == null) || (text.equals(""))) {
  515. return "";
  516. }
  517. int textWidth = SwingUtilities.computeStringWidth(fm, text);
  518. String clipString = "...";
  519. if (textWidth > availTextWidth) {
  520. int totalWidth = SwingUtilities.computeStringWidth(fm, clipString);
  521. int nChars;
  522. for (nChars = 0; nChars < text.length(); nChars++) {
  523. totalWidth += fm.charWidth(text.charAt(nChars));
  524. if (totalWidth > availTextWidth) {
  525. break;
  526. }
  527. }
  528. text = text.substring(0, nChars) + clipString;
  529. }
  530. return text;
  531. }
  532. void paintFrameBorder(SynthContext context, Graphics g, int x0, int y0, int width, int height) {
  533. this.context = context;
  534. JInternalFrame frame = (JInternalFrame)context.getComponent();
  535. JComponent titlePane = findChild(frame, "InternalFrame.northPane");
  536. //boolean active = ((context.getComponentState() & SynthConstants.SELECTED) != 0);
  537. boolean active = frame.isSelected();
  538. setFrameGeometry(titlePane, normalFrameGeometry);
  539. Image leftBorder = getImage("left-border", active);
  540. Image rightBorder = getImage("right-border", active);
  541. Image bottomLeftCorner = getImage("bottom-left-corner", active);
  542. Image bottomLeftBorder = getImage("bottom-left-border", active);
  543. Image bottomRightBorder = getImage("bottom-right-border", active);
  544. Image bottomRightCorner = getImage("bottom-right-corner", active);
  545. Image bottomMidBorder = getImage("bottom-mid-border", active);
  546. Image bottomMidLeftBorder = getImage("bottom-mid-left-border", active);
  547. Image bottomMidRightBorder = getImage("bottom-mid-right-border", active);
  548. Font oldFont = g.getFont();
  549. g.setFont(titlePane.getFont());
  550. g.translate(x0, y0);
  551. paintTitleBar(g, width, titlePane.getHeight(), active, frame, titlePane);
  552. FontMetrics fm = g.getFontMetrics();
  553. int title_width = calculateTitleWidth(frame, titlePane, fm);
  554. int title_height = (titlePane != null) ? titlePane.getPreferredSize().height : 16;
  555. int x, y, w, h;
  556. Image object;
  557. if (leftBorder == null) {
  558. // Ouch, we don't have any images. Let's just paint a border for now.
  559. g.setColor(active ? Color.black : Color.gray);
  560. g.drawRect(0, 0, width-1, height-1);
  561. } else if (!active) {
  562. /*
  563. <image filename="inactive-left-border.png" x="0" y="0" width="object_width" height="height"/>
  564. */
  565. object = leftBorder; x = 0; y = 0; w = object.getWidth(null); h = height;
  566. // Adjust for our positioning system
  567. y = title_height;
  568. h = height - title_height - bottomLeftCorner.getHeight(null);
  569. g.drawImage(object, x, y, w, h, null);
  570. /*
  571. <image filename="inactive-right-border.png" x="0" y="0" width="object_width" height="height"/>
  572. */
  573. object = rightBorder; x = 0; y = 0; w = object.getWidth(null); h = height;
  574. // Adjust for our positioning system
  575. x = width - rightBorder.getWidth(null);
  576. y = title_height;
  577. h = height - title_height - bottomRightCorner.getHeight(null);
  578. g.drawImage(object, x, y, w, h, null);
  579. /*
  580. <image filename="inactive-bottom-left-corner.png"
  581. x="0" y="height - object_height" width="object_width" height="object_height"/>
  582. */
  583. object = bottomLeftCorner;
  584. x = 0; y = height - object.getHeight(null);
  585. w = object.getWidth(null); h = object.getHeight(null);
  586. g.drawImage(object, x, y, w, h, null);
  587. /*
  588. <image filename="inactive-bottom-left-border.png" x="5" y="height - object_height"
  589. width="((title_width + height / 2 - 4) `min` (width - object_width - 26))"
  590. height="object_height"/>
  591. */
  592. object = bottomLeftBorder; x = 5; y = height - object.getHeight(null);
  593. w = Math.min((title_width + height / 2 - 4), (width - object.getWidth(null) - 26));
  594. h = object.getHeight(null);
  595. g.drawImage(object, x, y, w, h, null);
  596. /*
  597. <image filename="inactive-bottom-mid-border.png"
  598. x="((title_width + height / 2) `min` (width - object_width - 6)) + 1"
  599. y="height - object_height" width="object_width" height="object_height"/>
  600. */
  601. object = bottomMidBorder;
  602. if (bottomMidBorder == null) {
  603. object = bottomMidLeftBorder;
  604. }
  605. x = Math.min((title_width + height / 2), (width - object.getWidth(null) - 6)) + 1;
  606. y = height - object.getHeight(null);
  607. w = object.getWidth(null); h = object.getHeight(null);
  608. g.drawImage(object, x, y, w, h, null);
  609. if (bottomMidBorder == null) {
  610. object = bottomMidRightBorder;
  611. g.drawImage(object, x, y, w, h, null);
  612. }
  613. /*
  614. <image filename="inactive-bottom-right-border.png"
  615. x="((title_width + height / 2 + 32)) + 1"
  616. y="height - object_height"
  617. width="(width - title_width - height / 2 - 32 - 7) `max` 0"
  618. height="object_height"/>
  619. */
  620. object = bottomRightBorder;
  621. x = (title_width + height / 2 + 32) + 1;
  622. y = height - object.getHeight(null);
  623. w = Math.max((width - title_width - height / 2 - 32 - 7), 0);
  624. h = object.getHeight(null);
  625. g.drawImage(object, x, y, w, h, null);
  626. /*
  627. <image filename="inactive-bottom-right-corner.png"
  628. x="width - object_width" y="height - object_height"
  629. width="object_height" height="object_height"/>
  630. */
  631. object = bottomRightCorner;
  632. x = width - object.getWidth(null); y = height - object.getHeight(null);
  633. w = object.getWidth(null); h = object.getHeight(null);
  634. g.drawImage(object, x, y, w, h, null);
  635. } else {
  636. /*
  637. <image colorize="gtk:bg[SELECTED]" filename="active-left-border.png"
  638. x="0" y="0" width="object_width" height="height"/>
  639. */
  640. object = getImage("active-left-border", getColor(SELECTED, GTKColorType.BACKGROUND));
  641. x = 0; y = 0; w = object.getWidth(null); h = height;
  642. // Adjust for our positioning system
  643. y = title_height;
  644. h = height - title_height - bottomLeftCorner.getHeight(null);
  645. g.drawImage(object, x, y, w, h, null);
  646. /*
  647. <image filename="active-right-border.png"
  648. x="0" y="0" width="object_width" height="height"/>
  649. */
  650. object = rightBorder; x = 0; y = 0; w = object.getWidth(null); h = height;
  651. // Adjust for our positioning system
  652. x = width - rightBorder.getWidth(null);
  653. y = title_height;
  654. h = height - title_height - bottomRightCorner.getHeight(null);
  655. g.drawImage(object, x, y, w, h, null);
  656. /*
  657. <image filename="active-bottom-left-corner.png"
  658. colorize="gtk:bg[SELECTED]"
  659. x="0" y="height - object_height" width="object_width" height="object_height"/>
  660. */
  661. object = getImage("active-bottom-left-corner", getColor(SELECTED, GTKColorType.BACKGROUND));
  662. x = 0; y = height - object.getHeight(null);
  663. w = object.getWidth(null); h = object.getHeight(null);
  664. g.drawImage(object, x, y, w, h, null);
  665. /*
  666. <image filename="active-bottom-left-border.png" x="5" y="height - object_height"
  667. colorize="gtk:bg[SELECTED]"
  668. width="((title_width + height / 2 - 4) `min` (width - object_width - 26))"
  669. height="object_height"/>
  670. */
  671. object = getImage("active-bottom-left-border", getColor(SELECTED, GTKColorType.BACKGROUND));
  672. x = 5; y = height - object.getHeight(null);
  673. w = Math.min((title_width + height / 2 - 4), (width - object.getWidth(null) - 26));
  674. h = object.getHeight(null);
  675. g.drawImage(object, x, y, w, h, null);
  676. /*
  677. <image filename="active-bottom-mid-left-border.png"
  678. colorize="gtk:bg[SELECTED]"
  679. x="((title_width + height / 2) `min` (width - object_width - 6)) + 1"
  680. y="height - object_height" width="object_width" height="object_height"/>
  681. */
  682. object = getImage("active-bottom-mid-left-border", getColor(SELECTED, GTKColorType.BACKGROUND));
  683. x = Math.min((title_width + height / 2), (width - object.getWidth(null) - 6)) + 1;
  684. y = height - object.getHeight(null); w = object.getWidth(null); h = object.getHeight(null);
  685. g.drawImage(object, x, y, w, h, null);
  686. /*
  687. <image filename="active-bottom-mid-right-border.png"
  688. x="((title_width + height / 2) `min` (width - object_width - 6)) + 1"
  689. y="height - object_height" width="object_width" height="object_height"/>
  690. */
  691. object = bottomMidRightBorder;
  692. x = Math.min((title_width + height / 2), (width - object.getWidth(null) - 6)) + 1;
  693. y = height - object.getHeight(null); w = object.getWidth(null); h = object.getHeight(null);
  694. g.drawImage(object, x, y, w, h, null);
  695. /*
  696. <image filename="active-bottom-right-border.png"
  697. x="((title_width + height / 2 + 32)) + 1"
  698. y="height - object_height"
  699. width="(width - title_width - height / 2 - 32 - 7) `max` 0"
  700. height="object_height"/>
  701. */
  702. object = bottomRightBorder;
  703. x = (title_width + height / 2 + 32) + 1;
  704. y = height - object.getHeight(null);
  705. w = Math.max((width - title_width - height / 2 - 32 - 7), 0);
  706. h = object.getHeight(null);
  707. g.drawImage(object, x, y, w, h, null);
  708. /*
  709. <image filename="active-bottom-right-corner.png"
  710. x="width - object_width" y="height - object_height"
  711. width="object_height" height="object_height"/>
  712. */
  713. object = bottomRightCorner;
  714. x = width - object.getWidth(null); y = height - object.getHeight(null);
  715. w = object.getWidth(null); h = object.getHeight(null);
  716. g.drawImage(object, x, y, w, h, null);
  717. }
  718. g.translate(-x0, -y0);
  719. g.setFont(oldFont);
  720. }
  721. Insets getBorderInsets(SynthContext context, Insets insets) {
  722. FrameGeometry gm = getFrameGeometry();
  723. if (insets == null) {
  724. insets = new Insets(0, 0, 0, 0);
  725. }
  726. insets.top = gm.title_border.top;
  727. insets.bottom = gm.bottom_height;
  728. insets.left = gm.left_width;
  729. insets.right = gm.right_width;
  730. return insets;
  731. }
  732. private HashMap images = new HashMap();
  733. private Image getImage(String key, Color c) {
  734. Image image = (Image)images.get(key+"-"+c.getRGB());
  735. if (image == null) {
  736. image = colorizeImage(getImage(key), c);
  737. if (image != null) {
  738. images.put(key+"-"+c.getRGB(), image);
  739. }
  740. }
  741. return image;
  742. }
  743. private Image getImage(String key) {
  744. Image image = (Image)images.get(key);
  745. if (image == null) {
  746. if (themeDir != null) {
  747. final String file = themeDir + File.separator + key + ".png";
  748. image = (Image)AccessController.doPrivileged(new PrivilegedAction() {
  749. public Object run() {
  750. return new ImageIcon(file).getImage();
  751. }
  752. });
  753. } else {
  754. String filename = "resources/metacity/"+key+".png";
  755. URL url = getClass().getResource(filename);
  756. if (url != null) {
  757. image = new ImageIcon(url).getImage();
  758. }
  759. }
  760. if (image == null && key.startsWith("inactive")) {
  761. image = getImage(key.substring(2));
  762. }
  763. if (image != null) {
  764. images.put(key, image);
  765. }
  766. }
  767. return image;
  768. }
  769. private Image getImage(String key, boolean active) {
  770. return getImage((active ? "active" : "inactive") + "-" + key);
  771. }
  772. }