From 806c6dffe8e5f469b32eb6506ba5976ec560a997 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Tue, 25 Feb 2025 12:00:43 +0800 Subject: [PATCH] tiles: Add `active_panel` method to Tiles. (#656) --- crates/ui/src/dock/tiles.rs | 57 +++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/crates/ui/src/dock/tiles.rs b/crates/ui/src/dock/tiles.rs index 89172091..6f7b2fb1 100644 --- a/crates/ui/src/dock/tiles.rs +++ b/crates/ui/src/dock/tiles.rs @@ -15,11 +15,11 @@ use crate::{ use super::{DockArea, Panel, PanelEvent, PanelInfo, PanelState, PanelView, TabPanel, TileMeta}; use gpui::{ - actions, canvas, div, point, prelude::FluentBuilder as _, px, size, AnyElement, App, - AppContext, Bounds, Context, DismissEvent, DragMoveEvent, Empty, EntityId, EventEmitter, - FocusHandle, Focusable, Half, InteractiveElement, IntoElement, MouseButton, MouseDownEvent, - MouseUpEvent, ParentElement, Pixels, Point, Render, ScrollHandle, Size, - StatefulInteractiveElement, Styled, WeakEntity, Window, + actions, canvas, div, point, px, size, AnyElement, App, AppContext, Bounds, Context, + DismissEvent, DragMoveEvent, Empty, EntityId, EventEmitter, FocusHandle, Focusable, Half, + InteractiveElement, IntoElement, MouseButton, MouseDownEvent, MouseUpEvent, ParentElement, + Pixels, Point, Render, ScrollHandle, Size, StatefulInteractiveElement, Styled, WeakEntity, + Window, }; actions!(tiles, [Undo, Redo,]); @@ -131,6 +131,7 @@ pub struct Tiles { dragging_initial_mouse: Point, dragging_initial_bounds: Bounds, resizing_index: Option, + active_index: Option, resizing_drag_data: Option, bounds: Bounds, history: History, @@ -190,6 +191,7 @@ impl Tiles { history: History::new().group_interval(std::time::Duration::from_millis(100)), scroll_state: Rc::new(Cell::new(ScrollbarState::default())), scroll_handle: ScrollHandle::default(), + active_index: None, } } @@ -405,7 +407,11 @@ impl Tiles { } /// Bring the panel of target_index to front, returns (old_index, new_index) if successful - fn bring_to_front(&mut self, target_index: Option) -> Option<(usize, usize)> { + fn bring_to_front( + &mut self, + target_index: Option, + cx: &mut Context, + ) -> Option<(usize, usize)> { if let Some(old_index) = target_index { if old_index < self.panels.len() { let item = self.panels.remove(old_index); @@ -419,6 +425,7 @@ impl Tiles { new_order: Some(new_index), version: 0, }); + cx.notify(); return Some((old_index, new_index)); } } @@ -479,6 +486,24 @@ impl Tiles { cx.notify(); } + /// Returns the active panel, if any. + pub fn active_panel(&self) -> Option> { + let Some(active_index) = self.active_index else { + return None; + }; + + self.panels.get(active_index).map(|item| item.panel.clone()) + } + + fn set_active_index(&mut self, index: Option, cx: &mut Context) { + if self.active_index == index { + return; + } + + self.active_index = index; + cx.notify(); + } + /// Produce a vector of AnyElement representing the three possible resize handles fn render_resize_handles( &mut self, @@ -531,7 +556,8 @@ impl Tiles { last_bounds: panel_bounds, }; this.update_resizing_drag(drag_data, window, cx); - if let Some((_, new_ix)) = this.bring_to_front(this.resizing_index) { + if let Some((_, new_ix)) = this.bring_to_front(this.resizing_index, cx) + { this.resizing_index = Some(new_ix); } } @@ -587,7 +613,8 @@ impl Tiles { last_bounds: panel_bounds, }; this.update_resizing_drag(drag_data, window, cx); - if let Some((_, new_ix)) = this.bring_to_front(this.resizing_index) { + if let Some((_, new_ix)) = this.bring_to_front(this.resizing_index, cx) + { this.resizing_index = Some(new_ix); } } @@ -645,7 +672,8 @@ impl Tiles { last_bounds: panel_bounds, }; this.update_resizing_drag(drag_data, window, cx); - if let Some((_, new_ix)) = this.bring_to_front(this.resizing_index) { + if let Some((_, new_ix)) = this.bring_to_front(this.resizing_index, cx) + { this.resizing_index = Some(new_ix); } } @@ -717,7 +745,7 @@ impl Tiles { cx.listener(move |this, event: &MouseDownEvent, window, cx| { let last_position = event.position; this.update_initial_position(last_position, window, cx); - if let Some((_, new_ix)) = this.bring_to_front(this.dragging_index) { + if let Some((_, new_ix)) = this.bring_to_front(this.dragging_index, cx) { this.dragging_index = Some(new_ix); } }), @@ -780,10 +808,15 @@ impl Tiles { .h(item.bounds.size.height + px(1.)) .overflow_hidden() .rounded(cx.theme().radius) - .when(cx.theme().tile_shadow, |this| this.shadow_md()) .child(h_flex().size_full().child(panel_view)) .children(self.render_resize_handles(window, cx, entity_id, &item, &is_occluded)) .child(self.render_drag_bar(window, cx, entity_id, &item, &is_occluded)) + .on_mouse_up( + MouseButton::Left, + cx.listener(move |this, _, _, cx| { + this.set_active_index(Some(ix), cx); + }), + ) } /// Handle the mouse up event to finalize drag or resize operations @@ -927,7 +960,7 @@ impl Render for Tiles { if this.resizing_index.is_none() && this.dragging_index.is_none() { let position = event.position; if let Some((index, _)) = this.find_at_position(position) { - this.bring_to_front(Some(index)); + this.bring_to_front(Some(index), cx); cx.notify(); } }