]> uap-core.de Git - note.git/commitdiff
add label
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Mon, 18 May 2026 20:19:15 +0000 (22:19 +0200)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Mon, 18 May 2026 20:19:15 +0000 (22:19 +0200)
12 files changed:
application/src/main.rs
application/src/newnotebook.rs [new file with mode: 0644]
application/src/window.rs
ui-rs/src/ui/application.rs
ui-rs/src/ui/event.rs
ui-rs/src/ui/ffi.rs
ui-rs/src/ui/label.rs [new file with mode: 0644]
ui-rs/src/ui/mod.rs
ui-rs/src/ui/toolkit.rs
ui-rs/src/ui/window.rs
ui/common/object.c
ui/gtk/toolkit.c

index 4c957ea230c802d3830f85f04b5f21f8c0bb3bf8..4a5620ac9f391f0304c2faebe0997bef0191c644 100644 (file)
@@ -28,6 +28,7 @@
 
 mod window;
 mod backend;
+mod newnotebook;
 
 use std::env;
 use entity::collection::{create_notebook_hierarchy, Node};
diff --git a/application/src/newnotebook.rs b/application/src/newnotebook.rs
new file mode 100644 (file)
index 0000000..e65ec9e
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2026 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+use ui_rs::{UiModel, UiActions};
+use ui_rs::ui::*;
+
+#[derive(UiModel, UiActions, Default)]
+struct NewNotebookDialog {
+    name: UiString
+}
+
+pub fn new_notebook_dialog<T>(parent: &UiObject<T>) {
+    let data = NewNotebookDialog::default();
+
+    parent.dialogwindow_builder()
+        .title("Add Notebook")
+        .modal(true)
+        .show_closebutton(false)
+        .lbutton1("Add")
+        .rbutton4("Cancel")
+        .default_button(1)
+        .onclick(|e|{
+            e.obj.close();
+        })
+        .create(data, |obj, data|
+    {
+        obj.grid(|a| {
+            a.margin(10);
+            a.columnspacing(10);
+            a.rowspacing(10);
+        }, |obj| {
+
+        });
+    }).show();
+}
\ No newline at end of file
index e2931fefeaa6638f7fb0815751bc94cbf7381918..6fd2ab2d27f3889cd4dd103e75a05b978baa6389 100644 (file)
@@ -31,6 +31,7 @@ use ui_rs::ui::*;
 use crate::App;
 use entity::collection::{Model as Collection, Node};
 use crate::backend::{BackendHandle, BroadcastMessage};
+use crate::newnotebook::new_notebook_dialog;
 
 #[derive(UiModel)]
 pub struct MainWindow {
@@ -50,8 +51,8 @@ impl MainWindow {
     }
 
     #[action]
-    pub fn new_notebook(&mut self, _event: &ActionEvent) {
-
+    pub fn new_notebook(&mut self, event: &ActionEvent) {
+        new_notebook_dialog(event.obj);
     }
 
     #[action]
index fea2cbaf09c337b6706f4ad12c20381a4bd9cb93..7fccda44f9eab00dfbac1180b38235b6c466031e 100644 (file)
@@ -45,6 +45,7 @@ pub struct AppContext<T: UiModel + UiActions> {
     _marker: PhantomData<T>,
 }
 
+#[derive(Default)]
 pub struct NoAppData {}
 
 impl UiModel for NoAppData {
index e1d43f5e980cf9255dce471a6a6ce723abfec76d..7c3b3d3bbe9144b0cabe48bfb7b49617b1f69a4e 100644 (file)
@@ -29,7 +29,7 @@
 #![allow(dead_code)]
 
 use std::ffi::{c_char, c_void, CStr, CString};
-use crate::ui::{event, ffi, UiDouble, UiInteger, UiString, UiText, UiRange, ListSelection, UiObject};
+use crate::ui::{event, ffi, UiDouble, UiInteger, UiString, UiText, UiRange, ListSelection, UiObject, NoAppData};
 use crate::ui::ffi::{UiEvent};
 
 pub struct Event<'a, T> {
@@ -41,6 +41,7 @@ pub struct Event<'a, T> {
 }
 
 pub struct ActionEvent<'a> {
+    pub obj: &'a UiObject<NoAppData>,
     pub event_type: EventType<'a>,
     pub intval: i32,
     pub set: bool
@@ -152,7 +153,7 @@ pub extern "C" fn event_wrapper<T>(e: *const ffi::UiEvent, data: *mut c_void) {
         let mut event_data = get_event_data(e);
         let event_type = get_event_type(&mut event_data);
 
-        let obj_ptr = unsafe { ui_event_get_obj(e) };
+        let obj_ptr = ui_event_get_obj(e);
         let mut obj: UiObject<T> = UiObject::from_ptr(obj_ptr);
 
         let mut event = Event {
@@ -190,7 +191,11 @@ pub extern "C" fn action_event_wrapper<T>(e: *const ffi::UiEvent, data: *mut c_v
         let mut event_data = get_event_data(e);
         let event_type = get_event_type(&mut event_data);
 
+        let obj_ptr = ui_event_get_obj(e);
+        let obj: UiObject<NoAppData> = UiObject::from_ptr(obj_ptr);
+
         let event = ActionEvent {
+            obj: &obj,
             event_type: event_type,
             intval: ev_int,
             set: ev_set
index bac96bcf0771784ce26e58dbaecd033c045752cb..cc48d34bcc927ad612bf4f54ce1fa8dc8a5b8f3b 100644 (file)
@@ -137,6 +137,11 @@ pub struct UiItemListContainerArgs {
     _private: [u8; 0],
 }
 
+#[repr(C)]
+pub struct UiLabelArgs {
+    _private: [u8; 0],
+}
+
 #[repr(C)]
 pub struct UiButtonArgs {
     _private: [u8; 0],
diff --git a/ui-rs/src/ui/label.rs b/ui-rs/src/ui/label.rs
new file mode 100644 (file)
index 0000000..58212a6
--- /dev/null
@@ -0,0 +1,273 @@
+use std::ffi::{c_char, c_int, c_void, CString};
+use crate::ui::{ffi, toolkit, Button, ButtonBuilder};
+use crate::ui::ffi::{UiButtonArgs, UiLabelArgs, UiObject, UiString, UiToggleArgs};
+use crate::ui::widget::{widget_fn, Widget};
+
+pub struct Label {
+    ptr: *mut c_void
+}
+
+impl Widget for Label {
+    fn get_widget(&self) -> *mut c_void {
+        self.ptr
+    }
+}
+
+pub type LabelCreate = fn(*const UiObject, *const UiLabelArgs) -> *mut c_void;
+
+pub struct LabelBuilder<'a, T> {
+    args: *mut UiLabelArgs,
+    obj: &'a mut toolkit::UiObject<T>,
+    create: LabelCreate
+}
+
+pub enum LabelStyle {
+    Default = 0,
+    Title = 1,
+    SubTitle = 2,
+    Dim = 3
+}
+
+impl<T> toolkit::UiObject<T> {
+    widget_fn!(label, label_builder, LabelBuilder, Label);
+    widget_fn!(llabel, llabel_builder, LabelBuilder, Label);
+    widget_fn!(rlabel, rlabel_builder, LabelBuilder, Label);
+
+    pub fn label_builder<'a>(&'a mut self) -> LabelBuilder<'a, T> {
+        unsafe {
+            let args = ui_label_args_new();
+            LabelBuilder { args: args, obj: self, create: label_create }
+        }
+    }
+
+    pub fn llabel_builder<'a>(&'a mut self) -> LabelBuilder<'a, T> {
+        unsafe {
+            let args = ui_label_args_new();
+            LabelBuilder { args: args, obj: self, create: llabel_create }
+        }
+    }
+
+    pub fn rlabel_builder<'a>(&'a mut self) -> LabelBuilder<'a, T> {
+        unsafe {
+            let args = ui_label_args_new();
+            LabelBuilder { args: args, obj: self, create: rlabel_create }
+        }
+    }
+}
+
+fn label_create<'a>(obj: *const UiObject, args: *const UiLabelArgs) -> *mut c_void {
+    unsafe {
+        ui_label_create(obj, args)
+    }
+}
+
+fn llabel_create<'a>(obj: *const UiObject, args: *const UiLabelArgs) -> *mut c_void {
+    unsafe {
+        ui_llabel_create(obj, args)
+    }
+}
+
+fn rlabel_create<'a>(obj: *const UiObject, args: *const UiLabelArgs) -> *mut c_void {
+    unsafe {
+        ui_rlabel_create(obj, args)
+    }
+}
+
+impl<'a, T> Drop for LabelBuilder<'a, T> {
+    fn drop(&mut self) {
+        unsafe {
+            ui_label_args_free(self.args);
+        }
+    }
+}
+
+impl<'a, T> LabelBuilder<'a, T> {
+    pub fn create(&mut self) -> Label {
+        unsafe {
+            Label { ptr: (self.create)(self.obj.ptr, self.args) }
+        }
+    }
+
+    pub fn fill(&mut self, fill: bool) -> &mut Self {
+        unsafe {
+            ui_label_args_set_fill(self.args, fill as c_int);
+        }
+        self
+    }
+
+    pub fn hexpand(&mut self, value: bool) -> &mut Self {
+        unsafe {
+            ui_label_args_set_hexpand(self.args, value as c_int);
+        }
+        self
+    }
+
+    pub fn vexpand(&mut self, value: bool) -> &mut Self {
+        unsafe {
+            ui_label_args_set_vexpand(self.args, value as c_int);
+        }
+        self
+    }
+
+    pub fn hfill(&mut self, value: bool) -> &mut Self {
+        unsafe {
+            ui_label_args_set_hfill(self.args, value as c_int);
+        }
+        self
+    }
+
+    pub fn vfill(&mut self, value: bool) -> &mut Self {
+        unsafe {
+            ui_label_args_set_vfill(self.args, value as c_int);
+        }
+        self
+    }
+
+    pub fn override_defaults(&mut self, value: bool) -> &mut Self {
+        unsafe {
+            ui_label_args_set_override_defaults(self.args, value as c_int);
+        }
+        self
+    }
+
+    pub fn margin(&mut self, value: i32) -> &mut Self {
+        unsafe {
+            ui_label_args_set_margin(self.args, value);
+        }
+        self
+    }
+
+    pub fn margin_left(&mut self, value: i32) -> &mut Self {
+        unsafe {
+            ui_label_args_set_margin_left(self.args, value);
+        }
+        self
+    }
+
+    pub fn margin_right(&mut self, value: i32) -> &mut Self {
+        unsafe {
+            ui_label_args_set_margin_right(self.args, value);
+        }
+        self
+    }
+
+    pub fn margin_top(&mut self, value: i32) -> &mut Self {
+        unsafe {
+            ui_label_args_set_margin_top(self.args, value);
+        }
+        self
+    }
+
+    pub fn margin_bottom(&mut self, value: i32) -> &mut Self {
+        unsafe {
+            ui_label_args_set_margin_bottom(self.args, value);
+        }
+        self
+    }
+
+    pub fn colspan(&mut self, value: i32) -> &mut Self {
+        unsafe {
+            ui_label_args_set_colspan(self.args, value);
+        }
+        self
+    }
+
+    pub fn rowspan(&mut self, value: i32) -> &mut Self {
+        unsafe {
+            ui_label_args_set_rowspan(self.args, value);
+        }
+        self
+    }
+
+    pub fn name(&mut self, value: &str) -> &mut Self {
+        let cstr = CString::new(value).unwrap();
+        unsafe {
+            ui_label_args_set_name(self.args, cstr.as_ptr());
+        }
+        self
+    }
+
+    pub fn style_class(&mut self, value: &str) -> &mut Self {
+        let cstr = CString::new(value).unwrap();
+        unsafe {
+            ui_label_args_set_style_class(self.args, cstr.as_ptr());
+        }
+        self
+    }
+
+    pub fn label(&mut self, label: &str) -> &mut Self {
+        let cstr = CString::new(label).unwrap();
+        unsafe {
+            ui_label_args_set_label(self.args, cstr.as_ptr());
+        }
+        self
+    }
+
+    // TODO: align
+
+    pub fn style(&mut self, value: LabelStyle) -> &mut Self {
+        unsafe {
+            ui_label_args_set_style(self.args, value as c_int);
+        }
+        self
+    }
+
+    pub fn value(&mut self, value: &toolkit::UiString) {
+        unsafe {
+            ui_label_args_set_value(self.args, value.ptr);
+        }
+    }
+
+    pub fn varname(&mut self, varname: &str) -> &mut Self {
+        let cstr = CString::new(varname).unwrap();
+        unsafe {
+            ui_label_args_set_varname(self.args, cstr.as_ptr());
+        }
+        self
+    }
+
+    pub fn visibility_states(&mut self, states: &[i32]) -> &mut Self {
+        unsafe {
+            ui_label_args_set_visibility_states(self.args, states.as_ptr(), states.len() as c_int);
+        }
+        self
+    }
+
+    pub fn states(&mut self, states: &[i32]) -> &mut Self {
+        unsafe {
+            ui_label_args_set_states(self.args, states.as_ptr(), states.len() as c_int);
+        }
+        self
+    }
+}
+
+extern "C" {
+    fn ui_label_create(obj: *const ffi::UiObject, args: *const UiLabelArgs) -> *mut c_void;
+    fn ui_llabel_create(obj: *const ffi::UiObject, args: *const UiLabelArgs) -> *mut c_void;
+    fn ui_rlabel_create(obj: *const ffi::UiObject, args: *const UiLabelArgs) -> *mut c_void;
+
+    fn ui_label_args_new() -> *mut UiLabelArgs;
+    fn ui_label_args_set_fill(args: *mut UiLabelArgs, fill: c_int);
+    fn ui_label_args_set_hexpand(args: *mut UiLabelArgs, value: c_int);
+    fn ui_label_args_set_vexpand(args: *mut UiLabelArgs, value: c_int);
+    fn ui_label_args_set_hfill(args: *mut UiLabelArgs, value: c_int);
+    fn ui_label_args_set_vfill(args: *mut UiLabelArgs, value: c_int);
+    fn ui_label_args_set_override_defaults(args: *mut UiLabelArgs, value: c_int);
+    fn ui_label_args_set_margin(args: *mut UiLabelArgs, value: c_int);
+    fn ui_label_args_set_margin_left(args: *mut UiLabelArgs, value: c_int);
+    fn ui_label_args_set_margin_right(args: *mut UiLabelArgs, value: c_int);
+    fn ui_label_args_set_margin_top(args: *mut UiLabelArgs, value: c_int);
+    fn ui_label_args_set_margin_bottom(args: *mut UiLabelArgs, value: c_int);
+    fn ui_label_args_set_colspan(args: *mut UiLabelArgs, value: c_int);
+    fn ui_label_args_set_rowspan(args: *mut UiLabelArgs, value: c_int);
+    fn ui_label_args_set_name(args: *mut UiLabelArgs, name: *const c_char);
+    fn ui_label_args_set_style_class(args: *mut UiLabelArgs, classname: *const c_char);
+    fn ui_label_args_set_label(args: *mut UiLabelArgs, label: *const c_char);
+    fn ui_label_args_set_align(args: *mut UiLabelArgs, align: c_int);
+    fn ui_label_args_set_style(args: *mut UiLabelArgs, style: c_int);
+    fn ui_label_args_set_value(args: *mut UiLabelArgs, ivalue: *mut UiString);
+    fn ui_label_args_set_varname(args: *mut UiLabelArgs, varname: *const c_char);
+    fn ui_label_args_set_states(args: *mut UiLabelArgs, states: *const c_int, numstates: c_int);
+    fn ui_label_args_set_visibility_states(args: *mut UiLabelArgs, states: *const c_int, numstates: c_int);
+    fn ui_label_args_free(args: *mut UiLabelArgs);
+}
\ No newline at end of file
index 39035ff681fd9e04862fc3330b01b3aa34364265..13bcf84552d01a1acd3ceaa3640b96a5a2273ef3 100644 (file)
@@ -38,6 +38,7 @@ pub mod event;
 pub mod list;
 mod menu;
 mod toolbar;
+mod label;
 
 pub use toolkit::*;
 pub use event::*;
index 481e6d933798089f15532346a47418928518dc31..8f323d4a6f50e75aa3c05d668dacff1056f3b2fe 100644 (file)
@@ -207,7 +207,7 @@ impl<T> UiObject<T> {
         }
     }
 
-    pub fn window_data<F>(self, mut f: F)
+    pub fn window_data<F>(&mut self, mut f: F)
     where F: FnMut(&mut T) {
         unsafe {
             let wdata_ptr: *mut T = ui_object_get_windowdata(self.ptr).cast();
@@ -219,7 +219,7 @@ impl<T> UiObject<T> {
 
     pub fn call_mainthread<F>(&self, mut f: F)
     where F: FnMut(&mut T) + 'static {
-        let obj = self.clone();
+        let mut obj = self.clone();
         call_mainthread(move || {
             obj.window_data(|wdata| {
                 f(wdata);
index f84d3812e65f03177fe40fff2e9eec4f51d42ae6..39beac9169f2a8eca82bd8c8b5eee683f25a89ff 100644 (file)
@@ -43,6 +43,12 @@ impl<T> toolkit::UiObject<T> {
         }
     }
 
+    pub fn close(&self) {
+        unsafe {
+            ui_close(self.ptr);
+        }
+    }
+
     pub fn set_size(&mut self, width: u32, height: u32) {
         unsafe {
             ui_window_size(self.ptr, width as c_int, height as c_int);
@@ -476,6 +482,7 @@ extern "C" {
 
 
     fn ui_show(ui: *const UiObject);
+    fn ui_close(ui: *const UiObject);
 
     pub fn ui_object_get_windowdata(obj: *const UiObject) -> *mut c_void;
     pub fn ui_object_set_windowdata(obj: *mut UiObject, data: *mut c_void);
index 213a83481e13e1fcd466ebb6b9dade19eddc0f0c..16f2ed9a1ea8cff41f811cdf248375fcd09d05ac 100644 (file)
@@ -105,8 +105,9 @@ int ui_object_unref(UiObject *obj) {
     if(obj->ref == 0 || --obj->ref == 0) {
         if(obj->destroy) {
             obj->destroy(obj);
+        } else {
+            uic_object_destroy(obj);
         }
-        uic_object_destroy(obj);
         return 0;
     }
     return 1;
index 6ab00a3ea312cc0a2b9546e0f79c73400e06d8b5..9d6cf9150429d56662e63c2c20977e5e4a4af698 100644 (file)
@@ -181,7 +181,8 @@ void ui_show(UiObject *obj) {
 }
 
 void ui_close(UiObject *obj) {
-    uic_context_prepare_close(obj->ctx); // TODO: should this be moved to the close event handler?
+    uic_context_prepare_close(obj->ctx); // TODO: should this be moved to the close event handler? Yes!
+    /*
     if(obj->widget) {
 #if GTK_CHECK_VERSION(4, 0, 0)
         gtk_window_close(GTK_WINDOW(obj->widget));
@@ -191,6 +192,8 @@ void ui_close(UiObject *obj) {
     } else {
         ui_window_close_request(obj);
     }
+    */
+    ui_window_close_request(obj);
 }