Settings: controls give way, notices fold, and every edit needs its owner
A settings row's control slot shrinks to the box, so a control's text wraps and a palette's row folds; the font size's sample wraps in a plain block. A notice's boxes carry their channel's name and fold under the kind's name when narrow. canvas::panel::editing takes the owner's handler itself: the design panels, the structure editor, the index manager and the privacy, notice and startup settings take theirs at render and fail loud without one. Apply fails loud if pressed while the proxy does not read. Tests cover Apply resting on a bad port, the way back resting at the default size and a box pressed off. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
93de2a6bd6
commit
9a8dbcb92e
15 files changed
+172
-85
No files matched your search
@@ -127,7 +127,10 @@ impl AutoLayoutControls {
|
||||
|
||||
impl RenderOnce for AutoLayoutControls {
|
||||
fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let (id, layout, on_change) = (self.id, self.layout, &self.on_change);
|
||||
let on_change = self
|
||||
.on_change
|
||||
.unwrap_or_else(|| panic!("auto layout controls {:?} has no on_change", self.id));
|
||||
let (id, layout, on_change) = (self.id, self.layout, &on_change);
|
||||
let place = Rc::new(editing(
|
||||
"auto layout",
|
||||
&layout,
|
||||
|
||||
@@ -135,7 +135,10 @@ fn hairline(x: f32, y: f32, len: f32, across: bool, color: Hsla) -> gpui::Div {
|
||||
|
||||
impl RenderOnce for ConstraintsEditor {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let (id, now, on_change) = (self.id, self.constraints, &self.on_change);
|
||||
let on_change = self
|
||||
.on_change
|
||||
.unwrap_or_else(|| panic!("constraints editor {:?} has no on_change", self.id));
|
||||
let (id, now, on_change) = (self.id, self.constraints, &on_change);
|
||||
let theme = cx.theme();
|
||||
let (lit, rest) = (theme.colors.accent, theme.colors.border);
|
||||
let pin = |on: bool| if on { lit } else { rest };
|
||||
|
||||
@@ -138,7 +138,13 @@ impl ExportPanel {
|
||||
|
||||
impl RenderOnce for ExportPanel {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let (id, settings, on_change) = (self.id, self.settings, &self.on_change);
|
||||
let on_change = self
|
||||
.on_change
|
||||
.unwrap_or_else(|| panic!("export panel {:?} has no on_change", self.id));
|
||||
let on_export = self
|
||||
.on_export
|
||||
.unwrap_or_else(|| panic!("export panel {:?} has no on_export", self.id));
|
||||
let (id, settings, on_change) = (self.id, self.settings, &on_change);
|
||||
let files = export_files(&self.name, &settings);
|
||||
let next = added(&settings);
|
||||
let add = editing("export panel", &settings, on_change, move |all, _: ()| {
|
||||
@@ -204,7 +210,7 @@ impl RenderOnce for ExportPanel {
|
||||
)
|
||||
});
|
||||
let theme = cx.theme();
|
||||
let (exported, on_export) = (files.clone(), self.on_export);
|
||||
let (exported, on_export) = (files.clone(), on_export);
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
@@ -233,9 +239,7 @@ impl RenderOnce for ExportPanel {
|
||||
.disabled(exported.is_empty())
|
||||
.on_click(move |_, window, cx| {
|
||||
log::info!("export panel: {exported:?}");
|
||||
if let Some(on_export) = &on_export {
|
||||
on_export(exported.clone(), window, cx);
|
||||
}
|
||||
on_export(exported.clone(), window, cx);
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -45,6 +45,9 @@ impl InspectorPanel {
|
||||
|
||||
impl RenderOnce for InspectorPanel {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let on_change = self
|
||||
.on_change
|
||||
.unwrap_or_else(|| panic!("inspector panel {:?} has no on_change", self.id));
|
||||
let id = self.id;
|
||||
let [shape] = self.selection.as_slice() else {
|
||||
let title: SharedString = match self.selection.len() {
|
||||
@@ -55,7 +58,7 @@ impl RenderOnce for InspectorPanel {
|
||||
.body("Select one layer to see its properties.")
|
||||
.into_any_element();
|
||||
};
|
||||
let on_change = &self.on_change;
|
||||
let on_change = &on_change;
|
||||
let at = |edit: fn(&mut Shape, f64)| editing("inspector", shape, on_change, edit);
|
||||
let scrub = |name: &'static str, value: f32, least: f64| {
|
||||
ScrubInput::new((id.clone(), name), name, value as f64)
|
||||
|
||||
+2
-4
@@ -17,7 +17,7 @@ pub(crate) type OnEdit<V> = Rc<dyn Fn(V, &mut Window, &mut App)>;
|
||||
pub(crate) fn editing<V, T>(
|
||||
what: &'static str,
|
||||
value: &V,
|
||||
on_change: &Option<OnEdit<V>>,
|
||||
on_change: &OnEdit<V>,
|
||||
edit: impl Fn(&mut V, T) + 'static,
|
||||
) -> impl Fn(T, &mut Window, &mut App) + 'static
|
||||
where
|
||||
@@ -29,9 +29,7 @@ where
|
||||
let mut next = value.clone();
|
||||
edit(&mut next, input);
|
||||
log::info!("{what}: {next:?}");
|
||||
if let Some(on_change) = &on_change {
|
||||
on_change(next, window, cx);
|
||||
}
|
||||
on_change(next, window, cx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+14
-7
@@ -56,13 +56,14 @@ impl ColorPanel {
|
||||
|
||||
impl RenderOnce for ColorPanel {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let (picked, chosen) = (self.on_change.clone(), self.on_change);
|
||||
let report = |on_change: Option<OnEdit<Hsla>>| {
|
||||
let on_change = self
|
||||
.on_change
|
||||
.unwrap_or_else(|| panic!("color panel {:?} has no on_change", self.id));
|
||||
let (picked, chosen) = (on_change.clone(), on_change);
|
||||
let report = |on_change: OnEdit<Hsla>| {
|
||||
move |color: Hsla, window: &mut Window, cx: &mut App| {
|
||||
log::info!("color panel: {color:?}");
|
||||
if let Some(on_change) = &on_change {
|
||||
on_change(color, window, cx);
|
||||
}
|
||||
on_change(color, window, cx);
|
||||
}
|
||||
};
|
||||
div()
|
||||
@@ -120,6 +121,9 @@ impl ShadowEditor {
|
||||
|
||||
impl RenderOnce for ShadowEditor {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let on_change = self
|
||||
.on_change
|
||||
.unwrap_or_else(|| panic!("shadow editor {:?} has no on_change", self.id));
|
||||
let lift = cx
|
||||
.theme()
|
||||
.elevation(Elevation::Floating)
|
||||
@@ -132,7 +136,7 @@ impl RenderOnce for ShadowEditor {
|
||||
color: shadow.color,
|
||||
})
|
||||
.expect("a floating elevation casts a shadow");
|
||||
let (id, shadows, on_change) = (self.id, self.shadows, &self.on_change);
|
||||
let (id, shadows, on_change) = (self.id, self.shadows, &on_change);
|
||||
let add = editing("shadow editor", &shadows, on_change, move |all, _: ()| {
|
||||
all.push(lift)
|
||||
});
|
||||
@@ -265,7 +269,10 @@ const CORNERS: [&str; 4] = ["TL", "TR", "BR", "BL"];
|
||||
|
||||
impl RenderOnce for BorderEditor {
|
||||
fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let (id, border, on_change) = (self.id, self.border, &self.on_change);
|
||||
let on_change = self
|
||||
.on_change
|
||||
.unwrap_or_else(|| panic!("border editor {:?} has no on_change", self.id));
|
||||
let (id, border, on_change) = (self.id, self.border, &on_change);
|
||||
let parted = window.use_keyed_state((id.clone(), "split"), cx, |_, _| false);
|
||||
let uneven = border.radii.iter().any(|radius| *radius != border.radii[0]);
|
||||
let split = *parted.read(cx) || uneven;
|
||||
|
||||
@@ -73,7 +73,10 @@ impl TypographyPanel {
|
||||
|
||||
impl RenderOnce for TypographyPanel {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let (id, style, on_change) = (self.id, self.style, &self.on_change);
|
||||
let on_change = self
|
||||
.on_change
|
||||
.unwrap_or_else(|| panic!("typography panel {:?} has no on_change", self.id));
|
||||
let (id, style, on_change) = (self.id, self.style, &on_change);
|
||||
let theme = cx.theme();
|
||||
let family = editing(
|
||||
"typography panel",
|
||||
|
||||
Reference in new issue
Block a user