@@ -17,9 +17,9 @@ public class Scratch.FuzzySearchPopover : Gtk.Popover {
1717 private Gtk . SearchEntry search_term_entry;
1818 private Services . FuzzyFinder fuzzy_finder;
1919 private Gtk . ListBox search_result_container;
20+ private ListStore search_list_store;
2021 private int preselected_index;
2122 private Gtk . ScrolledWindow scrolled;
22- private Gee . ArrayList<FileItem > items;
2323 private Scratch . Services . FuzzySearchIndexer indexer;
2424 private int window_height;
2525 private int max_items;
@@ -49,12 +49,14 @@ public class Scratch.FuzzySearchPopover : Gtk.Popover {
4949 valign = START
5050 };
5151
52+ search_list_store = new ListStore (typeof (FileItem ));
5253 search_result_container = new Gtk .ListBox () {
5354 selection_mode = NONE ,
5455 activate_on_single_click = true ,
5556 can_focus = false
5657 };
5758 search_result_container. get_style_context (). add_class (" fuzzy-list" );
59+ search_result_container. bind_model (search_list_store, (obj) = > (FileItem )obj);
5860
5961 var entry_layout = new Gtk .Box (VERTICAL , 0 ) {
6062 valign = START
@@ -80,7 +82,6 @@ public class Scratch.FuzzySearchPopover : Gtk.Popover {
8082
8183 fuzzy_finder = new Services .FuzzyFinder (search_indexer. project_paths);
8284 indexer = search_indexer;
83- items = new Gee .ArrayList<FileItem > ();
8485 cancellables = new Gee .LinkedList<GLib . Cancellable > ();
8586
8687 search_result_container. row_activated. connect ((row) = > {
@@ -89,37 +90,37 @@ public class Scratch.FuzzySearchPopover : Gtk.Popover {
8990 return ;
9091 }
9192
92- handle_item_selection (items . index_of ( file_item) );
93+ handle_item_selection (file_item);
9394 });
9495
9596 search_term_entry_key_controller = new Gtk .EventControllerKey (search_term_entry);
9697 search_term_entry_key_controller. key_pressed. connect ((keyval, keycode, state) = > {
9798 // Handle key up/down to select other files found by fuzzy search
9899 switch (keyval) {
99100 case Gdk . Key . Down :
100- if (items . size > 0 ) {
101+ if (search_list_store . n_items > 0 ) {
101102 var old_index = preselected_index;
102- var item = items . get (preselected_index++ );
103- if (preselected_index >= items . size ) {
103+ var item = search_list_store . get_item (preselected_index++ );
104+ if (preselected_index >= search_list_store . n_items ) {
104105 preselected_index = 0 ;
105106 }
106107
107- var next_item = items . get (preselected_index);
108- preselect_new_item (item, next_item);
108+ var next_item = search_list_store . get_item (preselected_index);
109+ preselect_new_item (( FileItem ) item, ( FileItem ) next_item);
109110 calculate_scroll_offset (old_index, preselected_index);
110111 }
111112
112113 return true ;
113114 case Gdk . Key . Up :
114- if (items . size > 0 ) {
115+ if (search_list_store . n_items > 0 ) {
115116 var old_index = preselected_index;
116- var item = items . get (preselected_index-- );
117+ var item = search_list_store . get_item (preselected_index-- );
117118 if (preselected_index < 0 ) {
118- preselected_index = items . size - 1 ;
119+ preselected_index = ( int ) search_list_store . n_items - 1 ;
119120 }
120121
121- var next_item = items . get (preselected_index);
122- preselect_new_item (item, next_item);
122+ var next_item = search_list_store . get_item (preselected_index);
123+ preselect_new_item (( FileItem ) item, ( FileItem ) next_item);
123124 calculate_scroll_offset (old_index, preselected_index);
124125 }
125126 return true ;
@@ -135,8 +136,8 @@ public class Scratch.FuzzySearchPopover : Gtk.Popover {
135136 });
136137
137138 search_term_entry. activate. connect (() = > {
138- if (items . size > 0 ) {
139- handle_item_selection (preselected_index);
139+ if (search_list_store . n_items > 0 ) {
140+ handle_item_selection (( FileItem ) search_list_store . get_item ( preselected_index) );
140141 }
141142 });
142143
@@ -149,75 +150,68 @@ public class Scratch.FuzzySearchPopover : Gtk.Popover {
149150 }
150151
151152 Timeout . add (1 , () = > {
152- // If the entry is empty or the text has changed
153- // since searching, do nothing
154- if (previous_text. length == 0 || previous_text != search_term_entry. text) {
155- return Source . REMOVE ;
156- }
153+ // If the entry is empty or the text has changed
154+ // since searching, do nothing
155+ if (previous_text. length == 0 || previous_text != search_term_entry. text) {
156+ return Source . REMOVE ;
157+ }
157158
158- var next_cancellable = new GLib .Cancellable ();
159- cancellables. add (next_cancellable);
159+ var next_cancellable = new GLib .Cancellable ();
160+ cancellables. add (next_cancellable);
160161
161- var dir_length = 0 , term = search_term_entry. text;
162- var parts = term. split (Path . DIR_SEPARATOR_S , 0 );
163- var rev_parts = term. reverse (). split (Path . DIR_SEPARATOR_S , 2 );
164- if (rev_parts. length == 2 ) {
165- dir_length = rev_parts[0 ]. length + 1 ;
166- }
167-
168- fuzzy_finder. fuzzy_find_async. begin (term, dir_length,
169- current_doc_project,
170- next_cancellable,
171- (obj, res) = > {
172- if (next_cancellable. is_cancelled ()) {
173- cancellables. remove (next_cancellable);
174- return ;
175- }
162+ var dir_length = 0 , term = search_term_entry. text;
163+ var parts = term. split (Path . DIR_SEPARATOR_S , 0 );
164+ var rev_parts = term. reverse (). split (Path . DIR_SEPARATOR_S , 2 );
165+ if (rev_parts. length == 2 ) {
166+ dir_length = rev_parts[0 ]. length + 1 ;
167+ }
176168
177- var results = fuzzy_finder. fuzzy_find_async. end (res);
178- if (results == null ) {
179- return ;
180- }
169+ fuzzy_finder. fuzzy_find_async. begin (
170+ term,
171+ dir_length,
172+ current_doc_project,
173+ next_cancellable,
174+ (obj, res) = > {
175+ if (next_cancellable. is_cancelled ()) {
176+ cancellables. remove (next_cancellable);
177+ return ;
178+ }
181179
182- bool first = true ;
180+ var results = fuzzy_finder. fuzzy_find_async. end (res);
181+ if (results == null ) {
182+ return ;
183+ }
183184
185+ bool first = true ;
184186
187+ search_list_store. remove_all ();
185188
186- foreach (var c in search_result_container . get_children () ) {
187- search_result_container . remove (c );
188- }
189+ foreach (var result in results ) {
190+ var file_item = new FileItem (result, indexer . project_paths . size > 1 );
191+ file_item . can_focus = false ;
189192
190- items. clear ();
193+ if (first) {
194+ first = false ;
195+ file_item. get_style_context (). add_class (" preselect-fuzzy" );
196+ preselected_index = 0 ;
197+ }
191198
192- foreach (var result in results) {
193- var file_item = new FileItem (result, indexer. project_paths. size > 1 );
194- file_item. can_focus = false ;
195-
196- if (first) {
197- first = false ;
198- file_item. get_style_context (). add_class (" preselect-fuzzy" );
199- preselected_index = 0 ;
199+ search_list_store. insert_sorted (file_item, sort_func);
200200 }
201201
202- search_result_container. add (file_item);
203- items. add (file_item);
204- }
205-
206- scrolled. hide ();
207- scrolled. show_all ();
202+ scrolled. hide ();
203+ scrolled. show_all ();
208204
209- // Reset scrolling
210- scrolled. vadjustment. value = 0 ;
211- });
205+ // Reset scrolling
206+ scrolled. vadjustment. value = 0 ;
207+ }
208+ );
212209
213210 return Source . REMOVE ;
214211 });
215212 } else {
216- foreach (var c in search_result_container. get_children ()) {
217- search_result_container. remove (c);
218- }
213+ search_list_store. remove_all ();
219214
220- items. clear ();
221215 scrolled. hide ();
222216 }
223217 });
@@ -236,37 +230,38 @@ public class Scratch.FuzzySearchPopover : Gtk.Popover {
236230 scrolled. set_max_content_height (45 /* height */ * max_items);
237231
238232 current_doc_project = get_current_project (); // This will not change while popover is showing
239- search_result_container. set_sort_func ((a , b) = > {
240- var result_a = ((FileItem )a). result;
241- var result_b = ((FileItem )b). result;
242- var project_a_is_current = result_a. project == current_doc_project;
243- var project_b_is_current = result_b. project == current_doc_project;
244- if (project_a_is_current && ! project_b_is_current) {
245- return 1 ;
246- } else if (project_b_is_current && ! project_a_is_current) {
247- return - 1 ;
248- } else if (result_a. score > result_b. score) {
249- return - 1 ;
250- } else if (result_b. score > result_a. score) {
251- return 1 ;
252- } else {
253- return strcmp (((FileItem )a). result. full_path, ((FileItem )b). result. full_path);
254- }
255- });
256233 });
257234 }
258235
236+ private int sort_func (Object a , Object b ) {
237+ var result_a = ((FileItem )a). result;
238+ var result_b = ((FileItem )b). result;
239+ var project_a_is_current = result_a. project == current_doc_project;
240+ var project_b_is_current = result_b. project == current_doc_project;
241+ if (project_a_is_current && ! project_b_is_current) {
242+ return 1 ;
243+ } else if (project_b_is_current && ! project_a_is_current) {
244+ return - 1 ;
245+ } else if (result_a. score > result_b. score) {
246+ return - 1 ;
247+ } else if (result_b. score > result_a. score) {
248+ return 1 ;
249+ } else {
250+ return strcmp (((FileItem )a). result. full_path, ((FileItem )b). result. full_path);
251+ }
252+ }
253+
259254 private void calculate_scroll_offset (int old_position , int new_position ) {
260255 // Shortcut if jumping from first to last or the other way round
261256 if (new_position == 0 && old_position > new_position) {
262257 scrolled. vadjustment. value = 0 ;
263258 return ;
264- } else if (old_position == 0 && new_position == items . size - 1 ) {
259+ } else if (old_position == 0 && new_position == search_list_store . n_items - 1 ) {
265260 scrolled. vadjustment. value = scrolled. vadjustment. get_upper ();
266261 return ;
267262 }
268263
269- var size_box = scrolled. vadjustment. get_upper () / items . size ;
264+ var size_box = scrolled. vadjustment. get_upper () / search_list_store . n_items ;
270265 var current_top = scrolled. vadjustment. value ;
271266 var current_bottom = current_top + size_box * (max_items - 2 );
272267 if (old_position < new_position) {
@@ -284,8 +279,7 @@ public class Scratch.FuzzySearchPopover : Gtk.Popover {
284279 }
285280 }
286281
287- private void handle_item_selection (int index ) {
288- var item = items. get (index);
282+ private void handle_item_selection (FileItem item ) {
289283 open_file (item. filepath. strip ());
290284 }
291285
0 commit comments