From: Olaf Wintermann Date: Mon, 18 May 2026 20:19:15 +0000 (+0200) Subject: add label X-Git-Url: https://uap-core.de/gitweb/?a=commitdiff_plain;h=a1d613e4fb7c5b4fa66a39febe5713e36daf41a1;p=note.git add label --- diff --git a/application/src/main.rs b/application/src/main.rs index 4c957ea..4a5620a 100644 --- a/application/src/main.rs +++ b/application/src/main.rs @@ -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 index 0000000..e65ec9e --- /dev/null +++ b/application/src/newnotebook.rs @@ -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(parent: &UiObject) { + 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 diff --git a/application/src/window.rs b/application/src/window.rs index e2931fe..6fd2ab2 100644 --- a/application/src/window.rs +++ b/application/src/window.rs @@ -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] diff --git a/ui-rs/src/ui/application.rs b/ui-rs/src/ui/application.rs index fea2cba..7fccda4 100644 --- a/ui-rs/src/ui/application.rs +++ b/ui-rs/src/ui/application.rs @@ -45,6 +45,7 @@ pub struct AppContext { _marker: PhantomData, } +#[derive(Default)] pub struct NoAppData {} impl UiModel for NoAppData { diff --git a/ui-rs/src/ui/event.rs b/ui-rs/src/ui/event.rs index e1d43f5..7c3b3d3 100644 --- a/ui-rs/src/ui/event.rs +++ b/ui-rs/src/ui/event.rs @@ -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, pub event_type: EventType<'a>, pub intval: i32, pub set: bool @@ -152,7 +153,7 @@ pub extern "C" fn event_wrapper(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 = UiObject::from_ptr(obj_ptr); let mut event = Event { @@ -190,7 +191,11 @@ pub extern "C" fn action_event_wrapper(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 = UiObject::from_ptr(obj_ptr); + let event = ActionEvent { + obj: &obj, event_type: event_type, intval: ev_int, set: ev_set diff --git a/ui-rs/src/ui/ffi.rs b/ui-rs/src/ui/ffi.rs index bac96bc..cc48d34 100644 --- a/ui-rs/src/ui/ffi.rs +++ b/ui-rs/src/ui/ffi.rs @@ -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 index 0000000..58212a6 --- /dev/null +++ b/ui-rs/src/ui/label.rs @@ -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, + create: LabelCreate +} + +pub enum LabelStyle { + Default = 0, + Title = 1, + SubTitle = 2, + Dim = 3 +} + +impl toolkit::UiObject { + 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 diff --git a/ui-rs/src/ui/mod.rs b/ui-rs/src/ui/mod.rs index 39035ff..13bcf84 100644 --- a/ui-rs/src/ui/mod.rs +++ b/ui-rs/src/ui/mod.rs @@ -38,6 +38,7 @@ pub mod event; pub mod list; mod menu; mod toolbar; +mod label; pub use toolkit::*; pub use event::*; diff --git a/ui-rs/src/ui/toolkit.rs b/ui-rs/src/ui/toolkit.rs index 481e6d9..8f323d4 100644 --- a/ui-rs/src/ui/toolkit.rs +++ b/ui-rs/src/ui/toolkit.rs @@ -207,7 +207,7 @@ impl UiObject { } } - pub fn window_data(self, mut f: F) + pub fn window_data(&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 UiObject { pub fn call_mainthread(&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); diff --git a/ui-rs/src/ui/window.rs b/ui-rs/src/ui/window.rs index f84d381..39beac9 100644 --- a/ui-rs/src/ui/window.rs +++ b/ui-rs/src/ui/window.rs @@ -43,6 +43,12 @@ impl toolkit::UiObject { } } + 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); diff --git a/ui/common/object.c b/ui/common/object.c index 213a834..16f2ed9 100644 --- a/ui/common/object.c +++ b/ui/common/object.c @@ -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; diff --git a/ui/gtk/toolkit.c b/ui/gtk/toolkit.c index 6ab00a3..9d6cf91 100644 --- a/ui/gtk/toolkit.c +++ b/ui/gtk/toolkit.c @@ -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); }