ui/motif/container.c

changeset 0
2483f517c562
child 29
3fc287f06305
equal deleted inserted replaced
-1:000000000000 0:2483f517c562
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2014 Olaf Wintermann. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <inttypes.h>
32
33 #include "container.h"
34 #include "../common/context.h"
35 #include "../common/object.h"
36
37 #include <cx/array_list.h>
38 #include <cx/linked_list.h>
39 #include <cx/compare.h>
40
41 #define UI_GRID_MAX_COLUMNS 512
42
43 static UiBool ui_lb2bool(UiLayoutBool b) {
44 return b == UI_LAYOUT_TRUE ? TRUE : FALSE;
45 }
46
47 static UiLayoutBool ui_bool2lb(UiBool b) {
48 return b ? UI_LAYOUT_TRUE : UI_LAYOUT_FALSE;
49 }
50
51
52 UiContainer* ui_frame_container(UiObject *obj, Widget frame) {
53 UiContainer *ct = cxCalloc(
54 obj->ctx->allocator,
55 1,
56 sizeof(UiContainer));
57 ct->widget = frame;
58 ct->prepare = ui_frame_container_prepare;
59 ct->add = ui_frame_container_add;
60 return ct;
61 }
62
63 Widget ui_frame_container_prepare(UiContainer *ct, Arg *args, int *n, UiBool fill) {
64 return ct->widget;
65 }
66
67 void ui_frame_container_add(UiContainer *ct, Widget widget) {
68 ui_reset_layout(ct->layout);
69 ct->current = widget;
70 }
71
72
73 UiContainer* ui_box_container(UiObject *obj, Widget box, int margin, int spacing, UiBoxOrientation orientation) {
74 UiBoxContainer *ct = cxCalloc(
75 obj->ctx->allocator,
76 1,
77 sizeof(UiBoxContainer));
78 ct->container.widget = box;
79 ct->container.prepare = ui_box_container_prepare;
80 ct->container.add = ui_box_container_add;
81 ct->orientation = orientation;
82 ct->margin = margin;
83 ct->spacing = spacing;
84 return (UiContainer*)ct;
85 }
86
87 Widget ui_box_container_prepare(UiContainer *ct, Arg *args, int *n, UiBool fill) {
88 UiBoxContainer *bc = (UiBoxContainer*)ct;
89 if(ct->layout.fill != UI_LAYOUT_UNDEFINED) {
90 fill = ui_lb2bool(ct->layout.fill);
91 }
92
93 if(bc->has_fill && fill) {
94 fprintf(stderr, "UiError: container has 2 filled widgets");
95 fill = FALSE;
96 }
97 if(fill) {
98 bc->has_fill = TRUE;
99 }
100
101 int a = *n;
102 // determine fixed and dynamic attachments
103 void *f1;
104 void *f2;
105 void *d1;
106 void *d2;
107 void *w1;
108 void *w2;
109 if(bc->orientation == UI_BOX_VERTICAL) {
110 f1 = XmNleftAttachment;
111 f2 = XmNrightAttachment;
112 d1 = XmNtopAttachment;
113 d2 = XmNbottomAttachment;
114 w1 = XmNtopWidget;
115 w2 = XmNbottomWidget;
116
117 // margin/spacing
118 XtSetArg(args[a], XmNleftOffset, bc->margin); a++;
119 XtSetArg(args[a], XmNrightOffset, bc->margin); a++;
120
121 XtSetArg(args[a], XmNtopOffset, bc->prev_widget ? bc->spacing : bc->margin); a++;
122 } else {
123 f1 = XmNtopAttachment;
124 f2 = XmNbottomAttachment;
125 d1 = XmNleftAttachment;
126 d2 = XmNrightAttachment;
127 w1 = XmNleftWidget;
128 w2 = XmNrightWidget;
129
130 // margin/spacing
131 XtSetArg(args[a], XmNtopOffset, bc->margin); a++;
132 XtSetArg(args[a], XmNbottomOffset, bc->margin); a++;
133
134 XtSetArg(args[a], XmNleftOffset, bc->prev_widget ? bc->spacing : bc->margin); a++;
135 }
136 XtSetArg(args[a], f1, XmATTACH_FORM); a++;
137 XtSetArg(args[a], f2, XmATTACH_FORM); a++;
138
139 if(fill) {
140 XtSetArg(args[a], d2, XmATTACH_FORM); a++;
141 }
142 if(bc->prev_widget) {
143 XtSetArg(args[a], d1, XmATTACH_WIDGET); a++;
144 XtSetArg(args[a], w1, bc->prev_widget); a++;
145 } else {
146 XtSetArg(args[a], d1, XmATTACH_FORM); a++;
147 }
148
149 *n = a;
150 return ct->widget;
151 }
152
153 void ui_box_container_add(UiContainer *ct, Widget widget) {
154 UiBoxContainer *bc = (UiBoxContainer*)ct;
155 // determine dynamic attachments
156 void *d1;
157 void *d2;
158 void *w1;
159 void *w2;
160 if(bc->orientation == UI_BOX_VERTICAL) {
161 d1 = XmNtopAttachment;
162 d2 = XmNbottomAttachment;
163 w1 = XmNtopWidget;
164 w2 = XmNbottomWidget;
165
166 } else {
167 d1 = XmNleftAttachment;
168 d2 = XmNrightAttachment;
169 w1 = XmNleftWidget;
170 w2 = XmNrightWidget;
171 }
172
173 if(bc->prev_widget) {
174 int v = 0;
175 XtVaGetValues(bc->prev_widget, d2, &v, NULL);
176 if(v == XmATTACH_FORM) {
177 XtVaSetValues(
178 bc->prev_widget,
179 d2,
180 XmATTACH_WIDGET,
181 w2,
182 widget,
183 NULL);
184 XtVaSetValues(
185 widget,
186 d1,
187 XmATTACH_NONE,
188 d2,
189 XmATTACH_FORM,
190 NULL);
191 }
192 }
193 bc->prev_widget = widget;
194
195 ui_reset_layout(ct->layout);
196 ct->current = widget;
197 }
198
199 UiContainer* ui_grid_container(UiObject *obj, Widget form, int columnspacing, int rowspacing) {
200 UiGridContainer *ct = cxCalloc(
201 obj->ctx->allocator,
202 1,
203 sizeof(UiGridContainer));
204 ct->container.widget = form;
205 ct->container.prepare = ui_grid_container_prepare;
206 ct->container.add = ui_grid_container_add;
207 ct->columnspacing = columnspacing;
208 ct->rowspacing = rowspacing;
209 ct->lines = cxLinkedListCreateSimple(CX_STORE_POINTERS);
210 return (UiContainer*)ct;
211 }
212
213 void ui_grid_newline(UiGridContainer *grid) {
214 if(grid->current) {
215 grid->current = NULL;
216 }
217 grid->container.layout.newline = FALSE;
218 }
219
220 Widget ui_grid_container_prepare(UiContainer *ct, Arg *args, int *n, UiBool fill) {
221 UiGridContainer *grid = (UiGridContainer*)ct;
222 if(ct->layout.newline) {
223 ui_grid_newline(grid);
224 }
225 return ct->widget;
226 }
227
228 void ui_grid_container_add(UiContainer *ct, Widget widget) {
229 UiGridContainer *grid = (UiGridContainer*)ct;
230
231 if(grid->current) {
232 cxListAdd(grid->current, widget);
233 } else {
234 grid->current = cxLinkedListCreateSimple(CX_STORE_POINTERS);
235 cxListAdd(grid->current, widget);
236 cxListAdd(grid->lines, grid->current);
237 }
238
239 ui_reset_layout(ct->layout);
240 ct->current = widget;
241 }
242
243 static void ui_grid_resize(Widget widget, XtPointer udata, XtPointer cdata) {
244 UiGridContainer *grid = udata;
245
246 CxList *rowdim = cxArrayListCreateSimple(sizeof(int), grid->lines->size);
247 int coldim[UI_GRID_MAX_COLUMNS];
248 memset(coldim, 0, UI_GRID_MAX_COLUMNS*sizeof(int));
249 int numcol = 0;
250
251 // get the minimum size of the columns and rows
252 int sumw = 0;
253 int sumh = 0;
254 CxIterator lineIterator = cxListIterator(grid->lines);
255 cx_foreach(CxList *, row, lineIterator) {
256 int rheight = 0;
257 int i=0;
258 int sum_width = 0;
259 CxIterator colIterator = cxListIterator(row);
260 cx_foreach(Widget, w, colIterator) {
261 int widget_width = 0;
262 int widget_height = 0;
263 XtVaGetValues(
264 w,
265 XmNwidth,
266 &widget_width,
267 XmNheight,
268 &widget_height,
269 NULL);
270
271 // get the maximum height in this row
272 if(widget_height > rheight) {
273 rheight = widget_height;
274 }
275
276 // get the maximum width in this column
277 if(widget_width > coldim[i]) {
278 coldim[i] = widget_width;
279 }
280 sum_width += widget_width;
281 if(sum_width > sumw) {
282 sumw = sum_width;
283 }
284
285 i++;
286 if(i > numcol) {
287 numcol = i;
288 }
289 }
290 cxListAdd(rowdim, &rheight);
291 sumh += rheight;
292 }
293
294 // check container size
295 int gwidth = 0;
296 int gheight = 0;
297 XtVaGetValues(widget, XmNwidth, &gwidth, XmNheight, &gheight, NULL);
298 if(gwidth < sumw || gheight < sumh) {
299 XtVaSetValues(widget, XmNwidth, sumw, XmNheight, sumh, NULL);
300 cxListDestroy(rowdim);
301 return;
302 }
303
304
305 // adjust the positions of all children
306 int y = 0;
307 lineIterator = cxListIterator(grid->lines);
308 cx_foreach(CxList *, row, lineIterator) {
309 int x = 0;
310 int i=0;
311 int *rowheight = cxListAt(rowdim, lineIterator.index);
312 CxIterator colIterator = cxListIterator(row);
313 cx_foreach(Widget, w, colIterator) {
314 XtVaSetValues(
315 w,
316 XmNx, x,
317 XmNy, y,
318 XmNwidth, coldim[i],
319 XmNheight, *rowheight,
320 NULL);
321
322 x += coldim[i];
323 i++;
324 }
325 y += *rowheight;
326 }
327
328 cxListDestroy(rowdim);
329 }
330
331 UiContainer* ui_scrolledwindow_container(UiObject *obj, Widget scrolledwindow) {
332 UiContainer *ct = cxCalloc(
333 obj->ctx->allocator,
334 1,
335 sizeof(UiContainer));
336 ct->widget = scrolledwindow;
337 ct->prepare = ui_scrolledwindow_container_prepare;
338 ct->add = ui_scrolledwindow_container_add;
339 return ct;
340 }
341
342 Widget ui_scrolledwindow_container_prepare(UiContainer *ct, Arg *args, int *n, UiBool fill) {
343 return ct->widget;
344 }
345
346 void ui_scrolledwindow_container_add(UiContainer *ct, Widget widget) {
347 ui_reset_layout(ct->layout);
348 ct->current = widget;
349 }
350
351
352 UiContainer* ui_tabview_container(UiObject *obj, Widget frame) {
353 UiTabViewContainer *ct = cxCalloc(
354 obj->ctx->allocator,
355 1,
356 sizeof(UiTabViewContainer));
357 ct->context = obj->ctx;
358 ct->container.widget = frame;
359 ct->container.prepare = ui_tabview_container_prepare;
360 ct->container.add = ui_tabview_container_add;
361 ct->tabs = cxArrayListCreate(cxDefaultAllocator, cx_cmp_uintptr, CX_STORE_POINTERS, 16);
362 return (UiContainer*)ct;
363 }
364
365 Widget ui_tabview_container_prepare(UiContainer *ct, Arg *args, int *n, UiBool fill) {
366 int a = *n;
367 XtSetArg(args[a], XmNleftAttachment, XmATTACH_FORM); a++;
368 XtSetArg(args[a], XmNrightAttachment, XmATTACH_FORM); a++;
369 XtSetArg(args[a], XmNtopAttachment, XmATTACH_FORM); a++;
370 XtSetArg(args[a], XmNbottomAttachment, XmATTACH_FORM); a++;
371 *n = a;
372 return ct->widget;
373 }
374
375 void ui_tabview_container_add(UiContainer *ct, Widget widget) {
376 UiTabViewContainer *tabview = (UiTabViewContainer*)ct;
377
378 if(tabview->current) {
379 XtUnmanageChild(tabview->current);
380 }
381
382 tabview->current = widget;
383 cxListAdd(tabview->tabs, widget);
384
385 ui_select_tab(ct->widget, 0);
386 ui_reset_layout(ct->layout);
387 ct->current = widget;
388 }
389
390 UIWIDGET ui_box(UiObject *obj, int margin, int spacing, UiBoxOrientation orientation) {
391 UiContainer *ct = uic_get_current_container(obj);
392
393 Arg args[16];
394 int n = 0;
395 Widget parent = ct->prepare(ct, args, &n, TRUE);
396 Widget form = XmCreateForm(parent, "vbox", args, n);
397 ct->add(ct, form);
398 XtManageChild(form);
399
400 UiObject *newobj = uic_object_new(obj, form);
401 newobj->container = ui_box_container(obj, form, margin, spacing, orientation);
402 uic_obj_add(obj, newobj);
403
404 return form;
405 }
406
407 UIWIDGET ui_vbox(UiObject *obj) {
408 return ui_box(obj, 0, 0, UI_BOX_VERTICAL);
409 }
410
411 UIWIDGET ui_hbox(UiObject *obj) {
412 return ui_box(obj, 0, 0, UI_BOX_HORIZONTAL);
413 }
414
415 UIWIDGET ui_vbox_sp(UiObject *obj, int margin, int spacing) {
416 return ui_box(obj, margin, spacing, UI_BOX_VERTICAL);
417 }
418
419 UIWIDGET ui_hbox_sp(UiObject *obj, int margin, int spacing) {
420 return ui_box(obj, margin, spacing, UI_BOX_HORIZONTAL);
421 }
422
423 UIWIDGET ui_grid(UiObject *obj) {
424 return ui_grid_sp(obj, 0, 0, 0);
425 }
426
427 UIWIDGET ui_grid_sp(UiObject *obj, int margin, int columnspacing, int rowspacing) {
428 UiContainer *ct = uic_get_current_container(obj);
429
430 Arg args[16];
431 int n = 0;
432 Widget parent = ct->prepare(ct, args, &n, TRUE);
433 Widget grid = XmCreateDrawingArea(parent, "grid", args, n);
434 ct->add(ct, grid);
435 XtManageChild(grid);
436
437 UiObject *newobj = uic_object_new(obj, grid);
438 newobj->container = ui_grid_container(obj, grid, columnspacing, rowspacing);
439 uic_obj_add(obj, newobj);
440
441 XtAddCallback (grid, XmNresizeCallback , ui_grid_resize, newobj->container);
442
443 return grid;
444 }
445
446 UIWIDGET ui_scrolledwindow(UiObject *obj) {
447 UiContainer *ct = uic_get_current_container(obj);
448
449 Arg args[16];
450 int n = 0;
451 XtSetArg(args[n], XmNscrollingPolicy, XmAUTOMATIC); // TODO: dosn't work, use XmAPPLICATION_DEFINED
452 n++;
453 Widget parent = ct->prepare(ct, args, &n, TRUE);
454 Widget scrolledwindow = XmCreateScrolledWindow(parent, "scrolledwindow", args, n);
455 ct->add(ct, scrolledwindow);
456 XtManageChild(scrolledwindow);
457
458 UiObject *newobj = uic_object_new(obj, scrolledwindow);
459 newobj->container = ui_scrolledwindow_container(obj, scrolledwindow);
460 uic_obj_add(obj, newobj);
461
462 return scrolledwindow;
463 }
464
465 UIWIDGET ui_sidebar(UiObject *obj) {
466 UiContainer *ct = uic_get_current_container(obj);
467
468 Arg args[16];
469 int n = 0;
470
471 XtSetArg(args[n], XmNorientation, XmHORIZONTAL);
472 n++;
473
474 Widget parent = ct->prepare(ct, args, &n, TRUE);
475 Widget pane = XmCreatePanedWindow(parent, "pane", args, n);
476 ct->add(ct, pane);
477 XtManageChild(pane);
478
479 // add sidebar widget
480 Widget sidebar = XmCreateForm(pane, "sidebar", args, 0);
481 XtManageChild(sidebar);
482
483 UiObject *left = uic_object_new(obj, sidebar);
484 left->container = ui_box_container(left, sidebar, 0, 0, UI_BOX_VERTICAL);
485
486 // add content widget
487 XtSetArg (args[0], XmNpaneMaximum, 8000);
488 Widget content = XmCreateForm(pane, "content_area", args, 1);
489 XtManageChild(content);
490
491 UiObject *right = uic_object_new(obj, content);
492 right->container = ui_box_container(right, content, 0, 0, UI_BOX_VERTICAL);
493
494 uic_obj_add(obj, right);
495 uic_obj_add(obj, left);
496
497 return sidebar;
498 }
499
500 UIWIDGET ui_tabview(UiObject *obj) {
501 UiContainer *ct = uic_get_current_container(obj);
502
503 // create a simple frame as container widget
504 // when tabs are selected, the current child will be replaced by the
505 // the new tab widget
506 Arg args[16];
507 int n = 0;
508 XtSetArg(args[n], XmNshadowType, XmSHADOW_ETCHED_OUT);
509 n++;
510 XtSetArg(args[n], XmNshadowThickness, 0);
511 n++;
512 Widget parent = ct->prepare(ct, args, &n, TRUE);
513 Widget form = XmCreateForm(parent, "tabview", args, n);
514 ct->add(ct, form);
515 XtManageChild(form);
516
517 UiObject *tabviewobj = uic_object_new(obj, form);
518 tabviewobj->container = ui_tabview_container(obj, form);
519 uic_obj_add(obj, tabviewobj);
520
521 XtVaSetValues(form, XmNuserData, tabviewobj->container, NULL);
522
523 return form;
524 }
525
526 void ui_tab(UiObject *obj, char *title) {
527 UiContainer *ct = uic_get_current_container(obj);
528 ct->layout.label = title;
529
530 ui_vbox(obj);
531 }
532
533 void ui_select_tab(UIWIDGET tabview, int tab) {
534 UiTabViewContainer *ct = NULL;
535 XtVaGetValues(tabview, XmNuserData, &ct, NULL);
536 if(ct) {
537 XtUnmanageChild(ct->current);
538 Widget w = cxListAt(ct->tabs, tab);
539 if(w) {
540 XtManageChild(w);
541 ct->current = w;
542 } else {
543 fprintf(stderr, "UiError: front tab index: %d\n", tab);
544 }
545 } else {
546 fprintf(stderr, "UiError: widget is not a tabview\n");
547 }
548 }
549
550
551 /* document tabview */
552
553 static void ui_tabbar_resize(Widget widget, XtPointer udata, XtPointer cdata) {
554 MotifTabbedPane *v = (MotifTabbedPane*)udata;
555
556 int width = 0;
557 int height = 0;
558 XtVaGetValues(widget, XmNwidth, &width, XmNheight, &height, NULL);
559 int button_width = width / 4;
560 int x = 0;
561 CxIterator tabIterator = cxListIterator(v->tabs);
562 cx_foreach(UiTab*, tab, tabIterator) {
563 XtVaSetValues(
564 tab->tab_button,
565 XmNx, x,
566 XmNy, 0,
567 XmNwidth,
568 button_width,
569
570 NULL);
571 x += button_width;
572 }
573
574 if(height <= v->height) {
575 XtVaSetValues(widget, XmNheight, v->height + 4, NULL);
576 }
577 }
578
579 static void ui_tabbar_expose(Widget widget, XtPointer udata, XtPointer cdata) {
580 MotifTabbedPane *v = (MotifTabbedPane*)udata;
581 XmDrawingAreaCallbackStruct *cbs = (XmDrawingAreaCallbackStruct *)cdata;
582 XEvent *event = cbs->event;
583 Display *dpy = XtDisplay(widget);
584
585 XGCValues gcvals;
586 GC gc;
587 Pixel fgpix;
588
589 int tab_x;
590 int tab_width;
591 XtVaGetValues(v->current->tab_button, XmNx, &tab_x, XmNwidth, &tab_width, XmNhighlightColor, &fgpix, NULL);
592
593 gcvals.foreground = v->bg1;
594 gc = XCreateGC( dpy, XtWindow(widget), (GCForeground), &gcvals);
595
596 int width = 0;
597 int height = 0;
598 XtVaGetValues(widget, XmNwidth, &width, XmNheight, &height, NULL);
599 XFillRectangle(dpy, XtWindow(widget), gc, 0, 0, width, height);
600
601 gcvals.foreground = fgpix;
602 gc = XCreateGC( dpy, XtWindow(widget), (GCForeground), &gcvals);
603
604 XFillRectangle(dpy, XtWindow(widget), gc, tab_x, 0, tab_width, height);
605
606 }
607
608 UiTabbedPane* ui_tabbed_document_view(UiObject *obj) {
609 int n = 0;
610 Arg args[16];
611
612 UiContainer *ct = uic_get_current_container(obj);
613 Widget parent = ct->prepare(ct, args, &n, TRUE);
614
615 Widget tabview = XmCreateForm(parent, "tabview_form", args, n);
616 XtManageChild(tabview);
617
618 XtSetArg(args[0], XmNorientation, XmHORIZONTAL);
619 XtSetArg(args[1], XmNpacking, XmPACK_TIGHT);
620 XtSetArg(args[2], XmNspacing, 1);
621 XtSetArg(args[3], XmNleftAttachment, XmATTACH_FORM);
622 XtSetArg(args[4], XmNrightAttachment, XmATTACH_FORM);
623 XtSetArg(args[5], XmNtopAttachment, XmATTACH_FORM);
624 XtSetArg(args[6], XmNmarginWidth, 0);
625 XtSetArg(args[7], XmNmarginHeight, 0);
626 Widget tabbar = XmCreateDrawingArea(tabview, "tabbar", args, 8);
627 XtManageChild(tabbar);
628
629 XtSetArg(args[0], XmNleftAttachment, XmATTACH_FORM);
630 XtSetArg(args[1], XmNrightAttachment, XmATTACH_FORM);
631 XtSetArg(args[2], XmNtopAttachment, XmATTACH_WIDGET);
632 XtSetArg(args[3], XmNtopWidget, tabbar);
633 XtSetArg(args[4], XmNbottomAttachment, XmATTACH_FORM);
634 XtSetArg(args[5], XmNshadowThickness, 0);
635 Widget tabct = XmCreateForm(tabview, "tabview", args, 6);
636 XtManageChild(tabct);
637
638 MotifTabbedPane *tabbedpane = ui_malloc(obj->ctx, sizeof(MotifTabbedPane));
639 tabbedpane->view.ctx = uic_current_obj(obj)->ctx;
640 tabbedpane->view.widget = tabct;
641 tabbedpane->view.document = NULL;
642 tabbedpane->tabbar = tabbar;
643 tabbedpane->tabs = cxArrayListCreate(obj->ctx->allocator, cx_cmp_uintptr, CX_STORE_POINTERS, 16);
644 tabbedpane->current = NULL;
645 tabbedpane->height = 0;
646
647 XtAddCallback(tabbar, XmNresizeCallback , ui_tabbar_resize, tabbedpane);
648 XtAddCallback(tabbar, XmNexposeCallback, ui_tabbar_expose, tabbedpane);
649
650 return &tabbedpane->view;
651 }
652
653 UiObject* ui_document_tab(UiTabbedPane *view) {
654 MotifTabbedPane *v = (MotifTabbedPane*)view;
655 int n = 0;
656 Arg args[16];
657
658 // hide the current tab content
659 if(v->current) {
660 XtUnmanageChild(v->current->content->widget);
661 }
662
663 UiTab *tab = ui_malloc(view->ctx, sizeof(UiTab));
664
665 // create the new tab content
666 XtSetArg(args[0], XmNshadowThickness, 0);
667 XtSetArg(args[1], XmNleftAttachment, XmATTACH_FORM);
668 XtSetArg(args[2], XmNrightAttachment, XmATTACH_FORM);
669 XtSetArg(args[3], XmNtopAttachment, XmATTACH_FORM);
670 XtSetArg(args[4], XmNbottomAttachment, XmATTACH_FORM);
671 XtSetArg(args[5], XmNuserData, tab);
672 Widget frame = XmCreateFrame(view->widget, "tab", args, 6);
673 XtManageChild(frame);
674
675 UiObject *content = ui_malloc(view->ctx, sizeof(UiObject));
676 content->widget = NULL; // initialization for uic_context()
677 content->ctx = uic_context(content, view->ctx->allocator);
678 content->ctx->parent = view->ctx;
679 content->ctx->attach_document = uic_context_attach_document;
680 content->ctx->detach_document2 = uic_context_detach_document2;
681 content->widget = frame;
682 content->window = view->ctx->obj->window;
683 content->container = ui_frame_container(content, frame);
684 content->next = NULL;
685
686 // add tab button
687 cxListAdd(v->tabs, tab);
688
689 XmString label = XmStringCreateLocalized("tab");
690 XtSetArg(args[0], XmNlabelString, label);
691 XtSetArg(args[1], XmNshadowThickness, 0);
692 XtSetArg(args[2], XmNhighlightThickness, 0);
693
694 Widget button = XmCreatePushButton(v->tabbar, "tab_button", args, 3);
695 tab->tabbedpane = v;
696 tab->content = content;
697 tab->tab_button = button;
698 XtManageChild(button);
699 XtAddCallback(
700 button,
701 XmNactivateCallback,
702 (XtCallbackProc)ui_tab_button_callback,
703 tab);
704
705 if(v->height == 0) {
706 XtVaGetValues(
707 button,
708 XmNarmColor,
709 &v->bg1,
710 XmNbackground,
711 &v->bg2,
712 XmNheight,
713 &v->height,
714 NULL);
715 v->height += 2; // border
716 }
717
718 ui_change_tab(v, tab);
719 ui_tabbar_resize(v->tabbar, v, NULL);
720
721 return content;
722 }
723
724 void ui_tab_button_callback(Widget widget, UiTab *tab, XtPointer d) {
725 MotifTabbedPane *t = tab->tabbedpane;
726 if(t->current) {
727 XtUnmanageChild(t->current->content->widget);
728 XtVaSetValues(t->current->tab_button, XmNset, 0, NULL);
729 }
730 XtManageChild(tab->content->widget);
731
732 ui_change_tab(t, tab);
733
734 }
735
736 void ui_change_tab(MotifTabbedPane *pane, UiTab *tab) {
737 UiContext *ctx = tab->content->ctx;
738 ctx->parent->detach_document2(ctx->parent, pane->current->content->ctx->document);
739 ctx->parent->attach_document(ctx->parent, ctx->document);
740
741 if(pane->current) {
742 XtVaSetValues(pane->current->tab_button, XmNshadowThickness, 0, XmNbackground, pane->bg1, NULL);
743 }
744 XtVaSetValues(tab->tab_button, XmNshadowThickness, 1, XmNbackground, pane->bg2, NULL);
745
746 pane->current = tab;
747 pane->index = cxListFind(pane->tabs, tab);
748 printf("index: %d\n", pane->index);
749
750 // redraw tabbar
751 Display *dpy = XtDisplay(pane->tabbar);
752 Window window = XtWindow(pane->tabbar);
753 if(dpy && window) {
754 XClearArea(dpy, XtWindow(pane->tabbar), 0, 0, 0, 0, TRUE);
755 XFlush(dpy);
756 }
757 }
758
759 void ui_tab_set_document(UiContext *ctx, void *document) {
760 if(ctx->parent->document) {
761 //ctx->parent->detach_document(ctx->parent, ctx->parent->document);
762 }
763 uic_context_attach_document(ctx, document);
764 //uic_context_set_document(ctx->parent, document);
765 //ctx->parent->document = document;
766
767 UiTab *tab = NULL;
768 XtVaGetValues(
769 ctx->obj->widget,
770 XmNuserData,
771 &tab,
772 NULL);
773 if(tab) {
774 if(tab->tabbedpane->current == tab) {
775 ctx->parent->attach_document(ctx->parent, ctx->document);
776 }
777 } else {
778 fprintf(stderr, "UiError: ui_bar_set_document: Cannot set document");
779 }
780 }
781
782
783
784 /*
785 * -------------------- Layout Functions --------------------
786 *
787 * functions for setting layout attributes for the current container
788 *
789 */
790
791 void ui_layout_fill(UiObject *obj, UiBool fill) {
792 UiContainer *ct = uic_get_current_container(obj);
793 ct->layout.fill = ui_bool2lb(fill);
794 }
795
796 void ui_layout_hexpand(UiObject *obj, UiBool expand) {
797 UiContainer *ct = uic_get_current_container(obj);
798 ct->layout.hexpand = expand;
799 }
800
801 void ui_layout_vexpand(UiObject *obj, UiBool expand) {
802 UiContainer *ct = uic_get_current_container(obj);
803 ct->layout.vexpand = expand;
804 }
805
806 void ui_layout_gridwidth(UiObject *obj, int width) {
807 UiContainer *ct = uic_get_current_container(obj);
808 ct->layout.gridwidth = width;
809 }
810
811 void ui_newline(UiObject *obj) {
812 UiContainer *ct = uic_get_current_container(obj);
813 ct->layout.newline = TRUE;
814 }

mercurial