From 04545c0dd46a8c735711fed820e5bbbbc1a45dba Mon Sep 17 00:00:00 2001 From: tk Date: Fri, 8 Nov 2024 21:17:46 +0800 Subject: [PATCH] use the "files" example as a crate, and add the "files" example to widget-gallery (#677) * add animation example to widget-gallery * add draggable example to widget-gallery * add dropped file example to widget-gallery * format * add files example to widget-gallery * keep the "files" example, and use it as a crate --- examples/files/Cargo.toml | 2 +- examples/files/src/files.rs | 115 +++++++++++++++++++++++ examples/files/src/lib.rs | 2 + examples/files/src/main.rs | 98 +------------------ examples/widget-gallery/Cargo.toml | 3 +- examples/widget-gallery/src/draggable.rs | 23 +++-- examples/widget-gallery/src/main.rs | 63 +++++++++---- 7 files changed, 180 insertions(+), 126 deletions(-) create mode 100644 examples/files/src/files.rs create mode 100644 examples/files/src/lib.rs diff --git a/examples/files/Cargo.toml b/examples/files/Cargo.toml index 9e1bb7a2..970ea3d1 100644 --- a/examples/files/Cargo.toml +++ b/examples/files/Cargo.toml @@ -5,4 +5,4 @@ edition = "2021" [dependencies] im.workspace = true -floem = { path = "../..", features = ["rfd-async-std"] } +floem = { path = "../.." , features = ["rfd-async-std"] } diff --git a/examples/files/src/files.rs b/examples/files/src/files.rs new file mode 100644 index 00000000..e10d2e32 --- /dev/null +++ b/examples/files/src/files.rs @@ -0,0 +1,115 @@ +use floem::{ + action::{open_file, save_as}, + file::{FileDialogOptions, FileInfo, FileSpec}, + reactive::{create_rw_signal, SignalGet, SignalUpdate}, + text::Weight, + views::{button, h_stack, label, v_stack, Decorators}, + IntoView, +}; + +pub fn files_view() -> impl IntoView { + let files = create_rw_signal("".to_string()); + let view = h_stack(( + button("Select file").on_click_cont(move |_| { + open_file( + FileDialogOptions::new() + .force_starting_directory("/") + .title("Select file") + .allowed_types(vec![FileSpec { + name: "text", + extensions: &["txt", "rs", "md"], + }]), + move |file_info| { + if let Some(file) = file_info { + println!("Selected file: {:?}", file.path); + files.set(display_files(file)); + } + }, + ); + }), + button("Select multiple files").on_click_cont(move |_| { + open_file( + FileDialogOptions::new() + .multi_selection() + .title("Select file") + .allowed_types(vec![FileSpec { + name: "text", + extensions: &["txt", "rs", "md"], + }]), + move |file_info| { + if let Some(file) = file_info { + println!("Selected file: {:?}", file.path); + files.set(display_files(file)); + } + }, + ); + }), + button("Select folder").on_click_cont(move |_| { + open_file( + FileDialogOptions::new() + .select_directories() + .title("Select Folder"), + move |file_info| { + if let Some(file) = file_info { + println!("Selected folder: {:?}", file.path); + files.set(display_files(file)); + } + }, + ); + }), + button("Select multiple folder").on_click_cont(move |_| { + open_file( + FileDialogOptions::new() + .select_directories() + .multi_selection() + .title("Select multiple Folder"), + move |file_info| { + if let Some(file) = file_info { + println!("Selected folder: {:?}", file.path); + files.set(display_files(file)); + } + }, + ); + }), + button("Save file").on_click_cont(move |_| { + save_as( + FileDialogOptions::new() + .default_name("floem.file") + .title("Save file"), + move |file_info| { + if let Some(file) = file_info { + println!("Save file to: {:?}", file.path); + files.set(display_files(file)); + } + }, + ); + }), + )) + .style(|s| s.justify_center()); + + v_stack(( + view, + h_stack(( + "Path(s): ".style(|s| s.font_weight(Weight::BOLD)), + label(move || files.get()), + )), + )) + .style(|s| { + s.row_gap(5) + .width_full() + .height_full() + .items_center() + .justify_center() + }) +} + +fn display_files(file: FileInfo) -> String { + let paths: Vec<&str> = file + .path + .iter() + .map(|p| p.to_str()) + .filter(|p| p.is_some()) + .map(|p| p.unwrap()) + .collect(); + paths.join("\n") +} diff --git a/examples/files/src/lib.rs b/examples/files/src/lib.rs new file mode 100644 index 00000000..dfe01acc --- /dev/null +++ b/examples/files/src/lib.rs @@ -0,0 +1,2 @@ +pub mod files; +pub use files::*; diff --git a/examples/files/src/main.rs b/examples/files/src/main.rs index 929d3287..5dc078a3 100644 --- a/examples/files/src/main.rs +++ b/examples/files/src/main.rs @@ -1,99 +1,5 @@ -use floem::{ - action::{open_file, save_as}, - file::{FileDialogOptions, FileSpec}, - keyboard::{Key, NamedKey}, - views::{button, h_stack, Decorators}, - IntoView, View, -}; - -fn app_view() -> impl IntoView { - let view = h_stack(( - button("Select file").on_click_cont(|_| { - open_file( - FileDialogOptions::new() - .force_starting_directory("/") - .title("Select file") - .allowed_types(vec![FileSpec { - name: "text", - extensions: &["txt", "rs", "md"], - }]), - move |file_info| { - if let Some(file) = file_info { - println!("Selected file: {:?}", file.path); - } - }, - ); - }), - button("Select multiple files").on_click_cont(|_| { - open_file( - FileDialogOptions::new() - .multi_selection() - .title("Select file") - .allowed_types(vec![FileSpec { - name: "text", - extensions: &["txt", "rs", "md"], - }]), - move |file_info| { - if let Some(file) = file_info { - println!("Selected file: {:?}", file.path); - } - }, - ); - }), - button("Select folder").on_click_cont(|_| { - open_file( - FileDialogOptions::new() - .select_directories() - .title("Select Folder"), - move |file_info| { - if let Some(file) = file_info { - println!("Selected folder: {:?}", file.path); - } - }, - ); - }), - button("Select multiple folder").on_click_cont(|_| { - open_file( - FileDialogOptions::new() - .select_directories() - .multi_selection() - .title("Select multiple Folder"), - move |file_info| { - if let Some(file) = file_info { - println!("Selected folder: {:?}", file.path); - } - }, - ); - }), - button("Save file").on_click_cont(|_| { - save_as( - FileDialogOptions::new() - .default_name("floem.file") - .title("Save file"), - move |file_info| { - if let Some(file) = file_info { - println!("Save file to: {:?}", file.path); - } - }, - ); - }), - )) - .style(|s| { - s.row_gap(5) - .width_full() - .height_full() - .items_center() - .justify_center() - }); - - let id = view.id(); - view.on_key_up( - Key::Named(NamedKey::F11), - |m| m.is_empty(), - move |_| id.inspect(), - ) -} +pub mod files; fn main() { - floem::launch(app_view); + floem::launch(files::files_view); } diff --git a/examples/widget-gallery/Cargo.toml b/examples/widget-gallery/Cargo.toml index 8d1045e1..57435081 100644 --- a/examples/widget-gallery/Cargo.toml +++ b/examples/widget-gallery/Cargo.toml @@ -5,5 +5,6 @@ edition = "2021" [dependencies] im.workspace = true -floem = { path = "../.." } +floem = { path = "../.." , features = ["rfd-async-std"] } strum = { version = "0.25.0", features = ["derive"] } +files = { path = "../files/" } diff --git a/examples/widget-gallery/src/draggable.rs b/examples/widget-gallery/src/draggable.rs index 6ec67084..9a9041f1 100644 --- a/examples/widget-gallery/src/draggable.rs +++ b/examples/widget-gallery/src/draggable.rs @@ -1,7 +1,10 @@ use floem::{ keyboard::{Key, NamedKey}, - prelude::*, + peniko::Color, + reactive::{create_rw_signal, RwSignal, SignalGet, SignalUpdate}, style::CursorStyle, + views::{dyn_stack, label, Decorators}, + IntoView, View, }; fn sortable_item( @@ -32,7 +35,7 @@ fn sortable_item( floem::event::EventListener::PointerDown, |_| { /* Disable dragging for this view */ }, ), - text("drag me").style(|s| { + "drag me".style(|s| { s.selectable(false) .padding(2) .cursor(CursorStyle::RowResize) @@ -45,14 +48,16 @@ fn sortable_item( }) .on_event(floem::event::EventListener::DragOver, move |_| { if dragger_id.get_untracked() != item_id { - let dragger_pos = sortable_items.with(|items| { - items - .iter() - .position(|id| *id == dragger_id.get_untracked()) - .unwrap() - }); + let dragger_pos = sortable_items + .get() + .iter() + .position(|id| *id == dragger_id.get_untracked()) + .unwrap(); let hover_pos = sortable_items - .with(|items| items.iter().position(|id| *id == item_id).unwrap()); + .get() + .iter() + .position(|id| *id == item_id) + .unwrap(); sortable_items.update(|items| { items.remove(dragger_pos); diff --git a/examples/widget-gallery/src/main.rs b/examples/widget-gallery/src/main.rs index 0568afc5..cb497cd8 100644 --- a/examples/widget-gallery/src/main.rs +++ b/examples/widget-gallery/src/main.rs @@ -15,9 +15,12 @@ pub mod radio_buttons; pub mod rich_text; pub mod slider; +use files; use floem::{ event::{Event, EventListener, EventPropagation}, keyboard::{Key, NamedKey}, + kurbo::Size, + new_window, peniko::Color, reactive::{create_signal, SignalGet, SignalUpdate}, style::{Background, CursorStyle, Transition}, @@ -26,6 +29,7 @@ use floem::{ button, h_stack, label, scroll, stack, tab, v_stack, virtual_stack, Decorators, VirtualDirection, VirtualItemSize, }, + window::WindowConfig, IntoView, View, }; @@ -46,9 +50,31 @@ fn app_view() -> impl IntoView { "Animation", "Draggable", "DroppedFile", + "Files", ] .into_iter() .collect(); + + let create_view = |it: &str| match it { + "Label" => labels::label_view().into_any(), + "Button" => buttons::button_view().into_any(), + "Checkbox" => checkbox::checkbox_view().into_any(), + "Radio" => radio_buttons::radio_buttons_view().into_any(), + "Input" => inputs::text_input_view().into_any(), + "List" => lists::virt_list_view().into_any(), + "Menu" => context_menu::menu_view().into_any(), + "RichText" => rich_text::rich_text_view().into_any(), + "Image" => images::img_view().into_any(), + "Clipboard" => clipboard::clipboard_view().into_any(), + "Slider" => slider::slider_view().into_any(), + "Dropdown" => dropdown::dropdown_view().into_any(), + "Animation" => animation::animation_view().into_any(), + "Draggable" => draggable::draggable_view().into_any(), + "DroppedFile" => dropped_file::dropped_file_view().into_any(), + "Files" => files::files_view().into_any(), + _ => label(|| "Not implemented".to_owned()).into_any(), + }; + let (tabs, _set_tabs) = create_signal(tabs); let (active_tab, set_active_tab) = create_signal(0); @@ -136,30 +162,29 @@ fn app_view() -> impl IntoView { .action(move || id.inspect()) .style(|s| s); - let left = v_stack((list, inspector)).style(|s| s.height_full().column_gap(5.0)); + let new_window = button("Open In Window").action(move || { + let mut name = ""; + let active = active_tab.get(); + if active < tabs.get().len() { + name = tabs.get().get(active_tab.get()).unwrap_or(&name); + } + new_window( + move |_| create_view(name), + Some( + WindowConfig::default() + .size(Size::new(700.0, 400.0)) + .title(name), + ), + ); + }); + + let left = v_stack((list, new_window, inspector)).style(|s| s.height_full().column_gap(5.0)); let tab = tab( move || active_tab.get(), move || tabs.get(), |it| *it, - |it| match it { - "Label" => labels::label_view().into_any(), - "Button" => buttons::button_view().into_any(), - "Checkbox" => checkbox::checkbox_view().into_any(), - "Radio" => radio_buttons::radio_buttons_view().into_any(), - "Input" => inputs::text_input_view().into_any(), - "List" => lists::virt_list_view().into_any(), - "Menu" => context_menu::menu_view().into_any(), - "RichText" => rich_text::rich_text_view().into_any(), - "Image" => images::img_view().into_any(), - "Clipboard" => clipboard::clipboard_view().into_any(), - "Slider" => slider::slider_view().into_any(), - "Dropdown" => dropdown::dropdown_view().into_any(), - "Animation" => animation::animation_view().into_any(), - "Draggable" => draggable::draggable_view().into_any(), - "DroppedFile" => dropped_file::dropped_file_view().into_any(), - _ => label(|| "Not implemented".to_owned()).into_any(), - }, + move |it| create_view(it), ) .style(|s| s.flex_col().items_start());