diff --git a/Cargo.toml b/Cargo.toml index 616c787..90195af 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ include = ["src/**/*.rs", "Cargo.toml", "LICENSE"] [features] default = [] +viewports = [] # Enable serialization of `Tree`. serde = ["dep:serde", "egui/serde"] diff --git a/README.md b/README.md index 6afa8a3..2b2edd2 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![github](https://img.shields.io/badge/github-Adanos020/egui_dock-8da0cb?logo=github)](https://github.com/Adanos020/egui_dock) [![Crates.io](https://img.shields.io/crates/v/egui_dock)](https://crates.io/crates/egui_dock) [![docs.rs](https://img.shields.io/docsrs/egui_dock)](https://docs.rs/egui_dock/) -[![egui_version](https://img.shields.io/badge/egui-0.25-blue)](https://github.com/emilk/egui) +[![egui_version](https://img.shields.io/badge/egui-0.24-blue)](https://github.com/emilk/egui) Originally created by [@lain-dono](https://github.com/lain-dono), this library provides a docking system for `egui`. @@ -33,7 +33,7 @@ Add `egui` and `egui_dock` to your project's dependencies. ```toml [dependencies] egui = "0.25" -egui_dock = "0.10" +egui_dock = "0.11" ``` Then proceed by setting up `egui`, following its [quick start guide](https://github.com/emilk/egui#quick-start). diff --git a/src/dock_state/window_state.rs b/src/dock_state/window_state.rs index fd3d1a2..b43fcb9 100644 --- a/src/dock_state/window_state.rs +++ b/src/dock_state/window_state.rs @@ -1,5 +1,11 @@ use egui::{Id, Pos2, Rect, Vec2}; +#[cfg(feature = "viewports")] +use egui::ViewportBuilder; + +#[cfg(not(feature = "viewports"))] +use egui::Window; + /// The state of a [`Surface::Window`](crate::Surface::Window). /// /// Doubles as a handle for the surface, allowing the user to set its size and position. @@ -77,13 +83,30 @@ impl WindowState { self.next_size.take() } - //the 'static in this case means that the `open` field is always `None` - pub(crate) fn create_window(&mut self, id: Id, bounds: Rect) -> (egui::Window<'static>, bool) { + #[cfg(feature = "viewports")] + pub(crate) fn create_window(&mut self, id: Id, bounds: Rect) -> (ViewportBuilder, bool) { + let new = self.new; + let mut viewport_builder = ViewportBuilder::default() + .with_decorations(false) + .with_resizable(true) + .with_drag_and_drop(true); + + if let Some(position) = self.next_position() { + viewport_builder = viewport_builder.with_position(position); + } + if let Some(size) = self.next_size() { + viewport_builder = viewport_builder.with_inner_size(size); + } + + self.new = false; + (viewport_builder, new) + } + + // The 'static in this case means that the `open` field is always `None` + #[cfg(not(feature = "viewports"))] + pub(crate) fn create_window(&mut self, id: Id, bounds: Rect) -> (Window<'static>, bool) { let new = self.new; - let mut window_constructor = egui::Window::new("") - .id(id) - .constrain_to(bounds) - .title_bar(false); + let mut window_constructor = Window::new("").id(id).constrain_to(bounds).title_bar(false); if let Some(position) = self.next_position() { window_constructor = window_constructor.current_pos(position); diff --git a/src/widgets/dock_area/show/window_surface.rs b/src/widgets/dock_area/show/window_surface.rs index d844c55..95d2804 100644 --- a/src/widgets/dock_area/show/window_surface.rs +++ b/src/widgets/dock_area/show/window_surface.rs @@ -6,10 +6,11 @@ use egui::{ TextStyle, Ui, Vec2, Widget, }; +#[cfg(feature = "viewports")] +use egui::{CentralPanel, ViewportId}; + use crate::{ - dock_area::{state::State, tab_removal::TabRemoval}, - utils::fade_visuals, - DockArea, Node, Style, SurfaceIndex, TabViewer, + dock_area::state::State, utils::fade_visuals, DockArea, Node, Style, SurfaceIndex, TabViewer, }; impl<'tree, Tab> DockArea<'tree, Tab> { @@ -72,51 +73,87 @@ impl<'tree, Tab> DockArea<'tree, Tab> { frame.shadow.color = frame.shadow.color.linear_multiply(fade_factor); } - window - .frame(frame) - .min_width(min_window_width(&title, ui.spacing().indent)) - .show(ui.ctx(), |ui| { - //fade inner ui (if necessary) - if fade_factor != 1.0 { - fade_visuals(ui.visuals_mut(), fade_factor); + // Finds out if theres a reason for the close button to be disabled + // by iterating over the tree and finding if theres any non-closable nodes. + let disabled = !self.dock_state[surf_index] + .iter_mut() + .filter_map(|node| { + if let Node::Leaf { tabs, .. } = node { + Some( + tabs.iter_mut() + .map(|tab| tab_viewer.closeable(tab)) + .all(identity), + ) + } else { + None } + }) + .all(identity); - let collapser_id = id.with("collapser"); - let collapser_state = new.then_some(true); - let ch_res = self.show_window_body( - ui, - surf_index, - tab_viewer, - state, - fade_style, - collapser_state, - collapser_id, - title, - ); - if self.show_window_close_buttons { - // Finds out if theres a reason for the close button to be disabled - // by iterating over the tree and finding if theres any non-closable nodes. - let disabled = !self.dock_state[surf_index] - .iter_mut() - .filter_map(|node| { - if let Node::Leaf { tabs, .. } = node { - Some( - tabs.iter_mut() - .map(|tab| tab_viewer.closeable(tab)) - .all(identity), - ) - } else { - None - } - }) - .all(identity); + #[cfg(feature = "viewports")] + { + let window = window + .with_close_button(self.show_window_close_buttons && disabled) + .with_title(title.text()); + ui.ctx().show_viewport_immediate( + ViewportId::from_hash_of(id), + window, + |ctx, viewport_class| { + CentralPanel::default().show(ctx, |ui| { + if fade_factor != 1.0 { + fade_visuals(ui.visuals_mut(), fade_factor); + } - self.show_close_button(ui, &mut open, ch_res, disabled); - } - }); + let collapser_id = id.with("collapser"); + let collapser_state = new.then_some(true); + let ch_res = self.show_window_body( + ui, + surf_index, + tab_viewer, + state, + fade_style, + collapser_state, + collapser_id, + title, + ); + if self.show_window_close_buttons { + self.show_close_button(ui, &mut open, ch_res, disabled); + } + }); + }, + ) + } + #[cfg(not(feature = "viewports"))] + { + window + .frame(frame) + .min_width(min_window_width(&title, ui.spacing().indent)) + .show(ui.ctx(), |ui| { + //fade inner ui (if neccesary) + if fade_factor != 1.0 { + fade_visuals(ui.visuals_mut(), fade_factor); + } - if !open { - self.to_remove.push(TabRemoval::Window(surf_index)); + let collapser_id = id.with("collapser"); + let collapser_state = new.then_some(true); + let ch_res = self.show_window_body( + ui, + surf_index, + tab_viewer, + state, + fade_style, + collapser_state, + collapser_id, + title, + ); + if self.show_window_close_buttons { + self.show_close_button(ui, &mut open, ch_res, disabled); + } + }); + + if !open { + self.to_remove.push(TabRemoval::Window(surf_index)); + } } }