mod backend;
mod newnotebook;
mod notebook;
+mod note;
use std::env;
use entity::collection::{create_notebook_hierarchy, Node};
--- /dev/null
+use entity::note::NoteType;
+use ui_rs::{ui_actions, UiModel};
+use ui_rs::ui::*;
+
+
+#[derive(UiModel, Default)]
+pub struct Note {
+ pub note_id: i32,
+
+ #[bind("note_type")]
+ pub note_type: UiInteger,
+
+ #[bind("note_text")]
+ pub text: UiText
+}
+
+#[ui_actions]
+impl Note {
+
+
+}
\ No newline at end of file
-use ui_rs::{ui_actions, UiModel};
+use ui_rs::{action, ui_actions, UiModel};
use ui_rs::ui::*;
use entity::note::Model as Note;
#[derive(UiModel, Default)]
pub struct Notebook {
+ pub doc_ref: UiDocRef<Notebook>,
pub collection_id: i32,
+ pub selected_note: Option<UiDoc<crate::note::Note>>,
+
#[bind("notes")]
pub notes: UiList<Note>
}
}
self.notes.update();
}
+
+ #[action]
+ pub fn note_selected(&mut self, event: &ActionEvent) {
+ if let (EventType::ListSelection(s)) = event.event_type {
+ if let Some(note) = s.selected_element(self.notes.data()) {
+ // detach the current note
+ if let Some(current) = &self.selected_note {
+ self.doc_ref.get_doc().unwrap().ctx.detach(current);
+ self.selected_note = None;
+ }
+
+ // Create the new note
+ let mut note_data: crate::note::Note = Default::default();
+ // TODO: setting the text here is the right thing to do, but for some
+ // reasons it doesn't work yet. Fix this shit.
+ //note_data.text.set(note.content.as_str());
+
+ // Create the note document object
+ let note_doc = UiDoc::new2(note_data, |n,d| {
+ // TODO: remove this when toolkit is not that buggy
+ // for some reason we have to attach the doc first, before we can
+ // set the text
+ if let Some(mut nb) = self.doc_ref.get_doc() {
+ nb.ctx.attach(&d);
+ }
+
+ n.text.set(note.content.as_str());
+ });
+
+ // Attach the new note
+ if let Some(mut nb) = self.doc_ref.get_doc() {
+ nb.ctx.attach(¬e_doc);
+ self.selected_note = Some(note_doc);
+ }
+ }
+ }
+ }
}
pub fn note_getvalue<'a>(elm: &Note, col: i32, _row: i32) -> ListValue<'a> {
}
let notebook = Notebook::new(nb.collection_id);
- let doc = UiDoc::new(notebook);
+ let doc = UiDoc::new2(notebook, |notebook, doc| {
+ notebook.doc_ref = doc.doc_ref();
+ });
let proxy = doc.doc_proxy();
e.data.backend.get_notes(nb.collection_id, |result|{
proxy.call_mainthread(|nb| {
.model(&model)
.fill(true)
.getvalue(note_getvalue)
+ .onselection_action(("note_selected"))
.create();
});
b.varname("note_type");
},
|tabview| {
- tabview.tab("empty", |_obj| {});
+ //tabview.tab("empty", |_obj| {});
tabview.tab("textnote", |obj| {
obj.textarea(|b|{
b.fill(true);
+ b.varname("note_text");
});
});
});
let expanded = quote! {
#impl_block
impl UiActions for #self_ty {
- fn init_actions(&mut self, ctx: &mut UiContext) {
+ fn init_actions(&mut self, ctx: &UiContext) {
unsafe {
#(
ctx.add_action(
}
impl UiActions for NoAppData {
- fn init_actions(&mut self, _ctx: &mut UiContext) {}
+ fn init_actions(&mut self, _ctx: &UiContext) {}
}
extern "C" {
}
5 => {
let t: *mut ffi::UiText = ptr.cast();
- EventTypeData::TextValue( UiText { ptr: t } )
+ EventTypeData::TextValue( UiText::from_ptr(t) )
}
6 => {
let d: *mut ffi::UiDouble = ptr.cast();
}
self
}
+
+ pub fn onactivate_action(&mut self, action: &str) -> &mut Self {
+ let cstr = CString::new(action).unwrap();
+ unsafe {
+ ui_list_args_set_onactivate_action(self.args, cstr.as_ptr());
+ }
+ self
+ }
pub fn onselection<F>(&mut self, f: F) -> &mut Self
where F: FnMut(&mut event::Event<T>) + 'static {
self
}
+ pub fn onselection_action(&mut self, action: &str) -> &mut Self {
+ let cstr = CString::new(action).unwrap();
+ unsafe {
+ ui_list_args_set_onselection_action(self.args, cstr.as_ptr());
+ }
+ self
+ }
+
pub fn multiselection(&mut self, value: bool) -> &mut Self {
unsafe {
ui_list_args_set_multiselection(self.args, value as c_int);
}
self
}
+
+ pub fn onactivate_action(&mut self, action: &str) -> &mut Self {
+ let cstr = CString::new(action).unwrap();
+ unsafe {
+ ui_list_args_set_onactivate_action(self.args, cstr.as_ptr());
+ }
+ self
+ }
pub fn onselection<F>(&mut self, f: F) -> &mut Self
where F: FnMut(&mut event::Event<T>) + 'static {
self
}
+ pub fn onselection_action(&mut self, action: &str) -> &mut Self {
+ let cstr = CString::new(action).unwrap();
+ unsafe {
+ ui_list_args_set_onselection_action(self.args, cstr.as_ptr());
+ }
+ self
+ }
+
pub fn multiselection(&mut self, value: bool) -> &mut Self {
unsafe {
ui_list_args_set_multiselection(self.args, value as c_int);
fn ui_list_args_set_style_class(args: *mut UiListArgs, classname: *const c_char);
fn ui_list_args_set_onactivate(args: *mut UiListArgs, callback: UiCallback);
fn ui_list_args_set_onactivatedata(args: *mut UiListArgs, data: *mut c_void);
+ fn ui_list_args_set_onactivate_action(args: *mut UiListArgs, action: *const c_char);
fn ui_list_args_set_onselection(args: *mut UiListArgs, callback: UiCallback);
fn ui_list_args_set_onselectiondata(args: *mut UiListArgs, data: *mut c_void);
+ fn ui_list_args_set_onselection_action(args: *mut UiListArgs, action: *const c_char);
fn ui_list_args_set_varname(args: *mut UiListArgs, varname: *const c_char);
fn ui_list_args_set_value(args: *mut UiListArgs, ivalue: *mut UiList);
fn ui_list_args_set_model(args: *mut UiListArgs, model: *mut ffi::UiModel);
ls
}
- pub unsafe fn add_action<T, F>(&mut self, name: &str, f: F)
+ pub unsafe fn add_action<T, F>(&self, name: &str, f: F)
where F: FnMut(&mut T, &event::ActionEvent) + 'static {
// if this is a document context, use the document pointer as target
// otherwise it is a UiObject context, in that case we use the window_data as target
let doc_ptr = ui_context_document(self.ptr) as *mut T;
let target_ptr = if !doc_ptr.is_null() {
- doc_ptr
+ let doc_storage: *mut *mut T = doc_ptr.cast();
+ *doc_storage
} else {
let obj_ptr = ui_context_obj(self.ptr);
assert!(!obj_ptr.is_null());
}
pub fn new(mut data: T) -> UiDoc<T> {
+ UiDoc::new2(data, |_,_| {})
+ }
+
+ pub fn new2<F>(mut data: T, init: F) -> UiDoc<T>
+ where F: FnOnce(&mut T, &UiDoc<T>) {
unsafe {
let doc = ui_document_new(mem::size_of::<*mut T>());
let ctx = UiContext::from_ptr(ui_document_context(doc));
- data.init(&ctx);
let data_ptr = ctx.reg_box(Box::new(data)); // returns *mut T
let doc_storage: *mut *mut T = doc.cast();
*doc_storage = data_ptr;
- UiDoc::<T> { ctx: ctx, ptr: doc, _marker: PhantomData }
+ let doc_ref = &mut *data_ptr;
+ doc_ref.init(&ctx);
+ doc_ref.init_actions(&ctx);
+ let doc_handle = UiDoc::<T> { ctx: ctx, ptr: doc, _marker: PhantomData };
+ init(doc_ref, &doc_handle);
+ doc_handle
}
}
}
pub trait UiActions {
- fn init_actions(&mut self, _ctx: &mut UiContext) {}
+ fn init_actions(&mut self, _ctx: &UiContext) {}
}
pub struct UiText {
- pub ptr: *mut ffi::UiText
+ pub ptr: *mut ffi::UiText,
+ value: Option<String>
}
pub struct UiString {
};
}
+macro_rules! value_default_impl2 {
+ ($type_name:ident) => {
+ impl Default for $type_name {
+ fn default() -> Self {
+ Self { ptr: std::ptr::null_mut(), value: None }
+ }
+ }
+ };
+}
+
value_default_impl!(UiInteger);
value_default_impl!(UiDouble);
value_default_impl!(UiString);
-value_default_impl!(UiText);
+value_default_impl2!(UiText);
impl<T> Default for UiList<T> {
fn default() -> Self {
}
impl UiText {
+ pub fn from_ptr(ptr: *mut ffi::UiText) -> Self {
+ UiText { ptr, value: None }
+ }
+
pub fn init(&mut self, ctx: &UiContext, name: Option<&str>) {
let c_string = name.map(|n| CString::new(n).unwrap());
let c_str = c_string.as_ref().map_or(std::ptr::null(), |s| s.as_ptr());
unsafe {
self.ptr = ui_text_new(ctx.ptr, c_str);
}
+ if let Some(s) = self.value.take() {
+ self.set(&s);
+ }
}
pub fn get(&self) -> String {
}
pub fn set(&mut self, value: &str) {
- let cstr = CString::new(value).unwrap();
- unsafe {
- ui_text_set(self.ptr, cstr.as_ptr());
+ if self.ptr.is_null() {
+ self.value = Some(value.to_owned());
+ } else {
+ let cstr = CString::new(value).unwrap();
+ unsafe {
+ ui_text_set(self.ptr, cstr.as_ptr());
+ }
}
}
}
sel
}
+
+ pub fn selected_element<'a, T>(&self, data: &'a Vec<T>) -> Option<&'a T> {
+ unsafe {
+ let count = ui_list_selection_get_count(self.ptr);
+ if count == 1 {
+ let sel = ui_list_selection_get_rows(self.ptr);
+ let index = *sel;
+ if index >= 0 {
+ return data.get(index as usize);
+ }
+ }
+ }
+ None
+ }
}
// init view model
wdata.init(&obj.ctx);
- wdata.init_actions(&mut obj.ctx);
+ wdata.init_actions(&obj.ctx);
unsafe {
ui_update_action_bindings(obj.ctx.ptr);
}
args->onactivatedata = userdata;
}
+void ui_list_args_set_onactivate_action(UiListArgs *args, const char *action) {
+ args->onactivate_action = strdup(action);
+}
+
void ui_list_args_set_onselection(UiListArgs *args, ui_callback callback) {
args->onselection = callback;
}
args->onselectiondata = userdata;
}
+void ui_list_args_set_onselection_action(UiListArgs *args, const char *action) {
+ args->onselection_action = strdup(action);
+}
+
void ui_list_args_set_ondragstart(UiListArgs *args, ui_callback callback) {
args->ondragstart = callback;
}
args->ondragstartdata = userdata;
}
+void ui_list_args_set_ondragstart_action(UiListArgs *args, const char *action) {
+ args->ondragstart_action = strdup(action);
+}
+
void ui_list_args_set_ondragcomplete(UiListArgs *args, ui_callback callback) {
args->ondragcomplete = callback;
}
args->ondragcompletedata = userdata;
}
+void ui_list_args_set_ondragcomplete_action(UiListArgs *args, const char *action) {
+ args->ondragcomplete_action = strdup(action);
+}
+
void ui_list_args_set_ondrop(UiListArgs *args, ui_callback callback) {
args->ondrop = callback;
}
args->ondropdata = userdata;
}
+void ui_list_args_set_ondrop_action(UiListArgs *args, const char *action) {
+ args->ondrop_action = strdup(action);
+}
+
void ui_list_args_set_onsave(UiListArgs *args, ui_list_savefunc onsave) {
args->onsave = onsave;
}
free((void*)args->name);
free((void*)args->style_class);
free((void*)args->varname);
+ free((void*)args->onactivate_action);
+ free((void*)args->onselection_action);
+ free((void*)args->ondragstart_action);
+ free((void*)args->ondragcomplete_action);
+ free((void*)args->ondrop_action);
if(args->static_elements) {
for(int i=0;i<args->static_nelm;i++) {
free(args->static_elements[i]);
UIEXPORT void ui_list_args_set_getstyle_data(UiListArgs *args, void *userdata);
UIEXPORT void ui_list_args_set_onactivate(UiListArgs *args, ui_callback callback);
UIEXPORT void ui_list_args_set_onactivatedata(UiListArgs *args, void *userdata);
+UIEXPORT void ui_list_args_set_onactivate_action(UiListArgs *args, const char *action);
UIEXPORT void ui_list_args_set_onselection(UiListArgs *args, ui_callback callback);
UIEXPORT void ui_list_args_set_onselectiondata(UiListArgs *args, void *userdata);
+UIEXPORT void ui_list_args_set_onselection_action(UiListArgs *args, const char *action);
UIEXPORT void ui_list_args_set_ondragstart(UiListArgs *args, ui_callback callback);
UIEXPORT void ui_list_args_set_ondragstartdata(UiListArgs *args, void *userdata);
+UIEXPORT void ui_list_args_set_ondragstart_action(UiListArgs *args, const char *action);
UIEXPORT void ui_list_args_set_ondragcomplete(UiListArgs *args, ui_callback callback);
UIEXPORT void ui_list_args_set_ondragcompletedata(UiListArgs *args, void *userdata);
+UIEXPORT void ui_list_args_set_ondragcomplete_action(UiListArgs *args, const char *action);
UIEXPORT void ui_list_args_set_ondrop(UiListArgs *args, ui_callback callback);
UIEXPORT void ui_list_args_set_ondropdata(UiListArgs *args, void *userdata);
+UIEXPORT void ui_list_args_set_ondrop_action(UiListArgs *args, const char *action);
UIEXPORT void ui_list_args_set_onsave(UiListArgs *args, ui_list_savefunc onsave);
UIEXPORT void ui_list_args_set_onsavedata(UiListArgs *args, void *userdata);
UIEXPORT void ui_list_args_set_multiselection(UiListArgs *args, UiBool multiselection);
UiDoc *document = cxCalloc(a, sizeof(UiDoc) + size, 1);
document->ctx = ctx;
- ctx->self_doc = document;
- return &document->doc;
+ ctx->self_doc = &document->doc;
+ return ctx->self_doc;
}
void ui_document_destroy(void *doc) {
#include "../common/context.h"
#include "../common/object.h"
+#include "../common/action.h"
#include "container.h"
#include <cx/array_list.h>
tableview->multiselection = args->multiselection;
tableview->onactivate = args->onactivate;
tableview->onactivatedata = args->onactivatedata;
+ tableview->onactivate_action = args->onactivate_action ? strdup(args->onactivate_action) : NULL;
tableview->onselection = args->onselection;
tableview->onselectiondata = args->onselectiondata;
+ tableview->onselection_action = args->onselection_action ? strdup(args->onselection_action) : NULL;
tableview->ondragstart = args->ondragstart;
tableview->ondragstartdata = args->ondragstartdata;
+ tableview->ondragstart_action = args->ondragstart_action ? strdup(args->ondragstart_action) : NULL;
tableview->ondragcomplete = args->ondragcomplete;
tableview->ondragcompletedata = args->ondragcompletedata;
+ tableview->ondragcomplete_action = args->ondragcomplete_action ? strdup(args->ondragcomplete_action) : NULL;
tableview->ondrop = args->ondrop;
tableview->ondropdata = args->ondropdata;
+ tableview->ondrop_action = args->ondrop_action ? strdup(args->ondrop_action) : NULL;
tableview->selection.count = 0;
tableview->selection.rows = NULL;
tableview->current_row = -1;
}
// event handling
- if(args->onactivate) {
+ if(args->onactivate || args->onactivate_action) {
// columnview and listview can use the same callback function, because
// the first parameter (which is technically a different pointer type)
// is ignored
return sel;
}
-static void listview_event(ui_callback cb, void *cbdata, UiListView *view) {
+static void listview_event(ui_callback cb, void *cbdata, const char *action, UiListView *view) {
UiEvent event;
event.obj = view->obj;
event.document = event.obj->ctx->document;
if(cb) {
cb(&event, cbdata);
}
+
+ if(action) {
+ uic_action_callback(&event, action);
+ }
}
static void listview_update_selection(UiListView *view) {
if(view->selection.count == 0) {
listview_update_selection(view);
}
- listview_event(view->onactivate, view->onactivatedata, view);
+ listview_event(view->onactivate, view->onactivatedata, view->onactivate_action, view);
}
void ui_listview_selection_changed(GtkSelectionModel* self, guint position, guint n_items, gpointer userdata) {
UiListView *view = userdata;
listview_update_selection(view);
if(ui_selection_events_is_enabled()) {
- listview_event(view->onselection, view->onselectiondata, view);
+ listview_event(view->onselection, view->onselectiondata, view->onselection_action, view);
}
}
*/
void ui_listview_destroy(GtkWidget *w, UiListView *v) {
+ free(v->onactivate_action);
+ free(v->onselection_action);
+ free(v->ondragstart_action);
+ free(v->ondragcomplete_action);
+ free(v->ondrop_action);
//gtk_tree_view_set_model(GTK_TREE_VIEW(w), NULL);
if(v->var) {
ui_destroy_boundvar(v->obj->ctx, v->var);
#endif
ui_callback onactivate;
void *onactivatedata;
+ char *onactivate_action;
ui_callback onselection;
void *onselectiondata;
+ char *onselection_action;
ui_callback ondragstart;
void *ondragstartdata;
+ char *ondragstart_action;
ui_callback ondragcomplete;
void *ondragcompletedata;
+ char *ondragcomplete_action;
ui_callback ondrop;
void *ondropdata;
+ char *ondrop_action;
ui_list_savefunc onsave;
void *onsavedata;
UiListSelection selection;
CxIterator iter = cxListIterator(group->callbacks);
cx_foreach(UiCallbackData *, cb, iter) {
- event.intval = intval == iter.index;
+ event.intval = intval-1 == iter.index;
if(cb->callback) {
cb->callback(&event, cb->userdata);
}
cxListAdd(group->callbacks, &cb);
- cxmutstr action_name = cx_asprintf("win.%s::%d", i->varname, (int)item_index);
+ cxmutstr action_name = cx_asprintf("win.%s::%d", i->varname, (int)item_index+1);
g_menu_append(parent, i->label, action_name.ptr);
free(action_name.ptr);
}
#endif
return TRUE;
} else {
+ // this cleans up any widget references from the context
uic_context_prepare_close(obj->ctx);
+ ui_window_widget_destroy(obj);
return FALSE;
}
}
void *getstyledata;
ui_callback onactivate;
void *onactivatedata;
+ const char *onactivate_action;
ui_callback onselection;
void *onselectiondata;
+ const char *onselection_action;
ui_callback ondragstart;
void *ondragstartdata;
+ const char *ondragstart_action;
ui_callback ondragcomplete;
void *ondragcompletedata;
+ const char *ondragcomplete_action;
ui_callback ondrop;
void *ondropdata;
+ const char *ondrop_action;
UiBool multiselection;
UiBool hide_header;
UiMenuBuilder *contextmenu;
#include <gtk/gtk.h>
#define UIWIDGET GtkWidget*
+#define UIWINDOW void*
#if UI_GTK2 || UI_GTK3
#define UIMENU GtkMenu*
#include <Xm/XmAll.h>
#define UIWIDGET Widget
+#define UIWINDOW void*
#define UIMENU Widget
#define UIWINDOW UiWidget*
#define UIMENU void*
+#else
+
+#define UI_GENERIC
+#define UIWIDGET void*
+#define UIWINDOW void*
+#define UIMENU void*
+
#endif
#ifndef TRUE
*/
UIWIDGET widget;
-#if defined(UI_COCOA) || defined(UI_WINUI)
/*
* native window object
*/
UIWINDOW wobj;
-#endif
/*
* user window data
/*
* container list
- * TODO: remove old UiContainer and rename UiContainerX to UiContainer
*/
UiContainer *container_begin;
UiContainer *container_end;
const char *style_class;
} UiWidgetArgs;
+#ifndef UI_GENERIC
+
#ifdef UI_GTK
typedef UIWIDGET (*ui_createwidget_func)(UiObject *obj, UiWidgetArgs *args, void *userdata);
#elif defined(UI_QT)
#define ui_customwidget(obj, create_widget, userdata, ...) ui_customwidget_create(obj, create_widget, userdata, &(UiWidgetArgs) { __VA_ARGS__ })
+#endif
UIEXPORT UIWIDGET ui_separator_create(UiObject *obj, UiWidgetArgs *args);