From b440a51675deb1bd19bb62c6b260696c93d625d7 Mon Sep 17 00:00:00 2001 From: Keith Simmons Date: Tue, 8 Mar 2022 18:42:31 -0800 Subject: [PATCH] Make theme selector eagerly display the selected theme --- crates/outline/src/outline.rs | 2 +- crates/theme_selector/src/theme_selector.rs | 80 +++++++++++++++++---- crates/workspace/src/workspace.rs | 14 ++-- 3 files changed, 78 insertions(+), 18 deletions(-) diff --git a/crates/outline/src/outline.rs b/crates/outline/src/outline.rs index 3607f1af87b4b95fb0222ecaad0c35d4a49c2010..dc8ba002a38e9490e2e8980a42a24883277b92d3 100644 --- a/crates/outline/src/outline.rs +++ b/crates/outline/src/outline.rs @@ -144,7 +144,7 @@ impl OutlineView { let view = cx.add_view(|cx| OutlineView::new(outline, editor, settings, cx)); cx.subscribe(&view, Self::on_event).detach(); view - }) + }); } } } diff --git a/crates/theme_selector/src/theme_selector.rs b/crates/theme_selector/src/theme_selector.rs index 9ac35339abe5b1951e85899fbf4e240059092a15..8ea6b577d4978cb4355dda1e4905c26568d6798b 100644 --- a/crates/theme_selector/src/theme_selector.rs +++ b/crates/theme_selector/src/theme_selector.rs @@ -10,7 +10,7 @@ use gpui::{ use parking_lot::Mutex; use postage::watch; use std::{cmp, sync::Arc}; -use theme::ThemeRegistry; +use theme::{ThemeRegistry, Theme}; use workspace::{ menu::{Confirm, SelectNext, SelectPrev}, AppState, Settings, Workspace, @@ -31,6 +31,7 @@ pub struct ThemeSelector { query_editor: ViewHandle, list_state: UniformListState, selected_index: usize, + original_theme: Arc, } action!(Toggle, ThemeSelectorParams); @@ -72,6 +73,8 @@ impl ThemeSelector { cx.subscribe(&query_editor, Self::on_query_editor_event) .detach(); + let original_theme = settings.borrow().theme.clone(); + let mut this = Self { settings, settings_tx, @@ -79,14 +82,19 @@ impl ThemeSelector { query_editor, matches: Vec::new(), list_state: Default::default(), - selected_index: 0, + selected_index: 0, // Default index for now + original_theme, }; this.update_matches(cx); + + // Set selected index to current theme + this.select_if_matching(this.original_theme.name.clone()); + this } fn toggle(workspace: &mut Workspace, action: &Toggle, cx: &mut ViewContext) { - workspace.toggle_modal(cx, |cx, _| { + let possible_closed_theme_selector = workspace.toggle_modal(cx, |cx, _| { let selector = cx.add_view(|cx| { Self::new( action.0.settings_tx.clone(), @@ -98,6 +106,14 @@ impl ThemeSelector { cx.subscribe(&selector, Self::on_event).detach(); selector }); + + if let Some(closed_theme_selector) = possible_closed_theme_selector { + let theme_selector = closed_theme_selector.read(cx); + + theme_selector.settings_tx.lock().borrow_mut().theme = + theme_selector.original_theme.clone(); + cx.refresh_windows(); + } } fn reload(_: &mut Workspace, action: &Reload, cx: &mut ViewContext) { @@ -116,15 +132,8 @@ impl ThemeSelector { } fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext) { - if let Some(mat) = self.matches.get(self.selected_index) { - match self.themes.get(&mat.string) { - Ok(theme) => { - self.settings_tx.lock().borrow_mut().theme = theme; - cx.refresh_windows(); - cx.emit(Event::Dismissed); - } - Err(error) => log::error!("error loading theme {}: {}", mat.string, error), - } + if self.show_selected_theme(cx) { + cx.emit(Event::Dismissed); } } @@ -134,6 +143,8 @@ impl ThemeSelector { } self.list_state .scroll_to(ScrollTarget::Show(self.selected_index)); + + self.show_selected_theme(cx); cx.notify(); } @@ -143,9 +154,38 @@ impl ThemeSelector { } self.list_state .scroll_to(ScrollTarget::Show(self.selected_index)); + + self.show_selected_theme(cx); cx.notify(); } + fn show_selected_theme(&mut self, cx: &mut MutableAppContext) -> bool { + if let Some(mat) = self.matches.get(self.selected_index) { + match self.themes.get(&mat.string) { + Ok(theme) => { + self.settings_tx.lock().borrow_mut().theme = theme; + cx.refresh_windows(); + return true; + } + Err(error) => { + log::error!("error loading theme {}: {}", mat.string, error) + }, + } + } + + return false; + } + + fn select_if_matching(&mut self, theme_name: String) { + self.selected_index = self.matches.iter() + .position(|mat| mat.string == theme_name) + .unwrap_or(self.selected_index); + } + + fn selected_theme_name(&self) -> Option { + self.matches.get(self.selected_index).map(|mat| mat.string.clone()) + } + fn update_matches(&mut self, cx: &mut ViewContext) { let background = cx.background().clone(); let candidates = self @@ -181,6 +221,11 @@ impl ThemeSelector { background, )) }; + + self.selected_index = self.selected_index + .min(self.matches.len() - 1) + .max(0); + cx.notify(); } @@ -204,7 +249,16 @@ impl ThemeSelector { cx: &mut ViewContext, ) { match event { - editor::Event::Edited => self.update_matches(cx), + editor::Event::Edited => { + let previous_selection = self.selected_theme_name(); + self.update_matches(cx); + if let Some(previous_selection) = previous_selection { + self.select_if_matching(previous_selection); + } + + self.show_selected_theme(cx); + + }, editor::Event::Blurred => cx.emit(Event::Dismissed), _ => {} } diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index dee138b0aeec0ca2243c5146f08057f377e1921c..4e057fa6bc47086c507f8e79d7e1168da71f6f17 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -754,20 +754,26 @@ impl Workspace { }) } - pub fn toggle_modal(&mut self, cx: &mut ViewContext, add_view: F) + // Returns the model that was toggled closed if it was open + pub fn toggle_modal(&mut self, cx: &mut ViewContext, add_view: F) -> Option> where V: 'static + View, F: FnOnce(&mut ViewContext, &mut Self) -> ViewHandle, { - if self.modal.as_ref().map_or(false, |modal| modal.is::()) { - self.modal.take(); + cx.notify(); + // Whatever modal was visible is getting clobbered. If its the same type as V, then return + // it. Otherwise, create a new modal and set it as active. + let already_open_modal = self.modal.take() + .and_then(|modal| modal.downcast::()); + if let Some(already_open_modal) = already_open_modal { cx.focus_self(); + Some(already_open_modal) } else { let modal = add_view(cx, self); cx.focus(&modal); self.modal = Some(modal.into()); + None } - cx.notify(); } pub fn modal(&self) -> Option<&AnyViewHandle> {