diff --git a/crates/search/src/buffer_search.rs b/crates/search/src/buffer_search.rs index da9ee0664b..d1560274c4 100644 --- a/crates/search/src/buffer_search.rs +++ b/crates/search/src/buffer_search.rs @@ -8,7 +8,7 @@ use gpui::{ use language::OffsetRangeExt; use project::search::SearchQuery; use std::ops::Range; -use workspace::{ItemHandle, Pane, Settings, Toolbar, Workspace}; +use workspace::{ItemHandle, Pane, Settings, ToolbarItemView}; action!(Deploy, bool); action!(Dismiss); @@ -38,7 +38,7 @@ pub fn init(cx: &mut MutableAppContext) { cx.add_action(SearchBar::select_match_on_pane); } -struct SearchBar { +pub struct SearchBar { query_editor: ViewHandle, active_editor: Option>, active_match_index: Option, @@ -66,69 +66,69 @@ impl View for SearchBar { } fn render(&mut self, cx: &mut RenderContext) -> ElementBox { - let theme = cx.global::().theme.clone(); - let editor_container = if self.query_contains_error { - theme.search.invalid_editor + if self.dismissed { + Empty::new().boxed() } else { - theme.search.editor.input.container - }; - Flex::row() - .with_child( - ChildView::new(&self.query_editor) - .contained() - .with_style(editor_container) - .aligned() - .constrained() - .with_max_width(theme.search.editor.max_width) - .boxed(), - ) - .with_child( - Flex::row() - .with_child(self.render_search_option("Case", SearchOption::CaseSensitive, cx)) - .with_child(self.render_search_option("Word", SearchOption::WholeWord, cx)) - .with_child(self.render_search_option("Regex", SearchOption::Regex, cx)) - .contained() - .with_style(theme.search.option_button_group) - .aligned() - .boxed(), - ) - .with_child( - Flex::row() - .with_child(self.render_nav_button("<", Direction::Prev, cx)) - .with_child(self.render_nav_button(">", Direction::Next, cx)) - .aligned() - .boxed(), - ) - .with_children(self.active_editor.as_ref().and_then(|editor| { - let matches = self.editors_with_matches.get(&editor.downgrade())?; - let message = if let Some(match_ix) = self.active_match_index { - format!("{}/{}", match_ix + 1, matches.len()) - } else { - "No matches".to_string() - }; - - Some( - Label::new(message, theme.search.match_index.text.clone()) + let theme = cx.global::().theme.clone(); + let editor_container = if self.query_contains_error { + theme.search.invalid_editor + } else { + theme.search.editor.container + }; + Flex::row() + .with_child( + ChildView::new(&self.query_editor) .contained() - .with_style(theme.search.match_index.container) + .with_style(editor_container) + .aligned() + .constrained() + .with_max_width(theme.search.max_editor_width) + .boxed(), + ) + .with_child( + Flex::row() + .with_child(self.render_search_option( + "Case", + SearchOption::CaseSensitive, + cx, + )) + .with_child(self.render_search_option("Word", SearchOption::WholeWord, cx)) + .with_child(self.render_search_option("Regex", SearchOption::Regex, cx)) + .contained() + .with_style(theme.search.option_button_group) .aligned() .boxed(), ) - })) - .contained() - .with_style(theme.search.container) - .constrained() - .with_height(theme.workspace.toolbar.height) - .named("search bar") + .with_child( + Flex::row() + .with_child(self.render_nav_button("<", Direction::Prev, cx)) + .with_child(self.render_nav_button(">", Direction::Next, cx)) + .aligned() + .boxed(), + ) + .with_children(self.active_editor.as_ref().and_then(|editor| { + let matches = self.editors_with_matches.get(&editor.downgrade())?; + let message = if let Some(match_ix) = self.active_match_index { + format!("{}/{}", match_ix + 1, matches.len()) + } else { + "No matches".to_string() + }; + + Some( + Label::new(message, theme.search.match_index.text.clone()) + .contained() + .with_style(theme.search.match_index.container) + .aligned() + .boxed(), + ) + })) + .named("search bar") + } } } -impl Toolbar for SearchBar { - fn active_item_changed( - &mut self, - item: Option>, - cx: &mut ViewContext, - ) -> bool { +impl ToolbarItemView for SearchBar { + fn set_active_pane_item(&mut self, item: Option<&dyn ItemHandle>, cx: &mut ViewContext) { self.active_editor_subscription.take(); self.active_editor.take(); self.pending_search.take(); @@ -139,29 +139,19 @@ impl Toolbar for SearchBar { Some(cx.subscribe(&editor, Self::on_active_editor_event)); self.active_editor = Some(editor); self.update_matches(false, cx); - return true; + self.dismissed = false; + return; } } - false - } - fn on_dismiss(&mut self, cx: &mut ViewContext) { - self.dismissed = true; - for (editor, _) in &self.editors_with_matches { - if let Some(editor) = editor.upgrade(cx) { - editor.update(cx, |editor, cx| { - editor.clear_background_highlights::(cx) - }); - } - } + self.dismiss(&Dismiss, cx); } } impl SearchBar { - fn new(cx: &mut ViewContext) -> Self { - let query_editor = cx.add_view(|cx| { - Editor::auto_height(2, Some(|theme| theme.search.editor.input.clone()), cx) - }); + pub fn new(cx: &mut ViewContext) -> Self { + let query_editor = + cx.add_view(|cx| Editor::auto_height(2, Some(|theme| theme.search.editor.clone()), cx)); cx.subscribe(&query_editor, Self::on_query_editor_event) .detach(); @@ -176,10 +166,73 @@ impl SearchBar { regex: false, pending_search: None, query_contains_error: false, - dismissed: false, + dismissed: true, } } + fn dismiss(&mut self, _: &Dismiss, cx: &mut ViewContext) { + self.dismissed = true; + for (editor, _) in &self.editors_with_matches { + if let Some(editor) = editor.upgrade(cx) { + editor.update(cx, |editor, cx| { + editor.clear_background_highlights::(cx) + }); + } + } + if let Some(active_editor) = self.active_editor.as_ref() { + cx.focus(active_editor); + } + cx.notify(); + } + + fn show(&mut self, focus: bool, cx: &mut ViewContext) -> bool { + let editor = if let Some(editor) = self.active_editor.clone() { + editor + } else { + return false; + }; + + let display_map = editor + .update(cx, |editor, cx| editor.snapshot(cx)) + .display_snapshot; + let selection = editor + .read(cx) + .newest_selection_with_snapshot::(&display_map.buffer_snapshot); + + let mut text: String; + if selection.start == selection.end { + let point = selection.start.to_display_point(&display_map); + let range = editor::movement::surrounding_word(&display_map, point); + let range = range.start.to_offset(&display_map, Bias::Left) + ..range.end.to_offset(&display_map, Bias::Right); + text = display_map.buffer_snapshot.text_for_range(range).collect(); + if text.trim().is_empty() { + text = String::new(); + } + } else { + text = display_map + .buffer_snapshot + .text_for_range(selection.start..selection.end) + .collect(); + } + + if !text.is_empty() { + self.set_query(&text, cx); + } + + if focus { + let query_editor = self.query_editor.clone(); + query_editor.update(cx, |query_editor, cx| { + query_editor.select_all(&editor::SelectAll, cx); + }); + cx.focus_self(); + } + + self.dismissed = false; + cx.notify(); + true + } + fn set_query(&mut self, query: &str, cx: &mut ViewContext) { self.query_editor.update(cx, |query_editor, cx| { query_editor.buffer().update(cx, |query_buffer, cx| { @@ -238,61 +291,13 @@ impl SearchBar { .boxed() } - fn deploy(workspace: &mut Workspace, Deploy(focus): &Deploy, cx: &mut ViewContext) { - workspace.active_pane().update(cx, |pane, cx| { - pane.show_toolbar(cx, |cx| SearchBar::new(cx)); - - if let Some(search_bar) = pane - .active_toolbar() - .and_then(|toolbar| toolbar.downcast::()) - { - search_bar.update(cx, |search_bar, _| search_bar.dismissed = false); - let editor = pane.active_item().unwrap().act_as::(cx).unwrap(); - let display_map = editor - .update(cx, |editor, cx| editor.snapshot(cx)) - .display_snapshot; - let selection = editor - .read(cx) - .newest_selection_with_snapshot::(&display_map.buffer_snapshot); - - let mut text: String; - if selection.start == selection.end { - let point = selection.start.to_display_point(&display_map); - let range = editor::movement::surrounding_word(&display_map, point); - let range = range.start.to_offset(&display_map, Bias::Left) - ..range.end.to_offset(&display_map, Bias::Right); - text = display_map.buffer_snapshot.text_for_range(range).collect(); - if text.trim().is_empty() { - text = String::new(); - } - } else { - text = display_map - .buffer_snapshot - .text_for_range(selection.start..selection.end) - .collect(); - } - - if !text.is_empty() { - search_bar.update(cx, |search_bar, cx| search_bar.set_query(&text, cx)); - } - - if *focus { - let query_editor = search_bar.read(cx).query_editor.clone(); - query_editor.update(cx, |query_editor, cx| { - query_editor.select_all(&editor::SelectAll, cx); - }); - cx.focus(&search_bar); - } - } else { - cx.propagate_action(); + fn deploy(pane: &mut Pane, Deploy(focus): &Deploy, cx: &mut ViewContext) { + if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::() { + if search_bar.update(cx, |search_bar, cx| search_bar.show(*focus, cx)) { + return; } - }); - } - - fn dismiss(pane: &mut Pane, _: &Dismiss, cx: &mut ViewContext) { - if pane.toolbar::().is_some() { - pane.dismiss_toolbar(cx); } + cx.propagate_action(); } fn focus_editor(&mut self, _: &FocusEditor, cx: &mut ViewContext) { @@ -346,7 +351,7 @@ impl SearchBar { } fn select_match_on_pane(pane: &mut Pane, action: &SelectMatch, cx: &mut ViewContext) { - if let Some(search_bar) = pane.toolbar::() { + if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::() { search_bar.update(cx, |search_bar, cx| search_bar.select_match(action, cx)); } } @@ -541,7 +546,7 @@ mod tests { let search_bar = cx.add_view(Default::default(), |cx| { let mut search_bar = SearchBar::new(cx); - search_bar.active_item_changed(Some(Box::new(editor.clone())), cx); + search_bar.set_active_pane_item(Some(&editor), cx); search_bar }); diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index d78fcb12b7..cf74a21000 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -336,8 +336,7 @@ impl ProjectSearchView { .detach(); let query_editor = cx.add_view(|cx| { - let mut editor = - Editor::single_line(Some(|theme| theme.search.editor.input.clone()), cx); + let mut editor = Editor::single_line(Some(|theme| theme.search.editor.clone()), cx); editor.set_text(query_text, cx); editor }); @@ -569,7 +568,7 @@ impl ProjectSearchView { let editor_container = if self.query_contains_error { theme.search.invalid_editor } else { - theme.search.editor.input.container + theme.search.editor.container }; Flex::row() .with_child( @@ -578,7 +577,7 @@ impl ProjectSearchView { .with_style(editor_container) .aligned() .constrained() - .with_max_width(theme.search.editor.max_width) + .with_max_width(theme.search.max_editor_width) .boxed(), ) .with_child( @@ -615,7 +614,7 @@ impl ProjectSearchView { }) }) .contained() - .with_style(theme.search.container) + .with_style(theme.workspace.toolbar.container) .constrained() .with_height(theme.workspace.toolbar.height) .named("project search") diff --git a/crates/search/src/search.rs b/crates/search/src/search.rs index 9fb4cda8e9..b2543fe261 100644 --- a/crates/search/src/search.rs +++ b/crates/search/src/search.rs @@ -1,11 +1,11 @@ +pub use buffer_search::SearchBar; +use editor::{Anchor, MultiBufferSnapshot}; +use gpui::{action, MutableAppContext}; use std::{ cmp::{self, Ordering}, ops::Range, }; -use editor::{Anchor, MultiBufferSnapshot}; -use gpui::{action, MutableAppContext}; - mod buffer_search; mod project_search; diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index d10c282e35..bccf44dfff 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -94,14 +94,18 @@ pub struct Tab { #[derive(Clone, Deserialize, Default)] pub struct Toolbar { + #[serde(flatten)] + pub container: ContainerStyle, pub height: f32, + pub item_spacing: f32, } #[derive(Clone, Deserialize, Default)] pub struct Search { #[serde(flatten)] pub container: ContainerStyle, - pub editor: FindEditor, + pub max_editor_width: f32, + pub editor: FieldEditor, pub invalid_editor: ContainerStyle, pub option_button_group: ContainerStyle, pub option_button: ContainedText, @@ -115,13 +119,6 @@ pub struct Search { pub tab_icon_spacing: f32, } -#[derive(Clone, Deserialize, Default)] -pub struct FindEditor { - #[serde(flatten)] - pub input: FieldEditor, - pub max_width: f32, -} - #[derive(Deserialize, Default)] pub struct Sidebar { #[serde(flatten)] diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index df30d48dbe..ec9319a396 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -1,5 +1,5 @@ use super::{ItemHandle, SplitDirection}; -use crate::{Item, Settings, WeakItemHandle, Workspace}; +use crate::{toolbar::Toolbar, Item, Settings, WeakItemHandle, Workspace}; use collections::{HashMap, VecDeque}; use gpui::{ action, @@ -7,16 +7,11 @@ use gpui::{ geometry::{rect::RectF, vector::vec2f}, keymap::Binding, platform::{CursorStyle, NavigationDirection}, - AnyViewHandle, AppContext, Entity, MutableAppContext, Quad, RenderContext, Task, View, - ViewContext, ViewHandle, WeakViewHandle, + AppContext, Entity, MutableAppContext, Quad, RenderContext, Task, View, ViewContext, + ViewHandle, WeakViewHandle, }; use project::{ProjectEntryId, ProjectPath}; -use std::{ - any::{Any, TypeId}, - cell::RefCell, - cmp, mem, - rc::Rc, -}; +use std::{any::Any, cell::RefCell, cmp, mem, rc::Rc}; use util::ResultExt; action!(Split, SplitDirection); @@ -101,28 +96,7 @@ pub struct Pane { items: Vec>, active_item_index: usize, nav_history: Rc>, - toolbars: HashMap>, - active_toolbar_type: Option, - active_toolbar_visible: bool, -} - -pub trait Toolbar: View { - fn active_item_changed( - &mut self, - item: Option>, - cx: &mut ViewContext, - ) -> bool; - fn on_dismiss(&mut self, cx: &mut ViewContext); -} - -trait ToolbarHandle { - fn active_item_changed( - &self, - item: Option>, - cx: &mut MutableAppContext, - ) -> bool; - fn on_dismiss(&self, cx: &mut MutableAppContext); - fn to_any(&self) -> AnyViewHandle; + toolbar: ViewHandle, } pub struct ItemNavHistory { @@ -158,14 +132,12 @@ pub struct NavigationEntry { } impl Pane { - pub fn new() -> Self { + pub fn new(cx: &mut ViewContext) -> Self { Self { items: Vec::new(), active_item_index: 0, nav_history: Default::default(), - toolbars: Default::default(), - active_toolbar_type: Default::default(), - active_toolbar_visible: false, + toolbar: cx.add_view(|_| Toolbar::new()), } } @@ -402,7 +374,7 @@ impl Pane { self.items[prev_active_item_ix].deactivated(cx); cx.emit(Event::ActivateItem { local }); } - self.update_active_toolbar(cx); + self.update_toolbar(cx); if local { self.focus_active_item(cx); self.activate(cx); @@ -487,7 +459,7 @@ impl Pane { self.focus_active_item(cx); self.activate(cx); } - self.update_active_toolbar(cx); + self.update_toolbar(cx); cx.notify(); } @@ -502,63 +474,18 @@ impl Pane { cx.emit(Event::Split(direction)); } - pub fn show_toolbar(&mut self, cx: &mut ViewContext, build_toolbar: F) - where - F: FnOnce(&mut ViewContext) -> V, - V: Toolbar, - { - let type_id = TypeId::of::(); - if self.active_toolbar_type != Some(type_id) { - self.dismiss_toolbar(cx); - - 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 toolbar(&self) -> &ViewHandle { + &self.toolbar } - pub fn dismiss_toolbar(&mut self, cx: &mut ViewContext) { - if let Some(active_toolbar_type) = self.active_toolbar_type.take() { - self.toolbars - .get_mut(&active_toolbar_type) - .unwrap() - .on_dismiss(cx); - self.active_toolbar_visible = false; - self.focus_active_item(cx); - cx.notify(); - } - } - - pub fn toolbar(&self) -> Option> { - self.toolbars - .get(&TypeId::of::()) - .and_then(|toolbar| toolbar.to_any().downcast()) - } - - pub fn active_toolbar(&self) -> Option { - 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) { - let active_item = self.items.get(self.active_item_index); - for (toolbar_type_id, toolbar) in &self.toolbars { - let visible = toolbar.active_item_changed(active_item.cloned(), cx); - if Some(*toolbar_type_id) == self.active_toolbar_type { - self.active_toolbar_visible = visible; - } - } + fn update_toolbar(&mut self, cx: &mut ViewContext) { + let active_item = self + .items + .get(self.active_item_index) + .map(|item| item.as_ref()); + self.toolbar.update(cx, |toolbar, cx| { + toolbar.set_active_pane_item(active_item, cx); + }); } fn render_tabs(&self, cx: &mut RenderContext) -> ElementBox { @@ -713,11 +640,7 @@ impl View for Pane { EventHandler::new(if let Some(active_item) = self.active_item() { Flex::column() .with_child(self.render_tabs(cx)) - .with_children( - self.active_toolbar() - .as_ref() - .map(|view| ChildView::new(view).boxed()), - ) + .with_child(ChildView::new(&self.toolbar).boxed()) .with_child(ChildView::new(active_item).flexible(1., true).boxed()) .boxed() } else { @@ -740,24 +663,6 @@ impl View for Pane { } } -impl ToolbarHandle for ViewHandle { - fn active_item_changed( - &self, - item: Option>, - cx: &mut MutableAppContext, - ) -> bool { - self.update(cx, |this, cx| this.active_item_changed(item, cx)) - } - - fn on_dismiss(&self, cx: &mut MutableAppContext) { - self.update(cx, |this, cx| this.on_dismiss(cx)); - } - - fn to_any(&self) -> AnyViewHandle { - self.into() - } -} - impl ItemNavHistory { pub fn new(history: Rc>, item: &ViewHandle) -> Self { Self { diff --git a/crates/workspace/src/toolbar.rs b/crates/workspace/src/toolbar.rs new file mode 100644 index 0000000000..a709f4bd05 --- /dev/null +++ b/crates/workspace/src/toolbar.rs @@ -0,0 +1,131 @@ +use crate::{ItemHandle, Settings}; +use gpui::{ + elements::*, AnyViewHandle, ElementBox, Entity, MutableAppContext, RenderContext, View, + ViewContext, ViewHandle, +}; + +pub trait ToolbarItemView: View { + fn set_active_pane_item( + &mut self, + active_pane_item: Option<&dyn crate::ItemHandle>, + cx: &mut ViewContext, + ); +} + +trait ToolbarItemViewHandle { + fn to_any(&self) -> AnyViewHandle; + fn set_active_pane_item( + &self, + active_pane_item: Option<&dyn ItemHandle>, + cx: &mut MutableAppContext, + ); +} + +pub struct Toolbar { + active_pane_item: Option>, + left_items: Vec>, + right_items: Vec>, +} + +impl Entity for Toolbar { + type Event = (); +} + +impl View for Toolbar { + fn ui_name() -> &'static str { + "Toolbar" + } + + fn render(&mut self, cx: &mut RenderContext) -> ElementBox { + let theme = &cx.global::().theme.workspace.toolbar; + Flex::row() + .with_children(self.left_items.iter().map(|i| { + ChildView::new(i.as_ref()) + .aligned() + .contained() + .with_margin_right(theme.item_spacing) + .boxed() + })) + .with_child(Empty::new().flexible(1., true).boxed()) + .with_children(self.right_items.iter().map(|i| { + ChildView::new(i.as_ref()) + .aligned() + .contained() + .with_margin_left(theme.item_spacing) + .boxed() + })) + .contained() + .with_style(theme.container) + .constrained() + .with_height(theme.height) + .boxed() + } +} + +impl Toolbar { + pub fn new() -> Self { + Self { + active_pane_item: None, + left_items: Default::default(), + right_items: Default::default(), + } + } + + pub fn add_left_item(&mut self, item: ViewHandle, cx: &mut ViewContext) + where + T: 'static + ToolbarItemView, + { + item.set_active_pane_item(self.active_pane_item.as_deref(), cx); + self.left_items.push(Box::new(item)); + cx.notify(); + } + + pub fn add_right_item(&mut self, item: ViewHandle, cx: &mut ViewContext) + where + T: 'static + ToolbarItemView, + { + item.set_active_pane_item(self.active_pane_item.as_deref(), cx); + self.right_items.push(Box::new(item)); + cx.notify(); + } + + pub fn set_active_pane_item( + &mut self, + item: Option<&dyn ItemHandle>, + cx: &mut ViewContext, + ) { + self.active_pane_item = item.map(|item| item.boxed_clone()); + for tool in self.left_items.iter().chain(&self.right_items) { + tool.set_active_pane_item(item, cx); + } + } + + pub fn item_of_type(&self) -> Option> { + self.left_items + .iter() + .chain(&self.right_items) + .find_map(|tool| tool.to_any().downcast()) + } +} + +impl ToolbarItemViewHandle for ViewHandle { + fn to_any(&self) -> AnyViewHandle { + self.into() + } + + fn set_active_pane_item( + &self, + active_pane_item: Option<&dyn ItemHandle>, + cx: &mut MutableAppContext, + ) { + self.update(cx, |this, cx| { + this.set_active_pane_item(active_pane_item, cx) + }); + } +} + +impl Into for &dyn ToolbarItemViewHandle { + fn into(self) -> AnyViewHandle { + self.to_any() + } +} diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 4d9f0ca3da..d3a644d852 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -5,6 +5,7 @@ pub mod pane_group; pub mod settings; pub mod sidebar; mod status_bar; +mod toolbar; use anyhow::{anyhow, Context, Result}; use client::{ @@ -47,6 +48,7 @@ use std::{ }, }; use theme::{Theme, ThemeRegistry}; +pub use toolbar::ToolbarItemView; use util::ResultExt; type ProjectItemBuilders = HashMap< @@ -720,7 +722,7 @@ impl Workspace { }) .detach(); - let pane = cx.add_view(|_| Pane::new()); + let pane = cx.add_view(|cx| Pane::new(cx)); let pane_id = pane.id(); cx.observe(&pane, move |me, _, cx| { let active_entry = me.active_project_path(cx); @@ -733,6 +735,7 @@ impl Workspace { }) .detach(); cx.focus(&pane); + cx.emit(Event::PaneAdded(pane.clone())); let status_bar = cx.add_view(|cx| StatusBar::new(&pane, cx)); let mut current_user = params.user_store.read(cx).watch_current_user().clone(); @@ -1051,7 +1054,7 @@ impl Workspace { } fn add_pane(&mut self, cx: &mut ViewContext) -> ViewHandle { - let pane = cx.add_view(|_| Pane::new()); + let pane = cx.add_view(|cx| Pane::new(cx)); let pane_id = pane.id(); cx.observe(&pane, move |me, _, cx| { let active_entry = me.active_project_path(cx); diff --git a/crates/zed/assets/themes/_base.toml b/crates/zed/assets/themes/_base.toml index 7bd0c59045..54afc3d5a1 100644 --- a/crates/zed/assets/themes/_base.toml +++ b/crates/zed/assets/themes/_base.toml @@ -85,7 +85,10 @@ diagnostic_message = "$text.2" lsp_message = "$text.2" [workspace.toolbar] +background = "$surface.1" +border = { color = "$border.0", width = 1, left = false, right = false, bottom = true, top = false } height = 44 +item_spacing = 8 [panel] padding = { top = 12, left = 12, bottom = 12, right = 12 } @@ -353,8 +356,8 @@ tab_icon_spacing = 4 tab_summary_spacing = 10 [search] +max_editor_width = 400 match_background = "$state.highlighted_line" -background = "$surface.1" results_status = { extends = "$text.0", size = 18 } tab_icon_width = 14 tab_icon_spacing = 4 @@ -388,7 +391,6 @@ extends = "$text.1" padding = 6 [search.editor] -max_width = 400 background = "$surface.0" corner_radius = 6 padding = { left = 13, right = 13, top = 3, bottom = 3 } diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 1302d54067..ca3f18e233 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -21,6 +21,7 @@ pub use lsp; use project::Project; pub use project::{self, fs}; use project_panel::ProjectPanel; +use search::SearchBar; use std::{path::PathBuf, sync::Arc}; pub use workspace; use workspace::{AppState, Settings, Workspace, WorkspaceParams}; @@ -104,6 +105,17 @@ pub fn build_workspace( app_state: &Arc, cx: &mut ViewContext, ) -> Workspace { + cx.subscribe(&cx.handle(), |_, _, event, cx| { + let workspace::Event::PaneAdded(pane) = event; + pane.update(cx, |pane, cx| { + pane.toolbar().update(cx, |toolbar, cx| { + let search_bar = cx.add_view(|cx| SearchBar::new(cx)); + toolbar.add_right_item(search_bar, cx); + }) + }); + }) + .detach(); + let workspace_params = WorkspaceParams { project, client: app_state.client.clone(),