Skip to content

Highlight selection plugin: Fix highlighting when same word reselected #1582

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
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
45 changes: 18 additions & 27 deletions plugins/highlight-word-selection/highlight-word-selection.vala
Original file line number Diff line number Diff line change
Expand Up @@ -34,30 +34,27 @@ public class Scratch.Plugins.HighlightSelectedWords : Peas.ExtensionBase, Scratc
plugins = (Scratch.Services.Interface) object;
plugins.hook_document.connect ((doc) => {
if (current_source != null) {
current_source.deselected.disconnect (on_deselection);
current_source.selection_changed.disconnect (on_selection_changed);
current_source.selection_event.disconnect (on_selection_changed);
}

current_source = doc.source_view;
current_source.deselected.connect (on_deselection);
current_source.selection_changed.connect (on_selection_changed);
current_source.selection_event.connect (on_selection_changed);
});

plugins.hook_window.connect ((w) => {
main_window = w;
});
}

public void on_selection_changed (ref Gtk.TextIter start, ref Gtk.TextIter end) requires (main_window != null) {
if (!main_window.has_successful_search ()) {
// Perform plugin selection when there is no ongoing and successful search
current_search_context = new Gtk.SourceSearchContext (
(Gtk.SourceBuffer)current_source.buffer,
null
);
current_search_context.settings.search_text = "";
private void on_selection_changed (ref Gtk.TextIter start, ref Gtk.TextIter end) requires (main_window != null) {
if (current_search_context != null) {
// Cancel existing search
current_search_context.set_highlight (false);
current_search_context = null;
}

if (!main_window.has_successful_search ()) {
// Perform plugin selection when there is no ongoing and successful search
var original_start = start.copy ();

// Ignore leading space
Expand Down Expand Up @@ -113,31 +110,25 @@ public class Scratch.Plugins.HighlightSelectedWords : Peas.ExtensionBase, Scratc

// Ensure no leading or trailing space
var selected_text = start.get_text (end).strip ();

if (selected_text.char_count () > SELECTION_HIGHLIGHT_MAX_CHARS) {
return;
//Nevertheless select as much as permitted
selected_text = selected_text.substring (0, SELECTION_HIGHLIGHT_MAX_CHARS);
}

current_search_context = new Gtk.SourceSearchContext (
(Gtk.SourceBuffer)current_source.buffer,
null
);
current_search_context.settings.search_text = "";
current_search_context.set_highlight (false);
current_search_context.settings.search_text = selected_text;
current_search_context.set_highlight (true);
} else if (current_search_context != null) {
// Cancel existing search
current_search_context.set_highlight (false);
current_search_context = null;
}
}

public void on_deselection () {
if (current_search_context != null) {
current_search_context.set_highlight (false);
current_search_context = null;
}
}

public void deactivate () {
if (current_source != null) {
current_source.deselected.disconnect (on_deselection);
current_source.selection_changed.disconnect (on_selection_changed);
current_source.selection_event.disconnect (on_selection_changed);
}
}
}
Expand Down
72 changes: 28 additions & 44 deletions src/Widgets/SourceView.vala
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ namespace Scratch.Widgets {
private uint size_allocate_timer = 0;
private Gtk.TextIter last_select_start_iter;
private Gtk.TextIter last_select_end_iter;
private string selected_text = "";
private GitGutterRenderer git_diff_gutter_renderer;
private NavMarkGutterRenderer navmark_gutter_renderer;

Expand All @@ -44,9 +43,9 @@ namespace Scratch.Widgets {
private const double SCROLL_THRESHOLD = 1.0;

public signal void style_changed (Gtk.SourceStyleScheme style);
// "selection_changed" signal now only emitted when the selected text changes (position ignored). Listened to by searchbar and highlight word selection plugin
public signal void selection_changed (Gtk.TextIter start_iter, Gtk.TextIter end_iter);
public signal void deselected ();
// "selection_event" signal emitted when selection changes. May be selection or deselection.
// Listened to by highlight word selection plugin
public signal void selection_event (Gtk.TextIter start_iter, Gtk.TextIter end_iter);

//lang can be null, in the case of *No highlight style* aka Normal text
public Gtk.SourceLanguage? language {
Expand Down Expand Up @@ -558,20 +557,17 @@ namespace Scratch.Widgets {

Gtk.TextIter start, end;
var selection = buffer.get_selection_bounds (out start, out end);
var draw_spaces_state = (ScratchDrawSpacesState) Scratch.settings.get_enum ("draw-spaces");
var draw_spaces_state = Scratch.settings.get_enum ("draw-spaces");
/* Draw spaces in selection the same way if drawn at all */
if (selection &&
draw_spaces_state in (ScratchDrawSpacesState.FOR_SELECTION | ScratchDrawSpacesState.CURRENT | ScratchDrawSpacesState.ALWAYS)) {

if (selection && draw_spaces_state != ScratchDrawSpacesState.NEVER) {
buffer.apply_tag_by_name ("draw_spaces", start, end);
} else if (draw_spaces_state == ScratchDrawSpacesState.CURRENT) {
get_current_line (out start, out end);
buffer.apply_tag_by_name ("draw_spaces", start, end);
return;
}

if (draw_spaces_state == ScratchDrawSpacesState.CURRENT &&
get_current_line (out start, out end)) {

buffer.apply_tag_by_name ("draw_spaces", start, end);
}
//This is required for reliable results when this function is called from another thread (e.g. SourceFunc)
queue_draw ();
}

private void on_context_menu (Gtk.Menu menu) {
Expand Down Expand Up @@ -663,29 +659,34 @@ namespace Scratch.Widgets {

private void on_mark_set (Gtk.TextIter loc, Gtk.TextMark mar) {
// Weed out user movement for text selection changes
// may not be new selection - also caused by highlighting for example
Gtk.TextIter start, end;
buffer.get_selection_bounds (out start, out end);

if (start.equal (last_select_start_iter) && end.equal (last_select_end_iter)) {
if (last_select_start_iter.equal (start) && last_select_end_iter.equal (end)) {
// Selection unchanged - update draw spaces when required
return;
} else {
last_select_start_iter.assign (start);
last_select_end_iter.assign (end);
}

last_select_start_iter.assign (start);
last_select_end_iter.assign (end);
update_draw_spaces ();

if (selection_changed_timer != 0) {
Source.remove (selection_changed_timer);
selection_changed_timer = 0;
}

// Fire deselected immediately
if (start.equal (end)) {
deselected ();
// Don't fire signal till we think select movement is done
} else {
selection_changed_timer = Timeout.add (THROTTLE_MS, selection_changed_event);
}
selection_changed_timer = Timeout.add (
THROTTLE_MS,
() => {
selection_changed_timer = 0;
update_draw_spaces ();

Gtk.TextIter s, e;
bool selected = buffer.get_selection_bounds (out s, out e);
selection_event (s, e);
return Source.REMOVE;
}
);
}

private void on_mark_deleted (Gtk.TextMark mark) {
Expand All @@ -696,23 +697,6 @@ namespace Scratch.Widgets {
}
}

private bool selection_changed_event () {
Gtk.TextIter start, end;
bool selected = buffer.get_selection_bounds (out start, out end);
if (selected) {
var prev_selected_text = selected_text;
selected_text = buffer.get_text (start, end, true);
if (selected_text != prev_selected_text) {
selection_changed (start, end);
}
} else {
deselected ();
}

selection_changed_timer = 0;
return false;
}

uint refresh_timeout_id = 0;
public void schedule_refresh () {
if (refresh_timeout_id > 0) {
Expand Down