[gnome-builder] editor-frame: add context menu to the search entry



commit 724c7b33dad11bc0c3a2e172acfe6101cd5f5631
Author: Fangwen Yu <yynyygy gmail com>
Date:   Fri Mar 11 02:03:59 2016 +0800

    editor-frame: add context menu to the search entry
    
    We can now toggle various search settings with context menu, so
    we do not need smart case sensitive any more, also, the search
    now defaults to case insensitive.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=736522

 data/gtk/menus.ui                        |   44 +++++++++++++
 libide/editor/ide-editor-frame-actions.c |   73 ++++++++++++++++++++++
 libide/editor/ide-editor-frame.c         |   97 ++++++++++++++++++++++++++----
 libide/ide-source-view.c                 |   21 +------
 4 files changed, 203 insertions(+), 32 deletions(-)
---
diff --git a/data/gtk/menus.ui b/data/gtk/menus.ui
index 5d7d1f7..e6d418c 100644
--- a/data/gtk/menus.ui
+++ b/data/gtk/menus.ui
@@ -200,6 +200,50 @@
       </submenu>
     </section>
   </menu>
+  <menu id="ide-editor-frame-search-menu">
+    <section id="ide-editor-frame-search-menu-settings-section">
+      <item>
+        <attribute name="label" translatable="yes">_Match Case</attribute>
+        <attribute name="action">search-entry.change-case-sensitive</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">Match _Entire Word Only</attribute>
+        <attribute name="action">search-entry.change-word-boundaries</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">Match as _Regular Expression</attribute>
+        <attribute name="action">search-entry.change-regex-enabled</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Wrap Around</attribute>
+        <attribute name="action">search-entry.change-wrap-around</attribute>
+      </item>
+    </section>
+    <section id="ide-editor-frame-search-menu-clipboard-section">
+      <item>
+        <attribute name="label" translatable="yes">Cu_t</attribute>
+        <attribute name="action">search-entry.cut-clipboard</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Copy</attribute>
+        <attribute name="action">search-entry.copy-clipboard</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Paste</attribute>
+        <attribute name="action">search-entry.paste-clipboard</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Delete</attribute>
+        <attribute name="action">search-entry.delete-selection</attribute>
+      </item>
+    </section>
+    <section id="ide-editor-frame-search-menu-selection-section">
+      <item>
+        <attribute name="label" translatable="yes">Select _All</attribute>
+        <attribute name="action">search-entry.select-all</attribute>
+      </item>
+    </section>
+  </menu>
   <menu id="ide-layout-stack-menu">
     <section id="ide-layout-stack-menu-splits-section">
       <attribute name="display-hint">horizontal-buttons</attribute>
diff --git a/libide/editor/ide-editor-frame-actions.c b/libide/editor/ide-editor-frame-actions.c
index 6061274..775fcd6 100644
--- a/libide/editor/ide-editor-frame-actions.c
+++ b/libide/editor/ide-editor-frame-actions.c
@@ -97,12 +97,80 @@ ide_editor_frame_actions_previous_search_result (GSimpleAction *action,
     (self->source_view, GTK_DIR_UP, FALSE, TRUE, TRUE, FALSE, FALSE);
 }
 
+static void
+ide_editor_frame_actions_cut_clipboard (GSimpleAction *action,
+                                        GVariant      *state,
+                                        gpointer       user_data)
+{
+  IdeEditorFrame *self = user_data;
+
+  g_assert (IDE_IS_EDITOR_FRAME (self));
+
+  gtk_editable_cut_clipboard (GTK_EDITABLE (self->search_entry));
+}
+
+static void
+ide_editor_frame_actions_copy_clipboard (GSimpleAction *action,
+                                         GVariant      *state,
+                                         gpointer       user_data)
+{
+  IdeEditorFrame *self = user_data;
+
+  g_assert (IDE_IS_EDITOR_FRAME (self));
+
+  gtk_editable_copy_clipboard (GTK_EDITABLE (self->search_entry));
+}
+
+static void
+ide_editor_frame_actions_paste_clipboard (GSimpleAction *action,
+                                          GVariant      *state,
+                                          gpointer       user_data)
+{
+  IdeEditorFrame *self = user_data;
+
+  g_assert (IDE_IS_EDITOR_FRAME (self));
+
+  gtk_editable_paste_clipboard (GTK_EDITABLE (self->search_entry));
+}
+
+static void
+ide_editor_frame_actions_delete_selection (GSimpleAction *action,
+                                           GVariant      *state,
+                                           gpointer       user_data)
+{
+  IdeEditorFrame *self = user_data;
+
+  g_assert (IDE_IS_EDITOR_FRAME (self));
+
+  gtk_editable_delete_selection (GTK_EDITABLE (self->search_entry));
+}
+
+static void
+ide_editor_frame_actions_select_all (GSimpleAction *action,
+                                     GVariant      *state,
+                                     gpointer       user_data)
+{
+  IdeEditorFrame *self = user_data;
+
+  g_assert (IDE_IS_EDITOR_FRAME (self));
+
+  gtk_editable_select_region (GTK_EDITABLE (self->search_entry), 0, -1);
+}
+
 static const GActionEntry IdeEditorFrameActions[] = {
   { "find", ide_editor_frame_actions_find, "i" },
   { "next-search-result", ide_editor_frame_actions_next_search_result },
   { "previous-search-result", ide_editor_frame_actions_previous_search_result },
 };
 
+static const GActionEntry IdeEditorFrameSearchActions[] = {
+  { "cut-clipboard", ide_editor_frame_actions_cut_clipboard, },
+  { "copy-clipboard", ide_editor_frame_actions_copy_clipboard, },
+  { "paste-clipboard", ide_editor_frame_actions_paste_clipboard, },
+  { "delete-selection", ide_editor_frame_actions_delete_selection, },
+  { "select-all", ide_editor_frame_actions_select_all },
+};
+
 void
 ide_editor_frame_actions_init (IdeEditorFrame *self)
 {
@@ -114,4 +182,9 @@ ide_editor_frame_actions_init (IdeEditorFrame *self)
   g_action_map_add_action_entries (G_ACTION_MAP (group), IdeEditorFrameActions,
                                    G_N_ELEMENTS (IdeEditorFrameActions), self);
   gtk_widget_insert_action_group (GTK_WIDGET (self), "frame", G_ACTION_GROUP (group));
+
+  group = g_simple_action_group_new ();
+  g_action_map_add_action_entries (G_ACTION_MAP (group), IdeEditorFrameSearchActions,
+                                   G_N_ELEMENTS (IdeEditorFrameSearchActions), self);
+  gtk_widget_insert_action_group (GTK_WIDGET (self->search_entry), "search-entry", G_ACTION_GROUP (group));
 }
diff --git a/libide/editor/ide-editor-frame.c b/libide/editor/ide-editor-frame.c
index 0f2b137..602ab68 100644
--- a/libide/editor/ide-editor-frame.c
+++ b/libide/editor/ide-editor-frame.c
@@ -513,20 +513,8 @@ ide_editor_frame__search_key_press_event (IdeEditorFrame *self,
 
     default:
       {
-        GtkSourceSearchSettings *search_settings;
-        GtkSourceSearchContext *search_context;
-
         if (!ide_source_view_get_rubberband_search (self->source_view))
           ide_source_view_set_rubberband_search (self->source_view, TRUE);
-
-        /*
-         * Other modes, such as Vim emulation, want word boundaries, but we do
-         * not when searching from this entry. Sort of hacky, but gets the job
-         * done to just change that setting here.
-         */
-        search_context = ide_source_view_get_search_context (self->source_view);
-        search_settings = gtk_source_search_context_get_settings (search_context);
-        gtk_source_search_settings_set_at_word_boundaries (search_settings, FALSE);
       }
       break;
     }
@@ -664,6 +652,85 @@ ide_editor_frame__source_view_populate_popup (IdeEditorFrame *self,
 }
 
 static void
+ide_editor_frame_add_search_actions (IdeEditorFrame *self,
+                                     GActionGroup   *group)
+{
+  GPropertyAction *prop_action;
+  GtkSourceSearchContext *search_context;
+  GtkSourceSearchSettings *search_settings;
+
+  g_assert (IDE_IS_EDITOR_FRAME (self));
+  g_assert (G_IS_ACTION_GROUP (group));
+
+  search_context = ide_source_view_get_search_context (self->source_view);
+  search_settings = gtk_source_search_context_get_settings (search_context);
+
+  prop_action = g_property_action_new ("change-case-sensitive", search_settings, "case-sensitive");
+  g_action_map_add_action (G_ACTION_MAP (group), G_ACTION (prop_action));
+  g_object_unref (prop_action);
+
+  prop_action = g_property_action_new ("change-word-boundaries", search_settings, "at-word-boundaries");
+  g_action_map_add_action (G_ACTION_MAP (group), G_ACTION (prop_action));
+  g_object_unref (prop_action);
+
+  prop_action = g_property_action_new ("change-regex-enabled", search_settings, "regex-enabled");
+  g_action_map_add_action (G_ACTION_MAP (group), G_ACTION (prop_action));
+  g_object_unref (prop_action);
+
+  prop_action = g_property_action_new ("change-wrap-around", search_settings, "wrap-around");
+  g_action_map_add_action (G_ACTION_MAP (group), G_ACTION (prop_action));
+  g_object_unref (prop_action);
+}
+
+static void
+ide_editor_frame__search_populate_popup (IdeEditorFrame *self,
+                                         GtkWidget      *popup,
+                                         GdTaggedEntry  *entry)
+{
+  g_assert (IDE_IS_EDITOR_FRAME (self));
+  g_assert (GTK_IS_WIDGET (popup));
+  g_assert (GD_IS_TAGGED_ENTRY (entry));
+
+  if (GTK_IS_MENU_SHELL (popup))
+    {
+      GMenu *menu;
+      GActionGroup *group;
+      GAction *action;
+      GtkEntryBuffer *buffer;
+      GtkClipboard *clipboard;
+      gboolean clipboard_contains_text;
+      gboolean entry_has_selection;
+
+      group = gtk_widget_get_action_group (GTK_WIDGET (entry), "search-entry");
+      ide_editor_frame_add_search_actions (self, group);
+
+      menu = ide_application_get_menu_by_id (IDE_APPLICATION_DEFAULT, "ide-editor-frame-search-menu");
+      gtk_menu_shell_bind_model (GTK_MENU_SHELL (popup), G_MENU_MODEL (menu), NULL, TRUE);
+
+      clipboard = gtk_widget_get_clipboard (GTK_WIDGET (entry), GDK_SELECTION_CLIPBOARD);
+      clipboard_contains_text = gtk_clipboard_wait_is_text_available (clipboard);
+
+      action = g_action_map_lookup_action (G_ACTION_MAP (group), "paste-clipboard");
+      g_simple_action_set_enabled (G_SIMPLE_ACTION (action), clipboard_contains_text);
+
+      entry_has_selection = gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), NULL, NULL);
+
+      action = g_action_map_lookup_action (G_ACTION_MAP (group), "cut-clipboard");
+      g_simple_action_set_enabled (G_SIMPLE_ACTION (action), entry_has_selection);
+
+      action = g_action_map_lookup_action (G_ACTION_MAP (group), "copy-clipboard");
+      g_simple_action_set_enabled (G_SIMPLE_ACTION (action), entry_has_selection);
+
+      action = g_action_map_lookup_action (G_ACTION_MAP (group), "delete-selection");
+      g_simple_action_set_enabled (G_SIMPLE_ACTION (action), entry_has_selection);
+
+      action = g_action_map_lookup_action (G_ACTION_MAP (group), "select-all");
+      buffer = gtk_entry_get_buffer (GTK_ENTRY (self->search_entry));
+      g_simple_action_set_enabled (G_SIMPLE_ACTION (action), gtk_entry_buffer_get_length (buffer) > 0);
+    }
+}
+
+static void
 ide_editor_frame_constructed (GObject *object)
 {
   IdeEditorFrame *self = (IdeEditorFrame *)object;
@@ -699,6 +766,12 @@ ide_editor_frame_constructed (GObject *object)
                            G_CALLBACK (ide_editor_frame__search_key_press_event),
                            self,
                            G_CONNECT_SWAPPED);
+
+  g_signal_connect_object (self->search_entry,
+                           "populate-popup",
+                           G_CALLBACK (ide_editor_frame__search_populate_popup),
+                           self,
+                           G_CONNECT_SWAPPED);
 }
 
 static void
diff --git a/libide/ide-source-view.c b/libide/ide-source-view.c
index 5ef80b5..0d41efa 100644
--- a/libide/ide-source-view.c
+++ b/libide/ide-source-view.c
@@ -1060,27 +1060,12 @@ ide_source_view__search_settings_notify_search_text (IdeSourceView           *se
 {
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
   const gchar *search_text;
-  gboolean case_sensitive = FALSE;
 
   g_assert (IDE_IS_SOURCE_VIEW (self));
   g_assert (GTK_SOURCE_IS_SEARCH_SETTINGS (search_settings));
 
   search_text = gtk_source_search_settings_get_search_text (search_settings);
 
-  if (search_text != NULL)
-    {
-      for (const gchar *s = search_text; *s; s = g_utf8_next_char (s))
-        {
-          if (g_unichar_isupper (g_utf8_get_char (s)))
-            {
-              case_sensitive = TRUE;
-              break;
-            }
-        }
-    }
-
-  gtk_source_search_settings_set_case_sensitive (search_settings, case_sensitive);
-
   /*
    * If we have IdeSourceView:rubberband-search enabled, then we should try to
    * autoscroll to the next search result starting from our saved search mark.
@@ -1539,7 +1524,7 @@ ide_source_view_bind_buffer (IdeSourceView  *self,
   search_settings = g_object_new (GTK_SOURCE_TYPE_SEARCH_SETTINGS,
                                   "wrap-around", TRUE,
                                   "regex-enabled", FALSE,
-                                  "case-sensitive", TRUE,
+                                  "case-sensitive", FALSE,
                                   NULL);
   priv->search_context = g_object_new (GTK_SOURCE_TYPE_SEARCH_CONTEXT,
                                        "buffer", buffer,
@@ -3607,10 +3592,6 @@ ide_source_view_real_move_search (IdeSourceView    *self,
   gtk_source_search_context_set_highlight (priv->search_context, TRUE);
 
   settings = gtk_source_search_context_get_settings (priv->search_context);
-
-  if (word_boundaries != gtk_source_search_settings_get_at_word_boundaries (settings))
-    gtk_source_search_settings_set_at_word_boundaries (settings, word_boundaries);
-
   search_text = gtk_source_search_settings_get_search_text (settings);
 
   if (search_text == NULL || search_text[0] == '\0')


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]