[anjuta] document-manager: Update inline search to support replace and highlighting
- From: Johannes Schmid <jhs src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [anjuta] document-manager: Update inline search to support replace and highlighting
- Date: Thu, 17 Feb 2011 17:54:19 +0000 (UTC)
commit 2c356eea01eace4e5f9ca0ee8a31f9b34b5f11d4
Author: Eugenia Gabrielova <genia likes science gmail com>
Date: Thu Feb 17 18:08:02 2011 +0100
document-manager: Update inline search to support replace and highlighting
For more information, see
bgo#638134 - Redesign of Single and Multi-File Search & Replace
plugins/Makefile.am | 1 -
plugins/document-manager/action-callbacks.c | 77 +++-
plugins/document-manager/action-callbacks.h | 5 +
.../document-manager/anjuta-document-manager.xml | 29 +
plugins/document-manager/plugin.c | 43 ++-
plugins/document-manager/search-box.c | 594 +++++++++++++++-----
plugins/document-manager/search-box.h | 10 +-
7 files changed, 611 insertions(+), 148 deletions(-)
---
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index b72de18..7cabc64 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -31,7 +31,6 @@ SUBDIRS = . \
project-wizard \
python-loader \
run-program \
- search \
snippets-manager \
sourceview \
starter \
diff --git a/plugins/document-manager/action-callbacks.c b/plugins/document-manager/action-callbacks.c
index 163774d..154eec9 100644
--- a/plugins/document-manager/action-callbacks.c
+++ b/plugins/document-manager/action-callbacks.c
@@ -866,7 +866,7 @@ on_show_search (GtkAction *action, gpointer user_data)
if (!gtk_widget_get_parent (search_box))
gtk_box_pack_end (GTK_BOX (plugin->vbox), search_box, FALSE, FALSE, 0);
- search_box_fill_search_focus (SEARCH_BOX (search_box));
+ search_box_fill_search_focus (SEARCH_BOX (search_box), FALSE);
gtk_widget_show (search_box);
}
@@ -884,7 +884,80 @@ on_repeat_quicksearch (GtkAction *action, gpointer user_data)
if (!gtk_widget_get_visible (search_box))
gtk_widget_show (search_box);
- on_search_activated (NULL, SEARCH_BOX (search_box));
+ search_box_incremental_search (SEARCH_BOX (search_box), TRUE);
+}
+
+void
+on_search_and_replace (GtkAction *action, gpointer user_data)
+{
+ DocmanPlugin *plugin;
+ GtkWidget *search_box;
+
+ plugin = ANJUTA_PLUGIN_DOCMAN (user_data);
+
+ search_box = plugin->search_box;
+ if (!gtk_widget_get_parent (search_box))
+ gtk_box_pack_end (GTK_BOX (plugin->vbox), search_box, FALSE, FALSE, 0);
+
+ search_box_fill_search_focus (SEARCH_BOX (search_box), TRUE);
+ gtk_widget_show (search_box);
+}
+
+void
+on_search_popup_case_sensitive_toggle (GtkAction *action, gpointer user_data)
+{
+ DocmanPlugin *plugin;
+ GtkWidget *search_box;
+
+ gboolean case_sensitive_status =
+ gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
+ plugin = ANJUTA_PLUGIN_DOCMAN (user_data);
+
+ search_box = plugin->search_box;
+ if (!gtk_widget_get_parent (search_box))
+ gtk_box_pack_end (GTK_BOX (plugin->vbox), search_box, FALSE, FALSE, 0);
+
+ if (!gtk_widget_get_visible (search_box))
+ gtk_widget_show (search_box);
+
+ search_box_toggle_case_sensitive (SEARCH_BOX (search_box), case_sensitive_status);
+}
+
+void
+on_search_popup_highlight_toggle (GtkAction *action, gpointer user_data)
+{
+ DocmanPlugin *plugin;
+ GtkWidget *search_box;
+
+ gboolean highlight_status = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
+ plugin = ANJUTA_PLUGIN_DOCMAN (user_data);
+
+ search_box = plugin->search_box;
+ if (!gtk_widget_get_parent (search_box))
+ gtk_box_pack_end (GTK_BOX (plugin->vbox), search_box, FALSE, FALSE, 0);
+
+ if (!gtk_widget_get_visible (search_box))
+ gtk_widget_show (search_box);
+
+ search_box_toggle_highlight (SEARCH_BOX (search_box), highlight_status);
+}
+
+void
+on_search_popup_clear_highlight (GtkAction *action, gpointer user_data)
+{
+ DocmanPlugin *plugin;
+ GtkWidget *search_box;
+
+ plugin = ANJUTA_PLUGIN_DOCMAN (user_data);
+
+ search_box = plugin->search_box;
+ if (!gtk_widget_get_parent (search_box))
+ gtk_box_pack_end (GTK_BOX (plugin->vbox), search_box, FALSE, FALSE, 0);
+
+ if (!gtk_widget_get_visible (search_box))
+ gtk_widget_show (search_box);
+
+ search_box_clear_highlight (SEARCH_BOX (search_box));
}
void
diff --git a/plugins/document-manager/action-callbacks.h b/plugins/document-manager/action-callbacks.h
index 9fc3a7b..f97af8e 100644
--- a/plugins/document-manager/action-callbacks.h
+++ b/plugins/document-manager/action-callbacks.h
@@ -94,6 +94,11 @@ void on_editor_remove_view_activate (GtkAction *action, gpointer user_data);
void on_show_search (GtkAction *action, gpointer user_data);
void on_repeat_quicksearch (GtkAction *action, gpointer user_data);
+void on_search_and_replace (GtkAction *action, gpointer user_data);
+
+void on_search_popup_case_sensitive_toggle (GtkAction *action, gpointer user_data);
+void on_search_popup_highlight_toggle (GtkAction *action, gpointer user_data);
+void on_search_popup_clear_highlight (GtkAction *action, gpointer user_data);
void on_next_document (GtkAction *action, gpointer user_data);
void on_previous_document (GtkAction *action, gpointer user_data);
diff --git a/plugins/document-manager/anjuta-document-manager.xml b/plugins/document-manager/anjuta-document-manager.xml
index a0c3f0b..b53a03e 100644
--- a/plugins/document-manager/anjuta-document-manager.xml
+++ b/plugins/document-manager/anjuta-document-manager.xml
@@ -46,6 +46,7 @@
<placeholder name="PlaceholderQuickSearchMenu">
<menuitem name="QuickSearch" action="ActionEditSearchQuickSearch"/>
<menuitem name="QuickReSearch" action="ActionEditSearchQuickSearchAgain"/>
+ <menuitem name="DocmanReplace" action="ActionEditSearchDocmanReplace"/>
<separator name="separator8"/>
</placeholder>
</menu>
@@ -153,4 +154,32 @@
</menu>
<menuitem name="Close" action="ActionFileClose" />
</popup>
+ <popup name="PopupDocumentManager">
+ <menuitem name="Cut" action="ActionEditCut" />
+ <menuitem name="Copy" action="ActionEditCopy" />
+ <menuitem name="Paste" action="ActionEditPaste" />
+ <separator name="separator26"/>
+ <menu name="Goto" action="ActionMenuGoto">
+ <separator name="separator27"/>
+ <menuitem name="HistoryPrevious" action="ActionEditGotoHistoryPrev" />
+ <menuitem name="HistoryNext" action="ActionEditGotoHistoryNext" />
+ </menu>
+ <menu name="MenuView" action="ActionMenuView">
+ <menuitem name="LineNumbersMargin" action="ActionViewEditorLinenumbers" />
+ <menuitem name="MarkersMargin" action="ActionViewEditorMarkers" />
+ <menuitem name="CodeFoldMargin" action="ActionViewEditorFolds" />
+ <menuitem name="IndentationGuides" action="ActionViewEditorGuides" />
+ <menuitem name="LineWrapping" action="ActionViewEditorWrapping" />
+ <separator name="separator28"/>
+ <menuitem name="ZoomIn" action="ActionViewEditorZoomIn" />
+ <menuitem name="ZoomOut" action="ActionViewEditorZoomOut" />
+ </menu>
+ <menuitem name="Close" action="ActionFileClose" />
+ </popup>
+ <popup name="SearchboxPopup">
+ <menuitem name="CaseCheck" action="ActionSearchboxPopupCaseCheck" />
+ <separator name="separator29"/>
+ <menuitem name="HighlightAll" action="ActionSearchboxPopupHighlightAll" />
+ <menuitem name="ClearHighlight" action="ActionSearchboxPopupClearHighlight" />
+ </popup>
</ui>
diff --git a/plugins/document-manager/plugin.c b/plugins/document-manager/plugin.c
index 9fdc36d..6f0eec7 100644
--- a/plugins/document-manager/plugin.c
+++ b/plugins/document-manager/plugin.c
@@ -266,11 +266,29 @@ static GtkActionEntry actions_search[] = {
{ "ActionEditSearchQuickSearch", GTK_STOCK_FIND, N_("_Quick Search"),
"<control>f", N_("Quick editor embedded search"),
G_CALLBACK (on_show_search)},
- { "ActionEditSearchQuickSearchAgain", GTK_STOCK_FIND, N_("Quick _ReSearch"),
- "<control><shift>f", N_("Repeat quick search"),
- G_CALLBACK (on_repeat_quicksearch)}
+ { "ActionEditSearchQuickSearchAgain", GTK_STOCK_FIND, N_("Search Next"),
+ "<control><shift>f", N_("Search for next appearance of term."),
+ G_CALLBACK (on_repeat_quicksearch)},
+ { "ActionEditSearchDocmanReplace", GTK_STOCK_FIND, N_("Search and Replace"),
+ "<control><shift>h", N_("Search and replace"),
+ G_CALLBACK (on_search_and_replace)},
+ { "ActionSearchboxPopupClearHighlight", GTK_STOCK_FIND, N_("Clear Highlight"),
+ NULL, N_("Clear all highlighted text"),
+ G_CALLBACK (on_search_popup_clear_highlight)}
};
+static GtkToggleActionEntry actions_searchbox_popup[] = {
+ { "ActionSearchboxPopupCaseCheck", GTK_STOCK_FIND,
+ N_("Case Sensitive"), NULL,
+ N_("Match case in search results."),
+ G_CALLBACK (on_search_popup_case_sensitive_toggle)},
+ { "ActionSearchboxPopupHighlightAll", GTK_STOCK_FIND,
+ N_("Highlight All"), NULL,
+ N_("Highlight all occurrences"),
+ G_CALLBACK (on_search_popup_highlight_toggle)}
+};
+
+
static GtkActionEntry actions_edit[] = {
{ "ActionMenuEdit", NULL, N_("_Edit"), NULL, NULL, NULL},/* menu title */
{ "ActionMenuViewEditor", NULL, N_("_Editor"), NULL, NULL, NULL},
@@ -316,6 +334,7 @@ static GtkActionEntry actions_edit[] = {
}
};
+
static GtkToggleActionEntry actions_view[] = {
{ "ActionViewEditorLinenumbers", NULL, N_("_Line Number Margin"), NULL,
N_("Show/Hide line numbers"),
@@ -423,7 +442,9 @@ static struct ActionGroupInfo action_groups[] = {
};
static struct ActionToggleGroupInfo action_toggle_groups[] = {
- { actions_view, G_N_ELEMENTS (actions_view), "ActionGroupEditorView", N_("Editor view settings") }
+ { actions_view, G_N_ELEMENTS (actions_view), "ActionGroupEditorView", N_("Editor view settings") },
+ { actions_searchbox_popup, G_N_ELEMENTS(actions_searchbox_popup),
+ "ActionGroupEditorSearchOptions", N_("Toggle search options") }
};
// void pref_set_style_combo(DocmanPlugin *plugin);
@@ -846,9 +867,21 @@ update_document_ui_interface_items (AnjutaPlugin *plugin, IAnjutaDocument *doc)
action = anjuta_ui_get_action (ui, "ActionGroupEditorSearch",
"ActionEditSearchQuickSearchAgain");
g_object_set (G_OBJECT (action), "sensitive", flag, NULL);
+ action = anjuta_ui_get_action (ui, "ActionGroupEditorSearch",
+ "ActionEditSearchDocmanReplace");
+ g_object_set (G_OBJECT (action), "sensitive", flag, NULL);
+ action = anjuta_ui_get_action (ui, "ActionGroupEditorSearch",
+ "ActionSearchboxPopupClearHighlight");
+ g_object_set (G_OBJECT (action), "sensitive", flag, NULL);
action = anjuta_ui_get_action (ui, "ActionGroupEditorNavigate",
"ActionEditGotoLine");
g_object_set (G_OBJECT (action), "sensitive", flag, NULL);
+ action = anjuta_ui_get_action (ui, "ActionGroupEditorSearchOptions",
+ "ActionSearchboxPopupCaseCheck");
+ g_object_set (G_OBJECT (action), "sensitive", flag, NULL);
+ action = anjuta_ui_get_action (ui, "ActionGroupEditorSearchOptions",
+ "ActionSearchboxPopupHighlightAll");
+ g_object_set (G_OBJECT (action), "sensitive", flag, NULL);
/* IAnjutaEditorAssist */
flag = IANJUTA_IS_EDITOR_ASSIST (doc);
@@ -1765,9 +1798,9 @@ activate_plugin (AnjutaPlugin *plugin)
"/PopupDocumentManager");
g_assert (popup_menu != NULL && GTK_IS_MENU (popup_menu));
anjuta_docman_set_popup_menu (ANJUTA_DOCMAN (docman), popup_menu);
+
if (!initialized)
{
- //search_and_replace_init (ANJUTA_DOCMAN (docman));
}
/* Connect to save session */
g_signal_connect (G_OBJECT (plugin->shell), "save-session",
diff --git a/plugins/document-manager/search-box.c b/plugins/document-manager/search-box.c
index 4a52472..90a6f31 100644
--- a/plugins/document-manager/search-box.c
+++ b/plugins/document-manager/search-box.c
@@ -35,6 +35,7 @@
#include <libanjuta/interfaces/ianjuta-editor.h>
#include <libanjuta/interfaces/ianjuta-editor-search.h>
#include <libanjuta/interfaces/ianjuta-editor-selection.h>
+#include <libanjuta/interfaces/ianjuta-indicable.h>
#define ANJUTA_STOCK_GOTO_LINE "anjuta-goto-line"
@@ -42,19 +43,32 @@ typedef struct _SearchBoxPrivate SearchBoxPrivate;
struct _SearchBoxPrivate
{
+ GtkWidget* grid;
+
GtkWidget* search_entry;
- GtkWidget* case_check;
- GtkWidget* search_button;
+ GtkWidget* replace_entry;
+
GtkWidget* close_button;
-
+ GtkWidget* next_button;
+ GtkWidget* previous_button;
+
+ GtkWidget* replace_button;
+ GtkWidget* replace_all_button;
+
GtkWidget* goto_entry;
GtkWidget* goto_button;
-
+
IAnjutaEditor* current_editor;
AnjutaStatus* status;
-
+
+ /* Search options popup menu */
+ GtkWidget* popup_menu;
+ gboolean case_sensitive;
+ gboolean highlight_all;
+
/* Incremental search */
IAnjutaIterable* last_start;
+
};
#ifdef GET_PRIVATE
@@ -190,6 +204,7 @@ on_goto_key_pressed (GtkWidget* entry, GdkEventKey* event, SearchBox* search_box
static gboolean
on_entry_key_pressed (GtkWidget* entry, GdkEventKey* event, SearchBox* search_box)
{
+
SearchBoxPrivate* private = GET_PRIVATE(search_box);
switch (event->keyval)
{
@@ -225,68 +240,9 @@ on_search_focus_out (GtkWidget* widget, GdkEvent* event, SearchBox* search_box)
return FALSE;
}
-static void
-on_incremental_search (GtkWidget* widget, SearchBox* search_box)
-{
- IAnjutaEditorCell* search_start;
- IAnjutaEditorCell* search_end;
- IAnjutaEditorCell* result_start;
- IAnjutaEditorCell* result_end;
- IAnjutaEditorSelection* selection;
- SearchBoxPrivate* private = GET_PRIVATE(search_box);
- gboolean case_sensitive = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (private->case_check));
- const gchar* search_text = gtk_entry_get_text (GTK_ENTRY (private->search_entry));
- gboolean found = FALSE;
-
- if (!private->current_editor || !search_text || !strlen (search_text))
- return;
-
- if (private->last_start)
- {
- search_start = IANJUTA_EDITOR_CELL (private->last_start);
- }
- else
- {
- search_start =
- IANJUTA_EDITOR_CELL (ianjuta_editor_get_position (private->current_editor,
- NULL));
- }
-
- search_end = IANJUTA_EDITOR_CELL (ianjuta_editor_get_end_position (private->current_editor,
- NULL));
-
- if (ianjuta_editor_search_forward (IANJUTA_EDITOR_SEARCH (private->current_editor),
- search_text, case_sensitive,
- search_start, search_end,
- &result_start,
- &result_end, NULL))
- {
- found = TRUE;
- anjuta_status_pop (ANJUTA_STATUS (private->status));
- }
- if (found)
- {
- selection = IANJUTA_EDITOR_SELECTION (private->current_editor);
- ianjuta_editor_selection_set (selection,
- IANJUTA_ITERABLE (result_start),
- IANJUTA_ITERABLE (result_end), TRUE, NULL);
- g_object_unref (result_start);
- g_object_unref (result_end);
-
- private->last_start = IANJUTA_ITERABLE (search_start);
- }
- else
- {
- g_object_unref (search_start);
- private->last_start = NULL;
- }
-
- search_box_set_entry_color (search_box, found);
- g_object_unref (search_end);
-}
-void
-on_search_activated (GtkWidget* widget, SearchBox* search_box)
+gboolean
+search_box_incremental_search (SearchBox* search_box, gboolean search_forward)
{
IAnjutaEditorCell* search_start;
IAnjutaIterable* real_start;
@@ -295,15 +251,16 @@ on_search_activated (GtkWidget* widget, SearchBox* search_box)
IAnjutaEditorCell* result_end;
IAnjutaEditorSelection* selection;
SearchBoxPrivate* private = GET_PRIVATE(search_box);
- gboolean case_sensitive = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (private->case_check));
+
const gchar* search_text = gtk_entry_get_text (GTK_ENTRY (private->search_entry));
+
gboolean found = FALSE;
if (!private->current_editor || !search_text || !strlen (search_text))
- return;
-
+ return FALSE;
+
selection = IANJUTA_EDITOR_SELECTION (private->current_editor);
-
+
if (ianjuta_editor_selection_has_selection (selection, NULL))
{
search_start =
@@ -322,7 +279,9 @@ on_search_activated (GtkWidget* widget, SearchBox* search_box)
NULL));
/* If a search_result is already selected, move the search start
- * forward by one
+ * forward (or backward) by one. Then, if backwards, clone the
+ * search end to be the search start, and the search start to the
+ * start of the editor.
*/
if (ianjuta_editor_selection_has_selection (selection,
NULL))
@@ -334,11 +293,20 @@ on_search_activated (GtkWidget* widget, SearchBox* search_box)
{
gchar* selected_text =
ianjuta_editor_selection_get (selection, NULL);
- if (case_sensitive)
+ if (private->case_sensitive)
{
if (g_str_has_prefix (selected_text, search_text))
{
- ianjuta_iterable_next (IANJUTA_ITERABLE (search_start), NULL);
+ if (search_forward)
+ {
+ ianjuta_iterable_next (IANJUTA_ITERABLE (search_start), NULL);
+ }
+ else
+ {
+ search_end = ianjuta_iterable_clone (IANJUTA_ITERABLE (search_start), NULL);
+ ianjuta_iterable_previous (IANJUTA_ITERABLE (search_end), NULL);
+ ianjuta_iterable_first (IANJUTA_ITERABLE (search_start), NULL);
+ }
}
}
else if (strlen (selected_text) >= strlen (search_text))
@@ -347,7 +315,16 @@ on_search_activated (GtkWidget* widget, SearchBox* search_box)
gchar* search_text_up = g_utf8_casefold (search_text, strlen (search_text));
if (g_str_equal (selected_up, search_text_up))
{
- ianjuta_iterable_next (IANJUTA_ITERABLE (search_start), NULL);
+ if (search_forward)
+ {
+ ianjuta_iterable_next (IANJUTA_ITERABLE (search_start), NULL);
+ }
+ else
+ {
+ search_end = ianjuta_iterable_clone (IANJUTA_ITERABLE (search_start), NULL);
+ ianjuta_iterable_previous (IANJUTA_ITERABLE (search_end), NULL);
+ ianjuta_iterable_first (IANJUTA_ITERABLE (search_start), NULL);
+ }
}
g_free (selected_up);
g_free (search_text_up);
@@ -355,41 +332,84 @@ on_search_activated (GtkWidget* widget, SearchBox* search_box)
g_free (selected_text);
}
}
-
- if (ianjuta_editor_search_forward (IANJUTA_EDITOR_SEARCH (private->current_editor),
- search_text, case_sensitive,
- search_start, search_end,
- &result_start,
- &result_end, NULL))
+
+ if (search_forward)
{
- found = TRUE;
- anjuta_status_pop (ANJUTA_STATUS (private->status));
+ if (ianjuta_editor_search_forward (IANJUTA_EDITOR_SEARCH (private->current_editor),
+ search_text, private->case_sensitive,
+ search_start, search_end,
+ &result_start,
+ &result_end, NULL))
+ {
+ found = TRUE;
+ anjuta_status_pop (ANJUTA_STATUS (private->status));
+ }
+ else
+ {
+ /* Try to continue on top */
+ ianjuta_iterable_first (IANJUTA_ITERABLE (search_start), NULL);
+ if (ianjuta_editor_search_forward (IANJUTA_EDITOR_SEARCH (private->current_editor),
+ search_text, private->case_sensitive,
+ search_start, search_end,
+ &result_start,
+ &result_end, NULL))
+ {
+ if (ianjuta_iterable_compare (IANJUTA_ITERABLE (result_start),
+ real_start, NULL) != 0)
+ {
+ found = TRUE;
+ anjuta_status_push (private->status,
+ _("Search for \"%s\" reached the end and was continued at the top."), search_text);
+ }
+ else if (ianjuta_editor_selection_has_selection (selection, NULL))
+ {
+ anjuta_status_pop (private->status);
+ anjuta_status_push (private->status,
+ _("Search for \"%s\" reached the end and was continued at the top but no new match was found."), search_text);
+ }
+ }
+ }
}
else
{
- /* Try to continue on top */
- ianjuta_iterable_first (IANJUTA_ITERABLE (search_start), NULL);
- if (ianjuta_editor_search_forward (IANJUTA_EDITOR_SEARCH (private->current_editor),
- search_text, case_sensitive,
- search_start, search_end,
- &result_start,
- &result_end, NULL))
+
+ if (ianjuta_editor_search_backward (IANJUTA_EDITOR_SEARCH (private->current_editor),
+ search_text, private->case_sensitive,
+ search_end, search_start,
+ &result_start,
+ &result_end, NULL))
+ {
+ found = TRUE;
+ anjuta_status_pop (ANJUTA_STATUS (private->status));
+ }
+ else
{
- if (ianjuta_iterable_compare (IANJUTA_ITERABLE (result_start),
- real_start, NULL) != 0)
+ /* Try to continue on buttom */
+ ianjuta_iterable_last (IANJUTA_ITERABLE (search_end), NULL);
+ ianjuta_iterable_first (IANJUTA_ITERABLE (search_start), NULL);
+ if (ianjuta_editor_search_backward (IANJUTA_EDITOR_SEARCH (private->current_editor),
+ search_text, private->case_sensitive,
+ search_end, search_start,
+ &result_start,
+ &result_end, NULL))
{
- found = TRUE;
- anjuta_status_push (private->status,
- _("Search for \"%s\" reached the end and was continued at the top."), search_text);
+ if (ianjuta_iterable_compare (IANJUTA_ITERABLE (result_start),
+ real_start, NULL) != 0)
+ {
+ found = TRUE;
+ anjuta_status_push (private->status,
+ _("Search for \"%s\" reached the end and was continued at the bottom."), search_text);
+ }
+ else if (ianjuta_editor_selection_has_selection (selection, NULL))
+ {
+ anjuta_status_pop (private->status);
+ anjuta_status_push (private->status,
+ _("Search for \"%s\" reached the end and was continued at the bottom but no new match was found."), search_text);
+ }
}
- else if (ianjuta_editor_selection_has_selection (selection, NULL))
- {
- anjuta_status_pop (private->status);
- anjuta_status_push (private->status,
- _("Search for \"%s\" reached the end and was continued at the top but no new match was found."), search_text);
- }
}
}
+
if (found)
{
ianjuta_editor_selection_set (selection,
@@ -398,12 +418,11 @@ on_search_activated (GtkWidget* widget, SearchBox* search_box)
g_object_unref (result_start);
g_object_unref (result_end);
}
- search_box_set_entry_color (search_box, found);
+
+ search_box_set_entry_color (search_box, found);
g_object_unref (real_start);
g_object_unref (search_end);
-
- // We end the incremental search here
-
+
if (private->last_start)
{
g_object_unref (private->last_start);
@@ -413,8 +432,228 @@ on_search_activated (GtkWidget* widget, SearchBox* search_box)
{
g_object_unref (search_start);
}
+
+ return found;
+}
+
+void
+search_box_clear_highlight (SearchBox * search_box)
+{
+ SearchBoxPrivate* private = GET_PRIVATE(search_box);
+
+ if (!private->current_editor)
+ return;
+
+ ianjuta_indicable_clear(IANJUTA_INDICABLE(private->current_editor), NULL);
+}
+
+void
+search_box_toggle_highlight (SearchBox * search_box, gboolean status)
+{
+ SearchBoxPrivate* private = GET_PRIVATE(search_box);
+
+ if (!private->current_editor)
+ return;
+
+ private->highlight_all = status;
+}
+
+void
+search_box_toggle_case_sensitive (SearchBox * search_box, gboolean status)
+{
+ SearchBoxPrivate* private = GET_PRIVATE(search_box);
+
+ if (!private->current_editor)
+ return;
+
+ private->case_sensitive = status;
}
+
+static void
+search_box_search_highlight_all (SearchBox * search_box, gboolean search_forward)
+{
+ IAnjutaEditorCell * result_begin, * result_end, * highlight_start;
+ IAnjutaEditorSelection * selection;
+ gboolean entry_found;
+
+ SearchBoxPrivate* private = GET_PRIVATE(search_box);
+ highlight_start = NULL;
+ ianjuta_indicable_clear(IANJUTA_INDICABLE(private->current_editor), NULL);
+
+ /* Search through editor and highlight instances of search_entry */
+ while ((entry_found = search_box_incremental_search (search_box, search_forward)) == TRUE)
+ {
+
+ selection = IANJUTA_EDITOR_SELECTION (private->current_editor);
+
+ result_begin =
+ IANJUTA_EDITOR_CELL (ianjuta_editor_selection_get_start (selection, NULL));
+ result_end =
+ IANJUTA_EDITOR_CELL (ianjuta_editor_selection_get_end (selection, NULL));
+
+ if (!highlight_start)
+ {
+ highlight_start =
+ ianjuta_iterable_clone (IANJUTA_ITERABLE (result_begin), NULL);
+ }
+ else if (ianjuta_iterable_compare (IANJUTA_ITERABLE (result_begin),
+ IANJUTA_ITERABLE (highlight_start), NULL) == 0)
+ {
+ return;
+ }
+
+ ianjuta_indicable_set(IANJUTA_INDICABLE(private->current_editor),
+ IANJUTA_ITERABLE (result_begin),
+ IANJUTA_ITERABLE (result_end),
+ IANJUTA_INDICABLE_IMPORTANT, NULL);
+ }
+}
+
+static void
+on_search_box_document_changed (GtkWidget * widget, SearchBox * search_box)
+{
+ search_box_incremental_search (search_box, TRUE);
+}
+
+static void
+on_search_box_forward_search (GtkWidget * widget, SearchBox * search_box)
+{
+ SearchBoxPrivate* private = GET_PRIVATE(search_box);
+
+ if (private->highlight_all)
+ {
+ search_box_search_highlight_all (search_box, TRUE);
+ }
+ else
+ {
+ search_box_incremental_search (search_box, TRUE);
+ }
+}
+
+static void
+on_search_box_backward_search (GtkWidget * widget, SearchBox * search_box)
+{
+ SearchBoxPrivate* private = GET_PRIVATE(search_box);
+
+ if (private->highlight_all)
+ {
+ search_box_search_highlight_all (search_box, FALSE);
+ }
+ else
+ {
+ search_box_incremental_search (search_box, FALSE);
+ }
+}
+
+static gboolean
+on_search_box_replace (GtkWidget * widget, SearchBox * search_box)
+{
+
+ IAnjutaEditorSelection* selection;
+ gchar * selection_text;
+ SearchBoxPrivate* private = GET_PRIVATE(search_box);
+
+ const gchar* replace_text = gtk_entry_get_text (GTK_ENTRY (private->replace_entry));
+ const gchar* search_text = gtk_entry_get_text (GTK_ENTRY (private->search_entry));
+
+ selection = IANJUTA_EDITOR_SELECTION (private->current_editor);
+ selection_text = ianjuta_editor_selection_get (selection, NULL);
+
+ /* Replace if the editor has a selection which matches the search_entry */
+ if (ianjuta_editor_selection_has_selection (selection, NULL) &&
+ g_str_equal (selection_text, search_text))
+ {
+ ianjuta_document_begin_undo_action (IANJUTA_DOCUMENT (selection), NULL);
+ ianjuta_editor_selection_replace (selection, replace_text, strlen(replace_text), NULL);
+ ianjuta_document_end_undo_action (IANJUTA_DOCUMENT (selection), NULL);
+ return TRUE;
+ }
+
+ return FALSE;
+
+}
+
+static void
+on_replace_activated (GtkWidget* widget, SearchBox* search_box)
+{
+ gboolean successful_replace;
+
+ SearchBoxPrivate* private = GET_PRIVATE(search_box);
+ const gchar* replace_text = gtk_entry_get_text (GTK_ENTRY (private->replace_entry));
+
+ if (!private->current_editor || !replace_text || !strlen (replace_text))
+ return;
+
+ /* Either replace search-term or try to move search forward to next occurence */
+
+ successful_replace = on_search_box_replace (widget, search_box);
+
+ if (!successful_replace)
+ {
+ on_search_box_forward_search (widget, search_box);
+ }
+}
+
+static void
+do_popup_menu (GtkWidget* widget, GdkEventButton *event, SearchBox* search_box)
+{
+ int button, event_time;
+ SearchBoxPrivate* private = GET_PRIVATE(search_box);
+
+ if (event)
+ {
+ button = event->button;
+ event_time = event->time;
+ }
+ else
+ {
+ button = 0;
+ event_time = gtk_get_current_event_time ();
+ }
+
+ if (!gtk_menu_get_attach_widget(GTK_MENU (private->popup_menu)))
+ gtk_menu_attach_to_widget (GTK_MENU (private->popup_menu), widget, NULL);
+ gtk_menu_popup (GTK_MENU (private->popup_menu), NULL, NULL, NULL, NULL,
+ button, event_time);
+
+}
+
+static gboolean
+on_search_entry_icon_pressed (GtkWidget* widget, GtkEntryIconPosition pos,
+ GdkEvent* event, SearchBox * search_box)
+{
+ do_popup_menu (widget, event, search_box);
+ return TRUE;
+}
+
+static gboolean
+on_search_entry_popup_menu (GtkWidget* widget, SearchBox* search_box)
+{
+ do_popup_menu (widget, NULL, search_box);
+ return TRUE;
+}
+
+static void
+on_replace_all_activated (GtkWidget* widget, SearchBox* search_box)
+{
+
+ SearchBoxPrivate* private = GET_PRIVATE(search_box);
+ const gchar* replace_text = gtk_entry_get_text (GTK_ENTRY (private->replace_entry));
+
+ gboolean entry_found;
+
+ if (!private->current_editor || !replace_text || !strlen (replace_text))
+ return;
+
+ /* Replace all instances of search_entry with replace_entry text */
+ while ((entry_found = search_box_incremental_search (search_box, TRUE)) == TRUE)
+ {
+ on_search_box_replace (widget, search_box);
+ }
+
+}
+
static void
search_box_init (SearchBox *object)
{
@@ -423,35 +662,27 @@ search_box_init (SearchBox *object)
/* Button images */
GtkWidget* close =
gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
- GtkWidget* search =
- gtk_image_new_from_stock (GTK_STOCK_FIND, GTK_ICON_SIZE_SMALL_TOOLBAR);
- GtkWidget* goto_image =
- gtk_image_new_from_stock (ANJUTA_STOCK_GOTO_LINE, GTK_ICON_SIZE_SMALL_TOOLBAR);
/* Searching */
private->search_entry = gtk_entry_new();
g_signal_connect (G_OBJECT (private->search_entry), "activate",
- G_CALLBACK (on_search_activated),
+ G_CALLBACK (on_search_box_forward_search),
object);
g_signal_connect (G_OBJECT (private->search_entry), "key-press-event",
G_CALLBACK (on_entry_key_pressed),
object);
g_signal_connect (G_OBJECT (private->search_entry), "changed",
- G_CALLBACK (on_incremental_search),
+ G_CALLBACK (on_search_box_document_changed),
object);
g_signal_connect (G_OBJECT (private->search_entry), "focus-out-event",
G_CALLBACK (on_search_focus_out),
- object);
-
- private->case_check = gtk_check_button_new_with_label (_("Match case"));
-
- private->search_button = gtk_button_new ();
- gtk_button_set_image (GTK_BUTTON (private->search_button), search);
- gtk_button_set_relief (GTK_BUTTON (private->search_button), GTK_RELIEF_NONE);
- g_signal_connect (G_OBJECT (private->search_button), "clicked",
- G_CALLBACK (on_search_activated),
object);
-
+ g_signal_connect (G_OBJECT (private->search_entry), "icon-press",
+ G_CALLBACK (on_search_entry_icon_pressed),
+ object);
+ g_signal_connect (G_OBJECT (private->search_entry), "popup-menu",
+ G_CALLBACK (on_search_entry_popup_menu),
+ object);
private->close_button = gtk_button_new();
gtk_button_set_image (GTK_BUTTON (private->close_button), close);
@@ -459,34 +690,87 @@ search_box_init (SearchBox *object)
g_signal_connect (G_OBJECT (private->close_button), "clicked",
G_CALLBACK (on_search_box_hide), object);
-
+
+ /* Previous, Next Navigation */
+ private->next_button = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
+ gtk_button_set_relief (GTK_BUTTON (private->next_button), GTK_RELIEF_NONE);
+ g_signal_connect (G_OBJECT(private->next_button), "clicked",
+ G_CALLBACK (on_search_box_forward_search), object);
+ private->previous_button = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
+ gtk_button_set_relief (GTK_BUTTON (private->previous_button), GTK_RELIEF_NONE);
+ g_signal_connect (G_OBJECT(private->previous_button), "clicked",
+ G_CALLBACK (on_search_box_backward_search), object);
+
/* Goto line */
private->goto_entry = gtk_entry_new ();
- gtk_entry_set_width_chars (GTK_ENTRY (private->goto_entry), 5);
+ gtk_entry_set_width_chars (GTK_ENTRY (private->goto_entry), 7);
+ gtk_entry_set_icon_from_stock (GTK_ENTRY (private->goto_entry),
+ GTK_ENTRY_ICON_SECONDARY,
+ ANJUTA_STOCK_GOTO_LINE);
g_signal_connect (G_OBJECT (private->goto_entry), "activate",
G_CALLBACK (on_goto_activated),
object);
g_signal_connect (G_OBJECT (private->goto_entry), "key-press-event",
G_CALLBACK (on_goto_key_pressed),
object);
- private->goto_button = gtk_button_new();
- gtk_button_set_image (GTK_BUTTON (private->goto_button), goto_image);
- gtk_button_set_relief (GTK_BUTTON (private->goto_button), GTK_RELIEF_NONE);
- g_signal_connect (G_OBJECT (private->goto_button), "clicked",
- G_CALLBACK (on_goto_activated),
+ /* Replace */
+ private->replace_entry = gtk_entry_new();
+ g_signal_connect (G_OBJECT (private->replace_entry),
+ "key-press-event", G_CALLBACK (on_entry_key_pressed),
+ object);
+ g_signal_connect (G_OBJECT (private->replace_entry), "activate",
+ G_CALLBACK (on_replace_activated),
object);
-
- gtk_box_pack_start (GTK_BOX (object), private->goto_entry, FALSE, FALSE, 0);
- gtk_box_pack_start (GTK_BOX (object), private->goto_button, FALSE, FALSE, 0);
-
- gtk_box_pack_start (GTK_BOX (object), private->search_entry, TRUE, TRUE, 5);
- gtk_box_pack_start (GTK_BOX (object), private->search_button, FALSE, FALSE, 0);
- gtk_box_pack_start (GTK_BOX (object), private->case_check, FALSE, FALSE, 0);
- gtk_box_pack_end (GTK_BOX (object), private->close_button, FALSE, FALSE, 0);
- gtk_widget_show_all (GTK_WIDGET (object));
+ private->replace_button = gtk_button_new_with_label(_("Replace"));
+ gtk_button_set_relief (GTK_BUTTON (private->replace_button), GTK_RELIEF_NONE);
+ g_signal_connect (G_OBJECT(private->replace_button), "clicked",
+ G_CALLBACK (on_replace_activated), object);
+
+ private->replace_all_button = gtk_button_new_with_label(_("Replace all"));
+ gtk_button_set_relief (GTK_BUTTON (private->replace_all_button), GTK_RELIEF_NONE);
+ g_signal_connect (G_OBJECT(private->replace_all_button), "clicked",
+ G_CALLBACK (on_replace_all_activated), object);
+
+ /* Initialize search_box grid */
+ private->grid = gtk_grid_new();
+ gtk_orientable_set_orientation (GTK_ORIENTABLE (private->grid),
+ GTK_ORIENTATION_VERTICAL);
+ gtk_grid_set_row_spacing (GTK_GRID (private->grid), 5);
+
+ /* Attach search elements to grid */
+ gtk_grid_attach (GTK_GRID (private->grid), private->goto_entry, 0, 0, 1, 1);
+
+ gtk_grid_attach (GTK_GRID (private->grid), private->search_entry, 1, 0, 1, 1);
+
+ gtk_grid_attach (GTK_GRID (private->grid), private->previous_button, 2, 0, 1, 1);
+ gtk_grid_attach (GTK_GRID (private->grid), private->next_button, 3, 0, 1, 1);
+
+ gtk_grid_attach (GTK_GRID (private->grid), private->close_button, 4, 0, 1, 1);
+
+ /* Add Replace elements to search box on 2nd level */
+ gtk_grid_attach (GTK_GRID (private->grid), private->replace_entry, 1, 1, 1, 1);
+ gtk_grid_attach (GTK_GRID (private->grid), private->replace_button, 2, 1, 1, 1);
+ gtk_grid_attach (GTK_GRID (private->grid), private->replace_all_button, 3, 1, 1, 1);
+
+ /* Expand search entries (a bit) */
+ gtk_entry_set_width_chars (GTK_ENTRY (private->search_entry), 60);
+ gtk_entry_set_width_chars (GTK_ENTRY (private->replace_entry), 60);
+
+ /* Set nice icons */
+ gtk_entry_set_icon_from_stock (GTK_ENTRY (private->search_entry),
+ GTK_ENTRY_ICON_PRIMARY,
+ GTK_STOCK_FIND);
+ gtk_entry_set_icon_from_stock (GTK_ENTRY (private->replace_entry),
+ GTK_ENTRY_ICON_PRIMARY,
+ GTK_STOCK_FIND_AND_REPLACE);
+ /* Pack grid into search box */
+ gtk_box_pack_start (GTK_BOX(object), private->grid, TRUE, TRUE, 0);
+ gtk_widget_show_all (GTK_WIDGET (object));
+
private->last_start = NULL;
+
}
static void
@@ -511,21 +795,32 @@ search_box_new (AnjutaDocman *docman)
{
GtkWidget* search_box;
SearchBoxPrivate* private;
+ AnjutaUI *ui;
search_box = GTK_WIDGET (g_object_new (SEARCH_TYPE_BOX, "homogeneous",
FALSE, NULL));
+
g_signal_connect (G_OBJECT (docman), "document-changed",
G_CALLBACK (on_document_changed), search_box);
private = GET_PRIVATE (search_box);
private->status = anjuta_shell_get_status (docman->shell, NULL);
+
+ ui = anjuta_shell_get_ui (docman->shell, NULL);
+ private->popup_menu = gtk_ui_manager_get_widget (GTK_UI_MANAGER (ui),
+ "/SearchboxPopup");
+ g_assert (private->popup_menu != NULL && GTK_IS_MENU (private->popup_menu));
+
+ g_signal_connect (private->popup_menu, "deactivate",
+ G_CALLBACK (gtk_widget_hide), NULL);
return search_box;
}
void
-search_box_fill_search_focus (SearchBox* search_box)
+search_box_fill_search_focus (SearchBox* search_box, gboolean on_replace)
{
+
SearchBoxPrivate* private = GET_PRIVATE(search_box);
IAnjutaEditor* te = private->current_editor;
@@ -539,13 +834,18 @@ search_box_fill_search_focus (SearchBox* search_box)
g_strstrip (buffer);
if (*buffer != 0)
{
+
gtk_entry_set_text (GTK_ENTRY (private->search_entry), buffer);
gtk_editable_select_region (GTK_EDITABLE (private->search_entry), 0, -1);
+
}
g_free (buffer);
}
}
+ /* Toggle replace level (replace entry, replace buttons) of search box */
+ search_box_set_replace (search_box, on_replace);
+
gtk_widget_grab_focus (private->search_entry);
}
@@ -555,3 +855,23 @@ search_box_grab_line_focus (SearchBox* search_box)
SearchBoxPrivate* private = GET_PRIVATE(search_box);
gtk_widget_grab_focus (private->goto_entry);
}
+
+void
+search_box_set_replace (SearchBox* object, gboolean replace)
+{
+
+ SearchBoxPrivate* private = GET_PRIVATE(object);
+
+ if (replace)
+ {
+ gtk_widget_show (private->replace_entry);
+ gtk_widget_show (private->replace_button);
+ gtk_widget_show (private->replace_all_button);
+ }
+ else
+ {
+ gtk_widget_hide (private->replace_entry);
+ gtk_widget_hide (private->replace_button);
+ gtk_widget_hide (private->replace_all_button);
+ }
+}
diff --git a/plugins/document-manager/search-box.h b/plugins/document-manager/search-box.h
index 19b4932..8032e0e 100644
--- a/plugins/document-manager/search-box.h
+++ b/plugins/document-manager/search-box.h
@@ -52,13 +52,17 @@ struct _SearchBox
GtkWidget* new;
};
-
GType search_box_get_type (void);
GtkWidget* search_box_new (AnjutaDocman* docman);
-void search_box_fill_search_focus (SearchBox* search_box);
+void search_box_fill_search_focus (SearchBox* search_box, gboolean on_replace);
void search_box_grab_line_focus (SearchBox* search_box);
-void on_search_activated (GtkWidget* widget, SearchBox* search_box);
+void search_box_set_replace (SearchBox* object, gboolean replace);
+gboolean search_box_incremental_search (SearchBox* search_box, gboolean search_forward);
+
+void search_box_clear_highlight (SearchBox * search_box);
+void search_box_toggle_highlight (SearchBox * search_box, gboolean status);
+void search_box_toggle_case_sensitive (SearchBox * search_box, gboolean status);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]