@@ -484,7 +484,7 @@ impl SettingsStore {
files
}
- fn get_content_for_file(&self, file: SettingsFile) -> Option<&SettingsContent> {
+ pub fn get_content_for_file(&self, file: SettingsFile) -> Option<&SettingsContent> {
match file {
SettingsFile::User => self
.user_settings
@@ -538,6 +538,25 @@ impl SettingsStore {
&self,
target_file: SettingsFile,
pick: fn(&SettingsContent) -> &Option<T>,
+ ) -> (SettingsFile, Option<&T>) {
+ self.get_value_from_file_inner(target_file, pick, true)
+ }
+
+ /// Same as `Self::get_value_from_file` except that it does not include the current file.
+ /// Therefore it returns the value that was potentially overloaded by the target file.
+ pub fn get_value_up_to_file<T>(
+ &self,
+ target_file: SettingsFile,
+ pick: fn(&SettingsContent) -> &Option<T>,
+ ) -> (SettingsFile, Option<&T>) {
+ self.get_value_from_file_inner(target_file, pick, false)
+ }
+
+ fn get_value_from_file_inner<T>(
+ &self,
+ target_file: SettingsFile,
+ pick: fn(&SettingsContent) -> &Option<T>,
+ include_target_file: bool,
) -> (SettingsFile, Option<&T>) {
// todo(settings_ui): Add a metadata field for overriding the "overrides" tag, for contextually different settings
// e.g. disable AI isn't overridden, or a vec that gets extended instead or some such
@@ -547,10 +566,15 @@ impl SettingsStore {
let mut found_file = false;
for file in all_files.into_iter() {
- if !found_file && file != target_file && file != SettingsFile::Default {
- continue;
+ if !found_file && file != SettingsFile::Default {
+ if file != target_file {
+ continue;
+ }
+ found_file = true;
+ if !include_target_file {
+ continue;
+ }
}
- found_file = true;
if let SettingsFile::Project((worktree_id, ref path)) = file
&& let SettingsFile::Project((target_worktree_id, ref target_path)) = target_file
@@ -104,8 +104,15 @@ impl<T: 'static> Copy for SettingField<T> {}
/// Helper for unimplemented settings, used in combination with `SettingField::unimplemented`
/// to keep the setting around in the UI with valid pick and pick_mut implementations, but don't actually try to render it.
/// TODO(settings_ui): In non-dev builds (`#[cfg(not(debug_assertions))]`) make this render as edit-in-json
+#[derive(Clone, Copy)]
struct UnimplementedSettingField;
+impl PartialEq for UnimplementedSettingField {
+ fn eq(&self, _other: &Self) -> bool {
+ true
+ }
+}
+
impl<T: 'static> SettingField<T> {
/// Helper for settings with types that are not yet implemented.
#[allow(unused)]
@@ -123,9 +130,15 @@ trait AnySettingField {
fn type_id(&self) -> TypeId;
// Returns the file this value was set in and true, or File::Default and false to indicate it was not found in any file (missing default)
fn file_set_in(&self, file: SettingsUiFile, cx: &App) -> (settings::SettingsFile, bool);
+ fn reset_to_default_fn(
+ &self,
+ current_file: &SettingsUiFile,
+ file_set_in: &settings::SettingsFile,
+ cx: &App,
+ ) -> Option<Box<dyn Fn(&mut App)>>;
}
-impl<T> AnySettingField for SettingField<T> {
+impl<T: PartialEq + Clone + Send + Sync + 'static> AnySettingField for SettingField<T> {
fn as_any(&self) -> &dyn Any {
self
}
@@ -144,6 +157,47 @@ impl<T> AnySettingField for SettingField<T> {
.get_value_from_file(file.to_settings(), self.pick);
return (file, value.is_some());
}
+
+ fn reset_to_default_fn(
+ &self,
+ current_file: &SettingsUiFile,
+ file_set_in: &settings::SettingsFile,
+ cx: &App,
+ ) -> Option<Box<dyn Fn(&mut App)>> {
+ if file_set_in == &settings::SettingsFile::Default {
+ return None;
+ }
+ let this = *self;
+ let store = SettingsStore::global(cx);
+ let default_value = (this.pick)(store.raw_default_settings());
+ let is_default = store
+ .get_content_for_file(file_set_in.clone())
+ .map_or(&None, this.pick)
+ == default_value;
+ if is_default {
+ return None;
+ }
+ let current_file = current_file.clone();
+
+ return Some(Box::new(move |cx| {
+ let store = SettingsStore::global(cx);
+ let default_value = (this.pick)(store.raw_default_settings());
+ let is_set_somewhere_other_than_default = store
+ .get_value_up_to_file(current_file.to_settings(), this.pick)
+ .0
+ != settings::SettingsFile::Default;
+ let value_to_set = if is_set_somewhere_other_than_default {
+ default_value.clone()
+ } else {
+ None
+ };
+ update_settings_file(current_file.clone(), cx, move |settings, _| {
+ *(this.pick_mut)(settings) = value_to_set;
+ })
+ // todo(settings_ui): Don't log err
+ .log_err();
+ }));
+ }
}
#[derive(Default, Clone)]
@@ -658,7 +712,7 @@ fn render_settings_item(
cx: &mut Context<'_, SettingsWindow>,
) -> Stateful<Div> {
let (found_in_file, _) = setting_item.field.file_set_in(file.clone(), cx);
- let file_set_in = SettingsUiFile::from_settings(found_in_file);
+ let file_set_in = SettingsUiFile::from_settings(found_in_file.clone());
h_flex()
.id(setting_item.title)
@@ -673,6 +727,24 @@ fn render_settings_item(
.w_full()
.gap_1()
.child(Label::new(SharedString::new_static(setting_item.title)))
+ .when_some(
+ setting_item
+ .field
+ .reset_to_default_fn(&file, &found_in_file, cx),
+ |this, reset_to_default| {
+ this.child(
+ IconButton::new("reset-to-default-btn", IconName::Undo)
+ .icon_color(Color::Muted)
+ .size(ButtonSize::Compact)
+ .on_click({
+ move |_, _, cx| {
+ reset_to_default(cx);
+ }
+ })
+ .tooltip(Tooltip::text("Reset to default")),
+ )
+ },
+ )
.when_some(
file_set_in.filter(|file_set_in| file_set_in != &file),
|this, file_set_in| {
@@ -279,7 +279,7 @@ impl Component for Icon {
)
}
- fn preview(_window: &mut Window, _cx: &mut App) -> Option<AnyElement> {
+ fn preview(_window: &mut Window, cx: &mut App) -> Option<AnyElement> {
Some(
v_flex()
.gap_6()
@@ -314,6 +314,30 @@ impl Component for Icon {
),
],
),
+ example_group_with_title(
+ "All Icons",
+ vec![single_example(
+ "All Icons",
+ h_flex()
+ .image_cache(gpui::retain_all("all icons"))
+ .flex_wrap()
+ .gap_2()
+ .children(<IconName as strum::IntoEnumIterator>::iter().map(
+ |icon_name| {
+ h_flex()
+ .gap_1()
+ .border_1()
+ .rounded_md()
+ .px_2()
+ .py_1()
+ .border_color(Color::Muted.color(cx))
+ .child(SharedString::new_static(icon_name.into()))
+ .child(Icon::new(icon_name).into_any_element())
+ },
+ ))
+ .into_any_element(),
+ )],
+ ),
])
.into_any_element(),
)