diff --git a/examples/advanced.rs b/examples/advanced.rs index 1006b7c..a2a8bc7 100644 --- a/examples/advanced.rs +++ b/examples/advanced.rs @@ -202,7 +202,7 @@ impl Default for MyApp { let root = tiles.insert_tab_tile(tabs); - let tree = egui_tiles::Tree::new(root, tiles); + let tree = egui_tiles::Tree::new("my_app_tree", root, tiles); Self { tree, diff --git a/examples/simple.rs b/examples/simple.rs index 71e7ece..afa80ca 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -76,5 +76,5 @@ fn create_tree() -> egui_tiles::Tree { let root = tiles.insert_tab_tile(tabs); - egui_tiles::Tree::new(root, tiles) + egui_tiles::Tree::new("simple_tree", root, tiles) } diff --git a/src/container/linear.rs b/src/container/linear.rs index 623c3ec..9daca9a 100644 --- a/src/container/linear.rs +++ b/src/container/linear.rs @@ -461,7 +461,7 @@ fn linear_drop_zones( let preview_thickness = 12.0; let dragged_index = children .iter() - .position(|&child| is_being_dragged(egui_ctx, child)); + .position(|&child| is_being_dragged(egui_ctx, &tree.id, child)); let after_rect = |rect: Rect| match dir { LinearDir::Horizontal => Rect::from_min_max( diff --git a/src/container/tabs.rs b/src/container/tabs.rs index 5ee1e76..2ea5420 100644 --- a/src/container/tabs.rs +++ b/src/container/tabs.rs @@ -128,7 +128,7 @@ impl Tabs { .drag_started() { behavior.on_edit(); - ui.memory_mut(|mem| mem.set_dragged_id(tile_id.egui_id())); + ui.memory_mut(|mem| mem.set_dragged_id(tile_id.egui_id(&tree.id))); } } @@ -137,10 +137,10 @@ impl Tabs { continue; } - let is_being_dragged = is_being_dragged(ui.ctx(), child_id); + let is_being_dragged = is_being_dragged(ui.ctx(), &tree.id, child_id); let selected = self.is_active(child_id); - let id = child_id.egui_id(); + let id = child_id.egui_id(&tree.id); let response = behavior.tab_ui(&tree.tiles, ui, id, child_id, selected, is_being_dragged); diff --git a/src/lib.rs b/src/lib.rs index 91b661d..2415839 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -267,8 +267,8 @@ fn is_possible_drag(ctx: &egui::Context) -> bool { ctx.input(|input| input.pointer.is_decidedly_dragging()) } -fn is_being_dragged(ctx: &egui::Context, tile_id: TileId) -> bool { - ctx.memory(|mem| mem.is_being_dragged(tile_id.egui_id())) && is_possible_drag(ctx) +fn is_being_dragged(ctx: &egui::Context, tree_id: &egui::Id, tile_id: TileId) -> bool { + ctx.memory(|mem| mem.is_being_dragged(tile_id.egui_id(tree_id))) && is_possible_drag(ctx) } /// If this tile is currently being dragged, cover it with a semi-transparent overlay ([`Behavior::dragged_overlay_color`]). @@ -278,7 +278,7 @@ fn cover_tile_if_dragged( ui: &mut egui::Ui, tile_id: TileId, ) { - if is_being_dragged(ui.ctx(), tile_id) { + if is_being_dragged(ui.ctx(), &tree.id, tile_id) { if let Some(child_rect) = tree.tiles.try_rect(tile_id) { let overlay_color = behavior.dragged_overlay_color(ui.visuals()); ui.painter().rect_filled(child_rect, 0.0, overlay_color); diff --git a/src/tile.rs b/src/tile.rs index c13590d..114e01b 100644 --- a/src/tile.rs +++ b/src/tile.rs @@ -11,8 +11,8 @@ impl TileId { } /// Corresponding [`egui::Id`], used for dragging. - pub fn egui_id(&self) -> egui::Id { - egui::Id::new(("egui_tile", self)) + pub fn egui_id(&self, tree_id: &egui::Id) -> egui::Id { + tree_id.with(("tile", self)) } } diff --git a/src/tree.rs b/src/tree.rs index 290efdb..0c83265 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -33,16 +33,9 @@ pub struct Tree { /// All the tiles in the tree. pub tiles: Tiles, -} -impl Default for Tree { - // An empty tree - fn default() -> Self { - Self { - root: None, - tiles: Default::default(), - } - } + /// The previous id used to draw the tree. + pub(crate) id: egui::Id, } impl std::fmt::Debug for Tree { @@ -92,48 +85,58 @@ impl std::fmt::Debug for Tree { // ---------------------------------------------------------------------------- impl Tree { - pub fn empty() -> Self { - Self::default() + pub fn empty(id: impl Into) -> Self { + Self { + root: None, + tiles: Default::default(), + id: id.into(), + } } /// The most flexible constructor, allowing you to set up the tiles /// however you want. - pub fn new(root: TileId, tiles: Tiles) -> Self { + pub fn new(id: impl Into, root: TileId, tiles: Tiles) -> Self { Self { root: Some(root), tiles, + id: id.into(), } } + /// Get the id used by this Tree. + pub fn id(&self) -> egui::Id { + self.id + } + /// Create a top-level [`crate::Tabs`] container with the given panes. - pub fn new_tabs(panes: Vec) -> Self { - Self::new_container(ContainerKind::Tabs, panes) + pub fn new_tabs(id: impl Into, panes: Vec) -> Self { + Self::new_container(id, ContainerKind::Tabs, panes) } /// Create a top-level horizontal [`crate::Linear`] container with the given panes. - pub fn new_horizontal(panes: Vec) -> Self { - Self::new_container(ContainerKind::Horizontal, panes) + pub fn new_horizontal(id: impl Into, panes: Vec) -> Self { + Self::new_container(id, ContainerKind::Horizontal, panes) } /// Create a top-level vertical [`crate::Linear`] container with the given panes. - pub fn new_vertical(panes: Vec) -> Self { - Self::new_container(ContainerKind::Vertical, panes) + pub fn new_vertical(id: impl Into, panes: Vec) -> Self { + Self::new_container(id, ContainerKind::Vertical, panes) } /// Create a top-level [`crate::Grid`] container with the given panes. - pub fn new_grid(panes: Vec) -> Self { - Self::new_container(ContainerKind::Grid, panes) + pub fn new_grid(id: impl Into, panes: Vec) -> Self { + Self::new_container(id, ContainerKind::Grid, panes) } /// Create a top-level container with the given panes. - pub fn new_container(kind: ContainerKind, panes: Vec) -> Self { + pub fn new_container(id: impl Into, kind: ContainerKind, panes: Vec) -> Self { let mut tiles = Tiles::default(); let tile_ids = panes .into_iter() .map(|pane| tiles.insert_pane(pane)) .collect(); let root = tiles.insert_new(Tile::Container(Container::new(kind, tile_ids))); - Self::new(root, tiles) + Self::new(id, root, tiles) } /// Check if [`Self::root`] is [`None`]. @@ -169,6 +172,8 @@ impl Tree { /// /// The tree will use upp all the available space - nothing more, nothing less. pub fn ui(&mut self, behavior: &mut dyn Behavior, ui: &mut Ui) { + self.id = ui.id(); + self.simplify(&behavior.simplification_options()); self.gc(behavior); @@ -234,7 +239,7 @@ impl Tree { match &mut tile { Tile::Pane(pane) => { if behavior.pane_ui(&mut ui, tile_id, pane) == UiResponse::DragStarted { - ui.memory_mut(|mem| mem.set_dragged_id(tile_id.egui_id())); + ui.memory_mut(|mem| mem.set_dragged_id(tile_id.egui_id(&self.id))); } } Tile::Container(container) => { @@ -411,7 +416,7 @@ impl Tree { continue; // not allowed to drag root } - let id = tile_id.egui_id(); + let id = tile_id.egui_id(&self.id); let is_tile_being_dragged = ctx.memory(|mem| mem.is_being_dragged(id)); if is_tile_being_dragged { // Abort drags on escape: