Improved searching
This commit is contained in:
parent
8ab4125290
commit
53276e8a54
|
@ -1,4 +1,5 @@
|
|||
#include <gdk/gdkkeysyms.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../gm-app.h"
|
||||
#include "gm-world-view.h"
|
||||
|
@ -6,12 +7,16 @@
|
|||
#include "gm-world-input-view.h"
|
||||
#include "gm-text-scroller.h"
|
||||
#include "gm-editor-view.h"
|
||||
#include "gm-embedded-view.h"
|
||||
#include "gm-external-view.h"
|
||||
|
||||
#include "../gm-debug.h"
|
||||
#include "../gm-support.h"
|
||||
#include "../gm-color-table.h"
|
||||
#include "../mcp/gm-mcp-package.h"
|
||||
#include "../mcp/gm-mcp-session.h"
|
||||
#include "../gm-editor.h"
|
||||
#include "gm-searchable.h"
|
||||
|
||||
#define GM_WORLD_VIEW_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), \
|
||||
GM_TYPE_WORLD_VIEW, GmWorldViewPrivate))
|
||||
|
@ -24,6 +29,8 @@ struct _GmWorldViewPrivate {
|
|||
GmWorldTextView *text_view_world;
|
||||
GmWorldInputView *text_view_input;
|
||||
GmTextScroller *text_scroller_world;
|
||||
|
||||
GList *external_editors;
|
||||
};
|
||||
|
||||
void on_gm_world_view_world_text_received(GmWorld *world, gchar *text,
|
||||
|
@ -51,24 +58,54 @@ gboolean on_gm_world_view_world_text_view_scroll_event(GmWorldView *view,
|
|||
GdkEventScroll *event, GmWorldTextView *text);
|
||||
void on_gm_world_view_world_text_view_url_activate(GmWorldView *view,
|
||||
gchar const *url);
|
||||
|
||||
void on_gm_world_view_editor_view_close_clicked(GtkButton *button,
|
||||
GtkWidget *view);
|
||||
|
||||
gboolean on_gm_world_view_world_input_view_key_pressed(GtkWidget *widget,
|
||||
GdkEventKey *event, GmWorldView *view);
|
||||
|
||||
/* Signals */
|
||||
|
||||
/* Signals
|
||||
|
||||
/*enum {
|
||||
NUM_SIGNALS
|
||||
enum {
|
||||
NUM_SIGNALS
|
||||
};
|
||||
|
||||
static guint world_view_signals[NUM_SIGNALS] = {0};*/
|
||||
static guint gm_world_view_signals[NUM_SIGNALS] = {0};*/
|
||||
|
||||
G_DEFINE_TYPE(GmWorldView, gm_world_view, GTK_TYPE_NOTEBOOK)
|
||||
static void gm_world_view_searchable_iface_init(
|
||||
GmSearchableInterface *iface);
|
||||
|
||||
static GtkTextView *gm_world_view_searchable_get_text_view(GmSearchable *sea);
|
||||
|
||||
G_DEFINE_TYPE_EXTENDED(GmWorldView, gm_world_view, GTK_TYPE_NOTEBOOK, 0, \
|
||||
G_IMPLEMENT_INTERFACE(GM_TYPE_SEARCHABLE, \
|
||||
gm_world_view_searchable_iface_init))
|
||||
|
||||
static void
|
||||
gm_world_view_searchable_iface_init(GmSearchableInterface *iface) {
|
||||
iface->get_text_view = gm_world_view_searchable_get_text_view;
|
||||
}
|
||||
|
||||
static GtkTextView *
|
||||
gm_world_view_searchable_get_text_view(GmSearchable *sea) {
|
||||
GmWorldView *view = (GmWorldView *)(sea);
|
||||
|
||||
g_return_val_if_fail(GM_IS_WORLD_VIEW(sea), NULL);
|
||||
|
||||
return GTK_TEXT_VIEW(view->priv->text_view_world);
|
||||
}
|
||||
|
||||
static void
|
||||
gm_world_view_finalize(GObject *object) {
|
||||
GmWorldView *view = GM_WORLD_VIEW(object);
|
||||
|
||||
GList *ext;
|
||||
|
||||
for (ext = view->priv->external_editors; ext; ext = ext->next) {
|
||||
gm_external_view_destroy(GM_EXTERNAL_VIEW(ext->data));
|
||||
}
|
||||
|
||||
g_list_free(view->priv->external_editors);
|
||||
|
||||
g_signal_handlers_disconnect_by_func(view->priv->world,
|
||||
G_CALLBACK(on_gm_world_view_world_text_received), view);
|
||||
g_signal_handlers_disconnect_by_func(view->priv->world,
|
||||
|
@ -95,7 +132,7 @@ gm_world_view_class_init(GmWorldViewClass *klass) {
|
|||
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
object_class->finalize = gm_world_view_finalize;
|
||||
|
||||
|
||||
g_type_class_add_private(object_class, sizeof(GmWorldViewPrivate));
|
||||
}
|
||||
|
||||
|
@ -158,34 +195,74 @@ gm_world_view_update_status(GmWorldView *view, gchar const *status) {
|
|||
}
|
||||
}
|
||||
|
||||
GmEditorView *
|
||||
GtkWidget *
|
||||
gm_world_view_log_page_new(GmWorldView *view, gchar const *filename) {
|
||||
/*GtkWidget *label;
|
||||
GmLabelInfo info;
|
||||
GtkWidget *scrolled_window = gtk_scrolled_window_new();
|
||||
GtkWidget *text_view;
|
||||
|
||||
label = gm_create_tab_label("editor_text.xpm", */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gm_world_view_editor_create_view(GmWorldView *view, GmEditor *editor) {
|
||||
GtkWidget *editor_view;
|
||||
GmOptions *options = gm_app_options(gm_app_instance());
|
||||
if (strcmp(gm_options_get(options, "editor_alternative"),
|
||||
"0") != 0) {
|
||||
if (gm_options_get_int(options, "editor_embed")) {
|
||||
editor_view = GTK_WIDGET(gm_embedded_view_new(view->priv->world,
|
||||
editor));
|
||||
} else {
|
||||
view->priv->external_editors = g_list_append(
|
||||
view->priv->external_editors,
|
||||
gm_external_view_new(view->priv->world, editor));
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
editor_view = GTK_WIDGET(gm_editor_view_new(view->priv->world, editor));
|
||||
g_signal_connect(editor_view, "modified-changed",
|
||||
G_CALLBACK(on_gm_world_view_editor_view_modified_changed),
|
||||
view);
|
||||
}
|
||||
|
||||
gtk_widget_show(editor_view);
|
||||
return editor_view;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gm_world_view_editor_page_new(GmWorldView *view, GmEditor *editor) {
|
||||
GmEditorView *editor_view = gm_editor_view_new(view->priv->world, editor);
|
||||
GtkWidget *label;
|
||||
GtkWidget *editor_view;
|
||||
|
||||
GmLabelInfo info;
|
||||
gchar const *icon;
|
||||
|
||||
|
||||
if (gm_editor_is_code(editor)) {
|
||||
icon = "editor_verb.xpm";
|
||||
} else {
|
||||
icon = "editor_text.xpm";
|
||||
}
|
||||
|
||||
gtk_widget_show(GTK_WIDGET(editor_view));
|
||||
label = gm_create_tab_label("editor_verb.xpm", gm_editor_name(editor),
|
||||
TRUE, &info);
|
||||
gtk_notebook_append_page(GTK_NOTEBOOK(view), GTK_WIDGET(editor_view),
|
||||
label);
|
||||
|
||||
editor_view = gm_world_view_editor_create_view(view, editor);
|
||||
|
||||
if (editor_view == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gtk_notebook_append_page(GTK_NOTEBOOK(view), editor_view, label);
|
||||
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(view), TRUE);
|
||||
gtk_notebook_set_current_page(GTK_NOTEBOOK(view),
|
||||
gtk_notebook_page_num(GTK_NOTEBOOK(view),
|
||||
GTK_WIDGET(editor_view)));
|
||||
gtk_notebook_page_num(GTK_NOTEBOOK(view), editor_view));
|
||||
|
||||
GM_DEBUG("Connecting modified changed!!!");
|
||||
|
||||
g_signal_connect(editor_view, "modified-changed",
|
||||
G_CALLBACK(on_gm_world_view_editor_view_modified_changed),
|
||||
view);
|
||||
g_signal_connect(info.button_exit, "clicked",
|
||||
G_CALLBACK(on_gm_world_view_editor_view_close_clicked),
|
||||
editor_view);
|
||||
|
||||
return editor_view;
|
||||
}
|
||||
|
@ -289,83 +366,6 @@ gm_world_view_new(GmWorld *world) {
|
|||
return GTK_WIDGET(view);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gm_world_view_find_first(GmWorldView *view, const gchar *str,
|
||||
GmWorldViewSearchFlags flags) {
|
||||
GtkTextView *tview = GTK_TEXT_VIEW(view->priv->text_view_world);
|
||||
GtkTextIter iter;
|
||||
GtkTextBuffer *buffer;
|
||||
|
||||
if (tview) {
|
||||
buffer = gtk_text_view_get_buffer(tview);
|
||||
|
||||
if (buffer) {
|
||||
if (flags & GM_WORLD_VIEW_SEARCH_BACKWARDS) {
|
||||
gtk_text_buffer_get_end_iter(buffer, &iter);
|
||||
} else {
|
||||
gtk_text_buffer_get_start_iter(buffer, &iter);
|
||||
}
|
||||
|
||||
gtk_text_buffer_place_cursor(buffer, &iter);
|
||||
|
||||
return gm_world_view_find_next(view, str, flags);
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gm_world_view_find_next(GmWorldView *view, const gchar *str,
|
||||
GmWorldViewSearchFlags flags) {
|
||||
GtkTextBuffer *buffer = NULL;
|
||||
GtkTextView *tview = NULL;
|
||||
GtkTextIter end, start, matchStart, matchEnd;
|
||||
gboolean found = FALSE;
|
||||
|
||||
if (*str == '\0') {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
tview = GTK_TEXT_VIEW(view->priv->text_view_world);
|
||||
|
||||
if (tview) {
|
||||
buffer = gtk_text_view_get_buffer(tview);
|
||||
}
|
||||
|
||||
if (buffer) {
|
||||
if (!gtk_text_buffer_get_selection_bounds(buffer, &start, &end)) {
|
||||
if (flags & GM_WORLD_VIEW_SEARCH_BACKWARDS) {
|
||||
gtk_text_buffer_get_end_iter(buffer, &end);
|
||||
} else {
|
||||
gtk_text_buffer_get_start_iter(buffer, &end);
|
||||
}
|
||||
|
||||
start = end;
|
||||
}
|
||||
|
||||
if (flags & GM_WORLD_VIEW_SEARCH_FORWARDS) {
|
||||
found = gtk_text_iter_forward_search(&end, str,
|
||||
GTK_TEXT_SEARCH_VISIBLE_ONLY | GTK_TEXT_SEARCH_TEXT_ONLY,
|
||||
&matchStart, &matchEnd, NULL);
|
||||
} else {
|
||||
found = gtk_text_iter_backward_search(&start, str,
|
||||
GTK_TEXT_SEARCH_VISIBLE_ONLY | GTK_TEXT_SEARCH_TEXT_ONLY,
|
||||
&matchStart, &matchEnd, NULL);
|
||||
}
|
||||
|
||||
if (found) {
|
||||
gtk_text_buffer_place_cursor(buffer, &matchStart);
|
||||
gtk_text_buffer_move_mark_by_name(buffer, "selection_bound",
|
||||
&matchEnd);
|
||||
gtk_text_view_scroll_to_iter(tview, &matchStart,
|
||||
0.0, FALSE, 0.0, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gm_world_view_text_active(GmWorldView *view) {
|
||||
return gtk_notebook_get_current_page(GTK_NOTEBOOK(view)) == 0;
|
||||
|
@ -381,6 +381,82 @@ gm_world_view_scroll_end(GmWorldView *view) {
|
|||
// TODO
|
||||
}
|
||||
|
||||
gboolean
|
||||
gm_world_view_page_can_find(GmWorldView *view, gint page_num) {
|
||||
GtkWidget *page;
|
||||
GmSearchable *sea;
|
||||
|
||||
if (page_num == -1) {
|
||||
return FALSE;
|
||||
} else if (page_num == 0) {
|
||||
return gm_searchable_can_find(GM_SEARCHABLE(view));
|
||||
} else {
|
||||
page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(view), page_num);
|
||||
|
||||
if (GM_IS_SEARCHABLE(page)) {
|
||||
sea = GM_SEARCHABLE(page);
|
||||
|
||||
return gm_searchable_can_find(sea);
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gm_world_view_can_find(GmWorldView *view) {
|
||||
gint np = gtk_notebook_get_current_page(GTK_NOTEBOOK(view));
|
||||
return gm_world_view_page_can_find(view, np);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gm_world_view_find_first(GmWorldView *view, const gchar *str,
|
||||
GmSearchableSearchFlags flags) {
|
||||
gint np = gtk_notebook_get_current_page(GTK_NOTEBOOK(view));
|
||||
GtkWidget *page;
|
||||
GmSearchable *sea;
|
||||
|
||||
if (np == 0) {
|
||||
return gm_searchable_find_first(GM_SEARCHABLE(view), str, flags);
|
||||
} else {
|
||||
page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(view), np);
|
||||
|
||||
if (GM_IS_SEARCHABLE(page)) {
|
||||
sea = GM_SEARCHABLE(page);
|
||||
|
||||
if (gm_searchable_can_find(sea)) {
|
||||
return gm_searchable_find_first(sea, str, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gm_world_view_find_next(GmWorldView *view, const gchar *str,
|
||||
GmSearchableSearchFlags flags) {
|
||||
gint np = gtk_notebook_get_current_page(GTK_NOTEBOOK(view));
|
||||
GtkWidget *page;
|
||||
GmSearchable *sea;
|
||||
|
||||
if (np == 0) {
|
||||
return gm_searchable_find_next(GM_SEARCHABLE(view), str, flags);
|
||||
} else {
|
||||
page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(view), np);
|
||||
|
||||
if (GM_IS_SEARCHABLE(page)) {
|
||||
sea = GM_SEARCHABLE(page);
|
||||
|
||||
if (gm_searchable_can_find(sea)) {
|
||||
return gm_searchable_find_next(sea, str, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GmWorld *
|
||||
gm_world_view_world(GmWorldView *view) {
|
||||
return view->priv->world;
|
||||
|
@ -408,7 +484,7 @@ gm_world_view_hpaned(GmWorldView *view) {
|
|||
|
||||
void
|
||||
gm_world_view_open_log(GmWorldView *view, const gchar *filename) {
|
||||
// TODO: open log
|
||||
gm_world_view_log_page_new(view, filename);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -463,6 +539,18 @@ on_gm_world_view_editor_save(GmEditor *editor, GmWorldView *view) {
|
|||
gtk_widget_grab_focus(GTK_WIDGET(view->priv->text_view_input));
|
||||
}
|
||||
|
||||
void
|
||||
on_gm_world_view_editor_view_close_clicked(GtkButton *button,
|
||||
GtkWidget *view) {
|
||||
// TODO: make this into an interface
|
||||
if (GM_IS_EDITOR_VIEW(view)) {
|
||||
gm_editor_close(gm_editor_view_editor(GM_EDITOR_VIEW(view)));
|
||||
} else if (GM_IS_EMBEDDED_VIEW(view)) {
|
||||
gm_editor_close(gm_embedded_view_editor(GM_EMBEDDED_VIEW(view)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
on_gm_world_view_editor_view_modified_changed(GmEditorView *editor_view,
|
||||
gboolean modified, GmWorldView *view) {
|
||||
|
@ -508,19 +596,40 @@ on_gm_world_view_world_editor_removed(GmWorld *world, GmEditor *editor,
|
|||
GmWorldView *view) {
|
||||
gint i, n = gtk_notebook_get_n_pages(GTK_NOTEBOOK(view));
|
||||
GtkWidget *page;
|
||||
gboolean found = FALSE;
|
||||
GList *ext;
|
||||
|
||||
for (i = 1; i < n; ++i) {
|
||||
page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(view), i);
|
||||
found = GM_IS_EDITOR_VIEW(page) && gm_editor_view_editor(
|
||||
GM_EDITOR_VIEW(page)) == editor;
|
||||
found = found || (GM_IS_EMBEDDED_VIEW(page) && gm_embedded_view_editor(
|
||||
GM_EMBEDDED_VIEW(page)) == editor);
|
||||
|
||||
if (GM_IS_EDITOR_VIEW(page) && gm_editor_view_editor(
|
||||
GM_EDITOR_VIEW(page)) == editor) {
|
||||
|
||||
if (found) {
|
||||
g_signal_handlers_disconnect_by_func(editor,
|
||||
on_gm_world_view_editor_save, view);
|
||||
gtk_widget_destroy(page);
|
||||
|
||||
gtk_notebook_set_current_page(GTK_NOTEBOOK(view), 0);
|
||||
gtk_widget_grab_focus(GTK_WIDGET(view->priv->text_view_input));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
// Might be an external editor?
|
||||
for (ext = view->priv->external_editors; ext; ext = ext->next) {
|
||||
if ((GM_EXTERNAL_VIEW(ext->data))->editor == editor) {
|
||||
g_signal_handlers_disconnect_by_func(editor,
|
||||
on_gm_world_view_editor_save, view);
|
||||
gm_external_view_destroy(GM_EXTERNAL_VIEW(ext->data));
|
||||
|
||||
view->priv->external_editors =
|
||||
g_list_remove_link(view->priv->external_editors, ext);
|
||||
g_list_free_1(ext);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Reference in New Issue