Branch: refs/heads/master Author: Enrico Tröger enrico.troeger@uvena.de Committer: Enrico Tröger enrico.troeger@uvena.de Date: Wed, 07 Sep 2016 19:44:15 UTC Commit: 26e6906ed5eeab0adf5c7ad0ea177f99a3e49ea5 https://github.com/geany/geany-plugins/commit/26e6906ed5eeab0adf5c7ad0ea177f...
Log Message: ----------- Addons: Implement unselect with single click
For this to work, we need to connect to the "button-press-event" for each document, then process each single click and delay the detected double click event by 50ms before processing it. This way all markers will be removed (in case of double click actually twice) and new markers will be set on double click.
Due to the new behaviour introduced here, the feature is disabled by default.
Closes #445.
Modified Paths: -------------- addons/src/addons.c addons/src/ao_markword.c addons/src/ao_markword.h
Modified: addons/src/addons.c 45 lines changed, 40 insertions(+), 5 deletions(-) =================================================================== @@ -77,6 +77,7 @@ typedef struct gboolean enable_systray; gboolean enable_bookmarklist; gboolean enable_markword; + gboolean enable_markword_single_click_deselect; gboolean enable_xmltagging; gboolean enable_enclose_words; gboolean enable_enclose_words_auto; @@ -175,7 +176,6 @@ gboolean ao_editor_notify_cb(GObject *object, GeanyEditor *editor, SCNotification *nt, gpointer data) { ao_bookmark_list_update_marker(ao_info->bookmarklist, editor, nt); - ao_mark_word_check(ao_info->markword, editor, nt);
return FALSE; } @@ -204,6 +204,7 @@ static void ao_document_open_cb(GObject *obj, GeanyDocument *doc, gpointer data) g_return_if_fail(doc != NULL && doc->is_valid);
ao_tasks_update(ao_info->tasks, doc); + ao_mark_document_open(ao_info->markword, doc); }
@@ -212,6 +213,7 @@ static void ao_document_close_cb(GObject *obj, GeanyDocument *doc, gpointer data g_return_if_fail(doc != NULL && doc->is_valid);
ao_tasks_remove(ao_info->tasks, doc); + ao_mark_document_close(ao_info->markword, doc); }
@@ -280,6 +282,8 @@ void plugin_init(GeanyData *data) "addons", "enable_bookmarklist", FALSE); ao_info->enable_markword = utils_get_setting_boolean(config, "addons", "enable_markword", FALSE); + ao_info->enable_markword_single_click_deselect = utils_get_setting_boolean(config, + "addons", "enable_markword_single_click_deselect", FALSE); ao_info->strip_trailing_blank_lines = utils_get_setting_boolean(config, "addons", "strip_trailing_blank_lines", FALSE); ao_info->enable_xmltagging = utils_get_setting_boolean(config, "addons", @@ -295,7 +299,8 @@ void plugin_init(GeanyData *data) ao_info->openuri = ao_open_uri_new(ao_info->enable_openuri); ao_info->systray = ao_systray_new(ao_info->enable_systray); ao_info->bookmarklist = ao_bookmark_list_new(ao_info->enable_bookmarklist); - ao_info->markword = ao_mark_word_new(ao_info->enable_markword); + ao_info->markword = ao_mark_word_new(ao_info->enable_markword, + ao_info->enable_markword_single_click_deselect); ao_info->tasks = ao_tasks_new(ao_info->enable_tasks, ao_info->tasks_token_list, ao_info->tasks_scan_all_documents); ao_info->copyfilepath = ao_copy_file_path_new(); @@ -332,6 +337,15 @@ static void ao_configure_tasks_toggled_cb(GtkToggleButton *togglebutton, gpointe }
+static void ao_configure_markword_toggled_cb(GtkToggleButton *togglebutton, gpointer data) +{ + gboolean sens = gtk_toggle_button_get_active(togglebutton); + + gtk_widget_set_sensitive(g_object_get_data( + G_OBJECT(data), "check_markword_single_click_deselect"), sens); +} + + static void ao_configure_doclist_toggled_cb(GtkToggleButton *togglebutton, gpointer data) { gboolean sens = gtk_toggle_button_get_active(togglebutton); @@ -379,6 +393,8 @@ static void ao_configure_response_cb(GtkDialog *dialog, gint response, gpointer g_object_get_data(G_OBJECT(dialog), "check_bookmarklist")))); ao_info->enable_markword = (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON( g_object_get_data(G_OBJECT(dialog), "check_markword")))); + ao_info->enable_markword_single_click_deselect = (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON( + g_object_get_data(G_OBJECT(dialog), "check_markword_single_click_deselect")))); ao_info->strip_trailing_blank_lines = (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON( g_object_get_data(G_OBJECT(dialog), "check_blanklines")))); ao_info->enable_xmltagging = (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON( @@ -403,6 +419,8 @@ static void ao_configure_response_cb(GtkDialog *dialog, gint response, gpointer g_key_file_set_boolean(config, "addons", "enable_bookmarklist", ao_info->enable_bookmarklist); g_key_file_set_boolean(config, "addons", "enable_markword", ao_info->enable_markword); + g_key_file_set_boolean(config, "addons", "enable_markword_single_click_deselect", + ao_info->enable_markword_single_click_deselect); g_key_file_set_boolean(config, "addons", "strip_trailing_blank_lines", ao_info->strip_trailing_blank_lines); g_key_file_set_boolean(config, "addons", "enable_xmltagging", @@ -418,7 +436,10 @@ static void ao_configure_response_cb(GtkDialog *dialog, gint response, gpointer g_object_set(ao_info->systray, "enable-systray", ao_info->enable_systray, NULL); g_object_set(ao_info->bookmarklist, "enable-bookmarklist", ao_info->enable_bookmarklist, NULL); - g_object_set(ao_info->markword, "enable-markword", ao_info->enable_markword, NULL); + g_object_set(ao_info->markword, + "enable-markword", ao_info->enable_markword, + "enable-single-click-deselect", ao_info->enable_markword_single_click_deselect, + NULL); g_object_set(ao_info->tasks, "enable-tasks", ao_info->enable_tasks, "scan-all-documents", ao_info->tasks_scan_all_documents, @@ -449,7 +470,8 @@ GtkWidget *plugin_configure(GtkDialog *dialog) GtkWidget *vbox, *check_openuri, *check_tasks, *check_systray; GtkWidget *check_doclist, *vbox_doclist, *frame_doclist; GtkWidget *radio_doclist_name, *radio_doclist_tab_order, *radio_doclist_tab_order_reversed; - GtkWidget *check_bookmarklist, *check_markword, *frame_tasks, *vbox_tasks; + GtkWidget *check_bookmarklist, *check_markword, *check_markword_single_click_deselect; + GtkWidget *frame_markword, *frame_tasks, *vbox_tasks; GtkWidget *check_tasks_scan_mode, *entry_tasks_tokens, *label_tasks_tokens, *tokens_hbox; GtkWidget *check_blanklines, *check_xmltagging; GtkWidget *check_enclose_words, *check_enclose_words_auto, *enclose_words_config_button, *enclose_words_hbox; @@ -557,7 +579,17 @@ GtkWidget *plugin_configure(GtkDialog *dialog) _("Mark all occurrences of a word when double-clicking it")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_markword), ao_info->enable_markword); - gtk_box_pack_start(GTK_BOX(vbox), check_markword, FALSE, FALSE, 3); + g_signal_connect(check_markword, "toggled", G_CALLBACK(ao_configure_markword_toggled_cb), dialog); + + check_markword_single_click_deselect = gtk_check_button_new_with_label( + _("Deselect a previous highlight by single click")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_markword_single_click_deselect), + ao_info->enable_markword_single_click_deselect); + + frame_markword = gtk_frame_new(NULL); + gtk_frame_set_label_widget(GTK_FRAME(frame_markword), check_markword); + gtk_container_add(GTK_CONTAINER(frame_markword), check_markword_single_click_deselect); + gtk_box_pack_start(GTK_BOX(vbox), frame_markword, FALSE, FALSE, 3);
check_blanklines = gtk_check_button_new_with_label( _("Strip trailing blank lines")); @@ -602,6 +634,8 @@ GtkWidget *plugin_configure(GtkDialog *dialog) g_object_set_data(G_OBJECT(dialog), "check_systray", check_systray); g_object_set_data(G_OBJECT(dialog), "check_bookmarklist", check_bookmarklist); g_object_set_data(G_OBJECT(dialog), "check_markword", check_markword); + g_object_set_data(G_OBJECT(dialog), "check_markword_single_click_deselect", + check_markword_single_click_deselect); g_object_set_data(G_OBJECT(dialog), "check_blanklines", check_blanklines); g_object_set_data(G_OBJECT(dialog), "check_xmltagging", check_xmltagging); g_object_set_data(G_OBJECT(dialog), "check_enclose_words", check_enclose_words); @@ -610,6 +644,7 @@ GtkWidget *plugin_configure(GtkDialog *dialog) g_signal_connect(dialog, "response", G_CALLBACK(ao_configure_response_cb), NULL);
ao_configure_tasks_toggled_cb(GTK_TOGGLE_BUTTON(check_tasks), dialog); + ao_configure_markword_toggled_cb(GTK_TOGGLE_BUTTON(check_markword), dialog); ao_configure_doclist_toggled_cb(GTK_TOGGLE_BUTTON(check_doclist), dialog);
gtk_widget_show_all(vbox);
Modified: addons/src/ao_markword.c 94 lines changed, 85 insertions(+), 9 deletions(-) =================================================================== @@ -32,6 +32,9 @@
typedef struct _AoMarkWordPrivate AoMarkWordPrivate;
+#define DOUBLE_CLICK_DELAY 50 + + #define AO_MARKWORD_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj),\ AO_MARKWORD_TYPE, AoMarkWordPrivate))
@@ -48,12 +51,16 @@ struct _AoMarkWordClass struct _AoMarkWordPrivate { gboolean enable_markword; + gboolean enable_single_click_deselect; + + guint double_click_timer_id; };
enum { PROP_0, - PROP_ENABLE_MARKWORD + PROP_ENABLE_MARKWORD, + PROP_ENABLE_MARKWORD_SINGLE_CLICK_DESELECT };
@@ -72,6 +79,9 @@ static void ao_mark_word_set_property(GObject *object, guint prop_id, case PROP_ENABLE_MARKWORD: priv->enable_markword = g_value_get_boolean(value); break; + case PROP_ENABLE_MARKWORD_SINGLE_CLICK_DESELECT: + priv->enable_single_click_deselect = g_value_get_boolean(value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; @@ -96,6 +106,15 @@ static void ao_mark_word_class_init(AoMarkWordClass *klass) "Whether to mark all occurrences of a word when double-clicking it", TRUE, G_PARAM_WRITABLE)); + + g_object_class_install_property(g_object_class, + PROP_ENABLE_MARKWORD_SINGLE_CLICK_DESELECT, + g_param_spec_boolean( + "enable-single-click-deselect", + "enable-single-click-deselect", + "Enable deselecting a previous highlight by single click", + TRUE, + G_PARAM_WRITABLE)); }
@@ -108,28 +127,85 @@ static void ao_mark_word_finalize(GObject *object) }
-void ao_mark_word_check(AoMarkWord *bm, GeanyEditor *editor, SCNotification *nt) +static void clear_marker(void) +{ + /* There might be a small risk that the current document is not the one we want + * but this is very unlikely. */ + GeanyDocument *document = document_get_current(); + /* clear current search indicators */ + if (DOC_VALID(document)) + editor_indicator_clear(document->editor, GEANY_INDICATOR_SEARCH); +} + + +static gboolean mark_word(gpointer bm) { AoMarkWordPrivate *priv = AO_MARKWORD_GET_PRIVATE(bm); + keybindings_send_command(GEANY_KEY_GROUP_SEARCH, GEANY_KEYS_SEARCH_MARKALL); + /* unset and remove myself */ + priv->double_click_timer_id = 0; + return FALSE; +}
- if (priv->enable_markword) + +static gboolean on_editor_button_press_event(GtkWidget *widget, GdkEventButton *event, + AoMarkWord *bm) +{ + if (event->button == 1) { - switch (nt->nmhdr.code) + AoMarkWordPrivate *priv = AO_MARKWORD_GET_PRIVATE(bm); + if (! priv->enable_markword) + return FALSE; + + if (event->type == GDK_BUTTON_PRESS) { - case SCN_DOUBLECLICK: - keybindings_send_command(GEANY_KEY_GROUP_SEARCH, GEANY_KEYS_SEARCH_MARKALL); - break; + if (priv->enable_single_click_deselect) + clear_marker(); + } + else if (event->type == GDK_2BUTTON_PRESS) + { + if (priv->double_click_timer_id == 0) + priv->double_click_timer_id = g_timeout_add(DOUBLE_CLICK_DELAY, mark_word, bm); } } + return FALSE; +} + + +void ao_mark_document_open(AoMarkWord *mw, GeanyDocument *document) +{ + g_return_if_fail(DOC_VALID(document)); + + plugin_signal_connect( + geany_plugin, + G_OBJECT(document->editor->sci), + "button-press-event", + FALSE, + G_CALLBACK(on_editor_button_press_event), + mw); +} + + +void ao_mark_document_close(AoMarkWord *mw, GeanyDocument *document) +{ + g_return_if_fail(DOC_VALID(document)); + + g_signal_handlers_disconnect_by_func(document->editor->sci, on_editor_button_press_event, mw); }
static void ao_mark_word_init(AoMarkWord *self) { + AoMarkWordPrivate *priv = AO_MARKWORD_GET_PRIVATE(self); + priv->double_click_timer_id = 0; }
-AoMarkWord *ao_mark_word_new(gboolean enable) +AoMarkWord *ao_mark_word_new(gboolean enable, gboolean single_click_deselect) { - return g_object_new(AO_MARKWORD_TYPE, "enable-markword", enable, NULL); + return g_object_new( + AO_MARKWORD_TYPE, + "enable-markword", enable, + "enable-single-click-deselect", single_click_deselect, + NULL); }
Modified: addons/src/ao_markword.h 6 lines changed, 3 insertions(+), 3 deletions(-) =================================================================== @@ -40,9 +40,9 @@ typedef struct _AoMarkWord AoMarkWord; typedef struct _AoMarkWordClass AoMarkWordClass;
GType ao_mark_word_get_type (void); -AoMarkWord* ao_mark_word_new (gboolean enable); -void ao_mark_word_check (AoMarkWord *bm, GeanyEditor *editor, - SCNotification *nt); +AoMarkWord* ao_mark_word_new (gboolean enable, gboolean single_click_deselect); +void ao_mark_document_open (AoMarkWord *mw, GeanyDocument *document); +void ao_mark_document_close (AoMarkWord *mw, GeanyDocument *document);
G_END_DECLS
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
plugins-commits@lists.geany.org