Filter:   InfoImg
download bonobo-ui-sync-keys.c
Language: C
Copyright: Copyright 2000 Ximian, Inc.
LOC: 176
Project Info
libbonoboui
Server: Gnome
Type: cvs
...onoboui\libbonoboui\bonobo\
   .cvsignore
   bonobo-a11y.c
   bonobo-a11y.h
   bonobo-canvas-component.c
   bonobo-canvas-component.h
   bonobo-canvas-item.c
   bonobo-canvas-item.h
   bonobo-control-frame.c
   bonobo-control-frame.h
   bonobo-control-internal.h
   bonobo-control.c
   bonobo-control.h
   bonobo-dock-band.c
   bonobo-dock-band.h
   bonobo-dock-item-grip.c
   bonobo-dock-item-grip.h
   bonobo-dock-item.c
   bonobo-dock-item.h
   bonobo-dock-layout.c
   bonobo-dock-layout.h
   bonobo-dock.c
   bonobo-dock.h
   ...bo-embeddable-factory.h
   ...bo-file-selector-util.c
   ...bo-file-selector-util.h
   ...bo-insert-component.xpm
   bonobo-plug.c
   bonobo-plug.h
   bonobo-property-control.c
   bonobo-property-control.h
   bonobo-selector-widget.c
   bonobo-selector-widget.h
   bonobo-selector.c
   bonobo-selector.h
   bonobo-socket.c
   bonobo-socket.h
   bonobo-ui-component.c
   bonobo-ui-component.h
   bonobo-ui-config-widget.c
   bonobo-ui-config-widget.h
   bonobo-ui-container.c
   bonobo-ui-container.h
   bonobo-ui-engine-config.c
   bonobo-ui-engine-config.h
   bonobo-ui-engine-private.h
   bonobo-ui-engine.c
   bonobo-ui-engine.h
   bonobo-ui-init-gtk.c
   ...o-ui-internal-toolbar.c
   bonobo-ui-main.c
   bonobo-ui-main.h
   bonobo-ui-marshal-main.c
   bonobo-ui-marshal.list
   bonobo-ui-node-private.h
   bonobo-ui-node.c
   bonobo-ui-node.h
   bonobo-ui-preferences.c
   bonobo-ui-preferences.h
   bonobo-ui-private.h
   bonobo-ui-sync-keys.c
   bonobo-ui-sync-keys.h
   bonobo-ui-sync-menu.c
   bonobo-ui-sync-menu.h
   bonobo-ui-sync-status.c
   bonobo-ui-sync-status.h
   bonobo-ui-sync-toolbar.c
   bonobo-ui-sync-toolbar.h
   bonobo-ui-sync.c
   bonobo-ui-sync.h
   ...i-toolbar-button-item.c
   ...i-toolbar-button-item.h
   ...-toolbar-control-item.c
   ...-toolbar-control-item.h
   bonobo-ui-toolbar-item.c
   bonobo-ui-toolbar-item.h
   ...ui-toolbar-popup-item.c
   ...ui-toolbar-popup-item.h
   ...ar-toggle-button-item.c
   ...ar-toggle-button-item.h
   bonobo-ui-toolbar.c
   bonobo-ui-toolbar.h
   bonobo-ui-util.c
   bonobo-ui-util.h
   bonobo-ui-win32.c
   bonobo-ui-xml.c
   bonobo-ui-xml.h
   bonobo-widget.c
   bonobo-widget.h
   bonobo-window.c
   bonobo-window.h
   bonobo-wrapper.h
   bonobo-zoomable-frame.c
   bonobo-zoomable-frame.h
   bonobo-zoomable.c
   bonobo-zoomable.h
   ...i-2.0-uninstalled.pc.in
   libbonoboui-2.0.pc.in
   Makefile.am

/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/*
 * bonobo-ui-sync-keys.h: The Bonobo UI/XML sync engine for keys bits.
 *
 * Author:
 *	Michael Meeks (michael@ximian.com)
 *
 * Copyright 2000 Ximian, Inc.
 */

#include <config.h>
#include <stdlib.h>

#include <bonobo/bonobo-ui-xml.h>
#include <bonobo/bonobo-ui-util.h>
#include <bonobo/bonobo-ui-engine.h>
#include <bonobo/bonobo-ui-sync.h>
#include <bonobo/bonobo-ui-sync-keys.h>
#include <bonobo/bonobo-ui-private.h>

static GQuark accel_id = 0;
static GQuark keybindings_id = 0;

static BonoboUISyncClass *parent_class = NULL;

#define PARENT_TYPE bonobo_ui_sync_get_type ()

#define	BINDING_MOD_MASK()				\
	(gtk_accelerator_get_default_mod_mask () | GDK_RELEASE_MASK)

typedef struct {
	guint           key;
	GdkModifierType mods;
	BonoboUINode        *node;
} Binding;

static gboolean
keybindings_free (gpointer key,
		  gpointer value,
		  gpointer user_data)
{
	g_free (key);

	return TRUE;
}

/* Shamelessly stolen from gtkbindings.c */
static guint
keybinding_hash_fn (gconstpointer  key)
{
	register const Binding *e = key;
	register guint h;

	h = e->key;
	h ^= e->mods;

	return h;
}

static gint
keybinding_compare_fn (gconstpointer a,
		       gconstpointer b)
{
	register const Binding *ba = a;
	register const Binding *bb = b;

	return (ba->key == bb->key && ba->mods == bb->mods);
}

gint
bonobo_ui_sync_keys_binding_handle (GtkWidget        *widget,
				    GdkEventKey      *event,
				    BonoboUISyncKeys *msync)
{
	Binding lookup, *binding;

	lookup.key  = gdk_keyval_to_lower (event->keyval);
	lookup.mods = event->state & BINDING_MOD_MASK ();

	if (!(binding = g_hash_table_lookup (
		msync->keybindings, &lookup)))

		return FALSE;
	else {
		bonobo_ui_engine_emit_verb_on (
			msync->parent.engine, binding->node);

		return TRUE;
	}
}

static void
impl_finalize (GObject *object)
{
	BonoboUISyncKeys *sync;

	sync = BONOBO_UI_SYNC_KEYS (object);

	g_hash_table_foreach_remove (sync->keybindings,
				     keybindings_free, NULL);
	g_hash_table_destroy (sync->keybindings);
	sync->keybindings = NULL;

	G_OBJECT_CLASS (parent_class)->finalize (object);
}

static void
update_keybindings (BonoboUISyncKeys *msync,
		    BonoboUINode     *node)
{
	BonoboUINode    *l;
	BonoboUIXmlData *data;

	if (!bonobo_ui_engine_node_is_dirty (msync->parent.engine, node))
		return;

	data = bonobo_ui_xml_get_data (NULL, node);
	g_return_if_fail (data != NULL);

	if (!data->dirty)
		return;


	g_hash_table_foreach_remove (
		msync->keybindings, keybindings_free, NULL);

	for (l = bonobo_ui_node_children (node); l;
	     l = bonobo_ui_node_next (l)) {
		guint           key;
		GdkModifierType mods;
		const char     *name;
		Binding        *binding;
		
		name = bonobo_ui_node_peek_attr (l, "name");
		if (!name)
			continue;
		
		bonobo_ui_util_accel_parse (name, &key, &mods);

		binding       = g_new0 (Binding, 1);
		binding->mods = mods & BINDING_MOD_MASK ();
		binding->key  = gdk_keyval_to_lower (key);
		binding->node = l;

		g_hash_table_insert (msync->keybindings, binding, binding);
	}
}

static void
impl_bonobo_ui_sync_keys_update_root (BonoboUISync *sync,
				      BonoboUINode *root)
{
	if (bonobo_ui_node_has_name (root, "keybindings"))
		update_keybindings (BONOBO_UI_SYNC_KEYS (sync), root);
}

static void
impl_bonobo_ui_sync_keys_stamp_root (BonoboUISync *sync)
{
	BonoboUINode *node;

	node = bonobo_ui_engine_get_path (sync->engine, "/keybindings");

	if (node)
		bonobo_ui_engine_node_set_dirty (sync->engine, node, TRUE);
}

static gboolean
impl_bonobo_ui_sync_keys_can_handle (BonoboUISync *sync,
				     BonoboUINode *node)
{
	if (!accel_id) {
		accel_id = g_quark_from_static_string ("accel");
		keybindings_id = g_quark_from_static_string ("keybindings");
	}

	return (node->name_id == accel_id ||
		node->name_id == keybindings_id);
}

/* We need to map the shell to the item */

static void
class_init (BonoboUISyncClass *sync_class)
{
	GObjectClass *object_class;

	parent_class = g_type_class_peek_parent (sync_class);

	object_class = G_OBJECT_CLASS (sync_class);
	object_class->finalize    = impl_finalize;

	sync_class->update_root   = impl_bonobo_ui_sync_keys_update_root;
	sync_class->can_handle    = impl_bonobo_ui_sync_keys_can_handle;
	sync_class->stamp_root    = impl_bonobo_ui_sync_keys_stamp_root;
}

static void
init (BonoboUISyncKeys *msync)
{
	msync->keybindings = g_hash_table_new (
		keybinding_hash_fn, keybinding_compare_fn);	
}

GType
bonobo_ui_sync_keys_get_type (void)
{
	static GType type = 0;

	if (type == 0) {
		GTypeInfo info = {
			sizeof (BonoboUISyncKeysClass),
			(GBaseInitFunc) NULL,
			(GBaseFinalizeFunc) NULL,
			(GClassInitFunc) class_init,
			NULL, /* class_finalize */
			NULL, /* class_data */
			sizeof (BonoboUISyncKeys),
			0, /* n_preallocs */
			(GInstanceInitFunc) init
		};

		type = g_type_register_static (PARENT_TYPE, "BonoboUISyncKeys",
					       &info, 0);
	}

	return type;
}

BonoboUISync *
bonobo_ui_sync_keys_new (BonoboUIEngine *engine)
{
	BonoboUISyncKeys *sync;

	g_return_val_if_fail (BONOBO_IS_UI_ENGINE (engine), NULL);

	sync = g_object_new (BONOBO_TYPE_UI_SYNC_KEYS, NULL);

	return bonobo_ui_sync_construct (
		BONOBO_UI_SYNC (sync), engine, FALSE, FALSE);
}