settings_ui: Add theme settings controls (#15115)
This PR adds settings controls for the theme settings. Release Notes: - N/A
This commit is contained in:
parent
325e6b9fef
commit
740c444089
11 changed files with 392 additions and 156 deletions
257
crates/settings_ui/src/appearance_settings_controls.rs
Normal file
257
crates/settings_ui/src/appearance_settings_controls.rs
Normal file
|
@ -0,0 +1,257 @@
|
|||
use gpui::{AppContext, FontWeight};
|
||||
use settings::{EditableSettingControl, Settings};
|
||||
use theme::{SystemAppearance, ThemeMode, ThemeRegistry, ThemeSettings};
|
||||
use ui::{
|
||||
prelude::*, ContextMenu, DropdownMenu, NumericStepper, SettingsContainer, SettingsGroup,
|
||||
ToggleButton,
|
||||
};
|
||||
|
||||
#[derive(IntoElement)]
|
||||
pub struct AppearanceSettingsControls {}
|
||||
|
||||
impl AppearanceSettingsControls {
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for AppearanceSettingsControls {
|
||||
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
||||
SettingsContainer::new()
|
||||
.child(
|
||||
SettingsGroup::new("Theme").child(
|
||||
h_flex()
|
||||
.gap_2()
|
||||
.justify_between()
|
||||
.child(ThemeControl)
|
||||
.child(ThemeModeControl),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
SettingsGroup::new("Font")
|
||||
.child(UiFontSizeControl)
|
||||
.child(UiFontWeightControl),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(IntoElement)]
|
||||
struct ThemeControl;
|
||||
|
||||
impl EditableSettingControl for ThemeControl {
|
||||
type Value = String;
|
||||
type Settings = ThemeSettings;
|
||||
|
||||
fn name(&self) -> SharedString {
|
||||
"Theme".into()
|
||||
}
|
||||
|
||||
fn read(cx: &AppContext) -> Self::Value {
|
||||
let settings = ThemeSettings::get_global(cx);
|
||||
let appearance = SystemAppearance::global(cx);
|
||||
settings
|
||||
.theme_selection
|
||||
.as_ref()
|
||||
.map(|selection| selection.theme(appearance.0).to_string())
|
||||
.unwrap_or_else(|| ThemeSettings::default_theme(*appearance).to_string())
|
||||
}
|
||||
|
||||
fn apply(
|
||||
settings: &mut <Self::Settings as Settings>::FileContent,
|
||||
value: Self::Value,
|
||||
cx: &AppContext,
|
||||
) {
|
||||
let appearance = SystemAppearance::global(cx);
|
||||
settings.set_theme(value, appearance.0);
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for ThemeControl {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
let value = Self::read(cx);
|
||||
|
||||
DropdownMenu::new(
|
||||
"theme",
|
||||
value.clone(),
|
||||
ContextMenu::build(cx, |mut menu, cx| {
|
||||
let theme_registry = ThemeRegistry::global(cx);
|
||||
|
||||
for theme in theme_registry.list_names(false) {
|
||||
menu = menu.custom_entry(
|
||||
{
|
||||
let theme = theme.clone();
|
||||
move |_cx| Label::new(theme.clone()).into_any_element()
|
||||
},
|
||||
{
|
||||
let theme = theme.clone();
|
||||
move |cx| {
|
||||
Self::write(theme.to_string(), cx);
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
menu
|
||||
}),
|
||||
)
|
||||
.full_width(true)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(IntoElement)]
|
||||
struct ThemeModeControl;
|
||||
|
||||
impl EditableSettingControl for ThemeModeControl {
|
||||
type Value = ThemeMode;
|
||||
type Settings = ThemeSettings;
|
||||
|
||||
fn name(&self) -> SharedString {
|
||||
"Theme Mode".into()
|
||||
}
|
||||
|
||||
fn read(cx: &AppContext) -> Self::Value {
|
||||
let settings = ThemeSettings::get_global(cx);
|
||||
settings
|
||||
.theme_selection
|
||||
.as_ref()
|
||||
.and_then(|selection| selection.mode())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn apply(
|
||||
settings: &mut <Self::Settings as Settings>::FileContent,
|
||||
value: Self::Value,
|
||||
_cx: &AppContext,
|
||||
) {
|
||||
settings.set_mode(value);
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for ThemeModeControl {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
let value = Self::read(cx);
|
||||
|
||||
h_flex()
|
||||
.child(
|
||||
ToggleButton::new("light", "Light")
|
||||
.style(ButtonStyle::Filled)
|
||||
.size(ButtonSize::Large)
|
||||
.selected(value == ThemeMode::Light)
|
||||
.on_click(|_, cx| Self::write(ThemeMode::Light, cx))
|
||||
.first(),
|
||||
)
|
||||
.child(
|
||||
ToggleButton::new("system", "System")
|
||||
.style(ButtonStyle::Filled)
|
||||
.size(ButtonSize::Large)
|
||||
.selected(value == ThemeMode::System)
|
||||
.on_click(|_, cx| Self::write(ThemeMode::System, cx))
|
||||
.middle(),
|
||||
)
|
||||
.child(
|
||||
ToggleButton::new("dark", "Dark")
|
||||
.style(ButtonStyle::Filled)
|
||||
.size(ButtonSize::Large)
|
||||
.selected(value == ThemeMode::Dark)
|
||||
.on_click(|_, cx| Self::write(ThemeMode::Dark, cx))
|
||||
.last(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(IntoElement)]
|
||||
struct UiFontSizeControl;
|
||||
|
||||
impl EditableSettingControl for UiFontSizeControl {
|
||||
type Value = Pixels;
|
||||
type Settings = ThemeSettings;
|
||||
|
||||
fn name(&self) -> SharedString {
|
||||
"UI Font Size".into()
|
||||
}
|
||||
|
||||
fn read(cx: &AppContext) -> Self::Value {
|
||||
let settings = ThemeSettings::get_global(cx);
|
||||
settings.ui_font_size
|
||||
}
|
||||
|
||||
fn apply(
|
||||
settings: &mut <Self::Settings as Settings>::FileContent,
|
||||
value: Self::Value,
|
||||
_cx: &AppContext,
|
||||
) {
|
||||
settings.ui_font_size = Some(value.into());
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for UiFontSizeControl {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
let value = Self::read(cx);
|
||||
|
||||
h_flex()
|
||||
.gap_2()
|
||||
.child(Icon::new(IconName::FontSize))
|
||||
.child(NumericStepper::new(
|
||||
value.to_string(),
|
||||
move |_, cx| {
|
||||
Self::write(value - px(1.), cx);
|
||||
},
|
||||
move |_, cx| {
|
||||
Self::write(value + px(1.), cx);
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(IntoElement)]
|
||||
struct UiFontWeightControl;
|
||||
|
||||
impl EditableSettingControl for UiFontWeightControl {
|
||||
type Value = FontWeight;
|
||||
type Settings = ThemeSettings;
|
||||
|
||||
fn name(&self) -> SharedString {
|
||||
"UI Font Weight".into()
|
||||
}
|
||||
|
||||
fn read(cx: &AppContext) -> Self::Value {
|
||||
let settings = ThemeSettings::get_global(cx);
|
||||
settings.ui_font.weight
|
||||
}
|
||||
|
||||
fn apply(
|
||||
settings: &mut <Self::Settings as Settings>::FileContent,
|
||||
value: Self::Value,
|
||||
_cx: &AppContext,
|
||||
) {
|
||||
settings.ui_font_weight = Some(value.0);
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for UiFontWeightControl {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
let value = Self::read(cx);
|
||||
|
||||
h_flex()
|
||||
.gap_2()
|
||||
.child(Icon::new(IconName::FontWeight))
|
||||
.child(DropdownMenu::new(
|
||||
"ui-font-weight",
|
||||
value.0.to_string(),
|
||||
ContextMenu::build(cx, |mut menu, _cx| {
|
||||
for weight in FontWeight::ALL {
|
||||
menu = menu.custom_entry(
|
||||
move |_cx| Label::new(weight.0.to_string()).into_any_element(),
|
||||
{
|
||||
move |cx| {
|
||||
Self::write(weight, cx);
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
menu
|
||||
}),
|
||||
))
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
mod theme_settings_controls;
|
||||
mod appearance_settings_controls;
|
||||
|
||||
use std::any::TypeId;
|
||||
|
||||
|
@ -10,7 +10,7 @@ use ui::prelude::*;
|
|||
use workspace::item::{Item, ItemEvent};
|
||||
use workspace::Workspace;
|
||||
|
||||
use crate::theme_settings_controls::ThemeSettingsControls;
|
||||
use crate::appearance_settings_controls::AppearanceSettingsControls;
|
||||
|
||||
pub struct SettingsUiFeatureFlag;
|
||||
|
||||
|
@ -110,7 +110,7 @@ impl Render for SettingsPage {
|
|||
v_flex()
|
||||
.gap_1()
|
||||
.child(Label::new("Appearance"))
|
||||
.child(ThemeSettingsControls::new()),
|
||||
.child(AppearanceSettingsControls::new()),
|
||||
)
|
||||
.child(
|
||||
v_flex()
|
||||
|
|
|
@ -1,112 +0,0 @@
|
|||
use gpui::{AppContext, FontWeight};
|
||||
use settings::{EditableSettingControl, Settings};
|
||||
use theme::ThemeSettings;
|
||||
use ui::{prelude::*, ContextMenu, DropdownMenu, NumericStepper, SettingsContainer, SettingsGroup};
|
||||
|
||||
#[derive(IntoElement)]
|
||||
pub struct ThemeSettingsControls {}
|
||||
|
||||
impl ThemeSettingsControls {
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for ThemeSettingsControls {
|
||||
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
||||
SettingsContainer::new().child(
|
||||
SettingsGroup::new("Font")
|
||||
.child(UiFontSizeControl)
|
||||
.child(UiFontWeightControl),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(IntoElement)]
|
||||
struct UiFontSizeControl;
|
||||
|
||||
impl EditableSettingControl for UiFontSizeControl {
|
||||
type Value = Pixels;
|
||||
type Settings = ThemeSettings;
|
||||
|
||||
fn name(&self) -> SharedString {
|
||||
"UI Font Size".into()
|
||||
}
|
||||
|
||||
fn read(cx: &AppContext) -> Self::Value {
|
||||
let settings = ThemeSettings::get_global(cx);
|
||||
settings.ui_font_size
|
||||
}
|
||||
|
||||
fn apply(settings: &mut <Self::Settings as Settings>::FileContent, value: Self::Value) {
|
||||
settings.ui_font_size = Some(value.into());
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for UiFontSizeControl {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
let value = Self::read(cx);
|
||||
|
||||
h_flex()
|
||||
.gap_2()
|
||||
.child(Icon::new(IconName::FontSize))
|
||||
.child(NumericStepper::new(
|
||||
value.to_string(),
|
||||
move |_, cx| {
|
||||
Self::write(value - px(1.), cx);
|
||||
},
|
||||
move |_, cx| {
|
||||
Self::write(value + px(1.), cx);
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(IntoElement)]
|
||||
struct UiFontWeightControl;
|
||||
|
||||
impl EditableSettingControl for UiFontWeightControl {
|
||||
type Value = FontWeight;
|
||||
type Settings = ThemeSettings;
|
||||
|
||||
fn name(&self) -> SharedString {
|
||||
"UI Font Weight".into()
|
||||
}
|
||||
|
||||
fn read(cx: &AppContext) -> Self::Value {
|
||||
let settings = ThemeSettings::get_global(cx);
|
||||
settings.ui_font.weight
|
||||
}
|
||||
|
||||
fn apply(settings: &mut <Self::Settings as Settings>::FileContent, value: Self::Value) {
|
||||
settings.ui_font_weight = Some(value.0);
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for UiFontWeightControl {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
let value = Self::read(cx);
|
||||
|
||||
h_flex()
|
||||
.gap_2()
|
||||
.child(Icon::new(IconName::FontWeight))
|
||||
.child(DropdownMenu::new(
|
||||
"ui-font-weight",
|
||||
value.0.to_string(),
|
||||
ContextMenu::build(cx, |mut menu, _cx| {
|
||||
for weight in FontWeight::ALL {
|
||||
menu = menu.custom_entry(
|
||||
move |_cx| Label::new(weight.0.to_string()).into_any_element(),
|
||||
{
|
||||
move |cx| {
|
||||
Self::write(weight, cx);
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
menu
|
||||
}),
|
||||
))
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue