Skip to content
124 changes: 58 additions & 66 deletions src/Widgets/SearchBar.vala
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,14 @@ public class Scratch.Widgets.SearchBar : Gtk.Box { //TODO In Gtk4 use a BinLayou
* "Down", it will go at the start of the file to search for the content
* of the search entry.
**/
private Granite.SwitchModelButton cycle_search_button ;
private Gtk.ComboBoxText case_sensitive_search_button;
private Granite.SwitchModelButton regex_search_button;
private Granite.SwitchModelButton whole_word_search_button;
private Gtk.SearchEntry search_entry;
private Gtk.SearchEntry replace_entry;
private Granite.SwitchModelButton cycle_search_button;
private Gtk.Label search_occurence_count_label;
private Scratch.Widgets.SourceView? text_view = null;
private Gtk.TextBuffer? text_buffer = null;
private Gtk.SourceSearchContext? search_context;
private Gtk.SourceSearchSettings search_settings;
private uint update_search_label_timeout_id = 0;
private Gtk.Revealer revealer;

Expand Down Expand Up @@ -147,7 +145,7 @@ public class Scratch.Widgets.SearchBar : Gtk.Box { //TODO In Gtk4 use a BinLayou

cycle_search_button = new Granite.SwitchModelButton (_("Cyclic Search"));

case_sensitive_search_button = new Gtk.ComboBoxText ();
var case_sensitive_search_button = new Gtk.ComboBoxText ();
case_sensitive_search_button.append ("never", _("Never"));
case_sensitive_search_button.append ("mixed", _("Mixed Case"));
case_sensitive_search_button.append ("always", _("Always"));
Expand All @@ -160,8 +158,8 @@ public class Scratch.Widgets.SearchBar : Gtk.Box { //TODO In Gtk4 use a BinLayou
case_sensitive_box.add (case_sensitive_search_button);
case_sensitive_box.get_style_context ().add_class (Gtk.STYLE_CLASS_MENUITEM);

regex_search_button = new Granite.SwitchModelButton (_("Use Regular Expressions"));
whole_word_search_button = new Granite.SwitchModelButton (_("Match Whole Words"));
var regex_search_button = new Granite.SwitchModelButton (_("Use Regular Expressions"));
var whole_word_search_button = new Granite.SwitchModelButton (_("Match Whole Words"));

var search_option_box = new Gtk.Box (VERTICAL, 0) {
margin_top = 3,
Expand All @@ -187,31 +185,6 @@ public class Scratch.Widgets.SearchBar : Gtk.Box { //TODO In Gtk4 use a BinLayou
};
search_menubutton.add (search_buttonbox);

cycle_search_button.toggled.connect (on_search_parameters_changed);
case_sensitive_search_button.changed.connect (on_search_parameters_changed);
whole_word_search_button.toggled.connect (on_search_parameters_changed);
regex_search_button.toggled.connect (on_search_parameters_changed);

// Bind some application settings
settings.bind ("cyclic-search", cycle_search_button, "active", DEFAULT);
settings.bind ("wholeword-search", whole_word_search_button, "active", DEFAULT);
settings.bind ("case-sensitive-search", case_sensitive_search_button, "active-id", DEFAULT);
settings.bind ("regex-search", regex_search_button, "active", DEFAULT);

// These settings are ignored when regex searching
regex_search_button.bind_property (
"active", cycle_search_button, "sensitive", SYNC_CREATE | INVERT_BOOLEAN
);
regex_search_button.bind_property (
"active", whole_word_search_button, "sensitive", SYNC_CREATE | INVERT_BOOLEAN
);
regex_search_button.bind_property (
"active", case_sensitive_search_label, "sensitive", SYNC_CREATE | INVERT_BOOLEAN
);
regex_search_button.bind_property (
"active", case_sensitive_search_button, "sensitive", SYNC_CREATE | INVERT_BOOLEAN
);

var search_box = new Gtk.Box (HORIZONTAL, 0) {
margin_top = 3,
margin_end = 3,
Expand Down Expand Up @@ -257,8 +230,28 @@ public class Scratch.Widgets.SearchBar : Gtk.Box { //TODO In Gtk4 use a BinLayou
replace_flow_box_child.can_focus = false;
replace_flow_box_child.add (replace_grid);

search_settings = new Gtk.SourceSearchSettings ();

// Bind some application settings
settings.bind ("case-sensitive-search", case_sensitive_search_button, "active-id", DEFAULT);
settings.bind ("cyclic-search", cycle_search_button, "active", DEFAULT);
settings.bind ("cyclic-search", search_settings, "wrap-around", DEFAULT);
settings.bind ("regex-search", regex_search_button, "active", DEFAULT);
settings.bind ("regex-search", search_settings, "regex-enabled", DEFAULT);
settings.bind ("wholeword-search", search_settings, "at-word-boundaries", DEFAULT);
settings.bind ("wholeword-search", whole_word_search_button, "active", DEFAULT);

// These settings are ignored when regex searching
settings.bind ("regex-search", cycle_search_button, "sensitive", INVERT_BOOLEAN);
settings.bind ("regex-search", whole_word_search_button, "sensitive", INVERT_BOOLEAN);
settings.bind ("regex-search", case_sensitive_search_button, "sensitive", INVERT_BOOLEAN);
settings.bind ("regex-search", case_sensitive_search_label, "sensitive", INVERT_BOOLEAN);

settings.changed.connect (on_settings_changed);

// Connecting to some signals
search_entry.changed.connect (on_search_parameters_changed);
search_entry.bind_property ("text", search_settings, "search-text", SYNC_CREATE);
search_entry.changed.connect (update_search_widgets);
search_entry.notify["is-focus"].connect (() => {
if (search_entry.is_focus && text_buffer != null) {
Idle.add (() => {
Expand Down Expand Up @@ -313,10 +306,8 @@ public class Scratch.Widgets.SearchBar : Gtk.Box { //TODO In Gtk4 use a BinLayou
this.text_view = text_view;
this.text_buffer = text_view.get_buffer ();
this.text_buffer.changed.connect (update_search_widgets);
this.search_context = new Gtk.SourceSearchContext (text_buffer as Gtk.SourceBuffer, null);
search_context.settings.wrap_around = cycle_search_button.active;
search_context.settings.regex_enabled = regex_search_button.active;
search_context.settings.search_text = search_entry.text;
search_context = new Gtk.SourceSearchContext ((Gtk.SourceBuffer) text_buffer, search_settings);

update_search_widgets ();
}

Expand Down Expand Up @@ -364,7 +355,7 @@ public class Scratch.Widgets.SearchBar : Gtk.Box { //TODO In Gtk4 use a BinLayou
Gtk.TextIter? start_iter, end_iter;
if (text_buffer != null) {
text_buffer.get_selection_bounds (out start_iter, out end_iter);
if (!search_for_iter_backward (start_iter, out end_iter) && cycle_search_button.active) {
if (!search_for_iter_backward (start_iter, out end_iter) && settings.get_boolean ("cyclic-search")) {
text_buffer.get_end_iter (out start_iter);
search_for_iter_backward (start_iter, out end_iter);
}
Expand All @@ -378,7 +369,7 @@ public class Scratch.Widgets.SearchBar : Gtk.Box { //TODO In Gtk4 use a BinLayou
Gtk.TextIter? start_iter, end_iter, end_iter_tmp;
if (text_buffer != null) {
text_buffer.get_selection_bounds (out start_iter, out end_iter);
if (!search_for_iter (end_iter, out end_iter_tmp) && cycle_search_button.active) {
if (!search_for_iter (end_iter, out end_iter_tmp) && settings.get_boolean ("cyclic-search")) {
text_buffer.get_start_iter (out start_iter);
search_for_iter (start_iter, out end_iter);
}
Expand Down Expand Up @@ -436,34 +427,18 @@ public class Scratch.Widgets.SearchBar : Gtk.Box { //TODO In Gtk4 use a BinLayou
this.window.get_current_document ().toggle_changed_handlers (true);
}

// Called when one of the settings buttons or the search term changes
private void on_search_parameters_changed () {
if (search_context != null) {
var search_string = search_entry.text;
search_context.settings.search_text = search_string;
var case_mode = (CaseSensitiveMode)(case_sensitive_search_button.active);
switch (case_mode) {
case CaseSensitiveMode.NEVER:
search_context.settings.case_sensitive = false;
break;
case CaseSensitiveMode.MIXED:
var found = ((search_string.up () == search_string) ||
(search_string.down () == search_string)
);
search_context.settings.case_sensitive = !found;
break;
case CaseSensitiveMode.ALWAYS:
search_context.settings.case_sensitive = true;
break;
default:
assert_not_reached ();
}

search_context.settings.at_word_boundaries = whole_word_search_button.active;
search_context.settings.regex_enabled = regex_search_button.active;
private void on_settings_changed (string key) {
switch (key) {
case "case-sensitive-search":
case "cyclic-search":
case "regex-search":
case "wholeword-search":
update_search_widgets ();
break;
default:
// Don't update widgets for non-search settings change
return;
}

update_search_widgets ();
}

private bool has_matches () {
Expand Down Expand Up @@ -610,6 +585,23 @@ public class Scratch.Widgets.SearchBar : Gtk.Box { //TODO In Gtk4 use a BinLayou
}
}

switch (settings.get_enum ("case-sensitive-search")) {
case CaseSensitiveMode.NEVER:
search_settings.case_sensitive = false;
break;
case CaseSensitiveMode.MIXED:
search_settings.case_sensitive = !(
search_entry.text.up () == search_entry.text ||
search_entry.text.down () == search_entry.text
);
break;
case CaseSensitiveMode.ALWAYS:
search_settings.case_sensitive = true;
break;
default:
assert_not_reached ();
}

// Update appearance of search entry
var ctx = search_entry.get_style_context ();

Expand Down