corundum_framework_gui/settings/
scope.rs1use super::layout::marked;
4
5#[derive(Clone, PartialEq, Eq, Debug)]
8pub struct ScopeTab<S> {
9 pub scope: S,
11 pub label: String,
13 pub enabled: bool,
15 pub dirty: bool,
17}
18
19impl<S> ScopeTab<S> {
20 pub fn new(scope: S, label: impl Into<String>) -> ScopeTab<S> {
22 ScopeTab {
23 scope,
24 label: label.into(),
25 enabled: true,
26 dirty: false,
27 }
28 }
29
30 pub fn enabled(mut self, enabled: bool) -> ScopeTab<S> {
32 self.enabled = enabled;
33 self
34 }
35
36 pub fn dirty(mut self, dirty: bool) -> ScopeTab<S> {
38 self.dirty = dirty;
39 self
40 }
41}
42
43pub fn scope_tabs<S: Copy + PartialEq>(
48 ui: &mut egui::Ui,
49 open: &mut S,
50 tabs: &[ScopeTab<S>],
51 hint: Option<&str>,
52) -> bool {
53 let before = *open;
54 if !tabs.iter().any(|t| t.enabled && t.scope == *open)
55 && let Some(first) = tabs.iter().find(|t| t.enabled)
56 {
57 *open = first.scope;
58 }
59 ui.horizontal_wrapped(|ui| {
60 for tab in tabs {
61 if ui
62 .add_enabled(
63 tab.enabled,
64 egui::Button::selectable(*open == tab.scope, marked(&tab.label, tab.dirty)),
65 )
66 .clicked()
67 {
68 *open = tab.scope;
69 }
70 }
71 if let Some(hint) = hint {
72 ui.small(hint);
73 }
74 });
75 *open != before
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81 use crate::test_support::render;
82
83 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
84 enum Scope {
85 Device,
86 Workgroup,
87 Workspace,
88 }
89
90 fn tabs(workspace: bool) -> Vec<ScopeTab<Scope>> {
91 vec![
92 ScopeTab::new(Scope::Device, "Device").dirty(true),
93 ScopeTab::new(Scope::Workgroup, "Workgroup"),
94 ScopeTab::new(Scope::Workspace, "Workspace").enabled(workspace),
95 ]
96 }
97
98 #[test]
99 fn an_enabled_open_tab_stays() {
100 let mut open = Scope::Workgroup;
101 let mut changed = false;
102 render([600.0, 400.0], |ui| {
103 changed |= scope_tabs(ui, &mut open, &tabs(true), None)
104 });
105 assert_eq!(open, Scope::Workgroup);
106 assert!(!changed);
107 }
108
109 #[test]
110 fn a_disabled_open_tab_yields_to_the_first_enabled() {
111 let mut open = Scope::Workspace;
112 let mut changed = false;
113 render([600.0, 400.0], |ui| {
114 changed |= scope_tabs(ui, &mut open, &tabs(false), Some("No workspace"))
115 });
116 assert_eq!(open, Scope::Device);
117 assert!(changed);
118 }
119
120 #[test]
121 fn with_no_tab_enabled_the_open_one_stays() {
122 let mut open = Scope::Workspace;
123 let none: Vec<_> = tabs(false).into_iter().map(|t| t.enabled(false)).collect();
124 render([600.0, 400.0], |ui| {
125 scope_tabs(ui, &mut open, &none, None);
126 });
127 assert_eq!(open, Scope::Workspace);
128 }
129}