Box the widget: Widget field of WidgetInstance (#3506)

Box the `pub widget: Box<Widget>` field of `WidgetInstance`
This commit is contained in:
Keavon Chambers
2025-12-22 04:18:33 -08:00
committed by GitHub
parent 20bbe6cdcc
commit 9d26c040e9
3 changed files with 25 additions and 23 deletions
+1 -1
View File
@@ -594,7 +594,7 @@ mod test {
if let FrontendMessage::UpdateDialogColumn1 { diff } = response { if let FrontendMessage::UpdateDialogColumn1 { diff } = response {
if let DiffUpdate::Layout(sub_layout) = &diff[0].new_value { if let DiffUpdate::Layout(sub_layout) = &diff[0].new_value {
if let LayoutGroup::Row { widgets } = &sub_layout.0[0] { if let LayoutGroup::Row { widgets } = &sub_layout.0[0] {
if let Widget::TextLabel(TextLabel { value, .. }) = &widgets[0].widget { if let Widget::TextLabel(TextLabel { value, .. }) = &*widgets[0].widget {
print_problem_to_terminal_on_failure(value); print_problem_to_terminal_on_failure(value);
} }
} }
@@ -71,7 +71,7 @@ impl LayoutMessageHandler {
return Some((widget, widget_path)); return Some((widget, widget_path));
} }
if let Widget::PopoverButton(popover) = &widget.widget { if let Widget::PopoverButton(popover) = &*widget.widget {
stack.extend( stack.extend(
popover popover
.popover_layout .popover_layout
@@ -97,7 +97,7 @@ impl LayoutMessageHandler {
return Some((cell, widget_path)); return Some((cell, widget_path));
} }
if let Widget::PopoverButton(popover) = &cell.widget { if let Widget::PopoverButton(popover) = &*cell.widget {
stack.extend( stack.extend(
popover popover
.popover_layout .popover_layout
@@ -126,7 +126,7 @@ impl LayoutMessageHandler {
return; return;
}; };
match &mut widget_instance.widget { match &mut *widget_instance.widget {
Widget::BreadcrumbTrailButtons(breadcrumb_trail_buttons) => { Widget::BreadcrumbTrailButtons(breadcrumb_trail_buttons) => {
let callback_message = match action { let callback_message = match action {
WidgetValueAction::Commit => (breadcrumb_trail_buttons.on_commit.callback)(&()), WidgetValueAction::Commit => (breadcrumb_trail_buttons.on_commit.callback)(&()),
@@ -229,13 +229,13 @@ impl<'a> Iterator for WidgetIter<'a> {
Some(first) Some(first)
}); });
if let Some(item) = widget { if let Some(instance) = widget {
if let WidgetInstance { widget: Widget::PopoverButton(p), .. } = item { if let Widget::PopoverButton(popover_button) = &*instance.widget {
self.stack.extend(p.popover_layout.0.iter()); self.stack.extend(popover_button.popover_layout.0.iter());
return self.next(); return self.next();
} }
return Some(item); return Some(instance);
} }
match self.stack.pop() { match self.stack.pop() {
@@ -279,13 +279,15 @@ impl<'a> Iterator for WidgetIterMut<'a> {
Some(first) Some(first)
}); });
if let Some(widget) = widget { if let Some(instance) = widget {
if let WidgetInstance { widget: Widget::PopoverButton(p), .. } = widget { // We have to check that we're not a popover and return first, then extract the popover with an unreachable else condition second, to satisfy the borrow checker.
self.stack.extend(p.popover_layout.0.iter_mut()); // After Rust's Polonius is stable, we can reverse that order of steps to avoid the redundancy and unreachable statement.
return self.next(); if !matches!(*instance.widget, Widget::PopoverButton(_)) {
return Some(instance);
} }
let Widget::PopoverButton(popover_button) = &mut *instance.widget else { unreachable!() };
return Some(widget); self.stack.extend(popover_button.popover_layout.0.iter_mut());
return self.next();
} }
match self.stack.pop() { match self.stack.pop() {
@@ -362,7 +364,7 @@ impl LayoutGroup {
}; };
let description = description.into(); let description = description.into();
for widget in &mut widgets { for widget in &mut widgets {
let val = match &mut widget.widget { let val = match &mut *widget.widget {
Widget::CheckboxInput(x) => &mut x.tooltip_description, Widget::CheckboxInput(x) => &mut x.tooltip_description,
Widget::ColorInput(x) => &mut x.tooltip_description, Widget::ColorInput(x) => &mut x.tooltip_description,
Widget::CurveInput(x) => &mut x.tooltip_description, Widget::CurveInput(x) => &mut x.tooltip_description,
@@ -552,7 +554,7 @@ impl Diffable for LayoutGroup {
pub struct WidgetInstance { pub struct WidgetInstance {
#[serde(rename = "widgetId")] #[serde(rename = "widgetId")]
pub widget_id: WidgetId, pub widget_id: WidgetId,
pub widget: Widget, pub widget: Box<Widget>,
} }
impl PartialEq for WidgetInstance { impl PartialEq for WidgetInstance {
@@ -566,7 +568,7 @@ impl WidgetInstance {
pub fn new(widget: Widget) -> Self { pub fn new(widget: Widget) -> Self {
Self { Self {
widget_id: WidgetId(generate_uuid()), widget_id: WidgetId(generate_uuid()),
widget, widget: Box::new(widget),
} }
} }
} }
@@ -584,7 +586,7 @@ impl Diffable for WidgetInstance {
} }
// Special handling for PopoverButton: recursively diff nested layout if only the layout changed // Special handling for PopoverButton: recursively diff nested layout if only the layout changed
if let (Widget::PopoverButton(button1), Widget::PopoverButton(button2)) = (&mut self.widget, &new.widget) { if let (Widget::PopoverButton(button1), Widget::PopoverButton(button2)) = (&mut *self.widget, &*new.widget) {
// Check if only the popover layout changed (all other fields are the same) // Check if only the popover layout changed (all other fields are the same)
if self.widget_id == new.widget_id if self.widget_id == new.widget_id
&& button1.disabled == button2.disabled && button1.disabled == button2.disabled
@@ -614,7 +616,7 @@ impl Diffable for WidgetInstance {
} }
fn collect_checkbox_ids(&self, layout_target: LayoutTarget, widget_path: &mut Vec<usize>, checkbox_map: &mut HashMap<CheckboxId, CheckboxId>) { fn collect_checkbox_ids(&self, layout_target: LayoutTarget, widget_path: &mut Vec<usize>, checkbox_map: &mut HashMap<CheckboxId, CheckboxId>) {
match &self.widget { match &*self.widget {
Widget::CheckboxInput(checkbox) => { Widget::CheckboxInput(checkbox) => {
// Compute stable ID based on position and insert mapping // Compute stable ID based on position and insert mapping
let checkbox_id = checkbox.for_label; let checkbox_id = checkbox.for_label;
@@ -644,7 +646,7 @@ impl Diffable for WidgetInstance {
self.widget_id = compute_widget_id(layout_target, widget_path, &self.widget); self.widget_id = compute_widget_id(layout_target, widget_path, &self.widget);
// 2. Replace CheckboxIds if present // 2. Replace CheckboxIds if present
match &mut self.widget { match &mut *self.widget {
Widget::CheckboxInput(checkbox) => { Widget::CheckboxInput(checkbox) => {
let old_id = checkbox.for_label; let old_id = checkbox.for_label;
if let Some(&new_id) = checkbox_map.get(&old_id) { if let Some(&new_id) = checkbox_map.get(&old_id) {
@@ -744,7 +746,7 @@ impl DiffUpdate {
// Go through each widget to convert `ActionShortcut::Action` to `ActionShortcut::Shortcut` and append the key combination to the widget tooltip // Go through each widget to convert `ActionShortcut::Action` to `ActionShortcut::Shortcut` and append the key combination to the widget tooltip
let convert_tooltip = |widget_instance: &mut WidgetInstance| { let convert_tooltip = |widget_instance: &mut WidgetInstance| {
// Handle all the widgets that have tooltips // Handle all the widgets that have tooltips
let tooltip_shortcut = match &mut widget_instance.widget { let tooltip_shortcut = match &mut *widget_instance.widget {
Widget::BreadcrumbTrailButtons(widget) => widget.tooltip_shortcut.as_mut(), Widget::BreadcrumbTrailButtons(widget) => widget.tooltip_shortcut.as_mut(),
Widget::CheckboxInput(widget) => widget.tooltip_shortcut.as_mut(), Widget::CheckboxInput(widget) => widget.tooltip_shortcut.as_mut(),
Widget::ColorInput(widget) => widget.tooltip_shortcut.as_mut(), Widget::ColorInput(widget) => widget.tooltip_shortcut.as_mut(),
@@ -775,7 +777,7 @@ impl DiffUpdate {
} }
// Handle RadioInput separately because its tooltips are children of the widget // Handle RadioInput separately because its tooltips are children of the widget
if let Widget::RadioInput(radio_input) = &mut widget_instance.widget { if let Widget::RadioInput(radio_input) = &mut *widget_instance.widget {
for radio_entry_data in &mut radio_input.entries { for radio_entry_data in &mut radio_input.entries {
// Convert `ActionShortcut::Action` to `ActionShortcut::Shortcut` // Convert `ActionShortcut::Action` to `ActionShortcut::Shortcut`
if let Some(tooltip_shortcut) = radio_entry_data.tooltip_shortcut.as_mut() { if let Some(tooltip_shortcut) = radio_entry_data.tooltip_shortcut.as_mut() {
@@ -827,7 +829,7 @@ impl DiffUpdate {
}; };
// Apply shortcut conversions to all widgets that have menu lists // Apply shortcut conversions to all widgets that have menu lists
let convert_menu_lists = |widget_instance: &mut WidgetInstance| match &mut widget_instance.widget { let convert_menu_lists = |widget_instance: &mut WidgetInstance| match &mut *widget_instance.widget {
Widget::DropdownInput(dropdown_input) => { Widget::DropdownInput(dropdown_input) => {
apply_action_shortcut_to_menu_lists(&mut dropdown_input.entries); apply_action_shortcut_to_menu_lists(&mut dropdown_input.entries);
dropdown_input.entries_hash = hash_menu_list_entry_sections(&dropdown_input.entries); dropdown_input.entries_hash = hash_menu_list_entry_sections(&dropdown_input.entries);