Detailed changes
@@ -6,7 +6,7 @@ use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings_macros::{MergeFrom, with_fallible_options};
-use crate::FontFamilyName;
+use crate::{FontFamilyName, FontSize};
#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
pub struct ProjectTerminalSettingsContent {
@@ -75,8 +75,7 @@ pub struct TerminalSettingsContent {
///
/// If this option is not included,
/// the terminal will default to matching the buffer's font size.
- #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
- pub font_size: Option<f32>,
+ pub font_size: Option<FontSize>,
/// Sets the terminal's font family.
///
/// If this option is not included,
@@ -1,5 +1,5 @@
use collections::{HashMap, IndexMap};
-use gpui::{FontFallbacks, FontFeatures, FontStyle, FontWeight, SharedString};
+use gpui::{FontFallbacks, FontFeatures, FontStyle, FontWeight, Pixels, SharedString};
use schemars::{JsonSchema, JsonSchema_repr};
use serde::{Deserialize, Deserializer, Serialize};
use serde_json::Value;
@@ -15,8 +15,7 @@ use crate::serialize_f32_with_two_decimal_places;
#[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
pub struct ThemeSettingsContent {
/// The default font size for text in the UI.
- #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
- pub ui_font_size: Option<f32>,
+ pub ui_font_size: Option<FontSize>,
/// The name of a font to use for rendering in the UI.
pub ui_font_family: Option<FontFamilyName>,
/// The font fallbacks to use for rendering in the UI.
@@ -35,8 +34,7 @@ pub struct ThemeSettingsContent {
#[schemars(extend("uniqueItems" = true))]
pub buffer_font_fallbacks: Option<Vec<FontFamilyName>>,
/// The default font size for rendering in text buffers.
- #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
- pub buffer_font_size: Option<f32>,
+ pub buffer_font_size: Option<FontSize>,
/// The weight of the editor font in CSS units from 100 to 900.
#[schemars(default = "default_buffer_font_weight")]
pub buffer_font_weight: Option<FontWeight>,
@@ -46,11 +44,9 @@ pub struct ThemeSettingsContent {
#[schemars(default = "default_font_features")]
pub buffer_font_features: Option<FontFeatures>,
/// The font size for agent responses in the agent panel. Falls back to the UI font size if unset.
- #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
- pub agent_ui_font_size: Option<f32>,
+ pub agent_ui_font_size: Option<FontSize>,
/// The font size for user messages in the agent panel.
- #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
- pub agent_buffer_font_size: Option<f32>,
+ pub agent_buffer_font_size: Option<FontSize>,
/// The name of the Zed theme to use.
pub theme: Option<ThemeSelection>,
/// The name of the icon theme to use.
@@ -79,6 +75,46 @@ pub struct ThemeSettingsContent {
pub theme_overrides: HashMap<String, ThemeStyleContent>,
}
+/// A font size value in pixels, wrapping around `f32` for custom settings UI rendering.
+#[derive(
+ Clone,
+ Copy,
+ Debug,
+ Serialize,
+ Deserialize,
+ JsonSchema,
+ MergeFrom,
+ PartialEq,
+ PartialOrd,
+ derive_more::FromStr,
+)]
+#[serde(transparent)]
+pub struct FontSize(#[serde(serialize_with = "serialize_f32_with_two_decimal_places")] pub f32);
+
+impl Display for FontSize {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{:.2}", self.0)
+ }
+}
+
+impl From<f32> for FontSize {
+ fn from(value: f32) -> Self {
+ Self(value)
+ }
+}
+
+impl From<FontSize> for Pixels {
+ fn from(value: FontSize) -> Self {
+ value.0.into()
+ }
+}
+
+impl From<Pixels> for FontSize {
+ fn from(value: Pixels) -> Self {
+ Self(value.into())
+ }
+}
+
#[derive(
Clone,
Copy,
@@ -736,7 +736,9 @@ impl VsCodeSettings {
font_fallbacks,
font_family,
font_features: None,
- font_size: self.read_f32("terminal.integrated.fontSize"),
+ font_size: self
+ .read_f32("terminal.integrated.fontSize")
+ .map(FontSize::from),
font_weight: None,
keep_selection_on_copy: None,
line_height: self
@@ -795,7 +797,7 @@ impl VsCodeSettings {
ui_font_weight: None,
buffer_font_family,
buffer_font_fallbacks,
- buffer_font_size: self.read_f32("editor.fontSize"),
+ buffer_font_size: self.read_f32("editor.fontSize").map(FontSize::from),
buffer_font_weight: self.read_f32("editor.fontWeight").map(|w| w.into()),
buffer_line_height: None,
buffer_font_features: None,
@@ -31,7 +31,7 @@ use ui::{
Banner, ContextMenu, Divider, DropdownMenu, DropdownStyle, IconButtonShape, KeyBinding,
KeybindingHint, PopoverMenu, Switch, Tooltip, TreeViewItem, WithScrollbar, prelude::*,
};
-use ui_input::{NumberField, NumberFieldType};
+use ui_input::{NumberField, NumberFieldMode, NumberFieldType};
use util::{ResultExt as _, paths::PathStyle, rel_path::RelPath};
use workspace::{AppState, OpenOptions, OpenVisible, Workspace, client_side_decorations};
use zed_actions::{OpenProjectSettings, OpenSettings, OpenSettingsAt};
@@ -513,6 +513,7 @@ fn init_renderers(cx: &mut App) {
.add_basic_renderer::<settings::EditPredictionsMode>(render_dropdown)
.add_basic_renderer::<settings::RelativeLineNumbers>(render_dropdown)
.add_basic_renderer::<settings::WindowDecorations>(render_dropdown)
+ .add_basic_renderer::<settings::FontSize>(render_editable_number_field)
// please semicolon stay on next line
;
}
@@ -3667,7 +3668,44 @@ fn render_number_field<T: NumberFieldType + Send + Sync>(
) -> AnyElement {
let (_, value) = SettingsStore::global(cx).get_value_from_file(file.to_settings(), field.pick);
let value = value.copied().unwrap_or_else(T::min_value);
- NumberField::new("numeric_stepper", value, window, cx)
+
+ let id = field
+ .json_path
+ .map(|p| format!("numeric_stepper_{}", p))
+ .unwrap_or_else(|| "numeric_stepper".to_string());
+
+ NumberField::new(id, value, window, cx)
+ .tab_index(0_isize)
+ .on_change({
+ move |value, _window, cx| {
+ let value = *value;
+ update_settings_file(file.clone(), field.json_path, cx, move |settings, _cx| {
+ (field.write)(settings, Some(value));
+ })
+ .log_err(); // todo(settings_ui) don't log err
+ }
+ })
+ .into_any_element()
+}
+
+fn render_editable_number_field<T: NumberFieldType + Send + Sync>(
+ field: SettingField<T>,
+ file: SettingsUiFile,
+ _metadata: Option<&SettingsFieldMetadata>,
+ window: &mut Window,
+ cx: &mut App,
+) -> AnyElement {
+ let (_, value) = SettingsStore::global(cx).get_value_from_file(file.to_settings(), field.pick);
+ let value = value.copied().unwrap_or_else(T::min_value);
+
+ let id = field
+ .json_path
+ .map(|p| format!("numeric_stepper_{}", p))
+ .unwrap_or_else(|| "numeric_stepper".to_string());
+
+ NumberField::new(id, value, window, cx)
+ .mode(NumberFieldMode::Edit, cx)
+ .tab_index(0_isize)
.on_change({
move |value, _window, cx| {
let value = *value;
@@ -84,7 +84,7 @@ impl settings::Settings for TerminalSettings {
TerminalSettings {
shell: settings_shell_to_task_shell(project_content.shell.unwrap()),
working_directory: project_content.working_directory.unwrap(),
- font_size: user_content.font_size.map(px),
+ font_size: user_content.font_size.map(Into::into),
font_family: user_content.font_family,
font_fallbacks: user_content.font_fallbacks.map(|fallbacks| {
FontFallbacks::from_fonts(
@@ -11,7 +11,9 @@ use gpui::{
TextStyleRefinement, WeakEntity,
};
-use settings::{CenteredPaddingSettings, CodeFade, DelayMs, InactiveOpacity, MinimumContrast};
+use settings::{
+ CenteredPaddingSettings, CodeFade, DelayMs, FontSize, InactiveOpacity, MinimumContrast,
+};
use ui::prelude::*;
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
@@ -105,6 +107,7 @@ macro_rules! impl_newtype_numeric_stepper_int {
#[rustfmt::skip]
impl_newtype_numeric_stepper_float!(FontWeight, 50., 100., 10., FontWeight::THIN, FontWeight::BLACK);
impl_newtype_numeric_stepper_float!(CodeFade, 0.1, 0.2, 0.05, 0.0, 0.9);
+impl_newtype_numeric_stepper_float!(FontSize, 1.0, 4.0, 0.5, 6.0, 72.0);
impl_newtype_numeric_stepper_float!(InactiveOpacity, 0.1, 0.2, 0.05, 0.0, 1.0);
impl_newtype_numeric_stepper_float!(MinimumContrast, 1., 10., 0.5, 0.0, 106.0);
impl_newtype_numeric_stepper_int!(DelayMs, 100, 500, 10, 0, 2000);