# HG changeset patch # User Olaf Wintermann # Date 1734083971 -3600 # Node ID e35cdf33998cd0b8ae13734b1a6da7af8e6980fa # Parent ef60d527c06647f70aedf871abc16bb5e017bcaf finish motif path bar implementation diff -r ef60d527c066 -r e35cdf33998c ui/motif/text.c --- a/ui/motif/text.c Thu Dec 12 23:23:09 2024 +0100 +++ b/ui/motif/text.c Fri Dec 13 10:59:31 2024 +0100 @@ -115,7 +115,7 @@ #define XNETextSetInsertionPosition(widget, i) XmTextFieldSetInsertionPosition(widget, i) #define XNETextSetSelection(w, f, l, t) XmTextFieldSetSelection(w, f, l, t) -typedef void(*updatedir_callback)(void*,char*); +typedef void(*updatedir_callback)(void*,char*,int); typedef struct PathBar { Widget widget; @@ -130,6 +130,7 @@ int shift; + UiPathElm *current_pathelms; Widget *pathSegments; size_t numSegments; size_t segmentAlloc; @@ -142,6 +143,9 @@ updatedir_callback updateDir; void *updateDirData; + + ui_pathelm_func getpathelm; + void *getpathelmdata; } PathBar; void PathBarSetPath(PathBar *bar, const char *path); @@ -333,7 +337,7 @@ /* update path */ PathBarSetPath(p, newpath); if(p->updateDir) { - p->updateDir(p->updateDirData, newpath); + p->updateDir(p->updateDirData, newpath, -1); } XtFree(newpath); @@ -384,6 +388,9 @@ bar->focus_widget = NULL; + bar->getpathelm = NULL; + bar->getpathelmdata = NULL; + bar->shift = 0; XtSetArg(args[n], XmNmarginWidth, 0); n++; @@ -453,7 +460,8 @@ { XmToggleButtonSetState(bar->pathSegments[bar->selection], False, False); - for(int i=0;inumSegments;i++) { + int i; + for(i=0;inumSegments;i++) { if(bar->pathSegments[i] == w) { bar->selection = i; XmToggleButtonSetState(w, True, False); @@ -461,23 +469,20 @@ } } - int plen = strlen(bar->path); - int countSeg = 0; - for(int i=0;i<=plen;i++) { - char c = bar->path[i]; - if(c == '/' || c == '\0') { - if(countSeg == bar->selection) { - char *dir = XtMalloc(i+2); - memcpy(dir, bar->path, i+1); - dir[i+1] = '\0'; - if(bar->updateDir) { - bar->updateDir(bar->updateDirData, dir); - } - free(dir); - } - countSeg++; - } + UiPathElm elm = bar->current_pathelms[i]; + cxmutstr name = cx_strdup(cx_strn(elm.name, elm.name_len)); + if(bar->updateDir) { + bar->updateDir(bar->updateDirData, name.ptr, i); } + free(name.ptr); +} + +static void ui_pathelm_destroy(UiPathElm *elms, size_t nelm) { + for(int i=0;inumSegments = 0; - int i=0; - if(path[0] == '/') { - str = XmStringCreateLocalized("/"); + ui_pathelm_destroy(bar->current_pathelms, bar->numSegments); + size_t nelm = 0; + UiPathElm* path_elm = bar->getpathelm(bar->path, strlen(bar->path), &nelm, bar->getpathelmdata); + if (!path_elm) { + return; + } + bar->current_pathelms = path_elm; + bar->numSegments = nelm; + bar->pathSegments = realloc(bar->pathSegments, nelm * sizeof(Widget*)); + + for(int i=0;ipathSegments[0] = XmCreateToggleButton( - bar->widget, "pbbutton", args, 3); + Widget button = XmCreateToggleButton(bar->widget, "pbbutton", args, 3); XtAddCallback( - bar->pathSegments[0], + button, XmNvalueChangedCallback, (XtCallbackProc)PathBarChangeDir, bar); XmStringFree(str); - bar->numSegments++; - i++; - } - - int len = strlen(path); - int begin = i; - for(;i<=len;i++) { - char c = path[i]; - if((c == '/' || c == '\0') && i > begin) { - char *segStr = XtMalloc(i - begin + 1); - memcpy(segStr, path+begin, i-begin); - segStr[i-begin] = '\0'; - begin = i+1; - - str = XmStringCreateLocalized(segStr); - XtFree(segStr); - XtSetArg(args[0], XmNlabelString, str); - XtSetArg(args[1], XmNfillOnSelect, True); - XtSetArg(args[2], XmNindicatorOn, False); - Widget button = XmCreateToggleButton(bar->widget, "pbbutton", args, 3); - XtAddCallback( - button, - XmNvalueChangedCallback, - (XtCallbackProc)PathBarChangeDir, - bar); - XmStringFree(str); - - if(bar->numSegments >= bar->segmentAlloc) { - bar->segmentAlloc += 8; - bar->pathSegments = realloc(bar->pathSegments, bar->segmentAlloc * sizeof(Widget)); - } - - bar->pathSegments[bar->numSegments++] = button; - } + + bar->pathSegments[i] = button; } bar->selection = bar->numSegments-1; @@ -577,6 +563,58 @@ XtFree((void*)pathbar); } +// TODO: move to common +static UiPathElm* default_pathelm_func(const char* full_path, size_t len, size_t* ret_nelm, void* data) { + cxstring *pathelms; + size_t nelm = cx_strsplit_a(cxDefaultAllocator, cx_strn(full_path, len), CX_STR("/"), 4096, &pathelms); + + if (nelm == 0) { + *ret_nelm = 0; + return NULL; + } + + UiPathElm* elms = (UiPathElm*)calloc(nelm, sizeof(UiPathElm)); + size_t n = nelm; + int j = 0; + for (int i = 0; i < nelm; i++) { + cxstring c = pathelms[i]; + if (c.length == 0) { + if (i == 0) { + c.length = 1; + } + else { + n--; + continue; + } + } + + cxmutstr m = cx_strdup(c); + elms[j].name = m.ptr; + elms[j].name_len = m.length; + + size_t elm_path_len = c.ptr + c.length - full_path; + cxmutstr elm_path = cx_strdup(cx_strn(full_path, elm_path_len)); + elms[j].path = elm_path.ptr; + elms[j].path_len = elm_path.length; + + j++; + } + *ret_nelm = n; + + return elms; +} + +static void pathbar_activate(void *data, char *path, int index) { + UiEventData *event = data; + UiEvent evt; + evt.obj = event->obj; + evt.window = evt.obj->window; + evt.document = evt.obj->ctx->document; + evt.eventdata = path; + evt.intval = index; + event->callback(&evt, event->userdata); +} + UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs args) { Arg xargs[16]; int n = 0; @@ -587,7 +625,16 @@ Widget parent = ctn->prepare(ctn, xargs, &n); // TODO: name + PathBar *pathbar = CreatePathBar(parent, xargs, n); + if(!args.getpathelm) { + pathbar->getpathelm= default_pathelm_func; + } else { + pathbar->getpathelm = args.getpathelm; + pathbar->getpathelmdata = args.getpathelmdata; + } + + XtManageChild(pathbar->widget); ctn->add(ctn, pathbar->widget); @@ -605,6 +652,23 @@ } } + if(args.onactivate) { + UiEventData *eventdata = malloc(sizeof(UiEventData)); + eventdata->callback = args.onactivate; + eventdata->userdata = args.onactivatedata; + eventdata->obj = obj; + eventdata->value = 0; + + pathbar->updateDir = pathbar_activate; + pathbar->updateDirData = eventdata; + + XtAddCallback( + pathbar->widget, + XmNdestroyCallback, + (XtCallbackProc)ui_destroy_eventdata, + eventdata); + } + XtAddCallback( pathbar->widget, XmNdestroyCallback, @@ -615,7 +679,12 @@ } char* ui_path_textfield_get(UiString *str) { - + PathBar *pathbar = str->obj; + str->value.free(str->value.ptr); + char *value = XmTextFieldGetString(pathbar->textfield); + str->value.ptr = value; + str->value.free = (ui_freefunc)XtFree; + return value; } void ui_path_textfield_set(UiString *str, const char *value) {