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:
parent
001376fd6d
commit
659f34bf21
4 changed files with 191 additions and 6 deletions
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
52
crates/theme/src/font_family_cache.rs
Normal file
52
crates/theme/src/font_family_cache.rs
Normal 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()
|
||||
}
|
||||
}
|
|
@ -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| {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue