ui/motif/text.c

branch
newapi
changeset 415
e35cdf33998c
parent 414
ef60d527c066
child 416
89ad8467c39f
equal deleted inserted replaced
414:ef60d527c066 415:e35cdf33998c
113 #define XNETextGetString(widget) XmTextFieldGetString(widget) 113 #define XNETextGetString(widget) XmTextFieldGetString(widget)
114 #define XNETextGetLastPosition(widget) XmTextFieldGetLastPosition(widget) 114 #define XNETextGetLastPosition(widget) XmTextFieldGetLastPosition(widget)
115 #define XNETextSetInsertionPosition(widget, i) XmTextFieldSetInsertionPosition(widget, i) 115 #define XNETextSetInsertionPosition(widget, i) XmTextFieldSetInsertionPosition(widget, i)
116 #define XNETextSetSelection(w, f, l, t) XmTextFieldSetSelection(w, f, l, t) 116 #define XNETextSetSelection(w, f, l, t) XmTextFieldSetSelection(w, f, l, t)
117 117
118 typedef void(*updatedir_callback)(void*,char*); 118 typedef void(*updatedir_callback)(void*,char*,int);
119 119
120 typedef struct PathBar { 120 typedef struct PathBar {
121 Widget widget; 121 Widget widget;
122 Widget textfield; 122 Widget textfield;
123 123
128 Dimension lw; 128 Dimension lw;
129 Dimension rw; 129 Dimension rw;
130 130
131 int shift; 131 int shift;
132 132
133 UiPathElm *current_pathelms;
133 Widget *pathSegments; 134 Widget *pathSegments;
134 size_t numSegments; 135 size_t numSegments;
135 size_t segmentAlloc; 136 size_t segmentAlloc;
136 137
137 char *path; 138 char *path;
140 141
141 int focus; 142 int focus;
142 143
143 updatedir_callback updateDir; 144 updatedir_callback updateDir;
144 void *updateDirData; 145 void *updateDirData;
146
147 ui_pathelm_func getpathelm;
148 void *getpathelmdata;
145 } PathBar; 149 } PathBar;
146 150
147 void PathBarSetPath(PathBar *bar, const char *path); 151 void PathBarSetPath(PathBar *bar, const char *path);
148 152
149 void pathbar_resize(Widget w, PathBar *p, XtPointer d) 153 void pathbar_resize(Widget w, PathBar *p, XtPointer d)
331 } 335 }
332 336
333 /* update path */ 337 /* update path */
334 PathBarSetPath(p, newpath); 338 PathBarSetPath(p, newpath);
335 if(p->updateDir) { 339 if(p->updateDir) {
336 p->updateDir(p->updateDirData, newpath); 340 p->updateDir(p->updateDirData, newpath, -1);
337 } 341 }
338 XtFree(newpath); 342 XtFree(newpath);
339 343
340 /* hide textfield and show path as buttons */ 344 /* hide textfield and show path as buttons */
341 XtUnmanageChild(p->textfield); 345 XtUnmanageChild(p->textfield);
381 bar->path = NULL; 385 bar->path = NULL;
382 bar->updateDir = NULL; 386 bar->updateDir = NULL;
383 bar->updateDirData = NULL; 387 bar->updateDirData = NULL;
384 388
385 bar->focus_widget = NULL; 389 bar->focus_widget = NULL;
390
391 bar->getpathelm = NULL;
392 bar->getpathelmdata = NULL;
386 393
387 bar->shift = 0; 394 bar->shift = 0;
388 395
389 XtSetArg(args[n], XmNmarginWidth, 0); n++; 396 XtSetArg(args[n], XmNmarginWidth, 0); n++;
390 XtSetArg(args[n], XmNmarginHeight, 0); n++; 397 XtSetArg(args[n], XmNmarginHeight, 0); n++;
451 458
452 void PathBarChangeDir(Widget w, PathBar *bar, XtPointer c) 459 void PathBarChangeDir(Widget w, PathBar *bar, XtPointer c)
453 { 460 {
454 XmToggleButtonSetState(bar->pathSegments[bar->selection], False, False); 461 XmToggleButtonSetState(bar->pathSegments[bar->selection], False, False);
455 462
456 for(int i=0;i<bar->numSegments;i++) { 463 int i;
464 for(i=0;i<bar->numSegments;i++) {
457 if(bar->pathSegments[i] == w) { 465 if(bar->pathSegments[i] == w) {
458 bar->selection = i; 466 bar->selection = i;
459 XmToggleButtonSetState(w, True, False); 467 XmToggleButtonSetState(w, True, False);
460 break; 468 break;
461 } 469 }
462 } 470 }
463 471
464 int plen = strlen(bar->path); 472 UiPathElm elm = bar->current_pathelms[i];
465 int countSeg = 0; 473 cxmutstr name = cx_strdup(cx_strn(elm.name, elm.name_len));
466 for(int i=0;i<=plen;i++) { 474 if(bar->updateDir) {
467 char c = bar->path[i]; 475 bar->updateDir(bar->updateDirData, name.ptr, i);
468 if(c == '/' || c == '\0') { 476 }
469 if(countSeg == bar->selection) { 477 free(name.ptr);
470 char *dir = XtMalloc(i+2); 478 }
471 memcpy(dir, bar->path, i+1); 479
472 dir[i+1] = '\0'; 480 static void ui_pathelm_destroy(UiPathElm *elms, size_t nelm) {
473 if(bar->updateDir) { 481 for(int i=0;i<nelm;i++) {
474 bar->updateDir(bar->updateDirData, dir); 482 free(elms[i].name);
475 } 483 free(elms[i].path);
476 free(dir); 484 }
477 } 485 free(elms);
478 countSeg++;
479 }
480 }
481 } 486 }
482 487
483 void PathBarSetPath(PathBar *bar, const char *path) 488 void PathBarSetPath(PathBar *bar, const char *path)
484 { 489 {
485 if(bar->path) { 490 if(bar->path) {
498 Arg args[4]; 503 Arg args[4];
499 XmString str; 504 XmString str;
500 505
501 bar->numSegments = 0; 506 bar->numSegments = 0;
502 507
503 int i=0; 508 ui_pathelm_destroy(bar->current_pathelms, bar->numSegments);
504 if(path[0] == '/') { 509 size_t nelm = 0;
505 str = XmStringCreateLocalized("/"); 510 UiPathElm* path_elm = bar->getpathelm(bar->path, strlen(bar->path), &nelm, bar->getpathelmdata);
511 if (!path_elm) {
512 return;
513 }
514 bar->current_pathelms = path_elm;
515 bar->numSegments = nelm;
516 bar->pathSegments = realloc(bar->pathSegments, nelm * sizeof(Widget*));
517
518 for(int i=0;i<nelm;i++) {
519 UiPathElm elm = path_elm[i];
520
521 cxmutstr name = cx_strdup(cx_strn(elm.name, elm.name_len));
522 str = XmStringCreateLocalized(elm.name);
523 free(name.ptr);
524
506 XtSetArg(args[0], XmNlabelString, str); 525 XtSetArg(args[0], XmNlabelString, str);
507 XtSetArg(args[1], XmNfillOnSelect, True); 526 XtSetArg(args[1], XmNfillOnSelect, True);
508 XtSetArg(args[2], XmNindicatorOn, False); 527 XtSetArg(args[2], XmNindicatorOn, False);
509 bar->pathSegments[0] = XmCreateToggleButton( 528 Widget button = XmCreateToggleButton(bar->widget, "pbbutton", args, 3);
510 bar->widget, "pbbutton", args, 3);
511 XtAddCallback( 529 XtAddCallback(
512 bar->pathSegments[0], 530 button,
513 XmNvalueChangedCallback, 531 XmNvalueChangedCallback,
514 (XtCallbackProc)PathBarChangeDir, 532 (XtCallbackProc)PathBarChangeDir,
515 bar); 533 bar);
516 XmStringFree(str); 534 XmStringFree(str);
517 bar->numSegments++; 535
518 i++; 536 bar->pathSegments[i] = button;
519 }
520
521 int len = strlen(path);
522 int begin = i;
523 for(;i<=len;i++) {
524 char c = path[i];
525 if((c == '/' || c == '\0') && i > begin) {
526 char *segStr = XtMalloc(i - begin + 1);
527 memcpy(segStr, path+begin, i-begin);
528 segStr[i-begin] = '\0';
529 begin = i+1;
530
531 str = XmStringCreateLocalized(segStr);
532 XtFree(segStr);
533 XtSetArg(args[0], XmNlabelString, str);
534 XtSetArg(args[1], XmNfillOnSelect, True);
535 XtSetArg(args[2], XmNindicatorOn, False);
536 Widget button = XmCreateToggleButton(bar->widget, "pbbutton", args, 3);
537 XtAddCallback(
538 button,
539 XmNvalueChangedCallback,
540 (XtCallbackProc)PathBarChangeDir,
541 bar);
542 XmStringFree(str);
543
544 if(bar->numSegments >= bar->segmentAlloc) {
545 bar->segmentAlloc += 8;
546 bar->pathSegments = realloc(bar->pathSegments, bar->segmentAlloc * sizeof(Widget));
547 }
548
549 bar->pathSegments[bar->numSegments++] = button;
550 }
551 } 537 }
552 538
553 bar->selection = bar->numSegments-1; 539 bar->selection = bar->numSegments-1;
554 XmToggleButtonSetState(bar->pathSegments[bar->selection], True, False); 540 XmToggleButtonSetState(bar->pathSegments[bar->selection], True, False);
555 541
575 // TODO: check if there is somonething missing 561 // TODO: check if there is somonething missing
576 XtFree((void*)pathbar->pathSegments); 562 XtFree((void*)pathbar->pathSegments);
577 XtFree((void*)pathbar); 563 XtFree((void*)pathbar);
578 } 564 }
579 565
566 // TODO: move to common
567 static UiPathElm* default_pathelm_func(const char* full_path, size_t len, size_t* ret_nelm, void* data) {
568 cxstring *pathelms;
569 size_t nelm = cx_strsplit_a(cxDefaultAllocator, cx_strn(full_path, len), CX_STR("/"), 4096, &pathelms);
570
571 if (nelm == 0) {
572 *ret_nelm = 0;
573 return NULL;
574 }
575
576 UiPathElm* elms = (UiPathElm*)calloc(nelm, sizeof(UiPathElm));
577 size_t n = nelm;
578 int j = 0;
579 for (int i = 0; i < nelm; i++) {
580 cxstring c = pathelms[i];
581 if (c.length == 0) {
582 if (i == 0) {
583 c.length = 1;
584 }
585 else {
586 n--;
587 continue;
588 }
589 }
590
591 cxmutstr m = cx_strdup(c);
592 elms[j].name = m.ptr;
593 elms[j].name_len = m.length;
594
595 size_t elm_path_len = c.ptr + c.length - full_path;
596 cxmutstr elm_path = cx_strdup(cx_strn(full_path, elm_path_len));
597 elms[j].path = elm_path.ptr;
598 elms[j].path_len = elm_path.length;
599
600 j++;
601 }
602 *ret_nelm = n;
603
604 return elms;
605 }
606
607 static void pathbar_activate(void *data, char *path, int index) {
608 UiEventData *event = data;
609 UiEvent evt;
610 evt.obj = event->obj;
611 evt.window = evt.obj->window;
612 evt.document = evt.obj->ctx->document;
613 evt.eventdata = path;
614 evt.intval = index;
615 event->callback(&evt, event->userdata);
616 }
617
580 UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs args) { 618 UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs args) {
581 Arg xargs[16]; 619 Arg xargs[16];
582 int n = 0; 620 int n = 0;
583 621
584 UiContainerPrivate *ctn = ui_obj_container(obj); 622 UiContainerPrivate *ctn = ui_obj_container(obj);
585 UI_APPLY_LAYOUT(ctn->layout, args); 623 UI_APPLY_LAYOUT(ctn->layout, args);
586 624
587 Widget parent = ctn->prepare(ctn, xargs, &n); 625 Widget parent = ctn->prepare(ctn, xargs, &n);
588 // TODO: name 626 // TODO: name
589 627
628
590 PathBar *pathbar = CreatePathBar(parent, xargs, n); 629 PathBar *pathbar = CreatePathBar(parent, xargs, n);
630 if(!args.getpathelm) {
631 pathbar->getpathelm= default_pathelm_func;
632 } else {
633 pathbar->getpathelm = args.getpathelm;
634 pathbar->getpathelmdata = args.getpathelmdata;
635 }
636
637
591 XtManageChild(pathbar->widget); 638 XtManageChild(pathbar->widget);
592 ctn->add(ctn, pathbar->widget); 639 ctn->add(ctn, pathbar->widget);
593 640
594 UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.value, args.varname, UI_VAR_STRING); 641 UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.value, args.varname, UI_VAR_STRING);
595 if (var) { 642 if (var) {
603 ui_string_set(value, str); 650 ui_string_set(value, str);
604 free(str); 651 free(str);
605 } 652 }
606 } 653 }
607 654
655 if(args.onactivate) {
656 UiEventData *eventdata = malloc(sizeof(UiEventData));
657 eventdata->callback = args.onactivate;
658 eventdata->userdata = args.onactivatedata;
659 eventdata->obj = obj;
660 eventdata->value = 0;
661
662 pathbar->updateDir = pathbar_activate;
663 pathbar->updateDirData = eventdata;
664
665 XtAddCallback(
666 pathbar->widget,
667 XmNdestroyCallback,
668 (XtCallbackProc)ui_destroy_eventdata,
669 eventdata);
670 }
671
608 XtAddCallback( 672 XtAddCallback(
609 pathbar->widget, 673 pathbar->widget,
610 XmNdestroyCallback, 674 XmNdestroyCallback,
611 (XtCallbackProc)destroy_pathbar, 675 (XtCallbackProc)destroy_pathbar,
612 pathbar); 676 pathbar);
613 677
614 return pathbar->widget; 678 return pathbar->widget;
615 } 679 }
616 680
617 char* ui_path_textfield_get(UiString *str) { 681 char* ui_path_textfield_get(UiString *str) {
618 682 PathBar *pathbar = str->obj;
683 str->value.free(str->value.ptr);
684 char *value = XmTextFieldGetString(pathbar->textfield);
685 str->value.ptr = value;
686 str->value.free = (ui_freefunc)XtFree;
687 return value;
619 } 688 }
620 689
621 void ui_path_textfield_set(UiString *str, const char *value) { 690 void ui_path_textfield_set(UiString *str, const char *value) {
622 PathBarSetPath(str->obj, value); 691 PathBarSetPath(str->obj, value);
623 } 692 }

mercurial