From 89d234a4d57167e6e29138c1db39f8a7ede41ac4 Mon Sep 17 00:00:00 2001 From: Benign X <1341398182@qq.com> Date: Sun, 1 Dec 2024 23:37:17 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8(ImageShower):=20add=20file=20drag=20a?= =?UTF-8?q?nd=20drop=20functionality?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This update introduces the ability to drag and drop files into the image shower, displaying information about the dropped files and handling their data. The new `ui_file_drag_and_drop` method manages the UI for this feature, including visual feedback during the drag operation and a window to show the details of the dropped files. Signed-off-by: Benign X <1341398182@qq.com> --- src/image_shower.rs | 84 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/src/image_shower.rs b/src/image_shower.rs index 7521293..915dc14 100644 --- a/src/image_shower.rs +++ b/src/image_shower.rs @@ -39,6 +39,8 @@ struct MyEguiApp { height: u32, image_data: Option>, + dropped_files: Vec, + context: AppContext, } @@ -75,6 +77,8 @@ impl MyEguiApp { height, image_data, + dropped_files: Default::default(), + context, } } @@ -196,9 +200,89 @@ impl eframe::App for MyEguiApp { ); } }); + + self.ui_file_drag_and_drop(ctx); } fn save(&mut self, storage: &mut dyn eframe::Storage) { eframe::set_value(storage, eframe::APP_KEY, &self.context); } } + +impl MyEguiApp { + fn ui_file_drag_and_drop(&mut self, ctx: &egui::Context) { + use std::fmt::Write as _; + + if !ctx.input(|i| i.raw.hovered_files.is_empty()) { + let text = ctx.input(|i| { + let mut text = "Dropping files:\n".to_owned(); + for file in &i.raw.hovered_files { + if let Some(path) = &file.path { + write!(text, "\n{}", path.display()).ok(); + } else if !file.mime.is_empty() { + write!(text, "\n{}", file.mime).ok(); + } else { + text += "\n???"; + } + } + text + }); + + let painter = ctx.layer_painter(egui::LayerId::new( + egui::Order::Foreground, + egui::Id::new("file_drop_target"), + )); + + let screen_rect = ctx.screen_rect(); + painter.rect_filled(screen_rect, 0.0, Color32::from_black_alpha(192)); + painter.text( + screen_rect.center(), + egui::Align2::CENTER_CENTER, + text, + egui::TextStyle::Heading.resolve(&ctx.style()), + Color32::WHITE, + ); + } + + // Collect dropped files: + ctx.input(|i| { + if !i.raw.dropped_files.is_empty() { + self.dropped_files = i.raw.dropped_files.clone(); + } + }); + + // Show dropped files (if any): + if !self.dropped_files.is_empty() { + let mut open = true; + egui::Window::new("Dropped files") + .open(&mut open) + .show(ctx, |ui| { + for file in &self.dropped_files { + let mut info = if let Some(path) = &file.path { + path.display().to_string() + } else if !file.name.is_empty() { + file.name.clone() + } else { + "???".to_owned() + }; + + let mut additional_info = vec![]; + if !file.mime.is_empty() { + additional_info.push(format!("type: {}", file.mime)); + } + if let Some(bytes) = &file.bytes { + additional_info.push(format!("{} bytes", bytes.len())); + } + if !additional_info.is_empty() { + info += &format!(" ({})", additional_info.join(", ")); + } + + ui.label(info); + } + }); + if !open { + self.dropped_files.clear(); + } + } + } +}