pub text: UiText,
#[bind("note_info")]
- pub info: UiString
+ pub info: UiString,
+
+ #[bind("note_attachments")]
+ pub attachments: UiList<entity::attachment::Model>
}
#[ui_actions]
title: Default::default(),
text: Default::default(),
info: Default::default(),
+ attachments: Default::default()
}
}
});
}
+ pub fn load_attachments(&mut self) {
+ let NoteId::Id(note_id) = self.id else {
+ return;
+ };
+
+ let Some(doc) = self.doc.get_doc() else {
+ return;
+ };
+
+ let proxy = doc.doc_proxy();
+ self.backend.get_note_attachments(note_id, move|result|{
+ proxy.call_mainthread(move |_doc, note|{
+ match result {
+ Ok(attachments) => {
+ note.attachments.data_mut().clear();
+ note.attachments.data_mut().extend(attachments);
+ note.attachments.update();
+ },
+ Err(e) => {
+ println!("Cannot get note attachments: {}", e);
+ }
+ }
+ });
+ });
+ }
+
pub fn update_title(&mut self, s: &str, notify: bool) {
let title = match generate_title(s) {
Some(result) => {
println!("note changed by {}", _from);
self.load_content();
+ self.load_attachments();
}
/// Event before the text is changed: detect if the change affects the title
use std::any::Any;
use backend::backend::{BackendHandle, BroadcastMessage, NoteId};
-use ui_rs::{action, button, grid, hbox, imageviewer, label, sourcelist, tableview, tabview, textarea, textfield, ui_actions, webview, UiModel};
+use ui_rs::{action, button, grid, hbox, imageviewer, label, scrolledwindow, sourcelist, tableview, tabview, textarea, textfield, ui_actions, webview, UiModel};
use ui_rs::ui::*;
use crate::{App, AppStates};
use entity::collection::{CollectionType, Model as Collection, Node};
+use ui_rs::ui::widget::Widget;
use crate::newnotebook::new_notebook_dialog;
use crate::notebook::{notelist_getvalue, Notebook, NotebookItem};
button!(obj, label = "Close", action = "note_title_close");
});
hbox!(obj, visibility_states = &[AppStates::NoteHasAttachments], margin = 10, spacing = 4, |obj|{
-
+ let mut w = scrolledwindow!(obj, |obj|{
+ obj.itemlist::<entity::attachment::Model>()
+ .varname("note_attachments")
+ .create();
+ });
+ w.set_size(-1, 120);
});
let textarea = textarea!(obj, fill = true, varname = "note_text", onchange_action = "note_text_change", ontextchanged_action = "note_text_changed");
obj.ctx.add_action_untyped("textarea_focus", move|_event|{
}};
}
+#[macro_export]
+macro_rules! itemlist {
+ ($parent:expr, $($tt:tt)*) => {
+ $crate::widget!($parent, itemlist, $($tt)*)
+ };
+}
pub struct Container {
ptr: *mut c_void
}
}
}
+impl<T> toolkit::UiObject<T> {
+ pub fn itemlist<'a, E>(&'a mut self) -> ItemListContainerBuilder<'a, T, E> {
+ unsafe {
+ let args = ui_itemlist_container_args_new();
+ ItemListContainerBuilder {
+ args: args,
+ obj: self,
+ _marker: PhantomData
+ }
+ }
+ }
+}
+
/* -------------------------------- ItemList Container -------------------------------- */
type CreateUiFunc = extern "C" fn(obj: *mut ffi::UiObject, list: *mut ffi::UiList, row: c_int, elm: *mut c_void, userdata: *mut c_void);
}
impl<'a, T, C> ItemListContainerBuilder<'a, T, C> {
- pub fn create<F>(&mut self, create_ui: F) -> Container
- where F: FnOnce(&mut toolkit::UiObject<T>) {
+ pub fn create(&mut self) -> Container {
let widget_ptr = unsafe { ui_itemlist_create(self.obj.ptr, self.args) };
- create_ui(self.obj);
- unsafe {
- ui_container_begin_close(self.obj.ptr);
- ui_container_finish(self.obj.ptr);
- }
Container {
ptr: widget_ptr,
}
#![allow(dead_code)]
use crate::ui::ffi::{UiObject, UiListArgs, UiCallback, UiList, UiSourceListArgs};
-use crate::ui::{event, ffi, toolkit, ui_list_get, ui_list_get_data, Button, EventWrapper};
+use crate::ui::{event, ffi, toolkit, ui_list_get, ui_list_get_data, Button, EventWrapper, ItemListContainerBuilder};
use std::ffi::{c_char, c_int, c_void};
use std::ffi::CString;
use std::marker::PhantomData;
mod window;
mod button;
mod container;
-mod widget;
+pub mod widget;
mod text;
pub mod event;
pub mod list;