Panics · P35 Settings: handlers in new; gone sections and themes mark none, drifted font sizes peg
This commit is contained in:
1 parent
45cecebea5
commit
ad472490e0
18 files changed
+384
-427
No files matched your search
+12
-24
@@ -40,7 +40,7 @@ pub struct FeatureFlags {
|
||||
id: ElementId,
|
||||
flags: Vec<Flag>,
|
||||
search: Entity<TextInput>,
|
||||
on_toggle: Option<OnFlag>,
|
||||
on_toggle: OnFlag,
|
||||
}
|
||||
|
||||
impl FeatureFlags {
|
||||
@@ -49,22 +49,15 @@ impl FeatureFlags {
|
||||
id: impl Into<ElementId>,
|
||||
flags: impl IntoIterator<Item = Flag>,
|
||||
search: &Entity<TextInput>,
|
||||
on_toggle: impl Fn(&SharedString, bool, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
flags: flags.into_iter().collect(),
|
||||
search: search.clone(),
|
||||
on_toggle: None,
|
||||
on_toggle: Rc::new(on_toggle),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_toggle(
|
||||
mut self,
|
||||
handler: impl Fn(&SharedString, bool, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
self.on_toggle = Some(Rc::new(handler));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// The flags whose name or description holds every word of `query`.
|
||||
@@ -83,9 +76,7 @@ fn kept_flags<'a>(flags: &'a [Flag], query: &str) -> Vec<&'a Flag> {
|
||||
|
||||
impl RenderOnce for FeatureFlags {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let on_toggle = self
|
||||
.on_toggle
|
||||
.unwrap_or_else(|| panic!("feature flags {:?} has no on_toggle", self.id));
|
||||
let on_toggle = self.on_toggle;
|
||||
let query = self.search.read(cx).text().to_string();
|
||||
let theme = cx.theme();
|
||||
let rows = kept_flags(&self.flags, &query).into_iter().map(|flag| {
|
||||
@@ -134,29 +125,26 @@ type OnBool = Rc<dyn Fn(bool, &mut Window, &mut App)>;
|
||||
pub struct DeveloperModeToggle {
|
||||
id: ElementId,
|
||||
on: bool,
|
||||
on_change: Option<OnBool>,
|
||||
on_change: OnBool,
|
||||
}
|
||||
|
||||
impl DeveloperModeToggle {
|
||||
pub fn new(id: impl Into<ElementId>, on: bool) -> Self {
|
||||
pub fn new(
|
||||
id: impl Into<ElementId>,
|
||||
on: bool,
|
||||
on_change: impl Fn(bool, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
on,
|
||||
on_change: None,
|
||||
on_change: Rc::new(on_change),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_change(mut self, handler: impl Fn(bool, &mut Window, &mut App) + 'static) -> Self {
|
||||
self.on_change = Some(Rc::new(handler));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for DeveloperModeToggle {
|
||||
fn render(self, _: &mut Window, _: &mut App) -> impl IntoElement {
|
||||
let on_change = self
|
||||
.on_change
|
||||
.unwrap_or_else(|| panic!("developer mode toggle {:?} has no on_change", self.id));
|
||||
let on_change = self.on_change;
|
||||
let on_change = on_change;
|
||||
div()
|
||||
.flex()
|
||||
|
||||
+39
-54
@@ -45,32 +45,26 @@ type OnAppearance = Rc<dyn Fn(Appearance, &mut Window, &mut App)>;
|
||||
pub struct ThemeSelector {
|
||||
id: ElementId,
|
||||
appearance: Appearance,
|
||||
on_change: Option<OnAppearance>,
|
||||
on_change: OnAppearance,
|
||||
}
|
||||
|
||||
impl ThemeSelector {
|
||||
pub fn new(id: impl Into<ElementId>, appearance: Appearance) -> Self {
|
||||
pub fn new(
|
||||
id: impl Into<ElementId>,
|
||||
appearance: Appearance,
|
||||
on_change: impl Fn(Appearance, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
appearance,
|
||||
on_change: None,
|
||||
on_change: Rc::new(on_change),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_change(
|
||||
mut self,
|
||||
handler: impl Fn(Appearance, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
self.on_change = Some(Rc::new(handler));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for ThemeSelector {
|
||||
fn render(self, _: &mut Window, _: &mut App) -> impl IntoElement {
|
||||
let on_change = self
|
||||
.on_change
|
||||
.unwrap_or_else(|| panic!("theme selector {:?} has no on_change", self.id));
|
||||
let on_change = self.on_change;
|
||||
let (_, words, _) = Appearance::ALL
|
||||
.iter()
|
||||
.find(|(each, _, _)| *each == self.appearance)
|
||||
@@ -100,7 +94,7 @@ pub struct AccentColorPicker {
|
||||
id: ElementId,
|
||||
color: Hsla,
|
||||
presets: Vec<(SharedString, Hsla)>,
|
||||
on_change: Option<OnColor>,
|
||||
on_change: OnColor,
|
||||
}
|
||||
|
||||
impl AccentColorPicker {
|
||||
@@ -108,6 +102,7 @@ impl AccentColorPicker {
|
||||
id: impl Into<ElementId>,
|
||||
color: impl Into<Hsla>,
|
||||
presets: impl IntoIterator<Item = (impl Into<SharedString>, impl Into<Hsla>)>,
|
||||
on_change: impl Fn(Hsla, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
@@ -116,21 +111,14 @@ impl AccentColorPicker {
|
||||
.into_iter()
|
||||
.map(|(name, color)| (name.into(), color.into()))
|
||||
.collect(),
|
||||
on_change: None,
|
||||
on_change: Rc::new(on_change),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_change(mut self, handler: impl Fn(Hsla, &mut Window, &mut App) + 'static) -> Self {
|
||||
self.on_change = Some(Rc::new(handler));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for AccentColorPicker {
|
||||
fn render(self, _: &mut Window, _: &mut App) -> impl IntoElement {
|
||||
let on_change = self
|
||||
.on_change
|
||||
.unwrap_or_else(|| panic!("accent color picker {:?} has no on_change", self.id));
|
||||
let on_change = self.on_change;
|
||||
let (picked, custom) = (on_change.clone(), on_change);
|
||||
let report = |on_change: OnColor| {
|
||||
move |color: Hsla, window: &mut Window, cx: &mut App| {
|
||||
@@ -169,38 +157,38 @@ pub struct FontSizeControl {
|
||||
size: f32,
|
||||
default: f32,
|
||||
range: (f32, f32),
|
||||
on_change: Option<OnSize>,
|
||||
on_change: OnSize,
|
||||
}
|
||||
|
||||
impl FontSizeControl {
|
||||
/// `size` and `default` lie within `range`, in pixels.
|
||||
pub fn new(id: impl Into<ElementId>, size: f32, default: f32, range: (f32, f32)) -> Self {
|
||||
assert!(
|
||||
range.0 < range.1
|
||||
&& (range.0..=range.1).contains(&size)
|
||||
&& (range.0..=range.1).contains(&default),
|
||||
"font size {size} and default {default} outside {range:?}"
|
||||
);
|
||||
pub fn new(
|
||||
id: impl Into<ElementId>,
|
||||
size: f32,
|
||||
default: f32,
|
||||
range: (f32, f32),
|
||||
on_change: impl Fn(f32, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
assert!(range.0 < range.1, "font sizes {range:?} run backwards");
|
||||
let held = |what: &str, value: f32| {
|
||||
if !(range.0..=range.1).contains(&value) {
|
||||
log::error!("font size control: {what} {value} outside {range:?}; pegged");
|
||||
}
|
||||
value.clamp(range.0, range.1)
|
||||
};
|
||||
Self {
|
||||
id: id.into(),
|
||||
size,
|
||||
default,
|
||||
size: held("size", size),
|
||||
default: held("default", default),
|
||||
range,
|
||||
on_change: None,
|
||||
on_change: Rc::new(on_change),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_change(mut self, handler: impl Fn(f32, &mut Window, &mut App) + 'static) -> Self {
|
||||
self.on_change = Some(Rc::new(handler));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for FontSizeControl {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let on_change = self
|
||||
.on_change
|
||||
.unwrap_or_else(|| panic!("font size control {:?} has no on_change", self.id));
|
||||
let on_change = self.on_change;
|
||||
let theme = cx.theme();
|
||||
let (slid, reset, default) = (on_change.clone(), on_change, self.default);
|
||||
let (low, high) = self.range;
|
||||
@@ -258,7 +246,7 @@ type OnDensity = Rc<dyn Fn(Density, &mut Window, &mut App)>;
|
||||
pub struct DensitySelector {
|
||||
id: ElementId,
|
||||
density: Density,
|
||||
on_change: Option<OnDensity>,
|
||||
on_change: OnDensity,
|
||||
}
|
||||
|
||||
const DENSITIES: [(Density, &str); 3] = [
|
||||
@@ -268,25 +256,22 @@ const DENSITIES: [(Density, &str); 3] = [
|
||||
];
|
||||
|
||||
impl DensitySelector {
|
||||
pub fn new(id: impl Into<ElementId>, density: Density) -> Self {
|
||||
pub fn new(
|
||||
id: impl Into<ElementId>,
|
||||
density: Density,
|
||||
on_change: impl Fn(Density, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
density,
|
||||
on_change: None,
|
||||
on_change: Rc::new(on_change),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_change(mut self, handler: impl Fn(Density, &mut Window, &mut App) + 'static) -> Self {
|
||||
self.on_change = Some(Rc::new(handler));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for DensitySelector {
|
||||
fn render(self, _: &mut Window, _: &mut App) -> impl IntoElement {
|
||||
let on_change = self
|
||||
.on_change
|
||||
.unwrap_or_else(|| panic!("density selector {:?} has no on_change", self.id));
|
||||
let on_change = self.on_change;
|
||||
let (_, words) = DENSITIES
|
||||
.iter()
|
||||
.find(|(each, _)| *each == self.density)
|
||||
|
||||
+15
-18
@@ -58,33 +58,27 @@ type OnDraft = Rc<dyn Fn(&ThemeDraft, &mut Window, &mut App)>;
|
||||
pub struct ThemeEditor {
|
||||
id: ElementId,
|
||||
draft: ThemeDraft,
|
||||
on_change: Option<OnDraft>,
|
||||
on_change: OnDraft,
|
||||
}
|
||||
|
||||
impl ThemeEditor {
|
||||
pub fn new(id: impl Into<ElementId>, draft: ThemeDraft) -> Self {
|
||||
pub fn new(
|
||||
id: impl Into<ElementId>,
|
||||
draft: ThemeDraft,
|
||||
on_change: impl Fn(&ThemeDraft, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
draft,
|
||||
on_change: None,
|
||||
on_change: Rc::new(on_change),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_change(
|
||||
mut self,
|
||||
handler: impl Fn(&ThemeDraft, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
self.on_change = Some(Rc::new(handler));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for ThemeEditor {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let id = self.id;
|
||||
let on_change = self
|
||||
.on_change
|
||||
.unwrap_or_else(|| panic!("theme editor {id:?} has no on_change"));
|
||||
let on_change = self.on_change;
|
||||
let draft = Rc::new(self.draft);
|
||||
let edit = {
|
||||
let (draft, on_change) = (draft.clone(), on_change);
|
||||
@@ -104,11 +98,14 @@ impl RenderOnce for ThemeEditor {
|
||||
let look = SettingsSection::new("Look")
|
||||
.row(row(
|
||||
"Density",
|
||||
DensitySelector::new((id.clone(), "density"), draft.density)
|
||||
.on_change(move |next, window, cx| {
|
||||
DensitySelector::new(
|
||||
(id.clone(), "density"),
|
||||
draft.density,
|
||||
move |next, window, cx| {
|
||||
density(&|d: &mut ThemeDraft| d.density = next, window, cx)
|
||||
})
|
||||
.into_any_element(),
|
||||
},
|
||||
)
|
||||
.into_any_element(),
|
||||
))
|
||||
.row(row(
|
||||
"Corners",
|
||||
|
||||
@@ -46,32 +46,25 @@ pub(super) type OnTheme = Rc<dyn Fn(&VsCodeTheme, &mut Window, &mut App)>;
|
||||
#[derive(IntoElement)]
|
||||
pub struct ThemeImporter {
|
||||
id: ElementId,
|
||||
on_apply: Option<OnTheme>,
|
||||
on_apply: OnTheme,
|
||||
}
|
||||
|
||||
impl ThemeImporter {
|
||||
pub fn new(id: impl Into<ElementId>) -> Self {
|
||||
pub fn new(
|
||||
id: impl Into<ElementId>,
|
||||
on_apply: impl Fn(&VsCodeTheme, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
on_apply: None,
|
||||
on_apply: Rc::new(on_apply),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_apply(
|
||||
mut self,
|
||||
handler: impl Fn(&VsCodeTheme, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
self.on_apply = Some(Rc::new(handler));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for ThemeImporter {
|
||||
fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let id = self.id;
|
||||
let on_apply = self
|
||||
.on_apply
|
||||
.unwrap_or_else(|| panic!("theme importer {id:?} has no on_apply"));
|
||||
let on_apply = self.on_apply;
|
||||
let last = window.use_keyed_state((id.clone(), "read"), cx, |_, _| None::<Read>);
|
||||
let took = last.clone();
|
||||
let zone = DropZone::new((id.clone(), "zone"))
|
||||
|
||||
+8
-11
@@ -54,22 +54,21 @@ type OnProxy = Rc<dyn Fn(Proxy, &mut Window, &mut App)>;
|
||||
pub struct ProxySettings {
|
||||
id: ElementId,
|
||||
proxy: Proxy,
|
||||
on_apply: Option<OnProxy>,
|
||||
on_apply: OnProxy,
|
||||
}
|
||||
|
||||
impl ProxySettings {
|
||||
pub fn new(id: impl Into<ElementId>, proxy: Proxy) -> Self {
|
||||
pub fn new(
|
||||
id: impl Into<ElementId>,
|
||||
proxy: Proxy,
|
||||
on_apply: impl Fn(Proxy, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
proxy,
|
||||
on_apply: None,
|
||||
on_apply: Rc::new(on_apply),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_apply(mut self, handler: impl Fn(Proxy, &mut Window, &mut App) + 'static) -> Self {
|
||||
self.on_apply = Some(Rc::new(handler));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for ProxySettings {
|
||||
@@ -129,9 +128,7 @@ impl RenderOnce for ProxySettings {
|
||||
"manual" => manual(&text(&host), &text(&port), &text(&bypass)),
|
||||
other => panic!("proxy settings: no way named {other}"),
|
||||
};
|
||||
let on_apply = self
|
||||
.on_apply
|
||||
.unwrap_or_else(|| panic!("proxy settings {id:?} has no on_apply"));
|
||||
let on_apply = self.on_apply;
|
||||
let switched = fields.clone();
|
||||
div()
|
||||
.flex()
|
||||
|
||||
+20
-32
@@ -26,29 +26,26 @@ pub struct Privacy {
|
||||
pub struct PrivacySettings {
|
||||
id: ElementId,
|
||||
privacy: Privacy,
|
||||
on_change: Option<OnEdit<Privacy>>,
|
||||
on_change: OnEdit<Privacy>,
|
||||
}
|
||||
|
||||
impl PrivacySettings {
|
||||
pub fn new(id: impl Into<ElementId>, privacy: Privacy) -> Self {
|
||||
pub fn new(
|
||||
id: impl Into<ElementId>,
|
||||
privacy: Privacy,
|
||||
on_change: impl Fn(Privacy, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
privacy,
|
||||
on_change: None,
|
||||
on_change: Rc::new(on_change),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_change(mut self, handler: impl Fn(Privacy, &mut Window, &mut App) + 'static) -> Self {
|
||||
self.on_change = Some(Rc::new(handler));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for PrivacySettings {
|
||||
fn render(self, _: &mut Window, _: &mut App) -> impl IntoElement {
|
||||
let on_change = self
|
||||
.on_change
|
||||
.unwrap_or_else(|| panic!("privacy settings {:?} has no on_change", self.id));
|
||||
let on_change = self.on_change;
|
||||
let (id, privacy, on_change) = (self.id, self.privacy, &on_change);
|
||||
let row = |key: &'static str,
|
||||
title: &'static str,
|
||||
@@ -108,29 +105,26 @@ pub struct Notices {
|
||||
pub struct NotificationSettings {
|
||||
id: ElementId,
|
||||
notices: Notices,
|
||||
on_change: Option<OnEdit<Notices>>,
|
||||
on_change: OnEdit<Notices>,
|
||||
}
|
||||
|
||||
impl NotificationSettings {
|
||||
pub fn new(id: impl Into<ElementId>, notices: Notices) -> Self {
|
||||
pub fn new(
|
||||
id: impl Into<ElementId>,
|
||||
notices: Notices,
|
||||
on_change: impl Fn(Notices, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
notices,
|
||||
on_change: None,
|
||||
on_change: Rc::new(on_change),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_change(mut self, handler: impl Fn(Notices, &mut Window, &mut App) + 'static) -> Self {
|
||||
self.on_change = Some(Rc::new(handler));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for NotificationSettings {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let on_change = self
|
||||
.on_change
|
||||
.unwrap_or_else(|| panic!("notification settings {:?} has no on_change", self.id));
|
||||
let on_change = self.on_change;
|
||||
let (id, notices, on_change) = (self.id, self.notices, &on_change);
|
||||
let theme = cx.theme();
|
||||
let rows = notices.kinds.iter().map(|(kind, name)| {
|
||||
@@ -209,7 +203,7 @@ pub struct StartupSettings {
|
||||
id: ElementId,
|
||||
startup: Startup,
|
||||
pages: Vec<Choice>,
|
||||
on_change: Option<OnEdit<Startup>>,
|
||||
on_change: OnEdit<Startup>,
|
||||
}
|
||||
|
||||
impl StartupSettings {
|
||||
@@ -217,26 +211,20 @@ impl StartupSettings {
|
||||
id: impl Into<ElementId>,
|
||||
startup: Startup,
|
||||
pages: impl IntoIterator<Item = Choice>,
|
||||
on_change: impl Fn(Startup, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
startup,
|
||||
pages: pages.into_iter().collect(),
|
||||
on_change: None,
|
||||
on_change: Rc::new(on_change),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_change(mut self, handler: impl Fn(Startup, &mut Window, &mut App) + 'static) -> Self {
|
||||
self.on_change = Some(Rc::new(handler));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for StartupSettings {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let on_change = self
|
||||
.on_change
|
||||
.unwrap_or_else(|| panic!("startup settings {:?} has no on_change", self.id));
|
||||
let on_change = self.on_change;
|
||||
let (id, startup, on_change) = (self.id, self.startup, &on_change);
|
||||
let switch = |key: &'static str, on: bool, set: fn(&mut Startup, bool)| {
|
||||
Switch::new((id.clone(), key), on)
|
||||
|
||||
+4
-13
@@ -46,7 +46,7 @@ pub struct SettingsSearch {
|
||||
id: ElementId,
|
||||
entries: Vec<SettingEntry>,
|
||||
search: Entity<TextInput>,
|
||||
on_pick: Option<OnKey>,
|
||||
on_pick: OnKey,
|
||||
}
|
||||
|
||||
impl SettingsSearch {
|
||||
@@ -55,29 +55,20 @@ impl SettingsSearch {
|
||||
id: impl Into<ElementId>,
|
||||
entries: impl IntoIterator<Item = SettingEntry>,
|
||||
search: &Entity<TextInput>,
|
||||
on_pick: impl Fn(&SharedString, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
entries: entries.into_iter().collect(),
|
||||
search: search.clone(),
|
||||
on_pick: None,
|
||||
on_pick: Rc::new(on_pick),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_pick(
|
||||
mut self,
|
||||
handler: impl Fn(&SharedString, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
self.on_pick = Some(Rc::new(handler));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for SettingsSearch {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let on_pick = self
|
||||
.on_pick
|
||||
.unwrap_or_else(|| panic!("settings search {:?} has no on_pick", self.id));
|
||||
let on_pick = self.on_pick;
|
||||
let query = self.search.read(cx).text().trim().to_string();
|
||||
let theme = cx.theme();
|
||||
let found = if query.is_empty() {
|
||||
|
||||
+7
-17
@@ -20,7 +20,7 @@ pub struct SettingsLayout {
|
||||
sections: Vec<(SharedString, SharedString, IconName)>,
|
||||
selected: SharedString,
|
||||
page: Option<AnyElement>,
|
||||
on_select: Option<OnKey>,
|
||||
on_select: OnKey,
|
||||
}
|
||||
|
||||
impl SettingsLayout {
|
||||
@@ -29,22 +29,22 @@ impl SettingsLayout {
|
||||
id: impl Into<ElementId>,
|
||||
sections: impl IntoIterator<Item = (impl Into<SharedString>, impl Into<SharedString>, IconName)>,
|
||||
selected: impl Into<SharedString>,
|
||||
on_select: impl Fn(&SharedString, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
let sections: Vec<_> = sections
|
||||
.into_iter()
|
||||
.map(|(key, name, icon)| (key.into(), name.into(), icon))
|
||||
.collect();
|
||||
let selected = selected.into();
|
||||
assert!(
|
||||
sections.iter().any(|(key, _, _)| *key == selected),
|
||||
"settings layout: no section {selected}"
|
||||
);
|
||||
if !sections.iter().any(|(key, _, _)| *key == selected) {
|
||||
log::error!("settings layout: no section {selected}; none open");
|
||||
}
|
||||
Self {
|
||||
id: id.into(),
|
||||
sections,
|
||||
selected,
|
||||
page: None,
|
||||
on_select: None,
|
||||
on_select: Rc::new(on_select),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,21 +53,11 @@ impl SettingsLayout {
|
||||
self.page = Some(page.into_any_element());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn on_select(
|
||||
mut self,
|
||||
handler: impl Fn(&SharedString, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
self.on_select = Some(Rc::new(handler));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for SettingsLayout {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let on_select = self
|
||||
.on_select
|
||||
.unwrap_or_else(|| panic!("settings layout {:?} has no on_select", self.id));
|
||||
let on_select = self.on_select;
|
||||
let theme = cx.theme();
|
||||
let muted = theme.colors.fg_muted;
|
||||
let list = self.sections.iter().fold(
|
||||
|
||||
+31
-59
@@ -29,32 +29,26 @@ type OnKey = Rc<dyn Fn(&SharedString, &mut Window, &mut App)>;
|
||||
pub struct StorageSettings {
|
||||
id: ElementId,
|
||||
stores: Vec<Store>,
|
||||
on_clear: Option<OnKey>,
|
||||
on_clear: OnKey,
|
||||
}
|
||||
|
||||
impl StorageSettings {
|
||||
pub fn new(id: impl Into<ElementId>, stores: impl IntoIterator<Item = Store>) -> Self {
|
||||
pub fn new(
|
||||
id: impl Into<ElementId>,
|
||||
stores: impl IntoIterator<Item = Store>,
|
||||
on_clear: impl Fn(&SharedString, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
stores: stores.into_iter().collect(),
|
||||
on_clear: None,
|
||||
on_clear: Rc::new(on_clear),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_clear(
|
||||
mut self,
|
||||
handler: impl Fn(&SharedString, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
self.on_clear = Some(Rc::new(handler));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for StorageSettings {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let on_clear = self
|
||||
.on_clear
|
||||
.unwrap_or_else(|| panic!("storage settings {:?} has no on_clear", self.id));
|
||||
let on_clear = self.on_clear;
|
||||
let theme = cx.theme();
|
||||
let total: u64 = self.stores.iter().map(|store| store.bytes).sum();
|
||||
let bar = self.stores.iter().fold(
|
||||
@@ -134,42 +128,30 @@ type Run = Rc<dyn Fn(&mut Window, &mut App)>;
|
||||
pub struct ResetToDefault {
|
||||
id: ElementId,
|
||||
changed: Vec<Changed>,
|
||||
on_reset: Option<OnKey>,
|
||||
on_reset_all: Option<Run>,
|
||||
on_reset: OnKey,
|
||||
on_reset_all: Run,
|
||||
}
|
||||
|
||||
impl ResetToDefault {
|
||||
pub fn new(id: impl Into<ElementId>, changed: impl IntoIterator<Item = Changed>) -> Self {
|
||||
pub fn new(
|
||||
id: impl Into<ElementId>,
|
||||
changed: impl IntoIterator<Item = Changed>,
|
||||
on_reset: impl Fn(&SharedString, &mut Window, &mut App) + 'static,
|
||||
on_reset_all: impl Fn(&mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
changed: changed.into_iter().collect(),
|
||||
on_reset: None,
|
||||
on_reset_all: None,
|
||||
on_reset: Rc::new(on_reset),
|
||||
on_reset_all: Rc::new(on_reset_all),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_reset(
|
||||
mut self,
|
||||
handler: impl Fn(&SharedString, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
self.on_reset = Some(Rc::new(handler));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn on_reset_all(mut self, handler: impl Fn(&mut Window, &mut App) + 'static) -> Self {
|
||||
self.on_reset_all = Some(Rc::new(handler));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for ResetToDefault {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let on_reset = self
|
||||
.on_reset
|
||||
.unwrap_or_else(|| panic!("reset to default {:?} has no on_reset", self.id));
|
||||
let on_reset_all = self
|
||||
.on_reset_all
|
||||
.unwrap_or_else(|| panic!("reset to default {:?} has no on_reset_all", self.id));
|
||||
let on_reset = self.on_reset;
|
||||
let on_reset_all = self.on_reset_all;
|
||||
let theme = cx.theme();
|
||||
if self.changed.is_empty() {
|
||||
return div()
|
||||
@@ -249,38 +231,28 @@ type OnFile = Rc<dyn Fn(PathBuf, &mut Window, &mut App)>;
|
||||
#[derive(IntoElement)]
|
||||
pub struct ImportExportSettings {
|
||||
id: ElementId,
|
||||
on_export: Option<Run>,
|
||||
on_import: Option<OnFile>,
|
||||
on_export: Run,
|
||||
on_import: OnFile,
|
||||
}
|
||||
|
||||
impl ImportExportSettings {
|
||||
pub fn new(id: impl Into<ElementId>) -> Self {
|
||||
pub fn new(
|
||||
id: impl Into<ElementId>,
|
||||
on_export: impl Fn(&mut Window, &mut App) + 'static,
|
||||
on_import: impl Fn(PathBuf, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
on_export: None,
|
||||
on_import: None,
|
||||
on_export: Rc::new(on_export),
|
||||
on_import: Rc::new(on_import),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_export(mut self, handler: impl Fn(&mut Window, &mut App) + 'static) -> Self {
|
||||
self.on_export = Some(Rc::new(handler));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn on_import(mut self, handler: impl Fn(PathBuf, &mut Window, &mut App) + 'static) -> Self {
|
||||
self.on_import = Some(Rc::new(handler));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for ImportExportSettings {
|
||||
fn render(self, _: &mut Window, _: &mut App) -> impl IntoElement {
|
||||
let on_export = self
|
||||
.on_export
|
||||
.unwrap_or_else(|| panic!("import export settings {:?} has no on_export", self.id));
|
||||
let on_import = self
|
||||
.on_import
|
||||
.unwrap_or_else(|| panic!("import export settings {:?} has no on_import", self.id));
|
||||
let on_export = self.on_export;
|
||||
let on_import = self.on_import;
|
||||
let (on_export, on_import) = (on_export, on_import);
|
||||
div()
|
||||
.flex()
|
||||
|
||||
+7
-17
@@ -57,7 +57,7 @@ pub struct SyntaxThemePicker {
|
||||
id: ElementId,
|
||||
themes: Vec<SyntaxTheme>,
|
||||
selected: SharedString,
|
||||
on_change: Option<OnName>,
|
||||
on_change: OnName,
|
||||
}
|
||||
|
||||
impl SyntaxThemePicker {
|
||||
@@ -66,36 +66,26 @@ impl SyntaxThemePicker {
|
||||
id: impl Into<ElementId>,
|
||||
themes: impl IntoIterator<Item = SyntaxTheme>,
|
||||
selected: impl Into<SharedString>,
|
||||
on_change: impl Fn(&'static str, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
let themes: Vec<SyntaxTheme> = themes.into_iter().collect();
|
||||
let selected = selected.into();
|
||||
assert!(
|
||||
themes.iter().any(|theme| theme.name == selected.as_ref()),
|
||||
"syntax theme picker: no theme {selected}"
|
||||
);
|
||||
if !themes.iter().any(|theme| theme.name == selected.as_ref()) {
|
||||
log::error!("syntax theme picker: no theme {selected}; none chosen");
|
||||
}
|
||||
Self {
|
||||
id: id.into(),
|
||||
themes,
|
||||
selected,
|
||||
on_change: None,
|
||||
on_change: Rc::new(on_change),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_change(
|
||||
mut self,
|
||||
handler: impl Fn(&'static str, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
self.on_change = Some(Rc::new(handler));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for SyntaxThemePicker {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let id = self.id;
|
||||
let on_change = self
|
||||
.on_change
|
||||
.unwrap_or_else(|| panic!("syntax theme picker {id:?} has no on_change"));
|
||||
let on_change = self.on_change;
|
||||
let mode: Mode = cx.theme().mode();
|
||||
let cards = self.themes.iter().map(|theme| {
|
||||
let (pick, name) = (on_change.clone(), theme.name);
|
||||
|
||||
@@ -8,9 +8,13 @@ use crate::settings::{AccentColorPicker, FontSizeControl};
|
||||
|
||||
fn accent(_: &mut Window, _: &mut App, owner: Entity<Desk>) -> AnyElement {
|
||||
let (red, blue) = (hsla(0.0, 0.6, 0.5, 1.0), hsla(0.6, 0.6, 0.5, 1.0));
|
||||
AccentColorPicker::new("accent", red, [("Red", red), ("Blue", blue)])
|
||||
.on_change(move |color, _, cx| say(&owner, format!("blue {}", color == blue), cx))
|
||||
.into_any_element()
|
||||
AccentColorPicker::new(
|
||||
"accent",
|
||||
red,
|
||||
[("Red", red), ("Blue", blue)],
|
||||
move |color, _, cx| say(&owner, format!("blue {}", color == blue), cx),
|
||||
)
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
/// Stops: the presets, Red then Blue, then the custom well.
|
||||
@@ -23,9 +27,10 @@ fn a_preset_sets_the_accent(cx: &mut TestAppContext) {
|
||||
}
|
||||
|
||||
fn default_size(_: &mut Window, _: &mut App, owner: Entity<Desk>) -> AnyElement {
|
||||
FontSizeControl::new("size", 14.0, 14.0, (12.0, 24.0))
|
||||
.on_change(move |size, _, cx| say(&owner, format!("size {size}"), cx))
|
||||
.into_any_element()
|
||||
FontSizeControl::new("size", 14.0, 14.0, (12.0, 24.0), move |size, _, cx| {
|
||||
say(&owner, format!("size {size}"), cx)
|
||||
})
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
/// At the default size the way back rests, so the second stop wraps to the slider.
|
||||
@@ -43,7 +48,12 @@ fn many_presets(_: &mut Window, _: &mut App, _: Entity<Desk>) -> AnyElement {
|
||||
.collect();
|
||||
div()
|
||||
.w(px(280.0))
|
||||
.child(AccentColorPicker::new("accent", presets[0].1, presets).on_change(|_, _, _| {}))
|
||||
.child(AccentColorPicker::new(
|
||||
"accent",
|
||||
presets[0].1,
|
||||
presets,
|
||||
|_, _, _| {},
|
||||
))
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
@@ -61,3 +71,35 @@ fn many_presets_fold_inside_a_narrow_box(cx: &mut TestAppContext) {
|
||||
"its swatches fold to a second row: {picker:?}"
|
||||
);
|
||||
}
|
||||
|
||||
/// A size saved past the range, a section and a code palette no longer offered.
|
||||
fn drifted(_: &mut Window, _: &mut App, _: Entity<Desk>) -> AnyElement {
|
||||
let sections = [("a", "Appearance", crate::primitives::IconName::Palette)];
|
||||
div()
|
||||
.w(px(480.0))
|
||||
.child(FontSizeControl::new(
|
||||
"size",
|
||||
40.0,
|
||||
9.0,
|
||||
(12.0, 24.0),
|
||||
|_, _, _| {},
|
||||
))
|
||||
.child(crate::settings::SettingsLayout::new(
|
||||
"layout",
|
||||
sections,
|
||||
"gone",
|
||||
|_, _, _| {},
|
||||
))
|
||||
.child(crate::settings::SyntaxThemePicker::new(
|
||||
"syntax",
|
||||
crate::theme::syntax_themes(),
|
||||
"Gone",
|
||||
|_, _, _| {},
|
||||
))
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn settings_that_drifted_draw(cx: &mut TestAppContext) {
|
||||
let _ = desk(drifted, cx);
|
||||
}
|
||||
+60
-47
@@ -96,8 +96,8 @@ fn search(window: &mut Window, cx: &mut App, owner: Entity<Desk>) -> AnyElement
|
||||
entry("size", "Font size", &["zoom"]),
|
||||
],
|
||||
&field,
|
||||
move |key, _, cx| say(&owner, format!("go {key}"), cx),
|
||||
)
|
||||
.on_pick(move |key, _, cx| say(&owner, format!("go {key}"), cx))
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
@@ -121,10 +121,13 @@ fn reset(_: &mut Window, _: &mut App, owner: Entity<Desk>) -> AnyElement {
|
||||
default: "off".into(),
|
||||
};
|
||||
let (one, all) = (owner.clone(), owner);
|
||||
ResetToDefault::new("reset", [changed("a"), changed("b")])
|
||||
.on_reset(move |key, _, cx| say(&one, format!("reset {key}"), cx))
|
||||
.on_reset_all(move |_, cx| say(&all, "reset all".into(), cx))
|
||||
.into_any_element()
|
||||
ResetToDefault::new(
|
||||
"reset",
|
||||
[changed("a"), changed("b")],
|
||||
move |key, _, cx| say(&one, format!("reset {key}"), cx),
|
||||
move |_, cx| say(&all, "reset all".into(), cx),
|
||||
)
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
/// Stops: each row's way back, then Reset all, which asks twice.
|
||||
@@ -149,9 +152,13 @@ fn flags(window: &mut Window, cx: &mut App, owner: Entity<Desk>) -> AnyElement {
|
||||
stage: Stage::Beta,
|
||||
on,
|
||||
};
|
||||
FeatureFlags::new("flags", [flag("tabs", false), flag("sync", true)], &field)
|
||||
.on_toggle(move |key, on, _, cx| say(&owner, format!("{key} {on}"), cx))
|
||||
.into_any_element()
|
||||
FeatureFlags::new(
|
||||
"flags",
|
||||
[flag("tabs", false), flag("sync", true)],
|
||||
&field,
|
||||
move |key, on, _, cx| say(&owner, format!("{key} {on}"), cx),
|
||||
)
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
/// Stops: the search, then each flag's switch.
|
||||
@@ -170,11 +177,10 @@ fn notices(_: &mut Window, _: &mut App, owner: Entity<Desk>) -> AnyElement {
|
||||
on: vec![("mention".into(), "App".into())],
|
||||
quiet: false,
|
||||
};
|
||||
NotificationSettings::new("notices", notices)
|
||||
.on_change(move |notices, _, cx| {
|
||||
say(&owner, format!("{:?} {}", notices.on, notices.quiet), cx)
|
||||
})
|
||||
.into_any_element()
|
||||
NotificationSettings::new("notices", notices, move |notices, _, cx| {
|
||||
say(&owner, format!("{:?} {}", notices.on, notices.quiet), cx)
|
||||
})
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
/// Stops: Do not disturb, then a box per channel.
|
||||
@@ -211,8 +217,8 @@ fn storage(_: &mut Window, _: &mut App, owner: Entity<Desk>) -> AnyElement {
|
||||
clearable: false,
|
||||
},
|
||||
],
|
||||
move |key, _, cx| say(&owner, format!("clear {key}"), cx),
|
||||
)
|
||||
.on_clear(move |key, _, cx| say(&owner, format!("clear {key}"), cx))
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
@@ -227,9 +233,10 @@ fn a_store_clears_on_the_second_press(cx: &mut TestAppContext) {
|
||||
}
|
||||
|
||||
fn size(_: &mut Window, _: &mut App, owner: Entity<Desk>) -> AnyElement {
|
||||
FontSizeControl::new("size", 18.0, 14.0, (12.0, 24.0))
|
||||
.on_change(move |size, _, cx| say(&owner, format!("size {size}"), cx))
|
||||
.into_any_element()
|
||||
FontSizeControl::new("size", 18.0, 14.0, (12.0, 24.0), move |size, _, cx| {
|
||||
say(&owner, format!("size {size}"), cx)
|
||||
})
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
/// Stops: the slider, then the way back.
|
||||
@@ -242,9 +249,10 @@ fn the_way_back_gives_the_default_size(cx: &mut TestAppContext) {
|
||||
}
|
||||
|
||||
fn theme(_: &mut Window, _: &mut App, owner: Entity<Desk>) -> AnyElement {
|
||||
ThemeSelector::new("theme", Appearance::Light)
|
||||
.on_change(move |appearance, _, cx| say(&owner, format!("{appearance:?}"), cx))
|
||||
.into_any_element()
|
||||
ThemeSelector::new("theme", Appearance::Light, move |appearance, _, cx| {
|
||||
say(&owner, format!("{appearance:?}"), cx)
|
||||
})
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
/// Stops: a segment each.
|
||||
@@ -262,9 +270,10 @@ fn proxy(_: &mut Window, _: &mut App, owner: Entity<Desk>) -> AnyElement {
|
||||
port: 8080,
|
||||
bypass: vec!["localhost".into()],
|
||||
};
|
||||
ProxySettings::new("proxy", proxy)
|
||||
.on_apply(move |proxy, _, cx| say(&owner, format!("{proxy:?}"), cx))
|
||||
.into_any_element()
|
||||
ProxySettings::new("proxy", proxy, move |proxy, _, cx| {
|
||||
say(&owner, format!("{proxy:?}"), cx)
|
||||
})
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
/// Apply is the last stop, so a step back from nothing reaches it.
|
||||
@@ -291,8 +300,8 @@ fn layout(_: &mut Window, _: &mut App, owner: Entity<Desk>) -> AnyElement {
|
||||
("b", "Network", IconName::Globe),
|
||||
],
|
||||
"a",
|
||||
move |key, _, cx| say(&owner, format!("open {key}"), cx),
|
||||
)
|
||||
.on_select(move |key, _, cx| say(&owner, format!("open {key}"), cx))
|
||||
.page(div())
|
||||
.into_any_element()
|
||||
}
|
||||
@@ -313,9 +322,10 @@ fn privacy(_: &mut Window, _: &mut App, owner: Entity<Desk>) -> AnyElement {
|
||||
personalization: false,
|
||||
history: true,
|
||||
};
|
||||
PrivacySettings::new("privacy", privacy)
|
||||
.on_change(move |next, _, cx| say(&owner, format!("{next:?}"), cx))
|
||||
.into_any_element()
|
||||
PrivacySettings::new("privacy", privacy, move |next, _, cx| {
|
||||
say(&owner, format!("{next:?}"), cx)
|
||||
})
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
/// Stops: a switch per field, telemetry first.
|
||||
@@ -339,15 +349,14 @@ fn quiet(_: &mut Window, _: &mut App, owner: Entity<Desk>) -> AnyElement {
|
||||
on: vec![("replies".into(), "App".into())],
|
||||
quiet: false,
|
||||
};
|
||||
NotificationSettings::new("notices", notices)
|
||||
.on_change(move |next, _, cx| {
|
||||
say(
|
||||
&owner,
|
||||
format!("quiet {} on {}", next.quiet, next.on.len()),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.into_any_element()
|
||||
NotificationSettings::new("notices", notices, move |next, _, cx| {
|
||||
say(
|
||||
&owner,
|
||||
format!("quiet {} on {}", next.quiet, next.on.len()),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
/// Stops: Do not disturb, then a box per kind and channel.
|
||||
@@ -370,8 +379,8 @@ fn startup(_: &mut Window, _: &mut App, owner: Entity<Desk>) -> AnyElement {
|
||||
"startup",
|
||||
startup,
|
||||
[Choice::new("last", "Where I left off")],
|
||||
move |next, _, cx| say(&owner, format!("login {}", next.at_login), cx),
|
||||
)
|
||||
.on_change(move |next, _, cx| say(&owner, format!("login {}", next.at_login), cx))
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
@@ -385,9 +394,10 @@ fn open_at_login_turns_on(cx: &mut TestAppContext) {
|
||||
}
|
||||
|
||||
fn developer(_: &mut Window, _: &mut App, owner: Entity<Desk>) -> AnyElement {
|
||||
DeveloperModeToggle::new("developer", false)
|
||||
.on_change(move |on, _, cx| say(&owner, format!("developer {on}"), cx))
|
||||
.into_any_element()
|
||||
DeveloperModeToggle::new("developer", false, move |on, _, cx| {
|
||||
say(&owner, format!("developer {on}"), cx)
|
||||
})
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
/// Stops: the switch.
|
||||
@@ -400,10 +410,12 @@ fn developer_mode_turns_on(cx: &mut TestAppContext) {
|
||||
}
|
||||
|
||||
fn files(_: &mut Window, _: &mut App, owner: Entity<Desk>) -> AnyElement {
|
||||
ImportExportSettings::new("files")
|
||||
.on_export(move |_, cx| say(&owner, "export".into(), cx))
|
||||
.on_import(|_, _, _| {})
|
||||
.into_any_element()
|
||||
ImportExportSettings::new(
|
||||
"files",
|
||||
move |_, cx| say(&owner, "export".into(), cx),
|
||||
|_, _, _| {},
|
||||
)
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
/// Stops: Export first.
|
||||
@@ -421,9 +433,10 @@ fn bad_port(_: &mut Window, _: &mut App, owner: Entity<Desk>) -> AnyElement {
|
||||
port: 0,
|
||||
bypass: Vec::new(),
|
||||
};
|
||||
ProxySettings::new("proxy", proxy)
|
||||
.on_apply(move |proxy, _, cx| say(&owner, format!("{proxy:?}"), cx))
|
||||
.into_any_element()
|
||||
ProxySettings::new("proxy", proxy, move |proxy, _, cx| {
|
||||
say(&owner, format!("{proxy:?}"), cx)
|
||||
})
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
/// With port 0 Apply rests, so a step back from nothing lands on the field before it.
|
||||
|
||||
+28
-30
@@ -14,18 +14,17 @@ use crate::{
|
||||
};
|
||||
|
||||
fn editor(_: &mut Window, cx: &mut App, owner: Entity<Desk>) -> AnyElement {
|
||||
ThemeEditor::new("editor", ThemeDraft::of(cx.theme()))
|
||||
.on_change(move |draft, _, cx| {
|
||||
say(
|
||||
&owner,
|
||||
format!(
|
||||
"{:?} contrast {} still {}",
|
||||
draft.density, draft.high_contrast, draft.reduced_motion
|
||||
),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.into_any_element()
|
||||
ThemeEditor::new("editor", ThemeDraft::of(cx.theme()), move |draft, _, cx| {
|
||||
say(
|
||||
&owner,
|
||||
format!(
|
||||
"{:?} contrast {} still {}",
|
||||
draft.density, draft.high_contrast, draft.reduced_motion
|
||||
),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
/// Stops: the three densities, corners, text size, high contrast, reduced motion, then the colors. A switch hands on a draft with its own flag turned and the rest as it stood.
|
||||
@@ -47,12 +46,11 @@ fn a_switch_turns_its_own_flag(cx: &mut TestAppContext) {
|
||||
}
|
||||
|
||||
fn colors(_: &mut Window, cx: &mut App, owner: Entity<Desk>) -> AnyElement {
|
||||
ThemeEditor::new("editor", ThemeDraft::of(cx.theme()))
|
||||
.on_change(move |draft, _, cx| {
|
||||
let background = gpui::Rgba::from(draft.colors.bg);
|
||||
say(&owner, crate::forms::hex(background), cx)
|
||||
})
|
||||
.into_any_element()
|
||||
ThemeEditor::new("editor", ThemeDraft::of(cx.theme()), move |draft, _, cx| {
|
||||
let background = gpui::Rgba::from(draft.colors.bg);
|
||||
say(&owner, crate::forms::hex(background), cx)
|
||||
})
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
/// The first color is the eighth stop; Enter opens its picker, where the hex field follows the eyedropper, a stop on macOS alone, and takes a new background.
|
||||
@@ -71,15 +69,14 @@ fn a_color_well_sets_its_own_color(cx: &mut TestAppContext) {
|
||||
}
|
||||
|
||||
fn look(_: &mut Window, cx: &mut App, owner: Entity<Desk>) -> AnyElement {
|
||||
ThemeEditor::new("editor", ThemeDraft::of(cx.theme()))
|
||||
.on_change(move |draft, _, cx| {
|
||||
let words = format!(
|
||||
"{:?} corners {} text {}",
|
||||
draft.density, draft.radius_scale, draft.font_scale
|
||||
);
|
||||
say(&owner, words, cx)
|
||||
})
|
||||
.into_any_element()
|
||||
ThemeEditor::new("editor", ThemeDraft::of(cx.theme()), move |draft, _, cx| {
|
||||
let words = format!(
|
||||
"{:?} corners {} text {}",
|
||||
draft.density, draft.radius_scale, draft.font_scale
|
||||
);
|
||||
say(&owner, words, cx)
|
||||
})
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
/// Stops: Compact, Standard, Comfortable, corners, text size. Compact picks the density alone, and Right on each slider moves its own measure a step.
|
||||
@@ -157,9 +154,10 @@ fn the_thumb_covers_the_chosen_segment(cx: &mut TestAppContext) {
|
||||
}
|
||||
|
||||
fn syntax(_: &mut Window, _: &mut App, owner: Entity<Desk>) -> AnyElement {
|
||||
SyntaxThemePicker::new("syntax", syntax_themes(), "Ely")
|
||||
.on_change(move |name, _, cx| say(&owner, name.to_string(), cx))
|
||||
.into_any_element()
|
||||
SyntaxThemePicker::new("syntax", syntax_themes(), "Ely", move |name, _, cx| {
|
||||
say(&owner, name.to_string(), cx)
|
||||
})
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
/// Stops: a card for each code palette; Space on the third picks Paper.
|
||||
|
||||
Reference in new issue
Block a user