@@ -58,6 +58,31 @@ pub(crate) struct StructurePickerState {
5858 pub ( crate ) visible : bool ,
5959}
6060
61+ #[ derive( Resource , Default ) ]
62+ pub ( crate ) struct StructurePickerSelectionState {
63+ pending : Option < ( Entity , String ) > ,
64+ suppress_click_frames : u8 ,
65+ }
66+
67+ impl StructurePickerSelectionState {
68+ fn consume_suppression ( & mut self ) -> bool {
69+ if self . suppress_click_frames > 0 {
70+ self . suppress_click_frames = self . suppress_click_frames . saturating_sub ( 1 ) ;
71+ true
72+ } else {
73+ false
74+ }
75+ }
76+
77+ fn suppress_for_touch_drag ( & mut self ) {
78+ self . suppress_click_frames = self . suppress_click_frames . max ( 2 ) ;
79+ }
80+
81+ fn is_suppressed ( & self ) -> bool {
82+ self . suppress_click_frames > 0
83+ }
84+ }
85+
6186#[ derive( Resource ) ]
6287pub ( crate ) struct StructurePickerCaretState {
6388 timer : Timer ,
@@ -640,22 +665,30 @@ pub(crate) fn update_structure_picker_scroll_indicator(
640665 * visibility = Visibility :: Inherited ;
641666}
642667
668+ #[ allow( clippy:: too_many_arguments) ]
643669pub ( crate ) fn structure_picker_scroll (
644670 mut mouse_wheel_events : EventReader < MouseWheel > ,
645671 hover_map : Res < HoverMap > ,
646672 scroll_nodes : Query < Entity , With < StructurePickerResultsScroll > > ,
673+ panel_nodes : Query < Entity , With < StructurePickerPanel > > ,
647674 mut scroll_positions : Query < & mut ScrollPosition > ,
648675 parents : Query < & ChildOf > ,
649676 touch_gesture_state : Res < TouchGestureState > ,
650677 keyboard_input : Res < ButtonInput < KeyCode > > ,
678+ mut picker_selection_state : ResMut < StructurePickerSelectionState > ,
651679) {
652- let picker_hovered = scroll_nodes. iter ( ) . any ( |scroll_root| {
653- hover_map. iter ( ) . any ( |( _, pointer_map) | {
654- pointer_map
655- . iter ( )
656- . any ( |( hovered, _) | is_descendant_or_self ( * hovered, scroll_root, & parents) )
657- } )
658- } ) ;
680+ let _ = picker_selection_state. consume_suppression ( ) ;
681+
682+ let picker_hovered = panel_nodes
683+ . iter ( )
684+ . chain ( scroll_nodes. iter ( ) )
685+ . any ( |picker_root| {
686+ hover_map. iter ( ) . any ( |( _, pointer_map) | {
687+ pointer_map
688+ . iter ( )
689+ . any ( |( hovered, _) | is_descendant_or_self ( * hovered, picker_root, & parents) )
690+ } )
691+ } ) ;
659692
660693 for mouse_wheel in mouse_wheel_events. read ( ) {
661694 let ( mut dx, mut dy) = match mouse_wheel. unit {
@@ -692,7 +725,10 @@ pub(crate) fn structure_picker_scroll(
692725 }
693726 }
694727
695- if picker_hovered && touch_gesture_state. rotate . length_squared ( ) > 0.0004 {
728+ let rotate_drag = touch_gesture_state. rotate . length_squared ( ) > 0.0004 ;
729+ if picker_hovered && rotate_drag {
730+ picker_selection_state. suppress_for_touch_drag ( ) ;
731+ picker_selection_state. pending = None ;
696732 for scroll_root in scroll_nodes. iter ( ) {
697733 if let Ok ( mut scroll_position) = scroll_positions. get_mut ( scroll_root) {
698734 scroll_position. offset_x -= touch_gesture_state. rotate . x ;
@@ -719,6 +755,7 @@ fn is_descendant_or_self(mut entity: Entity, ancestor: Entity, parents: &Query<&
719755pub ( crate ) fn structure_picker_result_buttons (
720756 mut interaction_query : Query <
721757 (
758+ Entity ,
722759 & Interaction ,
723760 & StructurePickerResultButton ,
724761 & mut BackgroundColor ,
@@ -729,27 +766,53 @@ pub(crate) fn structure_picker_result_buttons(
729766 mut file_drag_drop : ResMut < crate :: io:: FileDragDrop > ,
730767 catalog_channel : Option < Res < CatalogLoadChannel > > ,
731768 theme : Res < UiTheme > ,
769+ mut picker_selection_state : ResMut < StructurePickerSelectionState > ,
732770) {
733- for ( interaction, selected, mut background) in & mut interaction_query {
771+ let mut selected_path = None ;
772+
773+ for ( entity, interaction, selected, mut background) in & mut interaction_query {
734774 match * interaction {
735775 Interaction :: Pressed => {
736776 * background = BackgroundColor ( themed_button_bg ( theme. mode , Interaction :: Pressed ) ) ;
737- super :: load_structure_from_catalog_path (
738- & selected. path ,
739- & mut file_drag_drop,
740- catalog_channel. as_deref ( ) ,
741- ) ;
742- picker. visible = false ;
743- set_structure_picker_keyboard_active ( false ) ;
777+ if !picker_selection_state. is_suppressed ( ) {
778+ picker_selection_state. pending = Some ( ( entity, selected. path . clone ( ) ) ) ;
779+ }
744780 }
745781 Interaction :: Hovered => {
746782 * background = BackgroundColor ( themed_button_bg ( theme. mode , Interaction :: Hovered ) ) ;
783+
784+ if let Some ( ( pending_entity, pending_path) ) = picker_selection_state. pending . take ( )
785+ {
786+ if pending_entity == entity {
787+ if !picker_selection_state. is_suppressed ( ) {
788+ selected_path = Some ( pending_path) ;
789+ }
790+ } else {
791+ picker_selection_state. pending = Some ( ( pending_entity, pending_path) ) ;
792+ }
793+ }
747794 }
748795 Interaction :: None => {
749796 * background = BackgroundColor ( themed_button_bg ( theme. mode , Interaction :: None ) ) ;
797+
798+ if let Some ( ( pending_entity, _) ) = picker_selection_state. pending . as_ref ( ) {
799+ if * pending_entity == entity {
800+ picker_selection_state. pending = None ;
801+ }
802+ }
750803 }
751804 }
752805 }
806+
807+ if let Some ( path) = selected_path {
808+ super :: load_structure_from_catalog_path (
809+ & path,
810+ & mut file_drag_drop,
811+ catalog_channel. as_deref ( ) ,
812+ ) ;
813+ picker. visible = false ;
814+ set_structure_picker_keyboard_active ( false ) ;
815+ }
753816}
754817
755818fn structure_matches_query ( path : & str , query : & str ) -> bool {
0 commit comments