application/window.c

changeset 97
5a3d27b8e6b0
parent 95
e92c72705da4
--- a/application/window.c	Wed Nov 27 18:53:11 2024 +0100
+++ b/application/window.c	Thu Nov 28 18:03:12 2024 +0100
@@ -30,6 +30,7 @@
 
 #include "davcontroller.h"
 #include "appsettings.h"
+#include "xml.h"
 
 #include <ui/stock.h>
 #include <ui/dnd.h>
@@ -188,17 +189,13 @@
     UiObject *win = ui_simple_window(name, NULL);
     ui_window_size(win, 600, 600);
     
-    // TODO: when properties can be modified, always add the headerbar
-    if(type == DAV_RESOURCE_VIEW_TEXT) {
-        ui_headerbar(win, .showtitle = TRUE) {
-            ui_headerbar_start(win) {
-                ui_button(win, .label = "Save", .style_class = "suggested-action", .onclick = action_resourceviewer_save, .groups = UI_GROUPS(RESOURCEVIEWER_STATE_MODIFIED));
-            }
+    ui_headerbar(win, .showtitle = TRUE) {
+        ui_headerbar_start(win) {
+            ui_button(win, .label = "Save", .onclick = action_resourceviewer_save, .groups = UI_GROUPS(RESOURCEVIEWER_STATE_MODIFIED));
         }
     }
     
-    
-    DavResourceViewer *doc = dav_resourceviewer_create(browser->sn, path, type);
+    DavResourceViewer *doc = dav_resourceviewer_create(win, browser->sn, path, type);
     ui_attach_document(win->ctx, doc);
     ui_context_closefunc(win->ctx, resourceviewer_close, doc);
     
@@ -255,7 +252,12 @@
                 ui_tab(win, "Properties") {
                     UiModel* model = ui_model(win->ctx, UI_STRING, "Namespace", UI_STRING, "Name", UI_STRING, "Value", -1);
                     model->getvalue = (ui_getvaluefunc) resourceviewer_proplist_getvalue;
-                    ui_table(win, .fill = UI_ON, .model = model, .varname = "properties");
+                    ui_table(win, .fill = UI_ON, .model = model, .varname = "properties", .onselection = action_resourceviewer_property_select, .onactivate = action_resourceviewer_property_activate);
+                    ui_hbox(win, .fill = UI_OFF, .margin = 4, .spacing = 4) {
+                        ui_button(win, .label = "Add", .onclick = action_resourceviewer_property_add);
+                        ui_button(win, .label = "Edit", .onclick = action_resourceviewer_property_edit, .groups = UI_GROUPS(RESOURCEVIEWER_STATE_PROP_SELECTED));
+                        ui_button(win, .label = "Remove", .onclick = action_resourceviewer_property_remove, .groups = UI_GROUPS(RESOURCEVIEWER_STATE_PROP_SELECTED));
+                    }
                 }
             }
         }
@@ -545,3 +547,196 @@
     DavResourceViewer *doc = event->document;
     dav_resourceviewer_save(event->obj, doc);
 }
+
+void action_resourceviewer_property_select(UiEvent *event, void *data) {
+    DavResourceViewer *doc = event->document;
+    UiListSelection *selection = event->eventdata;
+    if(selection->count == 1) {
+        ui_set_group(event->obj->ctx, RESOURCEVIEWER_STATE_PROP_SELECTED);
+        doc->selected_property = ui_list_get(doc->properties, selection->rows[0]);
+    } else {
+        ui_unset_group(event->obj->ctx, RESOURCEVIEWER_STATE_PROP_SELECTED);
+        doc->selected_property = NULL;
+    }
+}
+
+void action_resourceviewer_property_activate(UiEvent *event, void *data) {
+    action_resourceviewer_property_select(event, data);
+    action_resourceviewer_property_edit(event, data);
+}
+
+
+typedef struct PropertyDialog {
+    UiInteger *type;
+    UiString *ns;
+    UiString *name;
+    UiText *value;
+} PropertyDialog;
+
+static void propertydialog_action(UiEvent *event, void *data) {
+    DavResourceViewer *res = data;
+    if(event->intval == 4) {
+        char *ns = ui_get(res->property_ns);
+        char *name = ui_get(res->property_name);
+        int type = ui_get(res->property_type);
+        char *nsdef = ui_get(res->property_nsdef);
+        char *value = ui_get(res->property_value);
+        
+        if(strlen(ns) == 0) {
+            ui_set(res->property_errormsg, "Namespace must not be empty!");
+            return;
+        }
+        if(strlen(name) == 0) {
+            ui_set(res->property_errormsg, "Name must not be empty!");
+            return;
+        }
+        
+        char *textvalue = NULL;
+        DavXmlNode *xmlvalue = NULL;
+        if(type == 0) {
+            // text value
+            textvalue = value;
+        } else {
+            // xml value
+        }
+        
+        DavBool add = FALSE;
+        if(res->edit_property) {
+            if(strcmp(res->edit_property->ns, ns) || strcmp(res->edit_property->name, name)) {
+                // name or namespace changed, remove existing and create new property
+                dav_resourceviewer_property_remove(res, res->edit_property);
+                add = TRUE;
+            }
+        } else {
+            add = TRUE;
+        }
+        
+        if(add) {
+            if(textvalue) {
+                dav_resourceviewer_property_add_text(res, ns, name, textvalue);
+            } else {
+                dav_resourceviewer_property_add_xml(res, ns, name, nsdef, xmlvalue);
+            }
+        } else {
+            if(textvalue) {
+                dav_resourceviewer_property_update_text(res, res->edit_property, textvalue);
+            } else {
+                dav_resourceviewer_property_update_xml(res, res->edit_property, xmlvalue);
+            }
+        }
+    }
+    ui_close(event->obj);
+}
+
+static void prop_type_changed(UiEvent *event, void *data) {
+    DavResourceViewer *res = data;
+    switch(ui_get(res->property_type)) {
+        case 0: {
+            ui_unset_group(event->obj->ctx, RESOURCEVIEWER_STATE_PROP_XML);
+            break;
+        }
+        case 1: {
+            ui_set_group(event->obj->ctx, RESOURCEVIEWER_STATE_PROP_XML);
+            char *ns = ui_get(res->property_ns);
+            char *nsdef = ui_get(res->property_nsdef);
+            if(strlen(nsdef) == 0) {
+                cxmutstr def = cx_asprintf("xmlns:x0=\"%s\"", ns);
+                ui_set(res->property_nsdef, def.ptr);
+                free(def.ptr);
+            }
+            
+            break;
+        }
+    }
+}
+
+static void edit_property_dialog(DavResourceViewer *res, const char *title, DavPropertyList *prop) {
+    res->edit_property = prop;
+    
+    UiObject *obj = ui_dialog_window(res->obj,
+            .title = title,
+            .show_closebutton = UI_OFF,
+            .lbutton1 = "Cancel",
+            .rbutton4 = "Save",
+            .default_button = 4,
+            .onclick = propertydialog_action,
+            .onclickdata = res,
+            .width = 600,
+            .height = 500);
+    
+    ui_grid(obj, .margin = 16, .columnspacing = 8, .rowspacing = 12) {
+        ui_llabel(obj, .label = "Namespace");
+        ui_textfield(obj, .hexpand = TRUE, .value = res->property_ns);
+        ui_newline(obj);
+        
+        ui_llabel(obj, .label = "Property Name");
+        ui_textfield(obj, .hexpand = TRUE, .value = res->property_name);
+        ui_newline(obj);
+        
+        ui_llabel(obj, .label = "Type");
+        ui_hbox(obj, .spacing = 8, .colspan = 2) {
+            ui_radiobutton(obj, .label = "Text", .value = res->property_type, .onchange = prop_type_changed, .onchangedata = res);
+            ui_radiobutton(obj, .label = "XML", .value = res->property_type, .onchange = prop_type_changed, .onchangedata = res);
+        }
+        ui_newline(obj);
+        
+        ui_llabel(obj, .label = "Namespace Declarations");
+        ui_textfield(obj, .hexpand = TRUE, .value = res->property_nsdef, .groups = UI_GROUPS(RESOURCEVIEWER_STATE_PROP_XML));
+        ui_newline(obj);
+        
+        ui_textarea(obj, .value = res->property_value, .hexpand = TRUE, .vexpand = TRUE, .colspan = 2);
+        ui_newline(obj);
+        
+        ui_llabel(obj, .colspan = 2, .value = res->property_errormsg);
+    }
+    
+    if(prop && prop->ns && prop->name) {
+        ui_set(res->property_ns, prop->ns);
+        ui_set(res->property_name, prop->name);
+        if(prop->value_full) {
+            ui_set(res->property_type, 0);
+            ui_set(res->property_nsdef, "");
+            ui_set(res->property_value, prop->value_full);
+            ui_unset_group(obj->ctx, RESOURCEVIEWER_STATE_PROP_XML);
+        } else if(prop->xml) {
+            ui_set(res->property_type, 1);
+            cxmutstr xml;
+            cxmutstr nsdef;
+            property_xml2str(prop->xml, prop->ns, &xml, &nsdef);
+            ui_set(res->property_nsdef, nsdef.ptr);
+            ui_set(res->property_value, xml.ptr);
+            free(xml.ptr);
+            free(nsdef.ptr);
+            ui_set_group(obj->ctx, RESOURCEVIEWER_STATE_PROP_XML);
+        }
+    } else {
+        ui_set(res->property_ns, "");
+        ui_set(res->property_name, "");
+        ui_set(res->property_nsdef, "");
+        ui_set(res->property_type, 0);
+        ui_set(res->property_value, "");
+    }
+    
+    ui_set(res->property_errormsg, "");
+    
+    ui_show(obj);
+}
+
+void action_resourceviewer_property_add(UiEvent *event, void *data) {
+    DavResourceViewer *doc = event->document;
+    edit_property_dialog(doc, "Add Property", NULL);
+}
+
+void action_resourceviewer_property_edit(UiEvent *event, void *data) {
+    DavResourceViewer *doc = event->document;
+    edit_property_dialog(doc, "Edit Property", doc->selected_property);
+}
+
+void action_resourceviewer_property_remove(UiEvent *event, void *data) {
+    DavResourceViewer *doc = event->document;
+    if(!doc->selected_property) {
+        return; // shouldn't happen
+    }
+    dav_resourceviewer_property_remove(doc, doc->selected_property);
+}
+

mercurial