diff --git a/crates/breadcrumbs2/src/breadcrumbs.rs b/crates/breadcrumbs2/src/breadcrumbs.rs index db26b85e9d9a1a4707363b2bc5f49e2c48443529..7d9055cbf1921e02d100ba17f9ed55504e7e71db 100644 --- a/crates/breadcrumbs2/src/breadcrumbs.rs +++ b/crates/breadcrumbs2/src/breadcrumbs.rs @@ -1,6 +1,6 @@ use gpui::{ - div, Div, Element, EventEmitter, InteractiveElement, IntoElement, ParentElement, Render, - Stateful, StatefulInteractiveElement, StyledText, Subscription, ViewContext, WeakView, + Div, Element, EventEmitter, InteractiveElement, IntoElement, ParentElement, Render, Stateful, + StatefulInteractiveElement, Styled, StyledText, Subscription, ViewContext, WeakView, }; use itertools::Itertools; use theme::ActiveTheme; @@ -18,7 +18,7 @@ pub struct Breadcrumbs { pane_focused: bool, active_item: Option>, subscription: Option, - workspace: WeakView, + _workspace: WeakView, } impl Breadcrumbs { @@ -27,7 +27,7 @@ impl Breadcrumbs { pane_focused: false, active_item: Default::default(), subscription: Default::default(), - workspace: workspace.weak_handle(), + _workspace: workspace.weak_handle(), } } } @@ -39,45 +39,44 @@ impl Render for Breadcrumbs { type Element = Stateful
; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { - let id = "breadcrumbs"; - let default_style = cx.text_style(); + let div = h_stack().id("breadcrumbs").bg(gpui::red()); let active_item = match &self.active_item { Some(active_item) => active_item, - None => return div().id(id), + None => return div, }; let not_editor = active_item.downcast::().is_none(); let breadcrumbs = match active_item.breadcrumbs(cx.theme(), cx) { Some(breadcrumbs) => breadcrumbs, - None => return div().id(id), + None => return div, } .into_iter() .map(|breadcrumb| { StyledText::new(breadcrumb.text) - .with_highlights(&default_style, breadcrumb.highlights.unwrap_or_default()) + .with_highlights(&cx.text_style(), breadcrumb.highlights.unwrap_or_default()) .into_any() }); - let crumbs = h_stack().children(Itertools::intersperse_with(breadcrumbs, || { + let crumbs = div.children(Itertools::intersperse_with(breadcrumbs, || { Label::new(" › ").into_any_element() })); if not_editor || !self.pane_focused { - return crumbs.id(id); + return crumbs; } - let this = cx.view().downgrade(); - crumbs.id(id).on_click(move |_, cx| { - this.update(cx, |this, cx| { - if let Some(workspace) = this.workspace.upgrade() { - workspace.update(cx, |_workspace, _cx| { - todo!("outline::toggle"); - // outline::toggle(workspace, &Default::default(), cx) - }) - } - }) - .ok(); + // let this = cx.view().downgrade(); + crumbs.on_click(move |_, _cx| { + todo!("outline::toggle"); + // this.update(cx, |this, cx| { + // if let Some(workspace) = this.workspace.upgrade() { + // workspace.update(cx, |_workspace, _cx| { + // outline::toggle(workspace, &Default::default(), cx) + // }) + // } + // }) + // .ok(); }) } } diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index 8e03d00cd710e553d41938a4b9b8cdf334b2a55d..f97d5a01257cbc45dcafef573e198e9326452afb 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -7,9 +7,9 @@ use crate::{ use anyhow::Result; use collections::{HashMap, HashSet, VecDeque}; use gpui::{ - actions, prelude::*, Action, AppContext, AsyncWindowContext, Div, EntityId, EventEmitter, - FocusHandle, Focusable, FocusableView, Model, Pixels, Point, PromptLevel, Render, Task, View, - ViewContext, VisualContext, WeakView, WindowContext, + actions, prelude::*, Action, AnyWeakView, AppContext, AsyncWindowContext, Div, EntityId, + EventEmitter, FocusHandle, Focusable, FocusableView, Model, Pixels, Point, PromptLevel, Render, + Task, View, ViewContext, VisualContext, WeakView, WindowContext, }; use parking_lot::Mutex; use project2::{Project, ProjectEntryId, ProjectPath}; @@ -143,13 +143,18 @@ impl fmt::Debug for Event { } } +struct FocusedView { + view: AnyWeakView, + focus_handle: FocusHandle, +} + pub struct Pane { focus_handle: FocusHandle, items: Vec>, activation_history: Vec, zoomed: bool, active_item_index: usize, - // last_focused_view_by_item: HashMap, + last_focused_view_by_item: HashMap, autoscroll: bool, nav_history: NavHistory, toolbar: View, @@ -306,7 +311,7 @@ impl Pane { activation_history: Vec::new(), zoomed: false, active_item_index: 0, - // last_focused_view_by_item: Default::default(), + last_focused_view_by_item: Default::default(), autoscroll: false, nav_history: NavHistory(Arc::new(Mutex::new(NavHistoryState { mode: NavigationMode::Normal, @@ -395,6 +400,53 @@ impl Pane { self.focus_handle.contains_focused(cx) } + fn focus_in(&mut self, cx: &mut ViewContext) { + println!("focus_in"); + + if !self.has_focus(cx) { + cx.emit(Event::Focus); + cx.notify(); + } + + self.toolbar.update(cx, |toolbar, cx| { + toolbar.focus_changed(true, cx); + }); + + if let Some(active_item) = self.active_item() { + if self.focus_handle.is_focused(cx) { + // Pane was focused directly. We need to either focus a view inside the active item, + // or focus the active item itself + if let Some(weak_last_focused_view) = + self.last_focused_view_by_item.get(&active_item.item_id()) + { + weak_last_focused_view.focus(cx); + // if let Some(last_focused_view) = weak_last_focused_view.upgrade() { + // last_focused_view.cx.focus(&last_focused_view); + // return; + // } else { + // self.last_focused_view_by_item.remove(&active_item.id()); + // } + } + + active_item.focus_handle(cx).focus(cx); + // todo!() Do this once we have tab bar context menu + // } else if !self.tab_bar_context_menu.handle.is_focused() { + } else if let Some(focused) = cx.focused() { + self.last_focused_view_by_item + .insert(active_item.item_id(), focused); + } + } + } + + fn focus_out(&mut self, cx: &mut ViewContext) { + println!("focus_out"); + + self.toolbar.update(cx, |toolbar, cx| { + toolbar.focus_changed(false, cx); + }); + cx.notify(); + } + pub fn active_item_index(&self) -> usize { self.active_item_index } @@ -1936,9 +1988,23 @@ impl Render for Pane { type Element = Focusable
; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + let this = cx.view().downgrade(); + v_stack() .key_context("Pane") .track_focus(&self.focus_handle) + .on_focus_in({ + let this = this.clone(); + move |event, cx| { + this.update(cx, |this, cx| this.focus_in(cx)).ok(); + } + }) + .on_focus_out({ + let this = this.clone(); + move |event, cx| { + this.update(cx, |this, cx| this.focus_out(cx)).ok(); + } + }) .on_action(cx.listener(|pane: &mut Pane, _: &SplitLeft, cx| { pane.split(SplitDirection::Left, cx) })) diff --git a/crates/workspace2/src/toolbar.rs b/crates/workspace2/src/toolbar.rs index 616d70a5a5913d6df346d78adf9c00b906fc5e86..81ad2ab69ec6a9231c75fbd4a130f33e618d5e89 100644 --- a/crates/workspace2/src/toolbar.rs +++ b/crates/workspace2/src/toolbar.rs @@ -289,6 +289,7 @@ impl ToolbarItemViewHandle for View { } fn focus_changed(&mut self, pane_focused: bool, cx: &mut WindowContext) { + println!("focus changed, pane_focused: {pane_focused}"); self.update(cx, |this, cx| { this.pane_focus_update(pane_focused, cx); cx.notify();