This repository has been archived on 2020-04-11. You can view files and clone it, but cannot push or open issues or pull requests.
gnoemoe/gnoemoe/widgets/gm-world-view.c

995 lines
28 KiB
C

#include <gdk/gdkkeysyms.h>
#include <string.h>
#include "gm-app.h"
#include "gm-world-view.h"
#include "gm-world-text-view.h"
#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-log-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))
struct _GmWorldViewPrivate {
GmWorld *world;
GtkStatusbar *statusbar;
GtkHPaned *hpaned;
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,
GmWorldView *view);
void on_gm_world_view_world_error(GmWorld *world, gchar *text, gint code,
GmWorldView *view);
void on_gm_world_input_view_world_text_activate(GmWorldInputView *iview,
gchar *text, GmWorldView *view);
void on_gm_world_view_world_state_changing(GmWorld *world, guint state,
GmWorldView *view);
void on_gm_world_view_world_active_changed(GmWorld *world, GParamSpec *pspec,
GmWorldView *view);
void on_gm_world_view_world_highlight(GmWorld *world, gint start, gint end,
gchar *color, GmWorldView *view);
void on_gm_world_view_world_editor_added(GmWorld *world, GmEditor *editor,
GmWorldView *view);
void on_gm_world_view_world_editor_removed(GmWorld *world, GmEditor *editor,
GmWorldView *view);
void on_gm_world_view_world_mcp_package_created(GmMcpSession *session,
GmMcpPackage *package, GmWorldView *view);
void on_gm_world_view_editor_view_modified_changed(GmEditorView *editor_view,
gboolean modified, GmWorldView *view);
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);
void on_gm_world_view_log_view_close_clicked(GtkButton *button,
GtkWidget *view);
gboolean on_gm_world_view_world_input_view_key_pressed(GtkWidget *widget,
GdkEventKey *event, GmWorldView *view);
/* Signals
enum {
NUM_SIGNALS
};
static guint gm_world_view_signals[NUM_SIGNALS] = {0};*/
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,
G_CALLBACK(on_gm_world_view_world_error), view);
g_signal_handlers_disconnect_by_func(view->priv->world,
G_CALLBACK(on_gm_world_view_world_state_changing), view);
g_signal_handlers_disconnect_by_func(view->priv->world,
G_CALLBACK(on_gm_world_view_world_active_changed), view);
g_signal_handlers_disconnect_by_func(view->priv->world,
G_CALLBACK(on_gm_world_view_world_highlight), view);
g_signal_handlers_disconnect_by_func(view->priv->world,
G_CALLBACK(on_gm_world_view_world_editor_added), view);
g_signal_handlers_disconnect_by_func(view->priv->world,
G_CALLBACK(on_gm_world_view_world_editor_removed), view);
g_signal_handlers_disconnect_by_func(
gm_world_get_mcp_session(view->priv->world),
G_CALLBACK(on_gm_world_view_world_mcp_package_created), view);
g_object_unref(view->priv->world);
G_OBJECT_CLASS(gm_world_view_parent_class)->finalize(object);
}
static void
gm_world_view_destroy(GtkObject *object) {
GmWorldView *view = GM_WORLD_VIEW(object);
gm_options_set_int(gm_world_options(view->priv->world), "pane_position",
GTK_WIDGET(view->priv->hpaned)->allocation.width -
gtk_paned_get_position(GTK_PANED(view->priv->hpaned)));
gm_options_save(gm_world_options(view->priv->world));
if (GTK_OBJECT_CLASS(gm_world_view_parent_class)->destroy) {
GTK_OBJECT_CLASS(gm_world_view_parent_class)->destroy(object);
}
}
static gboolean
gm_world_view_input_grab_focus(GmWorldView *view) {
gtk_widget_grab_focus(GTK_WIDGET(view->priv->text_view_input));
return FALSE;
}
static void
gm_world_view_switch_page(GtkNotebook *notebook, GtkNotebookPage *page,
guint page_num) {
if (GTK_NOTEBOOK_CLASS(gm_world_view_parent_class)->switch_page) {
GTK_NOTEBOOK_CLASS(gm_world_view_parent_class)->switch_page(notebook, page, page_num);
}
if (page_num == 0) {
g_idle_add((GSourceFunc)gm_world_view_input_grab_focus,
GM_WORLD_VIEW(notebook));
}
}
static void
gm_world_view_remove_page(GtkContainer *container, GtkWidget *page) {
GtkNotebook *notebook = GTK_NOTEBOOK(container);
if (GTK_CONTAINER_CLASS(gm_world_view_parent_class)->remove) {
GTK_CONTAINER_CLASS(gm_world_view_parent_class)->remove(container, page);
}
if (gtk_notebook_get_n_pages(notebook) == 1) {
gtk_notebook_set_show_tabs(notebook, FALSE);
}
}
static void
gm_world_view_show(GtkWidget *widget) {
GmWorldView *view = GM_WORLD_VIEW(widget);
if (GTK_WIDGET_CLASS(gm_world_view_parent_class)->show) {
GTK_WIDGET_CLASS(gm_world_view_parent_class)->show(widget);
}
gm_do_events();
gtk_paned_set_position(GTK_PANED(view->priv->hpaned),
GTK_WIDGET(view->priv->hpaned)->allocation.width
- gm_options_get_int(gm_world_options(view->priv->world),
"pane_position"));
}
static void
gm_world_view_class_init(GmWorldViewClass *klass) {
GObjectClass *object_class = G_OBJECT_CLASS(klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS(klass);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS(klass);
object_class->finalize = gm_world_view_finalize;
widget_class->show = gm_world_view_show;
gtk_object_class->destroy = gm_world_view_destroy;
GTK_NOTEBOOK_CLASS(klass)->switch_page = gm_world_view_switch_page;
container_class->remove = gm_world_view_remove_page;
g_type_class_add_private(object_class, sizeof(GmWorldViewPrivate));
}
static void
gm_world_view_ensure_show_tabs(GmWorldView *view) {
if (!gtk_notebook_get_show_tabs(GTK_NOTEBOOK(view))) {
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(view), TRUE);
}
}
/*gboolean
timeout_text(gpointer user_data) {
GtkTextView *view = GTK_TEXT_VIEW(user_data);
GtkTextBuffer *buffer = gtk_text_view_get_buffer(view);
GtkTextIter end, start;
static GdkEvent *event_press = NULL;
static GdkEvent *event_release = NULL;
gboolean result;
gtk_text_buffer_get_bounds(buffer, &start, &end);
if (gtk_text_iter_get_offset(&end) > 80) {
gtk_text_buffer_delete(buffer, &start, &end);
} else {
if (!event_press) {
gtk_widget_realize(GTK_WIDGET(view));
event_press = gdk_event_new(GDK_KEY_PRESS);
event_press->key.keyval = 119;
event_press->key.window = gtk_text_view_get_window(view, GTK_TEXT_WINDOW_TEXT);
event_release = gdk_event_new(GDK_KEY_RELEASE);
event_release->key.keyval = 119;
event_release->key.window = event_press->key.window;
}
event_press->key.time = gtk_get_current_event_time();
event_release->key.time = gtk_get_current_event_time();
g_signal_emit_by_name(GTK_WIDGET(view), "key_press_event", event_press, &result);
g_signal_emit_by_name(GTK_WIDGET(view), "key_release_event", event_release, &result);
}
return TRUE;
}*/
GtkWidget *
gm_world_view_create_input_text_view(GmWorldView *view) {
GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL);
GtkWidget *input_text_view = gm_world_input_view_new_with_color_table(
gm_app_color_table(gm_app_instance()));
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
GTK_POLICY_NEVER, GTK_POLICY_NEVER);
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window),
GTK_SHADOW_IN);
gtk_container_add(GTK_CONTAINER(scrolled_window), input_text_view);
view->priv->text_view_input = GM_WORLD_INPUT_VIEW(input_text_view);
g_signal_connect(input_text_view, "key_press_event",
G_CALLBACK(on_gm_world_view_world_input_view_key_pressed), view);
return scrolled_window;
}
GtkWidget *
gm_world_view_create_world_text_view(GmWorldView *view) {
GtkWidget *world_text_view = gm_world_text_view_new_with_color_table(
gm_app_color_table(gm_app_instance()));
GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window),
GTK_SHADOW_IN);
gtk_container_add(GTK_CONTAINER(scrolled_window), world_text_view);
view->priv->text_view_world = GM_WORLD_TEXT_VIEW(world_text_view);
// Create new text scroller, this object will take care of itself and will
// destroy itself when the view dies, neat!
view->priv->text_scroller_world =
gm_text_scroller_new(GTK_TEXT_VIEW(view->priv->text_view_world));
g_signal_connect(world_text_view, "scroll_event",
G_CALLBACK(on_gm_world_view_world_text_view_scroll_event), view);
g_signal_connect(world_text_view, "url_activate",
G_CALLBACK(on_gm_world_view_world_text_view_url_activate), view);
return scrolled_window;
}
void
gm_world_view_update_status(GmWorldView *view, gchar const *status) {
gtk_statusbar_pop(view->priv->statusbar, 0);
if (status == NULL) {
gtk_statusbar_push(view->priv->statusbar, 0,
_("Welcome to GnoeMoe, explorer of new worlds!"));
} else {
gtk_statusbar_push(view->priv->statusbar, 0,
status);
}
}
GtkWidget *
gm_world_view_log_page_new(GmWorldView *view, gchar const *filename) {
gchar *text = gm_read_file(filename);
gchar *base;
GmLabelInfo info;
GtkWidget *log_view;
GtkWidget *label;
if (text == NULL) {
return NULL;
}
base = g_path_get_basename(filename);
label = gm_create_tab_label("editor_text.xpm", base, TRUE, &info);
g_free(base);
log_view = GTK_WIDGET(gm_log_view_new());
gtk_widget_show(log_view);
gtk_notebook_append_page(GTK_NOTEBOOK(view), log_view, label);
gm_world_view_ensure_show_tabs(view);
gtk_notebook_set_current_page(GTK_NOTEBOOK(view),
gtk_notebook_page_num(GTK_NOTEBOOK(view), log_view));
g_signal_connect(info.button_exit, "clicked",
G_CALLBACK(on_gm_world_view_log_view_close_clicked),
log_view);
gm_log_view_set_text(GM_LOG_VIEW(log_view), text);
g_free(text);
return log_view;
}
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) {
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";
}
label = gm_create_tab_label("editor_verb.xpm", gm_editor_name(editor),
TRUE, &info);
editor_view = gm_world_view_editor_create_view(view, editor);
if (editor_view == NULL) {
return NULL;
}
gm_world_view_ensure_show_tabs(view);
gtk_notebook_append_page(GTK_NOTEBOOK(view), editor_view, label);
gtk_notebook_set_current_page(GTK_NOTEBOOK(view),
gtk_notebook_page_num(GTK_NOTEBOOK(view), editor_view));
g_signal_connect(info.button_exit, "clicked",
G_CALLBACK(on_gm_world_view_editor_view_close_clicked),
editor_view);
return editor_view;
}
GtkWidget *
gm_world_view_world_page_new(GmWorldView *view) {
GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
GtkWidget *hpaned = gtk_hpaned_new();
GtkWidget *status = gtk_statusbar_new();
GtkWidget *vbox_world = gtk_vbox_new(FALSE, 3);
gtk_box_pack_start(GTK_BOX(vbox_world),
gm_world_view_create_world_text_view(view), TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox_world),
gm_world_view_create_input_text_view(view), FALSE, FALSE, 0);
gtk_container_set_border_width(GTK_CONTAINER(vbox_world), 3);
gtk_paned_pack1(GTK_PANED(hpaned), vbox_world, TRUE, TRUE);
gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(status), FALSE);
gtk_box_pack_start(GTK_BOX(vbox), hpaned, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox), status, FALSE, FALSE, 0);
view->priv->statusbar = GTK_STATUSBAR(status);
view->priv->hpaned = GTK_HPANED(hpaned);
gm_world_view_update_status(view, NULL);
return vbox;
}
static void
gm_world_view_init(GmWorldView *view) {
GtkWidget *label;
GmLabelInfo info;
view->priv = GM_WORLD_VIEW_GET_PRIVATE(view);
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(view), FALSE);
gtk_notebook_set_show_border(GTK_NOTEBOOK(view), FALSE);
gtk_notebook_set_tab_pos(GTK_NOTEBOOK(view), GTK_POS_BOTTOM);
gtk_notebook_set_scrollable(GTK_NOTEBOOK(view), TRUE);
label = gm_create_tab_label("world.svg", _("World"), FALSE, &info);
gtk_notebook_append_page(GTK_NOTEBOOK(view),
gm_world_view_world_page_new(view), label);
}
GtkWidget *
gm_world_view_new(GmWorld *world) {
GmWorldView *view = GM_WORLD_VIEW(g_object_new(GM_TYPE_WORLD_VIEW, NULL));
view->priv->world = g_object_ref(world);
gm_world_input_view_set_history(view->priv->text_view_input,
gm_world_history(view->priv->world));
g_signal_connect(world, "text_received",
G_CALLBACK(on_gm_world_view_world_text_received), view);
g_signal_connect(world, "world_error",
G_CALLBACK(on_gm_world_view_world_error), view);
g_signal_connect(world, "state_changing",
G_CALLBACK(on_gm_world_view_world_state_changing), view);
g_signal_connect(world, "notify::active",
G_CALLBACK(on_gm_world_view_world_active_changed), view);
g_signal_connect(world, "highlight",
G_CALLBACK(on_gm_world_view_world_highlight), view);
g_signal_connect(world, "editor_added",
G_CALLBACK(on_gm_world_view_world_editor_added), view);
g_signal_connect(world, "editor_removed",
G_CALLBACK(on_gm_world_view_world_editor_removed), view);
g_signal_connect(gm_world_get_mcp_session(world), "package_created",
G_CALLBACK(on_gm_world_view_world_mcp_package_created), view);
g_signal_connect(view->priv->text_view_input, "text_activate",
G_CALLBACK(on_gm_world_input_view_world_text_activate), view);
return GTK_WIDGET(view);
}
gboolean
gm_world_view_text_active(GmWorldView *view) {
return gtk_notebook_get_current_page(GTK_NOTEBOOK(view)) == 0;
}
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;
}
gboolean
gm_world_view_replace(GmWorldView *view, gchar const *replace) {
gint np = gtk_notebook_get_current_page(GTK_NOTEBOOK(view));
GtkWidget *page;
GmSearchable *sea;
if (np == 0) {
return FALSE;
} else {
page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(view), np);
if (GM_IS_SEARCHABLE(page)) {
sea = GM_SEARCHABLE(page);
if (gm_searchable_can_replace(sea)) {
return gm_searchable_replace(sea, replace);
}
}
}
return FALSE;
}
gboolean
gm_world_view_replace_all(GmWorldView *view, gchar const *str,
gchar const *replace, GmSearchableSearchFlags flags) {
gint np = gtk_notebook_get_current_page(GTK_NOTEBOOK(view));
GtkWidget *page;
GmSearchable *sea;
if (np == 0) {
return FALSE;
} else {
page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(view), np);
if (GM_IS_SEARCHABLE(page)) {
sea = GM_SEARCHABLE(page);
if (gm_searchable_can_replace(sea)) {
return gm_searchable_replace_all(sea, str, replace, flags);
}
}
}
return FALSE;
}
gboolean
gm_world_view_can_replace(GmWorldView *view) {
gint np = gtk_notebook_get_current_page(GTK_NOTEBOOK(view));
return gm_world_view_page_can_replace(view, np);
}
gboolean
gm_world_view_page_can_replace(GmWorldView *view, gint page_num) {
GtkWidget *page;
GmSearchable *sea;
if (page_num == -1) {
return FALSE;
} else if (page_num == 0) {
return gm_searchable_can_replace(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_replace(sea);
}
}
return FALSE;
}
GmWorld *
gm_world_view_world(GmWorldView *view) {
return view->priv->world;
}
GmWorldInputView *
gm_world_view_input(GmWorldView *view) {
return view->priv->text_view_input;
}
GmWorldTextView *
gm_world_view_text_view(GmWorldView *view) {
return view->priv->text_view_world;
}
GtkTextBuffer *
gm_world_view_buffer(GmWorldView *view) {
return gtk_text_view_get_buffer(GTK_TEXT_VIEW(view->priv->text_view_world));
}
GtkHPaned *
gm_world_view_hpaned(GmWorldView *view) {
return view->priv->hpaned;
}
void
gm_world_view_open_log(GmWorldView *view, const gchar *filename) {
gm_world_view_log_page_new(view, filename);
}
void
gm_world_view_set_userlist_width(GmWorldView *view, gint width) {
gtk_paned_set_position(GTK_PANED(view->priv->hpaned),
GTK_WIDGET(view->priv->hpaned)->allocation.width - width);
}
void
gm_world_view_set_focus(GmWorldView *view) {
gtk_widget_grab_focus(GTK_WIDGET(view->priv->text_view_input));
}
void
gm_world_view_change_font_size(GmWorldView *view, gint size_change) {
GtkStyle *style = gtk_widget_get_style(GTK_WIDGET(view));
PangoFontDescription *desc = style->font_desc;
PangoFontDescription *copy = pango_font_description_copy(desc);
gchar *new_font;
pango_font_description_set_size(copy,
pango_font_description_get_size(copy) +
(size_change * PANGO_SCALE));
new_font = pango_font_description_to_string(copy);
gm_color_table_set_font_description(gm_app_color_table(gm_app_instance()),
new_font);
pango_font_description_free(copy);
g_free(new_font);
}
/* Callbacks */
void
on_gm_world_input_view_world_text_activate(GmWorldInputView *iview, gchar *text,
GmWorldView *view) {
gm_world_process_input(view->priv->world, text);
gm_text_scroller_scroll_end(view->priv->text_scroller_world);
}
void
on_gm_world_view_world_text_received(GmWorld *world, gchar *text,
GmWorldView *view) {
gchar *inserted =
gm_world_text_view_insert(view->priv->text_view_world, text);
g_free(inserted);
}
void
on_gm_world_view_editor_save(GmEditor *editor, GmWorldView *view) {
gtk_notebook_set_current_page(GTK_NOTEBOOK(view), 0);
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_log_view_close_clicked(GtkButton *button,
GtkWidget *view) {
gtk_widget_destroy(view);
}
void
on_gm_world_view_editor_view_modified_changed(GmEditorView *editor_view,
gboolean modified, GmWorldView *view) {
gint i, n = gtk_notebook_get_n_pages(GTK_NOTEBOOK(view));
GtkWidget *page;
GtkLabel *label;
gchar *str;
// Find this view then
for (i = 1; i < n; ++i) {
page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(view), i);
if (GM_IS_EDITOR_VIEW(page) && GM_EDITOR_VIEW(page) == editor_view) {
label = GTK_LABEL(gm_container_item(GTK_CONTAINER(
gtk_notebook_get_tab_label(GTK_NOTEBOOK(view), page)),
GTK_TYPE_LABEL));
if (!modified) {
gtk_label_set_label(label,
gm_editor_name(gm_editor_view_editor(
GM_EDITOR_VIEW(page))));
} else {
str = g_strconcat(gm_editor_name(gm_editor_view_editor(
GM_EDITOR_VIEW(page))), "*", NULL);
gtk_label_set_label(label, str);
g_free(str);
}
}
}
}
void
on_gm_world_view_world_editor_added(GmWorld *world, GmEditor *editor,
GmWorldView *view) {
gm_world_view_editor_page_new(view, editor);
g_signal_connect(editor, "save",
G_CALLBACK(on_gm_world_view_editor_save), view);
}
void
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 (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;
}
}
}
}
void
on_gm_world_view_world_error(GmWorld *world, gchar *text, gint code,
GmWorldView *view) {
gchar *line;
switch (code) {
case GM_NET_ERROR_CONNECTING:
line = g_strdup_printf(_("# Connect failed: %s"), text);
break;
case GM_NET_ERROR_DISCONNECTED:
line = g_strdup_printf(_("# Connection lost... (%s)"), text);
break;
default:
line = g_strdup_printf(_("# Error: %s"), text);
break;
}
gm_world_writeln(world, line);
g_free(line);
}
void
on_gm_world_view_world_state_changing(GmWorld *world, guint state,
GmWorldView *view) {
gchar *line = NULL;
GmNetState pstate = gm_world_state(world);
switch (state) {
case GM_NET_STATE_TRY_ADDRESS:
line = g_strdup_printf(_("# Trying %s port %s"),
gm_world_current_host(world), gm_world_current_port(world));
break;
case GM_NET_STATE_CONNECTING:
line = g_strdup_printf(_("# Connecting to %s port %s"),
gm_world_current_host(world), gm_world_current_port(world));
break;
case GM_NET_STATE_CONNECTED:
line = g_strdup(_("# Connected"));
break;
case GM_NET_STATE_DISCONNECTED:
if (pstate == GM_NET_STATE_CONNECTED ||
pstate == GM_NET_STATE_DISCONNECTING) {
line = g_strdup(_("# Disconnected"));
}
gm_world_view_update_status(view, NULL);
break;
case GM_NET_STATE_DISCONNECTING:
line = g_strdup(_("# Disconnecting"));
break;
default:
break;
}
if (line) {
gm_world_writeln(world, line);
g_free(line);
}
}
void
on_gm_world_view_world_active_changed(GmWorld *world, GParamSpec *pspec,
GmWorldView *view) {
if (gm_world_active(world)) {
gtk_widget_grab_focus(GTK_WIDGET(view->priv->text_view_input));
}
}
void
on_gm_world_view_world_highlight(GmWorld *world, gint start, gint end,
gchar *color, GmWorldView *view) {
GtkTextIter istart, iend;
GtkTextBuffer *buffer = gtk_text_view_get_buffer(
GTK_TEXT_VIEW(view->priv->text_view_world));
gtk_text_buffer_get_end_iter(buffer, &iend);
istart = iend;
gtk_text_iter_backward_line(&istart);
if (start != -1) {
gtk_text_iter_forward_chars(&istart, start);
iend = istart;
gtk_text_iter_forward_chars(&iend, end);
}
gtk_text_buffer_apply_tag_by_name(buffer, color, &istart, &iend);
}
gboolean on_gm_world_view_world_text_view_scroll_event(GmWorldView *view,
GdkEventScroll *event, GmWorldTextView *text) {
if (event->state & GDK_CONTROL_MASK) {
switch (event->direction) {
case GDK_SCROLL_UP:
// Decrease font size
gm_world_view_change_font_size(view, -1);
break;
case GDK_SCROLL_DOWN:
// Increase font size
gm_world_view_change_font_size(view, 1);
break;
default:
break;
}
return TRUE;
} else {
return FALSE;
}
return FALSE;
}
gboolean
on_gm_world_view_world_input_view_key_pressed(GtkWidget *widget,
GdkEventKey *event, GmWorldView *view) {
switch (event->keyval) {
case GDK_Home: case GDK_End:
if ((event->state | GDK_CONTROL_MASK) == event->state) {
if (event->keyval == GDK_End) {
gm_text_scroller_scroll_end(
view->priv->text_scroller_world);
} else {
gm_text_scroller_scroll_begin(
view->priv->text_scroller_world);
}
return TRUE;
}
break;
case GDK_Page_Up: case GDK_Page_Down:
if (!(event->state & GDK_CONTROL_MASK &&
!(event->state & GDK_SHIFT_MASK))) {
if (event->keyval == GDK_Page_Up) {
gm_text_scroller_scroll_page(
view->priv->text_scroller_world, -1);
} else {
gm_text_scroller_scroll_page(
view->priv->text_scroller_world, 1);
}
return TRUE;
}
default:
break;
}
return FALSE;
}
void
on_gm_world_view_world_mcp_package_created(GmMcpSession *session,
GmMcpPackage *package, GmWorldView *view) {
gm_mcp_package_create_view(package, G_OBJECT(view));
}
void
on_gm_world_view_world_text_view_url_activate(GmWorldView *view,
gchar const *url) {
gm_open_url(url);
}