x3common.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. /* Functions common to more than one platform. */
  2. #include <stdlib.h>
  3. #include "x3.h"
  4. #include "x3common.h"
  5. int n_x3needshow = 0;
  6. int n_x3needshow_max = 0;
  7. x3widget **x3needshow = NULL;
  8. #if defined(X3_GTK) || defined(X3_WIN32)
  9. int x3n_winopen = 0;
  10. #endif
  11. #if defined(X3_CARBON) || defined(X3_WIN32)
  12. int n_x3needsizereqs = 0;
  13. int n_x3needsizereqs_max = 0;
  14. x3widget **x3needsizereqs = NULL;
  15. int n_x3needsizeallocs = 0;
  16. int n_x3needsizeallocs_max = 0;
  17. x3widget **x3needsizeallocs = NULL;
  18. void x3qsizereq(x3widget *w)
  19. {
  20. if (w && !(w->flags & x3flag_needsizereq)) {
  21. x3qsizereq(w->parent);
  22. if (n_x3needsizereqs == n_x3needsizereqs_max)
  23. x3needsizereqs = (x3widget **)realloc(x3needsizereqs,
  24. sizeof(x3widget *) *
  25. (n_x3needsizereqs_max <<= 1));
  26. x3needsizereqs[n_x3needsizereqs++] = w;
  27. w->flags |= x3flag_needsizereq;
  28. }
  29. }
  30. void x3add_default(x3widget *parent, x3widget *child)
  31. {
  32. const int n_children_init = 4;
  33. child->parent = parent;
  34. if (parent->n_children == 0)
  35. parent->children = (x3widget **)malloc(sizeof(x3widget *) *
  36. n_children_init);
  37. else if (parent->n_children >= n_children_init &&
  38. !(parent->n_children & (parent->n_children - 1)))
  39. parent->children = (x3widget **)realloc(parent->children,
  40. sizeof(x3widget *) *
  41. (parent->n_children << 1));
  42. parent->children[parent->n_children++] = child;
  43. }
  44. void x3add(x3widget *parent, x3widget *child)
  45. {
  46. parent->type->add(parent, child);
  47. }
  48. /* Widgets common to carbon and win32 platforms */
  49. typedef struct {
  50. x3widget base;
  51. int homogeneous;
  52. int spacing;
  53. int cur_child_prop;
  54. int *child_props; /* bit 0=expand, bit 1=fill, bits 2:31=padding */
  55. } x3widget_box;
  56. void x3vbox_sizereq(x3widget *w)
  57. {
  58. x3widget_box *wb = (x3widget_box *)w;
  59. int i;
  60. int spacing = wb->spacing;
  61. w->sizerequest.x0 = 0;
  62. w->sizerequest.y0 = 0;
  63. w->sizerequest.x1 = 0;
  64. w->sizerequest.y1 = 0;
  65. for (i = 0; i < w->n_children; i++) {
  66. x3widget *child = w->children[i];
  67. int childw = child->sizerequest.x1 - child->sizerequest.x0;
  68. int childh = child->sizerequest.y1 - child->sizerequest.y0;
  69. int padding = wb->child_props[i] >> 2;
  70. if (i < w->n_children - 1)
  71. childh += spacing;
  72. w->sizerequest.y1 += childh + 2 * padding;
  73. if (childw > w->sizerequest.x1)
  74. w->sizerequest.x1 = childw;
  75. }
  76. }
  77. void x3vbox_sizealloc(x3widget *w, x3rect *r)
  78. {
  79. x3widget_box *wb = (x3widget_box *)w;
  80. int i;
  81. x3rect child_r = *r;
  82. int spacing = wb->spacing;
  83. int n_extend = 0;
  84. int n_stretch, i_stretch = 0;
  85. int extra;
  86. /* todo: impl padding & homog, factor hbox/vbox common */
  87. printf("vbox sizealloc = (%g, %g) - (%g, %g), req was %g x %g\n",
  88. r->x0, r->y0, r->x1, r->y1,
  89. w->sizerequest.x1, w->sizerequest.y1);
  90. extra = r->y1 - r->y0 - w->sizerequest.y1;
  91. for (i = 0; i < w->n_children; i++)
  92. if (wb->child_props[i] & 1)
  93. n_extend++;
  94. n_stretch = n_extend ? n_extend : w->n_children;
  95. printf("extra = %d, n_stretch = %d\n", extra, n_stretch);
  96. for (i = 0; i < w->n_children; i++) {
  97. x3widget *child = w->children[i];
  98. int childh = child->sizerequest.y1 - child->sizerequest.y0;
  99. int my_extra;
  100. int next_top;
  101. if (n_extend == 0 || (wb->child_props[i] & 1)) {
  102. my_extra = (extra * (i_stretch + 1)) / n_stretch -
  103. (extra * i_stretch) / n_stretch;
  104. i_stretch++;
  105. } else
  106. my_extra = 0;
  107. next_top = child_r.y0 + childh + spacing + my_extra;
  108. if (wb->child_props[i] & 2) {
  109. childh += my_extra;
  110. } else {
  111. child_r.y0 += my_extra >> 1;
  112. }
  113. child_r.y1 = child_r.y0 + childh;
  114. child->type->sizealloc(child, &child_r);
  115. child->flags &= ~x3flag_needsizealloc;
  116. child_r.y0 = next_top;
  117. }
  118. }
  119. void x3vbox_add(x3widget *w, x3widget *child)
  120. {
  121. x3widget_box *wb = (x3widget_box *)w;
  122. const int n_children_init = 4;
  123. if (w->n_children == 0)
  124. wb->child_props = (int *)malloc(sizeof(int) * n_children_init);
  125. else if (w->n_children >= n_children_init &&
  126. !(w->n_children & (w->n_children - 1)))
  127. wb->child_props = (int *)realloc(wb->child_props,
  128. sizeof(int) * (w->n_children << 1));
  129. wb->child_props[w->n_children] = wb->cur_child_prop;
  130. x3add_default(w, child);
  131. }
  132. x3type x3vboxtype = { x3vbox_sizereq,
  133. x3vbox_sizealloc,
  134. x3vbox_add };
  135. x3widget *x3vbox(x3widget *parent, int homogeneous, int spacing)
  136. {
  137. x3widget_box *result = (x3widget_box *)malloc(sizeof(x3widget_box));
  138. x3widget_init(&result->base, &x3vboxtype);
  139. x3add(parent, &result->base);
  140. result->homogeneous = homogeneous;
  141. result->spacing = spacing;
  142. result->cur_child_prop = 3;
  143. x3qsizereq(&result->base);
  144. return &result->base;
  145. }
  146. void x3setpacking(x3widget *w, int fill, int expand, int padding)
  147. {
  148. if (w->type == &x3vboxtype) {
  149. x3widget_box *wb = (x3widget_box *)w;
  150. int child_props = padding << 2;
  151. if (fill) child_props |= 1;
  152. if (expand) child_props |= 2;
  153. wb->cur_child_prop = child_props;
  154. }
  155. }
  156. typedef struct {
  157. x3widget base;
  158. x3alignment alignment;
  159. } x3widget_align;
  160. void x3align_sizereq(x3widget *w)
  161. {
  162. w->sizerequest.x0 = 0;
  163. w->sizerequest.y0 = 0;
  164. w->sizerequest.x1 = 0;
  165. w->sizerequest.y1 = 0;
  166. if (w->n_children) {
  167. x3widget *child = w->children[0];
  168. int childw = child->sizerequest.x1 - child->sizerequest.x0;
  169. int childh = child->sizerequest.y1 - child->sizerequest.y0;
  170. w->sizerequest.x1 = childw;
  171. w->sizerequest.y1 = childh;
  172. }
  173. }
  174. void x3align_sizealloc(x3widget *w, x3rect *r)
  175. {
  176. x3widget_align *z = (x3widget_align *)w;
  177. x3alignment a = z->alignment;
  178. int xa = a & 3;
  179. int ya = (a >> 2) & 3;
  180. x3rect child_r = *r;
  181. printf("align sizealloc = (%g, %g) - (%g, %g)\n",
  182. r->x0, r->y0, r->x1, r->y1);
  183. if (w->n_children) {
  184. x3widget *child = w->children[0];
  185. if (xa < 3) {
  186. int childw = child->sizerequest.x1 - child->sizerequest.x0;
  187. int pad = r->x1 - r->x0 - childw;
  188. child_r.x0 += (pad * (1 + (xa >> 1) - (xa & 1)) + 1) >> 1;
  189. child_r.x1 = child_r.x0 + childw;
  190. }
  191. if (ya < 3) {
  192. int childh = child->sizerequest.y1 - child->sizerequest.y0;
  193. int pad = r->y1 - r->y0 - childh;
  194. child_r.y0 += (pad * (1 + (ya >> 1) - (ya & 1)) + 1) >> 1;
  195. child_r.y1 = child_r.y0 + childh;
  196. }
  197. child->type->sizealloc(child, &child_r);
  198. child->flags &= ~x3flag_needsizealloc;
  199. }
  200. }
  201. x3type x3aligntype = { x3align_sizereq,
  202. x3align_sizealloc,
  203. x3add_default };
  204. x3widget *x3align(x3widget *parent, x3alignment alignment)
  205. {
  206. x3widget *result = (x3widget *)malloc(sizeof(x3widget_align));
  207. x3widget_init(result, &x3aligntype);
  208. x3add(parent, result);
  209. x3qsizereq(result);
  210. ((x3widget_align *)result)->alignment = alignment;
  211. return result;
  212. }
  213. typedef struct {
  214. x3widget base;
  215. int t, b, l, r;
  216. } x3widget_pad;
  217. void x3pad_sizereq(x3widget *w)
  218. {
  219. x3widget_pad *z = (x3widget_pad *)w;
  220. w->sizerequest.x0 = 0;
  221. w->sizerequest.y0 = 0;
  222. w->sizerequest.x1 = 0;
  223. w->sizerequest.y1 = 0;
  224. if (w->n_children) {
  225. x3widget *child = w->children[0];
  226. int childw = child->sizerequest.x1 - child->sizerequest.x0;
  227. int childh = child->sizerequest.y1 - child->sizerequest.y0;
  228. w->sizerequest.x1 = childw + z->l + z->r;
  229. w->sizerequest.y1 = childh + z->t + z->b;
  230. }
  231. }
  232. void x3pad_sizealloc(x3widget *w, x3rect *r)
  233. {
  234. x3widget_pad *z = (x3widget_pad *)w;
  235. x3rect child_r = *r;
  236. printf("pad sizealloc = (%g, %g) - (%g, %g)\n",
  237. r->x0, r->y0, r->x1, r->y1);
  238. if (w->n_children) {
  239. x3widget *child = w->children[0];
  240. child_r.x0 += z->l;
  241. child_r.x1 -= z->r;
  242. child_r.y0 += z->t;
  243. child_r.y1 -= z->b;
  244. child->type->sizealloc(child, &child_r);
  245. child->flags &= ~x3flag_needsizealloc;
  246. }
  247. }
  248. x3type x3padtype = { x3pad_sizereq,
  249. x3pad_sizealloc,
  250. x3add_default };
  251. x3widget *x3pad(x3widget *parent, int t, int b, int l, int r)
  252. {
  253. x3widget *result = (x3widget *)malloc(sizeof(x3widget_pad));
  254. x3widget_init(result, &x3padtype);
  255. x3add(parent, result);
  256. x3qsizereq(result);
  257. ((x3widget_pad *)result)->t = t;
  258. ((x3widget_pad *)result)->b = b;
  259. ((x3widget_pad *)result)->l = l;
  260. ((x3widget_pad *)result)->r = r;
  261. return result;
  262. }
  263. #endif
  264. void x3initqs(void)
  265. {
  266. n_x3needshow = 0;
  267. x3needshow = (x3widget **)malloc(sizeof(x3widget *) *
  268. (n_x3needshow_max = 16));
  269. #if defined(X3_CARBON) || defined(X3_WIN32)
  270. n_x3needsizereqs = 0;
  271. x3needsizereqs = (x3widget **)malloc(sizeof(x3widget *) *
  272. (n_x3needsizereqs_max = 16));
  273. n_x3needsizeallocs = 0;
  274. x3needsizeallocs = (x3widget **)malloc(sizeof(x3widget *) *
  275. (n_x3needsizeallocs_max = 16));
  276. #endif
  277. }
  278. void x3qshow(x3widget *w)
  279. {
  280. if (n_x3needshow == n_x3needshow_max)
  281. x3needshow = (x3widget **)realloc(x3needshow,
  282. sizeof(x3widget *) *
  283. (n_x3needshow_max <<= 1));
  284. x3needshow[n_x3needshow++] = w;
  285. }
  286. void x3sync(void)
  287. {
  288. int i;
  289. #if defined(X3_CARBON) || defined(X3_WIN32)
  290. for (i = n_x3needsizereqs - 1; i >= 0; i--) {
  291. x3widget *w = x3needsizereqs[i];
  292. w->type->sizereq(w);
  293. w->flags &= ~x3flag_needsizereq;
  294. w->flags |= x3flag_needsizealloc;
  295. }
  296. for (i = 0; i < n_x3needsizereqs; i++) {
  297. x3widget *w = x3needsizereqs[i];
  298. if (w->flags & x3flag_needsizealloc) {
  299. w->type->sizealloc(w, NULL);
  300. w->flags &= ~x3flag_needsizealloc;
  301. }
  302. }
  303. n_x3needsizereqs = 0;
  304. #endif
  305. for (i = 0; i < n_x3needshow; i++)
  306. x3_window_show(x3needshow[i]);
  307. n_x3needshow = 0;
  308. }