1. /*
  2. * @(#)GTKEngine.java 1.53 04/01/13
  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 java.awt.*;
  9. import javax.swing.*;
  10. /**
  11. * GTKEngine mirrors that of a a GtkStyleClass.
  12. * <p>
  13. * The states that are passed in correspond to gtk's set of states:
  14. * <table>
  15. * <tr><td>Synth<td>GTK
  16. * <tr><td>GTKConstants.ENABLED<td>NORMAL
  17. * <tr><td>GTKConstants.PRESSED<td>ACTIVE
  18. * <tr><td>GTKConstants.SELECTED<td>SELECTED
  19. * <tr><td>GTKConstants.MOUSE_OVER<td>PRELIGHT
  20. * <tr><td>GTKConstants.DISABLED<td>INSENSITIVE
  21. * </table>
  22. * @version 1.53, 01/13/04
  23. * @author Josh Outwater
  24. * @author Scott Violet
  25. */
  26. class GTKEngine {
  27. static final GTKEngine INSTANCE = new GTKEngine();
  28. static final int[] DEFAULT_FOCUS_PATTERN = new int[] {1, 1};
  29. static int adjustAxisForComponentOrientation(JComponent c,
  30. int axis) {
  31. if (c.getComponentOrientation().isLeftToRight()) {
  32. return axis;
  33. }
  34. switch (axis) {
  35. case SwingConstants.EAST:
  36. return SwingConstants.WEST;
  37. case SwingConstants.WEST:
  38. return SwingConstants.EAST;
  39. }
  40. return axis;
  41. }
  42. public void paintArrow(SynthContext context, Graphics g, int state,
  43. int shadowType, int direction, String info,
  44. int x, int y, int w, int h) {
  45. // Draw the arrow
  46. int sizeW = w / 2;
  47. if (w % 2 == 1) {
  48. sizeW++;
  49. }
  50. int sizeH = h / 2;
  51. if (h % 2 == 1) {
  52. sizeH++;
  53. }
  54. int size = Math.max(2, Math.min(sizeW, sizeH));
  55. switch (direction) {
  56. case GTKConstants.ARROW_UP:
  57. x += w / 2 - 1;
  58. y += (h - size) / 2;
  59. break;
  60. case GTKConstants.ARROW_DOWN:
  61. x += w / 2 - 1;
  62. y += (h - size) / 2 + 1;
  63. break;
  64. case GTKConstants.ARROW_LEFT:
  65. x += (w - size) / 2;
  66. y += h / 2 - 1;
  67. break;
  68. case GTKConstants.ARROW_RIGHT:
  69. x += (w - size) / 2 + 1;
  70. y += h / 2 - 1;
  71. break;
  72. }
  73. GTKStyle style = (GTKStyle)context.getStyle();
  74. int mid, i, j;
  75. j = 0;
  76. mid = (size / 2) - 1;
  77. g.translate(x, y);
  78. if (state == SynthConstants.DISABLED) {
  79. g.setColor(style.getGTKColor(context.getComponent(),
  80. context.getRegion(), state, GTKColorType.WHITE));
  81. }
  82. else {
  83. g.setColor(style.getGTKColor(context.getComponent(),
  84. context.getRegion(), state, GTKColorType.FOREGROUND));
  85. }
  86. switch(direction) {
  87. case GTKConstants.ARROW_UP:
  88. for(i = 0; i < size; i++) {
  89. g.drawLine(mid-i, i, mid+i, i);
  90. }
  91. break;
  92. case GTKConstants.ARROW_DOWN:
  93. j = 0;
  94. for (i = size-1; i >= 0; i--) {
  95. g.drawLine(mid-i, j, mid+i, j);
  96. j++;
  97. }
  98. break;
  99. case GTKConstants.ARROW_LEFT:
  100. for (i = 0; i < size; i++) {
  101. g.drawLine(i, mid-i, i, mid+i);
  102. }
  103. break;
  104. case GTKConstants.ARROW_RIGHT:
  105. j = 0;
  106. for (i = size-1; i >= 0; i--) {
  107. g.drawLine(j, mid-i, j, mid+i);
  108. j++;
  109. }
  110. break;
  111. }
  112. g.translate(-x, -y);
  113. }
  114. public void paintBox(SynthContext context, Graphics g, int state,
  115. int shadowType, String info, int x, int y,
  116. int w, int h) {
  117. GTKStyle style = (GTKStyle)context.getStyle();
  118. Region region = context.getRegion();
  119. // This should really happen after the shadow is drawn.
  120. if (info == "menuitem" && state == SynthConstants.MOUSE_OVER &&
  121. GTKLookAndFeel.is2_2()) {
  122. paintBackground(context, g, state,
  123. style.getGTKColor(context.getComponent(), region,
  124. SynthConstants.SELECTED, GTKColorType.BACKGROUND), x, y, w,h);
  125. }
  126. else {
  127. paintBackground(context, g, state,
  128. style.getGTKColor(context.getComponent(), region, state,
  129. GTKColorType.BACKGROUND), x, y, w, h);
  130. }
  131. paintShadow(context, g, state, shadowType, info, x, y, w, h);
  132. }
  133. public void paintBoxGap(SynthContext context, Graphics g, int state,
  134. int shadowType, String info, int x, int y,
  135. int w, int h, int boxGapType, int tabBegin,
  136. int size) {
  137. _paintBoxGap(context, g, state, shadowType, x, y, w, h, boxGapType,
  138. tabBegin, size, GTKColorType.BACKGROUND,
  139. GTKColorType.LIGHT, GTKColorType.BLACK,
  140. GTKColorType.DARK, false);
  141. }
  142. void _paintBoxGap(SynthContext context, Graphics g, int state,
  143. int shadowType, int x, int y, int w, int h,
  144. int boxGapType, int tabBegin, int size,
  145. ColorType backgroundType, ColorType upperLeftType,
  146. ColorType bottomRightType, ColorType innerRightType,
  147. boolean paintWhite) {
  148. GTKStyle style = (GTKStyle)context.getStyle();
  149. JComponent c = context.getComponent();
  150. Region region = context.getRegion();
  151. paintBackground(context, g, state, style.getGTKColor(c, region, state,
  152. backgroundType), x, y, w, h);
  153. int tabEnd = tabBegin + size;
  154. Color upperLeft = style.getGTKColor(c, region, state, upperLeftType);
  155. Color bottomRight = style.getGTKColor(c, region, state,
  156. bottomRightType);
  157. Color innerRight = style.getGTKColor(c, region, state, innerRightType);
  158. Color white = style.getGTKColor(c, region, state, GTKColorType.WHITE);
  159. g.translate(x, y);
  160. if (boxGapType == GTKConstants.TOP) {
  161. // Paint bottom.
  162. g.setColor(bottomRight);
  163. g.drawLine(0, h - 1, w - 1, h - 1);
  164. g.setColor(innerRight);
  165. g.drawLine(1, h - 2, w - 2, h - 2);
  166. // Paint left side.
  167. g.setColor(upperLeft);
  168. g.drawLine(0, 0, 0, h - 2);
  169. if (paintWhite) {
  170. g.setColor(white);
  171. g.drawLine(1, 0, 1, h - 3);
  172. }
  173. // Paint right side.
  174. g.setColor(bottomRight);
  175. g.drawLine(w - 1, 0, w - 1, h - 1);
  176. g.setColor(innerRight);
  177. g.drawLine(w - 2, 0, w - 2, h - 2);
  178. // Paint top.
  179. if (tabBegin > 0) {
  180. g.setColor(upperLeft);
  181. g.drawLine(0, 0, tabBegin, 0);
  182. }
  183. g.setColor(upperLeft);
  184. g.drawLine(tabEnd, 0, w - 2, 0);
  185. if (paintWhite) {
  186. g.setColor(white);
  187. if (tabBegin > 0) {
  188. g.drawLine(0, 1, tabBegin, 1);
  189. }
  190. g.drawLine(tabEnd, 1, w - 2, 1);
  191. }
  192. }
  193. else if (boxGapType == GTKConstants.BOTTOM) {
  194. // Paint top.
  195. g.setColor(upperLeft);
  196. g.drawLine(0, 0, w - 1, 0);
  197. if (paintWhite) {
  198. g.setColor(white);
  199. g.drawLine(0, 1, w - 1, 1);
  200. }
  201. // Paint left side.
  202. g.setColor(upperLeft);
  203. g.drawLine(0, 0, 0, h - 1);
  204. if (paintWhite) {
  205. g.setColor(white);
  206. g.drawLine(1, 1, 1, h - 2);
  207. }
  208. // Paint right side.
  209. g.setColor(bottomRight);
  210. g.drawLine(w - 1, 0, w - 1, h - 1);
  211. g.setColor(innerRight);
  212. g.drawLine(w - 2, 1, w - 2, h - 2);
  213. // Paint bottom.
  214. if (tabBegin > 0) {
  215. g.setColor(bottomRight);
  216. g.drawLine(0, h - 1, tabBegin, h - 1);
  217. g.setColor(innerRight);
  218. g.drawLine(1, h - 2, tabBegin, h - 2);
  219. }
  220. g.setColor(bottomRight);
  221. g.drawLine(tabEnd, h - 1, w - 1, h - 1);
  222. g.setColor(innerRight);
  223. g.drawLine(tabEnd, h - 2, w - 2, h - 2);
  224. }
  225. else if (boxGapType == GTKConstants.RIGHT) {
  226. // Paint top.
  227. g.setColor(upperLeft);
  228. g.drawLine(0, 0, w - 1, 0);
  229. if (paintWhite) {
  230. g.setColor(white);
  231. g.drawLine(0, 1, w - 1, 1);
  232. }
  233. // Paint bottom.
  234. g.setColor(bottomRight);
  235. g.drawLine(0, h - 1, w - 1, h - 1);
  236. g.setColor(innerRight);
  237. g.drawLine(1, h - 2, w - 2, h - 2);
  238. // Paint left side.
  239. g.setColor(upperLeft);
  240. g.drawLine(0, 0, 0, h - 2);
  241. if (paintWhite) {
  242. g.setColor(white);
  243. g.drawLine(1, 1, 1, h - 3);
  244. }
  245. if (tabBegin > 0) {
  246. g.setColor(bottomRight);
  247. g.drawLine(w - 1, 0, w - 1, tabBegin);
  248. g.setColor(innerRight);
  249. g.drawLine(w - 2, 1, w - 2, tabBegin);
  250. }
  251. g.setColor(bottomRight);
  252. g.drawLine(w - 1, tabEnd, w - 1, h - 1);
  253. g.setColor(innerRight);
  254. g.drawLine(w - 2, tabEnd, w - 2, h - 2);
  255. }
  256. else if (boxGapType == GTKConstants.LEFT) {
  257. // Paint top.
  258. g.setColor(upperLeft);
  259. g.drawLine(0, 0, w - 2, 0);
  260. if (paintWhite) {
  261. g.setColor(white);
  262. g.drawLine(0, 1, w - 2, 1);
  263. }
  264. // Paint bottom.
  265. g.setColor(bottomRight);
  266. g.drawLine(0, h - 1, w - 1, h - 1);
  267. g.setColor(innerRight);
  268. g.drawLine(1, h - 2, w - 2, h - 2);
  269. // Paint right side.
  270. g.setColor(bottomRight);
  271. g.drawLine(w - 1, 1, w - 1, h - 1);
  272. g.setColor(innerRight);
  273. g.drawLine(w - 2, 0, w - 2, h - 2);
  274. // Paint left side.
  275. if (tabBegin > 0) {
  276. g.setColor(upperLeft);
  277. g.drawLine(0, 0, 0, tabBegin);
  278. }
  279. g.setColor(upperLeft);
  280. g.drawLine(0, tabEnd, 0, h - 2);
  281. if (paintWhite) {
  282. g.setColor(white);
  283. if (tabBegin > 0) {
  284. g.drawLine(1, 0, 1, tabBegin);
  285. }
  286. g.drawLine(1, tabEnd, 1, h - 3);
  287. }
  288. }
  289. g.translate(-x, -y);
  290. }
  291. public void paintCheck(SynthContext context, Graphics g, int state,
  292. int shadowType, String info, int x, int y,
  293. int w, int h) {
  294. int componentState = context.getComponentState();
  295. JComponent component = context.getComponent();
  296. Region r = context.getRegion();
  297. GTKStyle style = (GTKStyle)context.getStyle();
  298. if ("checkbutton" == info) {
  299. if ((componentState & SynthConstants.PRESSED) == 0) {
  300. paintBox(context, g, SynthConstants.ENABLED,
  301. GTKConstants.SHADOW_IN, info, x, y, w, h);
  302. g.setColor(style.getGTKColor(component, r, state,
  303. GTKColorType.WHITE));
  304. } else {
  305. paintBox(context, g, SynthConstants.PRESSED,
  306. GTKConstants.SHADOW_IN, info, x, y, w, h);
  307. g.setColor(style.getGTKColor(component, r, state,
  308. GTKColorType.BACKGROUND));
  309. }
  310. }
  311. g.translate(x, y);
  312. int centerY = h / 2 - 1;
  313. if ("checkbutton" == info) {
  314. g.fillRect(2, 2, w - 4, h - 4);
  315. }
  316. // Paint check mark in center if selected.
  317. if ((componentState & SynthConstants.SELECTED) != 0) {
  318. g.setColor(
  319. style.getGTKColor(component, r, state, GTKColorType.FOREGROUND));
  320. g.drawLine(3, centerY + 2, 4, centerY + 2);
  321. g.drawLine(5, centerY + 3, 6, centerY + 3);
  322. g.drawLine(6, centerY + 2, 6, centerY + 4);
  323. g.drawLine(7, centerY + 1, 7, centerY);
  324. g.drawLine(7, centerY, 8, centerY);
  325. g.drawLine(8, centerY, 8, centerY - 1);
  326. g.drawLine(8, centerY - 1, 9, centerY - 1);
  327. g.drawLine(9, centerY - 1, 9, centerY - 2);
  328. if (!GTKLookAndFeel.is2_2()) {
  329. if ((componentState & SynthConstants.PRESSED) != 0) {
  330. g.setColor(style.getGTKColor(component, r,
  331. SynthConstants.PRESSED, GTKColorType.DARK));
  332. } else {
  333. g.setColor(style.getGTKColor(component, r,
  334. SynthConstants.ENABLED, GTKColorType.DARK));
  335. }
  336. }
  337. g.drawLine(3, centerY + 1, 4, centerY + 1);
  338. g.drawLine(4, centerY + 3, 4, centerY + 3);
  339. g.drawLine(5, centerY + 2, 5, centerY + 2);
  340. g.drawLine(6, centerY + 1, 6, centerY + 1);
  341. g.drawLine(7, centerY + 2, 7, centerY + 2);
  342. g.drawLine(10, centerY - 2, 10, centerY - 2);
  343. }
  344. g.translate(-x, -y);
  345. }
  346. public void paintExtension(SynthContext context, Graphics g, int state,
  347. int shadowType, String info, int x, int y,
  348. int w, int h, int placement) {
  349. _paintExtension(context, g, state, shadowType, x, y, w, h, placement,
  350. GTKColorType.LIGHT, GTKColorType.BACKGROUND,
  351. GTKColorType.BLACK, GTKColorType.DARK, false);
  352. }
  353. void _paintExtension(SynthContext context, Graphics g, int state,
  354. int shadowType, int x, int y,
  355. int w, int h, int placement, ColorType upperLeftType,
  356. ColorType backgroundType, ColorType bottomRightType,
  357. ColorType innerRightType, boolean paintWhite) {
  358. GTKStyle style = (GTKStyle)context.getStyle();
  359. TabContext tabContext = (TabContext)context;
  360. JComponent c = context.getComponent();
  361. Region region = context.getRegion();
  362. int xThickness = style.getXThickness();
  363. int yThickness = style.getYThickness();
  364. if (xThickness < 0 && yThickness < 0) {
  365. // nothing to paint.
  366. return;
  367. }
  368. Color upperLeft =
  369. style.getGTKColor(c, region, state, upperLeftType);
  370. Color background =
  371. style.getGTKColor(c, region, state, backgroundType);
  372. Color bottomRight =
  373. style.getGTKColor(c, region, state, bottomRightType);
  374. Color innerRight =
  375. style.getGTKColor(c, region, state, innerRightType);
  376. Color white = style.getGTKColor(c, region, state, GTKColorType.WHITE);
  377. int tabIndex = tabContext.getTabIndex();
  378. int selectedIndex = ((JTabbedPane)c).getSelectedIndex();
  379. g.translate(x, y);
  380. // NOTE: placement refers to the size of the extension, so that
  381. // BOTTOM corresponds to a TabbedPane with the tabs placed at the top.
  382. if (placement == GTKConstants.BOTTOM) {
  383. // Fill the background.
  384. paintBackground(context, g, state, background, 0, 1, w, h);
  385. if (tabIndex == selectedIndex || tabIndex == 0) {
  386. g.setColor(upperLeft);
  387. g.drawLine(0, 1, 0, h - 1);
  388. g.drawLine(1, 0, w - 2, 0);
  389. if (paintWhite) {
  390. g.setColor(white);
  391. g.drawLine(1, 1, 1, h - 1);
  392. g.drawLine(1, 1, w - 3, 1);
  393. }
  394. } else {
  395. g.setColor(upperLeft);
  396. g.drawLine(0, 0, w - 2, 0);
  397. if (paintWhite) {
  398. g.setColor(white);
  399. g.drawLine(0, 1, w - 3, 1);
  400. }
  401. }
  402. if ((tabIndex + 1) != selectedIndex) {
  403. g.setColor(innerRight);
  404. g.drawLine(w - 2, 2, w - 2, h - 1);
  405. g.setColor(bottomRight);
  406. g.drawLine(w - 1, 1, w - 1, h - 1);
  407. }
  408. } else if (placement == GTKConstants.TOP) {
  409. // Fill the background.
  410. paintBackground(context, g, state, background, 0, 0, w, h - 1);
  411. if (tabIndex == selectedIndex || tabIndex == 0) {
  412. g.setColor(upperLeft);
  413. g.drawLine(0, 0, 0, h - 2);
  414. g.setColor(bottomRight);
  415. g.drawLine(1, h - 1, w - 2, h - 1);
  416. g.setColor(innerRight);
  417. g.drawLine(2, h - 2, w - 2, h - 2);
  418. if (paintWhite) {
  419. g.setColor(white);
  420. g.drawLine(1, 0, 1, h - 2);
  421. }
  422. } else {
  423. g.setColor(bottomRight);
  424. g.drawLine(0, h - 1, w - 2, h - 1);
  425. g.setColor(innerRight);
  426. g.drawLine(0, h - 2, w - 2, h - 2);
  427. if (paintWhite) {
  428. g.setColor(white);
  429. g.drawLine(0, 0, 0, h - 2);
  430. }
  431. }
  432. if ((tabIndex + 1) != selectedIndex) {
  433. g.setColor(bottomRight);
  434. g.drawLine(w - 1, 0, w - 1, h - 2);
  435. g.setColor(innerRight);
  436. g.drawLine(w - 2, 0, w - 2, h - 2);
  437. }
  438. } else if (placement == GTKConstants.RIGHT) {
  439. // Fill the background.
  440. paintBackground(context, g, state, background, 1, 0, w, h);
  441. if (tabIndex == selectedIndex || tabIndex == 0) {
  442. g.setColor(upperLeft);
  443. g.drawLine(1, 0, w - 1, 0);
  444. g.drawLine(0, 1, 0, h - 2);
  445. if (paintWhite) {
  446. g.setColor(white);
  447. g.drawLine(1, 1, w, 1);
  448. g.drawLine(1, 1, 1, h - 3);
  449. }
  450. } else {
  451. g.setColor(upperLeft);
  452. g.drawLine(0, 0, 0, h - 2);
  453. if (paintWhite) {
  454. g.setColor(white);
  455. g.drawLine(1, 1, 1, h - 3);
  456. }
  457. }
  458. if ((tabIndex + 1) != selectedIndex) {
  459. g.setColor(bottomRight);
  460. g.drawLine(1, h - 1, w - 1, h - 1);
  461. g.setColor(innerRight);
  462. g.drawLine(2, h - 2, w - 1, h - 2);
  463. }
  464. } else if (placement == GTKConstants.LEFT) {
  465. // Fill the background.
  466. paintBackground(context, g, state, background, 0, 0, w - 1, h);
  467. if (tabIndex == selectedIndex || tabIndex == 0) {
  468. g.setColor(upperLeft);
  469. g.drawLine(0, 0, w - 2, 0);
  470. g.setColor(bottomRight);
  471. g.drawLine(w - 1, 1, w - 1, h - 2);
  472. g.setColor(innerRight);
  473. g.drawLine(w - 2, 2, w - 2, h - 2);
  474. if (paintWhite) {
  475. g.setColor(white);
  476. g.drawLine(0, 1, w - 2, 1);
  477. g.drawLine(w - 2, 1, w - 2, h - 3);
  478. }
  479. } else {
  480. g.setColor(bottomRight);
  481. g.drawLine(w - 1, 0, w - 1, h - 2);
  482. g.setColor(innerRight);
  483. g.drawLine(w - 2, 0, w - 2, h - 2);
  484. if (paintWhite) {
  485. g.setColor(white);
  486. g.drawLine(w - 2, 1, w - 2, h - 3);
  487. }
  488. }
  489. if ((tabIndex + 1) != selectedIndex) {
  490. g.setColor(bottomRight);
  491. g.drawLine(0, h - 1, w - 2, h - 1);
  492. g.setColor(innerRight);
  493. g.drawLine(0, h - 2, w - 2, h - 2);
  494. }
  495. }
  496. g.translate(-x, -y);
  497. }
  498. void paintFlatBoxNormal(SynthContext context, Graphics g, int state,
  499. String key, int x, int y, int w, int h) {
  500. g.setColor(((GTKStyle)context.getStyle()).getGTKColor(
  501. context.getComponent(), context.getRegion(), state,
  502. GTKColorType.BACKGROUND));
  503. paintFlatBox(context, g, state, key, x, y, w, h);
  504. }
  505. void paintFlatBoxText(SynthContext context, Graphics g, int state,
  506. String key, int x, int y, int w, int h) {
  507. g.setColor(((GTKStyle)context.getStyle()).getGTKColor(
  508. context.getComponent(), context.getRegion(), state,
  509. GTKColorType.TEXT_BACKGROUND));
  510. paintFlatBox(context, g, state, key, x, y, w, h);
  511. }
  512. // NOTE: this assumes you have set the right color before calling this
  513. public void paintFlatBox(SynthContext context, Graphics g, int state,
  514. String key, int x, int y, int w, int h) {
  515. GTKStyle style = (GTKStyle)context.getStyle();
  516. if (key == "cell_odd") {
  517. g.fillRect(x, y, w, h);
  518. }
  519. else {
  520. paintBackground(context, g, state, g.getColor(), x, y, w, h);
  521. }
  522. if (key == "tooltip") {
  523. g.setColor(Color.BLACK);
  524. g.drawRect(x, y, w - 1, h - 1);
  525. }
  526. }
  527. public void paintFocus(SynthContext context, Graphics g, int state,
  528. String key, int x, int y, int w, int h) {
  529. GTKStyle style = (GTKStyle)context.getStyle();
  530. int[] pattern = (int[])style.getClassSpecificValue(
  531. context, "focus-line-pattern");
  532. int size = style.getClassSpecificIntValue(context,
  533. "focus-line-width", 1);
  534. if (pattern == null) {
  535. pattern = DEFAULT_FOCUS_PATTERN;
  536. }
  537. if (size <= 0) {
  538. return;
  539. }
  540. g.setColor(getFocusColor(context, state));
  541. _paintFocus(g, x, y, w, h, pattern, size);
  542. }
  543. void _paintFocus(Graphics g, int x, int y, int w, int h, int[] pattern,
  544. int size) {
  545. g.translate(x, y);
  546. // PENDING: This will need to be optimized
  547. int initial = size / 2;
  548. int offset = initial;
  549. int index = 0;
  550. int max1 = w - size;
  551. int max2 = max1 + h - size;
  552. int max3 = max2 + w - size;
  553. int max4 = max3 + h;
  554. while (offset < max4) {
  555. int next = offset + pattern[index];
  556. if (index % 2 == 0) {
  557. if (offset < max1) {
  558. // top
  559. g.fillRect(offset, 0, Math.min(next, w) - offset, size);
  560. offset = Math.min(next, max1);
  561. }
  562. if (offset != next && offset < max2) {
  563. // right
  564. g.fillRect(w - size, offset - max1, size,
  565. Math.min(max2, next) - offset);
  566. offset = Math.min(max2, next);
  567. }
  568. if (offset != next && offset < max3) {
  569. // bottom
  570. int x2 = w - (offset - max2);
  571. int temp = Math.min(next - offset, max3 - offset);
  572. g.fillRect(x2 - temp, h - size, temp, size);
  573. offset += temp;
  574. }
  575. if (offset != next) {
  576. int y2 = h - (offset - max3);
  577. int temp = Math.min(next - offset, max4 - offset);
  578. g.fillRect(0, y2 - temp, size, temp);
  579. offset += temp;
  580. }
  581. }
  582. else {
  583. offset = next;
  584. }
  585. index = (index + 1) % pattern.length;
  586. }
  587. g.translate(-x, -y);
  588. }
  589. Color getFocusColor(SynthContext context, int state) {
  590. return ((GTKStyle)context.getStyle()).getGTKColor(
  591. context.getComponent(), context.getRegion(), state,
  592. ColorType.FOREGROUND);
  593. }
  594. public void paintHandle(SynthContext context, Graphics g, int paintState,
  595. int shadowType, String info, int x, int y,
  596. int w, int h, int orientation) {
  597. paintBox(context, g, paintState, shadowType, info, x, y, w, h);
  598. g.translate(x, y);
  599. Region region = context.getRegion();
  600. GTKStyle style = (GTKStyle)context.getStyle();
  601. JComponent component = context.getComponent();
  602. Color lightColor = style.getGTKColor(component, region, paintState,
  603. GTKColorType.LIGHT);
  604. Color darkColor = style.getGTKColor(component, region, paintState,
  605. GTKColorType.DARK);
  606. Color blackColor = style.getGTKColor(component, region, paintState,
  607. GTKColorType.BLACK);
  608. int startX;
  609. int startY;
  610. if (info == "paned") {
  611. JSplitPane splitPane = (JSplitPane)component;
  612. int markerLength = 7 * 3 + 6 * 2; // 7 markers width of 3
  613. // + 6 spacers width of 2.
  614. if (orientation == GTKConstants.HORIZONTAL) {
  615. // Components are above/below.
  616. startX = w / 2 - markerLength / 2;
  617. startY = splitPane.getDividerSize() / 2 - 1;
  618. } else {
  619. // Components are left/right
  620. startX = splitPane.getDividerSize() / 2 - 1;
  621. startY = h / 2 - markerLength / 2;
  622. }
  623. for (int i = 0; i < 7; i++) {
  624. // Add length of one marker and spacing.
  625. if (orientation == GTKConstants.HORIZONTAL) {
  626. startX += 5;
  627. } else {
  628. startY += 5;
  629. }
  630. g.setColor(lightColor);
  631. g.fillRect(startX, startY, 2, 2);
  632. g.setColor(blackColor);
  633. g.fillRect(startX + 1, startY + 1, 2, 2);
  634. g.setColor(darkColor);
  635. g.fillRect(startX + 1, startY + 1, 1, 1);
  636. }
  637. } else if (info == "handlebox") {
  638. JToolBar tb = (JToolBar)component;
  639. startX = 2;
  640. startY = 2;
  641. if (tb.getOrientation() == JToolBar.HORIZONTAL) {
  642. while (startY < h) {
  643. g.setColor(darkColor);
  644. g.fillRect(startX + 1, startY + 1, 2, 2);
  645. g.fillRect(startX + 4, startY + 2, 2, 2);
  646. g.setColor(lightColor);
  647. g.fillRect(startX, startY, 2, 2);
  648. g.fillRect(startX + 3, startY + 1, 2, 2);
  649. startY += 3;
  650. }
  651. } else {
  652. boolean toggle = true;
  653. while (startX < w) {
  654. g.setColor(darkColor);
  655. g.fillRect(startX + 1, startY + 1, 2, 2);
  656. g.fillRect(startX + 1, startY + 4, 2, 2);
  657. g.setColor(lightColor);
  658. g.fillRect(startX, startY, 2, 2);
  659. g.fillRect(startX, startY + 3, 2, 2);
  660. startX += 3;
  661. if (toggle) {
  662. startY++;
  663. toggle = false;
  664. } else {
  665. startY--;
  666. toggle = true;
  667. }
  668. }
  669. }
  670. // Fix up the shadow.
  671. paintShadow(context, g, paintState, shadowType, info, 0, 0, w, h);
  672. }
  673. g.translate(-x, -y);
  674. }
  675. public void paintOption(SynthContext context, Graphics g, int paintState,
  676. int shadowType, String info, int x, int y,
  677. int w, int h) {
  678. g.translate(x, y);
  679. int componentState = context.getComponentState();
  680. int centerY = h / 2 - 1;
  681. JComponent component = context.getComponent();
  682. Region region = context.getRegion();
  683. GTKStyle style = (GTKStyle)context.getStyle();
  684. // If the radio button is being pressed we fill the center with the
  685. // MID gtk color, otherwise we fill it WHITE. We need to use the state
  686. // from the context since the state passed in may have been modified.
  687. if ((componentState & SynthConstants.PRESSED) == 0) {
  688. g.setColor(style.getGTKColor(component, region, paintState,
  689. GTKColorType.WHITE));
  690. } else {
  691. g.setColor(style.getGTKColor(component, region, paintState,
  692. GTKColorType.MID));
  693. }
  694. if (region != Region.RADIO_BUTTON_MENU_ITEM) {
  695. // Paint center portion.
  696. g.fillOval(1, 0 , 11, 11);
  697. g.drawLine(13, centerY - 1, 13, centerY + 2);
  698. g.drawLine(12, centerY + 3, 12, centerY + 4);
  699. g.drawLine(11, centerY + 5, 11, centerY + 5);
  700. g.drawLine(9, centerY + 6, 10, centerY + 6);
  701. g.drawLine(5, centerY + 7, 8, centerY + 7);
  702. // Paint dark shadow.
  703. g.setColor(style.getGTKColor(component, region, paintState,
  704. GTKColorType.DARK));
  705. g.drawOval(1, 0, 11, 11);
  706. // Paint black shadow.
  707. g.setColor(style.getGTKColor(component, region, paintState,
  708. GTKColorType.BLACK));
  709. g.drawLine(5, centerY - 4, 8, centerY - 4);
  710. g.drawLine(9, centerY - 4, 10, centerY - 3);
  711. g.drawLine(3, centerY - 3, 4, centerY - 3);
  712. g.drawLine(3, centerY - 2, 2, centerY - 1);
  713. g.drawLine(2, centerY, 2, centerY + 2);
  714. g.drawLine(2, centerY + 3, 3, centerY + 4);
  715. }
  716. // Fill in center if selected.
  717. if ((componentState & SynthConstants.SELECTED) != 0) {
  718. if (region == Region.RADIO_BUTTON_MENU_ITEM) {
  719. g.setColor(style.getGTKColor(component, region, paintState,
  720. GTKColorType.FOREGROUND));
  721. }
  722. g.fillRect(5, centerY, 5, 3);
  723. g.drawLine(6, centerY - 1, 8, centerY - 1);
  724. g.drawLine(6, centerY + 3, 8, centerY + 3);
  725. }
  726. g.translate(-x, -y);
  727. }
  728. public void paintShadow(SynthContext context, Graphics g, int state,
  729. int shadowType, String info, int x, int y,
  730. int w, int h) {
  731. if (info == "buttondefault") {
  732. // YES, this appears to be special cased.
  733. g.setColor(((GTKStyle)context.getStyle()).getGTKColor(
  734. context.getComponent(), context.getRegion(),
  735. state, GTKColorType.BLACK));
  736. g.drawRect(x, y, w - 1, h - 1);
  737. return;
  738. }
  739. GTKStyle style = (GTKStyle)context.getStyle();
  740. JComponent c = context.getComponent();
  741. Region region = context.getRegion();
  742. int xThickness = style.getXThickness();
  743. int yThickness = style.getYThickness();
  744. if (info == "trough" ||
  745. (info == "spinbutton" && c instanceof JButton)) {
  746. // YES, this appears to be special cased.
  747. xThickness = yThickness = 1;
  748. }
  749. if (xThickness < 0 && yThickness < 0) {
  750. // nothing to paint.
  751. return;
  752. }
  753. Color upperLeft = null, innerLeft = null, bottomRight = null,
  754. innerRight = null;
  755. switch (shadowType) {
  756. case GTKConstants.SHADOW_IN:
  757. if (info == "spinbutton" && c instanceof JButton) {
  758. upperLeft = style.getGTKColor(c, region, state,
  759. GTKColorType.DARK);
  760. innerRight = upperLeft;
  761. bottomRight = style.getGTKColor(c, region, state,
  762. GTKColorType.BLACK);
  763. } else {
  764. upperLeft = style.getGTKColor(c, region, state,
  765. GTKColorType.DARK);
  766. innerLeft = style.getGTKColor(c, region, state,
  767. GTKColorType.BLACK);
  768. bottomRight = style.getGTKColor(c, region, state,
  769. GTKColorType.LIGHT);
  770. innerRight = style.getGTKColor(c, region, state,
  771. GTKColorType.BACKGROUND);
  772. }
  773. break;
  774. case GTKConstants.SHADOW_OUT:
  775. upperLeft = style.getGTKColor(c, region, state,GTKColorType.LIGHT);
  776. innerLeft = style.getGTKColor(c, region, state,
  777. GTKColorType.BACKGROUND);
  778. bottomRight = style.getGTKColor(c, region, state,
  779. GTKColorType.BLACK);
  780. innerRight = style.getGTKColor(c, region, state,GTKColorType.DARK);
  781. break;
  782. default:
  783. assert true : "Unknown shadow type!";
  784. }
  785. if (info == "spinbutton" && c instanceof JButton) {
  786. _paintSpinButtonShadow(g, x, y, w, h, xThickness, yThickness,
  787. upperLeft, innerLeft, bottomRight, innerRight);
  788. } else {
  789. _paintShadow(g, x, y, w, h, xThickness, yThickness,
  790. upperLeft, innerLeft, bottomRight, innerRight);
  791. }
  792. }
  793. void _paintShadow(Graphics g, int x, int y, int w, int h,
  794. int xThickness, int yThickness, Color upperLeft,
  795. Color innerLeft, Color bottomRight, Color innerRight) {
  796. g.translate(x, y);
  797. // left/top
  798. g.setColor(upperLeft);
  799. if (xThickness > 0) {
  800. g.drawLine(0, 0, 0, h - 1);
  801. }
  802. if (yThickness > 0) {
  803. g.drawLine(1, 0, w - 1, 0);
  804. }
  805. // Inner left/top
  806. if (xThickness > 1 || yThickness > 1) {
  807. g.setColor(innerLeft);
  808. if (xThickness > 1) {
  809. g.drawLine(1, 1, 1, h - 2);
  810. }
  811. if (yThickness > 1) {
  812. g.drawLine(2, 1, w - 2, 1);
  813. }
  814. }
  815. // Bottom/right
  816. g.setColor(bottomRight);
  817. if (xThickness > 0) {
  818. g.drawLine(w - 1, 1, w - 1, h - 1);
  819. }
  820. if (yThickness > 0) {
  821. g.drawLine(1, h - 1, w - 2, h - 1);
  822. }
  823. // Inner bottom/right
  824. if (xThickness > 1 || yThickness > 1) {
  825. g.setColor(innerRight);
  826. if (xThickness > 1) {
  827. g.drawLine(w - 2, 2, w - 2, h - 2);
  828. }
  829. if (yThickness > 1) {
  830. g.drawLine(2, h - 2, w - 3, h - 2);
  831. }
  832. }
  833. g.translate(-x, -y);
  834. }
  835. void _paintSpinButtonShadow(Graphics g, int x, int y,
  836. int w, int h, int xThickness, int yThickness, Color upperLeft,
  837. Color innerLeft, Color bottomRight, Color innerRight) {
  838. g.translate(x, y);
  839. // top
  840. g.setColor(upperLeft);
  841. g.drawLine(0, 0, w - 1, 0);
  842. // bottom
  843. g.setColor(innerRight);
  844. g.drawLine(0, h - 1, w - 1, h - 1);
  845. // left/right
  846. g.setColor(bottomRight);
  847. g.drawLine(0, 0, 0, h - 1);
  848. g.drawLine(w - 1, 0, w - 1, h - 1);
  849. g.translate(-x, -y);
  850. }
  851. public void paintExpander(SynthContext context, Graphics g, int state,
  852. int expanderStyle, String info, int x,
  853. int y, int w, int h) {
  854. if (expanderStyle == GTKConstants.EXPANDER_COLLAPSED) {
  855. if (state != SynthConstants.MOUSE_OVER) {
  856. paintHollowTriangle(context, g, state,
  857. x, y, Math.min(w,h),
  858. adjustAxisForComponentOrientation(
  859. context.getComponent(), SwingConstants.EAST));
  860. } else {
  861. }
  862. }
  863. else {
  864. if (state != SynthConstants.MOUSE_OVER) {
  865. paintHollowTriangle(context, g, state,
  866. x, y, Math.min(w,h), SwingConstants.SOUTH);
  867. } else {
  868. }
  869. }
  870. }
  871. private void paintHollowTriangle(SynthContext ss, Graphics g, int state,
  872. int x, int y, int size, int direction) {
  873. GTKStyle style = (GTKStyle)ss.getStyle();
  874. int mid, height, thick, i, j, up, down;
  875. mid = (size / 2);
  876. height = size / 2 + 1;
  877. thick = Math.max(1, size / 7);
  878. g.translate(x, y);
  879. Color foreground = style.getGTKColor(ss.getComponent(), ss.getRegion(),
  880. state, GTKColorType.FOREGROUND);
  881. Color background = style.getGTKColor(ss.getComponent(), ss.getRegion(),
  882. state, GTKColorType.BACKGROUND);
  883. switch(direction) {
  884. case SwingConstants.NORTH:
  885. j = size / 2 + height / 2 - 1;
  886. // Fill in the background of the expander icon.
  887. g.setColor(background);
  888. for(i = height - 1; i > 0; i--) {
  889. g.drawLine(mid - i + 1, j, mid + i - 1, j);
  890. j--;
  891. }
  892. g.setColor(foreground);
  893. j = size / 2 + height / 2 - 1;
  894. down = thick - 1;
  895. // Draw the base of the triangle.
  896. for (up = 0; up < thick; up++) {
  897. g.drawLine(0 - down, j - up, size + down, j - up);
  898. down--;
  899. }
  900. j--;
  901. // Paint sides of triangle.
  902. for(i = height - 1; i > 0; i--) {
  903. for (up = 0; up < thick; up++ ) {
  904. g.drawLine(mid - i + 1 - up, j, mid - i + 1 - up, j);
  905. g.drawLine(mid + i - 1 + up, j, mid + i - 1 + up, j);
  906. }
  907. j--;
  908. }
  909. // Paint remainder of tip if necessary.
  910. if (thick > 1) {
  911. for (up = thick - 2; up >= 0; up--) {
  912. g.drawLine(mid - up, j, mid + up, j);
  913. j--;
  914. }
  915. }
  916. break;
  917. case SwingConstants.SOUTH:
  918. j = size / 2 - height / 2 - 1;
  919. // Fill in the background of the expander icon.
  920. g.setColor(background);
  921. for (i = height - 1; i > 0; i--) {
  922. g.drawLine(mid - i + 1, j, mid + i - 1, j);
  923. j++;
  924. }
  925. g.setColor(foreground);
  926. j = size / 2 - height / 2 - 1;
  927. down = thick - 1;
  928. // Draw the base of the triangle.
  929. for (up = 0; up < thick; up++) {
  930. g.drawLine(0 - down, j + up, size + down, j + up);
  931. down--;
  932. }
  933. j++;
  934. // Paint sides of triangle.
  935. for (i = height - 1; i > 0; i--) {
  936. for (up = 0; up < thick; up++ ) {
  937. g.drawLine(mid - i + 1 - up, j, mid - i + 1 - up, j);
  938. g.drawLine(mid + i - 1 + up, j, mid + i - 1 + up, j);
  939. }
  940. j++;
  941. }
  942. // Paint remainder of tip if necessary.
  943. if (thick > 1) {
  944. for (up = thick - 2; up >= 0; up--) {
  945. g.drawLine(mid - up, j, mid + up, j);
  946. j++;
  947. }
  948. }
  949. break;
  950. case SwingConstants.WEST:
  951. i = size / 2 + height / 2 - 1;
  952. // Fill in the background of the expander icon.
  953. g.setColor(background);
  954. for (j = height - 1; j > 0; j--) {
  955. g.drawLine(i, mid - j + 1, i, mid + j - 1);
  956. i--;
  957. }
  958. g.setColor(foreground);
  959. i = size / 2 + height / 2 - 1;
  960. down = thick - 1;
  961. // Draw the base of the triangle.
  962. for (up = 0; up < thick; up++) {
  963. g.drawLine(i - up, 0 - down, i - up, size + down);
  964. down--;
  965. }
  966. i--;
  967. // Paint sides of triangle.
  968. for (j = height - 1; j > 0; j--) {
  969. for (up = 0; up < thick; up++) {
  970. g.drawLine(i, mid - j + 1 - up, i, mid - j + 1 - up);
  971. g.drawLine(i, mid + j - 1 + up, i, mid + j - 1 + up);
  972. }
  973. i--;
  974. }
  975. // Paint remainder of tip if necessary.
  976. if (thick > 1) {
  977. for (up = thick - 2; up >= 0; up--) {
  978. g.drawLine(i, mid - up, i, mid + up);
  979. i--;
  980. }
  981. }
  982. break;
  983. case SwingConstants.EAST:
  984. i = size / 2 - height / 2 - 1;
  985. // Fill in the background of the expander icon.
  986. g.setColor(background);
  987. for (j = height - 1; j > 0; j--) {
  988. g.drawLine(i, mid - j + 1, i, mid + j - 1);
  989. i++;
  990. }
  991. g.setColor(foreground);
  992. i = size / 2 - height / 2 - 1;
  993. down = thick - 1;
  994. // Draw the base of the triangle.
  995. for (up = 0; up < thick; up++) {
  996. g.drawLine(i + up, 0 - down, i + up, size + down);
  997. down--;
  998. }
  999. i++;
  1000. // Paint sides of triangle.
  1001. for (j = height - 1; j > 0; j--) {
  1002. for (up = 0; up < thick; up++) {
  1003. g.drawLine(i, mid - j + 1 - up, i, mid - j + 1 - up);
  1004. g.drawLine(i, mid + j - 1 + up, i, mid + j - 1 + up);
  1005. }
  1006. i++;
  1007. }
  1008. // Paint remainder of tip if necessary.
  1009. if (thick > 1) {
  1010. for (up = thick - 2; up >= 0; up--) {
  1011. g.drawLine(i, mid - up, i, mid + up);
  1012. i++;
  1013. }
  1014. }
  1015. break;
  1016. }
  1017. g.translate(-x, -y);
  1018. }
  1019. public void paintSlider(SynthContext context, Graphics g, int state,
  1020. int shadowType, String info,
  1021. int x, int y, int w, int h, int orientation) {
  1022. paintBox(context, g, state, shadowType, info, x, y, w, h);
  1023. if (context.getRegion() == Region.SLIDER_THUMB) {
  1024. if (orientation == GTKConstants.HORIZONTAL) {
  1025. paintVline(context, g, state, info, x + w / 2 - 1, y + 2, 2,
  1026. h - 4);
  1027. } else {
  1028. paintHline(context, g, state, info, x + 2, y + h / 2 - 1,
  1029. w - 4, 2);
  1030. }
  1031. }
  1032. }
  1033. public void paintHline(SynthContext context, Graphics g, int state,
  1034. String info, int x, int y, int w, int h) {
  1035. g.translate(x, y);
  1036. GTKStyle style = (GTKStyle)context.getStyle();
  1037. int centerY = h / 2;
  1038. if (h == 2) {
  1039. centerY = 0;
  1040. }
  1041. g.setColor(style.getGTKColor(context.getComponent(),
  1042. context.getRegion(), state,
  1043. GTKColorType.DARK));
  1044. g.drawLine(0, centerY, w - 2, centerY);
  1045. g.setColor(style.getGTKColor(context.getComponent(),
  1046. context.getRegion(), state,
  1047. GTKColorType.LIGHT));
  1048. g.drawLine(0, centerY + 1, w - 1, centerY + 1);
  1049. g.drawLine(w - 1, centerY, w - 1, centerY + 1);
  1050. g.translate(-x, -y);
  1051. }
  1052. public void paintVline(SynthContext context, Graphics g, int state,
  1053. String info, int x, int y, int w, int h) {
  1054. g.translate(x, y);
  1055. GTKStyle style = (GTKStyle)context.getStyle();
  1056. int centerX = w / 2;
  1057. g.setColor(style.getGTKColor(context.getComponent(),
  1058. context.getRegion(),
  1059. state, GTKColorType.DARK));
  1060. g.drawLine(centerX, 0, centerX, h - 2);
  1061. g.drawLine(centerX, 0, centerX + 1, 0);
  1062. g.setColor(style.getGTKColor(context.getComponent(),
  1063. context.getRegion(),
  1064. state, GTKColorType.LIGHT));
  1065. g.drawLine(centerX + 1, 1, centerX + 1, h - 1);
  1066. g.drawLine(centerX, h - 1, centerX + 1, h - 1);
  1067. g.translate(-x, -y);
  1068. }
  1069. /**
  1070. * If necessary paints the background.
  1071. */
  1072. void paintBackground(SynthContext context, Graphics g, int state,
  1073. Color color, int x, int y, int w, int h) {
  1074. GTKStyle style = (GTKStyle)context.getStyle();
  1075. if (style.fillBackground(context, state)) {
  1076. g.setColor(color);
  1077. g.fillRect(x, y, w, h);
  1078. }
  1079. else {
  1080. Image image = style.getBackgroundImage(context, state);
  1081. int iW;
  1082. int iH;
  1083. if (image != null && (iW = image.getWidth(null)) > 0 &&
  1084. (iH = image.getHeight(null)) > 0) {
  1085. // Map the x/y location to originate from the origin of the
  1086. // window
  1087. int x2 = x;
  1088. int y2 = y;
  1089. Component parent = context.getComponent().getParent();
  1090. while (parent != null && !(parent instanceof Window) &&
  1091. !(parent instanceof java.applet.Applet)) {
  1092. Component nextParent = parent.getParent();
  1093. if (parent instanceof JRootPane &&
  1094. !(nextParent instanceof Window) &&
  1095. !(nextParent instanceof java.applet.Applet)) {
  1096. x2 += parent.getX();
  1097. y2 += parent.getY();
  1098. }
  1099. parent = nextParent;
  1100. }
  1101. x2 = x2 % iW;
  1102. y2 = y2 % iH;
  1103. Rectangle clip = g.getClipRect();
  1104. int cx1 = clip.x;
  1105. int cy1 = clip.y;
  1106. int cx2 = cx1 + clip.width;
  1107. int cy2 = cy1 + clip.height;
  1108. int lastIY = y2;
  1109. for (int yCounter = y, maxY = y + h; yCounter < maxY;
  1110. yCounter += (iH - lastIY), lastIY = 0) {
  1111. int lastIX = x2;
  1112. for (int xCounter = x, maxX = x + w; xCounter < maxX;
  1113. xCounter += (iW - lastIX), lastIX = 0) {
  1114. int dx2 = Math.min(maxX, xCounter + iW - lastIX);
  1115. int dy2 = Math.min(maxY, yCounter + iH - lastIY);
  1116. if (dx2 > cx1 && dy2 > cy1 && cx2 > xCounter &&
  1117. cy2 > yCounter) {
  1118. g.drawImage(image, xCounter, yCounter, dx2, dy2,
  1119. lastIX, lastIY, lastIX + dx2 - xCounter,
  1120. lastIY + dy2 - yCounter, null);
  1121. }
  1122. }
  1123. }
  1124. }
  1125. }
  1126. }
  1127. }