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-app-view.c

1406 lines
39 KiB
C

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
#include <glade/glade.h>
#include <libgnomeui/libgnomeui.h>
#include <libgnome/gnome-url.h>
#include <vte/vte.h>
#include "../gm-debug.h"
#include "gm-app-view.h"
#include "../gm-ui.h"
#include "gm-world-view.h"
#include "../gm-world.h"
#include "../dialogs/gm-world-info-dialog.h"
#include "../dialogs/gm-worlds-list-dialog.h"
#include "../dialogs/gm-world-logs-dialog.h"
#include "../dialogs/gm-world-properties-dialog.h"
#include "../dialogs/gm-scripts-dialog.h"
#include "../dialogs/gm-preferences-dialog.h"
#include "gm-world-tab.h"
//#include "if_world.h"
//#include "if_worlds_listing.h"
//#include "if_preferences.h"
//#include "if_mcpconsole.h"
#include "../gm-pixbuf.h"
#include "../gm-support.h"
//#include "term.h"
//#include "world.h"
//#include "net.h"
//#include "main.h"
void on_gm_app_view_destroy(GtkWidget * caller, gpointer user_data);
gboolean on_gm_app_view_focus_in(GtkWidget *widget, GdkEventFocus *event,
gpointer user_data);
void on_gm_app_view_entry_find_activate(GtkEntry *entry, GmAppView *view);
void on_gm_app_view_entry_find_changed(GtkEditable *editable,
GmAppView *view);
gboolean on_gm_app_view_entry_find_key_press(GtkWidget *widget,
GdkEventKey *event, GmAppView *view);
void on_gm_app_view_button_find_close_clicked(GtkButton *button,
GmAppView *view);
void on_gm_app_view_notebook_switch_page(GtkNotebook * notebook,
GtkNotebookPage * page, guint page_num, GmAppView *view);
gboolean on_gm_app_view_notebook_button_press(GtkNotebook *notebook,
GdkEventButton *event, GmAppView *view);
gboolean on_gm_app_view_notebook_button_release(GtkNotebook *notebook,
GdkEventButton *event, GmAppView *view);
void on_gm_app_view_check_button_search_direction_toggled(
GtkToggleButton *button, GmAppView *view);
typedef struct _AccelInfo AccelInfo;
struct _AccelInfo {
int num;
GmAppView *view;
};
void on_gm_app_view_accel_switch_page(GtkAccelGroup * accelgroup,
GObject * arg1, guint arg2, GdkModifierType arg3, AccelInfo *info);
void on_gm_app_view_accel_switch_edit(GtkAccelGroup * accelgroup,
GObject * arg1, guint arg2, GdkModifierType arg3, AccelInfo *info);
void on_gm_app_view_accel_cycle_page(GtkAccelGroup * accelgroup,
GObject * arg1, guint arg2, GdkModifierType arg3, AccelInfo *info);
void on_gm_app_view_world_added(GmApp *app, GmWorld *world, GmAppView *view);
void on_gm_app_view_world_removed(GmApp *app, GmWorld *world, GmAppView *view);
void on_gm_app_view_world_activate(GtkAction * action, GmWorld *world);
void on_gm_app_view_world_load(GmWorld *world, GmAppView *view);
void on_gm_app_view_world_unload(GmWorld *world, GmAppView *view);
void on_gm_app_view_world_activate_request(GmWorld *world, GmAppView *view);
void on_gm_app_view_world_name_changed(GmWorld *world, const gchar *name,
GmAppView *view);
void on_gm_app_view_world_state_changing(GmWorld *world, GmNetState state,
GmAppView *view);
void on_gm_app_view_world_active_changed(GmWorld *world, gboolean active,
GmAppView *view);
#define GM_APP_VIEW_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), \
GM_TYPE_APP_VIEW, GmAppViewPrivate))
typedef struct _GmAppViewWorldMenuItem GmAppViewWorldMenuItem;
struct _GmAppViewWorldMenuItem {
guint merge_id;
GtkAction *action;
};
void gm_app_view_destroy_world_menu_item(GmAppViewWorldMenuItem *item);
struct _GmAppViewPrivate {
GmApp *application;
GtkUIManager *manager;
GtkActionGroup *sensitive_action_group;
GtkActionGroup *action_group;
GtkActionGroup *worlds_action_group;
GHashTable *world_menu_items;
GtkNotebook *notebook;
GmWorld *active_world;
GtkMenuBar *menu;
GtkEntry *entry_find;
GtkVBox *vbox_find;
GtkCheckButton *check_button_search_direction;
gboolean drag_in_progress;
gint motion_notify_handler_id;
gint x_start;
gint y_start;
GdkCursor *cursor;
};
/* Signals */
/*enum {
NUM_SIGNALS
};
static guint app_view_signals[NUM_SIGNALS] = {0};*/
G_DEFINE_TYPE(GmAppView, gm_app_view, GTK_TYPE_WINDOW)
static void
gm_app_view_finalize(GObject *object) {
GmAppView *view = GM_APP_VIEW(object);
gm_scripts_dialog_fini();
g_hash_table_destroy(view->priv->world_menu_items);
G_OBJECT_CLASS(gm_app_view_parent_class)->finalize(object);
}
static void
gm_app_view_class_init(GmAppViewClass *klass) {
GObjectClass *object_class = G_OBJECT_CLASS(klass);
object_class->finalize = gm_app_view_finalize;
g_type_class_add_private(object_class, sizeof(GmAppViewPrivate));
}
GtkWidget *
gm_app_view_create_menu(GmAppView *view) {
GError *error = NULL;
GtkActionGroup *action_group;
view->priv->manager = gtk_ui_manager_new();
gtk_window_add_accel_group(GTK_WINDOW(view),
gtk_ui_manager_get_accel_group(view->priv->manager));
gtk_ui_manager_add_ui_from_file(view->priv->manager,
PACKAGE_DATA_DIR "/" PACKAGE "/ui/gm-ui.xml", &error);
if (error) {
gm_debug_msg(DEBUG_DEFAULT, "Could not merge UI file");
g_error_free(error);
}
action_group = gtk_action_group_new("GmAppViewSensitiveActions");
gtk_action_group_set_translation_domain(action_group,
GETTEXT_PACKAGE);
gtk_action_group_add_actions(action_group, gm_sensitive_menu_entries,
G_N_ELEMENTS(gm_sensitive_menu_entries), view);
gtk_ui_manager_insert_action_group(view->priv->manager, action_group, 0);
view->priv->sensitive_action_group = action_group;
gtk_action_group_set_sensitive(action_group, TRUE);
action_group = gtk_action_group_new("GmAppViewActions");
gtk_action_group_set_translation_domain(action_group,
GETTEXT_PACKAGE);
gtk_action_group_add_actions(action_group, gm_menu_entries,
G_N_ELEMENTS(gm_menu_entries), view);
gtk_ui_manager_insert_action_group(view->priv->manager, action_group, 0);
view->priv->action_group = action_group;
gtk_action_group_set_sensitive(action_group, FALSE);
view->priv->worlds_action_group =
gtk_action_group_new("GmAppViewWorldsActions");
gtk_action_group_set_translation_domain(view->priv->worlds_action_group,
GETTEXT_PACKAGE);
gtk_ui_manager_insert_action_group(view->priv->manager,
view->priv->worlds_action_group, 0);
#ifndef HAVE_RUBY
gtk_widget_set_sensitive(gtk_ui_manager_get_widget(view->priv->manager,
"/MenuBar/ViewMenu/ViewScriptsMenu"), FALSE);
#endif
return gtk_ui_manager_get_widget(view->priv->manager, "/MenuBar");
}
GtkWidget *
gm_app_view_create_search_box(GmAppView *view) {
GtkWidget *vbox = gtk_vbox_new(FALSE, 3);
GtkWidget *hbox = gtk_hbox_new(FALSE, 6);
GtkWidget *lbl = gtk_label_new(_("Find:"));
GtkWidget *entry = gtk_entry_new();
GtkWidget *button = gtk_button_new();
GtkWidget *hbox_button = gtk_hbox_new(FALSE, 2);
GtkWidget *align = gtk_alignment_new(0.5, 0.5, 0.0, 0.0);
GtkWidget *check_button =
gtk_check_button_new_with_label(_("Search backwards"));
GtkWidget *button_close = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
GtkWidget *separator = gtk_hseparator_new();
gtk_container_set_border_width(GTK_CONTAINER(hbox), 3);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox), separator, FALSE, TRUE, 0);
gtk_container_add(GTK_CONTAINER(button), align);
gtk_container_add(GTK_CONTAINER(align), hbox_button);
gtk_box_pack_start(GTK_BOX(hbox_button), gtk_image_new_from_stock(
GTK_STOCK_FIND, GTK_ICON_SIZE_BUTTON), FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox_button),
gtk_label_new(_("Find next")), FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), lbl, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), check_button, FALSE, FALSE, 0);
gtk_box_pack_end(GTK_BOX(hbox), button_close, FALSE, FALSE, 0);
view->priv->vbox_find = GTK_VBOX(vbox);
view->priv->entry_find = GTK_ENTRY(entry);
view->priv->check_button_search_direction = GTK_CHECK_BUTTON(check_button);
gtk_widget_show_all(vbox);
gtk_widget_hide(vbox);
g_signal_connect(entry, "activate",
G_CALLBACK(on_gm_app_view_entry_find_activate), view);
g_signal_connect(entry, "changed",
G_CALLBACK(on_gm_app_view_entry_find_changed), view);
g_signal_connect(entry, "key_press_event",
G_CALLBACK(on_gm_app_view_entry_find_key_press), view);
g_signal_connect(button_close, "clicked",
G_CALLBACK(on_gm_app_view_button_find_close_clicked), view);
g_signal_connect(check_button, "toggled",
G_CALLBACK(on_gm_app_view_check_button_search_direction_toggled),
view);
return vbox;
}
void
gm_app_view_create_keybindings(GmAppView *view) {
GtkAccelGroup *grp;
GClosure *closure;
int i;
gchar num[2] = { 0, 0 };
AccelInfo *info;
grp = gtk_accel_group_new();
// Setting up Alt-1/Ctrl-1 -> Alt-9/Ctrl-9 accelerators
for (i = 0; i < 9; i++) {
info = g_new0(AccelInfo, 1);
info->num = i;
info->view = view;
num[0] = '1' + i;
closure = g_cclosure_new(G_CALLBACK(on_gm_app_view_accel_switch_page),
info, NULL);
gtk_accel_group_connect(grp, gdk_keyval_from_name(num), GDK_MOD1_MASK,
GTK_ACCEL_VISIBLE, closure);
g_closure_unref(closure);
closure = g_cclosure_new(G_CALLBACK(on_gm_app_view_accel_switch_edit),
info, NULL);
gtk_accel_group_connect(grp, gdk_keyval_from_name(num),
GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE, closure);
g_closure_unref(closure);
}
info = g_new0(AccelInfo, 1);
info->num = 1;
info->view = view;
// Next page
closure = g_cclosure_new(G_CALLBACK(on_gm_app_view_accel_cycle_page),
info, NULL);
gtk_accel_group_connect(grp, GDK_Page_Up, GDK_CONTROL_MASK,
GTK_ACCEL_VISIBLE, closure);
g_closure_unref(closure);
info = g_new0(AccelInfo, 1);
info->num = -1;
info->view = view;
// Previous page
closure = g_cclosure_new(G_CALLBACK(on_gm_app_view_accel_cycle_page),
info, NULL);
gtk_accel_group_connect(grp, GDK_Page_Down, GDK_CONTROL_MASK,
GTK_ACCEL_VISIBLE, closure);
g_closure_unref(closure);
gtk_window_add_accel_group(GTK_WINDOW(view), grp);
}
static void
gm_app_view_init(GmAppView *view) {
GtkWidget *menu;
GtkWidget *search;
GtkWidget *vbox;
GtkWidget *note;
view->priv = GM_APP_VIEW_GET_PRIVATE(view);
vbox = gtk_vbox_new(FALSE, 3);
gtk_widget_show(vbox);
gtk_container_add(GTK_CONTAINER(view), vbox);
menu = gm_app_view_create_menu(view);
gtk_widget_show(menu);
gtk_box_pack_start(GTK_BOX(vbox), menu, FALSE, TRUE, 0);
search = gm_app_view_create_search_box(view);
gtk_box_pack_start(GTK_BOX(vbox), search, FALSE, TRUE, 0);
note = gtk_notebook_new();
gtk_widget_show(note);
gtk_container_set_border_width(GTK_CONTAINER(note), 3);
gtk_notebook_set_show_border(GTK_NOTEBOOK(note), FALSE);
GTK_WIDGET_UNSET_FLAGS(note, GTK_CAN_FOCUS);
gtk_widget_add_events(GTK_WIDGET(note), GDK_BUTTON1_MOTION_MASK);
gtk_box_pack_start(GTK_BOX(vbox), note, TRUE, TRUE, 0);
gm_app_view_create_keybindings(view);
view->priv->menu = GTK_MENU_BAR(menu);
view->priv->notebook = GTK_NOTEBOOK(note);
gtk_window_set_title(GTK_WINDOW(view), "GnoeMoe");
gtk_window_set_icon(GTK_WINDOW(view), gm_pixbuf_get("gnoemoe_logo.svg"));
g_signal_connect(view, "destroy", G_CALLBACK(on_gm_app_view_destroy), NULL);
g_signal_connect(view, "focus_in_event",
G_CALLBACK(on_gm_app_view_focus_in), NULL);
/* Signals for tab reordering */
g_signal_connect_after(note, "switch-page",
G_CALLBACK(on_gm_app_view_notebook_switch_page), view);
g_signal_connect(note, "button-press-event",
G_CALLBACK(on_gm_app_view_notebook_button_press), view);
g_signal_connect(note, "button-release-event",
G_CALLBACK(on_gm_app_view_notebook_button_release), view);
view->priv->world_menu_items = g_hash_table_new_full(g_direct_hash,
g_direct_equal, NULL,
(GDestroyNotify)gm_app_view_destroy_world_menu_item);
view->priv->drag_in_progress = FALSE;
view->priv->motion_notify_handler_id = 0;
view->priv->x_start = 0;
view->priv->y_start = 0;
view->priv->cursor = NULL;
gm_scripts_dialog_init();
}
// Public functions
GmAppView *
gm_app_view_new(GmApp *application) {
GmAppView *view = GM_APP_VIEW(g_object_new(GM_TYPE_APP_VIEW, NULL));
gboolean dir;
view->priv->application = application;
view->priv->active_world = NULL;
// Toggle search direction
dir = gm_options_get_int(gm_app_options(application), "search_direction")
== 1;
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
view->priv->check_button_search_direction), dir);
g_signal_connect(application, "world_added",
G_CALLBACK(on_gm_app_view_world_added), view);
g_signal_connect(application, "world_removed",
G_CALLBACK(on_gm_app_view_world_removed), view);
return view;
}
const GmApp *
gm_app_view_application(GmAppView *view) {
return view->priv->application;
}
void
gm_app_view_destroy_world_menu_item(GmAppViewWorldMenuItem *item) {
g_object_unref(item->action);
g_free(item);
}
void
on_gm_app_view_world_removed(GmApp *app, GmWorld *world, GmAppView *view) {
GmAppViewWorldMenuItem *item = (GmAppViewWorldMenuItem *)
g_hash_table_lookup(view->priv->world_menu_items, world);
gtk_ui_manager_remove_ui(view->priv->manager, item->merge_id);
gtk_action_group_remove_action(view->priv->worlds_action_group,
item->action);
g_hash_table_remove(view->priv->world_menu_items, world);
}
void
gm_app_view_set_sensitivity(GmAppView *view, gboolean sens) {
gtk_action_group_set_sensitive(view->priv->action_group, sens);
if (sens) {
/* TODO: set world info menu item not sensitive if no world info avail
First fix MCP
gtk_widget_set_sensitive(if_main_get_widget("mnuWorldInfo"), sens); */
} else {
gtk_widget_hide(GTK_WIDGET(view->priv->vbox_find));
}
}
GmWorldView *
gm_app_view_active_world_view(GmAppView *view) {
gint n;
n = gtk_notebook_get_current_page(view->priv->notebook);
if (n == -1) {
return NULL;
}
return GM_WORLD_VIEW(gtk_notebook_get_nth_page(view->priv->notebook, n));
}
GmWorld *
gm_app_view_active_world(GmAppView *view) {
GmWorldView *world_view = gm_app_view_active_world_view(view);
if (world_view != NULL) {
return gm_world_view_world(world_view);
} else {
return NULL;
}
}
void
gm_app_view_update_title(GmAppView *view) {
gchar *title;
GmWorld *world = gm_app_view_active_world(view);
if (world == NULL) {
gtk_window_set_title(GTK_WINDOW(view), "GnoeMoe");
} else {
title = g_strconcat(gm_world_name(world), " - GnoeMoe", NULL);
gtk_window_set_title(GTK_WINDOW(view), title);
g_free(title);
}
}
GtkWidget *
gm_app_view_container_item(GtkContainer *cnt, GType type) {
GList *childFirst = gtk_container_get_children(cnt);
GList *child;
GtkWidget *result = NULL;
for (child = childFirst; child; child = child->next) {
if (G_TYPE_CHECK_INSTANCE_TYPE(child->data, type)) {
result = GTK_WIDGET(child->data);
break;
} else if (GTK_IS_CONTAINER(child->data)) {
if ((result = gm_app_view_container_item(
GTK_CONTAINER(child->data), type))) {
break;
}
}
}
g_list_free(childFirst);
return result;
}
void
gm_app_view_update_connect_button(GmAppView *view, gboolean connected) {
GtkImageMenuItem *img = GTK_IMAGE_MENU_ITEM(
gtk_ui_manager_get_widget(view->priv->manager,
"/MenuBar/WorldMenu/WorldConnectMenu"));
GtkLabel *label = GTK_LABEL(gm_app_view_container_item(GTK_CONTAINER(img),
GTK_TYPE_LABEL));
GtkWidget *im;
if (!connected) {
im = gtk_image_new_from_stock("gtk-network", GTK_ICON_SIZE_MENU);
gtk_label_set_text(label, _("Connect"));
} else {
im = gtk_image_new_from_stock("gtk-stop", GTK_ICON_SIZE_MENU);
gtk_label_set_text(label, _("Disconnect"));
}
gtk_image_menu_item_set_image(img, im);
gtk_widget_show(im);
}
void
gm_app_view_worlds_unloaded(GmAppView *view) {
gm_app_view_set_sensitivity(view, FALSE);
gm_app_view_update_connect_button(view, FALSE);
gm_app_view_update_title(view);
}
void
gm_app_view_worlds_loaded(GmAppView *view) {
gm_app_view_set_sensitivity(view, TRUE);
}
/* TODO: move to custom widget thingie, and put control in gm-app instead
of gm-app-view
static gboolean
have_tray(void) {
Screen *xscreen = DefaultScreenOfDisplay(gdk_display);
Atom selection_atom;
char *selection_atom_name;
selection_atom_name = g_strdup_printf("_NET_SYSTEM_TRAY_S%d",
XScreenNumberOfScreen(xscreen));
selection_atom = XInternAtom(DisplayOfScreen(xscreen),
selection_atom_name, False);
g_free(selection_atom_name);
if (XGetSelectionOwner(DisplayOfScreen(xscreen), selection_atom)) {
return TRUE;
} else {
return FALSE;
}
}
static gboolean
tray_flash_restore_func(gpointer data) {
switch (app_tray_info.iconnr) {
case TRAY_ICON_ACTIVE:
gtk_image_set_from_pixbuf(GTK_IMAGE(app_tray_info.image),
gnoe_pixbuf_get("tray/active.svg"));
break;
case TRAY_ICON_DEFAULT:
gtk_image_set_from_pixbuf(GTK_IMAGE(app_tray_info.image),
gnoe_pixbuf_get("tray/default.svg"));
break;
case TRAY_ICON_NOTIFY:
gtk_image_set_from_pixbuf(GTK_IMAGE(app_tray_info.image),
gnoe_pixbuf_get("tray/notify.svg"));
break;
}
app_tray_info.flash_timeout = -1;
return FALSE;
}
void
tray_activate() {
if (app_tray_info.flash_timeout != 0) {
g_source_remove(app_tray_info.flash_timeout);
}
gtk_image_set_from_pixbuf(GTK_IMAGE(app_tray_info.image),
gnoe_pixbuf_get("tray/activate.svg"));
app_tray_info.flash_timeout = g_timeout_add(1000, tray_flash_restore_func, NULL);
}
void
tray_set_notify(gchar *text) {
gboolean active = gtk_window_is_active(GTK_WINDOW(wndMain));
if (!active) {
app_tray_info.iconnr = TRAY_ICON_NOTIFY;
tray_flash_restore_func(NULL);
egg_tray_icon_send_message(app_tray_info.icon, 2000, text, g_utf8_strlen(text, -1));
gtk_tooltips_set_tip(app_tray_info.tooltips, app_tray_info.event_box, text, text);
}
}
void
tray_update() {
GList *wlds;
world *wld;
gchar *tmp = NULL, *tmp2 = NULL;
gboolean active = gtk_window_is_active(GTK_WINDOW(wndMain));
if (!active) {
for (wlds = world_get_worlds(); wlds; wlds = wlds->next) {
wld = (world *)(wlds->data);
if (wld->loaded && wld->inactive > 0) {
if (tmp == NULL) {
tmp = g_strdup_printf(_("Activity in:\n%s (%d)"), options_get_str(
wld->settings, "name"), wld->inactive);
} else {
tmp2 = g_strdup_printf("%s, %s (%d)", tmp, options_get_str(
wld->settings, "name"), wld->inactive);
g_free(tmp);
tmp = g_strdup(tmp2);
g_free(tmp2);
tmp2 = NULL;
}
}
}
if (tmp) {
app_tray_info.iconnr = TRAY_ICON_ACTIVE;
tray_activate();
} else if (app_tray_info.iconnr != TRAY_ICON_NOTIFY) {
app_tray_info.iconnr = TRAY_ICON_DEFAULT;
tray_flash_restore_func(NULL);
}
if (app_tray_info.iconnr != TRAY_ICON_NOTIFY) {
gtk_tooltips_set_tip(app_tray_info.tooltips, app_tray_info.event_box, tmp, tmp);
}
g_free(tmp);
} else {
app_tray_info.iconnr = TRAY_ICON_DEFAULT;
tray_flash_restore_func(NULL);
gtk_tooltips_set_tip(app_tray_info.tooltips, app_tray_info.event_box, NULL, NULL);
}
}
void
if_main_show_hide(gboolean show) {
world *wld;
if (show || !gtk_window_is_active(GTK_WINDOW(wndMain))) {
gtk_widget_show(wndMain);
gtk_window_present(GTK_WINDOW(wndMain));
wld = world_get_active();
if (wld) {
wld->inactive = 0;
}
tray_update();
} else {
gtk_widget_hide(wndMain);
}
}*/
void
gm_app_view_update_world_info(gboolean hasInfo) {
/* TODO: do this some other way */
/*GtkWidget *image;
world *wld = world_get_active();
gtk_widget_set_sensitive(if_main_get_widget("mnuWorldInfo"), hasInfo);
if (options_get_str(wld->settings, "logo")) {
image = gtk_image_new_from_pixbuf(gnoe_pixbuf_get_at_size(options_get_str(wld->settings, "logo"), 16, 16));
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(wld->widgets.menuItem), image);
}*/
}
GmWorldView *
gm_app_view_world_view_from_world(GmAppView *view, GmWorld *world) {
GtkNotebook *book = view->priv->notebook;
GmWorldView *current_view;
gint i;
for (i = 0; i < gtk_notebook_get_n_pages(book); i++) {
current_view = GM_WORLD_VIEW(gtk_notebook_get_nth_page(book, i));
if (gm_world_view_world(current_view) == world) {
return current_view;
}
}
return NULL;
}
/* Callbacks */
void
on_gm_app_view_destroy(GtkWidget * caller, gpointer user_data) {
gtk_main_quit();
}
void
on_gm_app_view_world_close(GtkMenuItem * menuitem, GmAppView *view) {
GmWorld *world = gm_app_view_active_world(view);
if (world) {
gm_world_unload(world);
}
}
void
on_gm_app_view_world_close_from_tab(GmWorldTab *tab, GmWorld *world) {
gm_world_unload(world);
}
void
on_gm_app_view_world_name_changed(GmWorld *world, const gchar *name,
GmAppView *view) {
GmAppViewWorldMenuItem *item = (GmAppViewWorldMenuItem *)
g_hash_table_lookup(view->priv->world_menu_items, world);
g_object_set(G_OBJECT(item->action), "label", name, NULL);
if (world == gm_app_view_active_world(view)) {
gm_app_view_update_title(view);
}
}
void
on_gm_app_view_world_added(GmApp *app, GmWorld *world, GmAppView *view) {
static guint id = 0;
GmAppViewWorldMenuItem *item = g_new0(GmAppViewWorldMenuItem, 1);
gchar *name = g_strdup_printf("WorldItem%d", id);
gchar *tooltip = g_strconcat(_("Open world "), gm_world_name(world), NULL);
id++;
/* TODO: add custom icon from logo */
item->merge_id = gtk_ui_manager_new_merge_id(view->priv->manager);
item->action = gtk_action_new(name, gm_world_name(world), tooltip, NULL);
gtk_action_group_add_action(view->priv->worlds_action_group, item->action);
gtk_ui_manager_add_ui(view->priv->manager, item->merge_id,
"/MenuBar/WorldMenu/WorldMenuAdditions", name, name,
GTK_UI_MANAGER_MENUITEM, FALSE);
g_signal_connect(item->action, "activate",
G_CALLBACK(on_gm_app_view_world_activate), world);
g_signal_connect(world, "load",
G_CALLBACK(on_gm_app_view_world_load), view);
g_signal_connect(world, "unload",
G_CALLBACK(on_gm_app_view_world_unload), view);
g_signal_connect(world, "activate_request",
G_CALLBACK(on_gm_app_view_world_activate_request), view);
g_signal_connect(world, "name_changed",
G_CALLBACK(on_gm_app_view_world_name_changed), view);
g_signal_connect(world, "state_changing",
G_CALLBACK(on_gm_app_view_world_state_changing), view);
g_signal_connect(world, "active_changed",
G_CALLBACK(on_gm_app_view_world_active_changed), view);
g_hash_table_insert(view->priv->world_menu_items, world, item);
g_free(name);
g_free(tooltip);
}
void
on_gm_app_view_world_state_changing(GmWorld *world, GmNetState state,
GmAppView *view) {
if (world == gm_app_view_active_world(view)) {
switch (state) {
case GM_NET_STATE_CONNECTED:
gm_app_view_update_connect_button(view, TRUE);
break;
case GM_NET_STATE_DISCONNECTED:
gm_app_view_update_connect_button(view, FALSE);
break;
default:
break;
}
}
}
void
on_gm_app_view_world_load(GmWorld *world, GmAppView *view) {
GtkWidget *world_view = gm_world_view_new(world);
GmWorldTab *tab = gm_world_tab_new(world);
g_signal_connect(tab, "close",
G_CALLBACK(on_gm_app_view_world_close_from_tab), world);
gtk_notebook_append_page(view->priv->notebook, world_view,
GTK_WIDGET(tab));
gtk_widget_show_all(world_view);
gm_world_view_set_userlist_width(GM_WORLD_VIEW(world_view),
gm_options_get_int(gm_world_options(world), "pane_position"));
if (gtk_notebook_get_n_pages(view->priv->notebook) == 1) {
gm_app_view_worlds_loaded(view);
}
}
void
on_gm_app_view_world_unload(GmWorld *world, GmAppView *view) {
GmWorldView *world_view = gm_app_view_world_view_from_world(view, world);
gtk_notebook_remove_page(view->priv->notebook,
gtk_notebook_page_num(view->priv->notebook, GTK_WIDGET(world_view)));
if (gtk_notebook_get_n_pages(view->priv->notebook) == 0) {
gm_app_view_worlds_unloaded(view);
}
}
void
on_gm_app_view_world_activate_request(GmWorld *world, GmAppView *view) {
gm_world_set_active(world, TRUE);
}
void
on_gm_app_view_world_quit(GtkMenuItem * menuitem, GmAppView *view) {
gtk_widget_destroy(GTK_WIDGET(view));
}
void
on_gm_app_view_edit_worlds(GtkMenuItem * menuitem, GmAppView *view) {
gm_worlds_list_dialog_run();
}
void
on_gm_app_view_accel_switch_page(GtkAccelGroup * accelgroup, GObject * arg1,
guint arg2, GdkModifierType arg3, AccelInfo *info) {
gtk_notebook_set_current_page(info->view->priv->notebook, info->num);
}
void
on_gm_app_view_accel_switch_edit(GtkAccelGroup * accelgroup, GObject * arg1,
guint arg2, GdkModifierType arg3, AccelInfo *info) {
GmWorld *world = gm_app_view_active_world(info->view);
if (world) {
gtk_notebook_set_current_page(info->view->priv->notebook, info->num);
}
}
void
on_gm_app_view_accel_cycle_page(GtkAccelGroup * accelgroup, GObject * arg1,
guint arg2, GdkModifierType arg3, AccelInfo *info) {
GtkNotebook *note = info->view->priv->notebook;
int p = gtk_notebook_get_current_page(note) + info->num;
if (p < 0) {
gtk_notebook_set_current_page(note, gtk_notebook_get_n_pages(note) - 1);
} else if (p > gtk_notebook_get_n_pages(note) - 1) {
gtk_notebook_set_current_page(note, 0);
} else {
gtk_notebook_set_current_page(note, p);
}
}
void
on_gm_app_view_world_activate(GtkAction * action, GmWorld *world) {
gm_world_load(world);
}
GmWorldViewSearchFlags
gm_app_view_search_flags(GmAppView *view) {
gboolean active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
view->priv->check_button_search_direction));
if (active) {
return GM_WORLD_VIEW_SEARCH_BACKWARDS;
} else {
return GM_WORLD_VIEW_SEARCH_FORWARDS;
}
}
gboolean
gm_app_view_find_first(GmAppView *view) {
GmWorldView *world_view = gm_app_view_active_world_view(view);
GdkColor red;
GtkEntry *entry = view->priv->entry_find;
if (world_view) {
gdk_color_parse ("#ff6666", &red);
//gdk_color_parse ("white", &white);
if (g_utf8_strlen(gtk_entry_get_text(entry), -1) == 0 ||
gm_world_view_find_first(world_view, gtk_entry_get_text(entry),
gm_app_view_search_flags(view))) {
gtk_widget_modify_base(GTK_WIDGET(entry), GTK_STATE_NORMAL, NULL);
} else {
gtk_widget_modify_base(GTK_WIDGET(entry), GTK_STATE_NORMAL, &red);
}
}
return FALSE;
}
void
on_gm_app_view_entry_find_changed(GtkEditable *editable, GmAppView *view) {
g_idle_add((GSourceFunc)gm_app_view_find_first, view);
}
void
on_gm_app_view_entry_find_activate(GtkEntry *entry, GmAppView *view) {
on_gm_app_view_edit_find_next(NULL, view);
}
void
gm_app_view_show_find_box(GmAppView *view) {
GmWorldView *world_view;
int i, n;
if (!GTK_WIDGET_VISIBLE(view->priv->vbox_find)) {
n = gtk_notebook_get_n_pages(view->priv->notebook);
for (i = 0; i < gtk_notebook_get_n_pages(view->priv->notebook); i++) {
world_view = GM_WORLD_VIEW(gtk_notebook_get_nth_page(
view->priv->notebook, i));
gm_world_view_scroll_end_prepare(world_view);
}
gtk_widget_show(GTK_WIDGET(view->priv->vbox_find));
gm_do_events();
for (i = 0; i < gtk_notebook_get_n_pages(view->priv->notebook); i++) {
world_view = GM_WORLD_VIEW(gtk_notebook_get_nth_page(
view->priv->notebook, i));
gm_world_view_scroll_end(world_view);
}
}
}
void
on_gm_app_view_edit_find(GtkMenuItem * menuitem, GmAppView *view) {
GtkWidget *entry = GTK_WIDGET(view->priv->entry_find);
gm_app_view_show_find_box(view);
gtk_widget_grab_focus(entry);
gtk_widget_modify_base(entry, GTK_STATE_NORMAL, NULL);
}
void
on_gm_app_view_edit_find_next(GtkMenuItem * menuitem, GmAppView *view) {
gm_app_view_show_find_box(view);
gm_world_view_find_next(gm_app_view_active_world_view(view),
gtk_entry_get_text(view->priv->entry_find),
gm_app_view_search_flags(view));
}
void
on_gm_app_view_button_find_clicked(GtkButton *button, gpointer user_data) {
on_gm_app_view_edit_find_next(NULL, NULL);
}
gboolean
on_gm_app_view_entry_find_key_press(GtkWidget *widget, GdkEventKey *event,
GmAppView *view) {
if (event->keyval == GDK_Escape) {
on_gm_app_view_button_find_close_clicked(NULL, view);
gtk_widget_grab_focus(GTK_WIDGET(gm_app_view_active_world_view(view)));
return TRUE;
} else {
return FALSE;
}
}
void
on_gm_app_view_button_find_close_clicked(GtkButton *button,
GmAppView *view) {
GmWorldView *world_view = gm_app_view_active_world_view(view);
gtk_widget_hide(GTK_WIDGET(view->priv->vbox_find));
if (world_view) {
gm_world_view_set_focus(world_view);
}
}
void
on_gm_app_view_check_button_search_direction_toggled(GtkToggleButton *button,
GmAppView *view) {
gboolean active = gtk_toggle_button_get_active(button);
gm_options_set_int(gm_app_options(view->priv->application),
"search_direction", active ? 1 : 0);
}
void
on_gm_app_view_edit_preferences(GtkMenuItem * menuitem, GmAppView *view) {
gm_preferences_dialog_run();
}
/* Tab moving from gedit */
gint
gm_app_view_find_tab_num_at_pos(GmAppView *view, gint abs_x,
gint abs_y) {
GtkNotebook *notebook = view->priv->notebook;
GtkPositionType tab_pos;
int page_num = 0;
GtkWidget *page;
tab_pos = gtk_notebook_get_tab_pos(notebook);
if (notebook->first_tab == NULL) {
return -1;
}
/* For some reason unfullscreen + quick click can
cause a wrong click event to be reported to the tab */
/*if (!is_in_notebook_window(notebook, abs_x, abs_y)) {
return -1;
}*/
while ((page = gtk_notebook_get_nth_page(notebook, page_num)) != NULL) {
GtkWidget *tab;
gint max_x, max_y;
gint x_root, y_root;
tab = gtk_notebook_get_tab_label(notebook, page);
g_return_val_if_fail(tab != NULL, -1);
if (!GTK_WIDGET_MAPPED(GTK_WIDGET(tab))) {
++page_num;
continue;
}
gdk_window_get_origin(GDK_WINDOW(tab->window), &x_root, &y_root);
max_x = x_root + tab->allocation.x + tab->allocation.width;
max_y = y_root + tab->allocation.y + tab->allocation.height;
if (((tab_pos == GTK_POS_TOP) || (tab_pos == GTK_POS_BOTTOM)) &&
(abs_x <= max_x)) {
return page_num;
} else if (((tab_pos == GTK_POS_LEFT) || (tab_pos == GTK_POS_RIGHT)) &&
(abs_y <= max_y)) {
return page_num;
}
++page_num;
}
return -1;
}
void
gm_app_view_drag_stop(GmAppView *view) {
view->priv->drag_in_progress = FALSE;
if (view->priv->motion_notify_handler_id != 0) {
g_signal_handler_disconnect(G_OBJECT(view->priv->notebook),
view->priv->motion_notify_handler_id);
view->priv->motion_notify_handler_id = 0;
}
}
void
gm_app_view_drag_start(GmAppView *view, guint32 time) {
view->priv->drag_in_progress = TRUE;
/* get a new cursor, if necessary */
/* FIXME multi-head */
if (view->priv->cursor == NULL)
view->priv->cursor = gdk_cursor_new(GDK_FLEUR);
/* grab the pointer */
gtk_grab_add(GTK_WIDGET(view->priv->notebook));
/* FIXME multi-head */
if (!gdk_pointer_is_grabbed()) {
gdk_pointer_grab(GTK_WIDGET(view->priv->notebook)->window,
FALSE, GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, NULL,
view->priv->cursor, time);
}
}
void
gm_app_view_move_current_tab(GmAppView *view, gint dest_position) {
gint cur_page_num;
cur_page_num = gtk_notebook_get_current_page(view->priv->notebook);
if (dest_position != cur_page_num) {
GtkWidget *cur_tab;
cur_tab = gtk_notebook_get_nth_page(view->priv->notebook, cur_page_num);
gtk_notebook_reorder_child(view->priv->notebook, cur_tab, dest_position);
}
}
gboolean
on_gm_app_view_motion_notify(GmAppView *view, GdkEventMotion *event,
gpointer data) {
gint page_num;
if (view->priv->drag_in_progress == FALSE) {
if (gtk_drag_check_threshold(GTK_WIDGET(view->priv->notebook),
view->priv->x_start,
view->priv->y_start,
event->x_root,
event->y_root)) {
gm_app_view_drag_start(view, event->time);
return TRUE;
}
return FALSE;
}
page_num = gm_app_view_find_tab_num_at_pos(view, event->x_root,
event->y_root);
if (page_num != -1) {
gm_app_view_move_current_tab(view, page_num);
}
return FALSE;
}
gboolean
on_gm_app_view_notebook_button_press(GtkNotebook *notebook,
GdkEventButton *event, GmAppView *view) {
gint tab_clicked;
if (view->priv->drag_in_progress)
return TRUE;
tab_clicked = gm_app_view_find_tab_num_at_pos(view, event->x_root,
event->y_root);
if ((event->button == 1) && (event->type == GDK_BUTTON_PRESS) &&
(tab_clicked >= 0)) {
view->priv->x_start = event->x_root;
view->priv->y_start = event->y_root;
view->priv->motion_notify_handler_id = g_signal_connect(G_OBJECT(notebook),
"motion-notify-event", G_CALLBACK(on_gm_app_view_motion_notify), NULL);
} else if ((event->type == GDK_BUTTON_PRESS) && (event->button == 3)) {
/* Switch to the page the mouse is over, but don't consume the event */
//gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), tab_clicked);
}
return FALSE;
}
gboolean
on_gm_app_view_notebook_button_release(GtkNotebook *notebook,
GdkEventButton *event, GmAppView *view) {
if (view->priv->drag_in_progress) {
gint cur_page_num;
GtkWidget *cur_page;
cur_page_num = gtk_notebook_get_current_page(notebook);
cur_page = gtk_notebook_get_nth_page(notebook, cur_page_num);
/* ungrab the pointer if it's grabbed */
if (gdk_pointer_is_grabbed()) {
gdk_pointer_ungrab(event->time);
}
gtk_grab_remove(GTK_WIDGET(notebook));
}
/* This must be called even if a drag isn't happening */
gm_app_view_drag_stop(view);
return FALSE;
}
void
on_gm_app_view_notebook_switch_page(GtkNotebook * notebook,
GtkNotebookPage * page, guint page_num, GmAppView *view) {
GmWorld *world = gm_app_view_active_world(view);
if (view->priv->active_world == world) {
return;
}
if (view->priv->active_world) {
gm_world_set_active(view->priv->active_world, FALSE);
}
if (world) {
view->priv->active_world = world;
gm_world_set_active(view->priv->active_world, TRUE);
}
}
static const gchar *authors[] = {
N_("Jesse van den Kieboom"),
N_("Sjoerd Simons (debian package)"),
NULL
};
static const gchar *artists[] = {
N_("Simon Gijsen"),
NULL
};
void
on_gm_app_view_help_about(GtkMenuItem *menuitem, GmAppView *view) {
gtk_show_about_dialog(GTK_WINDOW(view),
"name", _("GnoeMoe"),
"version", IVERSION,
"copyright", _("(C) 2004-2005 Icecrew.nl"),
"comments", _("GnoeMoe Gnome MOO Client"),
"authors", authors,
"artists", artists,
"logo", gm_pixbuf_get("gnoemoe_logo.svg"),
NULL);
}
void
on_gm_app_view_edit_cut(GtkMenuItem * menuitem, GmAppView *view) {
GtkWidget *active = gtk_window_get_focus(GTK_WINDOW(view));
GtkClipboard *clip = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
GtkTextBuffer *buf;
if (active && GTK_IS_TEXT_VIEW(active)) {
buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(active));
gtk_text_buffer_cut_clipboard(buf, clip, TRUE);
}
}
void
on_gm_app_view_edit_copy(GtkMenuItem * menuitem, GmAppView *view) {
GtkWidget *active = gtk_window_get_focus(GTK_WINDOW(view));
GtkClipboard *clip = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
GtkTextBuffer *buf;
GtkTextIter start, end;
GmWorldView *world_view;
world_view = gm_app_view_active_world_view(view);
if (world_view && active == GTK_WIDGET(gm_world_view_input(world_view))) {
buf = gm_world_view_buffer(world_view);
if (gtk_text_buffer_get_selection_bounds(buf, &start, &end)) {
gtk_text_buffer_copy_clipboard(buf, clip);
return;
}
}
if (active && GTK_IS_TEXT_VIEW(active)) {
buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(active));
gtk_text_buffer_copy_clipboard(buf, clip);
}
}
void
on_gm_app_view_edit_paste(GtkMenuItem * menuitem, GmAppView *view) {
GtkWidget *active = gtk_window_get_focus(GTK_WINDOW(view));
GtkClipboard *clip = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
GtkTextBuffer *buf;
if (active && GTK_IS_TEXT_VIEW(active)) {
buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(active));
gtk_text_buffer_paste_clipboard(buf, clip, NULL, TRUE);
}
}
void
on_gm_app_view_world_new(GtkMenuItem * menuitem, GmAppView *view) {
gm_world_properties_dialog_run_new(NULL);
}
void
on_gm_app_view_edit_world(GtkMenuItem * menuitem, GmAppView *view) {
GmWorld *active = gm_app_view_active_world(view);
gm_world_properties_dialog_run(active);
}
void
on_gm_app_view_world_connect(GtkMenuItem * menuitem, GmAppView *view) {
GmWorld *world = gm_app_view_active_world(view);
if (world != NULL) {
if (gm_world_connected(world)) {
gm_world_disconnect(world);
} else if (gm_world_disconnected(world)) {
gm_world_connect(world);
}
}
}
void
on_gm_app_view_world_info(GtkMenuItem *menuitem, GmAppView *view) {
GmWorld *world = gm_app_view_active_world(view);
if (world) {
gm_world_info_dialog_new(gm_world_info(world));
} else {
gm_app_view_update_world_info(FALSE);
}
}
void
on_gm_app_view_view_mcp(GtkMenuItem * menuitem, GmAppView *view) {
/* TODO: implementation */
//if_mcpconsole_create();
}
void
on_gm_app_view_view_scripts(GtkMenuItem * menuitem, GmAppView *view) {
#ifdef HAVE_RUBY
gm_scripts_dialog_run(view);
#endif
}
void
gm_app_view_open_log_progress(long bytes_read, long bytes_total, gchar *buf,
GtkProgressBar *progress) {
gtk_progress_bar_set_fraction(progress, (double)bytes_read / (double)bytes_total);
gm_do_events();
}
void
on_gm_app_view_world_logs(GtkMenuItem * menuitem, GmAppView *view) {
GtkDialog *dlg;
GtkTreeView *tview;
GtkTreeModel *smodel;
gchar *tmp, *tmp2;
GtkTreeIter iter;
gboolean done = FALSE;
static GdkCursor *wait_cursor = NULL;
GmWorld *world = gm_app_view_active_world(view);
GtkProgressBar *pgs;
dlg = gm_world_logs_dialog_new(gm_app_view_active_world(view), &tview, &pgs);
if (dlg != NULL) {
smodel = gtk_tree_view_get_model(tview);
while (!done) {
done = TRUE;
switch (gtk_dialog_run(dlg)) {
case GTK_RESPONSE_OK:
if (gtk_tree_selection_get_selected(
gtk_tree_view_get_selection(tview), &smodel, &iter)) {
gtk_tree_model_get(smodel, &iter, 0, &tmp, -1);
tmp2 = g_strconcat(gm_world_path(world), tmp, NULL);
gtk_widget_set_sensitive(GTK_WIDGET(dlg), FALSE);
if (wait_cursor == NULL) {
wait_cursor = gdk_cursor_new(GDK_WATCH);
}
gdk_window_set_cursor(GTK_WIDGET(dlg)->window, wait_cursor);
gtk_widget_show(GTK_WIDGET(pgs));
gm_world_view_open_log(gm_app_view_active_world_view(view), tmp2,
(OpenLogProgress)gm_app_view_open_log_progress,
pgs);
gtk_widget_hide(GTK_WIDGET(pgs));
gdk_window_set_cursor(GTK_WIDGET(dlg)->window, NULL);
g_free(tmp2);
g_free(tmp);
} else {
gm_error_dialog(_("You didn't select a log file"), NULL);
done = FALSE;
}
break;
default:
break;
}
}
gtk_widget_destroy(GTK_WIDGET(dlg));
}
}
void
on_gm_app_view_world_active_changed(GmWorld *world, gboolean active,
GmAppView *view) {
GmWorldView *world_view = gm_app_view_world_view_from_world(view, world);
if (active) {
gtk_notebook_set_current_page(view->priv->notebook,
gtk_notebook_page_num(view->priv->notebook,
GTK_WIDGET(world_view)));
gm_app_view_update_title(view);
}
}
gboolean
on_gm_app_view_focus_in(GtkWidget *widget, GdkEventFocus *event,
gpointer user_data) {
/* TODO: implementation
world *wld;
wld = world_get_active();
if (wld) {
world_activated(wld);
}
app_tray_info.iconnr = TRAY_ICON_DEFAULT;
tray_flash_restore_func(NULL);*/
return FALSE;
}