settings_ui: Add UI and buffer font family controls (#15124)

This PR adds settings controls for changing the UI and buffer font
families.

Release Notes:

- N/A
This commit is contained in:
Marshall Bowers 2024-07-24 18:01:35 -04:00 committed by GitHub
parent 001376fd6d
commit 659f34bf21
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 191 additions and 6 deletions

View file

@ -1,7 +1,7 @@
use gpui::{AppContext, FontWeight};
use project::project_settings::{InlineBlameSettings, ProjectSettings};
use settings::{EditableSettingControl, Settings};
use theme::ThemeSettings;
use theme::{FontFamilyCache, ThemeSettings};
use ui::{
prelude::*, CheckboxWithLabel, ContextMenu, DropdownMenu, NumericStepper, SettingsContainer,
SettingsGroup,
@ -21,13 +21,78 @@ impl RenderOnce for EditorSettingsControls {
SettingsContainer::new()
.child(
SettingsGroup::new("Font")
.child(BufferFontSizeControl)
.child(BufferFontWeightControl),
.child(
h_flex()
.gap_2()
.justify_between()
.child(BufferFontFamilyControl)
.child(BufferFontWeightControl),
)
.child(BufferFontSizeControl),
)
.child(SettingsGroup::new("Editor").child(InlineGitBlameControl))
}
}
#[derive(IntoElement)]
struct BufferFontFamilyControl;
impl EditableSettingControl for BufferFontFamilyControl {
type Value = SharedString;
type Settings = ThemeSettings;
fn name(&self) -> SharedString {
"Buffer Font Family".into()
}
fn read(cx: &AppContext) -> Self::Value {
let settings = ThemeSettings::get_global(cx);
settings.buffer_font.family.clone()
}
fn apply(
settings: &mut <Self::Settings as Settings>::FileContent,
value: Self::Value,
_cx: &AppContext,
) {
settings.buffer_font_family = Some(value.to_string());
}
}
impl RenderOnce for BufferFontFamilyControl {
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
let value = Self::read(cx);
h_flex()
.gap_2()
.child(Icon::new(IconName::Font))
.child(DropdownMenu::new(
"buffer-font-family",
value.clone(),
ContextMenu::build(cx, |mut menu, cx| {
let font_family_cache = FontFamilyCache::global(cx);
for font_name in font_family_cache.list_font_families(cx) {
menu = menu.custom_entry(
{
let font_name = font_name.clone();
move |_cx| Label::new(font_name.clone()).into_any_element()
},
{
let font_name = font_name.clone();
move |cx| {
Self::write(font_name.clone(), cx);
}
},
)
}
menu
}),
))
}
}
#[derive(IntoElement)]
struct BufferFontSizeControl;

View file

@ -1,6 +1,6 @@
use gpui::{AppContext, FontWeight};
use settings::{EditableSettingControl, Settings};
use theme::{SystemAppearance, ThemeMode, ThemeRegistry, ThemeSettings};
use theme::{FontFamilyCache, SystemAppearance, ThemeMode, ThemeRegistry, ThemeSettings};
use ui::{
prelude::*, ContextMenu, DropdownMenu, NumericStepper, SettingsContainer, SettingsGroup,
ToggleButton,
@ -29,8 +29,14 @@ impl RenderOnce for AppearanceSettingsControls {
)
.child(
SettingsGroup::new("Font")
.child(UiFontSizeControl)
.child(UiFontWeightControl),
.child(
h_flex()
.gap_2()
.justify_between()
.child(UiFontFamilyControl)
.child(UiFontWeightControl),
)
.child(UiFontSizeControl),
)
}
}
@ -159,6 +165,65 @@ impl RenderOnce for ThemeModeControl {
}
}
#[derive(IntoElement)]
struct UiFontFamilyControl;
impl EditableSettingControl for UiFontFamilyControl {
type Value = SharedString;
type Settings = ThemeSettings;
fn name(&self) -> SharedString {
"UI Font Family".into()
}
fn read(cx: &AppContext) -> Self::Value {
let settings = ThemeSettings::get_global(cx);
settings.ui_font.family.clone()
}
fn apply(
settings: &mut <Self::Settings as Settings>::FileContent,
value: Self::Value,
_cx: &AppContext,
) {
settings.ui_font_family = Some(value.to_string());
}
}
impl RenderOnce for UiFontFamilyControl {
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
let value = Self::read(cx);
h_flex()
.gap_2()
.child(Icon::new(IconName::Font))
.child(DropdownMenu::new(
"ui-font-family",
value.clone(),
ContextMenu::build(cx, |mut menu, cx| {
let font_family_cache = FontFamilyCache::global(cx);
for font_name in font_family_cache.list_font_families(cx) {
menu = menu.custom_entry(
{
let font_name = font_name.clone();
move |_cx| Label::new(font_name.clone()).into_any_element()
},
{
let font_name = font_name.clone();
move |cx| {
Self::write(font_name.clone(), cx);
}
},
)
}
menu
}),
))
}
}
#[derive(IntoElement)]
struct UiFontSizeControl;

View file

@ -0,0 +1,52 @@
use std::sync::Arc;
use std::time::Instant;
use gpui::{AppContext, Global, ReadGlobal, SharedString};
use parking_lot::RwLock;
#[derive(Default)]
struct FontFamilyCacheState {
loaded_at: Option<Instant>,
font_families: Vec<SharedString>,
}
/// A cache for the list of font families.
///
/// Listing the available font families from the text system is expensive,
/// so we do it once and then use the cached values each render.
#[derive(Default)]
pub struct FontFamilyCache {
state: RwLock<FontFamilyCacheState>,
}
#[derive(Default)]
struct GlobalFontFamilyCache(Arc<FontFamilyCache>);
impl Global for GlobalFontFamilyCache {}
impl FontFamilyCache {
pub fn init_global(cx: &mut AppContext) {
cx.default_global::<GlobalFontFamilyCache>();
}
pub fn global(cx: &AppContext) -> Arc<Self> {
GlobalFontFamilyCache::global(cx).0.clone()
}
pub fn list_font_families(&self, cx: &AppContext) -> Vec<SharedString> {
if self.state.read().loaded_at.is_some() {
return self.state.read().font_families.clone();
}
let mut lock = self.state.write();
lock.font_families = cx
.text_system()
.all_font_names()
.into_iter()
.map(SharedString::from)
.collect();
lock.loaded_at = Some(Instant::now());
lock.font_families.clone()
}
}

View file

@ -8,6 +8,7 @@
mod default_colors;
mod default_theme;
mod font_family_cache;
mod one_themes;
pub mod prelude;
mod registry;
@ -21,6 +22,7 @@ use std::sync::Arc;
use ::settings::{Settings, SettingsStore};
pub use default_colors::*;
pub use default_theme::*;
pub use font_family_cache::*;
pub use registry::*;
pub use scale::*;
pub use schema::*;
@ -82,6 +84,7 @@ pub fn init(themes_to_load: LoadThemes, cx: &mut AppContext) {
}
ThemeSettings::register(cx);
FontFamilyCache::init_global(cx);
let mut prev_buffer_font_size = ThemeSettings::get_global(cx).buffer_font_size;
cx.observe_global::<SettingsStore>(move |cx| {