mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-25 01:34:02 +00:00
Inform toolbars when active item changes
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
bebde782fa
commit
05e20ca72b
4 changed files with 148 additions and 31 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1725,6 +1725,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"editor",
|
"editor",
|
||||||
"gpui",
|
"gpui",
|
||||||
|
"postage",
|
||||||
"workspace",
|
"workspace",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -10,3 +10,4 @@ path = "src/find.rs"
|
||||||
editor = { path = "../editor" }
|
editor = { path = "../editor" }
|
||||||
gpui = { path = "../gpui" }
|
gpui = { path = "../gpui" }
|
||||||
workspace = { path = "../workspace" }
|
workspace = { path = "../workspace" }
|
||||||
|
postage = { version = "0.4.1", features = ["futures-traits"] }
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
|
use editor::{Editor, EditorSettings};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
action, color::Color, elements::*, keymap::Binding, Entity, MutableAppContext, RenderContext,
|
action, elements::*, keymap::Binding, Entity, MutableAppContext, RenderContext, View,
|
||||||
View, ViewContext,
|
ViewContext, ViewHandle,
|
||||||
};
|
};
|
||||||
use workspace::Workspace;
|
use postage::watch;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use workspace::{ItemViewHandle, Settings, Toolbar, Workspace};
|
||||||
|
|
||||||
action!(Deploy);
|
action!(Deploy);
|
||||||
|
|
||||||
|
@ -15,7 +18,11 @@ pub fn init(cx: &mut MutableAppContext) {
|
||||||
cx.add_action(FindBar::deploy);
|
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 {
|
impl Entity for FindBar {
|
||||||
type Event = ();
|
type Event = ();
|
||||||
|
@ -27,19 +34,65 @@ impl View for FindBar {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
|
fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
|
||||||
Empty::new()
|
ChildView::new(&self.query_editor)
|
||||||
.contained()
|
.contained()
|
||||||
.with_background_color(Color::red())
|
.with_style(self.settings.borrow().theme.selector.input_editor.container)
|
||||||
.constrained()
|
|
||||||
.with_height(30.)
|
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FindBar {
|
impl Toolbar for FindBar {
|
||||||
fn deploy(workspace: &mut Workspace, _: &Deploy, cx: &mut ViewContext<Workspace>) {
|
fn active_item_changed(
|
||||||
workspace
|
&mut self,
|
||||||
.active_pane()
|
item: Option<Box<dyn ItemViewHandle>>,
|
||||||
.update(cx, |pane, cx| pane.show_toolbar(cx, |_| FindBar));
|
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.hide_toolbar(cx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,14 +81,27 @@ pub struct Pane {
|
||||||
active_item_index: usize,
|
active_item_index: usize,
|
||||||
settings: watch::Receiver<Settings>,
|
settings: watch::Receiver<Settings>,
|
||||||
nav_history: Rc<RefCell<NavHistory>>,
|
nav_history: Rc<RefCell<NavHistory>>,
|
||||||
toolbars: HashMap<TypeId, AnyViewHandle>,
|
toolbars: HashMap<TypeId, Box<dyn ToolbarHandle>>,
|
||||||
active_toolbar: Option<AnyViewHandle>,
|
active_toolbar_type: Option<TypeId>,
|
||||||
|
active_toolbar_visible: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[derive(Debug, Eq, PartialEq)]
|
pub trait Toolbar: View {
|
||||||
// pub struct State {
|
fn active_item_changed(
|
||||||
// pub tabs: Vec<TabState>,
|
&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 {
|
pub struct ItemNavHistory {
|
||||||
history: Rc<RefCell<NavHistory>>,
|
history: Rc<RefCell<NavHistory>>,
|
||||||
|
@ -129,7 +142,8 @@ impl Pane {
|
||||||
settings,
|
settings,
|
||||||
nav_history: Default::default(),
|
nav_history: Default::default(),
|
||||||
toolbars: 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 {
|
if prev_active_item_ix != self.active_item_index {
|
||||||
self.item_views[prev_active_item_ix].1.deactivated(cx);
|
self.item_views[prev_active_item_ix].1.deactivated(cx);
|
||||||
}
|
}
|
||||||
|
self.update_active_toolbar(cx);
|
||||||
self.focus_active_item(cx);
|
self.focus_active_item(cx);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
@ -354,15 +369,18 @@ impl Pane {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.active_item_index = cmp::min(
|
self.activate_item(
|
||||||
self.active_item_index,
|
cmp::min(
|
||||||
self.item_views.len().saturating_sub(1),
|
self.active_item_index,
|
||||||
|
self.item_views.len().saturating_sub(1),
|
||||||
|
),
|
||||||
|
cx,
|
||||||
);
|
);
|
||||||
|
|
||||||
if self.item_views.is_empty() {
|
if self.item_views.is_empty() {
|
||||||
|
self.update_active_toolbar(cx);
|
||||||
cx.emit(Event::Remove);
|
cx.emit(Event::Remove);
|
||||||
}
|
}
|
||||||
cx.notify();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn focus_active_item(&mut self, cx: &mut ViewContext<Self>) {
|
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)
|
pub fn show_toolbar<F, V>(&mut self, cx: &mut ViewContext<Self>, build_toolbar: F)
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut ViewContext<V>) -> V,
|
F: FnOnce(&mut ViewContext<V>) -> V,
|
||||||
V: View,
|
V: Toolbar,
|
||||||
{
|
{
|
||||||
let handle = self
|
let type_id = TypeId::of::<V>();
|
||||||
.toolbars
|
let active_item = self.active_item();
|
||||||
.entry(TypeId::of::<V>())
|
self.toolbars
|
||||||
.or_insert_with(|| cx.add_view(build_toolbar).into());
|
.entry(type_id)
|
||||||
self.active_toolbar = Some(handle.clone());
|
.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();
|
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 {
|
fn render_tabs(&self, cx: &mut RenderContext<Self>) -> ElementBox {
|
||||||
let settings = self.settings.borrow();
|
let settings = self.settings.borrow();
|
||||||
let theme = &settings.theme;
|
let theme = &settings.theme;
|
||||||
|
@ -540,7 +588,7 @@ impl View for Pane {
|
||||||
Flex::column()
|
Flex::column()
|
||||||
.with_child(self.render_tabs(cx))
|
.with_child(self.render_tabs(cx))
|
||||||
.with_children(
|
.with_children(
|
||||||
self.active_toolbar
|
self.active_toolbar()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|view| ChildView::new(view).boxed()),
|
.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 {
|
impl ItemNavHistory {
|
||||||
pub fn new<T: ItemView>(history: Rc<RefCell<NavHistory>>, item_view: &ViewHandle<T>) -> Self {
|
pub fn new<T: ItemView>(history: Rc<RefCell<NavHistory>>, item_view: &ViewHandle<T>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
Loading…
Reference in a new issue