Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 2 additions & 38 deletions data/Application.css
Original file line number Diff line number Diff line change
Expand Up @@ -20,54 +20,18 @@ textview.scrubber {
border: 0;
}

.fuzzy-popover {
padding-top: 0.5rem;
padding-bottom: 1rem;
}

.fuzzy-popover entry {
margin-left: 1rem;
margin-right: 1rem;
}

.fuzzy-popover scrolledwindow {
margin-top: 1rem;
}

.fuzzy-list {
background-color: transparent;
margin-bottom: 1rem;
}

.fuzzy-item {
padding: 0.5rem;
margin-left: 10px;
margin-right: 10px;
background-color: transparent;
}

.fuzzy-item.preselect-fuzzy,
.fuzzy-item:hover {
border-radius: 0.5rem;
}

.fuzzy-item:hover {
background-color: @theme_unfocused_selected_bg_color;
}

.fuzzy-item.preselect-fuzzy {
background-color: @selected_bg_color;
}

.fuzzy-item .fuzzy-file-icon {
margin-right: 0.5rem;
}

.fuzzy-item label:nth-child(1) {
font-weight: 700;
}

.fuzzy-item.preselect-fuzzy label {
opacity: 0.7;
background-color: @theme_unfocused_selected_bg_color;
}

.symbol-outline > box.horizontal {
Expand Down
43 changes: 22 additions & 21 deletions plugins/fuzzy-search/file-item.vala
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,31 @@
*/

public class FileItem : Gtk.ListBoxRow {
public SearchResult result { get; private set; }
public SearchResult result { get; construct; }

public string filepath {
get {
return result.full_path;
}
}

public FileItem (SearchResult res, bool should_distinguish_project = false) {
this.get_style_context ().add_class ("fuzzy-item");
this.get_style_context ().add_class ("flat");
public FileItem (SearchResult result, bool should_distinguish_project = false) {
Object (result: result);

result = res;
Icon icon;
var path_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 1);
path_box.valign = Gtk.Align.CENTER;
var filename_label = new Gtk.Label (Path.get_basename (result.relative_path)) {
halign = START
};

var path_label = new Gtk.Label (
@"$(should_distinguish_project ? result.project + " " : "")$(result.relative_path)"
);

path_label.halign = Gtk.Align.START;

var filename_label = new Gtk.Label (Path.get_basename (result.relative_path));
filename_label.halign = Gtk.Align.START;
@"$(should_distinguish_project ? result.project + " " : "")$(result.relative_path)"
) {
ellipsize = MIDDLE,
halign = START
};
path_label.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL);
path_label.get_style_context ().add_class (Granite.STYLE_CLASS_SMALL_LABEL);

Icon icon;
try {
var fi = File.new_for_path (result.full_path);
var info = fi.query_info ("standard::*", 0);
Expand All @@ -42,18 +41,20 @@ public class FileItem : Gtk.ListBoxRow {
}

var image = new Gtk.Image.from_gicon (icon, Gtk.IconSize.DND);
image.get_style_context ().add_class ("fuzzy-file-icon");

var path_box = new Gtk.Box (VERTICAL, 0) {
valign = CENTER
};
path_box.add (filename_label);
path_box.add (path_label);

var container_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 1) {
valign = Gtk.Align.CENTER
};

var container_box = new Gtk.Box (HORIZONTAL, 12);
container_box.add (image);
container_box.add (path_box);

this.child = container_box;
get_style_context ().add_class ("fuzzy-item");
child = container_box;

show_all ();
}
}
125 changes: 38 additions & 87 deletions plugins/fuzzy-search/fuzzy-search-popover.vala
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,15 @@ public class Scratch.FuzzySearchPopover : Gtk.Popover {
public Scratch.Services.FuzzySearchIndexer search_indexer { get; construct; }
public bool sidebar_is_visible { get; set; }

private Gtk.SearchEntry search_term_entry;
private Services.FuzzyFinder fuzzy_finder;
private Gee.LinkedList<GLib.Cancellable> cancellables;
private Gtk.EventControllerKey search_term_entry_key_controller;
private Gtk.ListBox search_result_container;
private ListStore search_list_store;
private Gtk.SearchEntry search_term_entry;
private int max_items;
private int preselected_index;
private Gtk.ScrolledWindow scrolled;
private ListStore search_list_store;
private Scratch.Services.FuzzySearchIndexer indexer;
private int window_height;
private int max_items;
private Gee.LinkedList<GLib.Cancellable> cancellables;
private Gtk.EventControllerKey search_term_entry_key_controller;
private Gtk.Label title_label;
private Services.FuzzyFinder fuzzy_finder;
private string current_doc_project;

public FuzzySearchPopover (Scratch.Services.FuzzySearchIndexer search_indexer, Scratch.MainWindow window) {
Expand All @@ -42,43 +39,44 @@ public class Scratch.FuzzySearchPopover : Gtk.Popover {
pointing_to = { 0, 32, 1, 1 };
get_style_context ().add_class ("fuzzy-popover");

title_label = new Granite.HeaderLabel (_("Find project files"));

search_term_entry = new Gtk.SearchEntry () {
placeholder_text = _("Find project files"),
hexpand = true,
valign = START
};

search_list_store = new ListStore (typeof (FileItem));
search_result_container = new Gtk.ListBox () {
selection_mode = NONE,
activate_on_single_click = true,
can_focus = false
var title_label = new Granite.HeaderLabel (_("Find project files")) {
mnemonic_widget = search_term_entry
};
search_result_container.get_style_context ().add_class ("fuzzy-list");
search_result_container.bind_model (search_list_store, (obj) => (FileItem)obj);

var entry_layout = new Gtk.Box (VERTICAL, 0) {
valign = START
};
entry_layout.add (title_label);
entry_layout.add (search_term_entry);

scrolled = new Gtk.ScrolledWindow (null, null) {
propagate_natural_height = true,
search_list_store = new ListStore (typeof (FileItem));

search_result_container = new Gtk.ListBox () {
hexpand = true,
vexpand = true,
child = search_result_container
selection_mode = BROWSE,
activate_on_single_click = true
};
search_result_container.bind_model (search_list_store, (obj) => (FileItem)obj);

var scrolled = new Gtk.ScrolledWindow (null, null) {
propagate_natural_height = true,
child = search_result_container,
hscrollbar_policy = NEVER
};

var box = new Gtk.Box (VERTICAL, 0);
box.add (entry_layout);
box.add (scrolled);
box.show_all ();

scrolled.hide ();

add (box);
child = box;

fuzzy_finder = new Services.FuzzyFinder (search_indexer.project_paths);
indexer = search_indexer;
Expand All @@ -95,44 +93,16 @@ public class Scratch.FuzzySearchPopover : Gtk.Popover {

search_term_entry_key_controller = new Gtk.EventControllerKey (search_term_entry);
search_term_entry_key_controller.key_pressed.connect ((keyval, keycode, state) => {
// Handle key up/down to select other files found by fuzzy search
switch (keyval) {
case Gdk.Key.Down:
if (search_list_store.n_items > 0) {
var old_index = preselected_index;
var item = search_list_store.get_item (preselected_index++);
if (preselected_index >= search_list_store.n_items) {
preselected_index = 0;
}

var next_item = search_list_store.get_item (preselected_index);
preselect_new_item ((FileItem) item, (FileItem) next_item);
calculate_scroll_offset (old_index, preselected_index);
}

return true;
case Gdk.Key.Up:
if (search_list_store.n_items > 0) {
var old_index = preselected_index;
var item = search_list_store.get_item (preselected_index--);
if (preselected_index < 0) {
preselected_index = (int) search_list_store.n_items - 1;
}

var next_item = search_list_store.get_item (preselected_index);
preselect_new_item ((FileItem) item, (FileItem) next_item);
calculate_scroll_offset (old_index, preselected_index);
}
return true;
case Gdk.Key.Escape:
// Handle seperately, otherwise it takes 2 escape hits to close the modal
close_search ();
return true;
return Gdk.EVENT_STOP;
default:
break;
}

return false;
return Gdk.EVENT_PROPAGATE;
});

search_term_entry.activate.connect (() => {
Expand Down Expand Up @@ -188,7 +158,6 @@ public class Scratch.FuzzySearchPopover : Gtk.Popover {

foreach (var result in results) {
var file_item = new FileItem (result, indexer.project_paths.size > 1);
file_item.can_focus = false;

if (first) {
first = false;
Expand All @@ -199,9 +168,6 @@ public class Scratch.FuzzySearchPopover : Gtk.Popover {
search_list_store.insert_sorted (file_item, sort_func);
}

scrolled.hide ();
scrolled.show_all ();

// Reset scrolling
scrolled.vadjustment.value = 0;
}
Expand All @@ -211,8 +177,6 @@ public class Scratch.FuzzySearchPopover : Gtk.Popover {
});
} else {
search_list_store.remove_all ();

scrolled.hide ();
}
});

Expand All @@ -231,6 +195,8 @@ public class Scratch.FuzzySearchPopover : Gtk.Popover {

current_doc_project = get_current_project (); // This will not change while popover is showing
});

search_result_container.move_cursor.connect (move_cursor);
}

private int sort_func (Object a, Object b) {
Expand All @@ -251,44 +217,29 @@ public class Scratch.FuzzySearchPopover : Gtk.Popover {
}
}

private void calculate_scroll_offset (int old_position, int new_position) {
// Shortcut if jumping from first to last or the other way round
if (new_position == 0 && old_position > new_position) {
scrolled.vadjustment.value = 0;
private void move_cursor (Gtk.ListBox list_box, Gtk.MovementStep step, int count) {
unowned var selected = list_box.get_selected_row ();
if (step != DISPLAY_LINES || selected == null) {
return;
} else if (old_position == 0 && new_position == search_list_store.n_items - 1) {
scrolled.vadjustment.value = scrolled.vadjustment.get_upper ();
}

// Move up to the searchbar
if (selected == list_box.get_row_at_index (0) && count == -1) {
move_focus (TAB_BACKWARD);
return;
}

var size_box = scrolled.vadjustment.get_upper () / search_list_store.n_items;
var current_top = scrolled.vadjustment.value;
var current_bottom = current_top + size_box * (max_items - 2);
if (old_position < new_position) {
// Down movement
var new_adjust = size_box * (preselected_index);
if (new_adjust >= current_bottom) {
scrolled.vadjustment.value = size_box * (preselected_index - (max_items - 1));
}
} else if (old_position > new_position) {
// Up movement
var new_adjust = size_box * (preselected_index);
if (new_adjust < current_top) {
scrolled.vadjustment.value = new_adjust;
}
// Wrap to the searchbar
if (list_box.get_row_at_index (selected.get_index () + count) == null) {
list_box.select_row (list_box.get_row_at_index (0));
move_focus (TAB_FORWARD);
}
}

private void handle_item_selection (FileItem item) {
open_file (item.filepath.strip ());
}

private void preselect_new_item (FileItem old_item, FileItem new_item) {
var class_name = "preselect-fuzzy";
old_item.get_style_context ().remove_class (class_name);
new_item.get_style_context ().add_class (class_name);
}

private string get_current_project () {
Scratch.Services.Document current_document = current_window.document_view.current_document;
if (current_document == null) {
Expand Down
Loading