@@ -127,13 +127,8 @@ pub trait Diffable: Clone + PartialEq {
127127fn compute_widget_id ( layout_target : LayoutTarget , widget_path : & [ usize ] , widget : & Widget ) -> WidgetId {
128128 let mut hasher = DefaultHasher :: new ( ) ;
129129
130- // Hash the layout target
131130 ( layout_target as u8 ) . hash ( & mut hasher) ;
132-
133- // Hash the widget path
134131 widget_path. hash ( & mut hasher) ;
135-
136- // Hash the widget type discriminant
137132 std:: mem:: discriminant ( widget) . hash ( & mut hasher) ;
138133
139134 WidgetId ( hasher. finish ( ) )
@@ -509,7 +504,8 @@ impl Diffable for LayoutGroup {
509504 pinned : new_pinned,
510505 id : new_id,
511506 layout : new_layout,
512- } . into_diff_update ( ) ;
507+ }
508+ . into_diff_update ( ) ;
513509 let widget_path = widget_path. to_vec ( ) ;
514510 widget_diffs. push ( WidgetDiff { widget_path, new_value } ) ;
515511 }
@@ -613,37 +609,40 @@ impl Diffable for WidgetInstance {
613609 }
614610
615611 fn diff ( & mut self , new : Self , widget_path : & mut Vec < usize > , widget_diffs : & mut Vec < WidgetDiff > ) {
616- if let ( Widget :: PopoverButton ( button1) , Widget :: PopoverButton ( button2) ) = ( & mut self . widget , & new. widget )
617- && button1. disabled == button2. disabled
618- && button1. style == button2. style
619- && button1. menu_direction == button2. menu_direction
620- && button1. icon == button2. icon
621- && button1. tooltip_label == button2. tooltip_label
622- && button1. tooltip_description == button2. tooltip_description
623- && button1. tooltip_shortcut == button2. tooltip_shortcut
624- && button1. popover_min_width == button2. popover_min_width
625- {
626- for ( i, ( a, b) ) in button1. popover_layout . 0 . iter_mut ( ) . zip ( button2. popover_layout . 0 . iter ( ) ) . enumerate ( ) {
627- widget_path. push ( i) ;
628- a. diff ( b. clone ( ) , widget_path, widget_diffs) ;
629- widget_path. pop ( ) ;
630- }
612+ if self == & new {
613+ // Still need to update callbacks since PartialEq skips them
614+ self . widget = new. widget ;
631615 return ;
632616 }
633617
634- // If there have been changes to the actual widget (not just the id)
635- if self . widget != new. widget {
636- // We should update to the new widget value as well as a new widget id
637- * self = new. clone ( ) ;
638-
639- // Push a widget update to the diff
640- let new_value = new. into_diff_update ( ) ;
641- let widget_path = widget_path. to_vec ( ) ;
642- widget_diffs. push ( WidgetDiff { widget_path, new_value } ) ;
643- } else {
644- // Required to update the callback function, which the PartialEq check above skips
645- self . widget = new. widget ;
618+ // Special handling for PopoverButton: recursively diff nested layout if only the layout changed
619+ if let ( Widget :: PopoverButton ( button1) , Widget :: PopoverButton ( button2) ) = ( & mut self . widget , & new. widget ) {
620+ // Check if only the popover layout changed (all other fields are the same)
621+ if self . widget_id == new. widget_id
622+ && button1. disabled == button2. disabled
623+ && button1. style == button2. style
624+ && button1. menu_direction == button2. menu_direction
625+ && button1. icon == button2. icon
626+ && button1. tooltip_label == button2. tooltip_label
627+ && button1. tooltip_description == button2. tooltip_description
628+ && button1. tooltip_shortcut == button2. tooltip_shortcut
629+ && button1. popover_min_width == button2. popover_min_width
630+ {
631+ // Only the popover layout differs, diff it recursively
632+ for ( i, ( a, b) ) in button1. popover_layout . 0 . iter_mut ( ) . zip ( button2. popover_layout . 0 . iter ( ) ) . enumerate ( ) {
633+ widget_path. push ( i) ;
634+ a. diff ( b. clone ( ) , widget_path, widget_diffs) ;
635+ widget_path. pop ( ) ;
636+ }
637+ return ;
638+ }
646639 }
640+
641+ // Widget or ID changed, send full update
642+ * self = new. clone ( ) ;
643+ let new_value = new. into_diff_update ( ) ;
644+ let widget_path = widget_path. to_vec ( ) ;
645+ widget_diffs. push ( WidgetDiff { widget_path, new_value } ) ;
647646 }
648647
649648 fn collect_checkbox_ids ( & self , layout_target : LayoutTarget , widget_path : & mut Vec < usize > , checkbox_map : & mut HashMap < CheckboxId , CheckboxId > ) {
0 commit comments