settings ui: Add numeric steppers to settings UI (#39491)
This PR adds the numeric stepper component to the settings ui and
implements some settings that rely on this component as well.
I also switched {buffer/ui}_font_weight to the `gpui::FontWeight` type
and added a manual implementation of the Schemars trait. This allows Zed
to send min, max, and default information to the JSON LSP when a user is
manually editing the settings file.
The numeric stepper elements added to the settings ui are below:
- ui font size
- ui font weight
- Buffer font size
- Buffer font weight
- Scroll sensitivity
- Fast scroll sensitivity
- Vertical scroll margin
- Horizontal scroll margin
- Inline blame padding
- Inline blame delay
- Inline blame min column
- Unnecessary code fade
- Tab Size
- Hover popover delay
Release Notes:
- N/A
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
use std::{
|
||||
fmt::Display,
|
||||
ops::{Add, Sub},
|
||||
num::{NonZeroU32, NonZeroU64},
|
||||
rc::Rc,
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
use editor::{Editor, EditorStyle};
|
||||
use gpui::{ClickEvent, Entity, FocusHandle, Focusable, Modifiers};
|
||||
use gpui::{ClickEvent, Entity, FocusHandle, Focusable, FontWeight, Modifiers};
|
||||
|
||||
use settings::CodeFade;
|
||||
use ui::{IconButtonShape, prelude::*};
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
@@ -25,15 +26,7 @@ pub enum NumericStepperMode {
|
||||
}
|
||||
|
||||
pub trait NumericStepperType:
|
||||
Display
|
||||
+ Add<Output = Self>
|
||||
+ Sub<Output = Self>
|
||||
+ Copy
|
||||
+ Clone
|
||||
+ Sized
|
||||
+ PartialOrd
|
||||
+ FromStr
|
||||
+ 'static
|
||||
Display + Copy + Clone + Sized + PartialOrd + FromStr + 'static
|
||||
{
|
||||
fn default_format(value: &Self) -> String {
|
||||
format!("{}", value)
|
||||
@@ -43,6 +36,56 @@ pub trait NumericStepperType:
|
||||
fn small_step() -> Self;
|
||||
fn min_value() -> Self;
|
||||
fn max_value() -> Self;
|
||||
fn saturating_add(self, rhs: Self) -> Self;
|
||||
fn saturating_sub(self, rhs: Self) -> Self;
|
||||
}
|
||||
|
||||
impl NumericStepperType for gpui::FontWeight {
|
||||
fn default_step() -> Self {
|
||||
FontWeight(10.0)
|
||||
}
|
||||
fn large_step() -> Self {
|
||||
FontWeight(50.0)
|
||||
}
|
||||
fn small_step() -> Self {
|
||||
FontWeight(5.0)
|
||||
}
|
||||
fn min_value() -> Self {
|
||||
gpui::FontWeight::THIN
|
||||
}
|
||||
fn max_value() -> Self {
|
||||
gpui::FontWeight::BLACK
|
||||
}
|
||||
fn saturating_add(self, rhs: Self) -> Self {
|
||||
FontWeight((self.0 + rhs.0).min(Self::max_value().0))
|
||||
}
|
||||
fn saturating_sub(self, rhs: Self) -> Self {
|
||||
FontWeight((self.0 - rhs.0).max(Self::min_value().0))
|
||||
}
|
||||
}
|
||||
|
||||
impl NumericStepperType for settings::CodeFade {
|
||||
fn default_step() -> Self {
|
||||
CodeFade(0.10)
|
||||
}
|
||||
fn large_step() -> Self {
|
||||
CodeFade(0.20)
|
||||
}
|
||||
fn small_step() -> Self {
|
||||
CodeFade(0.05)
|
||||
}
|
||||
fn min_value() -> Self {
|
||||
CodeFade(0.0)
|
||||
}
|
||||
fn max_value() -> Self {
|
||||
CodeFade(0.9)
|
||||
}
|
||||
fn saturating_add(self, rhs: Self) -> Self {
|
||||
CodeFade((self.0 + rhs.0).min(Self::max_value().0))
|
||||
}
|
||||
fn saturating_sub(self, rhs: Self) -> Self {
|
||||
CodeFade((self.0 - rhs.0).max(Self::min_value().0))
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_numeric_stepper_int {
|
||||
@@ -67,6 +110,50 @@ macro_rules! impl_numeric_stepper_int {
|
||||
fn max_value() -> Self {
|
||||
<$type>::MAX
|
||||
}
|
||||
|
||||
fn saturating_add(self, rhs: Self) -> Self {
|
||||
self.saturating_add(rhs)
|
||||
}
|
||||
|
||||
fn saturating_sub(self, rhs: Self) -> Self {
|
||||
self.saturating_sub(rhs)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_numeric_stepper_nonzero_int {
|
||||
($nonzero:ty, $inner:ty) => {
|
||||
impl NumericStepperType for $nonzero {
|
||||
fn default_step() -> Self {
|
||||
<$nonzero>::new(1).unwrap()
|
||||
}
|
||||
|
||||
fn large_step() -> Self {
|
||||
<$nonzero>::new(10).unwrap()
|
||||
}
|
||||
|
||||
fn small_step() -> Self {
|
||||
<$nonzero>::new(1).unwrap()
|
||||
}
|
||||
|
||||
fn min_value() -> Self {
|
||||
<$nonzero>::MIN
|
||||
}
|
||||
|
||||
fn max_value() -> Self {
|
||||
<$nonzero>::MAX
|
||||
}
|
||||
|
||||
fn saturating_add(self, rhs: Self) -> Self {
|
||||
let result = self.get().saturating_add(rhs.get());
|
||||
<$nonzero>::new(result.max(1)).unwrap()
|
||||
}
|
||||
|
||||
fn saturating_sub(self, rhs: Self) -> Self {
|
||||
let result = self.get().saturating_sub(rhs.get()).max(1);
|
||||
<$nonzero>::new(result).unwrap()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -75,10 +162,7 @@ macro_rules! impl_numeric_stepper_float {
|
||||
($type:ident) => {
|
||||
impl NumericStepperType for $type {
|
||||
fn default_format(value: &Self) -> String {
|
||||
format!("{:^4}", value)
|
||||
.trim_end_matches('0')
|
||||
.trim_end_matches('.')
|
||||
.to_string()
|
||||
format!("{:.2}", value)
|
||||
}
|
||||
|
||||
fn default_step() -> Self {
|
||||
@@ -100,6 +184,14 @@ macro_rules! impl_numeric_stepper_float {
|
||||
fn max_value() -> Self {
|
||||
<$type>::MAX
|
||||
}
|
||||
|
||||
fn saturating_add(self, rhs: Self) -> Self {
|
||||
(self + rhs).clamp(Self::min_value(), Self::max_value())
|
||||
}
|
||||
|
||||
fn saturating_sub(self, rhs: Self) -> Self {
|
||||
(self - rhs).clamp(Self::min_value(), Self::max_value())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -113,6 +205,9 @@ impl_numeric_stepper_int!(u32);
|
||||
impl_numeric_stepper_int!(i64);
|
||||
impl_numeric_stepper_int!(u64);
|
||||
|
||||
impl_numeric_stepper_nonzero_int!(NonZeroU32, u32);
|
||||
impl_numeric_stepper_nonzero_int!(NonZeroU64, u64);
|
||||
|
||||
#[derive(RegisterComponent)]
|
||||
pub struct NumericStepper<T = usize> {
|
||||
id: ElementId,
|
||||
@@ -281,7 +376,7 @@ impl<T: NumericStepperType> RenderOnce for NumericStepper<T> {
|
||||
let min = self.min_value;
|
||||
move |click: &ClickEvent, window: &mut Window, cx: &mut App| {
|
||||
let step = get_step(click.modifiers());
|
||||
let new_value = value - step;
|
||||
let new_value = value.saturating_sub(step);
|
||||
let new_value = if new_value < min { min } else { new_value };
|
||||
on_change(&new_value, window, cx);
|
||||
window.focus_prev();
|
||||
@@ -410,7 +505,7 @@ impl<T: NumericStepperType> RenderOnce for NumericStepper<T> {
|
||||
let max = self.max_value;
|
||||
move |click: &ClickEvent, window: &mut Window, cx: &mut App| {
|
||||
let step = get_step(click.modifiers());
|
||||
let new_value = value + step;
|
||||
let new_value = value.saturating_add(step);
|
||||
let new_value = if new_value > max { max } else { new_value };
|
||||
on_change(&new_value, window, cx);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user