PageRenderTime 29ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/brlcad/tags/rel-7-16-10/src/other/tk/generic/ttk/ttkDefaultTheme.c

https://bitbucket.org/vrrm/brl-cad-copy-for-fast-history-browsing-in-git
C | 1165 lines | 876 code | 146 blank | 143 comment | 39 complexity | 629a768c9b88603709550b9d10e4a1bc MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, LGPL-2.1, Apache-2.0, AGPL-3.0, LGPL-3.0, GPL-3.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, 0BSD, BSD-3-Clause
  1. /* $Id$
  2. *
  3. * Copyright (c) 2003, Joe English
  4. *
  5. * Tk alternate theme, intended to match the MSUE and Gtk's (old) default theme
  6. */
  7. #include <math.h>
  8. #include <string.h>
  9. #include <tkInt.h>
  10. #include <X11/Xlib.h>
  11. #include <X11/Xutil.h>
  12. #include "ttkTheme.h"
  13. #if defined(WIN32)
  14. static const int WIN32_XDRAWLINE_HACK = 1;
  15. #else
  16. static const int WIN32_XDRAWLINE_HACK = 0;
  17. #endif
  18. #define BORDERWIDTH 2
  19. #define SCROLLBAR_WIDTH 14
  20. #define MIN_THUMB_SIZE 8
  21. /*
  22. *----------------------------------------------------------------------
  23. *
  24. * Helper routines for border drawing:
  25. *
  26. * NOTE: MSUE specifies a slightly different arrangement
  27. * for button borders than for other elements; "shadowColors"
  28. * is for button borders.
  29. *
  30. * Please excuse the gross misspelling "LITE" for "LIGHT",
  31. * but it makes things line up nicer.
  32. */
  33. enum BorderColor { FLAT = 1, LITE = 2, DARK = 3, BRDR = 4 };
  34. /* top-left outer, top-left inner, bottom-right inner, bottom-right outer */
  35. static int shadowColors[6][4] =
  36. {
  37. { FLAT, FLAT, FLAT, FLAT }, /* TK_RELIEF_FLAT = 0*/
  38. { DARK, LITE, DARK, LITE }, /* TK_RELIEF_GROOVE = 1*/
  39. { LITE, FLAT, DARK, BRDR }, /* TK_RELIEF_RAISED = 2*/
  40. { LITE, DARK, LITE, DARK }, /* TK_RELIEF_RIDGE = 3*/
  41. { BRDR, BRDR, BRDR, BRDR }, /* TK_RELIEF_SOLID = 4*/
  42. { BRDR, DARK, FLAT, LITE } /* TK_RELIEF_SUNKEN = 5*/
  43. };
  44. /* top-left, bottom-right */
  45. static int thinShadowColors[6][4] =
  46. {
  47. { FLAT, FLAT }, /* TK_RELIEF_FLAT = 0*/
  48. { DARK, LITE }, /* TK_RELIEF_GROOVE = 1*/
  49. { LITE, DARK }, /* TK_RELIEF_RAISED = 2*/
  50. { LITE, DARK }, /* TK_RELIEF_RIDGE = 3*/
  51. { BRDR, BRDR }, /* TK_RELIEF_SOLID = 4*/
  52. { DARK, LITE } /* TK_RELIEF_SUNKEN = 5*/
  53. };
  54. static void DrawCorner(
  55. Tk_Window tkwin,
  56. Drawable d,
  57. Tk_3DBorder border, /* get most GCs from here... */
  58. GC borderGC, /* "window border" color GC */
  59. int x,int y, int width,int height, /* where to draw */
  60. int corner, /* 0 => top left; 1 => bottom right */
  61. enum BorderColor color)
  62. {
  63. XPoint points[3];
  64. GC gc;
  65. --width; --height;
  66. points[0].x = x; points[0].y = y+height;
  67. points[1].x = x+width*corner; points[1].y = y+height*corner;
  68. points[2].x = x+width; points[2].y = y;
  69. if (color == BRDR)
  70. gc = borderGC;
  71. else
  72. gc = Tk_3DBorderGC(tkwin, border, (int)color);
  73. XDrawLines(Tk_Display(tkwin), d, gc, points, 3, CoordModeOrigin);
  74. }
  75. static void DrawBorder(
  76. Tk_Window tkwin, Drawable d, Tk_3DBorder border, XColor *borderColor,
  77. Ttk_Box b, int borderWidth, int relief)
  78. {
  79. GC borderGC = Tk_GCForColor(borderColor, d);
  80. switch (borderWidth) {
  81. case 2: /* "thick" border */
  82. DrawCorner(tkwin, d, border, borderGC,
  83. b.x, b.y, b.width, b.height, 0,shadowColors[relief][0]);
  84. DrawCorner(tkwin, d, border, borderGC,
  85. b.x+1, b.y+1, b.width-2, b.height-2, 0,shadowColors[relief][1]);
  86. DrawCorner(tkwin, d, border, borderGC,
  87. b.x+1, b.y+1, b.width-2, b.height-2, 1,shadowColors[relief][2]);
  88. DrawCorner(tkwin, d, border, borderGC,
  89. b.x, b.y, b.width, b.height, 1,shadowColors[relief][3]);
  90. break;
  91. case 1: /* "thin" border */
  92. DrawCorner(tkwin, d, border, borderGC,
  93. b.x, b.y, b.width, b.height, 0, thinShadowColors[relief][0]);
  94. DrawCorner(tkwin, d, border, borderGC,
  95. b.x, b.y, b.width, b.height, 1, thinShadowColors[relief][1]);
  96. break;
  97. case 0: /* no border -- do nothing */
  98. break;
  99. default: /* Fall back to Motif-style borders: */
  100. Tk_Draw3DRectangle(tkwin, d, border,
  101. b.x, b.y, b.width, b.height, borderWidth,relief);
  102. break;
  103. }
  104. }
  105. /* Alternate shadow colors for entry fields:
  106. * NOTE: FLAT color is normally white, and the LITE color is a darker shade.
  107. */
  108. static int fieldShadowColors[4] = { DARK, BRDR, LITE, FLAT };
  109. static void DrawFieldBorder(
  110. Tk_Window tkwin, Drawable d, Tk_3DBorder border, XColor *borderColor,
  111. Ttk_Box b)
  112. {
  113. GC borderGC = Tk_GCForColor(borderColor, d);
  114. DrawCorner(tkwin, d, border, borderGC,
  115. b.x, b.y, b.width, b.height, 0,fieldShadowColors[0]);
  116. DrawCorner(tkwin, d, border, borderGC,
  117. b.x+1, b.y+1, b.width-2, b.height-2, 0,fieldShadowColors[1]);
  118. DrawCorner(tkwin, d, border, borderGC,
  119. b.x+1, b.y+1, b.width-2, b.height-2, 1,fieldShadowColors[2]);
  120. DrawCorner(tkwin, d, border, borderGC,
  121. b.x, b.y, b.width, b.height, 1,fieldShadowColors[3]);
  122. return;
  123. }
  124. /*
  125. * ArrowPoints --
  126. * Compute points of arrow polygon.
  127. */
  128. static void ArrowPoints(Ttk_Box b, ArrowDirection dir, XPoint points[4])
  129. {
  130. int cx, cy, h;
  131. switch (dir) {
  132. case ARROW_UP:
  133. h = (b.width - 1)/2;
  134. cx = b.x + h;
  135. cy = b.y;
  136. if (b.height <= h) h = b.height - 1;
  137. points[0].x = cx; points[0].y = cy;
  138. points[1].x = cx - h; points[1].y = cy + h;
  139. points[2].x = cx + h; points[2].y = cy + h;
  140. break;
  141. case ARROW_DOWN:
  142. h = (b.width - 1)/2;
  143. cx = b.x + h;
  144. cy = b.y + b.height - 1;
  145. if (b.height <= h) h = b.height - 1;
  146. points[0].x = cx; points[0].y = cy;
  147. points[1].x = cx - h; points[1].y = cy - h;
  148. points[2].x = cx + h; points[2].y = cy - h;
  149. break;
  150. case ARROW_LEFT:
  151. h = (b.height - 1)/2;
  152. cx = b.x;
  153. cy = b.y + h;
  154. if (b.width <= h) h = b.width - 1;
  155. points[0].x = cx; points[0].y = cy;
  156. points[1].x = cx + h; points[1].y = cy - h;
  157. points[2].x = cx + h; points[2].y = cy + h;
  158. break;
  159. case ARROW_RIGHT:
  160. h = (b.height - 1)/2;
  161. cx = b.x + b.width - 1;
  162. cy = b.y + h;
  163. if (b.width <= h) h = b.width - 1;
  164. points[0].x = cx; points[0].y = cy;
  165. points[1].x = cx - h; points[1].y = cy - h;
  166. points[2].x = cx - h; points[2].y = cy + h;
  167. break;
  168. }
  169. points[3].x = points[0].x;
  170. points[3].y = points[0].y;
  171. }
  172. /*public*/
  173. void TtkArrowSize(int h, ArrowDirection dir, int *widthPtr, int *heightPtr)
  174. {
  175. switch (dir) {
  176. case ARROW_UP:
  177. case ARROW_DOWN: *widthPtr = 2*h+1; *heightPtr = h+1; break;
  178. case ARROW_LEFT:
  179. case ARROW_RIGHT: *widthPtr = h+1; *heightPtr = 2*h+1;
  180. }
  181. }
  182. /*
  183. * TtkDrawArrow, TtkFillArrow --
  184. * Draw an arrow in the indicated direction inside the specified box.
  185. */
  186. /*public*/
  187. void TtkFillArrow(
  188. Display *display, Drawable d, GC gc, Ttk_Box b, ArrowDirection dir)
  189. {
  190. XPoint points[4];
  191. ArrowPoints(b, dir, points);
  192. XFillPolygon(display, d, gc, points, 3, Convex, CoordModeOrigin);
  193. XDrawLines(display, d, gc, points, 4, CoordModeOrigin);
  194. }
  195. /*public*/
  196. void TtkDrawArrow(
  197. Display *display, Drawable d, GC gc, Ttk_Box b, ArrowDirection dir)
  198. {
  199. XPoint points[4];
  200. ArrowPoints(b, dir, points);
  201. XDrawLines(display, d, gc, points, 4, CoordModeOrigin);
  202. }
  203. /*
  204. *----------------------------------------------------------------------
  205. * +++ Border element implementation.
  206. *
  207. * This border consists of (from outside-in):
  208. *
  209. * + a 1-pixel thick default indicator (defaultable widgets only)
  210. * + 1- or 2- pixel shaded border (controlled by -background and -relief)
  211. * + 1 pixel padding (???)
  212. */
  213. typedef struct
  214. {
  215. Tcl_Obj *borderObj;
  216. Tcl_Obj *borderColorObj; /* Extra border color */
  217. Tcl_Obj *borderWidthObj;
  218. Tcl_Obj *reliefObj;
  219. Tcl_Obj *defaultStateObj; /* for buttons */
  220. } BorderElement;
  221. static Ttk_ElementOptionSpec BorderElementOptions[] =
  222. {
  223. { "-background", TK_OPTION_BORDER, Tk_Offset(BorderElement,borderObj),
  224. DEFAULT_BACKGROUND },
  225. { "-bordercolor",TK_OPTION_COLOR,
  226. Tk_Offset(BorderElement,borderColorObj), "black" },
  227. { "-default", TK_OPTION_ANY, Tk_Offset(BorderElement,defaultStateObj),
  228. "disabled" },
  229. { "-borderwidth",TK_OPTION_PIXELS,Tk_Offset(BorderElement,borderWidthObj),
  230. STRINGIFY(BORDERWIDTH) },
  231. { "-relief", TK_OPTION_RELIEF, Tk_Offset(BorderElement,reliefObj),
  232. "flat" },
  233. {NULL}
  234. };
  235. static void BorderElementSize(
  236. void *clientData, void *elementRecord, Tk_Window tkwin,
  237. int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
  238. {
  239. BorderElement *bd = elementRecord;
  240. int borderWidth = 0;
  241. int defaultState = TTK_BUTTON_DEFAULT_DISABLED;
  242. Tcl_GetIntFromObj(NULL, bd->borderWidthObj, &borderWidth);
  243. Ttk_GetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState);
  244. if (defaultState != TTK_BUTTON_DEFAULT_DISABLED) {
  245. ++borderWidth;
  246. }
  247. *paddingPtr = Ttk_UniformPadding((short)borderWidth);
  248. }
  249. static void BorderElementDraw(
  250. void *clientData, void *elementRecord,
  251. Tk_Window tkwin, Drawable d, Ttk_Box b, unsigned int state)
  252. {
  253. BorderElement *bd = elementRecord;
  254. Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, bd->borderObj);
  255. XColor *borderColor = Tk_GetColorFromObj(tkwin, bd->borderColorObj);
  256. int borderWidth = 2;
  257. int relief = TK_RELIEF_FLAT;
  258. int defaultState = TTK_BUTTON_DEFAULT_DISABLED;
  259. /*
  260. * Get option values.
  261. */
  262. Tcl_GetIntFromObj(NULL, bd->borderWidthObj, &borderWidth);
  263. Tk_GetReliefFromObj(NULL, bd->reliefObj, &relief);
  264. Ttk_GetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState);
  265. if (defaultState == TTK_BUTTON_DEFAULT_ACTIVE) {
  266. GC gc = Tk_GCForColor(borderColor, d);
  267. XDrawRectangle(Tk_Display(tkwin), d, gc,
  268. b.x, b.y, b.width-1, b.height-1);
  269. }
  270. if (defaultState != TTK_BUTTON_DEFAULT_DISABLED) {
  271. /* Space for default ring: */
  272. b = Ttk_PadBox(b, Ttk_UniformPadding(1));
  273. }
  274. DrawBorder(tkwin, d, border, borderColor, b, borderWidth, relief);
  275. }
  276. static Ttk_ElementSpec BorderElementSpec =
  277. {
  278. TK_STYLE_VERSION_2,
  279. sizeof(BorderElement),
  280. BorderElementOptions,
  281. BorderElementSize,
  282. BorderElementDraw
  283. };
  284. /*----------------------------------------------------------------------
  285. * +++ Field element:
  286. * Used for editable fields.
  287. */
  288. typedef struct
  289. {
  290. Tcl_Obj *borderObj;
  291. Tcl_Obj *borderColorObj; /* Extra border color */
  292. } FieldElement;
  293. static Ttk_ElementOptionSpec FieldElementOptions[] =
  294. {
  295. { "-fieldbackground", TK_OPTION_BORDER, Tk_Offset(FieldElement,borderObj),
  296. "white" },
  297. { "-bordercolor",TK_OPTION_COLOR, Tk_Offset(FieldElement,borderColorObj),
  298. "black" },
  299. {NULL}
  300. };
  301. static void FieldElementSize(
  302. void *clientData, void *elementRecord, Tk_Window tkwin,
  303. int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
  304. {
  305. *paddingPtr = Ttk_UniformPadding(2);
  306. }
  307. static void FieldElementDraw(
  308. void *clientData, void *elementRecord, Tk_Window tkwin,
  309. Drawable d, Ttk_Box b, unsigned int state)
  310. {
  311. FieldElement *field = elementRecord;
  312. Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, field->borderObj);
  313. XColor *borderColor = Tk_GetColorFromObj(tkwin, field->borderColorObj);
  314. Tk_Fill3DRectangle(
  315. tkwin, d, border, b.x, b.y, b.width, b.height, 0, TK_RELIEF_SUNKEN);
  316. DrawFieldBorder(tkwin, d, border, borderColor, b);
  317. }
  318. static Ttk_ElementSpec FieldElementSpec =
  319. {
  320. TK_STYLE_VERSION_2,
  321. sizeof(FieldElement),
  322. FieldElementOptions,
  323. FieldElementSize,
  324. FieldElementDraw
  325. };
  326. /*------------------------------------------------------------------------
  327. * Indicators --
  328. *
  329. * Code derived (probably incorrectly) from TIP 109 implementation,
  330. * unix/tkUnixButton.c r 1.15.
  331. */
  332. /*
  333. * Indicator bitmap descriptor:
  334. */
  335. typedef struct
  336. {
  337. int width; /* Width of each image */
  338. int height; /* Height of each image */
  339. int nimages; /* #images / row */
  340. char **pixels; /* array[height] of char[width*nimage] */
  341. Ttk_StateTable *map;/* used to look up image index by state */
  342. } IndicatorSpec;
  343. #if 0
  344. /*XPM*/
  345. static char *button_images[] = {
  346. /* width height ncolors chars_per_pixel */
  347. "52 26 7 1",
  348. /* colors */
  349. "A c #808000000000 s background",
  350. "B c #000080800000 s background",
  351. "C c #808080800000 s highlight",
  352. "D c #000000008080 s select",
  353. "E c #808000008080 s shadow",
  354. "F c #000080808080 s background",
  355. "G c #000000000000 s indicator",
  356. "H c #000080800000 s disabled",
  357. };
  358. #endif
  359. static Ttk_StateTable checkbutton_states[] =
  360. {
  361. { 0, 0, TTK_STATE_SELECTED|TTK_STATE_DISABLED },
  362. { 1, TTK_STATE_SELECTED, TTK_STATE_DISABLED },
  363. { 2, TTK_STATE_DISABLED, TTK_STATE_SELECTED },
  364. { 3, TTK_STATE_SELECTED|TTK_STATE_DISABLED, 0 },
  365. { 0, 0, 0 }
  366. };
  367. static char *checkbutton_pixels[] = {
  368. "AAAAAAAAAAAABAAAAAAAAAAAABAAAAAAAAAAAABAAAAAAAAAAAAB",
  369. "AEEEEEEEEEECBAEEEEEEEEEECBAEEEEEEEEEECBAEEEEEEEEEECB",
  370. "AEDDDDDDDDDCBAEDDDDDDDDDCBAEFFFFFFFFFCBAEFFFFFFFFFCB",
  371. "AEDDDDDDDDDCBAEDDDDDDDGDCBAEFFFFFFFFFCBAEFFFFFFFHFCB",
  372. "AEDDDDDDDDDCBAEDDDDDDGGDCBAEFFFFFFFFFCBAEFFFFFFHHFCB",
  373. "AEDDDDDDDDDCBAEDGDDDGGGDCBAEFFFFFFFFFCBAEFHFFFHHHFCB",
  374. "AEDDDDDDDDDCBAEDGGDGGGDDCBAEFFFFFFFFFCBAEFHHFHHHFFCB",
  375. "AEDDDDDDDDDCBAEDGGGGGDDDCBAEFFFFFFFFFCBAEFHHHHHFFFCB",
  376. "AEDDDDDDDDDCBAEDDGGGDDDDCBAEFFFFFFFFFCBAEFFHHHFFFFCB",
  377. "AEDDDDDDDDDCBAEDDDGDDDDDCBAEFFFFFFFFFCBAEFFFHFFFFFCB",
  378. "AEDDDDDDDDDCBAEDDDDDDDDDCBAEFFFFFFFFFCBAEFFFFFFFFFCB",
  379. "ACCCCCCCCCCCBACCCCCCCCCCCBACCCCCCCCCCCBACCCCCCCCCCCB",
  380. "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
  381. };
  382. static IndicatorSpec checkbutton_spec =
  383. {
  384. 13, 13, 4, /* width, height, nimages */
  385. checkbutton_pixels,
  386. checkbutton_states
  387. };
  388. static Ttk_StateTable radiobutton_states[] =
  389. {
  390. { 0, 0, TTK_STATE_SELECTED|TTK_STATE_DISABLED },
  391. { 1, TTK_STATE_SELECTED, TTK_STATE_DISABLED },
  392. { 2, TTK_STATE_DISABLED, TTK_STATE_SELECTED },
  393. { 3, TTK_STATE_SELECTED|TTK_STATE_DISABLED, 0 },
  394. { 0, 0, 0 }
  395. };
  396. static char *radiobutton_pixels[] = {
  397. "FFFFAAAAFFFFFFFFFAAAAFFFFFFFFFAAAAFFFFFFFFFAAAAFFFFF",
  398. "FFAAEEEEAAFFFFFAAEEEEAAFFFFFAAEEEEAAFFFFFAAEEEEAAFFF",
  399. "FAEEDDDDECBFFFAEEDDDDECBFFFAEEFFFFECBFFFAEEFFFFECBFF",
  400. "FAEDDDDDDCBFFFAEDDDDDDCBFFFAEFFFFFFCBFFFAEFFFFFFCBFF",
  401. "AEDDDDDDDDCBFAEDDDGGDDDCBFAEFFFFFFFFCBFAEFFFHHFFFCBF",
  402. "AEDDDDDDDDCBFAEDDGGGGDDCBFAEFFFFFFFFCBFAEFFHHHHFFCBF",
  403. "AEDDDDDDDDCBFAEDDGGGGDDCBFAEFFFFFFFFCBFAEFFHHHHFFCBF",
  404. "AEDDDDDDDDCBFAEDDDGGDDDCBFAEFFFFFFFFCBFAEFFFHHFFFCBF",
  405. "FAEDDDDDDCBFFFAEDDDDDDCBFFFAEFFFFFFCBFFFAEFFFFFFCBFF",
  406. "FACCDDDDCCBFFFACCDDDDCCBFFFACCFFFFCCBFFFACCFFFFCCBFF",
  407. "FFBBCCCCBBFFFFFBBCCCCBBFFFFFBBCCCCBBFFFFFBBCCCCBBFFF",
  408. "FFFFBBBBFFFFFFFFFBBBBFFFFFFFFFBBBBFFFFFFFFFBBBBFFFFF",
  409. "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
  410. };
  411. static IndicatorSpec radiobutton_spec =
  412. {
  413. 13, 13, 4, /* width, height, nimages */
  414. radiobutton_pixels,
  415. radiobutton_states
  416. };
  417. typedef struct
  418. {
  419. Tcl_Obj *backgroundObj;
  420. Tcl_Obj *foregroundObj;
  421. Tcl_Obj *colorObj;
  422. Tcl_Obj *lightColorObj;
  423. Tcl_Obj *shadeColorObj;
  424. Tcl_Obj *marginObj;
  425. } IndicatorElement;
  426. static Ttk_ElementOptionSpec IndicatorElementOptions[] =
  427. {
  428. { "-background", TK_OPTION_BORDER,
  429. Tk_Offset(IndicatorElement,backgroundObj), DEFAULT_BACKGROUND },
  430. { "-foreground", TK_OPTION_COLOR,
  431. Tk_Offset(IndicatorElement,foregroundObj), DEFAULT_FOREGROUND },
  432. { "-indicatorcolor", TK_OPTION_BORDER,
  433. Tk_Offset(IndicatorElement,colorObj), "#FFFFFF" },
  434. { "-lightcolor", TK_OPTION_COLOR,
  435. Tk_Offset(IndicatorElement,lightColorObj), "#DDDDDD" },
  436. { "-shadecolor", TK_OPTION_COLOR,
  437. Tk_Offset(IndicatorElement,shadeColorObj), "#888888" },
  438. { "-indicatormargin", TK_OPTION_STRING,
  439. Tk_Offset(IndicatorElement,marginObj), "0 2 4 2" },
  440. {NULL}
  441. };
  442. static void IndicatorElementSize(
  443. void *clientData, void *elementRecord, Tk_Window tkwin,
  444. int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
  445. {
  446. IndicatorSpec *spec = clientData;
  447. IndicatorElement *indicator = elementRecord;
  448. Ttk_Padding margins;
  449. Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins);
  450. *widthPtr = spec->width + Ttk_PaddingWidth(margins);
  451. *heightPtr = spec->height + Ttk_PaddingHeight(margins);
  452. }
  453. static void IndicatorElementDraw(
  454. void *clientData, void *elementRecord, Tk_Window tkwin,
  455. Drawable d, Ttk_Box b, unsigned int state)
  456. {
  457. IndicatorSpec *spec = clientData;
  458. IndicatorElement *indicator = elementRecord;
  459. Display *display = Tk_Display(tkwin);
  460. Tk_3DBorder bgBorder;
  461. Ttk_Padding padding;
  462. XColor *fgColor, *bgColor, *lightColor, *shadeColor, *selectColor;
  463. int index, ix, iy;
  464. XGCValues gcValues;
  465. GC copyGC;
  466. unsigned long imgColors[8];
  467. XImage *img;
  468. Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &padding);
  469. b = Ttk_PadBox(b, padding);
  470. if ( b.x < 0
  471. || b.y < 0
  472. || Tk_Width(tkwin) < b.x + spec->width
  473. || Tk_Height(tkwin) < b.y + spec->height)
  474. {
  475. /* Oops! not enough room to display the image.
  476. * Don't draw anything.
  477. */
  478. return;
  479. }
  480. /*
  481. * Fill in imgColors palette:
  482. *
  483. * (SHOULD: take light and shade colors from the border object,
  484. * but Tk doesn't provide easy access to these in the public API.)
  485. */
  486. fgColor = Tk_GetColorFromObj(tkwin, indicator->foregroundObj);
  487. bgBorder = Tk_Get3DBorderFromObj(tkwin, indicator->backgroundObj);
  488. bgColor = Tk_3DBorderColor(bgBorder);
  489. lightColor = Tk_GetColorFromObj(tkwin, indicator->lightColorObj);
  490. shadeColor = Tk_GetColorFromObj(tkwin, indicator->shadeColorObj);
  491. selectColor = Tk_GetColorFromObj(tkwin, indicator->colorObj);
  492. imgColors[0 /*A*/] = bgColor->pixel;
  493. imgColors[1 /*B*/] = bgColor->pixel;
  494. imgColors[2 /*C*/] = lightColor->pixel;
  495. imgColors[3 /*D*/] = selectColor->pixel;
  496. imgColors[4 /*E*/] = shadeColor->pixel;
  497. imgColors[5 /*F*/] = bgColor->pixel;
  498. imgColors[6 /*G*/] = fgColor->pixel;
  499. imgColors[7 /*H*/] = selectColor->pixel;
  500. /*
  501. * Create a scratch buffer to store the image:
  502. */
  503. img = XGetImage(display,d, 0, 0,
  504. (unsigned int)spec->width, (unsigned int)spec->height,
  505. AllPlanes, ZPixmap);
  506. if (img == NULL)
  507. return;
  508. /*
  509. * Create the image, painting it into an XImage one pixel at a time.
  510. */
  511. index = Ttk_StateTableLookup(spec->map, state);
  512. for (iy=0 ; iy<spec->height ; iy++) {
  513. for (ix=0 ; ix<spec->width ; ix++) {
  514. XPutPixel(img, ix, iy,
  515. imgColors[spec->pixels[iy][index*spec->width+ix] - 'A'] );
  516. }
  517. }
  518. /*
  519. * Copy onto our target drawable surface.
  520. */
  521. memset(&gcValues, 0, sizeof(gcValues));
  522. copyGC = Tk_GetGC(tkwin, 0, &gcValues);
  523. TkPutImage(NULL, 0, display, d, copyGC, img, 0, 0, b.x, b.y,
  524. spec->width, spec->height);
  525. /*
  526. * Tidy up.
  527. */
  528. Tk_FreeGC(display, copyGC);
  529. XDestroyImage(img);
  530. }
  531. static Ttk_ElementSpec IndicatorElementSpec =
  532. {
  533. TK_STYLE_VERSION_2,
  534. sizeof(IndicatorElement),
  535. IndicatorElementOptions,
  536. IndicatorElementSize,
  537. IndicatorElementDraw
  538. };
  539. /*----------------------------------------------------------------------
  540. * +++ Arrow element(s).
  541. *
  542. * Draws a solid triangle, inside a box.
  543. * clientData is an enum ArrowDirection pointer.
  544. */
  545. static int ArrowElements[] = { ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT };
  546. typedef struct
  547. {
  548. Tcl_Obj *sizeObj;
  549. Tcl_Obj *borderObj;
  550. Tcl_Obj *borderColorObj; /* Extra color for borders */
  551. Tcl_Obj *reliefObj;
  552. Tcl_Obj *colorObj; /* Arrow color */
  553. } ArrowElement;
  554. static Ttk_ElementOptionSpec ArrowElementOptions[] =
  555. {
  556. { "-arrowsize", TK_OPTION_PIXELS,
  557. Tk_Offset(ArrowElement,sizeObj), STRINGIFY(SCROLLBAR_WIDTH) },
  558. { "-background", TK_OPTION_BORDER,
  559. Tk_Offset(ArrowElement,borderObj), DEFAULT_BACKGROUND },
  560. { "-bordercolor", TK_OPTION_COLOR,
  561. Tk_Offset(ArrowElement,borderColorObj), "black" },
  562. { "-relief", TK_OPTION_RELIEF,
  563. Tk_Offset(ArrowElement,reliefObj),"raised"},
  564. { "-arrowcolor", TK_OPTION_COLOR,
  565. Tk_Offset(ArrowElement,colorObj),"black"},
  566. { NULL }
  567. };
  568. /*
  569. * Note asymmetric padding:
  570. * top/left padding is 1 less than bottom/right,
  571. * since in this theme 2-pixel borders are asymmetric.
  572. */
  573. static Ttk_Padding ArrowPadding = { 3,3,4,4 };
  574. static void ArrowElementSize(
  575. void *clientData, void *elementRecord, Tk_Window tkwin,
  576. int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
  577. {
  578. ArrowElement *arrow = elementRecord;
  579. int direction = *(int *)clientData;
  580. int width = SCROLLBAR_WIDTH;
  581. Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &width);
  582. width -= Ttk_PaddingWidth(ArrowPadding);
  583. TtkArrowSize(width/2, direction, widthPtr, heightPtr);
  584. *widthPtr += Ttk_PaddingWidth(ArrowPadding);
  585. *heightPtr += Ttk_PaddingHeight(ArrowPadding);
  586. }
  587. static void ArrowElementDraw(
  588. void *clientData, void *elementRecord, Tk_Window tkwin,
  589. Drawable d, Ttk_Box b, unsigned int state)
  590. {
  591. int direction = *(int *)clientData;
  592. ArrowElement *arrow = elementRecord;
  593. Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, arrow->borderObj);
  594. XColor *borderColor = Tk_GetColorFromObj(tkwin, arrow->borderColorObj);
  595. XColor *arrowColor = Tk_GetColorFromObj(tkwin, arrow->colorObj);
  596. int relief = TK_RELIEF_RAISED;
  597. int borderWidth = 2;
  598. Tk_GetReliefFromObj(NULL, arrow->reliefObj, &relief);
  599. Tk_Fill3DRectangle(
  600. tkwin, d, border, b.x, b.y, b.width, b.height, 0, TK_RELIEF_FLAT);
  601. DrawBorder(tkwin,d,border,borderColor,b,borderWidth,relief);
  602. TtkFillArrow(Tk_Display(tkwin), d, Tk_GCForColor(arrowColor, d),
  603. Ttk_PadBox(b, ArrowPadding), direction);
  604. }
  605. static Ttk_ElementSpec ArrowElementSpec =
  606. {
  607. TK_STYLE_VERSION_2,
  608. sizeof(ArrowElement),
  609. ArrowElementOptions,
  610. ArrowElementSize,
  611. ArrowElementDraw
  612. };
  613. /*----------------------------------------------------------------------
  614. * +++ Menubutton indicator:
  615. * Draw an arrow in the direction where the menu will be posted.
  616. */
  617. #define MENUBUTTON_ARROW_SIZE 5
  618. typedef struct {
  619. Tcl_Obj *directionObj;
  620. Tcl_Obj *sizeObj;
  621. Tcl_Obj *colorObj;
  622. } MenubuttonArrowElement;
  623. static const char *directionStrings[] = { /* See also: button.c */
  624. "above", "below", "left", "right", "flush", NULL
  625. };
  626. enum { POST_ABOVE, POST_BELOW, POST_LEFT, POST_RIGHT, POST_FLUSH };
  627. static Ttk_ElementOptionSpec MenubuttonArrowElementOptions[] =
  628. {
  629. { "-direction", TK_OPTION_STRING,
  630. Tk_Offset(MenubuttonArrowElement,directionObj), "below" },
  631. { "-arrowsize", TK_OPTION_PIXELS,
  632. Tk_Offset(MenubuttonArrowElement,sizeObj), STRINGIFY(MENUBUTTON_ARROW_SIZE)},
  633. { "-arrowcolor",TK_OPTION_COLOR,
  634. Tk_Offset(MenubuttonArrowElement,colorObj), "black"},
  635. { NULL }
  636. };
  637. static Ttk_Padding MenubuttonArrowPadding = { 3, 0, 3, 0 };
  638. static void MenubuttonArrowElementSize(
  639. void *clientData, void *elementRecord, Tk_Window tkwin,
  640. int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
  641. {
  642. MenubuttonArrowElement *arrow = elementRecord;
  643. int size = MENUBUTTON_ARROW_SIZE;
  644. Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &size);
  645. *widthPtr = *heightPtr = 2 * size + 1;
  646. *widthPtr += Ttk_PaddingWidth(MenubuttonArrowPadding);
  647. *heightPtr += Ttk_PaddingHeight(MenubuttonArrowPadding);
  648. }
  649. static void MenubuttonArrowElementDraw(
  650. void *clientData, void *elementRecord, Tk_Window tkwin,
  651. Drawable d, Ttk_Box b, unsigned int state)
  652. {
  653. MenubuttonArrowElement *arrow = elementRecord;
  654. XColor *arrowColor = Tk_GetColorFromObj(tkwin, arrow->colorObj);
  655. GC gc = Tk_GCForColor(arrowColor, d);
  656. int size = MENUBUTTON_ARROW_SIZE;
  657. int postDirection = POST_BELOW;
  658. ArrowDirection arrowDirection = ARROW_DOWN;
  659. int width = 0, height = 0;
  660. Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &size);
  661. Tcl_GetIndexFromObj(NULL, arrow->directionObj, directionStrings,
  662. ""/*message*/, 0/*flags*/, &postDirection);
  663. /* ... this might not be such a great idea ... */
  664. switch (postDirection) {
  665. case POST_ABOVE: arrowDirection = ARROW_UP; break;
  666. case POST_BELOW: arrowDirection = ARROW_DOWN; break;
  667. case POST_LEFT: arrowDirection = ARROW_LEFT; break;
  668. case POST_RIGHT: arrowDirection = ARROW_RIGHT; break;
  669. case POST_FLUSH: arrowDirection = ARROW_DOWN; break;
  670. }
  671. TtkArrowSize(size, arrowDirection, &width, &height);
  672. b = Ttk_PadBox(b, MenubuttonArrowPadding);
  673. b = Ttk_AnchorBox(b, width, height, TK_ANCHOR_CENTER);
  674. TtkFillArrow(Tk_Display(tkwin), d, gc, b, arrowDirection);
  675. }
  676. static Ttk_ElementSpec MenubuttonArrowElementSpec =
  677. {
  678. TK_STYLE_VERSION_2,
  679. sizeof(MenubuttonArrowElement),
  680. MenubuttonArrowElementOptions,
  681. MenubuttonArrowElementSize,
  682. MenubuttonArrowElementDraw
  683. };
  684. /*----------------------------------------------------------------------
  685. * +++ Trough element
  686. *
  687. * Used in scrollbars and the scale.
  688. *
  689. * The -groovewidth option can be used to set the size of the short axis
  690. * for the drawn area. This will not affect the geometry, but can be used
  691. * to draw a thin centered trough inside the packet alloted. This is used
  692. * to show a win32-style scale widget. Use -1 or a large number to use the
  693. * full area (default).
  694. *
  695. */
  696. typedef struct
  697. {
  698. Tcl_Obj *colorObj;
  699. Tcl_Obj *borderWidthObj;
  700. Tcl_Obj *reliefObj;
  701. Tcl_Obj *grooveWidthObj;
  702. Tcl_Obj *orientObj;
  703. } TroughElement;
  704. static Ttk_ElementOptionSpec TroughElementOptions[] =
  705. {
  706. { "-orient", TK_OPTION_ANY,
  707. Tk_Offset(TroughElement, orientObj), "horizontal" },
  708. { "-troughborderwidth", TK_OPTION_PIXELS,
  709. Tk_Offset(TroughElement,borderWidthObj), "1" },
  710. { "-troughcolor", TK_OPTION_BORDER,
  711. Tk_Offset(TroughElement,colorObj), DEFAULT_BACKGROUND },
  712. { "-troughrelief",TK_OPTION_RELIEF,
  713. Tk_Offset(TroughElement,reliefObj), "sunken" },
  714. { "-groovewidth", TK_OPTION_PIXELS,
  715. Tk_Offset(TroughElement,grooveWidthObj), "-1" },
  716. { NULL }
  717. };
  718. static void TroughElementSize(
  719. void *clientData, void *elementRecord, Tk_Window tkwin,
  720. int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
  721. {
  722. TroughElement *troughPtr = elementRecord;
  723. int borderWidth = 2, grooveWidth = 0;
  724. Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->borderWidthObj, &borderWidth);
  725. Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->grooveWidthObj, &grooveWidth);
  726. if (grooveWidth <= 0) {
  727. *paddingPtr = Ttk_UniformPadding((short)borderWidth);
  728. }
  729. }
  730. static void TroughElementDraw(
  731. void *clientData, void *elementRecord, Tk_Window tkwin,
  732. Drawable d, Ttk_Box b, unsigned int state)
  733. {
  734. TroughElement *troughPtr = elementRecord;
  735. Tk_3DBorder border = NULL;
  736. int borderWidth = 2, relief = TK_RELIEF_SUNKEN, groove = -1, orient;
  737. border = Tk_Get3DBorderFromObj(tkwin, troughPtr->colorObj);
  738. Ttk_GetOrientFromObj(NULL, troughPtr->orientObj, &orient);
  739. Tk_GetReliefFromObj(NULL, troughPtr->reliefObj, &relief);
  740. Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->borderWidthObj, &borderWidth);
  741. Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->grooveWidthObj, &groove);
  742. if (groove != -1 && groove < b.height && groove < b.width) {
  743. if (orient == TTK_ORIENT_HORIZONTAL) {
  744. b.y = b.y + b.height/2 - groove/2;
  745. b.height = groove;
  746. } else {
  747. b.x = b.x + b.width/2 - groove/2;
  748. b.width = groove;
  749. }
  750. }
  751. Tk_Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height,
  752. borderWidth, relief);
  753. }
  754. static Ttk_ElementSpec TroughElementSpec =
  755. {
  756. TK_STYLE_VERSION_2,
  757. sizeof(TroughElement),
  758. TroughElementOptions,
  759. TroughElementSize,
  760. TroughElementDraw
  761. };
  762. /*
  763. *----------------------------------------------------------------------
  764. * +++ Thumb element.
  765. */
  766. typedef struct
  767. {
  768. Tcl_Obj *sizeObj;
  769. Tcl_Obj *firstObj;
  770. Tcl_Obj *lastObj;
  771. Tcl_Obj *borderObj;
  772. Tcl_Obj *borderColorObj;
  773. Tcl_Obj *reliefObj;
  774. Tcl_Obj *orientObj;
  775. } ThumbElement;
  776. static Ttk_ElementOptionSpec ThumbElementOptions[] =
  777. {
  778. { "-width", TK_OPTION_PIXELS, Tk_Offset(ThumbElement,sizeObj),
  779. STRINGIFY(SCROLLBAR_WIDTH) },
  780. { "-background", TK_OPTION_BORDER, Tk_Offset(ThumbElement,borderObj),
  781. DEFAULT_BACKGROUND },
  782. { "-bordercolor", TK_OPTION_COLOR, Tk_Offset(ThumbElement,borderColorObj),
  783. "black" },
  784. { "-relief", TK_OPTION_RELIEF,Tk_Offset(ThumbElement,reliefObj),"raised" },
  785. { "-orient", TK_OPTION_ANY,Tk_Offset(ThumbElement,orientObj),"horizontal"},
  786. { NULL }
  787. };
  788. static void ThumbElementSize(
  789. void *clientData, void *elementRecord, Tk_Window tkwin,
  790. int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
  791. {
  792. ThumbElement *thumb = elementRecord;
  793. int orient, size;
  794. Tk_GetPixelsFromObj(NULL, tkwin, thumb->sizeObj, &size);
  795. Ttk_GetOrientFromObj(NULL, thumb->orientObj, &orient);
  796. if (orient == TTK_ORIENT_VERTICAL) {
  797. *widthPtr = size;
  798. *heightPtr = MIN_THUMB_SIZE;
  799. } else {
  800. *widthPtr = MIN_THUMB_SIZE;
  801. *heightPtr = size;
  802. }
  803. }
  804. static void ThumbElementDraw(
  805. void *clientData, void *elementRecord, Tk_Window tkwin,
  806. Drawable d, Ttk_Box b, unsigned int state)
  807. {
  808. ThumbElement *thumb = elementRecord;
  809. Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, thumb->borderObj);
  810. XColor *borderColor = Tk_GetColorFromObj(tkwin, thumb->borderColorObj);
  811. int relief = TK_RELIEF_RAISED;
  812. int borderWidth = 2;
  813. /*
  814. * Don't draw the thumb if we are disabled.
  815. * This makes it behave like Windows ... if that's what we want.
  816. if (state & TTK_STATE_DISABLED)
  817. return;
  818. */
  819. Tk_GetReliefFromObj(NULL, thumb->reliefObj, &relief);
  820. Tk_Fill3DRectangle(
  821. tkwin, d, border, b.x,b.y,b.width,b.height, 0, TK_RELIEF_FLAT);
  822. DrawBorder(tkwin, d, border, borderColor, b, borderWidth, relief);
  823. }
  824. static Ttk_ElementSpec ThumbElementSpec =
  825. {
  826. TK_STYLE_VERSION_2,
  827. sizeof(ThumbElement),
  828. ThumbElementOptions,
  829. ThumbElementSize,
  830. ThumbElementDraw
  831. };
  832. /*
  833. *----------------------------------------------------------------------
  834. * +++ Slider element.
  835. *
  836. * This is the moving part of the scale widget.
  837. *
  838. * The slider element is the thumb in the scale widget. This is drawn
  839. * as an arrow-type element that can point up, down, left or right.
  840. *
  841. */
  842. typedef struct
  843. {
  844. Tcl_Obj *lengthObj; /* Long axis dimension */
  845. Tcl_Obj *thicknessObj; /* Short axis dimension */
  846. Tcl_Obj *reliefObj; /* Relief for this object */
  847. Tcl_Obj *borderObj; /* Border / background color */
  848. Tcl_Obj *borderColorObj; /* Additional border color */
  849. Tcl_Obj *borderWidthObj;
  850. Tcl_Obj *orientObj; /* Orientation of overall slider */
  851. } SliderElement;
  852. static Ttk_ElementOptionSpec SliderElementOptions[] =
  853. {
  854. { "-sliderlength", TK_OPTION_PIXELS, Tk_Offset(SliderElement,lengthObj),
  855. "15" },
  856. { "-sliderthickness",TK_OPTION_PIXELS,Tk_Offset(SliderElement,thicknessObj),
  857. "15" },
  858. { "-sliderrelief", TK_OPTION_RELIEF, Tk_Offset(SliderElement,reliefObj),
  859. "raised" },
  860. { "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(SliderElement,borderWidthObj),
  861. STRINGIFY(BORDERWIDTH) },
  862. { "-background", TK_OPTION_BORDER, Tk_Offset(SliderElement,borderObj),
  863. DEFAULT_BACKGROUND },
  864. { "-bordercolor", TK_OPTION_COLOR, Tk_Offset(ThumbElement,borderColorObj),
  865. "black" },
  866. { "-orient", TK_OPTION_ANY, Tk_Offset(SliderElement,orientObj),
  867. "horizontal" },
  868. { NULL }
  869. };
  870. static void SliderElementSize(
  871. void *clientData, void *elementRecord, Tk_Window tkwin,
  872. int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
  873. {
  874. SliderElement *slider = elementRecord;
  875. int orient, length, thickness, borderWidth;
  876. Ttk_GetOrientFromObj(NULL, slider->orientObj, &orient);
  877. Tk_GetPixelsFromObj(NULL, tkwin, slider->borderWidthObj, &borderWidth);
  878. Tk_GetPixelsFromObj(NULL, tkwin, slider->lengthObj, &length);
  879. Tk_GetPixelsFromObj(NULL, tkwin, slider->thicknessObj, &thickness);
  880. switch (orient) {
  881. case TTK_ORIENT_VERTICAL:
  882. *widthPtr = thickness + (borderWidth *2);
  883. *heightPtr = *widthPtr/2;
  884. break;
  885. case TTK_ORIENT_HORIZONTAL:
  886. *heightPtr = thickness + (borderWidth *2);
  887. *widthPtr = *heightPtr/2;
  888. break;
  889. }
  890. }
  891. static void SliderElementDraw(
  892. void *clientData, void *elementRecord, Tk_Window tkwin,
  893. Drawable d, Ttk_Box b, unsigned int state)
  894. {
  895. SliderElement *slider = elementRecord;
  896. Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, slider->borderObj);
  897. XColor *borderColor = Tk_GetColorFromObj(tkwin, slider->borderColorObj);
  898. int relief = TK_RELIEF_RAISED, borderWidth = 2;
  899. Tk_GetPixelsFromObj(NULL, tkwin, slider->borderWidthObj, &borderWidth);
  900. Tk_GetReliefFromObj(NULL, slider->reliefObj, &relief);
  901. Tk_Fill3DRectangle(tkwin, d, border,
  902. b.x, b.y, b.width, b.height,
  903. borderWidth, TK_RELIEF_FLAT);
  904. DrawBorder(tkwin, d, border, borderColor, b, borderWidth, relief);
  905. }
  906. static Ttk_ElementSpec SliderElementSpec =
  907. {
  908. TK_STYLE_VERSION_2,
  909. sizeof(SliderElement),
  910. SliderElementOptions,
  911. SliderElementSize,
  912. SliderElementDraw
  913. };
  914. /*------------------------------------------------------------------------
  915. * +++ Tree indicator element.
  916. */
  917. #define TTK_STATE_OPEN TTK_STATE_USER1 /* XREF: treeview.c */
  918. #define TTK_STATE_LEAF TTK_STATE_USER2
  919. typedef struct
  920. {
  921. Tcl_Obj *colorObj;
  922. Tcl_Obj *marginObj;
  923. Tcl_Obj *diameterObj;
  924. } TreeitemIndicator;
  925. static Ttk_ElementOptionSpec TreeitemIndicatorOptions[] =
  926. {
  927. { "-foreground", TK_OPTION_COLOR,
  928. Tk_Offset(TreeitemIndicator,colorObj), DEFAULT_FOREGROUND },
  929. { "-diameter", TK_OPTION_PIXELS,
  930. Tk_Offset(TreeitemIndicator,diameterObj), "9" },
  931. { "-indicatormargins", TK_OPTION_STRING,
  932. Tk_Offset(TreeitemIndicator,marginObj), "2 2 4 2" },
  933. {NULL}
  934. };
  935. static void TreeitemIndicatorSize(
  936. void *clientData, void *elementRecord, Tk_Window tkwin,
  937. int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
  938. {
  939. TreeitemIndicator *indicator = elementRecord;
  940. int diameter = 0;
  941. Ttk_Padding margins;
  942. Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins);
  943. Tk_GetPixelsFromObj(NULL, tkwin, indicator->diameterObj, &diameter);
  944. *widthPtr = diameter + Ttk_PaddingWidth(margins);
  945. *heightPtr = diameter + Ttk_PaddingHeight(margins);
  946. }
  947. static void TreeitemIndicatorDraw(
  948. void *clientData, void *elementRecord, Tk_Window tkwin,
  949. Drawable d, Ttk_Box b, Ttk_State state)
  950. {
  951. TreeitemIndicator *indicator = elementRecord;
  952. XColor *color = Tk_GetColorFromObj(tkwin, indicator->colorObj);
  953. GC gc = Tk_GCForColor(color, d);
  954. Ttk_Padding padding = Ttk_UniformPadding(0);
  955. int w = WIN32_XDRAWLINE_HACK;
  956. int cx, cy;
  957. if (state & TTK_STATE_LEAF) {
  958. /* don't draw anything ... */
  959. return;
  960. }
  961. Ttk_GetPaddingFromObj(NULL,tkwin,indicator->marginObj,&padding);
  962. b = Ttk_PadBox(b, padding);
  963. XDrawRectangle(Tk_Display(tkwin), d, gc,
  964. b.x, b.y, b.width - 1, b.height - 1);
  965. cx = b.x + (b.width - 1) / 2;
  966. cy = b.y + (b.height - 1) / 2;
  967. XDrawLine(Tk_Display(tkwin), d, gc, b.x+2, cy, b.x+b.width-3+w, cy);
  968. if (!(state & TTK_STATE_OPEN)) {
  969. /* turn '-' into a '+' */
  970. XDrawLine(Tk_Display(tkwin), d, gc, cx, b.y+2, cx, b.y+b.height-3+w);
  971. }
  972. }
  973. static Ttk_ElementSpec TreeitemIndicatorElementSpec =
  974. {
  975. TK_STYLE_VERSION_2,
  976. sizeof(TreeitemIndicator),
  977. TreeitemIndicatorOptions,
  978. TreeitemIndicatorSize,
  979. TreeitemIndicatorDraw
  980. };
  981. /*------------------------------------------------------------------------
  982. * TtkAltTheme_Init --
  983. * Install alternate theme.
  984. */
  985. MODULE_SCOPE int TtkAltTheme_Init(Tcl_Interp *interp)
  986. {
  987. Ttk_Theme theme = Ttk_CreateTheme(interp, "alt", NULL);
  988. if (!theme) {
  989. return TCL_ERROR;
  990. }
  991. Ttk_RegisterElement(interp, theme, "border", &BorderElementSpec, NULL);
  992. Ttk_RegisterElement(interp, theme, "Checkbutton.indicator",
  993. &IndicatorElementSpec, &checkbutton_spec);
  994. Ttk_RegisterElement(interp, theme, "Radiobutton.indicator",
  995. &IndicatorElementSpec, &radiobutton_spec);
  996. Ttk_RegisterElement(interp, theme, "Menubutton.indicator",
  997. &MenubuttonArrowElementSpec, NULL);
  998. Ttk_RegisterElement(interp, theme, "field", &FieldElementSpec, NULL);
  999. Ttk_RegisterElement(interp, theme, "trough", &TroughElementSpec, NULL);
  1000. Ttk_RegisterElement(interp, theme, "thumb", &ThumbElementSpec, NULL);
  1001. Ttk_RegisterElement(interp, theme, "slider", &SliderElementSpec, NULL);
  1002. Ttk_RegisterElement(interp, theme, "uparrow",
  1003. &ArrowElementSpec, &ArrowElements[0]);
  1004. Ttk_RegisterElement(interp, theme, "downarrow",
  1005. &ArrowElementSpec, &ArrowElements[1]);
  1006. Ttk_RegisterElement(interp, theme, "leftarrow",
  1007. &ArrowElementSpec, &ArrowElements[2]);
  1008. Ttk_RegisterElement(interp, theme, "rightarrow",
  1009. &ArrowElementSpec, &ArrowElements[3]);
  1010. Ttk_RegisterElement(interp, theme, "arrow",
  1011. &ArrowElementSpec, &ArrowElements[0]);
  1012. Ttk_RegisterElement(interp, theme, "arrow",
  1013. &ArrowElementSpec, &ArrowElements[0]);
  1014. Ttk_RegisterElement(interp, theme, "Treeitem.indicator",
  1015. &TreeitemIndicatorElementSpec, 0);
  1016. Tcl_PkgProvide(interp, "ttk::theme::alt", TTK_VERSION);
  1017. return TCL_OK;
  1018. }
  1019. /*EOF*/