[gnome-builder/wip/gtk4-port] libide/sourceview: add populate-menu signal to view
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/gtk4-port] libide/sourceview: add populate-menu signal to view
- Date: Fri, 8 Apr 2022 19:34:15 +0000 (UTC)
commit 934c0c56ce9ea9d631866c45e193815287b090fe
Author: Christian Hergert <chergert redhat com>
Date: Fri Apr 8 12:34:06 2022 -0700
libide/sourceview: add populate-menu signal to view
This allows us to not need click controllers in various page addins just
to update menus/etc. There is still some popover issue I haven't deduced
yet, which doesn't happen in gnome-text-editor.
src/libide/sourceview/ide-source-view.c | 89 +++++++++++++++++-
.../spellcheck/gbp-spell-editor-page-addin.c | 100 ++++++++-------------
2 files changed, 125 insertions(+), 64 deletions(-)
---
diff --git a/src/libide/sourceview/ide-source-view.c b/src/libide/sourceview/ide-source-view.c
index 6ed34a636..6c132d3ae 100644
--- a/src/libide/sourceview/ide-source-view.c
+++ b/src/libide/sourceview/ide-source-view.c
@@ -39,6 +39,8 @@ struct _IdeSourceView
IdeJoinedMenu *joined_menu;
};
+G_DEFINE_TYPE (IdeSourceView, ide_source_view, GTK_SOURCE_TYPE_VIEW)
+
enum {
PROP_0,
PROP_FONT_DESC,
@@ -48,9 +50,13 @@ enum {
N_PROPS
};
-G_DEFINE_TYPE (IdeSourceView, ide_source_view, GTK_SOURCE_TYPE_VIEW)
+enum {
+ POPULATE_MENU,
+ N_SIGNALS
+};
-static GParamSpec *properties [N_PROPS];
+static GParamSpec *properties[N_PROPS];
+static guint signals[N_SIGNALS];
static void
ide_source_view_update_css (IdeSourceView *self)
@@ -164,6 +170,49 @@ tweak_gutter_spacing (GtkSourceView *view)
}
}
+static void
+ide_source_view_click_pressed_cb (IdeSourceView *self,
+ int n_press,
+ double x,
+ double y,
+ GtkGestureClick *click)
+{
+ GdkEventSequence *sequence;
+ g_auto(GStrv) corrections = NULL;
+ GtkTextBuffer *buffer;
+ GdkEvent *event;
+ GtkTextIter iter;
+ int buf_x, buf_y;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_SOURCE_VIEW (self));
+ g_assert (GTK_IS_GESTURE_CLICK (click));
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (self));
+ sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (click));
+ event = gtk_gesture_get_last_event (GTK_GESTURE (click), sequence);
+
+ if (n_press != 1 || !gdk_event_triggers_context_menu (event))
+ IDE_EXIT;
+
+ /* Move the cursor position to where the click occurred so that
+ * the context menu will be useful for the click location.
+ */
+ if (!gtk_text_buffer_get_has_selection (buffer))
+ {
+ gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (self),
+ GTK_TEXT_WINDOW_WIDGET,
+ x, y, &buf_x, &buf_y);
+ gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (self), &iter, buf_x, buf_y);
+ gtk_text_buffer_select_range (buffer, &iter, &iter);
+ }
+
+ g_signal_emit (self, signals[POPULATE_MENU], 0);
+
+ IDE_EXIT;
+}
+
static void
ide_source_view_dispose (GObject *object)
{
@@ -281,23 +330,59 @@ ide_source_view_class_init (IdeSourceViewClass *klass)
(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ /**
+ * IdeSourceView::populate-menu:
+ * @self: an #IdeSourceView
+ *
+ * The "populate-menu" signal is emitted before the context meu is shown
+ * to the user. Handlers of this signal should update any menu items they
+ * have which have been connected using ide_source_view_append_menu() or
+ * simmilar.
+ */
+ signals[POPULATE_MENU] =
+ g_signal_new_class_handler ("populate-menu",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ NULL,
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 0);
+
}
static void
ide_source_view_init (IdeSourceView *self)
{
GtkStyleContext *style_context;
+ GtkEventController *click;
+ /* Setup our extra menu so that consumers can use
+ * ide_source_view_append_men() or similar to update menus.
+ */
self->joined_menu = ide_joined_menu_new ();
gtk_text_view_set_extra_menu (GTK_TEXT_VIEW (self),
G_MENU_MODEL (self->joined_menu));
+ /* Setup a handler to emit ::populate-menu */
+ click = GTK_EVENT_CONTROLLER (gtk_gesture_click_new ());
+ gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (click), 0);
+ g_signal_connect_swapped (click,
+ "pressed",
+ G_CALLBACK (ide_source_view_click_pressed_cb),
+ self);
+ gtk_widget_add_controller (GTK_WIDGET (self), click);
+
+ /* This is sort of a layer vioaltion, but it's helpful for us to
+ * get the system font name and manage it invisibly.
+ */
g_signal_connect_object (g_application_get_default (),
"notify::system-font-name",
G_CALLBACK (ide_source_view_update_css),
self,
G_CONNECT_SWAPPED);
+ /* Setup the CSS provider for the custom font/scale/etc. */
self->css_provider = gtk_css_provider_new ();
style_context = gtk_widget_get_style_context (GTK_WIDGET (self));
gtk_style_context_add_provider (style_context,
diff --git a/src/plugins/spellcheck/gbp-spell-editor-page-addin.c
b/src/plugins/spellcheck/gbp-spell-editor-page-addin.c
index 7ce5c7174..94137edad 100644
--- a/src/plugins/spellcheck/gbp-spell-editor-page-addin.c
+++ b/src/plugins/spellcheck/gbp-spell-editor-page-addin.c
@@ -34,7 +34,6 @@ struct _GbpSpellEditorPageAddin
GObject parent_instance;
IdeEditorPage *page;
GbpSpellBufferAddin *buffer_addin;
- GtkGestureClick *click;
GMenuModel *menu;
GSimpleActionGroup *actions;
char *spelling_word;
@@ -137,66 +136,45 @@ set_action_enabled (GSimpleActionGroup *group,
}
static void
-on_click_pressed_cb (GtkGestureClick *click,
- int n_press,
- double x,
- double y,
- GbpSpellEditorPageAddin *self)
+gbp_spell_editor_page_addin_populate_menu_cb (GbpSpellEditorPageAddin *self,
+ IdeSourceView *view)
{
- GdkEventSequence *sequence;
g_auto(GStrv) corrections = NULL;
g_autofree char *word = NULL;
- IdeSourceView *view;
GtkTextBuffer *buffer;
- GdkEvent *event;
- GtkTextIter iter, begin, end;
- int buf_x, buf_y;
-
- g_assert (GBP_IS_SPELL_EDITOR_PAGE_ADDIN (self));
- g_assert (GTK_IS_GESTURE_CLICK (click));
- g_assert (IDE_IS_EDITOR_PAGE (self->page));
+ GtkTextIter begin, end;
- sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (click));
- event = gtk_gesture_get_last_event (GTK_GESTURE (click), sequence);
+ IDE_ENTRY;
- if (n_press != 1 || !gdk_event_triggers_context_menu (event))
- goto cleanup;
+ g_assert (GBP_IS_SPELL_EDITOR_PAGE_ADDIN (self));
+ g_assert (IDE_IS_SOURCE_VIEW (view));
- /* Move the cursor position to where the click occurred so that
- * the context menu will be useful for the click location.
- */
- view = ide_editor_page_get_view (self->page);
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
- if (gtk_text_buffer_get_selection_bounds (buffer, &begin, &end))
- goto cleanup;
+ gtk_text_buffer_get_selection_bounds (buffer, &begin, &end);
- gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (view),
- GTK_TEXT_WINDOW_WIDGET,
- x, y, &buf_x, &buf_y);
- gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (view), &iter, buf_x, buf_y);
- gtk_text_buffer_select_range (buffer, &iter, &iter);
-
- /* Get the word under the cursor */
- gtk_text_buffer_get_iter_at_mark (buffer, &iter, gtk_text_buffer_get_insert (buffer));
- begin = iter;
- if (!gtk_text_iter_starts_word (&begin))
- gtk_text_iter_backward_word_start (&begin);
- end = begin;
- if (!gtk_text_iter_ends_word (&end))
- gtk_text_iter_forward_word_end (&end);
- if (!gtk_text_iter_equal (&begin, &end) &&
- gtk_text_iter_compare (&begin, &iter) <= 0 &&
- gtk_text_iter_compare (&iter, &end) <= 0)
+ if (gtk_text_iter_equal (&begin, &end))
{
- word = gtk_text_iter_get_slice (&begin, &end);
-
- if (!gbp_spell_buffer_addin_check_spelling (self->buffer_addin, word))
- corrections = gbp_spell_buffer_addin_list_corrections (self->buffer_addin, word);
- else
- g_clear_pointer (&word, g_free);
+ GtkTextIter iter = begin;
+
+ /* Get the word under the cursor */
+ if (!gtk_text_iter_starts_word (&begin))
+ gtk_text_iter_backward_word_start (&begin);
+ end = begin;
+ if (!gtk_text_iter_ends_word (&end))
+ gtk_text_iter_forward_word_end (&end);
+ if (!gtk_text_iter_equal (&begin, &end) &&
+ gtk_text_iter_compare (&begin, &iter) <= 0 &&
+ gtk_text_iter_compare (&iter, &end) <= 0)
+ {
+ word = gtk_text_iter_get_slice (&begin, &end);
+
+ if (!gbp_spell_buffer_addin_check_spelling (self->buffer_addin, word))
+ corrections = gbp_spell_buffer_addin_list_corrections (self->buffer_addin, word);
+ else
+ g_clear_pointer (&word, g_free);
+ }
}
-cleanup:
g_free (self->spelling_word);
self->spelling_word = g_steal_pointer (&word);
@@ -205,6 +183,8 @@ cleanup:
editor_spell_menu_set_corrections (self->menu,
self->spelling_word,
(const char * const *)corrections);
+
+ IDE_EXIT;
}
static void
@@ -228,16 +208,6 @@ gbp_spell_editor_page_addin_load (IdeEditorPageAddin *addin,
self->page = page;
self->buffer_addin = GBP_SPELL_BUFFER_ADDIN (buffer_addin);
- self->click = GTK_GESTURE_CLICK (gtk_gesture_click_new ());
- gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (self->click), 0);
- g_signal_connect_object (self->click,
- "pressed",
- G_CALLBACK (on_click_pressed_cb),
- self,
- 0);
- gtk_widget_add_controller (GTK_WIDGET (view),
- GTK_EVENT_CONTROLLER (self->click));
-
self->menu = editor_spell_menu_new ();
ide_source_view_append_menu (view, self->menu);
@@ -252,6 +222,12 @@ gbp_spell_editor_page_addin_load (IdeEditorPageAddin *addin,
"spelling",
G_ACTION_GROUP (self->actions));
+ g_signal_connect_object (view,
+ "populate-menu",
+ G_CALLBACK (gbp_spell_editor_page_addin_populate_menu_cb),
+ self,
+ G_CONNECT_SWAPPED);
+
IDE_EXIT;
}
@@ -272,9 +248,9 @@ gbp_spell_editor_page_addin_unload (IdeEditorPageAddin *addin,
view = ide_editor_page_get_view (page);
ide_source_view_remove_menu (view, self->menu);
- gtk_widget_remove_controller (GTK_WIDGET (view),
- GTK_EVENT_CONTROLLER (self->click));
- self->click = NULL;
+ g_signal_handlers_disconnect_by_func (view,
+ G_CALLBACK (gbp_spell_editor_page_addin_populate_menu_cb),
+ self);
g_clear_object (&self->menu);
g_clear_object (&self->actions);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]