ui/motif/text.c

branch
newapi
changeset 415
e35cdf33998c
parent 414
ef60d527c066
child 416
89ad8467c39f
--- 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;i<bar->numSegments;i++) {  
+    int i;
+    for(i=0;i<bar->numSegments;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;i<nelm;i++) {
+        free(elms[i].name);
+        free(elms[i].path);
+    }
+    free(elms);
 }
 
 void PathBarSetPath(PathBar *bar, const char *path)
@@ -500,54 +505,35 @@
     
     bar->numSegments = 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;i<nelm;i++) {
+        UiPathElm elm = path_elm[i];
+        
+        cxmutstr name = cx_strdup(cx_strn(elm.name, elm.name_len));
+        str = XmStringCreateLocalized(elm.name);
+        free(name.ptr);
+        
         XtSetArg(args[0], XmNlabelString, str);
         XtSetArg(args[1], XmNfillOnSelect, True);
         XtSetArg(args[2], XmNindicatorOn, False);
-        bar->pathSegments[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) {

mercurial