Cargo.lock 🔗
@@ -1725,6 +1725,7 @@ version = "0.1.0"
dependencies = [
"editor",
"gpui",
+ "postage",
"workspace",
]
Max Brunsfeld and Nathan Sobo created
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
Cargo.lock | 1
crates/find/Cargo.toml | 1
crates/find/src/find.rs | 71 ++++++++++++++++++++++++---
crates/workspace/src/pane.rs | 98 +++++++++++++++++++++++++++++++------
4 files changed, 144 insertions(+), 27 deletions(-)
@@ -1725,6 +1725,7 @@ version = "0.1.0"
dependencies = [
"editor",
"gpui",
+ "postage",
"workspace",
]
@@ -10,3 +10,4 @@ path = "src/find.rs"
editor = { path = "../editor" }
gpui = { path = "../gpui" }
workspace = { path = "../workspace" }
+postage = { version = "0.4.1", features = ["futures-traits"] }
@@ -1,8 +1,11 @@
+use editor::{Editor, EditorSettings};
use gpui::{
- action, color::Color, elements::*, keymap::Binding, Entity, MutableAppContext, RenderContext,
- View, ViewContext,
+ action, elements::*, keymap::Binding, Entity, MutableAppContext, RenderContext, View,
+ ViewContext, ViewHandle,
};
-use workspace::Workspace;
+use postage::watch;
+use std::sync::Arc;
+use workspace::{ItemViewHandle, Settings, Toolbar, Workspace};
action!(Deploy);
@@ -15,7 +18,11 @@ pub fn init(cx: &mut MutableAppContext) {
cx.add_action(FindBar::deploy);
}
-struct FindBar;
+struct FindBar {
+ settings: watch::Receiver<Settings>,
+ query_editor: ViewHandle<Editor>,
+ active_editor: Option<ViewHandle<Editor>>,
+}
impl Entity for FindBar {
type Event = ();
@@ -27,19 +34,65 @@ impl View for FindBar {
}
fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
- Empty::new()
+ ChildView::new(&self.query_editor)
.contained()
- .with_background_color(Color::red())
- .constrained()
- .with_height(30.)
+ .with_style(self.settings.borrow().theme.selector.input_editor.container)
.boxed()
}
}
+impl Toolbar for FindBar {
+ fn active_item_changed(
+ &mut self,
+ item: Option<Box<dyn ItemViewHandle>>,
+ cx: &mut ViewContext<Self>,
+ ) -> bool {
+ self.active_editor = item.and_then(|item| item.act_as::<Editor>(cx));
+ self.active_editor.is_some()
+ }
+}
+
impl FindBar {
+ fn new(settings: watch::Receiver<Settings>, cx: &mut ViewContext<Self>) -> Self {
+ let query_editor = cx.add_view(|cx| {
+ Editor::single_line(
+ {
+ let settings = settings.clone();
+ Arc::new(move |_| {
+ let settings = settings.borrow();
+ EditorSettings {
+ style: settings.theme.selector.input_editor.as_editor(),
+ tab_size: settings.tab_size,
+ soft_wrap: editor::SoftWrap::None,
+ }
+ })
+ },
+ cx,
+ )
+ });
+ cx.subscribe(&query_editor, Self::on_query_editor_event)
+ .detach();
+
+ Self {
+ query_editor,
+ active_editor: None,
+ settings,
+ }
+ }
+
fn deploy(workspace: &mut Workspace, _: &Deploy, cx: &mut ViewContext<Workspace>) {
+ let settings = workspace.settings();
+ workspace.active_pane().update(cx, |pane, cx| {
+ pane.show_toolbar(cx, |cx| FindBar::new(settings, cx));
+ if let Some(toolbar) = pane.active_toolbar() {
+ cx.focus(toolbar);
+ }
+ });
+ }
+
+ fn cancel(workspace: &mut Workspace, _: &Cancel, cx: &mut ViewContext<Workspace>) {
workspace
.active_pane()
- .update(cx, |pane, cx| pane.show_toolbar(cx, |_| FindBar));
+ .update(cx, |pane, cx| pane.hide_toolbar(cx));
}
}
@@ -81,14 +81,27 @@ pub struct Pane {
active_item_index: usize,
settings: watch::Receiver<Settings>,
nav_history: Rc<RefCell<NavHistory>>,
- toolbars: HashMap<TypeId, AnyViewHandle>,
- active_toolbar: Option<AnyViewHandle>,
+ toolbars: HashMap<TypeId, Box<dyn ToolbarHandle>>,
+ active_toolbar_type: Option<TypeId>,
+ active_toolbar_visible: bool,
}
-// #[derive(Debug, Eq, PartialEq)]
-// pub struct State {
-// pub tabs: Vec<TabState>,
-// }
+pub trait Toolbar: View {
+ fn active_item_changed(
+ &mut self,
+ item: Option<Box<dyn ItemViewHandle>>,
+ cx: &mut ViewContext<Self>,
+ ) -> bool;
+}
+
+trait ToolbarHandle {
+ fn active_item_changed(
+ &self,
+ item: Option<Box<dyn ItemViewHandle>>,
+ cx: &mut MutableAppContext,
+ ) -> bool;
+ fn to_any(&self) -> AnyViewHandle;
+}
pub struct ItemNavHistory {
history: Rc<RefCell<NavHistory>>,
@@ -129,7 +142,8 @@ impl Pane {
settings,
nav_history: Default::default(),
toolbars: Default::default(),
- active_toolbar: Default::default(),
+ active_toolbar_type: Default::default(),
+ active_toolbar_visible: false,
}
}
@@ -301,6 +315,7 @@ impl Pane {
if prev_active_item_ix != self.active_item_index {
self.item_views[prev_active_item_ix].1.deactivated(cx);
}
+ self.update_active_toolbar(cx);
self.focus_active_item(cx);
cx.notify();
}
@@ -354,15 +369,18 @@ impl Pane {
true
}
});
- self.active_item_index = cmp::min(
- self.active_item_index,
- self.item_views.len().saturating_sub(1),
+ self.activate_item(
+ cmp::min(
+ self.active_item_index,
+ self.item_views.len().saturating_sub(1),
+ ),
+ cx,
);
if self.item_views.is_empty() {
+ self.update_active_toolbar(cx);
cx.emit(Event::Remove);
}
- cx.notify();
}
fn focus_active_item(&mut self, cx: &mut ViewContext<Self>) {
@@ -378,16 +396,46 @@ impl Pane {
pub fn show_toolbar<F, V>(&mut self, cx: &mut ViewContext<Self>, build_toolbar: F)
where
F: FnOnce(&mut ViewContext<V>) -> V,
- V: View,
+ V: Toolbar,
{
- let handle = self
- .toolbars
- .entry(TypeId::of::<V>())
- .or_insert_with(|| cx.add_view(build_toolbar).into());
- self.active_toolbar = Some(handle.clone());
+ let type_id = TypeId::of::<V>();
+ let active_item = self.active_item();
+ self.toolbars
+ .entry(type_id)
+ .or_insert_with(|| Box::new(cx.add_view(build_toolbar)));
+ self.active_toolbar_type = Some(type_id);
+ self.active_toolbar_visible = self.toolbars[&type_id].active_item_changed(active_item, cx);
+ cx.notify();
+ }
+
+ pub fn hide_toolbar(&mut self, cx: &mut ViewContext<Self>) {
+ self.active_toolbar_type = None;
+ self.active_toolbar_visible = false;
+ self.focus_active_item(cx);
cx.notify();
}
+ pub fn active_toolbar(&self) -> Option<AnyViewHandle> {
+ let type_id = self.active_toolbar_type?;
+ let toolbar = self.toolbars.get(&type_id)?;
+ if self.active_toolbar_visible {
+ Some(toolbar.to_any())
+ } else {
+ None
+ }
+ }
+
+ fn update_active_toolbar(&mut self, cx: &mut ViewContext<Self>) {
+ if let Some(type_id) = self.active_toolbar_type {
+ if let Some(toolbar) = self.toolbars.get(&type_id) {
+ self.active_toolbar_visible = toolbar.active_item_changed(
+ Some(self.item_views[self.active_item_index].1.clone()),
+ cx,
+ );
+ }
+ }
+ }
+
fn render_tabs(&self, cx: &mut RenderContext<Self>) -> ElementBox {
let settings = self.settings.borrow();
let theme = &settings.theme;
@@ -540,7 +588,7 @@ impl View for Pane {
Flex::column()
.with_child(self.render_tabs(cx))
.with_children(
- self.active_toolbar
+ self.active_toolbar()
.as_ref()
.map(|view| ChildView::new(view).boxed()),
)
@@ -556,6 +604,20 @@ impl View for Pane {
}
}
+impl<T: Toolbar> ToolbarHandle for ViewHandle<T> {
+ fn active_item_changed(
+ &self,
+ item: Option<Box<dyn ItemViewHandle>>,
+ cx: &mut MutableAppContext,
+ ) -> bool {
+ self.update(cx, |this, cx| this.active_item_changed(item, cx))
+ }
+
+ fn to_any(&self) -> AnyViewHandle {
+ self.into()
+ }
+}
+
impl ItemNavHistory {
pub fn new<T: ItemView>(history: Rc<RefCell<NavHistory>>, item_view: &ViewHandle<T>) -> Self {
Self {