PageRenderTime 163ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/brlcad/tags/rel-7-14-4/src/other/tk/generic/ttk/ttkClamTheme.c

https://bitbucket.org/vrrm/brl-cad-copy-for-fast-history-browsing-in-git
C | 973 lines | 763 code | 137 blank | 73 comment | 34 complexity | ef4525f1ae00e54367b563de5281e490 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. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2004 Joe English
  5. *
  6. * "clam" theme; inspired by the XFCE family of Gnome themes.
  7. */
  8. #include <tk.h>
  9. #include "ttkTheme.h"
  10. /*
  11. * Under windows, the Tk-provided XDrawLine and XDrawArc have an
  12. * off-by-one error in the end point. This is especially apparent with this
  13. * theme. Defining this macro as true handles this case.
  14. */
  15. #if defined(WIN32) && !defined(WIN32_XDRAWLINE_HACK)
  16. # define WIN32_XDRAWLINE_HACK 1
  17. #else
  18. # define WIN32_XDRAWLINE_HACK 0
  19. #endif
  20. #define STR(x) StR(x)
  21. #define StR(x) #x
  22. #define SCROLLBAR_THICKNESS 14
  23. #define FRAME_COLOR "#dcdad5"
  24. #define LIGHT_COLOR "#ffffff"
  25. #define DARK_COLOR "#cfcdc8"
  26. #define DARKER_COLOR "#bab5ab"
  27. #define DARKEST_COLOR "#9e9a91"
  28. /*------------------------------------------------------------------------
  29. * +++ Utilities.
  30. */
  31. static GC Ttk_GCForColor(Tk_Window tkwin, Tcl_Obj* colorObj, Drawable d)
  32. {
  33. GC gc = Tk_GCForColor(Tk_GetColorFromObj(tkwin, colorObj), d);
  34. #ifdef MAC_OSX_TK
  35. /*
  36. * Workaround for Tk bug under Aqua where the default line width is 0.
  37. */
  38. Display *display = Tk_Display(tkwin);
  39. unsigned long mask = 0ul;
  40. XGCValues gcValues;
  41. gcValues.line_width = 1;
  42. mask = GCLineWidth;
  43. XChangeGC(display, gc, mask, &gcValues);
  44. #endif
  45. return gc;
  46. }
  47. static void DrawSmoothBorder(
  48. Tk_Window tkwin, Drawable d, Ttk_Box b,
  49. Tcl_Obj *outerColorObj, Tcl_Obj *upperColorObj, Tcl_Obj *lowerColorObj)
  50. {
  51. Display *display = Tk_Display(tkwin);
  52. int x1 = b.x, x2 = b.x + b.width - 1;
  53. int y1 = b.y, y2 = b.y + b.height - 1;
  54. const int w = WIN32_XDRAWLINE_HACK;
  55. GC gc;
  56. if ( outerColorObj
  57. && (gc=Ttk_GCForColor(tkwin,outerColorObj,d)))
  58. {
  59. XDrawLine(display,d,gc, x1+1,y1, x2-1+w,y1); /* N */
  60. XDrawLine(display,d,gc, x1+1,y2, x2-1+w,y2); /* S */
  61. XDrawLine(display,d,gc, x1,y1+1, x1,y2-1+w); /* E */
  62. XDrawLine(display,d,gc, x2,y1+1, x2,y2-1+w); /* W */
  63. }
  64. if ( upperColorObj
  65. && (gc=Ttk_GCForColor(tkwin,upperColorObj,d)))
  66. {
  67. XDrawLine(display,d,gc, x1+1,y1+1, x2-1+w,y1+1); /* N */
  68. XDrawLine(display,d,gc, x1+1,y1+1, x1+1,y2-1); /* E */
  69. }
  70. if ( lowerColorObj
  71. && (gc=Ttk_GCForColor(tkwin,lowerColorObj,d)))
  72. {
  73. XDrawLine(display,d,gc, x2-1,y2-1, x1+1-w,y2-1); /* S */
  74. XDrawLine(display,d,gc, x2-1,y2-1, x2-1,y1+1-w); /* W */
  75. }
  76. }
  77. static GC BackgroundGC(Tk_Window tkwin, Tcl_Obj *backgroundObj)
  78. {
  79. Tk_3DBorder bd = Tk_Get3DBorderFromObj(tkwin, backgroundObj);
  80. return Tk_3DBorderGC(tkwin, bd, TK_3D_FLAT_GC);
  81. }
  82. /*------------------------------------------------------------------------
  83. * +++ Border element.
  84. */
  85. typedef struct {
  86. Tcl_Obj *borderColorObj;
  87. Tcl_Obj *lightColorObj;
  88. Tcl_Obj *darkColorObj;
  89. Tcl_Obj *reliefObj;
  90. Tcl_Obj *borderWidthObj; /* See <<NOTE-BORDERWIDTH>> */
  91. } BorderElement;
  92. static Ttk_ElementOptionSpec BorderElementOptions[] = {
  93. { "-bordercolor", TK_OPTION_COLOR,
  94. Tk_Offset(BorderElement,borderColorObj), DARKEST_COLOR },
  95. { "-lightcolor", TK_OPTION_COLOR,
  96. Tk_Offset(BorderElement,lightColorObj), LIGHT_COLOR },
  97. { "-darkcolor", TK_OPTION_COLOR,
  98. Tk_Offset(BorderElement,darkColorObj), DARK_COLOR },
  99. { "-relief", TK_OPTION_RELIEF,
  100. Tk_Offset(BorderElement,reliefObj), "flat" },
  101. { "-borderwidth", TK_OPTION_PIXELS,
  102. Tk_Offset(BorderElement,borderWidthObj), "2" },
  103. {0,0,0}
  104. };
  105. /*
  106. * <<NOTE-BORDERWIDTH>>: -borderwidth is only partially supported:
  107. * in this theme, borders are always exactly 2 pixels thick.
  108. * With -borderwidth 0, border is not drawn at all;
  109. * otherwise a 2-pixel border is used. For -borderwidth > 2,
  110. * the excess is used as padding.
  111. */
  112. static void BorderElementSize(
  113. void *clientData, void *elementRecord, Tk_Window tkwin,
  114. int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
  115. {
  116. BorderElement *border = (BorderElement*)elementRecord;
  117. int borderWidth = 2;
  118. Tk_GetPixelsFromObj(NULL, tkwin, border->borderWidthObj, &borderWidth);
  119. if (borderWidth == 1) ++borderWidth;
  120. *paddingPtr = Ttk_UniformPadding((short)borderWidth);
  121. }
  122. static void BorderElementDraw(
  123. void *clientData, void *elementRecord, Tk_Window tkwin,
  124. Drawable d, Ttk_Box b, unsigned state)
  125. {
  126. BorderElement *border = elementRecord;
  127. int relief = TK_RELIEF_FLAT;
  128. int borderWidth = 2;
  129. Tcl_Obj *outer = 0, *upper = 0, *lower = 0;
  130. Tk_GetReliefFromObj(NULL, border->reliefObj, &relief);
  131. Tk_GetPixelsFromObj(NULL, tkwin, border->borderWidthObj, &borderWidth);
  132. if (borderWidth == 0) return;
  133. switch (relief) {
  134. case TK_RELIEF_GROOVE :
  135. case TK_RELIEF_RIDGE :
  136. case TK_RELIEF_RAISED :
  137. outer = border->borderColorObj;
  138. upper = border->lightColorObj;
  139. lower = border->darkColorObj;
  140. break;
  141. case TK_RELIEF_SUNKEN :
  142. outer = border->borderColorObj;
  143. upper = border->darkColorObj;
  144. lower = border->lightColorObj;
  145. break;
  146. case TK_RELIEF_FLAT :
  147. outer = upper = lower = 0;
  148. break;
  149. case TK_RELIEF_SOLID :
  150. outer = upper = lower = border->borderColorObj;
  151. break;
  152. }
  153. DrawSmoothBorder(tkwin, d, b, outer, upper, lower);
  154. }
  155. static Ttk_ElementSpec BorderElementSpec = {
  156. TK_STYLE_VERSION_2,
  157. sizeof(BorderElement),
  158. BorderElementOptions,
  159. BorderElementSize,
  160. BorderElementDraw
  161. };
  162. /*------------------------------------------------------------------------
  163. * +++ Field element.
  164. */
  165. typedef struct {
  166. Tcl_Obj *borderColorObj;
  167. Tcl_Obj *lightColorObj;
  168. Tcl_Obj *darkColorObj;
  169. Tcl_Obj *backgroundObj;
  170. } FieldElement;
  171. static Ttk_ElementOptionSpec FieldElementOptions[] = {
  172. { "-bordercolor", TK_OPTION_COLOR,
  173. Tk_Offset(FieldElement,borderColorObj), DARKEST_COLOR },
  174. { "-lightcolor", TK_OPTION_COLOR,
  175. Tk_Offset(FieldElement,lightColorObj), LIGHT_COLOR },
  176. { "-darkcolor", TK_OPTION_COLOR,
  177. Tk_Offset(FieldElement,darkColorObj), DARK_COLOR },
  178. { "-fieldbackground", TK_OPTION_BORDER,
  179. Tk_Offset(FieldElement,backgroundObj), "white" },
  180. {0,0,0}
  181. };
  182. static void FieldElementSize(
  183. void *clientData, void *elementRecord, Tk_Window tkwin,
  184. int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
  185. {
  186. *paddingPtr = Ttk_UniformPadding(2);
  187. }
  188. static void FieldElementDraw(
  189. void *clientData, void *elementRecord, Tk_Window tkwin,
  190. Drawable d, Ttk_Box b, unsigned state)
  191. {
  192. FieldElement *field = elementRecord;
  193. Tk_3DBorder bg = Tk_Get3DBorderFromObj(tkwin, field->backgroundObj);
  194. Ttk_Box f = Ttk_PadBox(b, Ttk_UniformPadding(2));
  195. Tcl_Obj *outer = field->borderColorObj,
  196. *inner = field->lightColorObj;
  197. DrawSmoothBorder(tkwin, d, b, outer, inner, inner);
  198. Tk_Fill3DRectangle(
  199. tkwin, d, bg, f.x, f.y, f.width, f.height, 0, TK_RELIEF_SUNKEN);
  200. }
  201. static Ttk_ElementSpec FieldElementSpec = {
  202. TK_STYLE_VERSION_2,
  203. sizeof(FieldElement),
  204. FieldElementOptions,
  205. FieldElementSize,
  206. FieldElementDraw
  207. };
  208. /*
  209. * Modified field element for comboboxes:
  210. * Right edge is expanded to overlap the dropdown button.
  211. */
  212. static void ComboboxFieldElementDraw(
  213. void *clientData, void *elementRecord, Tk_Window tkwin,
  214. Drawable d, Ttk_Box b, unsigned state)
  215. {
  216. FieldElement *field = elementRecord;
  217. GC gc = Ttk_GCForColor(tkwin,field->borderColorObj,d);
  218. ++b.width;
  219. FieldElementDraw(clientData, elementRecord, tkwin, d, b, state);
  220. XDrawLine(Tk_Display(tkwin), d, gc,
  221. b.x + b.width - 1, b.y,
  222. b.x + b.width - 1, b.y + b.height - 1 + WIN32_XDRAWLINE_HACK);
  223. }
  224. static Ttk_ElementSpec ComboboxFieldElementSpec = {
  225. TK_STYLE_VERSION_2,
  226. sizeof(FieldElement),
  227. FieldElementOptions,
  228. FieldElementSize,
  229. ComboboxFieldElementDraw
  230. };
  231. /*------------------------------------------------------------------------
  232. * +++ Indicator elements for check and radio buttons.
  233. */
  234. typedef struct {
  235. Tcl_Obj *sizeObj;
  236. Tcl_Obj *marginObj;
  237. Tcl_Obj *backgroundObj;
  238. Tcl_Obj *foregroundObj;
  239. Tcl_Obj *upperColorObj;
  240. Tcl_Obj *lowerColorObj;
  241. } IndicatorElement;
  242. static Ttk_ElementOptionSpec IndicatorElementOptions[] = {
  243. { "-indicatorsize", TK_OPTION_PIXELS,
  244. Tk_Offset(IndicatorElement,sizeObj), "10" },
  245. { "-indicatormargin", TK_OPTION_STRING,
  246. Tk_Offset(IndicatorElement,marginObj), "1" },
  247. { "-indicatorbackground", TK_OPTION_COLOR,
  248. Tk_Offset(IndicatorElement,backgroundObj), "white" },
  249. { "-indicatorforeground", TK_OPTION_COLOR,
  250. Tk_Offset(IndicatorElement,foregroundObj), "black" },
  251. { "-upperbordercolor", TK_OPTION_COLOR,
  252. Tk_Offset(IndicatorElement,upperColorObj), DARKEST_COLOR },
  253. { "-lowerbordercolor", TK_OPTION_COLOR,
  254. Tk_Offset(IndicatorElement,lowerColorObj), DARK_COLOR },
  255. {0,0,0}
  256. };
  257. static void IndicatorElementSize(
  258. void *clientData, void *elementRecord, Tk_Window tkwin,
  259. int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
  260. {
  261. IndicatorElement *indicator = elementRecord;
  262. Ttk_Padding margins;
  263. int size = 10;
  264. Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins);
  265. Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size);
  266. *widthPtr = size + Ttk_PaddingWidth(margins);
  267. *heightPtr = size + Ttk_PaddingHeight(margins);
  268. }
  269. static void RadioIndicatorElementDraw(
  270. void *clientData, void *elementRecord, Tk_Window tkwin,
  271. Drawable d, Ttk_Box b, unsigned state)
  272. {
  273. IndicatorElement *indicator = elementRecord;
  274. GC gcb=Ttk_GCForColor(tkwin,indicator->backgroundObj,d);
  275. GC gcf=Ttk_GCForColor(tkwin,indicator->foregroundObj,d);
  276. GC gcu=Ttk_GCForColor(tkwin,indicator->upperColorObj,d);
  277. GC gcl=Ttk_GCForColor(tkwin,indicator->lowerColorObj,d);
  278. Ttk_Padding padding;
  279. Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &padding);
  280. b = Ttk_PadBox(b, padding);
  281. XFillArc(Tk_Display(tkwin),d,gcb, b.x,b.y,b.width,b.height, 0,360*64);
  282. XDrawArc(Tk_Display(tkwin),d,gcl, b.x,b.y,b.width,b.height, 225*64,180*64);
  283. XDrawArc(Tk_Display(tkwin),d,gcu, b.x,b.y,b.width,b.height, 45*64,180*64);
  284. if (state & TTK_STATE_SELECTED) {
  285. b = Ttk_PadBox(b,Ttk_UniformPadding(3));
  286. XFillArc(Tk_Display(tkwin),d,gcf, b.x,b.y,b.width,b.height, 0,360*64);
  287. XDrawArc(Tk_Display(tkwin),d,gcf, b.x,b.y,b.width,b.height, 0,360*64);
  288. #if WIN32_XDRAWLINE_HACK
  289. XDrawArc(Tk_Display(tkwin),d,gcf, b.x,b.y,b.width,b.height, 300*64,360*64);
  290. #endif
  291. }
  292. }
  293. static void CheckIndicatorElementDraw(
  294. void *clientData, void *elementRecord, Tk_Window tkwin,
  295. Drawable d, Ttk_Box b, unsigned state)
  296. {
  297. Display *display = Tk_Display(tkwin);
  298. IndicatorElement *indicator = elementRecord;
  299. GC gcb=Ttk_GCForColor(tkwin,indicator->backgroundObj,d);
  300. GC gcf=Ttk_GCForColor(tkwin,indicator->foregroundObj,d);
  301. GC gcu=Ttk_GCForColor(tkwin,indicator->upperColorObj,d);
  302. GC gcl=Ttk_GCForColor(tkwin,indicator->lowerColorObj,d);
  303. Ttk_Padding padding;
  304. const int w = WIN32_XDRAWLINE_HACK;
  305. Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &padding);
  306. b = Ttk_PadBox(b, padding);
  307. XFillRectangle(display,d,gcb, b.x,b.y,b.width,b.height);
  308. XDrawLine(display,d,gcl,b.x,b.y+b.height,b.x+b.width+w,b.y+b.height);/*S*/
  309. XDrawLine(display,d,gcl,b.x+b.width,b.y,b.x+b.width,b.y+b.height+w); /*E*/
  310. XDrawLine(display,d,gcu,b.x,b.y, b.x,b.y+b.height+w); /*W*/
  311. XDrawLine(display,d,gcu,b.x,b.y, b.x+b.width+w,b.y); /*N*/
  312. if (state & TTK_STATE_SELECTED) {
  313. int p,q,r,s;
  314. b = Ttk_PadBox(b,Ttk_UniformPadding(2));
  315. p = b.x, q = b.y, r = b.x+b.width, s = b.y+b.height;
  316. r+=w, s+=w;
  317. XDrawLine(display, d, gcf, p, q, r, s);
  318. XDrawLine(display, d, gcf, p+1, q, r, s-1);
  319. XDrawLine(display, d, gcf, p, q+1, r-1, s);
  320. s-=w, q-=w;
  321. XDrawLine(display, d, gcf, p, s, r, q);
  322. XDrawLine(display, d, gcf, p+1, s, r, q+1);
  323. XDrawLine(display, d, gcf, p, s-1, r-1, q);
  324. }
  325. }
  326. static Ttk_ElementSpec RadioIndicatorElementSpec = {
  327. TK_STYLE_VERSION_2,
  328. sizeof(IndicatorElement),
  329. IndicatorElementOptions,
  330. IndicatorElementSize,
  331. RadioIndicatorElementDraw
  332. };
  333. static Ttk_ElementSpec CheckIndicatorElementSpec = {
  334. TK_STYLE_VERSION_2,
  335. sizeof(IndicatorElement),
  336. IndicatorElementOptions,
  337. IndicatorElementSize,
  338. CheckIndicatorElementDraw
  339. };
  340. #define MENUBUTTON_ARROW_SIZE 5
  341. typedef struct {
  342. Tcl_Obj *sizeObj;
  343. Tcl_Obj *colorObj;
  344. Tcl_Obj *paddingObj;
  345. } MenuIndicatorElement;
  346. static Ttk_ElementOptionSpec MenuIndicatorElementOptions[] =
  347. {
  348. { "-arrowsize", TK_OPTION_PIXELS,
  349. Tk_Offset(MenuIndicatorElement,sizeObj),
  350. STR(MENUBUTTON_ARROW_SIZE)},
  351. { "-arrowcolor",TK_OPTION_COLOR,
  352. Tk_Offset(MenuIndicatorElement,colorObj),
  353. "black" },
  354. { "-arrowpadding",TK_OPTION_STRING,
  355. Tk_Offset(MenuIndicatorElement,paddingObj),
  356. "3" },
  357. { NULL }
  358. };
  359. static void MenuIndicatorElementSize(
  360. void *clientData, void *elementRecord, Tk_Window tkwin,
  361. int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
  362. {
  363. MenuIndicatorElement *indicator = elementRecord;
  364. Ttk_Padding margins;
  365. int size = MENUBUTTON_ARROW_SIZE;
  366. Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size);
  367. Ttk_GetPaddingFromObj(NULL, tkwin, indicator->paddingObj, &margins);
  368. TtkArrowSize(size, ARROW_DOWN, widthPtr, heightPtr);
  369. *widthPtr += Ttk_PaddingWidth(margins);
  370. *heightPtr += Ttk_PaddingHeight(margins);
  371. }
  372. static void MenuIndicatorElementDraw(
  373. void *clientData, void *elementRecord, Tk_Window tkwin,
  374. Drawable d, Ttk_Box b, unsigned int state)
  375. {
  376. MenuIndicatorElement *indicator = elementRecord;
  377. XColor *arrowColor = Tk_GetColorFromObj(tkwin, indicator->colorObj);
  378. GC gc = Tk_GCForColor(arrowColor, d);
  379. int size = MENUBUTTON_ARROW_SIZE;
  380. int width, height;
  381. Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size);
  382. TtkArrowSize(size, ARROW_DOWN, &width, &height);
  383. b = Ttk_StickBox(b, width, height, 0);
  384. TtkFillArrow(Tk_Display(tkwin), d, gc, b, ARROW_DOWN);
  385. }
  386. static Ttk_ElementSpec MenuIndicatorElementSpec =
  387. {
  388. TK_STYLE_VERSION_2,
  389. sizeof(MenuIndicatorElement),
  390. MenuIndicatorElementOptions,
  391. MenuIndicatorElementSize,
  392. MenuIndicatorElementDraw
  393. };
  394. /*------------------------------------------------------------------------
  395. * +++ Grips.
  396. *
  397. * TODO: factor this with ThumbElementDraw
  398. */
  399. static Ttk_Orient GripClientData[] = {
  400. TTK_ORIENT_HORIZONTAL, TTK_ORIENT_VERTICAL
  401. };
  402. typedef struct {
  403. Tcl_Obj *lightColorObj;
  404. Tcl_Obj *borderColorObj;
  405. Tcl_Obj *gripCountObj;
  406. } GripElement;
  407. static Ttk_ElementOptionSpec GripElementOptions[] = {
  408. { "-lightcolor", TK_OPTION_COLOR,
  409. Tk_Offset(GripElement,lightColorObj), LIGHT_COLOR },
  410. { "-bordercolor", TK_OPTION_COLOR,
  411. Tk_Offset(GripElement,borderColorObj), DARKEST_COLOR },
  412. { "-gripcount", TK_OPTION_INT,
  413. Tk_Offset(GripElement,gripCountObj), "5" },
  414. {0,0,0}
  415. };
  416. static void GripElementSize(
  417. void *clientData, void *elementRecord, Tk_Window tkwin,
  418. int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
  419. {
  420. int horizontal = *((Ttk_Orient*)clientData) == TTK_ORIENT_HORIZONTAL;
  421. GripElement *grip = elementRecord;
  422. int gripCount = 0;
  423. Tcl_GetIntFromObj(NULL, grip->gripCountObj, &gripCount);
  424. if (horizontal) {
  425. *widthPtr = 2*gripCount;
  426. } else {
  427. *heightPtr = 2*gripCount;
  428. }
  429. }
  430. static void GripElementDraw(
  431. void *clientData, void *elementRecord, Tk_Window tkwin,
  432. Drawable d, Ttk_Box b, unsigned state)
  433. {
  434. const int w = WIN32_XDRAWLINE_HACK;
  435. int horizontal = *((Ttk_Orient*)clientData) == TTK_ORIENT_HORIZONTAL;
  436. GripElement *grip = elementRecord;
  437. GC lightGC = Ttk_GCForColor(tkwin,grip->lightColorObj,d);
  438. GC darkGC = Ttk_GCForColor(tkwin,grip->borderColorObj,d);
  439. int gripPad = 1, gripCount = 0;
  440. int i;
  441. Tcl_GetIntFromObj(NULL, grip->gripCountObj, &gripCount);
  442. if (horizontal) {
  443. int x = b.x + b.width / 2 - gripCount;
  444. int y1 = b.y + gripPad, y2 = b.y + b.height - gripPad - 1 + w;
  445. for (i=0; i<gripCount; ++i) {
  446. XDrawLine(Tk_Display(tkwin), d, darkGC, x,y1, x,y2); ++x;
  447. XDrawLine(Tk_Display(tkwin), d, lightGC, x,y1, x,y2); ++x;
  448. }
  449. } else {
  450. int y = b.y + b.height / 2 - gripCount;
  451. int x1 = b.x + gripPad, x2 = b.x + b.width - gripPad - 1 + w;
  452. for (i=0; i<gripCount; ++i) {
  453. XDrawLine(Tk_Display(tkwin), d, darkGC, x1,y, x2,y); ++y;
  454. XDrawLine(Tk_Display(tkwin), d, lightGC, x1,y, x2,y); ++y;
  455. }
  456. }
  457. }
  458. static Ttk_ElementSpec GripElementSpec = {
  459. TK_STYLE_VERSION_2,
  460. sizeof(GripElement),
  461. GripElementOptions,
  462. GripElementSize,
  463. GripElementDraw
  464. };
  465. /*------------------------------------------------------------------------
  466. * +++ Scrollbar elements: trough, arrows, thumb.
  467. *
  468. * Notice that the trough element has 0 internal padding;
  469. * that way the thumb and arrow borders overlap the trough.
  470. */
  471. typedef struct { /* Common element record for scrollbar elements */
  472. Tcl_Obj *orientObj;
  473. Tcl_Obj *backgroundObj;
  474. Tcl_Obj *borderColorObj;
  475. Tcl_Obj *troughColorObj;
  476. Tcl_Obj *lightColorObj;
  477. Tcl_Obj *darkColorObj;
  478. Tcl_Obj *arrowColorObj;
  479. Tcl_Obj *arrowSizeObj;
  480. Tcl_Obj *gripCountObj;
  481. Tcl_Obj *sliderlengthObj;
  482. } ScrollbarElement;
  483. static Ttk_ElementOptionSpec ScrollbarElementOptions[] = {
  484. { "-orient", TK_OPTION_ANY,
  485. Tk_Offset(ScrollbarElement, orientObj), "horizontal" },
  486. { "-background", TK_OPTION_BORDER,
  487. Tk_Offset(ScrollbarElement,backgroundObj), FRAME_COLOR },
  488. { "-bordercolor", TK_OPTION_COLOR,
  489. Tk_Offset(ScrollbarElement,borderColorObj), DARKEST_COLOR },
  490. { "-troughcolor", TK_OPTION_COLOR,
  491. Tk_Offset(ScrollbarElement,troughColorObj), DARKER_COLOR },
  492. { "-lightcolor", TK_OPTION_COLOR,
  493. Tk_Offset(ScrollbarElement,lightColorObj), LIGHT_COLOR },
  494. { "-darkcolor", TK_OPTION_COLOR,
  495. Tk_Offset(ScrollbarElement,darkColorObj), DARK_COLOR },
  496. { "-arrowcolor", TK_OPTION_COLOR,
  497. Tk_Offset(ScrollbarElement,arrowColorObj), "#000000" },
  498. { "-arrowsize", TK_OPTION_PIXELS,
  499. Tk_Offset(ScrollbarElement,arrowSizeObj), STR(SCROLLBAR_THICKNESS) },
  500. { "-gripcount", TK_OPTION_INT,
  501. Tk_Offset(ScrollbarElement,gripCountObj), "5" },
  502. { "-sliderlength", TK_OPTION_INT,
  503. Tk_Offset(ScrollbarElement,sliderlengthObj), "30" },
  504. {0,0,0}
  505. };
  506. static void TroughElementDraw(
  507. void *clientData, void *elementRecord, Tk_Window tkwin,
  508. Drawable d, Ttk_Box b, unsigned state)
  509. {
  510. ScrollbarElement *sb = elementRecord;
  511. GC gcb = Ttk_GCForColor(tkwin,sb->borderColorObj,d);
  512. GC gct = Ttk_GCForColor(tkwin,sb->troughColorObj,d);
  513. XFillRectangle(Tk_Display(tkwin), d, gct, b.x, b.y, b.width-1, b.height-1);
  514. XDrawRectangle(Tk_Display(tkwin), d, gcb, b.x, b.y, b.width-1, b.height-1);
  515. }
  516. static Ttk_ElementSpec TroughElementSpec = {
  517. TK_STYLE_VERSION_2,
  518. sizeof(ScrollbarElement),
  519. ScrollbarElementOptions,
  520. TtkNullElementSize,
  521. TroughElementDraw
  522. };
  523. static void ThumbElementSize(
  524. void *clientData, void *elementRecord, Tk_Window tkwin,
  525. int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
  526. {
  527. ScrollbarElement *sb = elementRecord;
  528. int size = SCROLLBAR_THICKNESS;
  529. Tcl_GetIntFromObj(NULL, sb->arrowSizeObj, &size);
  530. *widthPtr = *heightPtr = size;
  531. }
  532. static void ThumbElementDraw(
  533. void *clientData, void *elementRecord, Tk_Window tkwin,
  534. Drawable d, Ttk_Box b, unsigned state)
  535. {
  536. ScrollbarElement *sb = elementRecord;
  537. int gripCount = 0, orient = TTK_ORIENT_HORIZONTAL;
  538. GC lightGC, darkGC;
  539. int x1, y1, x2, y2, dx, dy, i;
  540. const int w = WIN32_XDRAWLINE_HACK;
  541. DrawSmoothBorder(tkwin, d, b,
  542. sb->borderColorObj, sb->lightColorObj, sb->darkColorObj);
  543. XFillRectangle(
  544. Tk_Display(tkwin), d, BackgroundGC(tkwin, sb->backgroundObj),
  545. b.x+2, b.y+2, b.width-4, b.height-4);
  546. /*
  547. * Draw grip:
  548. */
  549. Ttk_GetOrientFromObj(NULL, sb->orientObj, &orient);
  550. Tcl_GetIntFromObj(NULL, sb->gripCountObj, &gripCount);
  551. lightGC = Ttk_GCForColor(tkwin,sb->lightColorObj,d);
  552. darkGC = Ttk_GCForColor(tkwin,sb->borderColorObj,d);
  553. if (orient == TTK_ORIENT_HORIZONTAL) {
  554. dx = 1; dy = 0;
  555. x1 = x2 = b.x + b.width / 2 - gripCount;
  556. y1 = b.y + 2;
  557. y2 = b.y + b.height - 3 + w;
  558. } else {
  559. dx = 0; dy = 1;
  560. y1 = y2 = b.y + b.height / 2 - gripCount;
  561. x1 = b.x + 2;
  562. x2 = b.x + b.width - 3 + w;
  563. }
  564. for (i=0; i<gripCount; ++i) {
  565. XDrawLine(Tk_Display(tkwin), d, darkGC, x1,y1, x2,y2);
  566. x1 += dx; x2 += dx; y1 += dy; y2 += dy;
  567. XDrawLine(Tk_Display(tkwin), d, lightGC, x1,y1, x2,y2);
  568. x1 += dx; x2 += dx; y1 += dy; y2 += dy;
  569. }
  570. }
  571. static Ttk_ElementSpec ThumbElementSpec = {
  572. TK_STYLE_VERSION_2,
  573. sizeof(ScrollbarElement),
  574. ScrollbarElementOptions,
  575. ThumbElementSize,
  576. ThumbElementDraw
  577. };
  578. /*------------------------------------------------------------------------
  579. * +++ Slider element.
  580. */
  581. static void SliderElementSize(
  582. void *clientData, void *elementRecord, Tk_Window tkwin,
  583. int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
  584. {
  585. ScrollbarElement *sb = elementRecord;
  586. int length, thickness, orient;
  587. length = thickness = SCROLLBAR_THICKNESS;
  588. Ttk_GetOrientFromObj(NULL, sb->orientObj, &orient);
  589. Tcl_GetIntFromObj(NULL, sb->arrowSizeObj, &thickness);
  590. Tk_GetPixelsFromObj(NULL, tkwin, sb->sliderlengthObj, &length);
  591. if (orient == TTK_ORIENT_VERTICAL) {
  592. *heightPtr = length;
  593. *widthPtr = thickness;
  594. } else {
  595. *heightPtr = thickness;
  596. *widthPtr = length;
  597. }
  598. }
  599. static Ttk_ElementSpec SliderElementSpec = {
  600. TK_STYLE_VERSION_2,
  601. sizeof(ScrollbarElement),
  602. ScrollbarElementOptions,
  603. SliderElementSize,
  604. ThumbElementDraw
  605. };
  606. /*------------------------------------------------------------------------
  607. * +++ Progress bar element
  608. */
  609. static void PbarElementSize(
  610. void *clientData, void *elementRecord, Tk_Window tkwin,
  611. int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
  612. {
  613. SliderElementSize(clientData, elementRecord, tkwin,
  614. widthPtr, heightPtr, paddingPtr);
  615. *paddingPtr = Ttk_UniformPadding(2);
  616. *widthPtr += 4;
  617. *heightPtr += 4;
  618. }
  619. static void PbarElementDraw(
  620. void *clientData, void *elementRecord, Tk_Window tkwin,
  621. Drawable d, Ttk_Box b, unsigned state)
  622. {
  623. ScrollbarElement *sb = elementRecord;
  624. b = Ttk_PadBox(b, Ttk_UniformPadding(2));
  625. if (b.width > 4 && b.height > 4) {
  626. DrawSmoothBorder(tkwin, d, b,
  627. sb->borderColorObj, sb->lightColorObj, sb->darkColorObj);
  628. XFillRectangle(Tk_Display(tkwin), d,
  629. BackgroundGC(tkwin, sb->backgroundObj),
  630. b.x+2, b.y+2, b.width-4, b.height-4);
  631. }
  632. }
  633. static Ttk_ElementSpec PbarElementSpec = {
  634. TK_STYLE_VERSION_2,
  635. sizeof(ScrollbarElement),
  636. ScrollbarElementOptions,
  637. PbarElementSize,
  638. PbarElementDraw
  639. };
  640. /*------------------------------------------------------------------------
  641. * +++ Scrollbar arrows.
  642. */
  643. static int ArrowElements[] = { ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT };
  644. static void ArrowElementSize(
  645. void *clientData, void *elementRecord, Tk_Window tkwin,
  646. int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
  647. {
  648. ScrollbarElement *sb = elementRecord;
  649. int size = SCROLLBAR_THICKNESS;
  650. Tcl_GetIntFromObj(NULL, sb->arrowSizeObj, &size);
  651. *widthPtr = *heightPtr = size;
  652. }
  653. static void ArrowElementDraw(
  654. void *clientData, void *elementRecord, Tk_Window tkwin,
  655. Drawable d, Ttk_Box b, unsigned state)
  656. {
  657. ArrowDirection dir = *(ArrowDirection*)clientData;
  658. ScrollbarElement *sb = elementRecord;
  659. GC gc = Ttk_GCForColor(tkwin,sb->arrowColorObj, d);
  660. int h, cx, cy;
  661. DrawSmoothBorder(tkwin, d, b,
  662. sb->borderColorObj, sb->lightColorObj, sb->darkColorObj);
  663. XFillRectangle(
  664. Tk_Display(tkwin), d, BackgroundGC(tkwin, sb->backgroundObj),
  665. b.x+2, b.y+2, b.width-4, b.height-4);
  666. b = Ttk_PadBox(b, Ttk_UniformPadding(3));
  667. h = b.width < b.height ? b.width : b.height;
  668. TtkArrowSize(h/2, dir, &cx, &cy);
  669. b = Ttk_AnchorBox(b, cx, cy, TK_ANCHOR_CENTER);
  670. TtkFillArrow(Tk_Display(tkwin), d, gc, b, dir);
  671. }
  672. static Ttk_ElementSpec ArrowElementSpec = {
  673. TK_STYLE_VERSION_2,
  674. sizeof(ScrollbarElement),
  675. ScrollbarElementOptions,
  676. ArrowElementSize,
  677. ArrowElementDraw
  678. };
  679. /*------------------------------------------------------------------------
  680. * +++ Notebook elements.
  681. *
  682. * Note: Tabs, except for the rightmost, overlap the neighbor to
  683. * their right by one pixel.
  684. */
  685. typedef struct {
  686. Tcl_Obj *backgroundObj;
  687. Tcl_Obj *borderColorObj;
  688. Tcl_Obj *lightColorObj;
  689. Tcl_Obj *darkColorObj;
  690. } NotebookElement;
  691. static Ttk_ElementOptionSpec NotebookElementOptions[] = {
  692. { "-background", TK_OPTION_BORDER,
  693. Tk_Offset(NotebookElement,backgroundObj), FRAME_COLOR },
  694. { "-bordercolor", TK_OPTION_COLOR,
  695. Tk_Offset(NotebookElement,borderColorObj), DARKEST_COLOR },
  696. { "-lightcolor", TK_OPTION_COLOR,
  697. Tk_Offset(NotebookElement,lightColorObj), LIGHT_COLOR },
  698. { "-darkcolor", TK_OPTION_COLOR,
  699. Tk_Offset(NotebookElement,darkColorObj), DARK_COLOR },
  700. {0,0,0}
  701. };
  702. static void TabElementSize(
  703. void *clientData, void *elementRecord, Tk_Window tkwin,
  704. int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
  705. {
  706. int borderWidth = 2;
  707. paddingPtr->top = paddingPtr->left = paddingPtr->right = borderWidth;
  708. paddingPtr->bottom = 0;
  709. }
  710. static void TabElementDraw(
  711. void *clientData, void *elementRecord, Tk_Window tkwin,
  712. Drawable d, Ttk_Box b, unsigned int state)
  713. {
  714. NotebookElement *tab = elementRecord;
  715. Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, tab->backgroundObj);
  716. Display *display = Tk_Display(tkwin);
  717. int borderWidth = 2, dh = 0;
  718. int x1,y1,x2,y2;
  719. GC gc;
  720. const int w = WIN32_XDRAWLINE_HACK;
  721. if (state & TTK_STATE_SELECTED) {
  722. dh = borderWidth;
  723. }
  724. if (state & TTK_STATE_USER2) { /* Rightmost tab */
  725. --b.width;
  726. }
  727. Tk_Fill3DRectangle(tkwin, d, border,
  728. b.x+2, b.y+2, b.width-1, b.height-2+dh, borderWidth, TK_RELIEF_FLAT);
  729. x1 = b.x, x2 = b.x + b.width;
  730. y1 = b.y, y2 = b.y + b.height;
  731. gc=Ttk_GCForColor(tkwin,tab->borderColorObj,d);
  732. XDrawLine(display,d,gc, x1,y1+1, x1,y2+w);
  733. XDrawLine(display,d,gc, x2,y1+1, x2,y2+w);
  734. XDrawLine(display,d,gc, x1+1,y1, x2-1+w,y1);
  735. gc=Ttk_GCForColor(tkwin,tab->lightColorObj,d);
  736. XDrawLine(display,d,gc, x1+1,y1+1, x1+1,y2-1+dh+w);
  737. XDrawLine(display,d,gc, x1+1,y1+1, x2-1+w,y1+1);
  738. }
  739. static Ttk_ElementSpec TabElementSpec =
  740. {
  741. TK_STYLE_VERSION_2,
  742. sizeof(NotebookElement),
  743. NotebookElementOptions,
  744. TabElementSize,
  745. TabElementDraw
  746. };
  747. static void ClientElementSize(
  748. void *clientData, void *elementRecord, Tk_Window tkwin,
  749. int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
  750. {
  751. int borderWidth = 2;
  752. *paddingPtr = Ttk_UniformPadding((short)borderWidth);
  753. }
  754. static void ClientElementDraw(
  755. void *clientData, void *elementRecord, Tk_Window tkwin,
  756. Drawable d, Ttk_Box b, unsigned int state)
  757. {
  758. NotebookElement *ce = elementRecord;
  759. Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, ce->backgroundObj);
  760. int borderWidth = 2;
  761. Tk_Fill3DRectangle(tkwin, d, border,
  762. b.x, b.y, b.width, b.height, borderWidth,TK_RELIEF_FLAT);
  763. DrawSmoothBorder(tkwin, d, b,
  764. ce->borderColorObj, ce->lightColorObj, ce->darkColorObj);
  765. }
  766. static Ttk_ElementSpec ClientElementSpec =
  767. {
  768. TK_STYLE_VERSION_2,
  769. sizeof(NotebookElement),
  770. NotebookElementOptions,
  771. ClientElementSize,
  772. ClientElementDraw
  773. };
  774. /*------------------------------------------------------------------------
  775. * +++ Modified widget layouts.
  776. */
  777. TTK_BEGIN_LAYOUT_TABLE(LayoutTable)
  778. TTK_LAYOUT("TCombobox",
  779. TTK_NODE("Combobox.downarrow", TTK_PACK_RIGHT|TTK_FILL_Y)
  780. TTK_GROUP("Combobox.field", TTK_PACK_LEFT|TTK_FILL_BOTH|TTK_EXPAND,
  781. TTK_GROUP("Combobox.padding", TTK_FILL_BOTH,
  782. TTK_NODE("Combobox.textarea", TTK_FILL_BOTH))))
  783. TTK_LAYOUT("Horizontal.Sash",
  784. TTK_GROUP("Sash.hsash", TTK_FILL_BOTH,
  785. TTK_NODE("Sash.hgrip", TTK_FILL_BOTH)))
  786. TTK_LAYOUT("Vertical.Sash",
  787. TTK_GROUP("Sash.vsash", TTK_FILL_BOTH,
  788. TTK_NODE("Sash.vgrip", TTK_FILL_BOTH)))
  789. TTK_END_LAYOUT_TABLE
  790. /*------------------------------------------------------------------------
  791. * +++ Initialization.
  792. */
  793. MODULE_SCOPE int
  794. TtkClamTheme_Init(Tcl_Interp *interp)
  795. {
  796. Ttk_Theme theme = Ttk_CreateTheme(interp, "clam", 0);
  797. if (!theme) {
  798. return TCL_ERROR;
  799. }
  800. Ttk_RegisterElement(interp,
  801. theme, "border", &BorderElementSpec, NULL);
  802. Ttk_RegisterElement(interp,
  803. theme, "field", &FieldElementSpec, NULL);
  804. Ttk_RegisterElement(interp,
  805. theme, "Combobox.field", &ComboboxFieldElementSpec, NULL);
  806. Ttk_RegisterElement(interp,
  807. theme, "trough", &TroughElementSpec, NULL);
  808. Ttk_RegisterElement(interp,
  809. theme, "thumb", &ThumbElementSpec, NULL);
  810. Ttk_RegisterElement(interp,
  811. theme, "uparrow", &ArrowElementSpec, &ArrowElements[0]);
  812. Ttk_RegisterElement(interp,
  813. theme, "downarrow", &ArrowElementSpec, &ArrowElements[1]);
  814. Ttk_RegisterElement(interp,
  815. theme, "leftarrow", &ArrowElementSpec, &ArrowElements[2]);
  816. Ttk_RegisterElement(interp,
  817. theme, "rightarrow", &ArrowElementSpec, &ArrowElements[3]);
  818. Ttk_RegisterElement(interp,
  819. theme, "Radiobutton.indicator", &RadioIndicatorElementSpec, NULL);
  820. Ttk_RegisterElement(interp,
  821. theme, "Checkbutton.indicator", &CheckIndicatorElementSpec, NULL);
  822. Ttk_RegisterElement(interp,
  823. theme, "Menubutton.indicator", &MenuIndicatorElementSpec, NULL);
  824. Ttk_RegisterElement(interp, theme, "tab", &TabElementSpec, NULL);
  825. Ttk_RegisterElement(interp, theme, "client", &ClientElementSpec, NULL);
  826. Ttk_RegisterElement(interp, theme, "slider", &SliderElementSpec, NULL);
  827. Ttk_RegisterElement(interp, theme, "bar", &PbarElementSpec, NULL);
  828. Ttk_RegisterElement(interp, theme, "pbar", &PbarElementSpec, NULL);
  829. Ttk_RegisterElement(interp, theme, "hgrip",
  830. &GripElementSpec, &GripClientData[0]);
  831. Ttk_RegisterElement(interp, theme, "vgrip",
  832. &GripElementSpec, &GripClientData[1]);
  833. Ttk_RegisterLayouts(theme, LayoutTable);
  834. Tcl_PkgProvide(interp, "ttk::theme::clam", TTK_VERSION);
  835. return TCL_OK;
  836. }