diff --git a/Cargo.lock b/Cargo.lock index c6fbe523b1..f79a7b851d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4012,6 +4012,7 @@ dependencies = [ "env_logger", "gpui", "menu", + "parking_lot 0.11.2", "serde_json", "settings", "theme", diff --git a/crates/collab_ui/src/contact_finder.rs b/crates/collab_ui/src/contact_finder.rs index 5165c3b1f6..98f70e83f0 100644 --- a/crates/collab_ui/src/contact_finder.rs +++ b/crates/collab_ui/src/contact_finder.rs @@ -170,8 +170,8 @@ impl ContactFinder { let this = cx.weak_handle(); Self { picker: cx.add_view(|cx| { - Picker::new(this, cx) - .with_theme(|cx| &cx.global::().theme.contact_finder.picker) + Picker::new("Search collaborator by username...", this, cx) + .with_theme(|theme| theme.contact_finder.picker.clone()) }), potential_contacts: Arc::from([]), user_store, diff --git a/crates/collab_ui/src/contact_list.rs b/crates/collab_ui/src/contact_list.rs index a4a0b5d18e..bc8b2947c4 100644 --- a/crates/collab_ui/src/contact_list.rs +++ b/crates/collab_ui/src/contact_list.rs @@ -175,7 +175,9 @@ impl ContactList { ) -> Self { let filter_editor = cx.add_view(|cx| { let mut editor = Editor::single_line( - Some(|theme| theme.contact_list.user_query_editor.clone()), + Some(Arc::new(|theme| { + theme.contact_list.user_query_editor.clone() + })), cx, ); editor.set_placeholder_text("Filter contacts", cx); diff --git a/crates/command_palette/src/command_palette.rs b/crates/command_palette/src/command_palette.rs index 51474be1be..b472da3bb5 100644 --- a/crates/command_palette/src/command_palette.rs +++ b/crates/command_palette/src/command_palette.rs @@ -70,7 +70,7 @@ impl CommandPalette { }) .collect(); - let picker = cx.add_view(|cx| Picker::new(this, cx)); + let picker = cx.add_view(|cx| Picker::new("Execute a command...", this, cx)); Self { picker, actions, diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 12790df442..a049239f70 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -437,8 +437,7 @@ pub struct EditorStyle { type CompletionId = usize; -pub type GetFieldEditorTheme = fn(&theme::Theme) -> theme::FieldEditor; - +type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor; type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option; #[derive(Clone, Copy)] @@ -523,7 +522,7 @@ pub struct Editor { scroll_top_anchor: Anchor, autoscroll_request: Option<(Autoscroll, bool)>, soft_wrap_mode_override: Option, - get_field_editor_theme: Option, + get_field_editor_theme: Option>, override_text_style: Option>, project: Option>, focused: bool, @@ -1070,7 +1069,7 @@ enum GotoDefinitionKind { impl Editor { pub fn single_line( - field_editor_style: Option, + field_editor_style: Option>, cx: &mut ViewContext, ) -> Self { let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx)); @@ -1080,7 +1079,7 @@ impl Editor { pub fn auto_height( max_lines: usize, - field_editor_style: Option, + field_editor_style: Option>, cx: &mut ViewContext, ) -> Self { let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx)); @@ -1116,7 +1115,7 @@ impl Editor { self.mode, self.buffer.clone(), self.project.clone(), - self.get_field_editor_theme, + self.get_field_editor_theme.clone(), cx, ); self.display_map.update(cx, |display_map, cx| { @@ -1136,12 +1135,12 @@ impl Editor { mode: EditorMode, buffer: ModelHandle, project: Option>, - get_field_editor_theme: Option, + get_field_editor_theme: Option>, cx: &mut ViewContext, ) -> Self { let display_map = cx.add_model(|cx| { let settings = cx.global::(); - let style = build_style(&*settings, get_field_editor_theme, None, cx); + let style = build_style(&*settings, get_field_editor_theme.as_deref(), None, cx); DisplayMap::new( buffer.clone(), style.text.font_id, @@ -1289,7 +1288,7 @@ impl Editor { fn style(&self, cx: &AppContext) -> EditorStyle { build_style( cx.global::(), - self.get_field_editor_theme, + self.get_field_editor_theme.as_deref(), self.override_text_style.as_deref(), cx, ) @@ -6846,7 +6845,7 @@ impl View for Editor { fn build_style( settings: &Settings, - get_field_editor_theme: Option, + get_field_editor_theme: Option<&GetFieldEditorTheme>, override_text_style: Option<&OverrideTextStyle>, cx: &AppContext, ) -> EditorStyle { diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index dc62b2e923..25100037d7 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1186,7 +1186,7 @@ impl EditorElement { } // When the editor is empty and unfocused, then show the placeholder. - if snapshot.is_empty() && !snapshot.is_focused() { + if snapshot.is_empty() { let placeholder_style = self .style .placeholder_text diff --git a/crates/file_finder/src/file_finder.rs b/crates/file_finder/src/file_finder.rs index 1a82613b84..06041f8b0b 100644 --- a/crates/file_finder/src/file_finder.rs +++ b/crates/file_finder/src/file_finder.rs @@ -119,7 +119,7 @@ impl FileFinder { cx.observe(&project, Self::project_updated).detach(); Self { project, - picker: cx.add_view(|cx| Picker::new(handle, cx)), + picker: cx.add_view(|cx| Picker::new("Search project files...", handle, cx)), search_count: 0, latest_search_id: 0, latest_search_did_cancel: false, diff --git a/crates/go_to_line/src/go_to_line.rs b/crates/go_to_line/src/go_to_line.rs index f183f9d8bd..68a69801cf 100644 --- a/crates/go_to_line/src/go_to_line.rs +++ b/crates/go_to_line/src/go_to_line.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use editor::{display_map::ToDisplayPoint, Autoscroll, DisplayPoint, Editor}; use gpui::{ actions, elements::*, geometry::vector::Vector2F, AnyViewHandle, Axis, Entity, @@ -31,7 +33,10 @@ pub enum Event { impl GoToLine { pub fn new(active_editor: ViewHandle, cx: &mut ViewContext) -> Self { let line_editor = cx.add_view(|cx| { - Editor::single_line(Some(|theme| theme.picker.input_editor.clone()), cx) + Editor::single_line( + Some(Arc::new(|theme| theme.picker.input_editor.clone())), + cx, + ) }); cx.subscribe(&line_editor, Self::on_line_editor_event) .detach(); diff --git a/crates/outline/src/outline.rs b/crates/outline/src/outline.rs index cee5388800..e0136f5005 100644 --- a/crates/outline/src/outline.rs +++ b/crates/outline/src/outline.rs @@ -67,7 +67,9 @@ impl OutlineView { ) -> Self { let handle = cx.weak_handle(); Self { - picker: cx.add_view(|cx| Picker::new(handle, cx).with_max_size(800., 1200.)), + picker: cx.add_view(|cx| { + Picker::new("Search buffer symbols...", handle, cx).with_max_size(800., 1200.) + }), last_query: Default::default(), matches: Default::default(), selected_match_index: 0, diff --git a/crates/picker/Cargo.toml b/crates/picker/Cargo.toml index bceb263e23..6438697910 100644 --- a/crates/picker/Cargo.toml +++ b/crates/picker/Cargo.toml @@ -16,6 +16,8 @@ util = { path = "../util" } theme = { path = "../theme" } workspace = { path = "../workspace" } +parking_lot = "0.11.1" + [dev-dependencies] gpui = { path = "../gpui", features = ["test-support"] } serde_json = { version = "1.0", features = ["preserve_order"] } diff --git a/crates/picker/src/picker.rs b/crates/picker/src/picker.rs index 95cbf2dacd..a9cf23fb3f 100644 --- a/crates/picker/src/picker.rs +++ b/crates/picker/src/picker.rs @@ -8,15 +8,15 @@ use gpui::{ RenderContext, Task, View, ViewContext, ViewHandle, WeakViewHandle, }; use menu::{Cancel, Confirm, SelectFirst, SelectIndex, SelectLast, SelectNext, SelectPrev}; -use settings::Settings; -use std::cmp; +use parking_lot::Mutex; +use std::{cmp, sync::Arc}; pub struct Picker { delegate: WeakViewHandle, query_editor: ViewHandle, list_state: UniformListState, max_size: Vector2F, - theme: Box &theme::Picker>, + theme: Arc theme::Picker>>>, confirmed: bool, } @@ -49,7 +49,7 @@ impl View for Picker { } fn render(&mut self, cx: &mut RenderContext) -> gpui::ElementBox { - let theme = (self.theme)(cx); + let theme = (self.theme.lock())(&cx.global::().theme); let query = self.query(cx); let delegate = self.delegate.clone(); let match_count = if let Some(delegate) = delegate.upgrade(cx.app) { @@ -148,9 +148,26 @@ impl Picker { cx.add_action(Self::cancel); } - pub fn new(delegate: WeakViewHandle, cx: &mut ViewContext) -> Self { - let query_editor = cx.add_view(|cx| { - Editor::single_line(Some(|theme| theme.picker.input_editor.clone()), cx) + pub fn new

(placeholder: P, delegate: WeakViewHandle, cx: &mut ViewContext) -> Self + where + P: Into>, + { + let theme = Arc::new(Mutex::new( + Box::new(|theme: &theme::Theme| theme.picker.clone()) + as Box theme::Picker>, + )); + let query_editor = cx.add_view({ + let picker_theme = theme.clone(); + |cx| { + let mut editor = Editor::single_line( + Some(Arc::new(move |theme| { + (picker_theme.lock())(theme).input_editor.clone() + })), + cx, + ); + editor.set_placeholder_text(placeholder, cx); + editor + } }); cx.subscribe(&query_editor, Self::on_query_editor_event) .detach(); @@ -159,7 +176,7 @@ impl Picker { list_state: Default::default(), delegate, max_size: vec2f(540., 420.), - theme: Box::new(|cx| &cx.global::().theme.picker), + theme, confirmed: false, }; cx.defer(|this, cx| { @@ -176,11 +193,11 @@ impl Picker { self } - pub fn with_theme(mut self, theme: F) -> Self + pub fn with_theme(self, theme: F) -> Self where - F: 'static + FnMut(&AppContext) -> &theme::Picker, + F: 'static + Fn(&theme::Theme) -> theme::Picker, { - self.theme = Box::new(theme); + *self.theme.lock() = Box::new(theme); self } diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 8f5d9b0e55..392fd73e03 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -23,6 +23,7 @@ use std::{ ffi::OsStr, ops::Range, path::{Path, PathBuf}, + sync::Arc, }; use unicase::UniCase; use workspace::Workspace; @@ -175,11 +176,11 @@ impl ProjectPanel { let filename_editor = cx.add_view(|cx| { Editor::single_line( - Some(|theme| { + Some(Arc::new(|theme| { let mut style = theme.project_panel.filename_editor.clone(); style.container.background_color.take(); style - }), + })), cx, ) }); diff --git a/crates/project_symbols/src/project_symbols.rs b/crates/project_symbols/src/project_symbols.rs index e4a251de00..440e11e7e4 100644 --- a/crates/project_symbols/src/project_symbols.rs +++ b/crates/project_symbols/src/project_symbols.rs @@ -63,7 +63,7 @@ impl ProjectSymbolsView { let handle = cx.weak_handle(); Self { project, - picker: cx.add_view(|cx| Picker::new(handle, cx)), + picker: cx.add_view(|cx| Picker::new("Search project symbols...", handle, cx)), selected_match_index: 0, symbols: Default::default(), visible_match_candidates: Default::default(), diff --git a/crates/search/src/buffer_search.rs b/crates/search/src/buffer_search.rs index cd7a74ce8e..7d668f6b3e 100644 --- a/crates/search/src/buffer_search.rs +++ b/crates/search/src/buffer_search.rs @@ -12,7 +12,7 @@ use gpui::{ use project::search::SearchQuery; use serde::Deserialize; use settings::Settings; -use std::any::Any; +use std::{any::Any, sync::Arc}; use workspace::{ searchable::{Direction, SearchEvent, SearchableItemHandle, WeakSearchableItemHandle}, ItemHandle, Pane, ToolbarItemLocation, ToolbarItemView, @@ -232,7 +232,11 @@ impl ToolbarItemView for BufferSearchBar { impl BufferSearchBar { pub 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) + Editor::auto_height( + 2, + Some(Arc::new(|theme| theme.search.editor.input.clone())), + cx, + ) }); cx.subscribe(&query_editor, Self::on_query_editor_event) .detach(); diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index 8eb8e110e4..6ba185b589 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -20,6 +20,7 @@ use std::{ any::{Any, TypeId}, ops::Range, path::PathBuf, + sync::Arc, }; use util::ResultExt as _; use workspace::{ @@ -378,8 +379,10 @@ 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(Arc::new(|theme| theme.search.editor.input.clone())), + cx, + ); editor.set_text(query_text, cx); editor }); diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index 4c3b60cdaf..cf7aa6e551 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -423,7 +423,7 @@ pub struct ChannelName { pub name: TextStyle, } -#[derive(Deserialize, Default)] +#[derive(Clone, Deserialize, Default)] pub struct Picker { #[serde(flatten)] pub container: ContainerStyle, diff --git a/crates/theme_selector/src/theme_selector.rs b/crates/theme_selector/src/theme_selector.rs index 1caeae75f5..252a64c7fd 100644 --- a/crates/theme_selector/src/theme_selector.rs +++ b/crates/theme_selector/src/theme_selector.rs @@ -38,7 +38,7 @@ pub enum Event { impl ThemeSelector { fn new(registry: Arc, cx: &mut ViewContext) -> Self { let handle = cx.weak_handle(); - let picker = cx.add_view(|cx| Picker::new(handle, cx)); + let picker = cx.add_view(|cx| Picker::new("Select Theme...", handle, cx)); let settings = cx.global::(); let original_theme = settings.theme.clone(); diff --git a/styles/src/styleTree/contactFinder.ts b/styles/src/styleTree/contactFinder.ts index a08007c695..d696f2c4b8 100644 --- a/styles/src/styleTree/contactFinder.ts +++ b/styles/src/styleTree/contactFinder.ts @@ -19,7 +19,7 @@ export default function contactFinder(colorScheme: ColorScheme) { background: background(layer, "on"), cornerRadius: 6, text: text(layer, "mono",), - placeholderText: text(layer, "mono", "variant", { size: "sm" }), + placeholderText: text(layer, "mono", "on", "disabled", { size: "xs" }), selection: colorScheme.players[0], border: border(layer), padding: { diff --git a/styles/src/styleTree/contactList.ts b/styles/src/styleTree/contactList.ts index 5addca96d2..456786c4be 100644 --- a/styles/src/styleTree/contactList.ts +++ b/styles/src/styleTree/contactList.ts @@ -53,7 +53,7 @@ export default function contactsPanel(colorScheme: ColorScheme) { background: background(layer, "on"), cornerRadius: 6, text: text(layer, "mono", "on"), - placeholderText: text(layer, "mono", "on", "disabled", { size: "sm" }), + placeholderText: text(layer, "mono", "on", "disabled", { size: "xs" }), selection: colorScheme.players[0], border: border(layer, "on"), padding: {