medit/moo/mooutils/mooaction.c

411 lines
10 KiB
C
Raw Normal View History

2005-06-22 11:20:32 -07:00
/*
* mooaction.c
2005-06-22 11:20:32 -07:00
*
* Copyright (C) 2004-2006 by Yevgen Muntyan <muntyan@math.tamu.edu>
2005-06-22 11:20:32 -07:00
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* See COPYING file that comes with this distribution.
*/
#include "mooutils/mooaction.h"
2005-11-19 19:59:01 -08:00
#include "mooutils/mooutils-gobject.h"
2006-05-08 21:57:16 -07:00
#include <gtk/gtktoggleaction.h>
2005-06-22 11:20:32 -07:00
#include <string.h>
2006-05-08 21:57:16 -07:00
static void
set_bool (gpointer object,
const char *key,
gboolean value)
2005-06-22 11:20:32 -07:00
{
2006-05-08 21:57:16 -07:00
g_object_set_data (object, key, GINT_TO_POINTER (value));
2005-06-22 11:20:32 -07:00
}
2006-05-08 21:57:16 -07:00
static gboolean
get_bool (gpointer object,
const char *key)
2005-06-22 11:20:32 -07:00
{
2006-05-08 21:57:16 -07:00
return g_object_get_data (object, key) != NULL;
2005-06-22 11:20:32 -07:00
}
2006-05-08 21:57:16 -07:00
static void
set_string (gpointer object,
const char *key,
const char *value)
2005-06-22 11:20:32 -07:00
{
2006-05-08 21:57:16 -07:00
if (value)
g_object_set_data_full (object, key, g_strdup (value), g_free);
else
g_object_set_data (object, key, NULL);
2005-06-22 11:20:32 -07:00
}
2006-05-08 21:57:16 -07:00
static const char *
get_string (gpointer object,
const char *key)
2005-11-19 19:59:01 -08:00
{
2006-05-08 21:57:16 -07:00
return g_object_get_data (object, key);
2005-11-19 19:59:01 -08:00
}
2006-05-08 21:57:16 -07:00
void
moo_action_set_no_accel (GtkAction *action,
gboolean no_accel)
2005-06-22 11:20:32 -07:00
{
2006-05-08 21:57:16 -07:00
g_return_if_fail (GTK_IS_ACTION (action));
set_bool (action, "moo-action-no-accel", no_accel);
2005-06-22 11:20:32 -07:00
}
2006-05-08 21:57:16 -07:00
gboolean
moo_action_get_no_accel (GtkAction *action)
2005-06-22 11:20:32 -07:00
{
2006-05-08 21:57:16 -07:00
g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
return get_bool (action, "moo-action-no-accel");
2005-06-22 11:20:32 -07:00
}
2006-05-08 21:57:16 -07:00
void
_moo_action_set_force_accel_label (GtkAction *action,
gboolean force)
2005-06-22 11:20:32 -07:00
{
2006-05-08 21:57:16 -07:00
g_return_if_fail (GTK_IS_ACTION (action));
set_bool (action, "moo-action-force-accel-label", force);
2005-06-22 11:20:32 -07:00
}
2006-05-08 21:57:16 -07:00
gboolean
_moo_action_get_force_accel_label (GtkAction *action)
2005-06-22 11:20:32 -07:00
{
2006-05-08 21:57:16 -07:00
g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
return get_bool (action, "moo-action-force-accel-label");
2005-06-22 11:20:32 -07:00
}
2006-05-08 21:57:16 -07:00
const char *
moo_action_get_default_accel (GtkAction *action)
2005-06-22 11:20:32 -07:00
{
2006-05-08 21:57:16 -07:00
const char *accel;
2005-06-22 11:20:32 -07:00
2006-05-08 21:57:16 -07:00
g_return_val_if_fail (GTK_IS_ACTION (action), "");
2005-06-22 11:20:32 -07:00
2006-05-08 21:57:16 -07:00
accel = get_string (action, "moo-action-default-accel");
return accel ? accel : "";
2005-06-22 11:20:32 -07:00
}
2005-11-19 19:59:01 -08:00
void
2006-05-08 21:57:16 -07:00
moo_action_set_default_accel (GtkAction *action,
const char *accel)
2005-06-22 11:20:32 -07:00
{
2006-05-08 21:57:16 -07:00
g_return_if_fail (GTK_IS_ACTION (action));
set_string (action, "moo-action-default-accel", accel);
2005-06-22 11:20:32 -07:00
}
2006-05-08 21:57:16 -07:00
void
_moo_action_set_accel_path (GtkAction *action,
const char *accel_path)
2005-06-22 11:20:32 -07:00
{
2006-05-08 21:57:16 -07:00
g_return_if_fail (GTK_IS_ACTION (action));
set_string (action, "moo-action-accel-path", accel_path);
2005-06-22 11:20:32 -07:00
2006-05-08 21:57:16 -07:00
if (!moo_action_get_no_accel (action))
gtk_action_set_accel_path (action, accel_path);
2005-06-22 11:20:32 -07:00
}
2006-05-08 21:57:16 -07:00
const char *
_moo_action_get_accel_path (GtkAction *action)
2005-06-22 11:20:32 -07:00
{
2006-05-08 21:57:16 -07:00
g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
return get_string (action, "moo-action-accel-path");
2005-06-22 11:20:32 -07:00
}
2006-05-08 21:57:16 -07:00
const char *
_moo_action_get_accel (GtkAction *action)
2005-06-22 11:20:32 -07:00
{
2006-05-08 21:57:16 -07:00
const char *string;
2005-06-22 11:20:32 -07:00
2006-05-08 21:57:16 -07:00
g_return_val_if_fail (GTK_IS_ACTION (action), "");
2005-06-22 11:20:32 -07:00
2006-05-08 21:57:16 -07:00
if ((string = get_string (action, "moo-action-accel-path")))
return string;
else if ((string = get_string (action, "moo-action-default-accel")))
return string;
else
return "";
2005-06-22 11:20:32 -07:00
}
2006-05-08 21:57:16 -07:00
const char *
_moo_action_make_accel_path (const char *group_id,
const char *action_id)
2005-06-22 11:20:32 -07:00
{
static GString *path = NULL;
2005-06-22 11:20:32 -07:00
g_return_val_if_fail (action_id != NULL && action_id[0] != 0, NULL);
if (!path)
path = g_string_new (NULL);
2005-06-22 11:20:32 -07:00
if (group_id && group_id[0])
g_string_printf (path, "<MooAction>/%s/%s", group_id, action_id);
2005-06-22 11:20:32 -07:00
else
g_string_printf (path, "<MooAction>/%s", action_id);
2005-06-22 11:20:32 -07:00
return path->str;
2005-06-22 11:20:32 -07:00
}
2006-05-08 21:57:16 -07:00
const char *
moo_action_get_display_name (GtkAction *action)
2005-06-22 11:20:32 -07:00
{
2006-05-08 21:57:16 -07:00
const char *name;
g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
name = get_string (action, "moo-action-display-name");
return name ? name : gtk_action_get_name (action);
}
2005-06-22 11:20:32 -07:00
2006-05-08 21:57:16 -07:00
void
moo_action_set_display_name (GtkAction *action,
const char *name)
{
g_return_if_fail (GTK_IS_ACTION (action));
set_string (action, "moo-action-display-name", name);
}
2005-06-22 11:20:32 -07:00
2006-05-08 21:57:16 -07:00
gboolean
_moo_action_get_dead (GtkAction *action)
{
g_return_val_if_fail (GTK_IS_ACTION (action), TRUE);
return get_bool (action, "moo-action-dead");
}
2006-05-08 21:57:16 -07:00
void
_moo_action_set_dead (GtkAction *action,
gboolean dead)
{
g_return_if_fail (GTK_IS_ACTION (action));
set_bool (action, "moo-action-dead", dead);
}
2005-06-22 11:20:32 -07:00
2006-05-08 21:57:16 -07:00
gboolean
_moo_action_get_has_submenu (GtkAction *action)
{
g_return_val_if_fail (GTK_IS_ACTION (action), TRUE);
return get_bool (action, "moo-action-has-submenu");
2005-06-22 11:20:32 -07:00
}
2006-05-08 21:57:16 -07:00
void
_moo_action_set_has_submenu (GtkAction *action,
gboolean has_submenu)
2005-06-22 11:20:32 -07:00
{
2006-05-08 21:57:16 -07:00
g_return_if_fail (GTK_IS_ACTION (action));
set_bool (action, "moo-action-has-submenu", has_submenu);
}
2005-06-22 11:20:32 -07:00
2006-05-08 21:57:16 -07:00
static void
moo_action_activate (GtkAction *action)
{
MooClosure *closure = _moo_action_get_closure (action);
2005-06-22 11:20:32 -07:00
2006-05-08 21:57:16 -07:00
if (closure)
moo_closure_invoke (closure);
}
2005-06-22 11:20:32 -07:00
2006-05-08 21:57:16 -07:00
void
_moo_action_set_closure (GtkAction *action,
MooClosure *closure)
{
g_return_if_fail (GTK_IS_ACTION (action));
2006-05-08 21:57:16 -07:00
if (closure)
2005-06-22 11:20:32 -07:00
{
2006-05-08 21:57:16 -07:00
moo_closure_ref_sink (closure);
g_object_set_data_full (G_OBJECT (action), "moo-action-closure",
closure, (GDestroyNotify) moo_closure_unref);
if (!g_signal_handler_find (action, G_SIGNAL_MATCH_FUNC,
0, 0, 0, moo_action_activate, NULL))
g_signal_connect (action, "activate",
G_CALLBACK (moo_action_activate),
NULL);
2005-06-22 11:20:32 -07:00
}
else
{
2006-05-08 21:57:16 -07:00
g_object_set_data (G_OBJECT (action), "moo-action-closure", NULL);
2005-06-22 11:20:32 -07:00
}
}
2006-05-08 21:57:16 -07:00
MooClosure *
_moo_action_get_closure (GtkAction *action)
2005-06-22 11:20:32 -07:00
{
2006-05-08 21:57:16 -07:00
g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
return g_object_get_data (G_OBJECT (action), "moo-action-closure");
2005-06-22 11:20:32 -07:00
}
2006-05-08 21:57:16 -07:00
/**************************************************************************/
/* moo_sync_toggle_action
*/
2005-06-22 11:20:32 -07:00
2006-05-08 21:57:16 -07:00
typedef struct {
MooObjectWatch parent;
GParamSpec *pspec;
gboolean invert;
} ToggleWatch;
2005-06-22 11:20:32 -07:00
2006-05-08 21:57:16 -07:00
static void action_toggled (ToggleWatch *watch);
static void prop_changed (ToggleWatch *watch);
static void toggle_watch_destroy (MooObjectWatch *watch);
2005-06-22 11:20:32 -07:00
2006-05-08 21:57:16 -07:00
static MooObjectWatchClass ToggleWatchClass = {NULL, NULL, toggle_watch_destroy};
2005-06-22 11:20:32 -07:00
2006-05-08 21:57:16 -07:00
static ToggleWatch *
toggle_watch_new (GObject *master,
const char *prop,
GtkAction *action,
gboolean invert)
2005-06-22 11:20:32 -07:00
{
2006-05-08 21:57:16 -07:00
ToggleWatch *watch;
GObjectClass *klass;
GParamSpec *pspec;
char *signal;
2005-06-22 11:20:32 -07:00
2006-05-08 21:57:16 -07:00
g_return_val_if_fail (G_IS_OBJECT (master), NULL);
g_return_val_if_fail (GTK_IS_TOGGLE_ACTION (action), NULL);
g_return_val_if_fail (prop != NULL, NULL);
2005-06-22 11:20:32 -07:00
2006-05-08 21:57:16 -07:00
klass = g_type_class_peek (G_OBJECT_TYPE (master));
pspec = g_object_class_find_property (klass, prop);
if (!pspec)
2005-11-19 19:59:01 -08:00
{
2006-05-08 21:57:16 -07:00
g_warning ("%s: no property '%s' in class '%s'",
G_STRLOC, prop, g_type_name (G_OBJECT_TYPE (master)));
return NULL;
2005-11-19 19:59:01 -08:00
}
2005-06-22 11:20:32 -07:00
2006-05-08 21:57:16 -07:00
watch = moo_object_watch_new (ToggleWatch, &ToggleWatchClass,
master, action, NULL, NULL);
2005-06-22 11:20:32 -07:00
2006-05-08 21:57:16 -07:00
watch->pspec = pspec;
watch->invert = invert;
signal = g_strdup_printf ("notify::%s", prop);
g_signal_connect_swapped (master, signal,
G_CALLBACK (prop_changed),
watch);
g_signal_connect_swapped (action, "toggled",
G_CALLBACK (action_toggled),
watch);
g_free (signal);
return watch;
2005-06-22 11:20:32 -07:00
}
2006-05-08 21:57:16 -07:00
static void
toggle_watch_destroy (MooObjectWatch *watch)
2005-06-22 11:20:32 -07:00
{
2006-05-08 21:57:16 -07:00
if (MOO_OBJECT_PTR_GET (watch->source))
{
2006-05-08 21:57:16 -07:00
g_signal_handlers_disconnect_by_func (MOO_OBJECT_PTR_GET (watch->source),
(gpointer) prop_changed,
watch);
}
2006-05-08 21:57:16 -07:00
if (MOO_OBJECT_PTR_GET (watch->target))
2005-06-22 11:20:32 -07:00
{
2006-05-08 21:57:16 -07:00
g_assert (GTK_IS_TOGGLE_ACTION (MOO_OBJECT_PTR_GET (watch->target)));
g_signal_handlers_disconnect_by_func (MOO_OBJECT_PTR_GET (watch->target),
(gpointer) action_toggled,
watch);
2005-06-22 11:20:32 -07:00
}
}
2006-05-08 21:57:16 -07:00
void
moo_sync_toggle_action (GtkAction *action,
gpointer master,
const char *prop,
gboolean invert)
{
2006-05-08 21:57:16 -07:00
ToggleWatch *watch;
2006-05-08 21:57:16 -07:00
g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
g_return_if_fail (G_IS_OBJECT (master));
g_return_if_fail (prop != NULL);
2006-05-08 21:57:16 -07:00
watch = toggle_watch_new (master, prop, action, invert);
g_return_if_fail (watch != NULL);
2006-05-08 21:57:16 -07:00
prop_changed (watch);
}
2006-05-08 21:57:16 -07:00
static void
prop_changed (ToggleWatch *watch)
{
2006-05-08 21:57:16 -07:00
gboolean value, active, equal;
gpointer action;
2006-05-08 21:57:16 -07:00
g_object_get (MOO_OBJECT_PTR_GET (watch->parent.source),
watch->pspec->name, &value, NULL);
2006-05-08 21:57:16 -07:00
action = MOO_OBJECT_PTR_GET (watch->parent.target);
g_assert (GTK_IS_TOGGLE_ACTION (action));
active = gtk_toggle_action_get_active (action);
2006-05-08 21:57:16 -07:00
if (!watch->invert)
equal = ((value && active) || (!value && !active));
else
2006-05-08 21:57:16 -07:00
equal = ((!value && active) || (value && !active));
if (!equal)
gtk_toggle_action_set_active (action, watch->invert ? !value : value);
}
2006-05-08 21:57:16 -07:00
static void
action_toggled (ToggleWatch *watch)
{
2006-05-08 21:57:16 -07:00
gboolean value, active, equal;
gpointer action;
2006-05-08 21:57:16 -07:00
g_object_get (MOO_OBJECT_PTR_GET (watch->parent.source),
watch->pspec->name, &value, NULL);
2006-05-08 21:57:16 -07:00
action = MOO_OBJECT_PTR_GET (watch->parent.target);
g_assert (GTK_IS_TOGGLE_ACTION (action));
active = gtk_toggle_action_get_active (action);
if (!watch->invert)
equal = ((value && active) || (!value && !active));
else
equal = ((!value && active) || (value && !active));
2006-05-08 21:57:16 -07:00
if (!equal)
g_object_set (MOO_OBJECT_PTR_GET (watch->parent.source),
watch->pspec->name,
watch->invert ? !active : active, NULL);
}