From 67a25126d48b173ba8a5dffdff1aaf94002c3781 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 17 May 2023 14:44:55 -0700 Subject: [PATCH] Define theme/ui text style settings in theme crate --- Cargo.lock | 9 +- crates/activity_indicator/Cargo.toml | 2 + .../src/activity_indicator.rs | 8 +- crates/auto_update/src/update_notification.rs | 3 +- crates/breadcrumbs/src/breadcrumbs.rs | 3 +- crates/collab/src/tests.rs | 6 +- .../src/tests/randomized_integration_tests.rs | 4 +- crates/collab_ui/src/collab_titlebar_item.rs | 7 +- crates/collab_ui/src/contact_finder.rs | 3 +- crates/collab_ui/src/contact_list.rs | 5 +- crates/collab_ui/src/contacts_popover.rs | 3 +- .../src/incoming_call_notification.rs | 28 +-- crates/collab_ui/src/notifications.rs | 3 +- .../src/project_shared_notification.rs | 27 +-- crates/command_palette/src/command_palette.rs | 5 +- crates/context_menu/src/context_menu.rs | 5 +- crates/copilot/src/sign_in.rs | 5 +- crates/copilot_button/src/copilot_button.rs | 11 +- crates/diagnostics/Cargo.toml | 1 + crates/diagnostics/src/diagnostics.rs | 38 ++-- crates/diagnostics/src/items.rs | 10 +- crates/editor/src/blink_manager.rs | 6 +- crates/editor/src/display_map/block_map.rs | 13 +- crates/editor/src/display_map/fold_map.rs | 14 +- .../editor/src/display_map/suggestion_map.rs | 10 +- crates/editor/src/display_map/wrap_map.rs | 14 +- crates/editor/src/editor.rs | 22 +- crates/editor/src/editor_tests.rs | 6 +- crates/editor/src/element.rs | 9 +- crates/editor/src/hover_popover.rs | 3 +- crates/editor/src/items.rs | 3 +- crates/editor/src/link_go_to_definition.rs | 3 +- crates/editor/src/movement.rs | 5 +- crates/editor/src/multi_buffer.rs | 6 +- .../src/test/editor_lsp_test_context.rs | 1 + crates/feedback/src/deploy_feedback_button.rs | 3 +- crates/feedback/src/feedback_info_text.rs | 3 +- crates/feedback/src/submit_feedback_button.rs | 3 +- crates/file_finder/src/file_finder.rs | 6 +- crates/go_to_line/Cargo.toml | 1 + crates/go_to_line/src/go_to_line.rs | 3 +- crates/language/src/language_settings.rs | 1 + .../src/active_buffer_language.rs | 3 +- .../src/language_selector.rs | 4 +- crates/lsp_log/src/lsp_log.rs | 3 +- crates/outline/Cargo.toml | 2 + crates/outline/src/outline.rs | 7 +- crates/picker/src/picker.rs | 2 +- crates/project/src/project.rs | 10 +- crates/project_panel/src/project_panel.rs | 13 +- crates/project_symbols/Cargo.toml | 3 + crates/project_symbols/src/project_symbols.rs | 12 +- crates/recent_projects/Cargo.toml | 1 + crates/recent_projects/src/recent_projects.rs | 6 +- crates/search/src/buffer_search.rs | 25 +-- crates/search/src/project_search.rs | 35 ++- crates/settings/Cargo.toml | 8 +- crates/settings/src/settings.rs | 209 +----------------- crates/settings/src/settings_file.rs | 25 +-- crates/settings/src/settings_store.rs | 30 ++- crates/terminal/src/terminal.rs | 3 +- crates/terminal_view/src/terminal_button.rs | 3 +- crates/terminal_view/src/terminal_element.rs | 6 +- crates/terminal_view/src/terminal_view.rs | 1 + crates/theme/Cargo.toml | 15 +- crates/theme/src/theme.rs | 18 +- crates/theme/src/theme_registry.rs | 12 +- crates/theme/src/theme_settings.rs | 136 ++++++++++++ crates/theme_selector/src/theme_selector.rs | 54 ++--- crates/theme_testbench/src/theme_testbench.rs | 7 +- crates/welcome/src/base_keymap_picker.rs | 4 +- crates/welcome/src/welcome.rs | 10 +- crates/workspace/src/dock.rs | 3 - .../workspace/src/dock/toggle_dock_button.rs | 3 +- crates/workspace/src/notifications.rs | 9 +- crates/workspace/src/pane.rs | 17 +- .../src/pane/dragged_item_receiver.rs | 12 +- crates/workspace/src/shared_screen.rs | 3 +- crates/workspace/src/sidebar.rs | 5 +- crates/workspace/src/status_bar.rs | 3 +- crates/workspace/src/toolbar.rs | 5 +- crates/workspace/src/workspace.rs | 17 +- crates/zed/src/languages.rs | 8 +- crates/zed/src/languages/json.rs | 31 +-- crates/zed/src/main.rs | 33 ++- crates/zed/src/zed.rs | 30 ++- 86 files changed, 530 insertions(+), 637 deletions(-) create mode 100644 crates/theme/src/theme_settings.rs diff --git a/Cargo.lock b/Cargo.lock index e5922f9e66..af412a8c1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,6 +20,7 @@ dependencies = [ "project", "settings", "smallvec", + "theme", "util", "workspace", ] @@ -2750,6 +2751,7 @@ dependencies = [ "postage", "settings", "text", + "theme", "util", "workspace", ] @@ -4398,6 +4400,7 @@ dependencies = [ "settings", "smol", "text", + "theme", "workspace", ] @@ -4915,6 +4918,7 @@ dependencies = [ "settings", "smol", "text", + "theme", "util", "workspace", ] @@ -5235,6 +5239,7 @@ dependencies = [ "settings", "smol", "text", + "theme", "util", "workspace", ] @@ -6135,7 +6140,6 @@ dependencies = [ "smallvec", "sqlez", "staff_mode", - "theme", "toml", "tree-sitter", "tree-sitter-json 0.19.0", @@ -6863,10 +6867,13 @@ dependencies = [ "gpui", "indexmap", "parking_lot 0.11.2", + "schemars", "serde", "serde_derive", "serde_json", + "settings", "toml", + "util", ] [[package]] diff --git a/crates/activity_indicator/Cargo.toml b/crates/activity_indicator/Cargo.toml index 629aa2c032..917383234a 100644 --- a/crates/activity_indicator/Cargo.toml +++ b/crates/activity_indicator/Cargo.toml @@ -16,6 +16,8 @@ gpui = { path = "../gpui" } project = { path = "../project" } settings = { path = "../settings" } util = { path = "../util" } +theme = { path = "../theme" } workspace = { path = "../workspace" } + futures.workspace = true smallvec.workspace = true diff --git a/crates/activity_indicator/src/activity_indicator.rs b/crates/activity_indicator/src/activity_indicator.rs index d5ee1364b3..801c8f7172 100644 --- a/crates/activity_indicator/src/activity_indicator.rs +++ b/crates/activity_indicator/src/activity_indicator.rs @@ -9,7 +9,6 @@ use gpui::{ }; use language::{LanguageRegistry, LanguageServerBinaryStatus}; use project::{LanguageServerProgress, Project}; -use settings::Settings; use smallvec::SmallVec; use std::{cmp::Reverse, fmt::Write, sync::Arc}; use util::ResultExt; @@ -325,12 +324,7 @@ impl View for ActivityIndicator { } = self.content_to_render(cx); let mut element = MouseEventHandler::::new(0, cx, |state, cx| { - let theme = &cx - .global::() - .theme - .workspace - .status_bar - .lsp_status; + let theme = &theme::current(cx).workspace.status_bar.lsp_status; let style = if state.hovered() && on_click.is_some() { theme.hover.as_ref().unwrap_or(&theme.default) } else { diff --git a/crates/auto_update/src/update_notification.rs b/crates/auto_update/src/update_notification.rs index b48ac2a413..6f31df614d 100644 --- a/crates/auto_update/src/update_notification.rs +++ b/crates/auto_update/src/update_notification.rs @@ -5,7 +5,6 @@ use gpui::{ Element, Entity, View, ViewContext, }; use menu::Cancel; -use settings::Settings; use util::channel::ReleaseChannel; use workspace::notifications::Notification; @@ -27,7 +26,7 @@ impl View for UpdateNotification { } fn render(&mut self, cx: &mut gpui::ViewContext) -> gpui::AnyElement { - let theme = cx.global::().theme.clone(); + let theme = theme::current(cx).clone(); let theme = &theme.update_notification; let app_name = cx.global::().display_name(); diff --git a/crates/breadcrumbs/src/breadcrumbs.rs b/crates/breadcrumbs/src/breadcrumbs.rs index f3be60f8de..906d70abb7 100644 --- a/crates/breadcrumbs/src/breadcrumbs.rs +++ b/crates/breadcrumbs/src/breadcrumbs.rs @@ -4,7 +4,6 @@ use gpui::{ }; use itertools::Itertools; use search::ProjectSearchView; -use settings::Settings; use workspace::{ item::{ItemEvent, ItemHandle}, ToolbarItemLocation, ToolbarItemView, Workspace, @@ -50,7 +49,7 @@ impl View for Breadcrumbs { }; let not_editor = active_item.downcast::().is_none(); - let theme = cx.global::().theme.clone(); + let theme = theme::current(cx).clone(); let style = &theme.workspace.breadcrumbs; let breadcrumbs = match active_item.breadcrumbs(&theme, cx) { diff --git a/crates/collab/src/tests.rs b/crates/collab/src/tests.rs index f1593822af..3c571327eb 100644 --- a/crates/collab/src/tests.rs +++ b/crates/collab/src/tests.rs @@ -19,7 +19,7 @@ use gpui::{ use language::LanguageRegistry; use parking_lot::Mutex; use project::{Project, WorktreeId}; -use settings::{Settings, SettingsStore}; +use settings::SettingsStore; use std::{ cell::{Ref, RefCell, RefMut}, env, @@ -30,7 +30,6 @@ use std::{ Arc, }, }; -use theme::ThemeRegistry; use util::http::FakeHttpClient; use workspace::Workspace; @@ -103,7 +102,6 @@ impl TestServer { async fn create_client(&mut self, cx: &mut TestAppContext, name: &str) -> TestClient { cx.update(|cx| { cx.set_global(SettingsStore::test(cx)); - cx.set_global(Settings::test(cx)); }); let http = FakeHttpClient::with_404_response(); @@ -192,7 +190,6 @@ impl TestServer { client: client.clone(), user_store: user_store.clone(), languages: Arc::new(LanguageRegistry::test()), - themes: ThemeRegistry::new((), cx.font_cache()), fs: fs.clone(), build_window_options: |_, _, _| Default::default(), initialize_workspace: |_, _, _| unimplemented!(), @@ -201,6 +198,7 @@ impl TestServer { }); cx.update(|cx| { + theme::init((), cx); Project::init(&client, cx); client::init(&client, cx); language::init(cx); diff --git a/crates/collab/src/tests/randomized_integration_tests.rs b/crates/collab/src/tests/randomized_integration_tests.rs index fb0645b147..3beff6942a 100644 --- a/crates/collab/src/tests/randomized_integration_tests.rs +++ b/crates/collab/src/tests/randomized_integration_tests.rs @@ -21,7 +21,7 @@ use rand::{ prelude::*, }; use serde::{Deserialize, Serialize}; -use settings::{Settings, SettingsStore}; +use settings::SettingsStore; use std::{ env, ops::Range, @@ -150,10 +150,8 @@ async fn test_random_collaboration( for (client, mut cx) in clients { cx.update(|cx| { let store = cx.remove_global::(); - let settings = cx.remove_global::(); cx.clear_globals(); cx.set_global(store); - cx.set_global(settings); drop(client); }); } diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index 7374b166ca..eb1755a9ff 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -18,7 +18,6 @@ use gpui::{ ViewContext, ViewHandle, WeakViewHandle, }; use project::Project; -use settings::Settings; use std::{ops::Range, sync::Arc}; use theme::{AvatarStyle, Theme}; use util::ResultExt; @@ -70,7 +69,7 @@ impl View for CollabTitlebarItem { }; let project = self.project.read(cx); - let theme = cx.global::().theme.clone(); + let theme = theme::current(cx).clone(); let mut left_container = Flex::row(); let mut right_container = Flex::row().align_children_center(); @@ -298,7 +297,7 @@ impl CollabTitlebarItem { } pub fn toggle_user_menu(&mut self, _: &ToggleUserMenu, cx: &mut ViewContext) { - let theme = cx.global::().theme.clone(); + let theme = theme::current(cx).clone(); let avatar_style = theme.workspace.titlebar.leader_avatar.clone(); let item_style = theme.context_menu.item.disabled_style().clone(); self.user_menu.update(cx, |user_menu, cx| { @@ -866,7 +865,7 @@ impl CollabTitlebarItem { ) -> Option> { enum ConnectionStatusButton {} - let theme = &cx.global::().theme.clone(); + let theme = &theme::current(cx).clone(); match status { client::Status::ConnectionError | client::Status::ConnectionLost diff --git a/crates/collab_ui/src/contact_finder.rs b/crates/collab_ui/src/contact_finder.rs index 8530867f14..b5f2416a5b 100644 --- a/crates/collab_ui/src/contact_finder.rs +++ b/crates/collab_ui/src/contact_finder.rs @@ -1,7 +1,6 @@ use client::{ContactRequestStatus, User, UserStore}; use gpui::{elements::*, AppContext, ModelHandle, MouseState, Task, ViewContext}; use picker::{Picker, PickerDelegate, PickerEvent}; -use settings::Settings; use std::sync::Arc; use util::TryFutureExt; @@ -98,7 +97,7 @@ impl PickerDelegate for ContactFinderDelegate { selected: bool, cx: &gpui::AppContext, ) -> AnyElement> { - let theme = &cx.global::().theme; + let theme = &theme::current(cx); let user = &self.potential_contacts[ix]; let request_status = self.user_store.read(cx).contact_request_status(user); diff --git a/crates/collab_ui/src/contact_list.rs b/crates/collab_ui/src/contact_list.rs index 452867b8c4..e8dae210c4 100644 --- a/crates/collab_ui/src/contact_list.rs +++ b/crates/collab_ui/src/contact_list.rs @@ -14,7 +14,6 @@ use gpui::{ use menu::{Confirm, SelectNext, SelectPrev}; use project::Project; use serde::Deserialize; -use settings::Settings; use std::{mem, sync::Arc}; use theme::IconButton; use workspace::Workspace; @@ -192,7 +191,7 @@ impl ContactList { .detach(); let list_state = ListState::::new(0, Orientation::Top, 1000., move |this, ix, cx| { - let theme = cx.global::().theme.clone(); + let theme = theme::current(cx).clone(); let is_selected = this.selection == Some(ix); let current_project_id = this.project.read(cx).remote_id(); @@ -1313,7 +1312,7 @@ impl View for ContactList { fn render(&mut self, cx: &mut ViewContext) -> AnyElement { enum AddContact {} - let theme = cx.global::().theme.clone(); + let theme = theme::current(cx).clone(); Flex::column() .with_child( diff --git a/crates/collab_ui/src/contacts_popover.rs b/crates/collab_ui/src/contacts_popover.rs index 35734d81f4..1d6d1c84c7 100644 --- a/crates/collab_ui/src/contacts_popover.rs +++ b/crates/collab_ui/src/contacts_popover.rs @@ -9,7 +9,6 @@ use gpui::{ }; use picker::PickerEvent; use project::Project; -use settings::Settings; use workspace::Workspace; actions!(contacts_popover, [ToggleContactFinder]); @@ -108,7 +107,7 @@ impl View for ContactsPopover { } fn render(&mut self, cx: &mut ViewContext) -> AnyElement { - let theme = cx.global::().theme.clone(); + let theme = theme::current(cx).clone(); let child = match &self.child { Child::ContactList(child) => ChildView::new(child, cx), Child::ContactFinder(child) => ChildView::new(child, cx), diff --git a/crates/collab_ui/src/incoming_call_notification.rs b/crates/collab_ui/src/incoming_call_notification.rs index 35484b3309..ed3e648555 100644 --- a/crates/collab_ui/src/incoming_call_notification.rs +++ b/crates/collab_ui/src/incoming_call_notification.rs @@ -9,7 +9,6 @@ use gpui::{ platform::{CursorStyle, MouseButton, WindowBounds, WindowKind, WindowOptions}, AnyElement, AppContext, Entity, View, ViewContext, }; -use settings::Settings; use util::ResultExt; use workspace::AppState; @@ -26,7 +25,7 @@ pub fn init(app_state: &Arc, cx: &mut AppContext) { if let Some(incoming_call) = incoming_call { const PADDING: f32 = 16.; let window_size = cx.read(|cx| { - let theme = &cx.global::().theme.incoming_call_notification; + let theme = &theme::current(cx).incoming_call_notification; vec2f(theme.window_width, theme.window_height) }); @@ -106,7 +105,7 @@ impl IncomingCallNotification { } fn render_caller(&self, cx: &mut ViewContext) -> AnyElement { - let theme = &cx.global::().theme.incoming_call_notification; + let theme = &theme::current(cx).incoming_call_notification; let default_project = proto::ParticipantProject::default(); let initial_project = self .call @@ -170,10 +169,11 @@ impl IncomingCallNotification { enum Accept {} enum Decline {} + let theme = theme::current(cx); Flex::column() .with_child( - MouseEventHandler::::new(0, cx, |_, cx| { - let theme = &cx.global::().theme.incoming_call_notification; + MouseEventHandler::::new(0, cx, |_, _| { + let theme = &theme.incoming_call_notification; Label::new("Accept", theme.accept_button.text.clone()) .aligned() .contained() @@ -186,8 +186,8 @@ impl IncomingCallNotification { .flex(1., true), ) .with_child( - MouseEventHandler::::new(0, cx, |_, cx| { - let theme = &cx.global::().theme.incoming_call_notification; + MouseEventHandler::::new(0, cx, |_, _| { + let theme = &theme.incoming_call_notification; Label::new("Decline", theme.decline_button.text.clone()) .aligned() .contained() @@ -200,12 +200,7 @@ impl IncomingCallNotification { .flex(1., true), ) .constrained() - .with_width( - cx.global::() - .theme - .incoming_call_notification - .button_width, - ) + .with_width(theme.incoming_call_notification.button_width) .into_any() } } @@ -220,12 +215,7 @@ impl View for IncomingCallNotification { } fn render(&mut self, cx: &mut ViewContext) -> AnyElement { - let background = cx - .global::() - .theme - .incoming_call_notification - .background; - + let background = theme::current(cx).incoming_call_notification.background; Flex::row() .with_child(self.render_caller(cx)) .with_child(self.render_buttons(cx)) diff --git a/crates/collab_ui/src/notifications.rs b/crates/collab_ui/src/notifications.rs index 1dec5a8411..abeb65b1dc 100644 --- a/crates/collab_ui/src/notifications.rs +++ b/crates/collab_ui/src/notifications.rs @@ -4,7 +4,6 @@ use gpui::{ platform::{CursorStyle, MouseButton}, AnyElement, Element, View, ViewContext, }; -use settings::Settings; use std::sync::Arc; enum Dismiss {} @@ -22,7 +21,7 @@ where F: 'static + Fn(&mut V, &mut ViewContext), V: View, { - let theme = cx.global::().theme.clone(); + let theme = theme::current(cx).clone(); let theme = &theme.contact_notification; Flex::column() diff --git a/crates/collab_ui/src/project_shared_notification.rs b/crates/collab_ui/src/project_shared_notification.rs index 8a41368276..155209f470 100644 --- a/crates/collab_ui/src/project_shared_notification.rs +++ b/crates/collab_ui/src/project_shared_notification.rs @@ -7,7 +7,6 @@ use gpui::{ platform::{CursorStyle, MouseButton, WindowBounds, WindowKind, WindowOptions}, AppContext, Entity, View, ViewContext, }; -use settings::Settings; use std::sync::{Arc, Weak}; use workspace::AppState; @@ -22,7 +21,7 @@ pub fn init(app_state: &Arc, cx: &mut AppContext) { worktree_root_names, } => { const PADDING: f32 = 16.; - let theme = &cx.global::().theme.project_shared_notification; + let theme = &theme::current(cx).project_shared_notification; let window_size = vec2f(theme.window_width, theme.window_height); for screen in cx.platform().screens() { @@ -109,7 +108,7 @@ impl ProjectSharedNotification { } fn render_owner(&self, cx: &mut ViewContext) -> AnyElement { - let theme = &cx.global::().theme.project_shared_notification; + let theme = &theme::current(cx).project_shared_notification; Flex::row() .with_children(self.owner.avatar.clone().map(|avatar| { Image::from_data(avatar) @@ -167,10 +166,11 @@ impl ProjectSharedNotification { enum Open {} enum Dismiss {} + let theme = theme::current(cx); Flex::column() .with_child( - MouseEventHandler::::new(0, cx, |_, cx| { - let theme = &cx.global::().theme.project_shared_notification; + MouseEventHandler::::new(0, cx, |_, _| { + let theme = &theme.project_shared_notification; Label::new("Open", theme.open_button.text.clone()) .aligned() .contained() @@ -181,8 +181,8 @@ impl ProjectSharedNotification { .flex(1., true), ) .with_child( - MouseEventHandler::::new(0, cx, |_, cx| { - let theme = &cx.global::().theme.project_shared_notification; + MouseEventHandler::::new(0, cx, |_, _| { + let theme = &theme.project_shared_notification; Label::new("Dismiss", theme.dismiss_button.text.clone()) .aligned() .contained() @@ -195,12 +195,7 @@ impl ProjectSharedNotification { .flex(1., true), ) .constrained() - .with_width( - cx.global::() - .theme - .project_shared_notification - .button_width, - ) + .with_width(theme.project_shared_notification.button_width) .into_any() } } @@ -215,11 +210,7 @@ impl View for ProjectSharedNotification { } fn render(&mut self, cx: &mut ViewContext) -> gpui::AnyElement { - let background = cx - .global::() - .theme - .project_shared_notification - .background; + let background = theme::current(cx).project_shared_notification.background; Flex::row() .with_child(self.render_owner(cx)) .with_child(self.render_buttons(cx)) diff --git a/crates/command_palette/src/command_palette.rs b/crates/command_palette/src/command_palette.rs index 12134f6d6e..2ee93a0734 100644 --- a/crates/command_palette/src/command_palette.rs +++ b/crates/command_palette/src/command_palette.rs @@ -5,7 +5,6 @@ use gpui::{ ViewContext, }; use picker::{Picker, PickerDelegate, PickerEvent}; -use settings::Settings; use std::cmp; use util::ResultExt; use workspace::Workspace; @@ -185,8 +184,7 @@ impl PickerDelegate for CommandPaletteDelegate { ) -> AnyElement> { let mat = &self.matches[ix]; let command = &self.actions[mat.candidate_id]; - let settings = cx.global::(); - let theme = &settings.theme; + let theme = theme::current(cx); let style = theme.picker.item.style_for(mouse_state, selected); let key_style = &theme.command_palette.key.style_for(mouse_state, selected); let keystroke_spacing = theme.command_palette.keystroke_spacing; @@ -366,6 +364,7 @@ mod tests { fn init_test(cx: &mut TestAppContext) -> Arc { cx.update(|cx| { let app_state = AppState::test(cx); + theme::init((), cx); language::init(cx); editor::init(cx); workspace::init(app_state.clone(), cx); diff --git a/crates/context_menu/src/context_menu.rs b/crates/context_menu/src/context_menu.rs index f0d477e42f..fb455fe1d0 100644 --- a/crates/context_menu/src/context_menu.rs +++ b/crates/context_menu/src/context_menu.rs @@ -8,7 +8,6 @@ use gpui::{ View, ViewContext, }; use menu::*; -use settings::Settings; use std::{any::TypeId, borrow::Cow, sync::Arc, time::Duration}; pub fn init(cx: &mut AppContext) { @@ -323,7 +322,7 @@ impl ContextMenu { } fn render_menu_for_measurement(&self, cx: &mut ViewContext) -> impl Element { - let style = cx.global::().theme.context_menu.clone(); + let style = theme::current(cx).context_menu.clone(); Flex::row() .with_child( Flex::column().with_children(self.items.iter().enumerate().map(|(ix, item)| { @@ -403,7 +402,7 @@ impl ContextMenu { enum Menu {} enum MenuItem {} - let style = cx.global::().theme.context_menu.clone(); + let style = theme::current(cx).context_menu.clone(); MouseEventHandler::::new(0, cx, |_, cx| { Flex::column() diff --git a/crates/copilot/src/sign_in.rs b/crates/copilot/src/sign_in.rs index da3c96956e..764a0e4df1 100644 --- a/crates/copilot/src/sign_in.rs +++ b/crates/copilot/src/sign_in.rs @@ -6,7 +6,6 @@ use gpui::{ AnyElement, AnyViewHandle, AppContext, ClipboardItem, Element, Entity, View, ViewContext, ViewHandle, }; -use settings::Settings; use theme::ui::modal; #[derive(PartialEq, Eq, Debug, Clone)] @@ -68,7 +67,7 @@ fn create_copilot_auth_window( cx: &mut AppContext, status: &Status, ) -> ViewHandle { - let window_size = cx.global::().theme.copilot.modal.dimensions(); + let window_size = theme::current(cx).copilot.modal.dimensions(); let window_options = WindowOptions { bounds: WindowBounds::Fixed(RectF::new(Default::default(), window_size)), titlebar: None, @@ -338,7 +337,7 @@ impl View for CopilotCodeVerification { fn render(&mut self, cx: &mut ViewContext) -> AnyElement { enum ConnectModal {} - let style = cx.global::().theme.clone(); + let style = theme::current(cx).clone(); modal::( "Connect Copilot to Zed", diff --git a/crates/copilot_button/src/copilot_button.rs b/crates/copilot_button/src/copilot_button.rs index d04f1e0e75..560506a529 100644 --- a/crates/copilot_button/src/copilot_button.rs +++ b/crates/copilot_button/src/copilot_button.rs @@ -10,7 +10,7 @@ use gpui::{ ViewContext, ViewHandle, WeakViewHandle, WindowContext, }; use language::language_settings::{self, all_language_settings, AllLanguageSettings}; -use settings::{update_settings_file, Settings, SettingsStore}; +use settings::{update_settings_file, SettingsStore}; use std::{path::Path, sync::Arc}; use util::{paths, ResultExt}; use workspace::{ @@ -46,8 +46,7 @@ impl View for CopilotButton { return Empty::new().into_any(); } - let settings = cx.global::(); - let theme = settings.theme.clone(); + let theme = theme::current(cx).clone(); let active = self.popup_menu.read(cx).visible(); let Some(copilot) = Copilot::global(cx) else { return Empty::new().into_any(); @@ -158,7 +157,7 @@ impl CopilotButton { Copilot::global(cx).map(|copilot| cx.observe(&copilot, |_, _, cx| cx.notify()).detach()); - cx.observe_global::(move |_, cx| cx.notify()) + cx.observe_global::(move |_, cx| cx.notify()) .detach(); Self { @@ -249,7 +248,7 @@ impl CopilotButton { menu_options.push(ContextMenuItem::Separator); - let icon_style = cx.global::().theme.copilot.out_link_icon.clone(); + let icon_style = theme::current(cx).copilot.out_link_icon.clone(); menu_options.push(ContextMenuItem::action( move |state: &mut MouseState, style: &theme::ContextMenuItem| { Flex::row() @@ -316,7 +315,7 @@ async fn configure_disabled_globs( let settings_editor = workspace .update(&mut cx, |_, cx| { create_and_open_local_file(&paths::SETTINGS, cx, || { - Settings::initial_user_settings_content(&assets::Assets) + settings::initial_user_settings_content(&assets::Assets) .as_ref() .into() }) diff --git a/crates/diagnostics/Cargo.toml b/crates/diagnostics/Cargo.toml index 9d455f520e..4e898cca0a 100644 --- a/crates/diagnostics/Cargo.toml +++ b/crates/diagnostics/Cargo.toml @@ -31,6 +31,7 @@ language = { path = "../language", features = ["test-support"] } lsp = { path = "../lsp", features = ["test-support"] } gpui = { path = "../gpui", features = ["test-support"] } workspace = { path = "../workspace", features = ["test-support"] } +theme = { path = "../theme", features = ["test-support"] } serde_json.workspace = true unindent.workspace = true diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index 4ce1303ba4..458ca51ce3 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -20,7 +20,6 @@ use language::{ use lsp::LanguageServerId; use project::{DiagnosticSummary, Project, ProjectPath}; use serde_json::json; -use settings::Settings; use smallvec::SmallVec; use std::{ any::{Any, TypeId}, @@ -30,6 +29,7 @@ use std::{ path::PathBuf, sync::Arc, }; +use theme::ThemeSettings; use util::TryFutureExt; use workspace::{ item::{BreadcrumbText, Item, ItemEvent, ItemHandle}, @@ -89,7 +89,7 @@ impl View for ProjectDiagnosticsEditor { fn render(&mut self, cx: &mut ViewContext) -> AnyElement { if self.path_states.is_empty() { - let theme = &cx.global::().theme.project_diagnostics; + let theme = &theme::current(cx).project_diagnostics; Label::new("No problems in workspace", theme.empty_message.clone()) .aligned() .contained() @@ -537,7 +537,7 @@ impl Item for ProjectDiagnosticsEditor { render_summary( &self.summary, &style.label.text, - &cx.global::().theme.project_diagnostics, + &theme::current(cx).project_diagnostics, ) } @@ -679,7 +679,7 @@ impl Item for ProjectDiagnosticsEditor { fn diagnostic_header_renderer(diagnostic: Diagnostic) -> RenderBlock { let (message, highlights) = highlight_diagnostic_message(Vec::new(), &diagnostic.message); Arc::new(move |cx| { - let settings = cx.global::(); + let settings = settings::get_setting::(None, cx); let theme = &settings.theme.editor; let style = theme.diagnostic_header.clone(); let font_size = (style.text_scale_factor @@ -832,23 +832,23 @@ mod tests { "/test", json!({ "consts.rs": " - const a: i32 = 'a'; - const b: i32 = c; - " + const a: i32 = 'a'; + const b: i32 = c; + " .unindent(), "main.rs": " - fn main() { - let x = vec![]; - let y = vec![]; - a(x); - b(y); - // comment 1 - // comment 2 - c(y); - d(x); - } - " + fn main() { + let x = vec![]; + let y = vec![]; + a(x); + b(y); + // comment 1 + // comment 2 + c(y); + d(x); + } + " .unindent(), }), ) @@ -1496,8 +1496,8 @@ mod tests { fn init_test(cx: &mut TestAppContext) { cx.update(|cx| { - cx.set_global(Settings::test(cx)); cx.set_global(SettingsStore::test(cx)); + theme::init((), cx); language::init(cx); client::init_settings(cx); workspace::init_settings(cx); diff --git a/crates/diagnostics/src/items.rs b/crates/diagnostics/src/items.rs index f0ceacc619..f84846eae1 100644 --- a/crates/diagnostics/src/items.rs +++ b/crates/diagnostics/src/items.rs @@ -7,7 +7,6 @@ use gpui::{ }; use language::Diagnostic; use lsp::LanguageServerId; -use settings::Settings; use workspace::{item::ItemHandle, StatusItemView, Workspace}; use crate::ProjectDiagnosticsEditor; @@ -92,13 +91,12 @@ impl View for DiagnosticIndicator { enum Summary {} enum Message {} - let tooltip_style = cx.global::().theme.tooltip.clone(); + let tooltip_style = theme::current(cx).tooltip.clone(); let in_progress = !self.in_progress_checks.is_empty(); let mut element = Flex::row().with_child( MouseEventHandler::::new(0, cx, |state, cx| { - let style = cx - .global::() - .theme + let theme = theme::current(cx); + let style = theme .workspace .status_bar .diagnostic_summary @@ -184,7 +182,7 @@ impl View for DiagnosticIndicator { .into_any(), ); - let style = &cx.global::().theme.workspace.status_bar; + let style = &theme::current(cx).workspace.status_bar; let item_spacing = style.item_spacing; if in_progress { diff --git a/crates/editor/src/blink_manager.rs b/crates/editor/src/blink_manager.rs index 303d0960ed..43d1ec6130 100644 --- a/crates/editor/src/blink_manager.rs +++ b/crates/editor/src/blink_manager.rs @@ -1,6 +1,6 @@ use crate::EditorSettings; use gpui::{Entity, ModelContext}; -use settings::Settings; +use settings::SettingsStore; use smol::Timer; use std::time::Duration; @@ -15,8 +15,8 @@ pub struct BlinkManager { impl BlinkManager { pub fn new(blink_interval: Duration, cx: &mut ModelContext) -> Self { - cx.observe_global::(move |this, cx| { - // Make sure we blink the cursors if the setting is re-enabled + // Make sure we blink the cursors if the setting is re-enabled + cx.observe_global::(move |this, cx| { this.blink_cursors(this.blink_epoch, cx) }) .detach(); diff --git a/crates/editor/src/display_map/block_map.rs b/crates/editor/src/display_map/block_map.rs index 93e43f876c..05ff9886f1 100644 --- a/crates/editor/src/display_map/block_map.rs +++ b/crates/editor/src/display_map/block_map.rs @@ -993,7 +993,7 @@ mod tests { use crate::multi_buffer::MultiBuffer; use gpui::{elements::Empty, Element}; use rand::prelude::*; - use settings::Settings; + use settings::SettingsStore; use std::env; use util::RandomCharIter; @@ -1013,7 +1013,7 @@ mod tests { #[gpui::test] fn test_basic_blocks(cx: &mut gpui::AppContext) { - cx.set_global(Settings::test(cx)); + init_test(cx); let family_id = cx .font_cache() @@ -1189,7 +1189,7 @@ mod tests { #[gpui::test] fn test_blocks_on_wrapped_lines(cx: &mut gpui::AppContext) { - cx.set_global(Settings::test(cx)); + init_test(cx); let family_id = cx .font_cache() @@ -1239,7 +1239,7 @@ mod tests { #[gpui::test(iterations = 100)] fn test_random_blocks(cx: &mut gpui::AppContext, mut rng: StdRng) { - cx.set_global(Settings::test(cx)); + init_test(cx); let operations = env::var("OPERATIONS") .map(|i| i.parse().expect("invalid `OPERATIONS` variable")) @@ -1647,6 +1647,11 @@ mod tests { } } + fn init_test(cx: &mut gpui::AppContext) { + cx.set_global(SettingsStore::test(cx)); + theme::init((), cx); + } + impl TransformBlock { fn as_custom(&self) -> Option<&Block> { match self { diff --git a/crates/editor/src/display_map/fold_map.rs b/crates/editor/src/display_map/fold_map.rs index bd3cd1a620..6ef1ebce1d 100644 --- a/crates/editor/src/display_map/fold_map.rs +++ b/crates/editor/src/display_map/fold_map.rs @@ -1204,7 +1204,7 @@ mod tests { use crate::{MultiBuffer, ToPoint}; use collections::HashSet; use rand::prelude::*; - use settings::Settings; + use settings::SettingsStore; use std::{cmp::Reverse, env, mem, sync::Arc}; use sum_tree::TreeMap; use util::test::sample_text; @@ -1213,7 +1213,7 @@ mod tests { #[gpui::test] fn test_basic_folds(cx: &mut gpui::AppContext) { - cx.set_global(Settings::test(cx)); + init_test(cx); let buffer = MultiBuffer::build_simple(&sample_text(5, 6, 'a'), cx); let subscription = buffer.update(cx, |buffer, _| buffer.subscribe()); let buffer_snapshot = buffer.read(cx).snapshot(cx); @@ -1286,7 +1286,7 @@ mod tests { #[gpui::test] fn test_adjacent_folds(cx: &mut gpui::AppContext) { - cx.set_global(Settings::test(cx)); + init_test(cx); let buffer = MultiBuffer::build_simple("abcdefghijkl", cx); let subscription = buffer.update(cx, |buffer, _| buffer.subscribe()); let buffer_snapshot = buffer.read(cx).snapshot(cx); @@ -1349,7 +1349,7 @@ mod tests { #[gpui::test] fn test_merging_folds_via_edit(cx: &mut gpui::AppContext) { - cx.set_global(Settings::test(cx)); + init_test(cx); let buffer = MultiBuffer::build_simple(&sample_text(5, 6, 'a'), cx); let subscription = buffer.update(cx, |buffer, _| buffer.subscribe()); let buffer_snapshot = buffer.read(cx).snapshot(cx); @@ -1400,7 +1400,7 @@ mod tests { #[gpui::test(iterations = 100)] fn test_random_folds(cx: &mut gpui::AppContext, mut rng: StdRng) { - cx.set_global(Settings::test(cx)); + init_test(cx); let operations = env::var("OPERATIONS") .map(|i| i.parse().expect("invalid `OPERATIONS` variable")) .unwrap_or(10); @@ -1676,6 +1676,10 @@ mod tests { assert_eq!(snapshot.buffer_rows(3).collect::>(), [Some(6)]); } + fn init_test(cx: &mut gpui::AppContext) { + cx.set_global(SettingsStore::test(cx)); + } + impl FoldMap { fn merged_fold_ranges(&self) -> Vec> { let buffer = self.buffer.lock().clone(); diff --git a/crates/editor/src/display_map/suggestion_map.rs b/crates/editor/src/display_map/suggestion_map.rs index f48efc76f4..eac903d0af 100644 --- a/crates/editor/src/display_map/suggestion_map.rs +++ b/crates/editor/src/display_map/suggestion_map.rs @@ -578,7 +578,7 @@ mod tests { use crate::{display_map::fold_map::FoldMap, MultiBuffer}; use gpui::AppContext; use rand::{prelude::StdRng, Rng}; - use settings::Settings; + use settings::SettingsStore; use std::{ env, ops::{Bound, RangeBounds}, @@ -631,7 +631,8 @@ mod tests { #[gpui::test(iterations = 100)] fn test_random_suggestions(cx: &mut AppContext, mut rng: StdRng) { - cx.set_global(Settings::test(cx)); + init_test(cx); + let operations = env::var("OPERATIONS") .map(|i| i.parse().expect("invalid `OPERATIONS` variable")) .unwrap_or(10); @@ -834,6 +835,11 @@ mod tests { } } + fn init_test(cx: &mut AppContext) { + cx.set_global(SettingsStore::test(cx)); + theme::init((), cx); + } + impl SuggestionMap { pub fn randomly_mutate( &self, diff --git a/crates/editor/src/display_map/wrap_map.rs b/crates/editor/src/display_map/wrap_map.rs index e1de4fce77..478eaf4c7e 100644 --- a/crates/editor/src/display_map/wrap_map.rs +++ b/crates/editor/src/display_map/wrap_map.rs @@ -1043,16 +1043,16 @@ mod tests { }; use gpui::test::observe; use rand::prelude::*; - use settings::Settings; + use settings::SettingsStore; use smol::stream::StreamExt; use std::{cmp, env, num::NonZeroU32}; use text::Rope; #[gpui::test(iterations = 100)] async fn test_random_wraps(cx: &mut gpui::TestAppContext, mut rng: StdRng) { - cx.update(|cx| cx.set_global(Settings::test(cx))); + init_test(cx); + cx.foreground().set_block_on_ticks(0..=50); - cx.foreground().forbid_parking(); let operations = env::var("OPERATIONS") .map(|i| i.parse().expect("invalid `OPERATIONS` variable")) .unwrap_or(10); @@ -1287,6 +1287,14 @@ mod tests { wrap_map.read_with(cx, |map, _| assert!(map.pending_edits.is_empty())); } + fn init_test(cx: &mut gpui::TestAppContext) { + cx.foreground().forbid_parking(); + cx.update(|cx| { + cx.set_global(SettingsStore::test(cx)); + theme::init((), cx); + }); + } + fn wrap_text( unwrapped_text: &str, wrap_width: Option, diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 915e041100..78844ac332 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -73,7 +73,7 @@ use scroll::{ }; use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection}; use serde::{Deserialize, Serialize}; -use settings::{Settings, SettingsStore}; +use settings::SettingsStore; use smallvec::SmallVec; use snippet::Snippet; use std::{ @@ -88,7 +88,7 @@ use std::{ time::{Duration, Instant}, }; pub use sum_tree::Bias; -use theme::{DiagnosticStyle, Theme}; +use theme::{DiagnosticStyle, Theme, ThemeSettings}; use util::{post_inc, RangeExt, ResultExt, TryFutureExt}; use workspace::{ItemNavHistory, ViewId, Workspace}; @@ -1237,8 +1237,8 @@ impl Editor { ) -> Self { let editor_view_id = cx.view_id(); let display_map = cx.add_model(|cx| { - let settings = cx.global::(); - let style = build_style(&*settings, get_field_editor_theme.as_deref(), None, cx); + let settings = settings::get_setting::(None, cx); + let style = build_style(settings, get_field_editor_theme.as_deref(), None, cx); DisplayMap::new( buffer.clone(), style.text.font_id, @@ -1319,7 +1319,7 @@ impl Editor { cx.subscribe(&buffer, Self::on_buffer_event), cx.observe(&display_map, Self::on_display_map_changed), cx.observe(&blink_manager, |_, _, cx| cx.notify()), - cx.observe_global::(Self::settings_changed), + cx.observe_global::(Self::settings_changed), ], }; @@ -1418,7 +1418,7 @@ impl Editor { fn style(&self, cx: &AppContext) -> EditorStyle { build_style( - cx.global::(), + settings::get_setting::(None, cx), self.get_field_editor_theme.as_deref(), self.override_text_style.as_deref(), cx, @@ -6561,8 +6561,8 @@ impl Editor { let buffer = &snapshot.buffer_snapshot; let start = buffer.anchor_before(0); let end = buffer.anchor_after(buffer.len()); - let theme = cx.global::().theme.as_ref(); - self.background_highlights_in_range(start..end, &snapshot, theme) + let theme = theme::current(cx); + self.background_highlights_in_range(start..end, &snapshot, theme.as_ref()) } fn document_highlights_for_position<'a>( @@ -6985,7 +6985,7 @@ impl Editor { let mut lines = Vec::new(); let mut line: VecDeque = VecDeque::new(); - let theme = &cx.global::().theme.editor.syntax; + let theme = &theme::current(cx).editor.syntax; for chunk in chunks { let highlight = chunk.syntax_highlight_id.and_then(|id| id.name(theme)); @@ -7407,7 +7407,7 @@ impl View for Editor { } fn build_style( - settings: &Settings, + settings: &ThemeSettings, get_field_editor_theme: Option<&GetFieldEditorTheme>, override_text_style: Option<&OverrideTextStyle>, cx: &AppContext, @@ -7607,7 +7607,7 @@ pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> Rend } Arc::new(move |cx: &mut BlockContext| { - let settings = cx.global::(); + let settings = settings::get_setting::(None, cx); let theme = &settings.theme.editor; let style = diagnostic_style(diagnostic.severity, is_valid, theme); let font_size = (style.text_scale_factor diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index cf72f0286c..b61c2a780f 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -5452,7 +5452,7 @@ fn test_highlighted_ranges(cx: &mut TestAppContext) { let mut highlighted_ranges = editor.background_highlights_in_range( anchor_range(Point::new(3, 4)..Point::new(7, 4)), &snapshot, - cx.global::().theme.as_ref(), + theme::current(cx).as_ref(), ); // Enforce a consistent ordering based on color without relying on the ordering of the // highlight's `TypeId` which is non-deterministic. @@ -5482,7 +5482,7 @@ fn test_highlighted_ranges(cx: &mut TestAppContext) { editor.background_highlights_in_range( anchor_range(Point::new(5, 6)..Point::new(6, 4)), &snapshot, - cx.global::().theme.as_ref(), + theme::current(cx).as_ref(), ), &[( DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5), @@ -6681,7 +6681,7 @@ pub(crate) fn init_test(cx: &mut TestAppContext, f: fn(&mut AllLanguageSettingsC cx.update(|cx| { cx.set_global(SettingsStore::test(cx)); - cx.set_global(Settings::test(cx)); + theme::init((), cx); client::init_settings(cx); language::init(cx); Project::init_settings(cx); diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index bc5998cc29..56a4f4ad18 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -40,7 +40,6 @@ use language::{ Selection, }; use project::ProjectPath; -use settings::Settings; use smallvec::SmallVec; use std::{ borrow::Cow, @@ -611,7 +610,7 @@ impl EditorElement { layout: &mut LayoutState, cx: &mut ViewContext, ) { - let diff_style = &cx.global::().theme.editor.diff.clone(); + let diff_style = &theme::current(cx).editor.diff.clone(); let line_height = layout.position_map.line_height; let scroll_position = layout.position_map.snapshot.scroll_position(); @@ -1417,7 +1416,7 @@ impl EditorElement { editor: &mut Editor, cx: &mut LayoutContext, ) -> (f32, Vec) { - let tooltip_style = cx.global::().theme.tooltip.clone(); + let tooltip_style = theme::current(cx).tooltip.clone(); let scroll_x = snapshot.scroll_anchor.offset.x(); let (fixed_blocks, non_fixed_blocks) = snapshot .blocks_in_range(rows.clone()) @@ -1936,11 +1935,11 @@ impl Element for EditorElement { let is_singleton = editor.is_singleton(cx); let highlighted_rows = editor.highlighted_rows(); - let theme = cx.global::().theme.as_ref(); + let theme = theme::current(cx); let highlighted_ranges = editor.background_highlights_in_range( start_anchor..end_anchor, &snapshot.display_snapshot, - theme, + theme.as_ref(), ); fold_ranges.extend( diff --git a/crates/editor/src/hover_popover.rs b/crates/editor/src/hover_popover.rs index 29d32e4a43..24f09f1082 100644 --- a/crates/editor/src/hover_popover.rs +++ b/crates/editor/src/hover_popover.rs @@ -12,7 +12,6 @@ use gpui::{ }; use language::{Bias, DiagnosticEntry, DiagnosticSeverity, Language, LanguageRegistry}; use project::{HoverBlock, HoverBlockKind, Project}; -use settings::Settings; use std::{ops::Range, sync::Arc, time::Duration}; use util::TryFutureExt; @@ -654,7 +653,7 @@ impl DiagnosticPopover { _ => style.hover_popover.container, }; - let tooltip_style = cx.global::().theme.tooltip.clone(); + let tooltip_style = theme::current(cx).tooltip.clone(); MouseEventHandler::::new(0, cx, |_, _| { text.with_soft_wrap(true) diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index 9e122cc63d..988f263337 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -16,7 +16,6 @@ use language::{ }; use project::{FormatTrigger, Item as _, Project, ProjectPath}; use rpc::proto::{self, update_view}; -use settings::Settings; use smallvec::SmallVec; use std::{ borrow::Cow, @@ -1116,7 +1115,7 @@ impl View for CursorPosition { fn render(&mut self, cx: &mut ViewContext) -> AnyElement { if let Some(position) = self.position { - let theme = &cx.global::().theme.workspace.status_bar; + let theme = &theme::current(cx).workspace.status_bar; let mut text = format!( "{}{FILE_ROW_COLUMN_DELIMITER}{}", position.row + 1, diff --git a/crates/editor/src/link_go_to_definition.rs b/crates/editor/src/link_go_to_definition.rs index 04cf4611f1..a52647fb55 100644 --- a/crates/editor/src/link_go_to_definition.rs +++ b/crates/editor/src/link_go_to_definition.rs @@ -2,7 +2,6 @@ use crate::{Anchor, DisplayPoint, Editor, EditorSnapshot, SelectPhase}; use gpui::{Task, ViewContext}; use language::{Bias, ToOffset}; use project::LocationLink; -use settings::Settings; use std::ops::Range; use util::TryFutureExt; @@ -210,7 +209,7 @@ pub fn show_link_definition( }); // Highlight symbol using theme link definition highlight style - let style = cx.global::().theme.editor.link_definition; + let style = theme::current(cx).editor.link_definition; this.highlight_text::( vec![highlight_range], style, diff --git a/crates/editor/src/movement.rs b/crates/editor/src/movement.rs index 311616cfe0..6c9bd6cb4f 100644 --- a/crates/editor/src/movement.rs +++ b/crates/editor/src/movement.rs @@ -367,10 +367,9 @@ pub fn split_display_range_by_lines( #[cfg(test)] mod tests { - use settings::{Settings, SettingsStore}; - use super::*; use crate::{test::marked_display_snapshot, Buffer, DisplayMap, ExcerptRange, MultiBuffer}; + use settings::SettingsStore; #[gpui::test] fn test_previous_word_start(cx: &mut gpui::AppContext) { @@ -703,7 +702,7 @@ mod tests { fn init_test(cx: &mut gpui::AppContext) { cx.set_global(SettingsStore::test(cx)); - cx.set_global(Settings::test(cx)); + theme::init((), cx); language::init(cx); crate::init(cx); } diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index 1e07bba065..99df8ce796 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/crates/editor/src/multi_buffer.rs @@ -3806,10 +3806,9 @@ mod tests { use gpui::{AppContext, TestAppContext}; use language::{Buffer, Rope}; use rand::prelude::*; - use settings::Settings; + use settings::SettingsStore; use std::{env, rc::Rc}; use unindent::Unindent; - use util::test::sample_text; #[gpui::test] @@ -5055,7 +5054,8 @@ mod tests { #[gpui::test] fn test_history(cx: &mut AppContext) { - cx.set_global(Settings::test(cx)); + cx.set_global(SettingsStore::test(cx)); + let buffer_1 = cx.add_model(|cx| Buffer::new(0, "1234", cx)); let buffer_2 = cx.add_model(|cx| Buffer::new(0, "5678", cx)); let multibuffer = cx.add_model(|_| MultiBuffer::new(0)); diff --git a/crates/editor/src/test/editor_lsp_test_context.rs b/crates/editor/src/test/editor_lsp_test_context.rs index 9f2ab4ffac..0fe49d4d04 100644 --- a/crates/editor/src/test/editor_lsp_test_context.rs +++ b/crates/editor/src/test/editor_lsp_test_context.rs @@ -37,6 +37,7 @@ impl<'a> EditorLspTestContext<'a> { let app_state = cx.update(AppState::test); cx.update(|cx| { + theme::init((), cx); language::init(cx); crate::init(cx); pane::init(cx); diff --git a/crates/feedback/src/deploy_feedback_button.rs b/crates/feedback/src/deploy_feedback_button.rs index b464d00887..9133174475 100644 --- a/crates/feedback/src/deploy_feedback_button.rs +++ b/crates/feedback/src/deploy_feedback_button.rs @@ -3,7 +3,6 @@ use gpui::{ platform::{CursorStyle, MouseButton}, Entity, View, ViewContext, WeakViewHandle, }; -use settings::Settings; use workspace::{item::ItemHandle, StatusItemView, Workspace}; use crate::feedback_editor::{FeedbackEditor, GiveFeedback}; @@ -33,7 +32,7 @@ impl View for DeployFeedbackButton { fn render(&mut self, cx: &mut ViewContext) -> AnyElement { let active = self.active; - let theme = cx.global::().theme.clone(); + let theme = theme::current(cx).clone(); Stack::new() .with_child( MouseEventHandler::::new(0, cx, |state, _| { diff --git a/crates/feedback/src/feedback_info_text.rs b/crates/feedback/src/feedback_info_text.rs index 9aee4e0e68..5852cd9a61 100644 --- a/crates/feedback/src/feedback_info_text.rs +++ b/crates/feedback/src/feedback_info_text.rs @@ -3,7 +3,6 @@ use gpui::{ platform::{CursorStyle, MouseButton}, AnyElement, Element, Entity, View, ViewContext, ViewHandle, }; -use settings::Settings; use workspace::{item::ItemHandle, ToolbarItemLocation, ToolbarItemView}; use crate::{feedback_editor::FeedbackEditor, open_zed_community_repo, OpenZedCommunityRepo}; @@ -30,7 +29,7 @@ impl View for FeedbackInfoText { } fn render(&mut self, cx: &mut ViewContext) -> AnyElement { - let theme = cx.global::().theme.clone(); + let theme = theme::current(cx).clone(); Flex::row() .with_child( diff --git a/crates/feedback/src/submit_feedback_button.rs b/crates/feedback/src/submit_feedback_button.rs index ccd58c3dc9..56bc235570 100644 --- a/crates/feedback/src/submit_feedback_button.rs +++ b/crates/feedback/src/submit_feedback_button.rs @@ -5,7 +5,6 @@ use gpui::{ platform::{CursorStyle, MouseButton}, AnyElement, AppContext, Element, Entity, Task, View, ViewContext, ViewHandle, }; -use settings::Settings; use workspace::{item::ItemHandle, ToolbarItemLocation, ToolbarItemView}; pub fn init(cx: &mut AppContext) { @@ -46,7 +45,7 @@ impl View for SubmitFeedbackButton { } fn render(&mut self, cx: &mut ViewContext) -> AnyElement { - let theme = cx.global::().theme.clone(); + let theme = theme::current(cx).clone(); enum SubmitFeedbackButton {} MouseEventHandler::::new(0, cx, |state, _| { let style = theme.feedback.submit_button.style_for(state, false); diff --git a/crates/file_finder/src/file_finder.rs b/crates/file_finder/src/file_finder.rs index 37ab4218a8..b318f1d167 100644 --- a/crates/file_finder/src/file_finder.rs +++ b/crates/file_finder/src/file_finder.rs @@ -5,7 +5,6 @@ use gpui::{ }; use picker::{Picker, PickerDelegate}; use project::{PathMatchCandidateSet, Project, ProjectPath, WorktreeId}; -use settings::Settings; use std::{ path::Path, sync::{ @@ -324,8 +323,8 @@ impl PickerDelegate for FileFinderDelegate { cx: &AppContext, ) -> AnyElement> { let path_match = &self.matches[ix]; - let settings = cx.global::(); - let style = settings.theme.picker.item.style_for(mouse_state, selected); + let theme = theme::current(cx); + let style = theme.picker.item.style_for(mouse_state, selected); let (file_name, file_name_positions, full_path, full_path_positions) = self.labels_for_match(path_match); Flex::column() @@ -909,6 +908,7 @@ mod tests { cx.foreground().forbid_parking(); cx.update(|cx| { let state = AppState::test(cx); + theme::init((), cx); language::init(cx); super::init(cx); editor::init(cx); diff --git a/crates/go_to_line/Cargo.toml b/crates/go_to_line/Cargo.toml index 8f99aa366c..441f7ef7e4 100644 --- a/crates/go_to_line/Cargo.toml +++ b/crates/go_to_line/Cargo.toml @@ -16,4 +16,5 @@ settings = { path = "../settings" } text = { path = "../text" } workspace = { path = "../workspace" } postage.workspace = true +theme = { path = "../theme" } util = { path = "../util" } diff --git a/crates/go_to_line/src/go_to_line.rs b/crates/go_to_line/src/go_to_line.rs index 967f17b794..0b41ee6dca 100644 --- a/crates/go_to_line/src/go_to_line.rs +++ b/crates/go_to_line/src/go_to_line.rs @@ -6,7 +6,6 @@ use gpui::{ View, ViewContext, ViewHandle, }; use menu::{Cancel, Confirm}; -use settings::Settings; use text::{Bias, Point}; use util::paths::FILE_ROW_COLUMN_DELIMITER; use workspace::{Modal, Workspace}; @@ -151,7 +150,7 @@ impl View for GoToLine { } fn render(&mut self, cx: &mut ViewContext) -> AnyElement { - let theme = &cx.global::().theme.picker; + let theme = &theme::current(cx).picker; let label = format!( "{}{FILE_ROW_COLUMN_DELIMITER}{} of {} lines", diff --git a/crates/language/src/language_settings.rs b/crates/language/src/language_settings.rs index 55afd2f572..4d33366a71 100644 --- a/crates/language/src/language_settings.rs +++ b/crates/language/src/language_settings.rs @@ -254,6 +254,7 @@ impl settings::Setting for AllLanguageSettings { fn json_schema( generator: &mut schemars::gen::SchemaGenerator, params: &settings::SettingsJsonSchemaParams, + _: &AppContext, ) -> schemars::schema::RootSchema { let mut root_schema = generator.root_schema_for::(); diff --git a/crates/language_selector/src/active_buffer_language.rs b/crates/language_selector/src/active_buffer_language.rs index 425f4c8dd7..2c78b89f31 100644 --- a/crates/language_selector/src/active_buffer_language.rs +++ b/crates/language_selector/src/active_buffer_language.rs @@ -4,7 +4,6 @@ use gpui::{ platform::{CursorStyle, MouseButton}, Entity, Subscription, View, ViewContext, ViewHandle, WeakViewHandle, }; -use settings::Settings; use std::sync::Arc; use workspace::{item::ItemHandle, StatusItemView, Workspace}; @@ -55,7 +54,7 @@ impl View for ActiveBufferLanguage { }; MouseEventHandler::::new(0, cx, |state, cx| { - let theme = &cx.global::().theme.workspace.status_bar; + let theme = &theme::current(cx).workspace.status_bar; let style = theme.active_language.style_for(state, false); Label::new(active_language_text, style.text.clone()) .contained() diff --git a/crates/language_selector/src/language_selector.rs b/crates/language_selector/src/language_selector.rs index fd43111443..817901cd3a 100644 --- a/crates/language_selector/src/language_selector.rs +++ b/crates/language_selector/src/language_selector.rs @@ -8,7 +8,6 @@ use gpui::{actions, elements::*, AppContext, ModelHandle, MouseState, ViewContex use language::{Buffer, LanguageRegistry}; use picker::{Picker, PickerDelegate, PickerEvent}; use project::Project; -use settings::Settings; use std::sync::Arc; use util::ResultExt; use workspace::Workspace; @@ -179,8 +178,7 @@ impl PickerDelegate for LanguageSelectorDelegate { selected: bool, cx: &AppContext, ) -> AnyElement> { - let settings = cx.global::(); - let theme = &settings.theme; + let theme = theme::current(cx); let mat = &self.matches[ix]; let style = theme.picker.item.style_for(mouse_state, selected); let buffer_language_name = self.buffer.read(cx).language().map(|l| l.name()); diff --git a/crates/lsp_log/src/lsp_log.rs b/crates/lsp_log/src/lsp_log.rs index 0efcd3afc8..db41c6ff4d 100644 --- a/crates/lsp_log/src/lsp_log.rs +++ b/crates/lsp_log/src/lsp_log.rs @@ -13,7 +13,6 @@ use gpui::{ }; use language::{Buffer, LanguageServerId, LanguageServerName}; use project::{Project, WorktreeId}; -use settings::Settings; use std::{borrow::Cow, sync::Arc}; use theme::{ui, Theme}; use workspace::{ @@ -304,7 +303,7 @@ impl View for LspLogToolbarItemView { } fn render(&mut self, cx: &mut ViewContext) -> AnyElement { - let theme = cx.global::().theme.clone(); + let theme = theme::current(cx).clone(); let Some(log_view) = self.log_view.as_ref() else { return Empty::new().into_any() }; let project = self.project.read(cx); let log_view = log_view.read(cx); diff --git a/crates/outline/Cargo.toml b/crates/outline/Cargo.toml index 91e5011b2a..95272b063e 100644 --- a/crates/outline/Cargo.toml +++ b/crates/outline/Cargo.toml @@ -16,7 +16,9 @@ language = { path = "../language" } picker = { path = "../picker" } settings = { path = "../settings" } text = { path = "../text" } +theme = { path = "../theme" } workspace = { path = "../workspace" } + ordered-float.workspace = true postage.workspace = true smol.workspace = true diff --git a/crates/outline/src/outline.rs b/crates/outline/src/outline.rs index 6ecaf370e4..1e364f5fc8 100644 --- a/crates/outline/src/outline.rs +++ b/crates/outline/src/outline.rs @@ -10,7 +10,6 @@ use gpui::{ use language::Outline; use ordered_float::OrderedFloat; use picker::{Picker, PickerDelegate, PickerEvent}; -use settings::Settings; use std::{ cmp::{self, Reverse}, sync::Arc, @@ -34,7 +33,7 @@ pub fn toggle(workspace: &mut Workspace, _: &Toggle, cx: &mut ViewContext().theme.editor.syntax.as_ref())); + .outline(Some(theme::current(cx).editor.syntax.as_ref())); if let Some(outline) = outline { workspace.toggle_modal(cx, |_, cx| { cx.add_view(|cx| { @@ -204,9 +203,9 @@ impl PickerDelegate for OutlineViewDelegate { selected: bool, cx: &AppContext, ) -> AnyElement> { - let settings = cx.global::(); + let theme = theme::current(cx); + let style = theme.picker.item.style_for(mouse_state, selected); let string_match = &self.matches[ix]; - let style = settings.theme.picker.item.style_for(mouse_state, selected); let outline_item = &self.outline.items[string_match.candidate_id]; Text::new(outline_item.text.clone(), style.label.text.clone()) diff --git a/crates/picker/src/picker.rs b/crates/picker/src/picker.rs index 01749ccf84..69f16e4949 100644 --- a/crates/picker/src/picker.rs +++ b/crates/picker/src/picker.rs @@ -57,7 +57,7 @@ impl View for Picker { } fn render(&mut self, cx: &mut ViewContext) -> AnyElement { - let theme = (self.theme.lock())(&cx.global::().theme); + let theme = (self.theme.lock())(theme::current(cx).as_ref()); let query = self.query(cx); let match_count = self.delegate.match_count(); diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 14359fa288..a487b23716 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -47,7 +47,7 @@ use project_settings::ProjectSettings; use rand::prelude::*; use search::SearchQuery; use serde::Serialize; -use settings::{Settings, SettingsStore}; +use settings::SettingsStore; use sha2::{Digest, Sha256}; use similar::{ChangeTag, TextDiff}; use std::{ @@ -610,12 +610,6 @@ impl Project { root_paths: impl IntoIterator, cx: &mut gpui::TestAppContext, ) -> ModelHandle { - if !cx.read(|cx| cx.has_global::()) { - cx.update(|cx| { - cx.set_global(Settings::test(cx)); - }); - } - let mut languages = LanguageRegistry::test(); languages.set_executor(cx.background()); let http_client = util::http::FakeHttpClient::with_404_response(); @@ -2137,7 +2131,7 @@ impl Project { let (mut settings_changed_tx, mut settings_changed_rx) = watch::channel(); let _ = postage::stream::Stream::try_recv(&mut settings_changed_rx); - let settings_observation = cx.observe_global::(move |_, _| { + let settings_observation = cx.observe_global::(move |_, _| { *settings_changed_tx.borrow_mut() = (); }); cx.spawn_weak(|this, mut cx| async move { diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 7325e69f3f..683ce8ad06 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -20,7 +20,6 @@ use project::{ repository::GitFileStatus, Entry, EntryKind, Project, ProjectEntryId, ProjectPath, Worktree, WorktreeId, }; -use settings::Settings; use std::{ cmp::Ordering, collections::{hash_map, HashMap}, @@ -1113,7 +1112,7 @@ impl ProjectPanel { ComponentHost::new(FileName::new( details.filename.clone(), details.git_status, - FileName::style(style.text.clone(), &cx.global::().theme), + FileName::style(style.text.clone(), &theme::current(cx)), )) .contained() .with_margin_left(style.icon_spacing) @@ -1223,7 +1222,7 @@ impl ProjectPanel { let row_container_style = theme.dragged_entry.container; move |_, cx: &mut ViewContext| { - let theme = cx.global::().theme.clone(); + let theme = theme::current(cx).clone(); Self::render_entry_visual_element( &details, None, @@ -1246,7 +1245,7 @@ impl View for ProjectPanel { fn render(&mut self, cx: &mut gpui::ViewContext) -> gpui::AnyElement { enum ProjectPanel {} - let theme = &cx.global::().theme.project_panel; + let theme = &theme::current(cx).project_panel; let mut container_style = theme.container; let padding = std::mem::take(&mut container_style.padding); let last_worktree_root_id = self.last_worktree_root_id; @@ -1265,7 +1264,7 @@ impl View for ProjectPanel { .sum(), cx, move |this, range, items, cx| { - let theme = cx.global::().theme.clone(); + let theme = theme::current(cx).clone(); let mut dragged_entry_destination = this.dragged_entry_destination.clone(); this.for_each_visible_entry(range, cx, |id, details, cx| { @@ -1302,8 +1301,7 @@ impl View for ProjectPanel { .with_child( MouseEventHandler::::new(2, cx, { let button_style = theme.open_project_button.clone(); - let context_menu_item_style = - cx.global::().theme.context_menu.item.clone(); + let context_menu_item_style = theme::current(cx).context_menu.item.clone(); move |state, cx| { let button_style = button_style.style_for(state, false).clone(); let context_menu_item = @@ -1952,6 +1950,7 @@ mod tests { cx.foreground().forbid_parking(); cx.update(|cx| { cx.set_global(SettingsStore::test(cx)); + theme::init((), cx); language::init(cx); editor::init_settings(cx); workspace::init_settings(cx); diff --git a/crates/project_symbols/Cargo.toml b/crates/project_symbols/Cargo.toml index be2510c895..7e23e42b26 100644 --- a/crates/project_symbols/Cargo.toml +++ b/crates/project_symbols/Cargo.toml @@ -17,7 +17,9 @@ project = { path = "../project" } text = { path = "../text" } settings = { path = "../settings" } workspace = { path = "../workspace" } +theme = { path = "../theme" } util = { path = "../util" } + anyhow.workspace = true ordered-float.workspace = true postage.workspace = true @@ -30,4 +32,5 @@ gpui = { path = "../gpui", features = ["test-support"] } language = { path = "../language", features = ["test-support"] } lsp = { path = "../lsp", features = ["test-support"] } project = { path = "../project", features = ["test-support"] } +theme = { path = "../theme", features = ["test-support"] } workspace = { path = "../workspace", features = ["test-support"] } diff --git a/crates/project_symbols/src/project_symbols.rs b/crates/project_symbols/src/project_symbols.rs index 74edd45c21..992283df01 100644 --- a/crates/project_symbols/src/project_symbols.rs +++ b/crates/project_symbols/src/project_symbols.rs @@ -9,7 +9,6 @@ use gpui::{ use ordered_float::OrderedFloat; use picker::{Picker, PickerDelegate, PickerEvent}; use project::{Project, Symbol}; -use settings::Settings; use std::{borrow::Cow, cmp::Reverse, sync::Arc}; use util::ResultExt; use workspace::Workspace; @@ -195,12 +194,13 @@ impl PickerDelegate for ProjectSymbolsDelegate { selected: bool, cx: &AppContext, ) -> AnyElement> { - let string_match = &self.matches[ix]; - let settings = cx.global::(); - let style = &settings.theme.picker.item; + let theme = theme::current(cx); + let style = &theme.picker.item; let current_style = style.style_for(mouse_state, selected); + + let string_match = &self.matches[ix]; let symbol = &self.symbols[string_match.candidate_id]; - let syntax_runs = styled_runs_for_code_label(&symbol.label, &settings.theme.editor.syntax); + let syntax_runs = styled_runs_for_code_label(&symbol.label, &theme.editor.syntax); let mut path = symbol.path.path.to_string_lossy(); if self.show_worktree_root_name { @@ -371,8 +371,8 @@ mod tests { fn init_test(cx: &mut TestAppContext) { cx.foreground().forbid_parking(); cx.update(|cx| { - cx.set_global(Settings::test(cx)); cx.set_global(SettingsStore::test(cx)); + theme::init((), cx); language::init(cx); Project::init_settings(cx); workspace::init_settings(cx); diff --git a/crates/recent_projects/Cargo.toml b/crates/recent_projects/Cargo.toml index 968ae8e9a4..d9e7546f34 100644 --- a/crates/recent_projects/Cargo.toml +++ b/crates/recent_projects/Cargo.toml @@ -18,6 +18,7 @@ picker = { path = "../picker" } settings = { path = "../settings" } text = { path = "../text" } util = { path = "../util"} +theme = { path = "../theme" } workspace = { path = "../workspace" } ordered-float.workspace = true diff --git a/crates/recent_projects/src/recent_projects.rs b/crates/recent_projects/src/recent_projects.rs index 644e74d878..a1dc8982c7 100644 --- a/crates/recent_projects/src/recent_projects.rs +++ b/crates/recent_projects/src/recent_projects.rs @@ -10,7 +10,6 @@ use gpui::{ use highlighted_workspace_location::HighlightedWorkspaceLocation; use ordered_float::OrderedFloat; use picker::{Picker, PickerDelegate, PickerEvent}; -use settings::Settings; use std::sync::Arc; use workspace::{ notifications::simple_message_notification::MessageNotification, Workspace, WorkspaceLocation, @@ -173,9 +172,10 @@ impl PickerDelegate for RecentProjectsDelegate { selected: bool, cx: &gpui::AppContext, ) -> AnyElement> { - let settings = cx.global::(); + let theme = theme::current(cx); + let style = theme.picker.item.style_for(mouse_state, selected); + let string_match = &self.matches[ix]; - let style = settings.theme.picker.item.style_for(mouse_state, selected); let highlighted_location = HighlightedWorkspaceLocation::new( &string_match, diff --git a/crates/search/src/buffer_search.rs b/crates/search/src/buffer_search.rs index 38f3894743..87a8b265fb 100644 --- a/crates/search/src/buffer_search.rs +++ b/crates/search/src/buffer_search.rs @@ -13,7 +13,6 @@ use gpui::{ }; use project::search::SearchQuery; use serde::Deserialize; -use settings::Settings; use std::{any::Any, sync::Arc}; use util::ResultExt; use workspace::{ @@ -93,7 +92,7 @@ impl View for BufferSearchBar { } fn render(&mut self, cx: &mut ViewContext) -> AnyElement { - let theme = cx.global::().theme.clone(); + let theme = theme::current(cx).clone(); let editor_container = if self.query_contains_error { theme.search.invalid_editor } else { @@ -324,16 +323,12 @@ impl BufferSearchBar { return None; } - let tooltip_style = cx.global::().theme.tooltip.clone(); + let tooltip_style = theme::current(cx).tooltip.clone(); let is_active = self.is_search_option_enabled(option); Some( MouseEventHandler::::new(option as usize, cx, |state, cx| { - let style = cx - .global::() - .theme - .search - .option_button - .style_for(state, is_active); + let theme = theme::current(cx); + let style = theme.search.option_button.style_for(state, is_active); Label::new(icon, style.text.clone()) .contained() .with_style(style.container) @@ -371,16 +366,12 @@ impl BufferSearchBar { tooltip = "Select Next Match"; } }; - let tooltip_style = cx.global::().theme.tooltip.clone(); + let tooltip_style = theme::current(cx).tooltip.clone(); enum NavButton {} MouseEventHandler::::new(direction as usize, cx, |state, cx| { - let style = cx - .global::() - .theme - .search - .option_button - .style_for(state, false); + let theme = theme::current(cx); + let style = theme.search.option_button.style_for(state, false); Label::new(icon, style.text.clone()) .contained() .with_style(style.container) @@ -408,7 +399,7 @@ impl BufferSearchBar { cx: &mut ViewContext, ) -> AnyElement { let tooltip = "Dismiss Buffer Search"; - let tooltip_style = cx.global::().theme.tooltip.clone(); + let tooltip_style = theme::current(cx).tooltip.clone(); enum CloseButton {} MouseEventHandler::::new(0, cx, |state, _| { diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index 0d020da570..17f86c153c 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -17,7 +17,6 @@ use gpui::{ }; use menu::Confirm; use project::{search::SearchQuery, Project}; -use settings::Settings; use smallvec::SmallVec; use std::{ any::{Any, TypeId}, @@ -195,7 +194,7 @@ impl View for ProjectSearchView { if model.match_ranges.is_empty() { enum Status {} - let theme = cx.global::().theme.clone(); + let theme = theme::current(cx).clone(); let text = if self.query_editor.read(cx).text(cx).is_empty() { "" } else if model.pending_search.is_some() { @@ -903,16 +902,12 @@ impl ProjectSearchBar { tooltip = "Select Next Match"; } }; - let tooltip_style = cx.global::().theme.tooltip.clone(); + let tooltip_style = theme::current(cx).tooltip.clone(); enum NavButton {} MouseEventHandler::::new(direction as usize, cx, |state, cx| { - let style = &cx - .global::() - .theme - .search - .option_button - .style_for(state, false); + let theme = theme::current(cx); + let style = theme.search.option_button.style_for(state, false); Label::new(icon, style.text.clone()) .contained() .with_style(style.container) @@ -939,15 +934,11 @@ impl ProjectSearchBar { option: SearchOption, cx: &mut ViewContext, ) -> AnyElement { - let tooltip_style = cx.global::().theme.tooltip.clone(); + let tooltip_style = theme::current(cx).tooltip.clone(); let is_active = self.is_option_enabled(option, cx); MouseEventHandler::::new(option as usize, cx, |state, cx| { - let style = &cx - .global::() - .theme - .search - .option_button - .style_for(state, is_active); + let theme = theme::current(cx); + let style = theme.search.option_button.style_for(state, is_active); Label::new(icon, style.text.clone()) .contained() .with_style(style.container) @@ -992,7 +983,7 @@ impl View for ProjectSearchBar { fn render(&mut self, cx: &mut ViewContext) -> AnyElement { if let Some(search) = self.active_project_search.as_ref() { let search = search.read(cx); - let theme = cx.global::().theme.clone(); + let theme = theme::current(cx).clone(); let query_container_style = if search.panels_with_errors.contains(&InputPanel::Query) { theme.search.invalid_editor } else { @@ -1154,6 +1145,7 @@ pub mod tests { use serde_json::json; use settings::SettingsStore; use std::sync::Arc; + use theme::ThemeSettings; #[gpui::test] async fn test_project_search(deterministic: Arc, cx: &mut TestAppContext) { @@ -1282,9 +1274,12 @@ pub mod tests { cx.set_global(SettingsStore::test(cx)); cx.set_global(ActiveSearches::default()); - let mut settings = Settings::test(cx); - settings.theme = Arc::new(theme); - cx.set_global(settings); + theme::init((), cx); + cx.update_global::(|store, _| { + let mut settings = store.get::(None).clone(); + settings.theme = Arc::new(theme); + store.override_global(settings) + }); language::init(cx); client::init_settings(cx); diff --git a/crates/settings/Cargo.toml b/crates/settings/Cargo.toml index 6d2b4ded91..2cb6637ead 100644 --- a/crates/settings/Cargo.toml +++ b/crates/settings/Cargo.toml @@ -9,7 +9,7 @@ path = "src/settings.rs" doctest = false [features] -test-support = ["theme/test-support", "gpui/test-support", "fs/test-support"] +test-support = ["gpui/test-support", "fs/test-support"] [dependencies] assets = { path = "../assets" } @@ -17,12 +17,11 @@ collections = { path = "../collections" } gpui = { path = "../gpui" } sqlez = { path = "../sqlez" } fs = { path = "../fs" } -anyhow.workspace = true -futures.workspace = true -theme = { path = "../theme" } staff_mode = { path = "../staff_mode" } util = { path = "../util" } +anyhow.workspace = true +futures.workspace = true glob.workspace = true json_comments = "0.2" lazy_static.workspace = true @@ -39,7 +38,6 @@ tree-sitter-json = "*" [dev-dependencies] gpui = { path = "../gpui", features = ["test-support"] } fs = { path = "../fs", features = ["test-support"] } -theme = { path = "../theme", features = ["test-support"] } pretty_assertions = "1.3.0" unindent.workspace = true diff --git a/crates/settings/src/settings.rs b/crates/settings/src/settings.rs index bd1104105f..e4784d61ac 100644 --- a/crates/settings/src/settings.rs +++ b/crates/settings/src/settings.rs @@ -3,23 +3,10 @@ mod keymap_file; mod settings_file; mod settings_store; -use anyhow::Result; -use gpui::{ - font_cache::{FamilyId, FontCache}, - fonts, AppContext, AssetSource, -}; -use schemars::{ - gen::SchemaGenerator, - schema::{InstanceType, Schema, SchemaObject}, - JsonSchema, -}; -use serde::{Deserialize, Serialize}; -use serde_json::Value; -use std::{borrow::Cow, str, sync::Arc}; -use theme::{Theme, ThemeRegistry}; -use util::ResultExt as _; +use std::{borrow::Cow, str}; pub use font_size::{adjust_font_size_delta, font_size_for_setting}; +use gpui::AssetSource; pub use keymap_file::{keymap_file_json_schema, KeymapFileContent}; pub use settings_file::*; pub use settings_store::{Setting, SettingsJsonSchemaParams, SettingsStore}; @@ -27,193 +14,9 @@ pub use settings_store::{Setting, SettingsJsonSchemaParams, SettingsStore}; pub const DEFAULT_SETTINGS_ASSET_PATH: &str = "settings/default.json"; pub const INITIAL_USER_SETTINGS_ASSET_PATH: &str = "settings/initial_user_settings.json"; -#[derive(Clone)] -pub struct Settings { - pub buffer_font_family_name: String, - pub buffer_font_features: fonts::Features, - pub buffer_font_family: FamilyId, - pub buffer_font_size: f32, - pub theme: Arc, -} - -impl Setting for Settings { - const KEY: Option<&'static str> = None; - - type FileContent = SettingsFileContent; - - fn load( - defaults: &Self::FileContent, - user_values: &[&Self::FileContent], - cx: &AppContext, - ) -> Result { - let buffer_font_features = defaults.buffer_font_features.clone().unwrap(); - let themes = cx.global::>(); - - let mut this = Self { - buffer_font_family: cx - .font_cache() - .load_family( - &[defaults.buffer_font_family.as_ref().unwrap()], - &buffer_font_features, - ) - .unwrap(), - buffer_font_family_name: defaults.buffer_font_family.clone().unwrap(), - buffer_font_features, - buffer_font_size: defaults.buffer_font_size.unwrap(), - theme: themes.get(defaults.theme.as_ref().unwrap()).unwrap(), - }; - - for value in user_values.into_iter().copied().cloned() { - this.set_user_settings(value, themes.as_ref(), cx.font_cache()); - } - - Ok(this) - } - - fn json_schema( - generator: &mut SchemaGenerator, - params: &SettingsJsonSchemaParams, - ) -> schemars::schema::RootSchema { - let mut root_schema = generator.root_schema_for::(); - - // Create a schema for a theme name. - let theme_name_schema = SchemaObject { - instance_type: Some(InstanceType::String.into()), - enum_values: Some( - params - .theme_names - .iter() - .cloned() - .map(Value::String) - .collect(), - ), - ..Default::default() - }; - - root_schema - .definitions - .extend([("ThemeName".into(), theme_name_schema.into())]); - - root_schema - .schema - .object - .as_mut() - .unwrap() - .properties - .extend([( - "theme".to_owned(), - Schema::new_ref("#/definitions/ThemeName".into()), - )]); - - root_schema - } -} - -#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)] -pub struct SettingsFileContent { - #[serde(default)] - pub buffer_font_family: Option, - #[serde(default)] - pub buffer_font_size: Option, - #[serde(default)] - pub buffer_font_features: Option, - #[serde(default)] - pub theme: Option, -} - -impl Settings { - pub fn initial_user_settings_content(assets: &'static impl AssetSource) -> Cow<'static, str> { - match assets.load(INITIAL_USER_SETTINGS_ASSET_PATH).unwrap() { - Cow::Borrowed(s) => Cow::Borrowed(str::from_utf8(s).unwrap()), - Cow::Owned(s) => Cow::Owned(String::from_utf8(s).unwrap()), - } - } - - /// Fill out the settings corresponding to the default.json file, overrides will be set later - pub fn defaults( - assets: impl AssetSource, - font_cache: &FontCache, - themes: &ThemeRegistry, - ) -> Self { - let defaults: SettingsFileContent = settings_store::parse_json_with_comments( - str::from_utf8(assets.load(DEFAULT_SETTINGS_ASSET_PATH).unwrap().as_ref()).unwrap(), - ) - .unwrap(); - - let buffer_font_features = defaults.buffer_font_features.unwrap(); - Self { - buffer_font_family: font_cache - .load_family( - &[defaults.buffer_font_family.as_ref().unwrap()], - &buffer_font_features, - ) - .unwrap(), - buffer_font_family_name: defaults.buffer_font_family.unwrap(), - buffer_font_features, - buffer_font_size: defaults.buffer_font_size.unwrap(), - theme: themes.get(&defaults.theme.unwrap()).unwrap(), - } - } - - // Fill out the overrride and etc. settings from the user's settings.json - fn set_user_settings( - &mut self, - data: SettingsFileContent, - theme_registry: &ThemeRegistry, - font_cache: &FontCache, - ) { - let mut family_changed = false; - if let Some(value) = data.buffer_font_family { - self.buffer_font_family_name = value; - family_changed = true; - } - if let Some(value) = data.buffer_font_features { - self.buffer_font_features = value; - family_changed = true; - } - if family_changed { - if let Some(id) = font_cache - .load_family(&[&self.buffer_font_family_name], &self.buffer_font_features) - .log_err() - { - self.buffer_font_family = id; - } - } - - if let Some(value) = &data.theme { - if let Some(theme) = theme_registry.get(value).log_err() { - self.theme = theme; - } - } - - merge(&mut self.buffer_font_size, data.buffer_font_size); - } - - #[cfg(any(test, feature = "test-support"))] - pub fn test(cx: &gpui::AppContext) -> Settings { - Settings { - buffer_font_family_name: "Monaco".to_string(), - buffer_font_features: Default::default(), - buffer_font_family: cx - .font_cache() - .load_family(&["Monaco"], &Default::default()) - .unwrap(), - buffer_font_size: 14., - theme: gpui::fonts::with_font_cache(cx.font_cache().clone(), Default::default), - } - } - - #[cfg(any(test, feature = "test-support"))] - pub fn test_async(cx: &mut gpui::TestAppContext) { - cx.update(|cx| { - let settings = Self::test(cx); - cx.set_global(settings); - }); - } -} - -fn merge(target: &mut T, value: Option) { - if let Some(value) = value { - *target = value; +pub fn initial_user_settings_content(assets: &'static impl AssetSource) -> Cow<'static, str> { + match assets.load(INITIAL_USER_SETTINGS_ASSET_PATH).unwrap() { + Cow::Borrowed(s) => Cow::Borrowed(str::from_utf8(s).unwrap()), + Cow::Owned(s) => Cow::Owned(String::from_utf8(s).unwrap()), } } diff --git a/crates/settings/src/settings_file.rs b/crates/settings/src/settings_file.rs index cf1787d7c0..ed27416512 100644 --- a/crates/settings/src/settings_file.rs +++ b/crates/settings/src/settings_file.rs @@ -1,7 +1,4 @@ -use crate::{ - settings_store::parse_json_with_comments, settings_store::SettingsStore, Setting, Settings, - DEFAULT_SETTINGS_ASSET_PATH, -}; +use crate::{settings_store::SettingsStore, Setting, DEFAULT_SETTINGS_ASSET_PATH}; use anyhow::Result; use assets::Assets; use fs::Fs; @@ -34,16 +31,21 @@ pub fn default_settings() -> Cow<'static, str> { } } +#[cfg(any(test, feature = "test-support"))] +pub const EMPTY_THEME_NAME: &'static str = "empty-theme"; + #[cfg(any(test, feature = "test-support"))] pub fn test_settings() -> String { - let mut value = - parse_json_with_comments::(default_settings().as_ref()).unwrap(); + let mut value = crate::settings_store::parse_json_with_comments::( + default_settings().as_ref(), + ) + .unwrap(); util::merge_non_null_json_value_into( serde_json::json!({ "buffer_font_family": "Courier", "buffer_font_features": {}, "buffer_font_size": 14, - "theme": theme::EMPTY_THEME_NAME, + "theme": EMPTY_THEME_NAME, }), &mut value, ); @@ -85,10 +87,6 @@ pub fn handle_settings_file_changes( store .set_user_settings(&user_settings_content, cx) .log_err(); - - // TODO - remove the Settings global, use the SettingsStore instead. - store.register_setting::(cx); - cx.set_global(store.get::(None).clone()); }); cx.spawn(move |mut cx| async move { while let Some(user_settings_content) = user_settings_file_rx.next().await { @@ -97,9 +95,6 @@ pub fn handle_settings_file_changes( store .set_user_settings(&user_settings_content, cx) .log_err(); - - // TODO - remove the Settings global, use the SettingsStore instead. - cx.set_global(store.get::(None).clone()); }); }); } @@ -113,7 +108,7 @@ async fn load_settings(fs: &Arc) -> Result { Err(err) => { if let Some(e) = err.downcast_ref::() { if e.kind() == ErrorKind::NotFound { - return Ok(Settings::initial_user_settings_content(&Assets).to_string()); + return Ok(crate::initial_user_settings_content(&Assets).to_string()); } } return Err(err); diff --git a/crates/settings/src/settings_store.rs b/crates/settings/src/settings_store.rs index cdc7659189..dd81b05434 100644 --- a/crates/settings/src/settings_store.rs +++ b/crates/settings/src/settings_store.rs @@ -40,7 +40,11 @@ pub trait Setting: 'static { where Self: Sized; - fn json_schema(generator: &mut SchemaGenerator, _: &SettingsJsonSchemaParams) -> RootSchema { + fn json_schema( + generator: &mut SchemaGenerator, + _: &SettingsJsonSchemaParams, + _: &AppContext, + ) -> RootSchema { generator.root_schema_for::() } @@ -75,7 +79,7 @@ pub trait Setting: 'static { } pub struct SettingsJsonSchemaParams<'a> { - pub theme_names: &'a [String], + pub staff_mode: bool, pub language_names: &'a [String], } @@ -112,6 +116,7 @@ trait AnySettingValue { &self, generator: &mut SchemaGenerator, _: &SettingsJsonSchemaParams, + cx: &AppContext, ) -> RootSchema; } @@ -169,6 +174,16 @@ impl SettingsStore { .expect("no default value for setting type") } + /// Override the global value for a setting. + /// + /// The given value will be overwritten if the user settings file changes. + pub fn override_global(&mut self, value: T) { + self.setting_values + .get_mut(&TypeId::of::()) + .unwrap_or_else(|| panic!("unregistered setting type {}", type_name::())) + .set_global_value(Box::new(value)) + } + /// Get the user's settings as a raw JSON value. /// /// This is only for debugging and reporting. For user-facing functionality, @@ -342,7 +357,11 @@ impl SettingsStore { Ok(()) } - pub fn json_schema(&self, schema_params: &SettingsJsonSchemaParams) -> serde_json::Value { + pub fn json_schema( + &self, + schema_params: &SettingsJsonSchemaParams, + cx: &AppContext, + ) -> serde_json::Value { use schemars::{ gen::SchemaSettings, schema::{Schema, SchemaObject}, @@ -355,7 +374,7 @@ impl SettingsStore { let mut combined_schema = RootSchema::default(); for setting_value in self.setting_values.values() { - let setting_schema = setting_value.json_schema(&mut generator, schema_params); + let setting_schema = setting_value.json_schema(&mut generator, schema_params, cx); combined_schema .definitions .extend(setting_schema.definitions); @@ -552,8 +571,9 @@ impl AnySettingValue for SettingValue { &self, generator: &mut SchemaGenerator, params: &SettingsJsonSchemaParams, + cx: &AppContext, ) -> RootSchema { - T::json_schema(generator, params) + T::json_schema(generator, params, cx) } } diff --git a/crates/terminal/src/terminal.rs b/crates/terminal/src/terminal.rs index cc4580daa1..f918d91b6d 100644 --- a/crates/terminal/src/terminal.rs +++ b/crates/terminal/src/terminal.rs @@ -33,7 +33,6 @@ use mappings::mouse::{ use procinfo::LocalProcessInfo; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use settings::Settings; use util::truncate_and_trailoff; use std::{ @@ -700,7 +699,7 @@ impl Terminal { match event { InternalEvent::ColorRequest(index, format) => { let color = term.colors()[*index].unwrap_or_else(|| { - let term_style = &cx.global::().theme.terminal; + let term_style = &theme::current(cx).terminal; to_alac_rgb(get_color_at_index(index, &term_style)) }); self.write_to_pty(format(color)) diff --git a/crates/terminal_view/src/terminal_button.rs b/crates/terminal_view/src/terminal_button.rs index a92f7285b5..fcb5e7feb3 100644 --- a/crates/terminal_view/src/terminal_button.rs +++ b/crates/terminal_view/src/terminal_button.rs @@ -5,7 +5,6 @@ use gpui::{ platform::{CursorStyle, MouseButton}, AnyElement, Element, Entity, View, ViewContext, ViewHandle, WeakViewHandle, }; -use settings::Settings; use std::any::TypeId; use workspace::{ dock::{Dock, FocusDock}, @@ -43,7 +42,7 @@ impl View for TerminalButton { let has_terminals = !project.local_terminal_handles().is_empty(); let terminal_count = project.local_terminal_handles().len() as i32; - let theme = cx.global::().theme.clone(); + let theme = theme::current(cx).clone(); Stack::new() .with_child( diff --git a/crates/terminal_view/src/terminal_element.rs b/crates/terminal_view/src/terminal_element.rs index 93be64b612..8976a34210 100644 --- a/crates/terminal_view/src/terminal_element.rs +++ b/crates/terminal_view/src/terminal_element.rs @@ -16,7 +16,7 @@ use gpui::{ use itertools::Itertools; use language::CursorShape; use ordered_float::OrderedFloat; -use settings::{font_size_for_setting, Settings}; +use settings::font_size_for_setting; use terminal::{ alacritty_terminal::{ ansi::{Color as AnsiColor, Color::Named, CursorShape as AlacCursorShape, NamedColor}, @@ -27,7 +27,7 @@ use terminal::{ mappings::colors::convert_color, IndexedCell, Terminal, TerminalContent, TerminalSettings, TerminalSize, }; -use theme::TerminalStyle; +use theme::{TerminalStyle, ThemeSettings}; use util::ResultExt; use std::{fmt::Debug, ops::RangeInclusive}; @@ -522,7 +522,7 @@ impl Element for TerminalElement { view: &mut TerminalView, cx: &mut LayoutContext, ) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) { - let settings = cx.global::(); + let settings = settings::get_setting::(None, cx); let terminal_settings = settings::get_setting::(None, cx); //Setup layout information diff --git a/crates/terminal_view/src/terminal_view.rs b/crates/terminal_view/src/terminal_view.rs index 76bc9b4a38..944366e358 100644 --- a/crates/terminal_view/src/terminal_view.rs +++ b/crates/terminal_view/src/terminal_view.rs @@ -904,6 +904,7 @@ mod tests { cx: &mut TestAppContext, ) -> (ModelHandle, ViewHandle) { let params = cx.update(AppState::test); + cx.update(|cx| theme::init((), cx)); let project = Project::test(params.fs.clone(), [], cx).await; let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); diff --git a/crates/theme/Cargo.toml b/crates/theme/Cargo.toml index 0cba8d8da2..b213cc9c1e 100644 --- a/crates/theme/Cargo.toml +++ b/crates/theme/Cargo.toml @@ -5,7 +5,11 @@ edition = "2021" publish = false [features] -test-support = ["gpui/test-support"] +test-support = [ + "gpui/test-support", + "fs/test-support", + "settings/test-support" +] [lib] path = "src/theme.rs" @@ -14,10 +18,19 @@ doctest = false [dependencies] gpui = { path = "../gpui" } fs = { path = "../fs" } +settings = { path = "../settings" } +util = { path = "../util" } + anyhow.workspace = true indexmap = "1.6.2" parking_lot.workspace = true +schemars.workspace = true serde.workspace = true serde_derive.workspace = true serde_json.workspace = true toml.workspace = true + +[dev-dependencies] +gpui = { path = "../gpui", features = ["test-support"] } +fs = { path = "../fs", features = ["test-support"] } +settings = { path = "../settings", features = ["test-support"] } diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index 8760ea54ea..ae3bcb765d 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -1,19 +1,31 @@ mod theme_registry; +mod theme_settings; +pub mod ui; use gpui::{ color::Color, elements::{ContainerStyle, ImageStyle, LabelStyle, Shadow, TooltipStyle}, fonts::{HighlightStyle, TextStyle}, - platform, Border, MouseState, + platform, AppContext, AssetSource, Border, MouseState, }; use serde::{de::DeserializeOwned, Deserialize}; use serde_json::Value; use std::{collections::HashMap, sync::Arc}; use ui::{ButtonStyle, CheckboxStyle, IconStyle, ModalStyle, SvgStyle}; -pub mod ui; +pub use theme_registry::ThemeRegistry; +pub use theme_settings::ThemeSettings; -pub use theme_registry::*; +pub fn current(cx: &AppContext) -> Arc { + settings::get_setting::(None, cx) + .theme + .clone() +} + +pub fn init(source: impl AssetSource, cx: &mut AppContext) { + cx.set_global(ThemeRegistry::new(source, cx.font_cache().clone())); + settings::register_setting::(cx); +} #[derive(Deserialize, Default)] pub struct Theme { diff --git a/crates/theme/src/theme_registry.rs b/crates/theme/src/theme_registry.rs index 2bcdb4528c..12ccaf3d51 100644 --- a/crates/theme/src/theme_registry.rs +++ b/crates/theme/src/theme_registry.rs @@ -20,9 +20,6 @@ pub struct ThemeRegistry { next_theme_id: AtomicUsize, } -#[cfg(any(test, feature = "test-support"))] -pub const EMPTY_THEME_NAME: &'static str = "empty-theme"; - impl ThemeRegistry { pub fn new(source: impl AssetSource, font_cache: Arc) -> Arc { let this = Arc::new(Self { @@ -35,8 +32,13 @@ impl ThemeRegistry { #[cfg(any(test, feature = "test-support"))] this.themes.lock().insert( - EMPTY_THEME_NAME.to_string(), - gpui::fonts::with_font_cache(this.font_cache.clone(), || Arc::new(Theme::default())), + settings::EMPTY_THEME_NAME.to_string(), + gpui::fonts::with_font_cache(this.font_cache.clone(), || { + let mut theme = Theme::default(); + theme.meta.id = this.next_theme_id.fetch_add(1, SeqCst); + theme.meta.name = settings::EMPTY_THEME_NAME.into(); + Arc::new(theme) + }), ); this diff --git a/crates/theme/src/theme_settings.rs b/crates/theme/src/theme_settings.rs new file mode 100644 index 0000000000..85958e576d --- /dev/null +++ b/crates/theme/src/theme_settings.rs @@ -0,0 +1,136 @@ +use crate::{Theme, ThemeRegistry}; +use anyhow::Result; +use gpui::{font_cache::FamilyId, fonts, AppContext}; +use schemars::{ + gen::SchemaGenerator, + schema::{InstanceType, Schema, SchemaObject}, + JsonSchema, +}; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use settings::SettingsJsonSchemaParams; +use std::sync::Arc; +use util::ResultExt as _; + +#[derive(Clone)] +pub struct ThemeSettings { + pub buffer_font_family_name: String, + pub buffer_font_features: fonts::Features, + pub buffer_font_family: FamilyId, + pub buffer_font_size: f32, + pub theme: Arc, +} + +#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)] +pub struct ThemeSettingsContent { + #[serde(default)] + pub buffer_font_family: Option, + #[serde(default)] + pub buffer_font_size: Option, + #[serde(default)] + pub buffer_font_features: Option, + #[serde(default)] + pub theme: Option, +} + +impl settings::Setting for ThemeSettings { + const KEY: Option<&'static str> = None; + + type FileContent = ThemeSettingsContent; + + fn load( + defaults: &Self::FileContent, + user_values: &[&Self::FileContent], + cx: &AppContext, + ) -> Result { + let buffer_font_features = defaults.buffer_font_features.clone().unwrap(); + let themes = cx.global::>(); + + let mut this = Self { + buffer_font_family: cx + .font_cache() + .load_family( + &[defaults.buffer_font_family.as_ref().unwrap()], + &buffer_font_features, + ) + .unwrap(), + buffer_font_family_name: defaults.buffer_font_family.clone().unwrap(), + buffer_font_features, + buffer_font_size: defaults.buffer_font_size.unwrap(), + theme: themes.get(defaults.theme.as_ref().unwrap()).unwrap(), + }; + + for value in user_values.into_iter().copied().cloned() { + let font_cache = cx.font_cache(); + let mut family_changed = false; + if let Some(value) = value.buffer_font_family { + this.buffer_font_family_name = value; + family_changed = true; + } + if let Some(value) = value.buffer_font_features { + this.buffer_font_features = value; + family_changed = true; + } + if family_changed { + if let Some(id) = font_cache + .load_family(&[&this.buffer_font_family_name], &this.buffer_font_features) + .log_err() + { + this.buffer_font_family = id; + } + } + + if let Some(value) = &value.theme { + if let Some(theme) = themes.get(value).log_err() { + this.theme = theme; + } + } + + merge(&mut this.buffer_font_size, value.buffer_font_size); + } + + Ok(this) + } + + fn json_schema( + generator: &mut SchemaGenerator, + params: &SettingsJsonSchemaParams, + cx: &AppContext, + ) -> schemars::schema::RootSchema { + let mut root_schema = generator.root_schema_for::(); + let theme_names = cx + .global::>() + .list(params.staff_mode) + .map(|theme| Value::String(theme.name.clone())) + .collect(); + + let theme_name_schema = SchemaObject { + instance_type: Some(InstanceType::String.into()), + enum_values: Some(theme_names), + ..Default::default() + }; + + root_schema + .definitions + .extend([("ThemeName".into(), theme_name_schema.into())]); + + root_schema + .schema + .object + .as_mut() + .unwrap() + .properties + .extend([( + "theme".to_owned(), + Schema::new_ref("#/definitions/ThemeName".into()), + )]); + + root_schema + } +} + +fn merge(target: &mut T, value: Option) { + if let Some(value) = value { + *target = value; + } +} diff --git a/crates/theme_selector/src/theme_selector.rs b/crates/theme_selector/src/theme_selector.rs index 27c5a9ef4e..a6c84d1d91 100644 --- a/crates/theme_selector/src/theme_selector.rs +++ b/crates/theme_selector/src/theme_selector.rs @@ -2,10 +2,10 @@ use fs::Fs; use fuzzy::{match_strings, StringMatch, StringMatchCandidate}; use gpui::{actions, elements::*, AnyElement, AppContext, Element, MouseState, ViewContext}; use picker::{Picker, PickerDelegate, PickerEvent}; -use settings::{update_settings_file, Settings}; +use settings::{update_settings_file, SettingsStore}; use staff_mode::StaffMode; use std::sync::Arc; -use theme::{Theme, ThemeMeta, ThemeRegistry}; +use theme::{Theme, ThemeMeta, ThemeRegistry, ThemeSettings}; use util::ResultExt; use workspace::Workspace; @@ -18,17 +18,17 @@ pub fn init(cx: &mut AppContext) { pub fn toggle(workspace: &mut Workspace, _: &Toggle, cx: &mut ViewContext) { workspace.toggle_modal(cx, |workspace, cx| { - let themes = workspace.app_state().themes.clone(); let fs = workspace.app_state().fs.clone(); - cx.add_view(|cx| ThemeSelector::new(ThemeSelectorDelegate::new(fs, themes, cx), cx)) + cx.add_view(|cx| ThemeSelector::new(ThemeSelectorDelegate::new(fs, cx), cx)) }); } #[cfg(debug_assertions)] -pub fn reload(themes: Arc, cx: &mut AppContext) { - let current_theme_name = cx.global::().theme.meta.name.clone(); - themes.clear(); - match themes.get(¤t_theme_name) { +pub fn reload(cx: &mut AppContext) { + let current_theme_name = theme::current(cx).meta.name.clone(); + let registry = cx.global::>(); + registry.clear(); + match registry.get(¤t_theme_name) { Ok(theme) => { ThemeSelectorDelegate::set_theme(theme, cx); log::info!("reloaded theme {}", current_theme_name); @@ -43,7 +43,6 @@ pub type ThemeSelector = Picker; pub struct ThemeSelectorDelegate { fs: Arc, - registry: Arc, theme_data: Vec, matches: Vec, original_theme: Arc, @@ -52,18 +51,12 @@ pub struct ThemeSelectorDelegate { } impl ThemeSelectorDelegate { - fn new( - fs: Arc, - registry: Arc, - cx: &mut ViewContext, - ) -> Self { - let settings = cx.global::(); + fn new(fs: Arc, cx: &mut ViewContext) -> Self { + let original_theme = theme::current(cx).clone(); - let original_theme = settings.theme.clone(); - - let mut theme_names = registry - .list(**cx.default_global::()) - .collect::>(); + let staff_mode = **cx.default_global::(); + let registry = cx.global::>(); + let mut theme_names = registry.list(staff_mode).collect::>(); theme_names.sort_unstable_by(|a, b| a.is_light.cmp(&b.is_light).then(a.name.cmp(&b.name))); let matches = theme_names .iter() @@ -76,7 +69,6 @@ impl ThemeSelectorDelegate { .collect(); let mut this = Self { fs, - registry, theme_data: theme_names, matches, original_theme: original_theme.clone(), @@ -89,7 +81,8 @@ impl ThemeSelectorDelegate { fn show_selected_theme(&mut self, cx: &mut ViewContext) { if let Some(mat) = self.matches.get(self.selected_index) { - match self.registry.get(&mat.string) { + let registry = cx.global::>(); + match registry.get(&mat.string) { Ok(theme) => { Self::set_theme(theme, cx); } @@ -109,8 +102,10 @@ impl ThemeSelectorDelegate { } fn set_theme(theme: Arc, cx: &mut AppContext) { - cx.update_global::(|settings, cx| { - settings.theme = theme; + cx.update_global::(|store, cx| { + let mut theme_settings = store.get::(None).clone(); + theme_settings.theme = theme; + store.override_global(theme_settings); cx.refresh_windows(); }); } @@ -128,9 +123,9 @@ impl PickerDelegate for ThemeSelectorDelegate { fn confirm(&mut self, cx: &mut ViewContext) { self.selection_completed = true; - let theme_name = cx.global::().theme.meta.name.clone(); - update_settings_file::(self.fs.clone(), cx, |settings_content| { - settings_content.theme = Some(theme_name); + let theme_name = theme::current(cx).meta.name.clone(); + update_settings_file::(self.fs.clone(), cx, |settings| { + settings.theme = Some(theme_name); }); cx.emit(PickerEvent::Dismiss); @@ -212,11 +207,10 @@ impl PickerDelegate for ThemeSelectorDelegate { selected: bool, cx: &AppContext, ) -> AnyElement> { - let settings = cx.global::(); - let theme = &settings.theme; - let theme_match = &self.matches[ix]; + let theme = theme::current(cx); let style = theme.picker.item.style_for(mouse_state, selected); + let theme_match = &self.matches[ix]; Label::new(theme_match.string.clone(), style.label.clone()) .with_highlights(theme_match.positions.clone()) .contained() diff --git a/crates/theme_testbench/src/theme_testbench.rs b/crates/theme_testbench/src/theme_testbench.rs index 125bc523b7..52eca5f8ad 100644 --- a/crates/theme_testbench/src/theme_testbench.rs +++ b/crates/theme_testbench/src/theme_testbench.rs @@ -10,8 +10,7 @@ use gpui::{ WeakViewHandle, }; use project::Project; -use settings::Settings; -use theme::{ColorScheme, Layer, Style, StyleSet}; +use theme::{ColorScheme, Layer, Style, StyleSet, ThemeSettings}; use workspace::{item::Item, register_deserializable_item, Pane, Workspace}; actions!(theme, [DeployThemeTestbench]); @@ -220,7 +219,7 @@ impl ThemeTestbench { } fn render_label(text: String, style: &Style, cx: &mut ViewContext) -> Label { - let settings = cx.global::(); + let settings = settings::get_setting::(None, cx); let font_cache = cx.font_cache(); let family_id = settings.buffer_font_family; let font_size = settings::font_size_for_setting(settings.buffer_font_size, cx); @@ -252,7 +251,7 @@ impl View for ThemeTestbench { } fn render(&mut self, cx: &mut gpui::ViewContext) -> AnyElement { - let color_scheme = &cx.global::().theme.clone().color_scheme; + let color_scheme = &theme::current(cx).clone().color_scheme; Flex::row() .with_child( diff --git a/crates/welcome/src/base_keymap_picker.rs b/crates/welcome/src/base_keymap_picker.rs index 815de5e6ae..c9dfec9eb0 100644 --- a/crates/welcome/src/base_keymap_picker.rs +++ b/crates/welcome/src/base_keymap_picker.rs @@ -7,7 +7,7 @@ use gpui::{ }; use picker::{Picker, PickerDelegate, PickerEvent}; use project::Fs; -use settings::{update_settings_file, Settings}; +use settings::update_settings_file; use std::sync::Arc; use util::ResultExt; use workspace::Workspace; @@ -139,7 +139,7 @@ impl PickerDelegate for BaseKeymapSelectorDelegate { selected: bool, cx: &gpui::AppContext, ) -> gpui::AnyElement> { - let theme = &cx.global::().theme; + let theme = &theme::current(cx); let keymap_match = &self.matches[ix]; let style = theme.picker.item.style_for(mouse_state, selected); diff --git a/crates/welcome/src/welcome.rs b/crates/welcome/src/welcome.rs index ca04d5f6dc..29b013156d 100644 --- a/crates/welcome/src/welcome.rs +++ b/crates/welcome/src/welcome.rs @@ -8,7 +8,7 @@ use gpui::{ elements::{Flex, Label, ParentElement}, AnyElement, AppContext, Element, Entity, Subscription, View, ViewContext, WeakViewHandle, }; -use settings::{update_settings_file, Settings}; +use settings::{update_settings_file, SettingsStore}; use std::{borrow::Cow, sync::Arc}; use workspace::{ item::Item, open_new, sidebar::SidebarSide, AppState, PaneBackdrop, Welcome, Workspace, @@ -61,9 +61,7 @@ impl View for WelcomePage { fn render(&mut self, cx: &mut gpui::ViewContext) -> AnyElement { let self_handle = cx.handle(); - let settings = cx.global::(); - let theme = settings.theme.clone(); - + let theme = theme::current(cx); let width = theme.welcome.page_width; let telemetry_settings = *settings::get_setting::(None, cx); @@ -224,7 +222,7 @@ impl WelcomePage { pub fn new(workspace: &Workspace, cx: &mut ViewContext) -> Self { WelcomePage { workspace: workspace.weak_handle(), - _settings_subscription: cx.observe_global::(move |_, cx| cx.notify()), + _settings_subscription: cx.observe_global::(move |_, cx| cx.notify()), } } } @@ -260,7 +258,7 @@ impl Item for WelcomePage { ) -> Option { Some(WelcomePage { workspace: self.workspace.clone(), - _settings_subscription: cx.observe_global::(move |_, cx| cx.notify()), + _settings_subscription: cx.observe_global::(move |_, cx| cx.notify()), }) } } diff --git a/crates/workspace/src/dock.rs b/crates/workspace/src/dock.rs index 9879aba5c6..beac87f99c 100644 --- a/crates/workspace/src/dock.rs +++ b/crates/workspace/src/dock.rs @@ -408,7 +408,6 @@ mod tests { use gpui::{AppContext, BorrowWindowContext, TestAppContext, ViewContext, WindowContext}; use project::{FakeFs, Project}; - use theme::ThemeRegistry; use super::*; use crate::{ @@ -468,7 +467,6 @@ mod tests { project.clone(), Arc::new(AppState { languages: project.read(cx).languages().clone(), - themes: ThemeRegistry::new((), cx.font_cache().clone()), client: project.read(cx).client(), user_store: project.read(cx).user_store(), fs: project.read(cx).fs().clone(), @@ -615,7 +613,6 @@ mod tests { project.clone(), Arc::new(AppState { languages: project.read(cx).languages().clone(), - themes: ThemeRegistry::new((), cx.font_cache().clone()), client: project.read(cx).client(), user_store: project.read(cx).user_store(), fs: project.read(cx).fs().clone(), diff --git a/crates/workspace/src/dock/toggle_dock_button.rs b/crates/workspace/src/dock/toggle_dock_button.rs index 1fda55b783..9ab7a8996b 100644 --- a/crates/workspace/src/dock/toggle_dock_button.rs +++ b/crates/workspace/src/dock/toggle_dock_button.rs @@ -6,7 +6,6 @@ use gpui::{ platform::MouseButton, AnyElement, Element, Entity, View, ViewContext, ViewHandle, WeakViewHandle, }; -use settings::Settings; pub struct ToggleDockButton { workspace: WeakViewHandle, @@ -43,7 +42,7 @@ impl View for ToggleDockButton { let dock_position = workspace.read(cx).dock.position; let dock_pane = workspace.read(cx).dock_pane().clone(); - let theme = cx.global::().theme.clone(); + let theme = theme::current(cx).clone(); let button = MouseEventHandler::::new(0, cx, { let theme = theme.clone(); diff --git a/crates/workspace/src/notifications.rs b/crates/workspace/src/notifications.rs index 7881603bbc..21b3be09d0 100644 --- a/crates/workspace/src/notifications.rs +++ b/crates/workspace/src/notifications.rs @@ -149,6 +149,8 @@ impl Workspace { } pub mod simple_message_notification { + use super::Notification; + use crate::Workspace; use gpui::{ actions, elements::{Flex, MouseEventHandler, Padding, ParentElement, Svg, Text}, @@ -158,13 +160,8 @@ pub mod simple_message_notification { }; use menu::Cancel; use serde::Deserialize; - use settings::Settings; use std::{borrow::Cow, sync::Arc}; - use crate::Workspace; - - use super::Notification; - actions!(message_notifications, [CancelMessageNotification]); #[derive(Clone, Default, Deserialize, PartialEq)] @@ -240,7 +237,7 @@ pub mod simple_message_notification { } fn render(&mut self, cx: &mut gpui::ViewContext) -> gpui::AnyElement { - let theme = cx.global::().theme.clone(); + let theme = theme::current(cx).clone(); let theme = &theme.simple_message_notification; enum MessageNotificationTag {} diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index ca454d2c75..3717cfc200 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -30,7 +30,6 @@ use gpui::{ }; use project::{Project, ProjectEntryId, ProjectPath}; use serde::Deserialize; -use settings::Settings; use std::{any::Any, cell::RefCell, cmp, mem, path::Path, rc::Rc}; use theme::Theme; use util::ResultExt; @@ -1297,7 +1296,7 @@ impl Pane { } fn render_tabs(&mut self, cx: &mut ViewContext) -> impl Element { - let theme = cx.global::().theme.clone(); + let theme = theme::current(cx).clone(); let pane = cx.handle().downgrade(); let autoscroll = if mem::take(&mut self.autoscroll) { @@ -1328,7 +1327,7 @@ impl Pane { let pane = pane.clone(); let detail = detail.clone(); - let theme = cx.global::().theme.clone(); + let theme = theme::current(cx).clone(); let mut tooltip_theme = theme.tooltip.clone(); tooltip_theme.max_text_width = None; let tab_tooltip_text = item.tab_tooltip_text(cx).map(|a| a.to_string()); @@ -1406,7 +1405,7 @@ impl Pane { pane: pane.clone(), }, { - let theme = cx.global::().theme.clone(); + let theme = theme::current(cx).clone(); let detail = detail.clone(); move |dragged_item: &DraggedItem, cx: &mut ViewContext| { @@ -1699,7 +1698,7 @@ impl View for Pane { if let Some(active_item) = self.active_item() { Flex::column() .with_child({ - let theme = cx.global::().theme.clone(); + let theme = theme::current(cx).clone(); let mut stack = Stack::new(); @@ -1765,7 +1764,7 @@ impl View for Pane { .into_any() } else { enum EmptyPane {} - let theme = cx.global::().theme.clone(); + let theme = theme::current(cx).clone(); dragged_item_receiver::(0, 0, false, None, cx, |_, cx| { self.render_blank_pane(&theme, cx) @@ -1862,7 +1861,7 @@ fn render_tab_bar_button)>( Stack::new() .with_child( MouseEventHandler::::new(index, cx, |mouse_state, cx| { - let theme = &cx.global::().theme.workspace.tab_bar; + let theme = &theme::current(cx).workspace.tab_bar; let style = theme.pane_button.style_for(mouse_state, false); Svg::new(icon) .with_color(style.color) @@ -2024,7 +2023,7 @@ impl Element for PaneBackdrop { view: &mut V, cx: &mut ViewContext, ) -> Self::PaintState { - let background = cx.global::().theme.editor.background; + let background = theme::current(cx).editor.background; let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default(); @@ -2536,7 +2535,7 @@ mod tests { fn init_test(cx: &mut TestAppContext) { cx.update(|cx| { cx.set_global(SettingsStore::test(cx)); - cx.set_global(settings::Settings::test(cx)); + theme::init((), cx); crate::init_settings(cx); }); } diff --git a/crates/workspace/src/pane/dragged_item_receiver.rs b/crates/workspace/src/pane/dragged_item_receiver.rs index 961205b9ee..532e6bff5c 100644 --- a/crates/workspace/src/pane/dragged_item_receiver.rs +++ b/crates/workspace/src/pane/dragged_item_receiver.rs @@ -1,3 +1,5 @@ +use super::DraggedItem; +use crate::{Pane, SplitDirection, Workspace}; use drag_and_drop::DragAndDrop; use gpui::{ color::Color, @@ -8,11 +10,6 @@ use gpui::{ AppContext, Element, EventContext, MouseState, Quad, View, ViewContext, WeakViewHandle, }; use project::ProjectEntryId; -use settings::Settings; - -use crate::{Pane, SplitDirection, Workspace}; - -use super::DraggedItem; pub fn dragged_item_receiver( region_id: usize, @@ -225,8 +222,5 @@ fn drop_split_direction( } fn overlay_color(cx: &AppContext) -> Color { - cx.global::() - .theme - .workspace - .drop_target_overlay_color + theme::current(cx).workspace.drop_target_overlay_color } diff --git a/crates/workspace/src/shared_screen.rs b/crates/workspace/src/shared_screen.rs index 5cc54a6a7f..9a2e0bc5d2 100644 --- a/crates/workspace/src/shared_screen.rs +++ b/crates/workspace/src/shared_screen.rs @@ -12,7 +12,6 @@ use gpui::{ platform::MouseButton, AppContext, Entity, Task, View, ViewContext, }; -use settings::Settings; use smallvec::SmallVec; use std::{ borrow::Cow, @@ -88,7 +87,7 @@ impl View for SharedScreen { } }) .contained() - .with_style(cx.global::().theme.shared_screen) + .with_style(theme::current(cx).shared_screen) }) .on_down(MouseButton::Left, |_, _, cx| cx.focus_parent()) .into_any() diff --git a/crates/workspace/src/sidebar.rs b/crates/workspace/src/sidebar.rs index 6463ab7d24..50148fa211 100644 --- a/crates/workspace/src/sidebar.rs +++ b/crates/workspace/src/sidebar.rs @@ -4,7 +4,6 @@ use gpui::{ AppContext, Entity, Subscription, View, ViewContext, ViewHandle, WeakViewHandle, WindowContext, }; use serde::Deserialize; -use settings::Settings; use std::rc::Rc; pub trait SidebarItem: View { @@ -192,7 +191,7 @@ impl View for Sidebar { fn render(&mut self, cx: &mut ViewContext) -> AnyElement { if let Some(active_item) = self.active_item() { enum ResizeHandleTag {} - let style = &cx.global::().theme.workspace.sidebar; + let style = &theme::current(cx).workspace.sidebar; ChildView::new(active_item.as_any(), cx) .contained() .with_style(style.container) @@ -231,7 +230,7 @@ impl View for SidebarButtons { } fn render(&mut self, cx: &mut ViewContext) -> AnyElement { - let theme = &cx.global::().theme; + let theme = &theme::current(cx); let tooltip_style = theme.tooltip.clone(); let theme = &theme.workspace.status_bar.sidebar_buttons; let sidebar = self.sidebar.read(cx); diff --git a/crates/workspace/src/status_bar.rs b/crates/workspace/src/status_bar.rs index b4de6b3575..6fc1467566 100644 --- a/crates/workspace/src/status_bar.rs +++ b/crates/workspace/src/status_bar.rs @@ -11,7 +11,6 @@ use gpui::{ AnyElement, AnyViewHandle, Entity, LayoutContext, SceneBuilder, SizeConstraint, Subscription, View, ViewContext, ViewHandle, WindowContext, }; -use settings::Settings; pub trait StatusItemView: View { fn set_active_pane_item( @@ -47,7 +46,7 @@ impl View for StatusBar { } fn render(&mut self, cx: &mut ViewContext) -> AnyElement { - let theme = &cx.global::().theme.workspace.status_bar; + let theme = &theme::current(cx).workspace.status_bar; StatusBarElement { left: Flex::row() diff --git a/crates/workspace/src/toolbar.rs b/crates/workspace/src/toolbar.rs index b2832aa1e8..30890ed5d2 100644 --- a/crates/workspace/src/toolbar.rs +++ b/crates/workspace/src/toolbar.rs @@ -3,7 +3,6 @@ use gpui::{ elements::*, platform::CursorStyle, platform::MouseButton, Action, AnyElement, AnyViewHandle, AppContext, Entity, View, ViewContext, ViewHandle, WeakViewHandle, WindowContext, }; -use settings::Settings; pub trait ToolbarItemView: View { fn set_active_pane_item( @@ -68,7 +67,7 @@ impl View for Toolbar { } fn render(&mut self, cx: &mut ViewContext) -> AnyElement { - let theme = &cx.global::().theme.workspace.toolbar; + let theme = &theme::current(cx).workspace.toolbar; let mut primary_left_items = Vec::new(); let mut primary_right_items = Vec::new(); @@ -131,7 +130,7 @@ impl View for Toolbar { let height = theme.height * primary_items_row_count as f32; let nav_button_height = theme.height; let button_style = theme.nav_button; - let tooltip_style = cx.global::().theme.tooltip.clone(); + let tooltip_style = theme::current(cx).tooltip.clone(); Flex::column() .with_child( diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index d956db10b6..a94bf3ce1c 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -76,12 +76,11 @@ pub use persistence::{ use postage::prelude::Stream; use project::{Project, ProjectEntryId, ProjectPath, Worktree, WorktreeId}; use serde::Deserialize; -use settings::Settings; use shared_screen::SharedScreen; use sidebar::{Sidebar, SidebarButtons, SidebarSide, ToggleSidebarItem}; use status_bar::StatusBar; pub use status_bar::StatusItemView; -use theme::{Theme, ThemeRegistry}; +use theme::Theme; pub use toolbar::{ToolbarItemLocation, ToolbarItemView}; use util::{async_iife, paths, ResultExt}; pub use workspace_settings::{AutosaveSetting, DockAnchor, GitGutterSetting, WorkspaceSettings}; @@ -276,7 +275,7 @@ pub fn init(app_state: Arc, cx: &mut AppContext) { cx.add_action( move |_: &mut Workspace, _: &OpenSettings, cx: &mut ViewContext| { create_and_open_local_file(&paths::SETTINGS, cx, || { - Settings::initial_user_settings_content(&Assets) + settings::initial_user_settings_content(&Assets) .as_ref() .into() }) @@ -361,7 +360,6 @@ pub fn register_deserializable_item(cx: &mut AppContext) { pub struct AppState { pub languages: Arc, - pub themes: Arc, pub client: Arc, pub user_store: ModelHandle, pub fs: Arc, @@ -379,7 +377,6 @@ impl AppState { if !cx.has_global::() { cx.set_global(SettingsStore::test(cx)); - cx.set_global(Settings::test(cx)); } let fs = fs::FakeFs::new(cx.background().clone()); @@ -387,14 +384,13 @@ impl AppState { let http_client = util::http::FakeHttpClient::with_404_response(); let client = Client::new(http_client.clone(), cx); let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http_client, cx)); - let themes = ThemeRegistry::new((), cx.font_cache().clone()); + theme::init((), cx); client::init(&client, cx); crate::init_settings(cx); Arc::new(Self { client, - themes, fs, languages, user_store, @@ -1992,7 +1988,7 @@ impl Workspace { enum DisconnectedOverlay {} Some( MouseEventHandler::::new(0, cx, |_, cx| { - let theme = &cx.global::().theme; + let theme = &theme::current(cx); Label::new( "Your connection to the remote project has been lost.", theme.workspace.disconnected_overlay.text.clone(), @@ -2630,7 +2626,6 @@ impl Workspace { pub fn test_new(project: ModelHandle, cx: &mut ViewContext) -> Self { let app_state = Arc::new(AppState { languages: project.read(cx).languages().clone(), - themes: ThemeRegistry::new((), cx.font_cache().clone()), client: project.read(cx).client(), user_store: project.read(cx).user_store(), fs: project.read(cx).fs().clone(), @@ -2776,7 +2771,7 @@ impl View for Workspace { } fn render(&mut self, cx: &mut ViewContext) -> AnyElement { - let theme = cx.global::().theme.clone(); + let theme = theme::current(cx).clone(); Stack::new() .with_child( Flex::column() @@ -3798,7 +3793,7 @@ mod tests { cx.foreground().forbid_parking(); cx.update(|cx| { cx.set_global(SettingsStore::test(cx)); - cx.set_global(Settings::test(cx)); + theme::init((), cx); language::init(cx); crate::init_settings(cx); }); diff --git a/crates/zed/src/languages.rs b/crates/zed/src/languages.rs index 91b58f634b..1f2b359af1 100644 --- a/crates/zed/src/languages.rs +++ b/crates/zed/src/languages.rs @@ -3,7 +3,6 @@ pub use language::*; use node_runtime::NodeRuntime; use rust_embed::RustEmbed; use std::{borrow::Cow, str, sync::Arc}; -use theme::ThemeRegistry; mod c; mod elixir; @@ -32,11 +31,7 @@ mod yaml; #[exclude = "*.rs"] struct LanguageDir; -pub fn init( - languages: Arc, - themes: Arc, - node_runtime: Arc, -) { +pub fn init(languages: Arc, node_runtime: Arc) { fn adapter_arc(adapter: impl LspAdapter) -> Arc { Arc::new(adapter) } @@ -69,7 +64,6 @@ pub fn init( vec![adapter_arc(json::JsonLspAdapter::new( node_runtime.clone(), languages.clone(), - themes.clone(), ))], ), ("markdown", tree_sitter_markdown::language(), vec![]), diff --git a/crates/zed/src/languages/json.rs b/crates/zed/src/languages/json.rs index 8ea07c626d..1fb1a5a941 100644 --- a/crates/zed/src/languages/json.rs +++ b/crates/zed/src/languages/json.rs @@ -16,7 +16,6 @@ use std::{ path::{Path, PathBuf}, sync::Arc, }; -use theme::ThemeRegistry; use util::http::HttpClient; use util::{paths, ResultExt}; @@ -30,20 +29,11 @@ fn server_binary_arguments(server_path: &Path) -> Vec { pub struct JsonLspAdapter { node: Arc, languages: Arc, - themes: Arc, } impl JsonLspAdapter { - pub fn new( - node: Arc, - languages: Arc, - themes: Arc, - ) -> Self { - JsonLspAdapter { - node, - languages, - themes, - } + pub fn new(node: Arc, languages: Arc) -> Self { + JsonLspAdapter { node, languages } } } @@ -128,18 +118,15 @@ impl LspAdapter for JsonLspAdapter { cx: &mut AppContext, ) -> Option> { let action_names = cx.all_action_names().collect::>(); - let theme_names = &self - .themes - .list(**cx.default_global::()) - .map(|meta| meta.name) - .collect::>(); + let staff_mode = cx.global::().0; let language_names = &self.languages.language_names(); - let settings_schema = cx - .global::() - .json_schema(&SettingsJsonSchemaParams { - theme_names, + let settings_schema = cx.global::().json_schema( + &SettingsJsonSchemaParams { language_names, - }); + staff_mode, + }, + cx, + ); Some( future::ready(serde_json::json!({ "json": { diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index def5049633..18abb2e2c5 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -23,9 +23,7 @@ use node_runtime::NodeRuntime; use parking_lot::Mutex; use project::Fs; use serde::{Deserialize, Serialize}; -use settings::{ - default_settings, handle_settings_file_changes, watch_config_file, Settings, SettingsStore, -}; +use settings::{default_settings, handle_settings_file_changes, watch_config_file, SettingsStore}; use simplelog::ConfigBuilder; use smol::process::Command; use std::{ @@ -56,7 +54,6 @@ use welcome::{show_welcome_experience, FIRST_OPEN}; use fs::RealFs; #[cfg(debug_assertions)] use staff_mode::StaffMode; -use theme::ThemeRegistry; use util::{channel::RELEASE_CHANNEL, paths, ResultExt, TryFutureExt}; use workspace::{ dock::FocusDock, item::ItemHandle, notifications::NotifyResultExt, AppState, OpenSettings, @@ -84,7 +81,6 @@ fn main() { load_embedded_fonts(&app); let fs = Arc::new(RealFs); - let themes = ThemeRegistry::new(Assets, app.font_cache()); let user_settings_file_rx = watch_config_file(app.background(), fs.clone(), paths::SETTINGS.clone()); let user_keymap_file_rx = @@ -124,7 +120,6 @@ fn main() { app.run(move |cx| { cx.set_global(*RELEASE_CHANNEL); - cx.set_global(themes.clone()); #[cfg(debug_assertions)] cx.set_global(StaffMode(true)); @@ -148,11 +143,12 @@ fn main() { let languages = Arc::new(languages); let node_runtime = NodeRuntime::new(http.clone(), cx.background().to_owned()); - languages::init(languages.clone(), themes.clone(), node_runtime.clone()); + languages::init(languages.clone(), node_runtime.clone()); let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http.clone(), cx)); cx.set_global(client.clone()); + theme::init(Assets, cx); context_menu::init(cx); project::Project::init(&client, cx); client::init(&client, cx); @@ -171,13 +167,12 @@ fn main() { theme_testbench::init(cx); copilot::init(http.clone(), node_runtime, cx); - cx.spawn(|cx| watch_themes(fs.clone(), themes.clone(), cx)) - .detach(); + cx.spawn(|cx| watch_themes(fs.clone(), cx)).detach(); - languages.set_theme(cx.global::().theme.clone()); - cx.observe_global::({ + languages.set_theme(theme::current(cx).clone()); + cx.observe_global::({ let languages = languages.clone(); - move |cx| languages.set_theme(cx.global::().theme.clone()) + move |cx| languages.set_theme(theme::current(cx).clone()) }) .detach(); @@ -190,7 +185,6 @@ fn main() { let app_state = Arc::new(AppState { languages, - themes, client: client.clone(), user_store, fs, @@ -208,10 +202,13 @@ fn main() { journal::init(app_state.clone(), cx); language_selector::init(cx); theme_selector::init(cx); - zed::init(&app_state, cx); + activity_indicator::init(cx); + lsp_log::init(cx); + call::init(app_state.client.clone(), app_state.user_store.clone(), cx); collab_ui::init(&app_state, cx); feedback::init(cx); welcome::init(cx); + zed::init(&app_state, cx); cx.set_menus(menus::menus()); @@ -584,11 +581,7 @@ fn load_embedded_fonts(app: &App) { } #[cfg(debug_assertions)] -async fn watch_themes( - fs: Arc, - themes: Arc, - mut cx: AsyncAppContext, -) -> Option<()> { +async fn watch_themes(fs: Arc, mut cx: AsyncAppContext) -> Option<()> { let mut events = fs .watch("styles/src".as_ref(), Duration::from_millis(100)) .await; @@ -600,7 +593,7 @@ async fn watch_themes( .await .log_err()?; if output.status.success() { - cx.update(|cx| theme_selector::reload(themes.clone(), cx)) + cx.update(|cx| theme_selector::reload(cx)) } else { eprintln!( "build script failed {}", diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index d6e4f26b67..5b271762ed 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -30,10 +30,11 @@ use search::{BufferSearchBar, ProjectSearchBar}; use serde::Deserialize; use serde_json::to_string_pretty; use settings::{ - adjust_font_size_delta, KeymapFileContent, Settings, SettingsStore, DEFAULT_SETTINGS_ASSET_PATH, + adjust_font_size_delta, KeymapFileContent, SettingsStore, DEFAULT_SETTINGS_ASSET_PATH, }; use std::{borrow::Cow, str, sync::Arc}; use terminal_view::terminal_button::TerminalButton; +use theme::ThemeSettings; use util::{channel::ReleaseChannel, paths, ResultExt}; use uuid::Uuid; use welcome::BaseKeymap; @@ -124,7 +125,7 @@ pub fn init(app_state: &Arc, cx: &mut gpui::AppContext) { }); cx.add_global_action(move |_: &DecreaseBufferFontSize, cx| { adjust_font_size_delta(cx, |size, cx| { - if cx.global::().buffer_font_size + *size > MIN_FONT_SIZE { + if cx.global::().buffer_font_size + *size > MIN_FONT_SIZE { *size -= 1.0; } }) @@ -258,9 +259,6 @@ pub fn init(app_state: &Arc, cx: &mut gpui::AppContext) { } } }); - activity_indicator::init(cx); - lsp_log::init(cx); - call::init(app_state.client.clone(), app_state.user_store.clone(), cx); load_default_keymap(cx); } @@ -1910,7 +1908,7 @@ mod tests { cx.update(|cx| { cx.set_global(SettingsStore::test(cx)); - cx.set_global(ThemeRegistry::new(Assets, cx.font_cache().clone())); + theme::init(Assets, cx); welcome::init(cx); cx.add_global_action(|_: &A, _cx| {}); @@ -2038,15 +2036,25 @@ mod tests { ]) .unwrap(); let themes = ThemeRegistry::new(Assets, cx.font_cache().clone()); - let settings = Settings::defaults(Assets, cx.font_cache(), &themes); + let mut settings = SettingsStore::default(); + settings + .set_default_settings(&settings::default_settings(), cx) + .unwrap(); + cx.set_global(settings); + theme::init(Assets, cx); let mut has_default_theme = false; for theme_name in themes.list(false).map(|meta| meta.name) { let theme = themes.get(&theme_name).unwrap(); - if theme.meta.name == settings.theme.meta.name { + assert_eq!(theme.meta.name, theme_name); + if theme.meta.name + == settings::get_setting::(None, cx) + .theme + .meta + .name + { has_default_theme = true; } - assert_eq!(theme.meta.name, theme_name); } assert!(has_default_theme); } @@ -2056,10 +2064,9 @@ mod tests { let mut languages = LanguageRegistry::test(); languages.set_executor(cx.background().clone()); let languages = Arc::new(languages); - let themes = ThemeRegistry::new((), cx.font_cache().clone()); let http = FakeHttpClient::with_404_response(); let node_runtime = NodeRuntime::new(http, cx.background().to_owned()); - languages::init(languages.clone(), themes, node_runtime); + languages::init(languages.clone(), node_runtime); for name in languages.language_names() { languages.language_for_name(&name); } @@ -2073,6 +2080,7 @@ mod tests { let state = Arc::get_mut(&mut app_state).unwrap(); state.initialize_workspace = initialize_workspace; state.build_window_options = build_window_options; + theme::init((), cx); call::init(app_state.client.clone(), app_state.user_store.clone(), cx); workspace::init(app_state.clone(), cx); language::init(cx);