diff --git a/Cargo.lock b/Cargo.lock index 8b82293ec8f..6d6e2e64b50 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3707,6 +3707,14 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "test_viewports" +version = "0.1.0" +dependencies = [ + "eframe", + "env_logger", +] + [[package]] name = "textwrap" version = "0.16.0" @@ -4059,14 +4067,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "viewports" -version = "0.1.0" -dependencies = [ - "eframe", - "env_logger", -] - [[package]] name = "waker-fn" version = "1.1.1" diff --git a/examples/viewports/Cargo.toml b/examples/test_viewports/Cargo.toml similarity index 93% rename from examples/viewports/Cargo.toml rename to examples/test_viewports/Cargo.toml index 235eb8aa47f..a7c7606990f 100644 --- a/examples/viewports/Cargo.toml +++ b/examples/test_viewports/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "viewports" +name = "test_viewports" version = "0.1.0" authors = ["konkitoman"] license = "MIT OR Apache-2.0" diff --git a/examples/test_viewports/README.md b/examples/test_viewports/README.md new file mode 100644 index 00000000000..4f34ac3db83 --- /dev/null +++ b/examples/test_viewports/README.md @@ -0,0 +1 @@ +This is a test of the viewports feature of eframe and egui, where we show off using multiple windows. diff --git a/examples/viewports/src/main.rs b/examples/test_viewports/src/main.rs similarity index 94% rename from examples/viewports/src/main.rs rename to examples/test_viewports/src/main.rs index c8fb83d9abb..65fb1eebc66 100644 --- a/examples/viewports/src/main.rs +++ b/examples/test_viewports/src/main.rs @@ -3,6 +3,9 @@ use std::sync::Arc; use eframe::egui; use egui::{mutex::RwLock, Id, InnerResponse, ViewportBuilder, ViewportId}; +// Drag-and-drop between windows is not yet implemented, but if you wanna work on it, enable this: +pub const DRAG_AND_DROP_TEST: bool = false; + fn main() { env_logger::init(); // Use `RUST_LOG=debug` to see logs. @@ -109,7 +112,7 @@ impl eframe::App for App { ctx.set_force_embedding(force_embedding); } - generic_ui(ui, Id::new("root_viewport"), &self.top); + generic_ui(ui, &self.top); }); } } @@ -130,7 +133,7 @@ fn show_async_viewport( let mut vp_state = vp_state.write(); show_as_popup(ctx, &title, id, move |ui: &mut egui::Ui| { ui.add(egui::DragValue::new(&mut vp_state.count).prefix("Count: ")); - generic_ui(ui, id, &vp_state.children); + generic_ui(ui, &vp_state.children); }); }, ); @@ -146,82 +149,12 @@ fn show_sync_viewport(ctx: &egui::Context, vp_id: ViewportId, vp_state: &mut Vie move |ctx| { show_as_popup(ctx, &vp_state.title, id, |ui: &mut egui::Ui| { ui.add(egui::DragValue::new(&mut vp_state.count).prefix("Count: ")); - generic_ui(ui, id, &vp_state.children); + generic_ui(ui, &vp_state.children); }); }, ); } -// This is taken from crates/egui_demo_lib/src/debo/drag_and_drop.rs -fn drag_source( - ui: &mut egui::Ui, - id: egui::Id, - body: impl FnOnce(&mut egui::Ui) -> R, -) -> InnerResponse { - let is_being_dragged = ui.memory(|mem| mem.is_being_dragged(id)); - - if !is_being_dragged { - let res = ui.scope(body); - - // Check for drags: - let response = ui.interact(res.response.rect, id, egui::Sense::drag()); - if response.hovered() { - ui.ctx().set_cursor_icon(egui::CursorIcon::Grab); - } - res - } else { - ui.ctx().set_cursor_icon(egui::CursorIcon::Grabbing); - - // Paint the body to a new layer: - let layer_id = egui::LayerId::new(egui::Order::Tooltip, id); - let res = ui.with_layer_id(layer_id, body); - - if let Some(pointer_pos) = ui.ctx().pointer_interact_pos() { - let delta = pointer_pos - res.response.rect.center(); - ui.ctx().translate_layer(layer_id, delta); - } - - res - } -} - -// This is taken from crates/egui_demo_lib/src/debo/drag_and_drop.rs -fn drop_target( - ui: &mut egui::Ui, - body: impl FnOnce(&mut egui::Ui) -> R, -) -> egui::InnerResponse { - let is_being_dragged = ui.memory(|mem| mem.is_anything_being_dragged()); - - let margin = egui::Vec2::splat(ui.visuals().clip_rect_margin); // 3.0 - - let background_id = ui.painter().add(egui::Shape::Noop); - - let available_rect = ui.available_rect_before_wrap(); - let inner_rect = available_rect.shrink2(margin); - let mut content_ui = ui.child_ui(inner_rect, *ui.layout()); - let ret = body(&mut content_ui); - - let outer_rect = - egui::Rect::from_min_max(available_rect.min, content_ui.min_rect().max + margin); - let (rect, response) = ui.allocate_at_least(outer_rect.size(), egui::Sense::hover()); - - let style = if is_being_dragged && response.hovered() { - ui.visuals().widgets.active - } else { - ui.visuals().widgets.inactive - }; - - let fill = style.bg_fill; - let stroke = style.bg_stroke; - - ui.painter().set( - background_id, - egui::epaint::RectShape::new(rect, style.rounding, fill, stroke), - ); - - egui::InnerResponse::new(ret, response) -} - /// This will make the content as a popup if cannot has his own native window fn show_as_popup(ctx: &egui::Context, title: &str, id: Id, content: impl FnOnce(&mut egui::Ui)) { if ctx.viewport_id() == ctx.parent_viewport_id() { @@ -231,7 +164,9 @@ fn show_as_popup(ctx: &egui::Context, title: &str, id: Id, content: impl FnOnce( } } -fn generic_ui(ui: &mut egui::Ui, container_id: Id, children: &[Arc>]) { +fn generic_ui(ui: &mut egui::Ui, children: &[Arc>]) { + let container_id = ui.id(); + let ctx = ui.ctx().clone(); ui.label(format!( "Frame nr: {} (this increases when this viewport is being rendered)", @@ -304,7 +239,9 @@ fn generic_ui(ui: &mut egui::Ui, container_id: Id, children: &[Arc> = OnceLock::new(); let data = DATA.get_or_init(Default::default); @@ -431,3 +373,73 @@ fn drag_and_drop_test(ui: &mut egui::Ui, container_id: Id) { } }); } + +// This is taken from crates/egui_demo_lib/src/debo/drag_and_drop.rs +fn drag_source( + ui: &mut egui::Ui, + id: egui::Id, + body: impl FnOnce(&mut egui::Ui) -> R, +) -> InnerResponse { + let is_being_dragged = ui.memory(|mem| mem.is_being_dragged(id)); + + if !is_being_dragged { + let res = ui.scope(body); + + // Check for drags: + let response = ui.interact(res.response.rect, id, egui::Sense::drag()); + if response.hovered() { + ui.ctx().set_cursor_icon(egui::CursorIcon::Grab); + } + res + } else { + ui.ctx().set_cursor_icon(egui::CursorIcon::Grabbing); + + // Paint the body to a new layer: + let layer_id = egui::LayerId::new(egui::Order::Tooltip, id); + let res = ui.with_layer_id(layer_id, body); + + if let Some(pointer_pos) = ui.ctx().pointer_interact_pos() { + let delta = pointer_pos - res.response.rect.center(); + ui.ctx().translate_layer(layer_id, delta); + } + + res + } +} + +// This is taken from crates/egui_demo_lib/src/debo/drag_and_drop.rs +fn drop_target( + ui: &mut egui::Ui, + body: impl FnOnce(&mut egui::Ui) -> R, +) -> egui::InnerResponse { + let is_being_dragged = ui.memory(|mem| mem.is_anything_being_dragged()); + + let margin = egui::Vec2::splat(ui.visuals().clip_rect_margin); // 3.0 + + let background_id = ui.painter().add(egui::Shape::Noop); + + let available_rect = ui.available_rect_before_wrap(); + let inner_rect = available_rect.shrink2(margin); + let mut content_ui = ui.child_ui(inner_rect, *ui.layout()); + let ret = body(&mut content_ui); + + let outer_rect = + egui::Rect::from_min_max(available_rect.min, content_ui.min_rect().max + margin); + let (rect, response) = ui.allocate_at_least(outer_rect.size(), egui::Sense::hover()); + + let style = if is_being_dragged && response.hovered() { + ui.visuals().widgets.active + } else { + ui.visuals().widgets.inactive + }; + + let fill = style.bg_fill; + let stroke = style.bg_stroke; + + ui.painter().set( + background_id, + egui::epaint::RectShape::new(rect, style.rounding, fill, stroke), + ); + + egui::InnerResponse::new(ret, response) +}