201 grid->x++; |
219 grid->x++; |
202 ui_reset_layout(ctn->layout); |
220 ui_reset_layout(ctn->layout); |
203 } |
221 } |
204 |
222 |
205 |
223 |
|
224 /* -------------------------- TabView Container -------------------------- */ |
|
225 |
|
226 static void ui_tabbar_resize(Widget widget, XtPointer udata, XtPointer cdata) { |
|
227 UiMotifTabView *tabview = udata; |
|
228 |
|
229 if(tabview->tabview == UI_TABVIEW_INVISIBLE) { |
|
230 return; |
|
231 } |
|
232 |
|
233 int width = 0; |
|
234 int height = 0; |
|
235 XtVaGetValues(widget, XmNwidth, &width, XmNheight, &height, NULL); |
|
236 int numbuttons = cxListSize(tabview->tabs); |
|
237 if(numbuttons == 0) { |
|
238 return; |
|
239 } |
|
240 int button_width = width / numbuttons; |
|
241 int x = 0; |
|
242 |
|
243 CxIterator i = cxListIterator(tabview->tabs); |
|
244 cx_foreach(UiTab *, tab, i) { |
|
245 if(i.index + 1 == numbuttons) { |
|
246 button_width = width - x; |
|
247 } |
|
248 XtVaSetValues( |
|
249 tab->tab_button, |
|
250 XmNx, x, |
|
251 XmNy, 0, |
|
252 XmNwidth, |
|
253 button_width, |
|
254 |
|
255 NULL); |
|
256 x += button_width; |
|
257 } |
|
258 |
|
259 if(height <= tabview->height) { |
|
260 XtVaSetValues(widget, XmNheight, tabview->height + 4, NULL); |
|
261 } |
|
262 } |
|
263 |
|
264 static void ui_tabbar_expose(Widget widget, XtPointer udata, XtPointer cdata) { |
|
265 UiMotifTabView *tabview = udata; |
|
266 XmDrawingAreaCallbackStruct *cbs = (XmDrawingAreaCallbackStruct *)cdata; |
|
267 XEvent *event = cbs->event; |
|
268 Display *dpy = XtDisplay(widget); |
|
269 |
|
270 if(!tabview->gc_initialized) { |
|
271 XGCValues gcvals; |
|
272 gcvals.foreground = tabview->fg1; |
|
273 tabview->gc = XCreateGC(XtDisplay(tabview->tabbar), XtWindow(tabview->tabbar), (GCForeground), &gcvals); |
|
274 } |
|
275 |
|
276 if(tabview->current_tab) { |
|
277 Widget tab = tabview->current_tab->tab_button; |
|
278 XFillRectangle(dpy, XtWindow(widget), tabview->gc, tab->core.x, tab->core.height, tab->core.width, 4); |
|
279 } |
|
280 } |
|
281 |
|
282 UIWIDGET ui_tabview_create(UiObject *obj, UiTabViewArgs args) { |
|
283 Arg xargs[16]; |
|
284 int n = 0; |
|
285 |
|
286 UiContainerPrivate *ctn = ui_obj_container(obj); |
|
287 UI_APPLY_LAYOUT(ctn->layout, args); |
|
288 |
|
289 // create widgets |
|
290 // form |
|
291 // - tabbar (Drawing Area) |
|
292 // - content (Frame) |
|
293 UiMotifTabView *tabview = malloc(sizeof(UiMotifTabView)); |
|
294 memset(tabview, 0, sizeof(UiMotifTabView)); |
|
295 char *name = args.name ? (char*)args.name : "tabview"; |
|
296 XtSetArg(xargs[n], XmNuserData, tabview); n++; |
|
297 Widget parent = ctn->prepare(ctn, xargs, &n); |
|
298 Widget form = XmCreateForm(parent, name, xargs, n); |
|
299 XtManageChild(form); |
|
300 |
|
301 n = 0; |
|
302 XtSetArg(xargs[n], XmNleftAttachment, XmATTACH_FORM); n++; |
|
303 XtSetArg(xargs[n], XmNrightAttachment, XmATTACH_FORM); n++; |
|
304 XtSetArg(xargs[n], XmNtopAttachment, XmATTACH_FORM); n++; |
|
305 XtSetArg(xargs[n], XmNorientation, XmHORIZONTAL); n++; |
|
306 XtSetArg(xargs[n], XmNpacking, XmPACK_TIGHT); n++; |
|
307 XtSetArg(xargs[n], XmNspacing, 1); n++; |
|
308 XtSetArg(xargs[n], XmNmarginWidth, 0); n++; |
|
309 XtSetArg(xargs[n], XmNmarginHeight, 0); n++; |
|
310 Widget tabbar = XmCreateDrawingArea(form, "ui_test", xargs, n); |
|
311 XtManageChild(tabbar); |
|
312 XtAddCallback(tabbar, XmNresizeCallback , ui_tabbar_resize, tabview); |
|
313 XtAddCallback(tabbar, XmNexposeCallback, ui_tabbar_expose, tabview); |
|
314 |
|
315 n = 0; |
|
316 XtSetArg(xargs[n], XmNleftAttachment, XmATTACH_FORM); n++; |
|
317 XtSetArg(xargs[n], XmNrightAttachment, XmATTACH_FORM); n++; |
|
318 XtSetArg(xargs[n], XmNbottomAttachment, XmATTACH_FORM); n++; |
|
319 XtSetArg(xargs[n], XmNtopAttachment, XmATTACH_WIDGET); n++; |
|
320 XtSetArg(xargs[n], XmNtopWidget, tabbar); n++; |
|
321 Widget content = XmCreateFrame(form, "tabviewcontent", xargs, n); |
|
322 |
|
323 // setup tabview object, that holds all relevant objects |
|
324 tabview->obj = obj; |
|
325 tabview->form = form; |
|
326 tabview->tabbar = tabbar; |
|
327 tabview->content = content; |
|
328 tabview->tabview = args.tabview; |
|
329 tabview->subcontainer = args.subcontainer; |
|
330 tabview->select = ui_motif_tabview_select; |
|
331 tabview->add = ui_motif_tabview_add_tab; |
|
332 tabview->remove = ui_motif_tabview_remove; |
|
333 tabview->tabs = cxArrayListCreate(obj->ctx->allocator, cx_cmp_ptr, sizeof(UiTab), 8); |
|
334 tabview->current_index = -1; |
|
335 |
|
336 UiTabViewContainer *ct = ui_malloc(obj->ctx, sizeof(UiTabViewContainer)); |
|
337 ct->container.widget = form; |
|
338 ct->container.type = UI_CONTAINER_TABVIEW; |
|
339 ct->container.prepare = ui_tabview_container_prepare; |
|
340 ct->container.add = ui_tabview_container_add; |
|
341 ct->tabview = tabview; |
|
342 |
|
343 UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.value, args.varname, UI_VAR_INTEGER); |
|
344 if(var) { |
|
345 UiInteger *i = var->value; |
|
346 i->obj = tabview; |
|
347 i->get = ui_tabview_get; |
|
348 i->set = ui_tabview_set; |
|
349 } |
|
350 |
|
351 uic_object_push_container(obj, (UiContainerX*)ct); |
|
352 |
|
353 return form; |
|
354 } |
|
355 |
|
356 int64_t ui_tabview_get(UiInteger *i) { |
|
357 UiMotifTabView *tabview = i->obj; |
|
358 i->value = tabview->current_index; |
|
359 return i->value; |
|
360 } |
|
361 |
|
362 void ui_tabview_set(UiInteger *i, int64_t value) { |
|
363 UiMotifTabView *tabview = i->obj; |
|
364 if(value < cxListSize(tabview->tabs)) { |
|
365 ui_motif_tabview_select(tabview, value); |
|
366 i->value = value; |
|
367 } |
|
368 } |
|
369 |
|
370 void ui_tab_create(UiObject *obj, const char* title) { |
|
371 UiContainerPrivate *ctn = ui_obj_container(obj); |
|
372 if(ctn->type != UI_CONTAINER_TABVIEW) { |
|
373 fprintf(stderr, "UI Error: container is not a tabview\n"); |
|
374 return; |
|
375 } |
|
376 |
|
377 UiMotifTabView *tabview = NULL; |
|
378 XtVaGetValues(ctn->widget, XmNuserData, &tabview, NULL); |
|
379 if(!tabview) { |
|
380 fprintf(stderr, "UI Error: no tabview\n"); |
|
381 return; |
|
382 } |
|
383 |
|
384 |
|
385 Widget child = ui_vbox_create(obj, (UiContainerArgs) { 0 }); |
|
386 if(tabview->current) { |
|
387 XtUnmanageChild(child); |
|
388 } else { |
|
389 tabview->current = child; |
|
390 } |
|
391 |
|
392 tabview->add(tabview, -1, title, child); |
|
393 } |
|
394 |
|
395 void ui_tabview_select(UIWIDGET tabview, int tab) { |
|
396 UiMotifTabView *tabviewdata = NULL; |
|
397 XtVaGetValues(tabview, XmNuserData, &tabviewdata, NULL); |
|
398 if(tabviewdata) { |
|
399 ui_motif_tabview_select(tabviewdata, tab); |
|
400 } else { |
|
401 fprintf(stderr, "ui_tabview_select: widget is not a tabview\n"); |
|
402 } |
|
403 } |
|
404 |
|
405 void ui_tabview_remove(UIWIDGET tabview, int tab) { |
|
406 UiMotifTabView *tabviewdata = NULL; |
|
407 XtVaGetValues(tabview, XmNuserData, &tabviewdata, NULL); |
|
408 if(tabviewdata) { |
|
409 ui_motif_tabview_remove(tabviewdata, tab); |
|
410 } else { |
|
411 fprintf(stderr, "ui_tabview_select: widget is not a tabview\n"); |
|
412 } |
|
413 } |
|
414 |
|
415 UiObject* ui_tabview_add(UIWIDGET tabview, const char *name, int tab_index) { |
|
416 UiMotifTabView *tabviewdata = NULL; |
|
417 XtVaGetValues(tabview, XmNuserData, &tabviewdata, NULL); |
|
418 if(tabviewdata) { |
|
419 Arg args[16]; |
|
420 int n = 0; |
|
421 |
|
422 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++; |
|
423 XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++; |
|
424 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++; |
|
425 XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++; |
|
426 XtSetArg(args[n], XmNtopWidget, tabviewdata->tabbar); n++; |
|
427 |
|
428 Widget grid = XtCreateManagedWidget("vbox", gridClass, tabviewdata->content, args, n); |
|
429 |
|
430 UiObject *newobj = ui_calloc(tabviewdata->obj->ctx, 1, sizeof(UiObject)); |
|
431 newobj->ctx = tabviewdata->obj->ctx; |
|
432 newobj->widget = grid; |
|
433 UiContainerX *container = ui_box_container(newobj, grid, UI_BOX_VERTICAL); |
|
434 newobj->container_begin = container; |
|
435 newobj->container_end = container; |
|
436 return newobj; |
|
437 } else { |
|
438 fprintf(stderr, "ui_tabview_select: widget is not a tabview\n"); |
|
439 return NULL; |
|
440 } |
|
441 } |
|
442 |
|
443 void ui_motif_tabview_select(UiMotifTabView *tabview, int tab) { |
|
444 UiTab *t = cxListAt(tabview->tabs, tab); |
|
445 if(t) { |
|
446 tabview->current_index = tab; |
|
447 ui_motif_tabview_change_tab(tabview, t); |
|
448 } |
|
449 } |
|
450 |
|
451 static void ui_tab_button_callback(Widget widget, UiTab *tab, XtPointer d) { |
|
452 UiMotifTabView *tabview = NULL; |
|
453 XtVaGetValues(widget, XmNuserData, &tabview, NULL); |
|
454 ui_motif_tabview_change_tab(tabview, tab); |
|
455 } |
|
456 |
|
457 void ui_motif_tabview_add_tab(UiMotifTabView *tabview, int index, const char *name, Widget child) { |
|
458 UiTab tab; |
|
459 |
|
460 Arg args[16]; |
|
461 int n = 0; |
|
462 |
|
463 XmString label = XmStringCreateLocalized((char*)name); |
|
464 XtSetArg(args[n], XmNlabelString, label); n++; |
|
465 XtSetArg(args[n], XmNshadowThickness, 0); n++; |
|
466 XtSetArg(args[n], XmNhighlightThickness, 0); n++; |
|
467 XtSetArg(args[n], XmNuserData, tabview); n++; |
|
468 |
|
469 Widget button = XmCreatePushButton(tabview->tabbar, "tab_button", args, n); |
|
470 if(tabview->tabview != UI_TABVIEW_INVISIBLE) { |
|
471 XtManageChild(button); |
|
472 } |
|
473 |
|
474 if(tabview->height == 0) { |
|
475 Dimension h; |
|
476 XtVaGetValues( |
|
477 button, |
|
478 XmNarmColor, |
|
479 &tabview->bg1, |
|
480 XmNbackground, |
|
481 &tabview->bg2, |
|
482 XmNhighlightColor, |
|
483 &tabview->fg1, |
|
484 XmNheight, |
|
485 &h, |
|
486 NULL); |
|
487 tabview->height = h + 2; // border |
|
488 |
|
489 XtVaSetValues(tabview->tabbar, XmNbackground, tabview->bg1, NULL); |
|
490 } |
|
491 |
|
492 tab.tab_button = button; |
|
493 tab.child = child; |
|
494 size_t newtab_index = cxListSize(tabview->tabs); |
|
495 cxListAdd(tabview->tabs, &tab); |
|
496 UiTab *newtab = cxListAt(tabview->tabs, newtab_index); |
|
497 |
|
498 XtAddCallback( |
|
499 button, |
|
500 XmNactivateCallback, |
|
501 (XtCallbackProc)ui_tab_button_callback, |
|
502 newtab); |
|
503 |
|
504 if(newtab_index == 0) { |
|
505 ui_motif_tabview_change_tab(tabview, newtab); |
|
506 } else { |
|
507 XtVaSetValues(button, XmNbackground, tabview->bg1, NULL); |
|
508 } |
|
509 } |
|
510 |
|
511 void ui_motif_tabview_remove(UiMotifTabView *tabview, int index) { |
|
512 UiTab *tab = cxListAt(tabview->tabs, index); |
|
513 if(tab) { |
|
514 if(tab == tabview->current_tab) { |
|
515 if(index > 0) { |
|
516 ui_motif_tabview_select(tabview, index-1); |
|
517 } else { |
|
518 if(index < cxListSize(tabview->tabs)) { |
|
519 ui_motif_tabview_select(tabview, index+1); |
|
520 } else { |
|
521 tabview->current_tab = NULL; |
|
522 tabview->current_index = -1; |
|
523 } |
|
524 } |
|
525 } |
|
526 XtDestroyWidget(tab->tab_button); |
|
527 XtDestroyWidget(tab->child); |
|
528 cxListRemove(tabview->tabs, index); |
|
529 } |
|
530 } |
|
531 |
|
532 void ui_motif_tabview_change_tab(UiMotifTabView *tabview, UiTab *tab) { |
|
533 if(tabview->current_tab) { |
|
534 XtVaSetValues(tabview->current_tab->tab_button, XmNshadowThickness, 0, XmNbackground, tabview->bg1, NULL); |
|
535 XtUnmanageChild(tabview->current_tab->child); |
|
536 } |
|
537 XtVaSetValues(tab->tab_button, XmNshadowThickness, 1, XmNbackground, tabview->bg2, NULL); |
|
538 tabview->current_tab = tab; |
|
539 tabview->current_index = (int)cxListFind(tabview->tabs, tab);; |
|
540 XtManageChild(tab->child); |
|
541 } |
|
542 |
|
543 Widget ui_tabview_container_prepare(UiContainerPrivate *ctn, Arg *args, int *n) { |
|
544 UiTabViewContainer *ct = (UiTabViewContainer*)ctn; |
|
545 UiMotifTabView *tabview = ct->tabview; |
|
546 int a = *n; |
|
547 XtSetArg(args[a], XmNleftAttachment, XmATTACH_FORM); a++; |
|
548 XtSetArg(args[a], XmNrightAttachment, XmATTACH_FORM); a++; |
|
549 XtSetArg(args[a], XmNbottomAttachment, XmATTACH_FORM); a++; |
|
550 XtSetArg(args[a], XmNtopAttachment, XmATTACH_WIDGET); a++; |
|
551 XtSetArg(args[a], XmNtopWidget, tabview->tabbar); a++; |
|
552 *n = a; |
|
553 return tabview->form; |
|
554 } |
|
555 |
|
556 void ui_tabview_container_add(UiContainerPrivate *ctn, Widget widget) { |
|
557 ui_reset_layout(ctn->layout); |
|
558 } |
|
559 |
|
560 |
|
561 |
206 /* -------------------- Container Helper Functions -------------------- */ |
562 /* -------------------- Container Helper Functions -------------------- */ |
207 |
563 |
208 void ui_container_begin_close(UiObject *obj) { |
564 void ui_container_begin_close(UiObject *obj) { |
209 UiContainerPrivate *ct = ui_obj_container(obj); |
565 UiContainerPrivate *ct = ui_obj_container(obj); |
210 ct->container.close = 1; |
566 ct->container.close = 1; |