1. /*
  2. * @(#)Metacity.java 1.22 04/06/24
  3. *
  4. * Copyright 2004 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 com.sun.java.swing.SwingUtilities2;
  9. import javax.swing.plaf.synth.*;
  10. import java.awt.*;
  11. import java.awt.geom.*;
  12. import java.awt.image.*;
  13. import java.io.*;
  14. import java.net.*;
  15. import java.security.*;
  16. import java.util.*;
  17. import javax.swing.*;
  18. import javax.swing.border.*;
  19. import javax.xml.parsers.*;
  20. import org.xml.sax.SAXException;
  21. import org.w3c.dom.*;
  22. /**
  23. * @version 1.22, 06/24/04
  24. */
  25. class Metacity implements SynthConstants {
  26. // Tutorial:
  27. // http://developer.gnome.org/doc/tutorials/metacity/metacity-themes.html
  28. // Themes:
  29. // http://art.gnome.org/theme_list.php?category=metacity
  30. static Metacity INSTANCE;
  31. private static final String[] themeNames = {
  32. getUserTheme(),
  33. "blueprint",
  34. "Bluecurve",
  35. "Crux",
  36. "SwingFallbackTheme"
  37. };
  38. static {
  39. for (String themeName : themeNames) {
  40. if (themeName != null) {
  41. try {
  42. INSTANCE = new Metacity(themeName);
  43. } catch (FileNotFoundException ex) {
  44. } catch (IOException ex) {
  45. logError(themeName, ex);
  46. } catch (ParserConfigurationException ex) {
  47. logError(themeName, ex);
  48. } catch (SAXException ex) {
  49. logError(themeName, ex);
  50. }
  51. }
  52. if (INSTANCE != null) {
  53. break;
  54. }
  55. }
  56. if (INSTANCE == null) {
  57. throw new Error("Could not find any installed metacity theme, and fallback failed");
  58. }
  59. }
  60. private static boolean errorLogged = false;
  61. private static DocumentBuilder documentBuilder;
  62. private static Document xmlDoc;
  63. private static String userHome;
  64. private Node frame_style_set;
  65. private Map<String, Object> frameGeometry;
  66. private Map<String, Map<String, Object>> frameGeometries;
  67. private LayoutManager titlePaneLayout = new TitlePaneLayout();
  68. private ColorizeImageFilter imageFilter = new ColorizeImageFilter();
  69. private URL themeDir = null;
  70. private SynthContext context;
  71. private String themeName;
  72. private ArithmeticExpressionEvaluator aee = new ArithmeticExpressionEvaluator();
  73. private Map<String, Integer> variables;
  74. // Reusable clip shape object
  75. private RoundRectClipShape roundedClipShape;
  76. protected Metacity(String themeName) throws IOException, ParserConfigurationException, SAXException {
  77. this.themeName = themeName;
  78. themeDir = getThemeDir(themeName);
  79. if (themeDir != null) {
  80. URL themeURL = new URL(themeDir, "metacity-theme-1.xml");
  81. xmlDoc = getXMLDoc(themeURL);
  82. if (xmlDoc == null) {
  83. throw new IOException(themeURL.toString());
  84. }
  85. } else {
  86. throw new FileNotFoundException(themeName);
  87. }
  88. // Initialize constants
  89. variables = new HashMap();
  90. NodeList nodes = xmlDoc.getElementsByTagName("constant");
  91. int n = nodes.getLength();
  92. for (int i = 0; i < n; i++) {
  93. Node node = nodes.item(i);
  94. String name = getStringAttr(node, "name");
  95. if (name != null) {
  96. String value = getStringAttr(node, "value");
  97. if (value != null) {
  98. try {
  99. variables.put(name, Integer.parseInt(value));
  100. } catch (NumberFormatException ex) {
  101. logError(themeName, ex);
  102. // Ignore bad value
  103. }
  104. }
  105. }
  106. }
  107. // Cache frame geometries
  108. frameGeometries = new HashMap();
  109. nodes = xmlDoc.getElementsByTagName("frame_geometry");
  110. n = nodes.getLength();
  111. for (int i = 0; i < n; i++) {
  112. Node node = nodes.item(i);
  113. String name = getStringAttr(node, "name");
  114. if (name != null) {
  115. HashMap<String, Object> gm = new HashMap();
  116. frameGeometries.put(name, gm);
  117. String parentGM = getStringAttr(node, "parent");
  118. if (parentGM != null) {
  119. gm.putAll(frameGeometries.get(parentGM));
  120. }
  121. gm.put("has_title",
  122. Boolean.valueOf(getBooleanAttr(node, "has_title", true)));
  123. gm.put("rounded_top_left",
  124. Boolean.valueOf(getBooleanAttr(node, "rounded_top_left", false)));
  125. gm.put("rounded_top_right",
  126. Boolean.valueOf(getBooleanAttr(node, "rounded_top_right", false)));
  127. gm.put("rounded_bottom_left",
  128. Boolean.valueOf(getBooleanAttr(node, "rounded_bottom_left", false)));
  129. gm.put("rounded_bottom_right",
  130. Boolean.valueOf(getBooleanAttr(node, "rounded_bottom_right", false)));
  131. NodeList childNodes = node.getChildNodes();
  132. int nc = childNodes.getLength();
  133. for (int j = 0; j < nc; j++) {
  134. Node child = childNodes.item(j);
  135. if (child.getNodeType() == Node.ELEMENT_NODE) {
  136. name = child.getNodeName();
  137. Object value = null;
  138. if ("distance".equals(name)) {
  139. value = new Integer(getIntAttr(child, "value", 0));
  140. } else if ("border".equals(name)) {
  141. value = new Insets(getIntAttr(child, "top", 0),
  142. getIntAttr(child, "left", 0),
  143. getIntAttr(child, "bottom", 0),
  144. getIntAttr(child, "right", 0));
  145. } else if ("aspect_ratio".equals(name)) {
  146. value = new Float(getFloatAttr(child, "value", 1.0F));
  147. } else {
  148. logError(themeName, "Unknown Metacity frame geometry value type: "+name);
  149. }
  150. String childName = getStringAttr(child, "name");
  151. if (childName != null && value != null) {
  152. gm.put(childName, value);
  153. }
  154. }
  155. }
  156. }
  157. }
  158. frameGeometry = frameGeometries.get("normal");
  159. }
  160. public static LayoutManager getTitlePaneLayout() {
  161. return INSTANCE.titlePaneLayout;
  162. }
  163. private Shape getRoundedClipShape(int x, int y, int w, int h,
  164. int arcw, int arch, int corners) {
  165. if (roundedClipShape == null) {
  166. roundedClipShape = new RoundRectClipShape();
  167. }
  168. roundedClipShape.setRoundedRect(x, y, w, h, arcw, arch, corners);
  169. return roundedClipShape;
  170. }
  171. void paintButtonBackground(SynthContext context, Graphics g, int x, int y, int w, int h) {
  172. this.context = context;
  173. JButton button = (JButton)context.getComponent();
  174. String buttonName = button.getName();
  175. int buttonState = context.getComponentState();
  176. JComponent titlePane = (JComponent)button.getParent();
  177. Container titlePaneParent = titlePane.getParent();
  178. JInternalFrame jif;
  179. if (titlePaneParent instanceof JInternalFrame) {
  180. jif = (JInternalFrame)titlePaneParent;
  181. } else if (titlePaneParent instanceof JInternalFrame.JDesktopIcon) {
  182. jif = ((JInternalFrame.JDesktopIcon)titlePaneParent).getInternalFrame();
  183. } else {
  184. return;
  185. }
  186. boolean active = jif.isSelected();
  187. button.setOpaque(false);
  188. String state = "normal";
  189. if ((buttonState & PRESSED) != 0) {
  190. state = "pressed";
  191. } else if ((buttonState & MOUSE_OVER) != 0) {
  192. state = "prelight";
  193. }
  194. String function = null;
  195. String location = null;
  196. boolean left_corner = false;
  197. boolean right_corner = false;
  198. if (buttonName == "InternalFrameTitlePane.menuButton") {
  199. function = "menu";
  200. location = "left_left";
  201. left_corner = true;
  202. } else if (buttonName == "InternalFrameTitlePane.iconifyButton") {
  203. function = "minimize";
  204. int nButtons = ((jif.isIconifiable() ? 1 : 0) +
  205. (jif.isMaximizable() ? 1 : 0) +
  206. (jif.isClosable() ? 1 : 0));
  207. right_corner = (nButtons == 1);
  208. switch (nButtons) {
  209. case 1: location = "right_right"; break;
  210. case 2: location = "right_middle"; break;
  211. case 3: location = "right_left"; break;
  212. }
  213. } else if (buttonName == "InternalFrameTitlePane.maximizeButton") {
  214. function = "maximize";
  215. right_corner = !jif.isClosable();
  216. location = jif.isClosable() ? "right_middle" : "right_right";
  217. } else if (buttonName == "InternalFrameTitlePane.closeButton") {
  218. function = "close";
  219. right_corner = true;
  220. location = "right_right";
  221. }
  222. Node frame = getNode(frame_style_set, "frame", new String[] {
  223. "focus", (active ? "yes" : "no"),
  224. "state", (jif.isMaximum() ? "maximized" : "normal")
  225. });
  226. if (function != null && frame != null) {
  227. Node frame_style = getNode("frame_style", new String[] {
  228. "name", getStringAttr(frame, "style")
  229. });
  230. if (frame_style != null) {
  231. setFrameGeometry(titlePane,
  232. frameGeometries.get(getStringAttr(frame_style, "geometry")));
  233. Shape oldClip = g.getClip();
  234. if ((right_corner && getBoolean("rounded_top_right", false)) ||
  235. (left_corner && getBoolean("rounded_top_left", false))) {
  236. Point buttonLoc = button.getLocation();
  237. if (right_corner) {
  238. g.setClip(getRoundedClipShape(0, 0, w, h,
  239. 12, 12, RoundRectClipShape.TOP_RIGHT));
  240. } else {
  241. g.setClip(getRoundedClipShape(0, 0, w, h,
  242. 11, 11, RoundRectClipShape.TOP_LEFT));
  243. }
  244. }
  245. drawButton(frame_style, location+"_background", state, g, w, h, jif);
  246. drawButton(frame_style, function, state, g, w, h, jif);
  247. g.setClip(oldClip);
  248. }
  249. }
  250. }
  251. protected void drawButton(Node frame_style, String function, String state,
  252. Graphics g, int w, int h, JInternalFrame jif) {
  253. Node buttonNode = getNode(frame_style, "button",
  254. new String[] { "function", function, "state", state });
  255. if (buttonNode == null && !state.equals("normal")) {
  256. buttonNode = getNode(frame_style, "button",
  257. new String[] { "function", function, "state", "normal" });
  258. }
  259. if (buttonNode != null) {
  260. Node draw_ops;
  261. String draw_ops_name = getStringAttr(buttonNode, "draw_ops");
  262. if (draw_ops_name != null) {
  263. draw_ops = getNode("draw_ops", new String[] { "name", draw_ops_name });
  264. } else {
  265. draw_ops = getNode(buttonNode, "draw_ops", null);
  266. }
  267. variables.put("width", w);
  268. variables.put("height", h);
  269. draw(draw_ops, g, jif);
  270. }
  271. }
  272. void paintFrameBorder(SynthContext context, Graphics g, int x0, int y0, int width, int height) {
  273. this.context = context;
  274. JComponent comp = context.getComponent();
  275. JComponent titlePane = findChild(comp, "InternalFrame.northPane");
  276. if (titlePane == null) {
  277. return;
  278. }
  279. JInternalFrame jif = null;
  280. if (comp instanceof JInternalFrame) {
  281. jif = (JInternalFrame)comp;
  282. } else if (comp instanceof JInternalFrame.JDesktopIcon) {
  283. jif = ((JInternalFrame.JDesktopIcon)comp).getInternalFrame();
  284. } else {
  285. return;
  286. }
  287. boolean active = jif.isSelected();
  288. Font oldFont = g.getFont();
  289. g.setFont(titlePane.getFont());
  290. g.translate(x0, y0);
  291. Rectangle titleRect = calculateTitleArea(jif);
  292. JComponent menuButton = findChild(titlePane, "InternalFrameTitlePane.menuButton");
  293. Icon frameIcon = jif.getFrameIcon();
  294. variables.put("mini_icon_width",
  295. (frameIcon != null) ? frameIcon.getIconWidth() : 0);
  296. variables.put("mini_icon_height",
  297. (frameIcon != null) ? frameIcon.getIconHeight() : 0);
  298. variables.put("title_width", calculateTitleTextWidth(g, jif));
  299. FontMetrics fm = SwingUtilities2.getFontMetrics(jif, g);
  300. variables.put("title_height", fm.getAscent() + fm.getDescent());
  301. // These don't seem to apply here, but the Galaxy theme uses them. Not sure why.
  302. variables.put("icon_width", 32);
  303. variables.put("icon_height", 32);
  304. if (frame_style_set == null) {
  305. frame_style_set = getNode("frame_style_set", new String[] { "name", "normal" });
  306. }
  307. if (frame_style_set != null) {
  308. Node frame = getNode(frame_style_set, "frame", new String[] {
  309. "focus", (active ? "yes" : "no"),
  310. "state", (jif.isMaximum() ? "maximized" : "normal")
  311. });
  312. if (frame != null) {
  313. Node frame_style = getNode("frame_style", new String[] {
  314. "name", getStringAttr(frame, "style")
  315. });
  316. if (frame_style != null) {
  317. Map gm = frameGeometries.get(getStringAttr(frame_style, "geometry"));
  318. setFrameGeometry(titlePane, gm);
  319. Shape oldClip = g.getClip();
  320. boolean roundTopLeft = getBoolean("rounded_top_left", false);
  321. boolean roundTopRight = getBoolean("rounded_top_right", false);
  322. boolean roundBottomLeft = getBoolean("rounded_bottom_left", false);
  323. boolean roundBottomRight = getBoolean("rounded_bottom_right", false);
  324. if (roundTopLeft || roundTopRight || roundBottomLeft || roundBottomRight) {
  325. jif.setOpaque(false);
  326. g.setClip(getRoundedClipShape(0, 0, width, height, 12, 12,
  327. (roundTopLeft ? RoundRectClipShape.TOP_LEFT : 0) |
  328. (roundTopRight ? RoundRectClipShape.TOP_RIGHT : 0) |
  329. (roundBottomLeft ? RoundRectClipShape.BOTTOM_LEFT : 0) |
  330. (roundBottomRight ? RoundRectClipShape.BOTTOM_RIGHT : 0)));
  331. }
  332. int titleHeight = titlePane.getHeight();
  333. boolean minimized = jif.isIcon();
  334. Insets insets = getBorderInsets(context, null);
  335. int leftTitlebarEdge = getInt("left_titlebar_edge");
  336. int rightTitlebarEdge = getInt("right_titlebar_edge");
  337. int topTitlebarEdge = getInt("top_titlebar_edge");
  338. int bottomTitlebarEdge = getInt("bottom_titlebar_edge");
  339. if (!minimized) {
  340. drawPiece(frame_style, g, "entire_background",
  341. 0, 0, width, height, jif);
  342. }
  343. drawPiece(frame_style, g, "titlebar",
  344. 0, 0, width, titleHeight, jif);
  345. drawPiece(frame_style, g, "titlebar_middle",
  346. leftTitlebarEdge, topTitlebarEdge,
  347. width - leftTitlebarEdge - rightTitlebarEdge,
  348. titleHeight - topTitlebarEdge - bottomTitlebarEdge,
  349. jif);
  350. drawPiece(frame_style, g, "left_titlebar_edge",
  351. 0, 0, leftTitlebarEdge, titleHeight, jif);
  352. drawPiece(frame_style, g, "right_titlebar_edge",
  353. width - rightTitlebarEdge, 0,
  354. rightTitlebarEdge, titleHeight, jif);
  355. drawPiece(frame_style, g, "top_titlebar_edge",
  356. 0, 0, width, topTitlebarEdge, jif);
  357. drawPiece(frame_style, g, "bottom_titlebar_edge",
  358. 0, titleHeight - bottomTitlebarEdge,
  359. width, bottomTitlebarEdge, jif);
  360. drawPiece(frame_style, g, "title",
  361. titleRect.x, titleRect.y, titleRect.width, titleRect.height, jif);
  362. if (!minimized) {
  363. drawPiece(frame_style, g, "left_edge",
  364. 0, titleHeight, insets.left, height-titleHeight, jif);
  365. drawPiece(frame_style, g, "right_edge",
  366. width-insets.right, titleHeight, insets.right, height-titleHeight, jif);
  367. drawPiece(frame_style, g, "bottom_edge",
  368. 0, height - insets.bottom, width, insets.bottom, jif);
  369. drawPiece(frame_style, g, "overlay",
  370. 0, 0, width, height, jif);
  371. }
  372. g.setClip(oldClip);
  373. }
  374. }
  375. }
  376. g.translate(-x0, -y0);
  377. g.setFont(oldFont);
  378. }
  379. private static class Privileged implements PrivilegedAction {
  380. private static int GET_THEME_DIR = 0;
  381. private static int GET_USER_THEME = 1;
  382. private static int GET_IMAGE = 2;
  383. private int type;
  384. private Object arg;
  385. public Object doPrivileged(int type, Object arg) {
  386. this.type = type;
  387. this.arg = arg;
  388. return AccessController.doPrivileged(this);
  389. }
  390. public Object run() {
  391. if (type == GET_THEME_DIR) {
  392. String sep = File.separator;
  393. String[] dirs = new String[] {
  394. userHome + sep + ".themes",
  395. System.getProperty("swing.metacitythemedir"),
  396. "/usr/share/themes",
  397. "/usr/gnome/share/themes", // Debian/Redhat/Solaris
  398. "/opt/gnome2/share/themes" // SuSE
  399. };
  400. URL themeDir = null;
  401. for (int i = 0; i < dirs.length; i++) {
  402. // System property may not be set so skip null directories.
  403. if (dirs[i] == null) {
  404. continue;
  405. }
  406. File dir =
  407. new File(dirs[i] + sep + arg + sep + "metacity-1");
  408. if (new File(dir, "metacity-theme-1.xml").canRead()) {
  409. try {
  410. themeDir = dir.toURL();
  411. } catch (MalformedURLException ex) {
  412. themeDir = null;
  413. }
  414. break;
  415. }
  416. }
  417. if (themeDir == null) {
  418. String filename = "resources/metacity/" + arg +
  419. "/metacity-1/metacity-theme-1.xml";
  420. URL url = getClass().getResource(filename);
  421. if (url != null) {
  422. String str = url.toString();
  423. try {
  424. themeDir = new URL(str.substring(0, str.lastIndexOf('/'))+"/");
  425. } catch (MalformedURLException ex) {
  426. themeDir = null;
  427. }
  428. }
  429. }
  430. return themeDir;
  431. } else if (type == GET_USER_THEME) {
  432. try {
  433. // Set userHome here because we need the privilege
  434. userHome = System.getProperty("user.home");
  435. String theme = System.getProperty("swing.metacitythemename");
  436. if (theme != null) {
  437. return theme;
  438. }
  439. // Note: this is a small file (< 1024 bytes) so it's not worth
  440. // starting an XML parser or even to use a buffered reader.
  441. URL url = new URL(new File(userHome).toURL(),
  442. ".gconf/apps/metacity/general/%25gconf.xml");
  443. // Pending: verify character encoding spec for gconf
  444. Reader reader = new InputStreamReader(url.openStream(), "ISO-8859-1");
  445. char[] buf = new char[1024];
  446. StringBuffer strBuf = new StringBuffer();
  447. int n;
  448. while ((n = reader.read(buf)) >= 0) {
  449. strBuf.append(buf, 0, n);
  450. }
  451. reader.close();
  452. String str = strBuf.toString();
  453. if (str != null) {
  454. String strLowerCase = str.toLowerCase();
  455. int i = strLowerCase.indexOf("<entry name=\"theme\"");
  456. if (i >= 0) {
  457. i = strLowerCase.indexOf("<stringvalue>", i);
  458. if (i > 0) {
  459. i += "<stringvalue>".length();
  460. int i2 = str.indexOf("<", i);
  461. return str.substring(i, i2);
  462. }
  463. }
  464. }
  465. } catch (MalformedURLException ex) {
  466. // OK to just ignore. We'll use a fallback theme.
  467. } catch (IOException ex) {
  468. // OK to just ignore. We'll use a fallback theme.
  469. }
  470. return null;
  471. } else if (type == GET_IMAGE) {
  472. return new ImageIcon((URL)arg).getImage();
  473. } else {
  474. return null;
  475. }
  476. }
  477. }
  478. private static URL getThemeDir(String themeName) {
  479. return (URL)new Privileged().doPrivileged(Privileged.GET_THEME_DIR, themeName);
  480. }
  481. private static String getUserTheme() {
  482. return (String)new Privileged().doPrivileged(Privileged.GET_USER_THEME, null);
  483. }
  484. protected void tileImage(Graphics g, Image image, int x0, int y0, int w, int h, float[] alphas) {
  485. Graphics2D g2 = (Graphics2D)g;
  486. Composite oldComp = g2.getComposite();
  487. int sw = image.getWidth(null);
  488. int sh = image.getHeight(null);
  489. int y = y0;
  490. while (y < y0 + h) {
  491. sh = Math.min(sh, y0 + h - y);
  492. int x = x0;
  493. while (x < x0 + w) {
  494. float f = (alphas.length - 1.0F) * x / (x0 + w);
  495. int i = (int)f;
  496. f -= (int)f;
  497. float alpha = (1-f) * alphas[i];
  498. if (i+1 < alphas.length) {
  499. alpha += f * alphas[i+1];
  500. }
  501. g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
  502. int swm = Math.min(sw, x0 + w - x);
  503. g.drawImage(image, x, y, x+swm, y+sh, 0, 0, swm, sh, null);
  504. x += swm;
  505. }
  506. y += sh;
  507. }
  508. g2.setComposite(oldComp);
  509. }
  510. private HashMap<String, Image> images = new HashMap();
  511. protected Image getImage(String key, Color c) {
  512. Image image = images.get(key+"-"+c.getRGB());
  513. if (image == null) {
  514. image = imageFilter.colorize(getImage(key), c);
  515. if (image != null) {
  516. images.put(key+"-"+c.getRGB(), image);
  517. }
  518. }
  519. return image;
  520. }
  521. protected Image getImage(String key) {
  522. Image image = images.get(key);
  523. if (image == null) {
  524. if (themeDir != null) {
  525. try {
  526. URL url = new URL(themeDir, key);
  527. image = (Image)new Privileged().doPrivileged(Privileged.GET_IMAGE, url);
  528. } catch (MalformedURLException ex) {
  529. //log("Bad image url: "+ themeDir + "/" + key);
  530. }
  531. }
  532. if (image != null) {
  533. images.put(key, image);
  534. }
  535. }
  536. return image;
  537. }
  538. private class ColorizeImageFilter extends RGBImageFilter {
  539. double cr, cg, cb;
  540. public ColorizeImageFilter() {
  541. canFilterIndexColorModel = true;
  542. }
  543. public void setColor(Color color) {
  544. cr = color.getRed() / 255.0;
  545. cg = color.getGreen() / 255.0;
  546. cb = color.getBlue() / 255.0;
  547. }
  548. public Image colorize(Image fromImage, Color c) {
  549. setColor(c);
  550. ImageProducer producer = new FilteredImageSource(fromImage.getSource(), this);
  551. return new ImageIcon(context.getComponent().createImage(producer)).getImage();
  552. }
  553. public int filterRGB(int x, int y, int rgb) {
  554. // Assume all rgb values are shades of gray
  555. double grayLevel = 2 * (rgb & 0xff) / 255.0;
  556. double r, g, b;
  557. if (grayLevel <= 1.0) {
  558. r = cr * grayLevel;
  559. g = cg * grayLevel;
  560. b = cb * grayLevel;
  561. } else {
  562. grayLevel -= 1.0;
  563. r = cr + (1.0 - cr) * grayLevel;
  564. g = cg + (1.0 - cg) * grayLevel;
  565. b = cb + (1.0 - cb) * grayLevel;
  566. }
  567. return ((rgb & 0xff000000) +
  568. (((int)(r * 255)) << 16) +
  569. (((int)(g * 255)) << 8) +
  570. (int)(b * 255));
  571. }
  572. }
  573. protected static JComponent findChild(JComponent parent, String name) {
  574. int n = parent.getComponentCount();
  575. for (int i = 0; i < n; i++) {
  576. JComponent c = (JComponent)parent.getComponent(i);
  577. if (name.equals(c.getName())) {
  578. return c;
  579. }
  580. }
  581. return null;
  582. }
  583. protected class TitlePaneLayout implements LayoutManager {
  584. public void addLayoutComponent(String name, Component c) {}
  585. public void removeLayoutComponent(Component c) {}
  586. public Dimension preferredLayoutSize(Container c) {
  587. return minimumLayoutSize(c);
  588. }
  589. public Dimension minimumLayoutSize(Container c) {
  590. JComponent titlePane = (JComponent)c;
  591. Container titlePaneParent = titlePane.getParent();
  592. JInternalFrame frame;
  593. if (titlePaneParent instanceof JInternalFrame) {
  594. frame = (JInternalFrame)titlePaneParent;
  595. } else if (titlePaneParent instanceof JInternalFrame.JDesktopIcon) {
  596. frame = ((JInternalFrame.JDesktopIcon)titlePaneParent).getInternalFrame();
  597. } else {
  598. return null;
  599. }
  600. Dimension buttonDim = calculateButtonSize(titlePane);
  601. Insets title_border = (Insets)getFrameGeometry().get("title_border");
  602. Insets button_border = (Insets)getFrameGeometry().get("button_border");
  603. // Calculate width.
  604. int width = getInt("left_titlebar_edge") + buttonDim.width + getInt("right_titlebar_edge");
  605. if (title_border != null) {
  606. width += title_border.left + title_border.right;
  607. }
  608. if (frame.isClosable()) {
  609. width += buttonDim.width;
  610. }
  611. if (frame.isMaximizable()) {
  612. width += buttonDim.width;
  613. }
  614. if (frame.isIconifiable()) {
  615. width += buttonDim.width;
  616. }
  617. FontMetrics fm = frame.getFontMetrics(titlePane.getFont());
  618. String frameTitle = frame.getTitle();
  619. int title_w = frameTitle != null ? SwingUtilities2.stringWidth(
  620. frame, fm, frameTitle) : 0;
  621. int title_length = frameTitle != null ? frameTitle.length() : 0;
  622. // Leave room for three characters in the title.
  623. if (title_length > 3) {
  624. int subtitle_w = SwingUtilities2.stringWidth(
  625. frame, fm, frameTitle.substring(0, 3) + "...");
  626. width += (title_w < subtitle_w) ? title_w : subtitle_w;
  627. } else {
  628. width += title_w;
  629. }
  630. // Calculate height.
  631. int titleHeight = fm.getHeight() + getInt("title_vertical_pad");
  632. if (title_border != null) {
  633. titleHeight += title_border.top + title_border.bottom;
  634. }
  635. int buttonHeight = buttonDim.height;
  636. if (button_border != null) {
  637. buttonHeight += button_border.top + button_border.bottom;
  638. }
  639. int height = Math.max(buttonHeight, titleHeight);
  640. return new Dimension(width, height);
  641. }
  642. public void layoutContainer(Container c) {
  643. JComponent titlePane = (JComponent)c;
  644. Container titlePaneParent = titlePane.getParent();
  645. JInternalFrame frame;
  646. if (titlePaneParent instanceof JInternalFrame) {
  647. frame = (JInternalFrame)titlePaneParent;
  648. } else if (titlePaneParent instanceof JInternalFrame.JDesktopIcon) {
  649. frame = ((JInternalFrame.JDesktopIcon)titlePaneParent).getInternalFrame();
  650. } else {
  651. return;
  652. }
  653. Map gm = getFrameGeometry();
  654. int w = titlePane.getWidth();
  655. int h = titlePane.getHeight();
  656. JComponent menuButton = findChild(titlePane, "InternalFrameTitlePane.menuButton");
  657. JComponent minimizeButton = findChild(titlePane, "InternalFrameTitlePane.iconifyButton");
  658. JComponent maximizeButton = findChild(titlePane, "InternalFrameTitlePane.maximizeButton");
  659. JComponent closeButton = findChild(titlePane, "InternalFrameTitlePane.closeButton");
  660. int buttonGap = 0;
  661. Insets button_border = (Insets)gm.get("button_border");
  662. Dimension buttonDim = calculateButtonSize(titlePane);
  663. int x = getInt("left_titlebar_edge");
  664. int y = (button_border != null) ? button_border.top : 0;
  665. menuButton.setBounds(x, y, buttonDim.width, buttonDim.height);
  666. x = w - buttonDim.width - getInt("right_titlebar_edge");
  667. if (button_border != null) {
  668. x -= button_border.right;
  669. }
  670. if (frame.isClosable()) {
  671. closeButton.setBounds(x, y, buttonDim.width, buttonDim.height);
  672. x -= (buttonDim.width + buttonGap);
  673. }
  674. if (frame.isMaximizable()) {
  675. maximizeButton.setBounds(x, y, buttonDim.width, buttonDim.height);
  676. x -= (buttonDim.width + buttonGap);
  677. }
  678. if (frame.isIconifiable()) {
  679. minimizeButton.setBounds(x, y, buttonDim.width, buttonDim.height);
  680. }
  681. }
  682. } // end TitlePaneLayout
  683. protected Map getFrameGeometry() {
  684. return frameGeometry;
  685. }
  686. protected void setFrameGeometry(JComponent titlePane, Map gm) {
  687. this.frameGeometry = gm;
  688. if (getInt("top_height") == 0) {
  689. gm.put("top_height", new Integer(titlePane.getHeight()));
  690. }
  691. }
  692. protected int getInt(String key) {
  693. Integer i = (Integer)frameGeometry.get(key);
  694. if (i == null) {
  695. i = variables.get(key);
  696. }
  697. return (i != null) ? i.intValue() : 0;
  698. }
  699. protected boolean getBoolean(String key, boolean fallback) {
  700. Boolean b = (Boolean)frameGeometry.get(key);
  701. return (b != null) ? b.booleanValue() : fallback;
  702. }
  703. protected void drawArc(Node node, Graphics g) {
  704. NamedNodeMap attrs = node.getAttributes();
  705. Color color = parseColor(getStringAttr(attrs, "color"));
  706. int x = aee.evaluate(getStringAttr(attrs, "x"));
  707. int y = aee.evaluate(getStringAttr(attrs, "y"));
  708. int w = aee.evaluate(getStringAttr(attrs, "width"));
  709. int h = aee.evaluate(getStringAttr(attrs, "height"));
  710. int start_angle = aee.evaluate(getStringAttr(attrs, "start_angle"));
  711. int extent_angle = aee.evaluate(getStringAttr(attrs, "extent_angle"));
  712. boolean filled = getBooleanAttr(node, "filled", false);
  713. if (getInt("width") == -1) {
  714. x -= w;
  715. }
  716. if (getInt("height") == -1) {
  717. y -= h;
  718. }
  719. g.setColor(color);
  720. if (filled) {
  721. g.fillArc(x, y, w, h, start_angle, extent_angle);
  722. } else {
  723. g.drawArc(x, y, w, h, start_angle, extent_angle);
  724. }
  725. }
  726. protected void drawLine(Node node, Graphics g) {
  727. NamedNodeMap attrs = node.getAttributes();
  728. Color color = parseColor(getStringAttr(attrs, "color"));
  729. int x1 = aee.evaluate(getStringAttr(attrs, "x1"));
  730. int y1 = aee.evaluate(getStringAttr(attrs, "y1"));
  731. int x2 = aee.evaluate(getStringAttr(attrs, "x2"));
  732. int y2 = aee.evaluate(getStringAttr(attrs, "y2"));
  733. int lineWidth = aee.evaluate(getStringAttr(attrs, "width"), 1);
  734. g.setColor(color);
  735. if (lineWidth != 1) {
  736. Graphics2D g2d = (Graphics2D)g;
  737. Stroke stroke = g2d.getStroke();
  738. g2d.setStroke(new BasicStroke((float)lineWidth));
  739. g2d.drawLine(x1, y1, x2, y2);
  740. g2d.setStroke(stroke);
  741. } else {
  742. g.drawLine(x1, y1, x2, y2);
  743. }
  744. }
  745. protected void drawRectangle(Node node, Graphics g) {
  746. NamedNodeMap attrs = node.getAttributes();
  747. Color color = parseColor(getStringAttr(attrs, "color"));
  748. boolean filled = getBooleanAttr(node, "filled", false);
  749. int x = aee.evaluate(getStringAttr(attrs, "x"));
  750. int y = aee.evaluate(getStringAttr(attrs, "y"));
  751. int w = aee.evaluate(getStringAttr(attrs, "width"));
  752. int h = aee.evaluate(getStringAttr(attrs, "height"));
  753. g.setColor(color);
  754. if (getInt("width") == -1) {
  755. x -= w;
  756. }
  757. if (getInt("height") == -1) {
  758. y -= h;
  759. }
  760. if (filled) {
  761. g.fillRect(x, y, w, h);
  762. } else {
  763. g.drawRect(x, y, w, h);
  764. }
  765. }
  766. protected void drawTile(Node node, Graphics g, JInternalFrame jif) {
  767. NamedNodeMap attrs = node.getAttributes();
  768. int x0 = aee.evaluate(getStringAttr(attrs, "x"));
  769. int y0 = aee.evaluate(getStringAttr(attrs, "y"));
  770. int w = aee.evaluate(getStringAttr(attrs, "width"));
  771. int h = aee.evaluate(getStringAttr(attrs, "height"));
  772. int tw = aee.evaluate(getStringAttr(attrs, "tile_width"));
  773. int th = aee.evaluate(getStringAttr(attrs, "tile_height"));
  774. int width = getInt("width");
  775. int height = getInt("height");
  776. if (width == -1) {
  777. x0 -= w;
  778. }
  779. if (height == -1) {
  780. y0 -= h;
  781. }
  782. Shape oldClip = g.getClip();
  783. if (g instanceof Graphics2D) {
  784. ((Graphics2D)g).clip(new Rectangle(x0, y0, w, h));
  785. }
  786. variables.put("width", tw);
  787. variables.put("height", th);
  788. Node draw_ops = getNode("draw_ops", new String[] { "name", getStringAttr(node, "name") });
  789. int y = y0;
  790. while (y < y0 + h) {
  791. int x = x0;
  792. while (x < x0 + w) {
  793. g.translate(x, y);
  794. draw(draw_ops, g, jif);
  795. g.translate(-x, -y);
  796. x += tw;
  797. }
  798. y += th;
  799. }
  800. variables.put("width", width);
  801. variables.put("height", height);
  802. g.setClip(oldClip);
  803. }
  804. protected void drawTint(Node node, Graphics g) {
  805. NamedNodeMap attrs = node.getAttributes();
  806. Color color = parseColor(getStringAttr(attrs, "color"));
  807. float alpha = Float.parseFloat(getStringAttr(attrs, "alpha"));
  808. int x = aee.evaluate(getStringAttr(attrs, "x"));
  809. int y = aee.evaluate(getStringAttr(attrs, "y"));
  810. int w = aee.evaluate(getStringAttr(attrs, "width"));
  811. int h = aee.evaluate(getStringAttr(attrs, "height"));
  812. if (getInt("width") == -1) {
  813. x -= w;
  814. }
  815. if (getInt("height") == -1) {
  816. y -= h;
  817. }
  818. if (g instanceof Graphics2D) {
  819. Graphics2D g2 = (Graphics2D)g;
  820. Composite oldComp = g2.getComposite();
  821. AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha);
  822. g2.setComposite(ac);
  823. g2.setColor(color);
  824. g2.fillRect(x, y, w, h);
  825. g2.setComposite(oldComp);
  826. }
  827. }
  828. protected void drawTitle(Node node, Graphics g, JInternalFrame jif) {
  829. NamedNodeMap attrs = node.getAttributes();
  830. String colorStr = getStringAttr(attrs, "color");
  831. int i = colorStr.indexOf("gtk:fg[");
  832. if (i > 0) {
  833. colorStr = colorStr.substring(0, i) + "gtk:text[" + colorStr.substring(i+7);
  834. }
  835. Color color = parseColor(colorStr);
  836. int x = aee.evaluate(getStringAttr(attrs, "x"));
  837. int y = aee.evaluate(getStringAttr(attrs, "y"));
  838. String title = jif.getTitle();
  839. if (title != null) {
  840. FontMetrics fm = SwingUtilities2.getFontMetrics(jif, g);
  841. if (jif.getComponentOrientation().isLeftToRight()) {
  842. title = SwingUtilities2.clipStringIfNecessary(jif, fm, title,
  843. calculateTitleTextWidth(g, jif));
  844. }
  845. g.setColor(color);
  846. SwingUtilities2.drawString(jif, g, title, x, y + fm.getAscent());
  847. }
  848. }
  849. protected Dimension calculateButtonSize(JComponent titlePane) {
  850. int buttonHeight = getInt("button_height");
  851. if (buttonHeight == 0) {
  852. buttonHeight = titlePane.getHeight();
  853. if (buttonHeight == 0) {
  854. buttonHeight = 13;
  855. } else {
  856. Insets button_border = (Insets)frameGeometry.get("button_border");
  857. if (button_border != null) {
  858. buttonHeight -= (button_border.top + button_border.bottom);
  859. }
  860. }
  861. }
  862. int buttonWidth = getInt("button_width");
  863. if (buttonWidth == 0) {
  864. buttonWidth = buttonHeight;
  865. Float aspect_ratio = (Float)frameGeometry.get("aspect_ratio");
  866. if (aspect_ratio != null) {
  867. buttonWidth = (int)(buttonHeight / aspect_ratio.floatValue());
  868. }
  869. }
  870. return new Dimension(buttonWidth, buttonHeight);
  871. }
  872. protected Rectangle calculateTitleArea(JInternalFrame jif) {
  873. JComponent titlePane = findChild(jif, "InternalFrame.northPane");
  874. Dimension buttonDim = calculateButtonSize(titlePane);
  875. Insets title_border = (Insets)frameGeometry.get("title_border");
  876. Rectangle r = new Rectangle();
  877. r.x = getInt("left_titlebar_edge") + buttonDim.width;
  878. r.y = 0;
  879. r.height = titlePane.getHeight();
  880. if (title_border != null) {
  881. r.x += title_border.left;
  882. r.y += title_border.top;
  883. r.height -= (title_border.top + title_border.bottom);
  884. }
  885. r.width = titlePane.getWidth() - r.x - getInt("right_titlebar_edge");
  886. if (jif.isClosable()) {
  887. r.width -= buttonDim.width;
  888. }
  889. if (jif.isMaximizable()) {
  890. r.width -= buttonDim.width;
  891. }
  892. if (jif.isIconifiable()) {
  893. r.width -= buttonDim.width;
  894. }
  895. if (title_border != null) {
  896. r.width -= title_border.right;
  897. }
  898. return r;
  899. }
  900. protected int calculateTitleTextWidth(Graphics g, JInternalFrame jif) {
  901. String title = jif.getTitle();
  902. if (title != null) {
  903. Rectangle r = calculateTitleArea(jif);
  904. return Math.min(SwingUtilities2.stringWidth(jif,
  905. SwingUtilities2.getFontMetrics(jif, g), title), r.width);
  906. }
  907. return 0;
  908. }
  909. protected void setClip(Node node, Graphics g) {
  910. NamedNodeMap attrs = node.getAttributes();
  911. int x = aee.evaluate(getStringAttr(attrs, "x"));
  912. int y = aee.evaluate(getStringAttr(attrs, "y"));
  913. int w = aee.evaluate(getStringAttr(attrs, "width"));
  914. int h = aee.evaluate(getStringAttr(attrs, "height"));
  915. if (getInt("width") == -1) {
  916. x -= w;
  917. }
  918. if (getInt("height") == -1) {
  919. y -= h;
  920. }
  921. if (g instanceof Graphics2D) {
  922. ((Graphics2D)g).clip(new Rectangle(x, y, w, h));
  923. }
  924. }
  925. protected void drawGTKArrow(Node node, Graphics g) {
  926. NamedNodeMap attrs = node.getAttributes();
  927. String arrow = getStringAttr(attrs, "arrow");
  928. String shadow = getStringAttr(attrs, "shadow");
  929. String stateStr = getStringAttr(attrs, "state").toUpperCase();
  930. int x = aee.evaluate(getStringAttr(attrs, "x"));
  931. int y = aee.evaluate(getStringAttr(attrs, "y"));
  932. int w = aee.evaluate(getStringAttr(attrs, "width"));
  933. int h = aee.evaluate(getStringAttr(attrs, "height"));
  934. int state = -1;
  935. if ("NORMAL".equals(stateStr)) {
  936. state = ENABLED;
  937. } else if ("SELECTED".equals(stateStr)) {
  938. state = SELECTED;
  939. } else if ("INSENSITIVE".equals(stateStr)) {
  940. state = DISABLED;
  941. } else if ("PRELIGHT".equals(stateStr)) {
  942. state = MOUSE_OVER;
  943. }
  944. int shadowType = -1;
  945. if ("in".equals(shadow)) {
  946. shadowType = GTKConstants.SHADOW_IN;
  947. } else if ("out".equals(shadow)) {
  948. shadowType = GTKConstants.SHADOW_OUT;
  949. } else if ("etched_in".equals(shadow)) {
  950. shadowType = GTKConstants.SHADOW_ETCHED_IN;
  951. } else if ("etched_out".equals(shadow)) {
  952. shadowType = GTKConstants.SHADOW_ETCHED_OUT;
  953. } else if ("none".equals(shadow)) {
  954. shadowType = GTKConstants.SHADOW_NONE;
  955. }
  956. int direction = -1;
  957. if ("up".equals(arrow)) {
  958. direction = GTKConstants.ARROW_UP;
  959. } else if ("down".equals(arrow)) {
  960. direction = GTKConstants.ARROW_DOWN;
  961. } else if ("left".equals(arrow)) {
  962. direction = GTKConstants.ARROW_LEFT;
  963. } else if ("right".equals(arrow)) {
  964. direction = GTKConstants.ARROW_RIGHT;
  965. }
  966. GTKEngine engine = ((GTKStyle)context.getStyle()).getEngine(context);
  967. engine.paintArrow(context, g, state, shadowType,
  968. direction, null, x, y, w, h);
  969. }
  970. protected void drawGTKBox(Node node, Graphics g) {
  971. NamedNodeMap attrs = node.getAttributes();
  972. String shadow = getStringAttr(attrs, "shadow");
  973. String stateStr = getStringAttr(attrs, "state").toUpperCase();
  974. int x = aee.evaluate(getStringAttr(attrs, "x"));
  975. int y = aee.evaluate(getStringAttr(attrs, "y"));
  976. int w = aee.evaluate(getStringAttr(attrs, "width"));
  977. int h = aee.evaluate(getStringAttr(attrs, "height"));
  978. int state = -1;
  979. if ("NORMAL".equals(stateStr)) {
  980. state = ENABLED;
  981. } else if ("SELECTED".equals(stateStr)) {
  982. state = SELECTED;
  983. } else if ("INSENSITIVE".equals(stateStr)) {
  984. state = DISABLED;
  985. } else if ("PRELIGHT".equals(stateStr)) {
  986. state = MOUSE_OVER;
  987. }
  988. int shadowType = -1;
  989. if ("in".equals(shadow)) {
  990. shadowType = GTKConstants.SHADOW_IN;
  991. } else if ("out".equals(shadow)) {
  992. shadowType = GTKConstants.SHADOW_OUT;
  993. } else if ("etched_in".equals(shadow)) {
  994. shadowType = GTKConstants.SHADOW_ETCHED_IN;
  995. } else if ("etched_out".equals(shadow)) {
  996. shadowType = GTKConstants.SHADOW_ETCHED_OUT;
  997. } else if ("none".equals(shadow)) {
  998. shadowType = GTKConstants.SHADOW_NONE;
  999. }
  1000. GTKEngine.INSTANCE.paintBox(context, g, state, shadowType,
  1001. null, x, y, w, h);
  1002. }
  1003. protected void drawGTKVLine(Node node, Graphics g) {
  1004. NamedNodeMap attrs = node.getAttributes();
  1005. String stateStr = getStringAttr(attrs, "state").toUpperCase();
  1006. int x = aee.evaluate(getStringAttr(attrs, "x"));
  1007. int y1 = aee.evaluate(getStringAttr(attrs, "y1"));
  1008. int y2 = aee.evaluate(getStringAttr(attrs, "y2"));
  1009. int state = -1;
  1010. if ("NORMAL".equals(stateStr)) {
  1011. state = ENABLED;
  1012. } else if ("SELECTED".equals(stateStr)) {
  1013. state = SELECTED;
  1014. } else if ("INSENSITIVE".equals(stateStr)) {
  1015. state = DISABLED;
  1016. } else if ("PRELIGHT".equals(stateStr)) {
  1017. state = MOUSE_OVER;
  1018. }
  1019. GTKEngine.INSTANCE.paintVline(context, g, state, null, x, y1, 1, y2-y1);
  1020. }
  1021. protected void drawGradient(Node node, Graphics g) {
  1022. NamedNodeMap attrs = node.getAttributes();
  1023. String type = getStringAttr(attrs, "type");
  1024. float alpha = getFloatAttr(node, "alpha", -1F);
  1025. int x = aee.evaluate(getStringAttr(attrs, "x"));
  1026. int y = aee.evaluate(getStringAttr(attrs, "y"));
  1027. int w = aee.evaluate(getStringAttr(attrs, "width"));
  1028. int h = aee.evaluate(getStringAttr(attrs, "height"));
  1029. if (getInt("width") == -1) {
  1030. x -= w;
  1031. }
  1032. if (getInt("height") == -1) {
  1033. y -= h;
  1034. }
  1035. // Get colors from child nodes
  1036. Node[] colorNodes = getNodesByName(node, "color");
  1037. Color[] colors = new Color[colorNodes.length];
  1038. for (int i = 0; i < colorNodes.length; i++) {
  1039. colors[i] = parseColor(getStringAttr(colorNodes[i], "value"));
  1040. }
  1041. boolean horizontal = ("diagonal".equals(type) || "horizontal".equals(type));
  1042. boolean vertical = ("diagonal".equals(type) || "vertical".equals(type));
  1043. if (g instanceof Graphics2D) {
  1044. Graphics2D g2 = (Graphics2D)g;
  1045. Composite oldComp = g2.getComposite();
  1046. if (alpha >= 0F) {
  1047. g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
  1048. }
  1049. int n = colors.length - 1;
  1050. for (int i = 0; i < n; i++) {
  1051. g2.setPaint(new GradientPaint(x + (horizontal ? (i*wn) : 0),
  1052. y + (vertical ? (i*hn) : 0),
  1053. colors[i],
  1054. x + (horizontal ? ((i+1)*wn) : 0),
  1055. y + (vertical ? ((i+1)*hn) : 0),
  1056. colors[i+1]));
  1057. g2.fillRect(x + (horizontal ? (i*wn) : 0),
  1058. y + (vertical ? (i*hn) : 0),
  1059. (horizontal ? (wn) : w),
  1060. (vertical ? (hn) : h));
  1061. }
  1062. g2.setComposite(oldComp);
  1063. }
  1064. }
  1065. protected void drawImage(Node node, Graphics g) {
  1066. NamedNodeMap attrs = node.getAttributes();
  1067. String filename = getStringAttr(attrs, "filename");
  1068. String colorizeStr = getStringAttr(attrs, "colorize");
  1069. Color colorize = (colorizeStr != null) ? parseColor(colorizeStr) : null;
  1070. String alpha = getStringAttr(attrs, "alpha");
  1071. Image object = (colorize != null) ? getImage(filename, colorize) : getImage(filename);
  1072. variables.put("object_width", object.getWidth(null));
  1073. variables.put("object_height", object.getHeight(null));
  1074. String fill_type = getStringAttr(attrs, "fill_type");
  1075. int x = aee.evaluate(getStringAttr(attrs, "x"));
  1076. int y = aee.evaluate(getStringAttr(attrs, "y"));
  1077. int w = aee.evaluate(getStringAttr(attrs, "width"));
  1078. int h = aee.evaluate(getStringAttr(attrs, "height"));
  1079. if (getInt("width") == -1) {
  1080. x -= w;
  1081. }
  1082. if (getInt("height") == -1) {
  1083. y -= h;
  1084. }
  1085. if (alpha != null) {
  1086. if ("tile".equals(fill_type)) {
  1087. StringTokenizer tokenizer = new StringTokenizer(alpha, ":");
  1088. float[] alphas = new float[tokenizer.countTokens()];
  1089. for (int i = 0; i < alphas.length; i++) {
  1090. alphas[i] = Float.parseFloat(tokenizer.nextToken());
  1091. }
  1092. tileImage(g, object, x, y, w, h, alphas);
  1093. } else {
  1094. float a = Float.parseFloat(alpha);
  1095. if (g instanceof Graphics2D) {
  1096. Graphics2D g2 = (Graphics2D)g;
  1097. Composite oldComp = g2.getComposite();
  1098. g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, a));
  1099. g2.drawImage(object, x, y, w, h, null);
  1100. g2.setComposite(oldComp);
  1101. }
  1102. }
  1103. } else {
  1104. g.drawImage(object, x, y, w, h, null);
  1105. }
  1106. }
  1107. protected void drawIcon(Node node, Graphics g, JInternalFrame jif) {
  1108. Icon icon = jif.getFrameIcon();
  1109. if (icon == null) {
  1110. return;
  1111. }
  1112. NamedNodeMap attrs = node.getAttributes();
  1113. String alpha = getStringAttr(attrs, "alpha");
  1114. int x = aee.evaluate(getStringAttr(attrs, "x"));
  1115. int y = aee.evaluate(getStringAttr(attrs, "y"));
  1116. int w = aee.evaluate(getStringAttr(attrs, "width"));
  1117. int h = aee.evaluate(getStringAttr(attrs, "height"));
  1118. if (getInt("width") == -1) {
  1119. x -= w;
  1120. }
  1121. if (getInt("height") == -1) {
  1122. y -= h;
  1123. }
  1124. if (alpha != null) {
  1125. float a = Float.parseFloat(alpha);
  1126. if (g instanceof Graphics2D) {
  1127. Graphics2D g2 = (Graphics2D)g;
  1128. Composite oldComp = g2.getComposite();
  1129. g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, a));
  1130. icon.paintIcon(jif, g, x, y);
  1131. g2.setComposite(oldComp);
  1132. }
  1133. } else {
  1134. icon.paintIcon(jif, g, x, y);
  1135. }
  1136. }
  1137. protected void drawInclude(Node node, Graphics g, JInternalFrame jif) {
  1138. int oldWidth = getInt("width");
  1139. int oldHeight = getInt("height");
  1140. NamedNodeMap attrs = node.getAttributes();
  1141. int x = aee.evaluate(getStringAttr(attrs, "x"), 0);
  1142. int y = aee.evaluate(getStringAttr(attrs, "y"), 0);
  1143. int w = aee.evaluate(getStringAttr(attrs, "width"), -1);
  1144. int h = aee.evaluate(getStringAttr(attrs, "height"), -1);
  1145. if (w != -1) {
  1146. variables.put("width", w);
  1147. }
  1148. if (h != -1) {
  1149. variables.put("height", h);
  1150. }
  1151. Node draw_ops = getNode("draw_ops", new String[] {
  1152. "name", getStringAttr(node, "name")
  1153. });
  1154. g.translate(x, y);
  1155. draw(draw_ops, g, jif);
  1156. g.translate(-x, -y);
  1157. if (w != -1) {
  1158. variables.put("width", oldWidth);
  1159. }
  1160. if (h != -1) {
  1161. variables.put("height", oldHeight);
  1162. }
  1163. }
  1164. protected void draw(