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 |
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 } |