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

1735 lines
50 KiB
C
Raw Normal View History

2005-11-07 10:56:25 +01:00
#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>
2006-01-10 01:39:05 +01:00
#include "gm-debug.h"
2005-11-07 10:56:25 +01:00
#include "gm-app-view.h"
2006-01-10 01:39:05 +01:00
#include "gm-ui.h"
2005-11-07 10:56:25 +01:00
#include "gm-world-view.h"
2006-01-10 01:39:05 +01:00
#include "gm-world.h"
#include "dialogs/gm-worlds-list-dialog.h"
2006-03-29 13:57:17 +02:00
#include "dialogs/gm-open-world-dialog.h"
2006-01-10 01:39:05 +01:00
#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"
2005-11-07 10:56:25 +01:00
#include "gm-world-tab.h"
#include "gm-editor-view.h"
#include "mcp/gm-mcp-session.h"
#include "mcp/gm-mcp-package.h"
#include "gm-searchable.h"
#include "gm-tray.h"
2006-01-10 01:39:05 +01:00
#include "gm-pixbuf.h"
#include "gm-support.h"
* VERSION CHANGED TO 2.0.9 * po/POTFILES.in: added gnoemoe/dialogs/gm-world-paste-dialog.c and ui/gm-world-paste.glade * po/nl.po: added translations * ui/Makefile.am: * ui/gm-ui.xml: * ui/gm-world-paste.glade: new paste dialog * gnoemoe/mcp/Makefile.include: added gm-cell-renderer-text.[ch] * gnoemoe/mcp/gm-cell-renderer-text.[ch]: new cell renderer for rendering userlist * gnoemoe/mcp/gm-mcp-vmoo-client.c: update metrics in timeout so to reduce the number of updates when resizing * gnoemoe/mcp/gm-mcp-icecrew-serverinfo.c: max version set to 1.0 (1.0 does not actively request the info because it will be send on initialization). Set menu item invisible instead of insensitive when there is no info available * gnoemoe/mcp/gm-mcp-icecrew-userlist.c: fixed menu item substitution * gnoemoe/mcp/gm-mcp-vmoo-userlist.c: removed support for status because it doesn't really support it * gm-mcp-userlist-view.[ch]: moved column constants to header. Render items with new gm-cell-renderer-text. * gnoemoe/mcp/gm-mcp-icecrew-playerdb.[ch]: made gm_mcp_icecrew_playerdb_players public * gnoemoe/dialogs/Makefile.include: added gm-world-paste-dialog * gnoemoe/dialogs/gm-world-paste-dialog.[ch]: new paste dialog * gnoemoe/dialogs/gm-world-properties-dialog.c: * gnoemoe/dialogs/gm-world-logs-dialog.c: fixed leaking tree stores * gnoemoe/widgets/Makefile.include: added gm-commands.[ch] * gnoemoe/widgets/gm-commands.[ch]: new file for handling action activation (removed from gm-app-view) * gnoemoe/widgets/gm-world-view.c: fixed userlist size restore * gnoemoe/widgets/gm-app-view.c: removed action handlers * gnoemoe/gm-support.[ch]: added gm_find_child * gnoemoe/gm-world.c: removed debug message * gnoemoe/gm-ui.h: changed actions to gm-commands
2006-04-23 16:51:04 +02:00
#include "gm-marshal.h"
2005-11-07 10:56:25 +01:00
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_button_replace_clicked(GtkButton *button,
GmAppView *view);
void on_gm_app_view_button_replace_all_clicked(GtkButton *button,
GmAppView *view);
void on_gm_app_view_expander_replace(GObject *object, GParamSpec *param_spec,
GmAppView *view);
2005-11-07 10:56:25 +01:00
void on_gm_app_view_notebook_switch_page(GtkNotebook * notebook,
GtkNotebookPage * page, guint page_num, GmAppView *view);
void on_gm_app_view_world_view_notebook_switch_page(GtkNotebook * notebook,
GtkNotebookPage * page, guint page_num, GmAppView *view);
2005-11-07 10:56:25 +01:00
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);
void on_gm_app_view_check_button_search_sensitive_toggled(
GtkToggleButton *button, GmAppView *view);
2005-11-07 10:56:25 +01:00
gboolean on_gm_app_view_tray_button_press(GmTray *tray, GdkEventButton *event,
GmAppView *view);
void on_gm_app_view_tray_message_clicked(GmTray *tray, GmAppView *view);
void on_gm_app_view_tray_destroy(GtkWidget *caller, GmAppView *view);
void on_gm_app_view_world_mcp_package_created(GmMcpSession *session,
GmMcpPackage *package, GmAppView *view);
2005-11-07 10:56:25 +01:00
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, GParamSpec *pspec,
GmAppView *view);
void on_gm_app_view_world_active_changed(GmWorld *world, GParamSpec *pspec,
GmAppView *view);
void on_gm_app_view_world_activity_changed(GmWorld *world, GParamSpec *pspec,
2005-11-07 10:56:25 +01:00
GmAppView *view);
void on_gm_app_view_world_state_changing(GmWorld *world, GmNetState state,
GmAppView *view);
void on_gm_app_view_world_notify_message(GmWorld *world, gchar const *message,
2005-11-07 10:56:25 +01:00
GmAppView *view);
void on_gm_app_view_world_view_destroy(GmWorldView *world_view,
GmAppView *view);
2005-11-07 10:56:25 +01:00
#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;
GtkActionGroup *editor_action_group;
2005-11-07 10:56:25 +01:00
GHashTable *world_menu_items;
GmTray *tray;
2005-11-07 10:56:25 +01:00
GtkNotebook *notebook;
GmWorld *active_world;
GtkMenuBar *menu;
GtkToolbar *toolbar;
2005-11-07 10:56:25 +01:00
GtkLabel *label_replace;
GtkExpander *expander_replace;
2005-11-07 10:56:25 +01:00
GtkEntry *entry_find;
GtkEntry *entry_replace;
2005-11-07 10:56:25 +01:00
GtkVBox *vbox_find;
GtkHBox *hbox_control_find;
GtkHBox *hbox_replace;
2005-11-07 10:56:25 +01:00
GtkCheckButton *check_button_search_direction;
GtkCheckButton *check_button_search_sensitive;
gboolean ignore_toggling;
2005-11-07 10:56:25 +01:00
gboolean drag_in_progress;
gint motion_notify_handler_id;
gint x_start;
gint y_start;
gint tab;
2005-11-07 10:56:25 +01:00
GdkCursor *cursor;
2006-01-10 01:39:05 +01:00
guint tray_idle_create;
2006-03-30 00:56:10 +02:00
gint position_left;
gint position_top;
2005-11-07 10:56:25 +01:00
};
/* Signals */
* VERSION CHANGED TO 2.0.9 * po/POTFILES.in: added gnoemoe/dialogs/gm-world-paste-dialog.c and ui/gm-world-paste.glade * po/nl.po: added translations * ui/Makefile.am: * ui/gm-ui.xml: * ui/gm-world-paste.glade: new paste dialog * gnoemoe/mcp/Makefile.include: added gm-cell-renderer-text.[ch] * gnoemoe/mcp/gm-cell-renderer-text.[ch]: new cell renderer for rendering userlist * gnoemoe/mcp/gm-mcp-vmoo-client.c: update metrics in timeout so to reduce the number of updates when resizing * gnoemoe/mcp/gm-mcp-icecrew-serverinfo.c: max version set to 1.0 (1.0 does not actively request the info because it will be send on initialization). Set menu item invisible instead of insensitive when there is no info available * gnoemoe/mcp/gm-mcp-icecrew-userlist.c: fixed menu item substitution * gnoemoe/mcp/gm-mcp-vmoo-userlist.c: removed support for status because it doesn't really support it * gm-mcp-userlist-view.[ch]: moved column constants to header. Render items with new gm-cell-renderer-text. * gnoemoe/mcp/gm-mcp-icecrew-playerdb.[ch]: made gm_mcp_icecrew_playerdb_players public * gnoemoe/dialogs/Makefile.include: added gm-world-paste-dialog * gnoemoe/dialogs/gm-world-paste-dialog.[ch]: new paste dialog * gnoemoe/dialogs/gm-world-properties-dialog.c: * gnoemoe/dialogs/gm-world-logs-dialog.c: fixed leaking tree stores * gnoemoe/widgets/Makefile.include: added gm-commands.[ch] * gnoemoe/widgets/gm-commands.[ch]: new file for handling action activation (removed from gm-app-view) * gnoemoe/widgets/gm-world-view.c: fixed userlist size restore * gnoemoe/widgets/gm-app-view.c: removed action handlers * gnoemoe/gm-support.[ch]: added gm_find_child * gnoemoe/gm-world.c: removed debug message * gnoemoe/gm-ui.h: changed actions to gm-commands
2006-04-23 16:51:04 +02:00
enum {
ACTIVE_WORLD_CHANGED,
NUM_SIGNALS
2005-11-07 10:56:25 +01:00
};
* VERSION CHANGED TO 2.0.9 * po/POTFILES.in: added gnoemoe/dialogs/gm-world-paste-dialog.c and ui/gm-world-paste.glade * po/nl.po: added translations * ui/Makefile.am: * ui/gm-ui.xml: * ui/gm-world-paste.glade: new paste dialog * gnoemoe/mcp/Makefile.include: added gm-cell-renderer-text.[ch] * gnoemoe/mcp/gm-cell-renderer-text.[ch]: new cell renderer for rendering userlist * gnoemoe/mcp/gm-mcp-vmoo-client.c: update metrics in timeout so to reduce the number of updates when resizing * gnoemoe/mcp/gm-mcp-icecrew-serverinfo.c: max version set to 1.0 (1.0 does not actively request the info because it will be send on initialization). Set menu item invisible instead of insensitive when there is no info available * gnoemoe/mcp/gm-mcp-icecrew-userlist.c: fixed menu item substitution * gnoemoe/mcp/gm-mcp-vmoo-userlist.c: removed support for status because it doesn't really support it * gm-mcp-userlist-view.[ch]: moved column constants to header. Render items with new gm-cell-renderer-text. * gnoemoe/mcp/gm-mcp-icecrew-playerdb.[ch]: made gm_mcp_icecrew_playerdb_players public * gnoemoe/dialogs/Makefile.include: added gm-world-paste-dialog * gnoemoe/dialogs/gm-world-paste-dialog.[ch]: new paste dialog * gnoemoe/dialogs/gm-world-properties-dialog.c: * gnoemoe/dialogs/gm-world-logs-dialog.c: fixed leaking tree stores * gnoemoe/widgets/Makefile.include: added gm-commands.[ch] * gnoemoe/widgets/gm-commands.[ch]: new file for handling action activation (removed from gm-app-view) * gnoemoe/widgets/gm-world-view.c: fixed userlist size restore * gnoemoe/widgets/gm-app-view.c: removed action handlers * gnoemoe/gm-support.[ch]: added gm_find_child * gnoemoe/gm-world.c: removed debug message * gnoemoe/gm-ui.h: changed actions to gm-commands
2006-04-23 16:51:04 +02:00
static guint gm_app_view_signals[NUM_SIGNALS] = {0};
2005-11-07 10:56:25 +01:00
G_DEFINE_TYPE(GmAppView, gm_app_view, GTK_TYPE_WINDOW)
static void
gm_app_view_finalize(GObject *object) {
GmAppView *view = GM_APP_VIEW(object);
2006-01-06 01:27:43 +01:00
#ifdef HAVE_RUBY
2005-11-07 10:56:25 +01:00
gm_scripts_dialog_fini();
2006-01-06 01:27:43 +01:00
#endif
2005-11-07 10:56:25 +01:00
if (view->priv->cursor) {
gdk_cursor_unref(view->priv->cursor);
}
2006-01-10 01:39:05 +01:00
if (view->priv->tray_idle_create) {
g_source_remove(view->priv->tray_idle_create);
}
if (view->priv->tray) {
g_signal_handlers_disconnect_by_func(view->priv->tray,
on_gm_app_view_tray_destroy, view);
gtk_widget_destroy(GTK_WIDGET(view->priv->tray));
g_object_unref(view->priv->tray);
}
2005-11-07 10:56:25 +01:00
g_hash_table_destroy(view->priv->world_menu_items);
G_OBJECT_CLASS(gm_app_view_parent_class)->finalize(object);
}
* VERSION CHANGED TO 2.0.9 * po/POTFILES.in: added gnoemoe/dialogs/gm-world-paste-dialog.c and ui/gm-world-paste.glade * po/nl.po: added translations * ui/Makefile.am: * ui/gm-ui.xml: * ui/gm-world-paste.glade: new paste dialog * gnoemoe/mcp/Makefile.include: added gm-cell-renderer-text.[ch] * gnoemoe/mcp/gm-cell-renderer-text.[ch]: new cell renderer for rendering userlist * gnoemoe/mcp/gm-mcp-vmoo-client.c: update metrics in timeout so to reduce the number of updates when resizing * gnoemoe/mcp/gm-mcp-icecrew-serverinfo.c: max version set to 1.0 (1.0 does not actively request the info because it will be send on initialization). Set menu item invisible instead of insensitive when there is no info available * gnoemoe/mcp/gm-mcp-icecrew-userlist.c: fixed menu item substitution * gnoemoe/mcp/gm-mcp-vmoo-userlist.c: removed support for status because it doesn't really support it * gm-mcp-userlist-view.[ch]: moved column constants to header. Render items with new gm-cell-renderer-text. * gnoemoe/mcp/gm-mcp-icecrew-playerdb.[ch]: made gm_mcp_icecrew_playerdb_players public * gnoemoe/dialogs/Makefile.include: added gm-world-paste-dialog * gnoemoe/dialogs/gm-world-paste-dialog.[ch]: new paste dialog * gnoemoe/dialogs/gm-world-properties-dialog.c: * gnoemoe/dialogs/gm-world-logs-dialog.c: fixed leaking tree stores * gnoemoe/widgets/Makefile.include: added gm-commands.[ch] * gnoemoe/widgets/gm-commands.[ch]: new file for handling action activation (removed from gm-app-view) * gnoemoe/widgets/gm-world-view.c: fixed userlist size restore * gnoemoe/widgets/gm-app-view.c: removed action handlers * gnoemoe/gm-support.[ch]: added gm_find_child * gnoemoe/gm-world.c: removed debug message * gnoemoe/gm-ui.h: changed actions to gm-commands
2006-04-23 16:51:04 +02:00
static gboolean
gm_app_view_delete_event(GtkWidget *widget, GdkEventAny *event) {
gboolean ret = FALSE;
if (GTK_WIDGET_CLASS(gm_app_view_parent_class)->delete_event) {
ret = GTK_WIDGET_CLASS(gm_app_view_parent_class)->delete_event(widget, event);
}
gtk_main_quit();
* VERSION CHANGED TO 2.0.9 * po/POTFILES.in: added gnoemoe/dialogs/gm-world-paste-dialog.c and ui/gm-world-paste.glade * po/nl.po: added translations * ui/Makefile.am: * ui/gm-ui.xml: * ui/gm-world-paste.glade: new paste dialog * gnoemoe/mcp/Makefile.include: added gm-cell-renderer-text.[ch] * gnoemoe/mcp/gm-cell-renderer-text.[ch]: new cell renderer for rendering userlist * gnoemoe/mcp/gm-mcp-vmoo-client.c: update metrics in timeout so to reduce the number of updates when resizing * gnoemoe/mcp/gm-mcp-icecrew-serverinfo.c: max version set to 1.0 (1.0 does not actively request the info because it will be send on initialization). Set menu item invisible instead of insensitive when there is no info available * gnoemoe/mcp/gm-mcp-icecrew-userlist.c: fixed menu item substitution * gnoemoe/mcp/gm-mcp-vmoo-userlist.c: removed support for status because it doesn't really support it * gm-mcp-userlist-view.[ch]: moved column constants to header. Render items with new gm-cell-renderer-text. * gnoemoe/mcp/gm-mcp-icecrew-playerdb.[ch]: made gm_mcp_icecrew_playerdb_players public * gnoemoe/dialogs/Makefile.include: added gm-world-paste-dialog * gnoemoe/dialogs/gm-world-paste-dialog.[ch]: new paste dialog * gnoemoe/dialogs/gm-world-properties-dialog.c: * gnoemoe/dialogs/gm-world-logs-dialog.c: fixed leaking tree stores * gnoemoe/widgets/Makefile.include: added gm-commands.[ch] * gnoemoe/widgets/gm-commands.[ch]: new file for handling action activation (removed from gm-app-view) * gnoemoe/widgets/gm-world-view.c: fixed userlist size restore * gnoemoe/widgets/gm-app-view.c: removed action handlers * gnoemoe/gm-support.[ch]: added gm_find_child * gnoemoe/gm-world.c: removed debug message * gnoemoe/gm-ui.h: changed actions to gm-commands
2006-04-23 16:51:04 +02:00
return ret;
}
static gboolean
gm_app_view_focus_in_event(GtkWidget *widget, GdkEventFocus *event) {
GmAppView *view = GM_APP_VIEW(widget);
GmWorld *world;
world = gm_app_view_active_world(view);
if (world) {
gm_world_set_active(world, TRUE);
}
if (view->priv->tray) {
gm_tray_normal(view->priv->tray);
}
gtk_window_set_urgency_hint(GTK_WINDOW(view), FALSE);
if (GTK_WIDGET_CLASS(gm_app_view_parent_class)->focus_in_event) {
return GTK_WIDGET_CLASS(gm_app_view_parent_class)->focus_in_event(
widget, event);
}
return FALSE;
}
static gboolean
gm_app_view_focus_out_event(GtkWidget *widget, GdkEventFocus *event) {
GmAppView *view = GM_APP_VIEW(widget);
GmWorld *world;
world = gm_app_view_active_world(view);
if (world) {
// Set the world to inactive so activity is counted and tray will
// update properly
gm_world_set_active(world, FALSE);
}
if (GTK_WIDGET_CLASS(gm_app_view_parent_class)->focus_out_event) {
return GTK_WIDGET_CLASS(gm_app_view_parent_class)->focus_out_event(
widget, event);
}
return FALSE;
2006-01-10 01:39:05 +01:00
}
static void
gm_app_view_size_allocate(GtkWidget *widget, GtkAllocation *allocation) {
GmAppView *view = GM_APP_VIEW(widget);
gm_options_set_int(gm_app_options(view->priv->application), "width",
allocation->width);
gm_options_set_int(gm_app_options(view->priv->application), "height",
allocation->height);
if (GTK_WIDGET_CLASS(gm_app_view_parent_class)->size_allocate) {
GTK_WIDGET_CLASS(gm_app_view_parent_class)->size_allocate(widget,
allocation);
}
}
static gboolean
gm_app_view_window_state_event(GtkWidget *widget, GdkEventWindowState *event) {
GmAppView *view = GM_APP_VIEW(widget);
if (event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED &&
GTK_WIDGET_VISIBLE(widget)) {
gm_options_set_int(gm_app_options(view->priv->application), "maximized",
(event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) != 0);
}
if (GTK_WIDGET_CLASS(gm_app_view_parent_class)->window_state_event) {
return GTK_WIDGET_CLASS(gm_app_view_parent_class)->window_state_event(
widget, event);
}
return FALSE;
}
2005-11-07 10:56:25 +01:00
static void
gm_app_view_class_init(GmAppViewClass *klass) {
GObjectClass *object_class = G_OBJECT_CLASS(klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
2005-11-07 10:56:25 +01:00
object_class->finalize = gm_app_view_finalize;
* VERSION CHANGED TO 2.0.9 * po/POTFILES.in: added gnoemoe/dialogs/gm-world-paste-dialog.c and ui/gm-world-paste.glade * po/nl.po: added translations * ui/Makefile.am: * ui/gm-ui.xml: * ui/gm-world-paste.glade: new paste dialog * gnoemoe/mcp/Makefile.include: added gm-cell-renderer-text.[ch] * gnoemoe/mcp/gm-cell-renderer-text.[ch]: new cell renderer for rendering userlist * gnoemoe/mcp/gm-mcp-vmoo-client.c: update metrics in timeout so to reduce the number of updates when resizing * gnoemoe/mcp/gm-mcp-icecrew-serverinfo.c: max version set to 1.0 (1.0 does not actively request the info because it will be send on initialization). Set menu item invisible instead of insensitive when there is no info available * gnoemoe/mcp/gm-mcp-icecrew-userlist.c: fixed menu item substitution * gnoemoe/mcp/gm-mcp-vmoo-userlist.c: removed support for status because it doesn't really support it * gm-mcp-userlist-view.[ch]: moved column constants to header. Render items with new gm-cell-renderer-text. * gnoemoe/mcp/gm-mcp-icecrew-playerdb.[ch]: made gm_mcp_icecrew_playerdb_players public * gnoemoe/dialogs/Makefile.include: added gm-world-paste-dialog * gnoemoe/dialogs/gm-world-paste-dialog.[ch]: new paste dialog * gnoemoe/dialogs/gm-world-properties-dialog.c: * gnoemoe/dialogs/gm-world-logs-dialog.c: fixed leaking tree stores * gnoemoe/widgets/Makefile.include: added gm-commands.[ch] * gnoemoe/widgets/gm-commands.[ch]: new file for handling action activation (removed from gm-app-view) * gnoemoe/widgets/gm-world-view.c: fixed userlist size restore * gnoemoe/widgets/gm-app-view.c: removed action handlers * gnoemoe/gm-support.[ch]: added gm_find_child * gnoemoe/gm-world.c: removed debug message * gnoemoe/gm-ui.h: changed actions to gm-commands
2006-04-23 16:51:04 +02:00
widget_class->delete_event = gm_app_view_delete_event;
widget_class->focus_in_event = gm_app_view_focus_in_event;
widget_class->focus_out_event = gm_app_view_focus_out_event;
2006-01-10 01:39:05 +01:00
widget_class->size_allocate = gm_app_view_size_allocate;
widget_class->window_state_event = gm_app_view_window_state_event;
* VERSION CHANGED TO 2.0.9 * po/POTFILES.in: added gnoemoe/dialogs/gm-world-paste-dialog.c and ui/gm-world-paste.glade * po/nl.po: added translations * ui/Makefile.am: * ui/gm-ui.xml: * ui/gm-world-paste.glade: new paste dialog * gnoemoe/mcp/Makefile.include: added gm-cell-renderer-text.[ch] * gnoemoe/mcp/gm-cell-renderer-text.[ch]: new cell renderer for rendering userlist * gnoemoe/mcp/gm-mcp-vmoo-client.c: update metrics in timeout so to reduce the number of updates when resizing * gnoemoe/mcp/gm-mcp-icecrew-serverinfo.c: max version set to 1.0 (1.0 does not actively request the info because it will be send on initialization). Set menu item invisible instead of insensitive when there is no info available * gnoemoe/mcp/gm-mcp-icecrew-userlist.c: fixed menu item substitution * gnoemoe/mcp/gm-mcp-vmoo-userlist.c: removed support for status because it doesn't really support it * gm-mcp-userlist-view.[ch]: moved column constants to header. Render items with new gm-cell-renderer-text. * gnoemoe/mcp/gm-mcp-icecrew-playerdb.[ch]: made gm_mcp_icecrew_playerdb_players public * gnoemoe/dialogs/Makefile.include: added gm-world-paste-dialog * gnoemoe/dialogs/gm-world-paste-dialog.[ch]: new paste dialog * gnoemoe/dialogs/gm-world-properties-dialog.c: * gnoemoe/dialogs/gm-world-logs-dialog.c: fixed leaking tree stores * gnoemoe/widgets/Makefile.include: added gm-commands.[ch] * gnoemoe/widgets/gm-commands.[ch]: new file for handling action activation (removed from gm-app-view) * gnoemoe/widgets/gm-world-view.c: fixed userlist size restore * gnoemoe/widgets/gm-app-view.c: removed action handlers * gnoemoe/gm-support.[ch]: added gm_find_child * gnoemoe/gm-world.c: removed debug message * gnoemoe/gm-ui.h: changed actions to gm-commands
2006-04-23 16:51:04 +02:00
gm_app_view_signals[ACTIVE_WORLD_CHANGED] =
g_signal_new("active_world_changed",
G_OBJECT_CLASS_TYPE(object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(GmAppViewClass, active_world_changed),
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE,
1,
G_TYPE_OBJECT);
2005-11-07 10:56:25 +01:00
g_type_class_add_private(object_class, sizeof(GmAppViewPrivate));
}
void
gm_app_view_create_ui(GmAppView *view) {
2005-11-07 10:56:25 +01:00
GError *error = NULL;
GtkActionGroup *action_group;
GtkAction *action;
#ifdef HAVE_PARSER
guint merge_id;
#endif
2005-11-07 10:56:25 +01:00
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) {
2006-01-10 01:39:05 +01:00
gm_debug_msg(DEBUG_ALWAYS, "Could not merge UI file");
2005-11-07 10:56:25 +01:00
g_error_free(error);
g_object_unref(view->priv->manager);
view->priv->manager = NULL;
return;
2005-11-07 10:56:25 +01:00
}
/* World sensitive actions */
2005-11-07 10:56:25 +01:00
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);
/* World insensitive actions */
2005-11-07 10:56:25 +01:00
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);
/* Worlds list action group */
2005-11-07 10:56:25 +01:00
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);
/* Editor action group */
view->priv->editor_action_group =
gtk_action_group_new("GmAppViewEditorActions");
gtk_action_group_set_translation_domain(view->priv->editor_action_group,
GETTEXT_PACKAGE);
gtk_action_group_add_actions(view->priv->editor_action_group,
gm_editor_entries, G_N_ELEMENTS(gm_editor_entries), view);
gtk_ui_manager_insert_action_group(view->priv->manager,
view->priv->editor_action_group, 0);
* VERSION CHANGED TO 2.0.9 * po/POTFILES.in: added gnoemoe/dialogs/gm-world-paste-dialog.c and ui/gm-world-paste.glade * po/nl.po: added translations * ui/Makefile.am: * ui/gm-ui.xml: * ui/gm-world-paste.glade: new paste dialog * gnoemoe/mcp/Makefile.include: added gm-cell-renderer-text.[ch] * gnoemoe/mcp/gm-cell-renderer-text.[ch]: new cell renderer for rendering userlist * gnoemoe/mcp/gm-mcp-vmoo-client.c: update metrics in timeout so to reduce the number of updates when resizing * gnoemoe/mcp/gm-mcp-icecrew-serverinfo.c: max version set to 1.0 (1.0 does not actively request the info because it will be send on initialization). Set menu item invisible instead of insensitive when there is no info available * gnoemoe/mcp/gm-mcp-icecrew-userlist.c: fixed menu item substitution * gnoemoe/mcp/gm-mcp-vmoo-userlist.c: removed support for status because it doesn't really support it * gm-mcp-userlist-view.[ch]: moved column constants to header. Render items with new gm-cell-renderer-text. * gnoemoe/mcp/gm-mcp-icecrew-playerdb.[ch]: made gm_mcp_icecrew_playerdb_players public * gnoemoe/dialogs/Makefile.include: added gm-world-paste-dialog * gnoemoe/dialogs/gm-world-paste-dialog.[ch]: new paste dialog * gnoemoe/dialogs/gm-world-properties-dialog.c: * gnoemoe/dialogs/gm-world-logs-dialog.c: fixed leaking tree stores * gnoemoe/widgets/Makefile.include: added gm-commands.[ch] * gnoemoe/widgets/gm-commands.[ch]: new file for handling action activation (removed from gm-app-view) * gnoemoe/widgets/gm-world-view.c: fixed userlist size restore * gnoemoe/widgets/gm-app-view.c: removed action handlers * gnoemoe/gm-support.[ch]: added gm_find_child * gnoemoe/gm-world.c: removed debug message * gnoemoe/gm-ui.h: changed actions to gm-commands
2006-04-23 16:51:04 +02:00
gtk_action_group_set_visible(view->priv->editor_action_group, FALSE);
* VERSION CHANGED TO 2.0.9 * po/POTFILES.in: added gnoemoe/dialogs/gm-world-paste-dialog.c and ui/gm-world-paste.glade * po/nl.po: added translations * ui/Makefile.am: * ui/gm-ui.xml: * ui/gm-world-paste.glade: new paste dialog * gnoemoe/mcp/Makefile.include: added gm-cell-renderer-text.[ch] * gnoemoe/mcp/gm-cell-renderer-text.[ch]: new cell renderer for rendering userlist * gnoemoe/mcp/gm-mcp-vmoo-client.c: update metrics in timeout so to reduce the number of updates when resizing * gnoemoe/mcp/gm-mcp-icecrew-serverinfo.c: max version set to 1.0 (1.0 does not actively request the info because it will be send on initialization). Set menu item invisible instead of insensitive when there is no info available * gnoemoe/mcp/gm-mcp-icecrew-userlist.c: fixed menu item substitution * gnoemoe/mcp/gm-mcp-vmoo-userlist.c: removed support for status because it doesn't really support it * gm-mcp-userlist-view.[ch]: moved column constants to header. Render items with new gm-cell-renderer-text. * gnoemoe/mcp/gm-mcp-icecrew-playerdb.[ch]: made gm_mcp_icecrew_playerdb_players public * gnoemoe/dialogs/Makefile.include: added gm-world-paste-dialog * gnoemoe/dialogs/gm-world-paste-dialog.[ch]: new paste dialog * gnoemoe/dialogs/gm-world-properties-dialog.c: * gnoemoe/dialogs/gm-world-logs-dialog.c: fixed leaking tree stores * gnoemoe/widgets/Makefile.include: added gm-commands.[ch] * gnoemoe/widgets/gm-commands.[ch]: new file for handling action activation (removed from gm-app-view) * gnoemoe/widgets/gm-world-view.c: fixed userlist size restore * gnoemoe/widgets/gm-app-view.c: removed action handlers * gnoemoe/gm-support.[ch]: added gm_find_child * gnoemoe/gm-world.c: removed debug message * gnoemoe/gm-ui.h: changed actions to gm-commands
2006-04-23 16:51:04 +02:00
gtk_action_group_set_sensitive(view->priv->editor_action_group, FALSE);
2005-11-07 10:56:25 +01:00
#ifndef HAVE_RUBY
gtk_action_set_sensitive(gm_app_view_action(view,
"/MenuBar/EditMenu/EditScriptsMenu"), FALSE);
2005-11-07 10:56:25 +01:00
#endif
#ifdef HAVE_PARSER
merge_id = gtk_ui_manager_new_merge_id(view->priv->manager);
gtk_ui_manager_add_ui(view->priv->manager, merge_id,
"/MenuBar/EditorMenu/EditorMenuAdditions", "EditorParseMenu",
"EditorParse", GTK_UI_MANAGER_MENUITEM, FALSE);
merge_id = gtk_ui_manager_new_merge_id(view->priv->manager);
gtk_ui_manager_add_ui(view->priv->manager, merge_id,
"/ToolBar/EditorToolAdditions", "EditorParseTool",
"EditorParse", GTK_UI_MANAGER_TOOLITEM, FALSE);
#endif
action = gm_app_view_action(view, "/MenuBar/WorldMenu/WorldOpenMenu");
g_object_set(action, "short-label", _("Open"), NULL);
2005-11-07 10:56:25 +01:00
}
GtkWidget *
create_button(gchar *label, gchar *stock) {
GtkWidget *align = gtk_alignment_new(0.5, 0.5, 0.0, 0.0);
GtkWidget *button = gtk_button_new();
GtkWidget *hbox = gtk_hbox_new(FALSE, 2);
gtk_container_add(GTK_CONTAINER(button), align);
gtk_container_add(GTK_CONTAINER(align), hbox);
gtk_box_pack_start(GTK_BOX(hbox), gtk_image_new_from_stock(
stock, GTK_ICON_SIZE_BUTTON), FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox),
gtk_label_new(label), FALSE, FALSE, 0);
return button;
}
2005-11-07 10:56:25 +01:00
GtkWidget *
gm_app_view_create_search_box(GmAppView *view) {
GtkWidget *vbox = gtk_vbox_new(FALSE, 3);
GtkWidget *table = gtk_table_new(2, 2, FALSE);
GtkWidget *hbox;
GtkWidget *hbox_control = gtk_hbox_new(FALSE, 6);
GtkWidget *lbl;
GtkWidget *entry;
GtkWidget *button;
GtkWidget *align;
GtkWidget *check_button;
2005-11-07 10:56:25 +01:00
GtkWidget *button_close = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
GtkWidget *separator = gtk_hseparator_new();
GtkWidget *expander = gtk_expander_new(NULL);
gtk_container_set_border_width(GTK_CONTAINER(table), 3);
hbox = gtk_hbox_new(FALSE, 6);
lbl = gtk_label_new(_("Find:"));
gtk_misc_set_alignment(GTK_MISC(lbl), 1.0, 0.5);
gtk_widget_set_sensitive(expander, FALSE);
align = gtk_alignment_new(0.0, 0.5, 0.0, 0.0);
gtk_container_add(GTK_CONTAINER(align), expander);
g_signal_connect(expander, "notify::expanded",
G_CALLBACK(on_gm_app_view_expander_replace), view);
gtk_box_pack_start(GTK_BOX(hbox), align, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), lbl, FALSE, FALSE, 0);
gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, 0, 1, GTK_SHRINK | GTK_FILL,
GTK_SHRINK | GTK_FILL, 0.0, 0.0);
lbl = gtk_label_new(_("Replace:"));
view->priv->label_replace = GTK_LABEL(lbl);
gtk_misc_set_alignment(GTK_MISC(lbl), 1.0, 0.5);
gtk_table_attach(GTK_TABLE(table), lbl, 0, 1, 1, 2, GTK_SHRINK | GTK_FILL,
GTK_SHRINK | GTK_FILL, 0.0, 0.0);
hbox = gtk_hbox_new(FALSE, 6);
2005-11-07 10:56:25 +01:00
gtk_container_set_border_width(GTK_CONTAINER(hbox), 3);
gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL,
GTK_SHRINK | GTK_FILL, 0.0, 0.0);
2005-11-07 10:56:25 +01:00
gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox), separator, FALSE, TRUE, 0);
2005-11-07 10:56:25 +01:00
entry = gtk_entry_new();
view->priv->entry_find = GTK_ENTRY(entry);
button = create_button(_("Find next"), GTK_STOCK_FIND);
g_signal_connect(button, "clicked",
G_CALLBACK(on_gm_app_view_entry_find_activate), view);
g_signal_connect(entry, "key_press_event",
G_CALLBACK(on_gm_app_view_entry_find_key_press), view);
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);
gtk_box_pack_start(GTK_BOX(hbox_control), entry, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox_control), button, FALSE, FALSE, 0);
check_button = gtk_check_button_new_with_label(_("Search backwards"));
g_signal_connect(check_button, "toggled",
G_CALLBACK(on_gm_app_view_check_button_search_direction_toggled),
view);
view->priv->check_button_search_direction = GTK_CHECK_BUTTON(check_button);
gtk_box_pack_start(GTK_BOX(hbox_control), check_button, FALSE, FALSE, 0);
check_button = gtk_check_button_new_with_label(_("Match case"));
g_signal_connect(check_button, "toggled",
G_CALLBACK(on_gm_app_view_check_button_search_sensitive_toggled),
view);
view->priv->check_button_search_sensitive = GTK_CHECK_BUTTON(check_button);
gtk_box_pack_start(GTK_BOX(hbox_control), check_button, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), hbox_control, FALSE, FALSE, 0);
2005-11-07 10:56:25 +01:00
gtk_box_pack_end(GTK_BOX(hbox), button_close, FALSE, FALSE, 0);
hbox = gtk_hbox_new(FALSE, 6);
gtk_container_set_border_width(GTK_CONTAINER(hbox), 3);
entry = gtk_entry_new();
g_signal_connect(entry, "key_press_event",
G_CALLBACK(on_gm_app_view_entry_find_key_press), view);
view->priv->entry_replace = GTK_ENTRY(entry);
gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 0);
button = create_button(_("Replace"), GTK_STOCK_FIND_AND_REPLACE);
g_signal_connect(button, "clicked",
G_CALLBACK(on_gm_app_view_button_replace_clicked), view);
gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
button = gtk_button_new_with_label(_("Replace all"));
g_signal_connect(button, "clicked",
G_CALLBACK(on_gm_app_view_button_replace_all_clicked), view);
gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 1, 2, GTK_EXPAND | GTK_FILL,
GTK_SHRINK | GTK_FILL, 0.0, 0.0);
view->priv->expander_replace = GTK_EXPANDER(expander);
view->priv->hbox_replace = GTK_HBOX(hbox);
2005-11-07 10:56:25 +01:00
view->priv->vbox_find = GTK_VBOX(vbox);
view->priv->hbox_control_find = GTK_HBOX(hbox_control);
view->priv->ignore_toggling = FALSE;
2005-11-07 10:56:25 +01:00
gtk_widget_show_all(vbox);
gtk_widget_hide(GTK_WIDGET(view->priv->label_replace));
gtk_widget_hide(GTK_WIDGET(view->priv->hbox_replace));
2005-11-07 10:56:25 +01:00
gtk_widget_hide(vbox);
2005-11-07 10:56:25 +01:00
g_signal_connect(button_close, "clicked",
G_CALLBACK(on_gm_app_view_button_find_close_clicked), 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);
}
2006-01-10 01:39:05 +01:00
static void
gm_app_view_create_tray(GmAppView *view) {
view->priv->tray = g_object_ref(gm_tray_new(_("GnoeMoe Gnome MOO Client")));
gm_tray_set_icon(view->priv->tray, TRAY_STATE_NORMAL,
gm_pixbuf_get("tray/default.svg"));
gm_tray_set_icon(view->priv->tray, TRAY_STATE_ACTIVE,
gm_pixbuf_get("tray/active.svg"));
gm_tray_set_icon(view->priv->tray, TRAY_STATE_NOTIFY,
gm_pixbuf_get("tray/notify.svg"));
gm_tray_set_icon(view->priv->tray, TRAY_STATE_ACTIVITY,
gm_pixbuf_get("tray/activity.svg"));
gtk_widget_show(GTK_WIDGET(view->priv->tray));
g_signal_connect(view->priv->tray, "message-clicked",
G_CALLBACK(on_gm_app_view_tray_message_clicked), view);
2006-01-10 01:39:05 +01:00
g_signal_connect(view->priv->tray, "button-press-event",
G_CALLBACK(on_gm_app_view_tray_button_press), view);
g_signal_connect(view->priv->tray, "destroy",
G_CALLBACK(on_gm_app_view_tray_destroy), view);
}
2005-11-07 10:56:25 +01:00
static void
gm_app_view_init(GmAppView *view) {
GtkWidget *menu = NULL;
GtkWidget *toolbar = NULL;
2005-11-07 10:56:25 +01:00
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);
gm_app_view_create_ui(view);
2006-01-10 01:39:05 +01:00
if (view->priv->manager) {
menu = gtk_ui_manager_get_widget(view->priv->manager, "/MenuBar");
if (menu) {
gtk_widget_show(menu);
gtk_box_pack_start(GTK_BOX(vbox), menu, FALSE, TRUE, 0);
}
toolbar = gtk_ui_manager_get_widget(view->priv->manager, "/ToolBar");
if (toolbar) {
gtk_widget_show(toolbar);
gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, TRUE, 0);
}
}
2005-11-07 10:56:25 +01:00
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->toolbar = GTK_TOOLBAR(toolbar);
2005-11-07 10:56:25 +01:00
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"));
/* 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;
2006-01-06 01:27:43 +01:00
#ifdef HAVE_RUBY
2005-11-07 10:56:25 +01:00
gm_scripts_dialog_init();
2006-01-06 01:27:43 +01:00
#endif
2006-01-10 01:39:05 +01:00
gm_app_view_create_tray(view);
2005-11-07 10:56:25 +01:00
}
2006-03-30 00:56:10 +02:00
static void
gm_app_view_store_position(GmAppView *view) {
gtk_window_get_position(GTK_WINDOW(view), &(view->priv->position_left),
&(view->priv->position_top));
}
static void
gm_app_view_restore_position(GmAppView *view) {
gtk_window_move(GTK_WINDOW(view), view->priv->position_left,
view->priv->position_top);
}
static void
2006-01-10 01:39:05 +01:00
gm_app_view_restore_size(GmAppView *view) {
gint width, height;
width = gm_options_get_int(gm_app_options(view->priv->application),
"width");
height = gm_options_get_int(gm_app_options(view->priv->application),
"height");
if (height > 10 && width > 10) {
gtk_window_set_default_size(GTK_WINDOW(view), width, height);
}
if (gm_options_get_int(gm_app_options(view->priv->application),
"maximized")) {
gtk_window_maximize(GTK_WINDOW(view));
}
}
2005-11-07 10:56:25 +01:00
// Public functions
GmAppView *
gm_app_view_new(GmApp *application) {
GmAppView *view = GM_APP_VIEW(g_object_new(GM_TYPE_APP_VIEW, NULL));
view->priv->application = application;
view->priv->active_world = NULL;
2006-01-10 01:39:05 +01:00
// Set stored width and height
gm_app_view_restore_size(view);
2005-11-07 10:56:25 +01:00
// Toggle search direction
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
view->priv->check_button_search_direction),
gm_options_get_int(gm_app_options(application),
"search_direction_world"));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
view->priv->check_button_search_sensitive),
gm_options_get_int(gm_app_options(application),
"search_sensitive"));
2005-11-07 10:56:25 +01:00
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;
}
GmApp const *
2005-11-07 10:56:25 +01:00
gm_app_view_application(GmAppView *view) {
return view->priv->application;
}
GtkNotebook *
gm_app_view_notebook(GmAppView *view) {
return view->priv->notebook;
}
2005-11-07 10:56:25 +01:00
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 == TRUE) {
gtk_action_set_visible(gtk_action_group_get_action(
view->priv->action_group, "WorldInfo"), FALSE);
}
if (!sens) {
2005-11-07 10:56:25 +01:00
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);
}
}
GtkMenuItem *
gm_app_view_menu_item(GmAppView *view, gchar const *path) {
GtkMenuItem *img = GTK_MENU_ITEM(
gtk_ui_manager_get_widget(view->priv->manager, path));
return img;
}
2005-11-07 10:56:25 +01:00
GtkAction *
gm_app_view_action(GmAppView *view, gchar const *path) {
GtkAction *action = gtk_ui_manager_get_action(view->priv->manager, path);
return action;
2005-11-07 10:56:25 +01:00
}
void
gm_app_view_update_connect_button(GmAppView *view, gboolean connected) {
GtkAction *action = gm_app_view_action(view,
"/MenuBar/WorldMenu/WorldConnectMenu");
2005-11-07 10:56:25 +01:00
if (!connected) {
g_object_set(action, "stock-id", GTK_STOCK_CONNECT, NULL);
g_object_set(action, "label", _("Connect"), NULL);
g_object_set(action, "tooltip", _("Connect the current world"), NULL);
2005-11-07 10:56:25 +01:00
} else {
g_object_set(action, "stock-id", GTK_STOCK_DISCONNECT, NULL);
g_object_set(action, "label", _("Disconnect"), NULL);
g_object_set(action, "tooltip", _("Disconnect the current world"), NULL);
2005-11-07 10:56:25 +01:00
}
}
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);
2005-11-07 10:56:25 +01:00
}
void
gm_app_view_worlds_loaded(GmAppView *view) {
gm_app_view_set_sensitivity(view, TRUE);
gtk_action_set_sensitive(gm_app_view_action(view,
"/MenuBar/EditMenu/EditReplaceMenu"), FALSE);
2005-11-07 10:56:25 +01:00
}
void
gm_app_view_update_tray(GmAppView *view) {
GList *worlds;
GmWorld *world;
gchar *tmp;
gboolean active = gtk_window_is_active(GTK_WINDOW(view));
gint activity;
GString *str = NULL;
if (!view->priv->tray) {
return;
2005-11-07 10:56:25 +01:00
}
if (!active) {
for (worlds = gm_app_worlds(view->priv->application); worlds;
worlds = worlds->next) {
world = GM_WORLD(worlds->data);
activity = gm_world_activity(world);
if (gm_world_loaded(world) && activity) {
if (!str) {
tmp = g_strdup_printf(_("Activity in:\n%s (%d)"),
gm_world_name(world), activity);
str = g_string_new(NULL);
} else {
tmp = g_strdup_printf(", %s (%d)",
gm_world_name(world), activity);
}
str = g_string_append(str, tmp);
g_free(tmp);
}
}
2005-11-07 10:56:25 +01:00
if (str) {
gm_tray_activate(view->priv->tray);
} else if (gm_tray_get_state(view->priv->tray) != TRAY_STATE_NOTIFY) {
gm_tray_normal(view->priv->tray);
}
if (gm_tray_get_state(view->priv->tray) != TRAY_STATE_NOTIFY) {
if (str) {
gm_tray_set_tip(view->priv->tray, str->str);
} else {
gm_tray_set_tip(view->priv->tray, NULL);
}
}
if (str) {
g_string_free(str, TRUE);
}
} else {
gm_tray_normal(view->priv->tray);
}
2005-11-07 10:56:25 +01:00
}
void
gm_app_view_toggle_visibility(GmAppView *view) {
gboolean visible = GTK_WIDGET_VISIBLE(view);
if (!visible || !gtk_window_is_active(GTK_WINDOW(view))) {
2006-01-10 01:39:05 +01:00
if (!visible) {
gm_app_view_restore_size(view);
2006-03-30 00:56:10 +02:00
gm_app_view_restore_position(view);
2006-01-10 01:39:05 +01:00
}
gtk_widget_show(GTK_WIDGET(view));
gtk_window_present(GTK_WINDOW(view));
gtk_widget_grab_focus(GTK_WIDGET(view));
if (view->priv->tray) {
gm_tray_normal(view->priv->tray);
}
} else if (view->priv->tray) {
2006-03-30 00:56:10 +02:00
gm_app_view_store_position(view);
gtk_widget_hide(GTK_WIDGET(view));
}
}
2005-11-07 10:56:25 +01:00
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_world_close_from_tab(GmWorldTab *tab, GmWorld *world) {
gm_world_unload(world);
}
void
on_gm_app_view_world_name_changed(GmWorld *world, GParamSpec *pspec,
2005-11-07 10:56:25 +01:00
GmAppView *view) {
GmAppViewWorldMenuItem *item = (GmAppViewWorldMenuItem *)
g_hash_table_lookup(view->priv->world_menu_items, world);
g_object_set(G_OBJECT(item->action), "label", gm_world_name(world), NULL);
2005-11-07 10:56:25 +01:00
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) {
GmAppViewWorldMenuItem *item = g_new0(GmAppViewWorldMenuItem, 1);
gchar *name = g_strconcat("WorldItem", gm_world_name(world), NULL);
2005-11-07 10:56:25 +01:00
gchar *tooltip = g_strconcat(_("Open world "), gm_world_name(world), NULL);
gchar *path;
GList *worlds, *position;
gboolean top;
// Find the world previous to this one
worlds = gm_app_worlds(app);
position = g_list_find(worlds, world);
2005-11-07 10:56:25 +01:00
if (!position || !position->prev) {
path = g_strdup("/MenuBar/WorldMenu/WorldMenuAdditions");
top = TRUE;
} else {
path = g_strconcat("/MenuBar/WorldMenu/WorldMenuAdditions/WorldItem",
gm_world_name((GmWorld *)(position->prev->data)), NULL);
top = FALSE;
}
2005-11-07 10:56:25 +01:00
/* 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,
path, name, name,
GTK_UI_MANAGER_MENUITEM, top);
g_free(path);
gtk_ui_manager_ensure_update(view->priv->manager);
2005-11-07 10:56:25 +01:00
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, "notify::name",
2005-11-07 10:56:25 +01:00
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, "notify::active",
2005-11-07 10:56:25 +01:00
G_CALLBACK(on_gm_app_view_world_active_changed), view);
g_signal_connect(world, "notify::activity",
G_CALLBACK(on_gm_app_view_world_activity_changed), view);
g_signal_connect(world, "notify_message",
G_CALLBACK(on_gm_app_view_world_notify_message), view);
2005-11-07 10:56:25 +01:00
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_CONNECTING:
2005-11-07 10:56:25 +01:00
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);
g_signal_connect(gm_world_get_mcp_session(world), "package_created",
G_CALLBACK(on_gm_app_view_world_mcp_package_created), view);
g_signal_connect(world_view, "switch_page",
G_CALLBACK(on_gm_app_view_world_view_notebook_switch_page), view);
g_signal_connect(world_view, "destroy",
G_CALLBACK(on_gm_app_view_world_view_destroy), view);
2005-11-07 10:56:25 +01:00
gtk_notebook_append_page(view->priv->notebook, world_view,
GTK_WIDGET(tab));
gtk_widget_show_all(world_view);
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);
g_signal_handlers_disconnect_by_func(gm_world_get_mcp_session(world),
on_gm_app_view_world_mcp_package_created, view);
if (world_view != NULL) {
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);
}
2005-11-07 10:56:25 +01:00
}
}
void
on_gm_app_view_world_activate_request(GmWorld *world, GmAppView *view) {
gm_world_set_active(world, TRUE);
}
void
on_gm_app_view_world_notify_message(GmWorld *world, gchar const *message,
GmAppView *view) {
if (!gtk_window_is_active(GTK_WINDOW(view))) {
if (view->priv->tray) {
gm_tray_notify(view->priv->tray, message);
}
gtk_window_set_urgency_hint(GTK_WINDOW(view), TRUE);
}
}
2005-11-07 10:56:25 +01:00
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);
2005-11-07 10:56:25 +01:00
}
void
on_gm_app_view_accel_switch_edit(GtkAccelGroup * accelgroup, GObject * arg1,
guint arg2, GdkModifierType arg3, AccelInfo *info) {
GmWorldView *view = gm_app_view_active_world_view(info->view);
2005-11-07 10:56:25 +01:00
if (view) {
gtk_notebook_set_current_page(GTK_NOTEBOOK(view), info->num);
}
2005-11-07 10:56:25 +01:00
}
void
on_gm_app_view_accel_cycle_page(GtkAccelGroup * accelgroup, GObject * arg1,
guint arg2, GdkModifierType arg3, AccelInfo *info) {
GtkNotebook *note = info->view->priv->notebook;
gint p = gtk_notebook_get_current_page(note) + info->num;
2005-11-07 10:56:25 +01:00
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);
}
2005-11-07 10:56:25 +01:00
}
void
on_gm_app_view_world_activate(GtkAction * action, GmWorld *world) {
gm_world_load(world);
}
GmSearchableSearchFlags
2005-11-07 10:56:25 +01:00
gm_app_view_search_flags(GmAppView *view) {
GmSearchableSearchFlags flags = 0;
2005-11-07 10:56:25 +01:00
gboolean active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
view->priv->check_button_search_direction));
gboolean sensitive = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
view->priv->check_button_search_sensitive));
2005-11-07 10:56:25 +01:00
if (active) {
flags = GM_SEARCHABLE_SEARCH_BACKWARDS;
2005-11-07 10:56:25 +01:00
} else {
flags = GM_SEARCHABLE_SEARCH_FORWARDS;
2005-11-07 10:56:25 +01:00
}
if (!sensitive) {
flags |= GM_SEARCHABLE_SEARCH_CASE_INSENSITIVE;
}
return flags;
2005-11-07 10:56:25 +01:00
}
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;
gchar const *text;
2005-11-07 10:56:25 +01:00
if (world_view) {
gdk_color_parse ("#ff6666", &red);
text = gtk_entry_get_text(entry);
if (gm_world_view_find_first(world_view, text,
gm_app_view_search_flags(view)) || *text == '\0') {
gtk_widget_modify_base(GTK_WIDGET(entry), GTK_STATE_NORMAL, NULL);
} else {
gtk_widget_modify_base(GTK_WIDGET(entry), GTK_STATE_NORMAL, &red);
}
}
2005-11-07 10:56:25 +01:00
return FALSE;
2005-11-07 10:56:25 +01:00
}
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
2006-01-10 01:39:05 +01:00
gm_app_view_show_replace_box(GmAppView *view) {
if (!GTK_WIDGET_VISIBLE(view->priv->hbox_replace)) {
gtk_widget_show(GTK_WIDGET(view->priv->label_replace));
gtk_widget_show(GTK_WIDGET(view->priv->hbox_replace));
}
}
2005-11-07 10:56:25 +01:00
void
gm_app_view_show_find_box(GmAppView *view) {
if (!GTK_WIDGET_VISIBLE(view->priv->vbox_find)) {
gtk_widget_show(GTK_WIDGET(view->priv->vbox_find));
}
}
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_edit_replace(GtkMenuItem * menuitem, GmAppView *view) {
GtkWidget *entry = GTK_WIDGET(view->priv->entry_replace);
gm_app_view_show_find_box(view);
gm_app_view_show_replace_box(view);
gtk_widget_grab_focus(entry);
}
2005-11-07 10:56:25 +01:00
void
on_gm_app_view_button_find_clicked(GtkButton *button, gpointer user_data) {
on_gm_app_view_edit_find_next(NULL, NULL);
}
void
on_gm_app_view_button_replace_clicked(GtkButton *button, GmAppView *view) {
if (gm_world_view_replace(gm_app_view_active_world_view(view),
gtk_entry_get_text(view->priv->entry_replace))) {
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_replace_all_clicked(GtkButton *button, GmAppView *view) {
gm_world_view_replace_all(gm_app_view_active_world_view(view),
gtk_entry_get_text(view->priv->entry_find),
gtk_entry_get_text(view->priv->entry_replace),
gm_app_view_search_flags(view));
}
void
on_gm_app_view_expander_replace(GObject *object, GParamSpec *param_spec,
GmAppView *view) {
gboolean exp = gtk_expander_get_expanded(view->priv->expander_replace);
if (exp) {
gm_app_view_show_replace_box(view);
} else {
gtk_widget_hide(GTK_WIDGET(view->priv->label_replace));
gtk_widget_hide(GTK_WIDGET(view->priv->hbox_replace));
}
}
2005-11-07 10:56:25 +01:00
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_sensitive_toggled(GtkToggleButton *button,
GmAppView *view) {
gboolean active = gtk_toggle_button_get_active(button);
gm_options_set_int(gm_app_options(view->priv->application),
"search_sensitive", active ? 1 : 0);
}
2005-11-07 10:56:25 +01:00
void
on_gm_app_view_check_button_search_direction_toggled(GtkToggleButton *button,
GmAppView *view) {
GmWorldView *active_view;
gboolean active;
2005-11-07 10:56:25 +01:00
if (view->priv->ignore_toggling) {
return;
}
active_view = gm_app_view_active_world_view(view);
if (active_view == NULL) {
return;
}
active = gtk_toggle_button_get_active(button);
if (gtk_notebook_get_current_page(GTK_NOTEBOOK(active_view)) == 0) {
gm_options_set_int(gm_app_options(view->priv->application),
"search_direction_world", active ? 1 : 0);
} else {
gm_options_set_int(gm_app_options(view->priv->application),
"search_direction", active ? 1 : 0);
}
2005-11-07 10:56:25 +01:00
}
/* 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)) {
2005-11-07 10:56:25 +01:00
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);
2005-11-07 10:56:25 +01:00
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);
2005-11-07 10:56:25 +01:00
}
}
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);
2005-11-07 10:56:25 +01:00
}
}
gboolean
on_gm_app_view_motion_notify(GtkWidget *widget, GdkEventMotion *event,
GmAppView *view) {
2005-11-07 10:56:25 +01:00
gint page_num;
if (view->priv->drag_in_progress == FALSE) {
if (gtk_drag_check_threshold(widget,
2005-11-07 10:56:25 +01:00
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->tab = tab_clicked;
view->priv->motion_notify_handler_id =
g_signal_connect(G_OBJECT(notebook), "motion-notify-event",
G_CALLBACK(on_gm_app_view_motion_notify), view);
} else if ((event->type == GDK_BUTTON_PRESS) && (event->button == 3)) {
if (tab_clicked == -1) {
/* Don't show context menu for non tabs */
return TRUE;
} else {
/* Switch to the page the mouse is over, but don't consume the event */
gtk_notebook_set_current_page(GTK_NOTEBOOK (notebook), tab_clicked);
}
2005-11-07 10:56:25 +01:00
}
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_world_view_notebook_switch_page(GtkNotebook *notebook,
GtkNotebookPage * p, guint page_num, GmAppView *view) {
GmWorldView *world_view = GM_WORLD_VIEW(notebook);
GtkWidget *page;
gboolean direction;
gboolean can_replace;
gboolean can_find;
if (!GTK_IS_WIDGET(view) || !GTK_IS_WIDGET(view->priv->hbox_control_find))
return;
can_find = gm_world_view_page_can_find(world_view, page_num);
gtk_action_set_sensitive(gm_app_view_action(view,
"/MenuBar/EditMenu/EditFindMenu"), can_find);
gtk_action_set_sensitive(gm_app_view_action(view,
"/MenuBar/EditMenu/EditFindNextMenu"), can_find);
gtk_widget_set_sensitive(GTK_WIDGET(view->priv->hbox_control_find),
can_find);
can_replace = gm_world_view_page_can_replace(world_view, page_num);
gtk_action_set_sensitive(gm_app_view_action(view,
"/MenuBar/EditMenu/EditReplaceMenu"), can_replace);
if (!can_replace) {
gtk_widget_hide(GTK_WIDGET(view->priv->hbox_replace));
gtk_widget_hide(GTK_WIDGET(view->priv->label_replace));
gtk_expander_set_expanded(view->priv->expander_replace, FALSE);
gtk_widget_set_sensitive(GTK_WIDGET(view->priv->expander_replace),
FALSE);
} else {
gtk_widget_set_sensitive(GTK_WIDGET(view->priv->expander_replace),
TRUE);
}
if (page_num == 0) {
direction = gm_options_get_int(gm_app_options(view->priv->application),
"search_direction_world");
} else {
direction = gm_options_get_int(gm_app_options(view->priv->application),
"search_direction");
}
view->priv->ignore_toggling = TRUE;
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
view->priv->check_button_search_direction), direction);
view->priv->ignore_toggling = FALSE;
/* Enable/disable editor toolbar */
page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(world_view), page_num);
gtk_action_group_set_visible(view->priv->editor_action_group,
GM_IS_EDITOR_VIEW(page));
* VERSION CHANGED TO 2.0.9 * po/POTFILES.in: added gnoemoe/dialogs/gm-world-paste-dialog.c and ui/gm-world-paste.glade * po/nl.po: added translations * ui/Makefile.am: * ui/gm-ui.xml: * ui/gm-world-paste.glade: new paste dialog * gnoemoe/mcp/Makefile.include: added gm-cell-renderer-text.[ch] * gnoemoe/mcp/gm-cell-renderer-text.[ch]: new cell renderer for rendering userlist * gnoemoe/mcp/gm-mcp-vmoo-client.c: update metrics in timeout so to reduce the number of updates when resizing * gnoemoe/mcp/gm-mcp-icecrew-serverinfo.c: max version set to 1.0 (1.0 does not actively request the info because it will be send on initialization). Set menu item invisible instead of insensitive when there is no info available * gnoemoe/mcp/gm-mcp-icecrew-userlist.c: fixed menu item substitution * gnoemoe/mcp/gm-mcp-vmoo-userlist.c: removed support for status because it doesn't really support it * gm-mcp-userlist-view.[ch]: moved column constants to header. Render items with new gm-cell-renderer-text. * gnoemoe/mcp/gm-mcp-icecrew-playerdb.[ch]: made gm_mcp_icecrew_playerdb_players public * gnoemoe/dialogs/Makefile.include: added gm-world-paste-dialog * gnoemoe/dialogs/gm-world-paste-dialog.[ch]: new paste dialog * gnoemoe/dialogs/gm-world-properties-dialog.c: * gnoemoe/dialogs/gm-world-logs-dialog.c: fixed leaking tree stores * gnoemoe/widgets/Makefile.include: added gm-commands.[ch] * gnoemoe/widgets/gm-commands.[ch]: new file for handling action activation (removed from gm-app-view) * gnoemoe/widgets/gm-world-view.c: fixed userlist size restore * gnoemoe/widgets/gm-app-view.c: removed action handlers * gnoemoe/gm-support.[ch]: added gm_find_child * gnoemoe/gm-world.c: removed debug message * gnoemoe/gm-ui.h: changed actions to gm-commands
2006-04-23 16:51:04 +02:00
gtk_action_group_set_sensitive(view->priv->editor_action_group,
GM_IS_EDITOR_VIEW(page));
#ifdef HAVE_PARSER
if (GM_IS_EDITOR_VIEW(page)) {
gtk_action_set_sensitive(gm_app_view_action(view,
"/ToolBar/EditorToolAdditions/EditorParseTool"), gm_editor_is_code(
gm_editor_view_editor(GM_EDITOR_VIEW(page))));
}
#endif
}
2005-11-07 10:56:25 +01:00
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);
on_gm_app_view_world_view_notebook_switch_page(GTK_NOTEBOOK(
gm_app_view_active_world_view(view)), NULL, 0, view);
}
* VERSION CHANGED TO 2.0.9 * po/POTFILES.in: added gnoemoe/dialogs/gm-world-paste-dialog.c and ui/gm-world-paste.glade * po/nl.po: added translations * ui/Makefile.am: * ui/gm-ui.xml: * ui/gm-world-paste.glade: new paste dialog * gnoemoe/mcp/Makefile.include: added gm-cell-renderer-text.[ch] * gnoemoe/mcp/gm-cell-renderer-text.[ch]: new cell renderer for rendering userlist * gnoemoe/mcp/gm-mcp-vmoo-client.c: update metrics in timeout so to reduce the number of updates when resizing * gnoemoe/mcp/gm-mcp-icecrew-serverinfo.c: max version set to 1.0 (1.0 does not actively request the info because it will be send on initialization). Set menu item invisible instead of insensitive when there is no info available * gnoemoe/mcp/gm-mcp-icecrew-userlist.c: fixed menu item substitution * gnoemoe/mcp/gm-mcp-vmoo-userlist.c: removed support for status because it doesn't really support it * gm-mcp-userlist-view.[ch]: moved column constants to header. Render items with new gm-cell-renderer-text. * gnoemoe/mcp/gm-mcp-icecrew-playerdb.[ch]: made gm_mcp_icecrew_playerdb_players public * gnoemoe/dialogs/Makefile.include: added gm-world-paste-dialog * gnoemoe/dialogs/gm-world-paste-dialog.[ch]: new paste dialog * gnoemoe/dialogs/gm-world-properties-dialog.c: * gnoemoe/dialogs/gm-world-logs-dialog.c: fixed leaking tree stores * gnoemoe/widgets/Makefile.include: added gm-commands.[ch] * gnoemoe/widgets/gm-commands.[ch]: new file for handling action activation (removed from gm-app-view) * gnoemoe/widgets/gm-world-view.c: fixed userlist size restore * gnoemoe/widgets/gm-app-view.c: removed action handlers * gnoemoe/gm-support.[ch]: added gm_find_child * gnoemoe/gm-world.c: removed debug message * gnoemoe/gm-ui.h: changed actions to gm-commands
2006-04-23 16:51:04 +02:00
g_signal_emit(view, gm_app_view_signals[ACTIVE_WORLD_CHANGED], 0,
gm_app_view_active_world_view(view));
}
GmEditorView *
gm_app_view_active_editor_view(GmAppView *view) {
GmWorldView *world_view = gm_app_view_active_world_view(view);
gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(world_view));
return GM_EDITOR_VIEW(gtk_notebook_get_nth_page(GTK_NOTEBOOK(world_view),
page));
}
2005-11-07 10:56:25 +01:00
void
on_gm_app_view_world_active_changed(GmWorld *world, GParamSpec *pspec,
2005-11-07 10:56:25 +01:00
GmAppView *view) {
GmWorldView *world_view = gm_app_view_world_view_from_world(view, world);
if (gm_world_active(world)) {
2005-11-07 10:56:25 +01:00
gtk_notebook_set_current_page(view->priv->notebook,
gtk_notebook_page_num(view->priv->notebook,
GTK_WIDGET(world_view)));
2006-02-06 19:33:49 +01:00
2005-11-07 10:56:25 +01:00
gm_app_view_update_title(view);
2006-02-06 19:33:49 +01:00
switch (gm_world_state(world)) {
case GM_NET_STATE_CONNECTING: 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;
}
2005-11-07 10:56:25 +01:00
}
}
void
on_gm_app_view_world_activity_changed(GmWorld *world, GParamSpec *pspec,
GmAppView *view) {
gm_app_view_update_tray(view);
2005-11-07 10:56:25 +01:00
}
void
on_gm_app_view_world_mcp_package_created(GmMcpSession *session,
GmMcpPackage *package, GmAppView *view) {
gm_mcp_package_create_view(package, G_OBJECT(view));
}
void
on_gm_app_view_world_view_destroy(GmWorldView *world_view,
GmAppView *view) {
GmWorld *world = gm_world_view_world(world_view);
if (gm_world_loaded(world)) {
// This only happens when the main view is destroyed when there are
// still worlds active. The thing is we need to unload the world here
// so that anything GUI related (like mcp things) can proper finalize
// Disconnect the unload handler to avoid strange things to happen
g_signal_handlers_disconnect_by_func(world,
on_gm_app_view_world_unload, view);
gm_world_unload(world);
}
}
gboolean
on_gm_app_view_tray_button_press(GmTray *tray, GdkEventButton *event,
GmAppView *view) {
if (event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS) {
return FALSE;
}
if (event->button == 1) {
gm_app_view_toggle_visibility(view);
}
return FALSE;
}
void
on_gm_app_view_tray_message_clicked(GmTray *tray, GmAppView *view) {
gboolean visible = GTK_WIDGET_VISIBLE(view);
if (!visible || !gtk_window_is_active(GTK_WINDOW(view))) {
gm_app_view_toggle_visibility(view);
gdk_window_focus(GTK_WIDGET(view)->window, GDK_CURRENT_TIME);
}
}
2006-01-10 01:39:05 +01:00
gboolean
idle_create_tray(gpointer user_data) {
GmAppView *view = GM_APP_VIEW(user_data);
view->priv->tray_idle_create = 0;
gm_app_view_create_tray(view);
if (!gm_tray_has_manager() && !GTK_WIDGET_VISIBLE(view)) {
gm_app_view_toggle_visibility(view);
gtk_window_present(GTK_WINDOW(view));
}
return FALSE;
}
void
on_gm_app_view_tray_destroy(GtkWidget *caller, GmAppView *view) {
// Make sure the view is visible
2006-01-10 01:39:05 +01:00
g_object_unref(G_OBJECT(caller));
view->priv->tray = NULL;
2006-01-10 01:39:05 +01:00
view->priv->tray_idle_create = g_idle_add(idle_create_tray, view);
}