/* This is -*- C -*- */
/* vim: set sw=2: */
/* $Id: guppi-attribute-flavor.c,v 1.12 2002/01/08 06:31:09 trow Exp $ */
/*
* guppi-attribute-flavor.c
*
* Copyright (C) 2001 The Free Software Foundation, Inc.
*
* Developed by Jon Trowbridge <trow@gnu.org>
*/
/*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
#include <config.h>
#include <locale.h>
#include <stdlib.h>
#include "guppi-attribute-flavor.h"
#include <gtk/gtk.h>
#include "guppi-attribute-flavor-private.h"
#include "guppi-attribute-widget.h"
#include "guppi-metric-entry.h"
#include "guppi-defaults.h"
#include "guppi-memory.h"
#include "guppi-rgb.h"
static guint flavor_count = 0;
static guint flavor_bufsize = 0;
static GuppiAttributeFlavorInfo **flavor_info_buffer = NULL;
static GHashTable *flavor_name_hash = NULL;
static GuppiAttributeFlavor
register_info (GuppiAttributeFlavorInfo *info)
{
g_assert (info->flavor < 0);
g_assert (info->name && *info->name);
g_assert (info->create_default != NULL);
g_assert (info->destroy != NULL);
g_assert (info->copy != NULL);
g_assert (info->va2p != NULL);
g_assert (info->p2va != NULL);
if (flavor_count >= flavor_bufsize) {
if (flavor_bufsize > 0) {
flavor_bufsize = 2*flavor_bufsize;
flavor_info_buffer = guppi_renew (GuppiAttributeFlavorInfo *, flavor_info_buffer, flavor_bufsize);
} else {
flavor_bufsize = 64;
flavor_info_buffer = guppi_new (GuppiAttributeFlavorInfo *, flavor_bufsize);
}
}
if (flavor_name_hash == NULL) {
flavor_name_hash = g_hash_table_new (g_str_hash, g_str_equal);
}
if (g_hash_table_lookup (flavor_name_hash, info->name) != NULL) {
g_warning ("Name collision for attribute flavor '%s'", info->name);
return (GuppiAttributeFlavor)-1;
}
info->flavor = flavor_count;
flavor_info_buffer[info->flavor] = info;
g_hash_table_insert (flavor_name_hash, info->name, info);
++flavor_count;
return info->flavor;
}
GuppiAttributeFlavor
guppi_attribute_flavor_register (const gchar *name,
AttributeCreateDefaultFn create_default,
AttributeDestroyFn destroy,
AttributeCopyFn copy,
AttributeEqualityFn equality,
AttributeGetFromPointerFn getp,
AttributeGetFromVarArgsFn va2p,
AttributePutToVarArgsFn p2va)
{
GuppiAttributeFlavorInfo *info = g_new0 (GuppiAttributeFlavorInfo, 1);
info->flavor = -1;
info->name = g_strdup (name);
info->create_default = create_default;
info->destroy = destroy;
info->copy = copy;
info->equality = equality;
info->getp = getp;
info->va2p = va2p;
info->p2va = p2va;
return register_info (info);
}
/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */
static gpointer
object_create_default (void)
{
return NULL;
}
static void
object_destroy (gpointer ptr)
{
guppi_unref (ptr);
}
static gpointer
object_copy (gpointer ptr)
{
guppi_ref (ptr);
return ptr;
}
static gboolean
object_equality (gpointer a, gpointer b)
{
return a == b;
}
static gboolean
object_va2p (const gchar *key, const gchar *subkey, va_list *va, gpointer *storage)
{
GtkObject *obj = va_arg (*va, GtkObject *);
if (obj != *storage) {
guppi_unref (*storage);
*storage = obj;
if (subkey == NULL || !strcmp (subkey, "ref")) {
guppi_ref (obj);
} else if (strcmp (subkey, "adopt")) {
g_warning ("Unknown subkey %s::%s", key, subkey);
guppi_ref (obj); /* also ref in this case */
}
return TRUE;
}
return FALSE;
}
static void
object_p2va (const gchar *key, const gchar *subkey, gpointer ptr, gpointer dest)
{
*(GtkObject **) dest = ptr;
if (subkey == NULL || !strcmp (subkey, "ref")) {
guppi_ref (ptr);
} else if (strcmp (subkey, "raw")) {
g_warning ("Unknown subkey %s::%s", key, subkey);
guppi_ref (ptr); /* also ref in this case */
}
}
GuppiAttributeFlavor
guppi_attribute_flavor_register_object_semantics (const gchar *name,
AttributeCreateDefaultFn create_default,
AttributeCopyFn copy,
AttributeEqualityFn equality)
{
return guppi_attribute_flavor_register (name,
create_default ? create_default : object_create_default,
object_destroy,
copy ? copy : object_copy,
equality ? equality : object_equality,
NULL,
object_va2p,
object_p2va);
}
/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */
void
guppi_attribute_flavor_add_widget (GuppiAttributeFlavor flavor,
AttributeWidgetFn widget_fn)
{
GuppiAttributeFlavorInfo *info = guppi_attribute_flavor_get_info (flavor);
g_assert (info != NULL);
g_assert (widget_fn != NULL);
g_assert (info->widget == NULL);
info->widget = widget_fn;
}
/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */
void
guppi_attribute_flavor_add_string_serialization (GuppiAttributeFlavor flavor,
AttributeExportStringFn export_str,
AttributeImportStringFn import_str)
{
GuppiAttributeFlavorInfo *info = guppi_attribute_flavor_get_info (flavor);
g_assert (info != NULL);
g_assert (export_str != NULL);
g_assert (import_str != NULL);
g_assert (info->export_string == NULL);
g_assert (info->import_string == NULL);
info->export_string = export_str;
info->import_string = import_str;
}
void
guppi_attribute_flavor_add_xml_serialization (GuppiAttributeFlavor flavor,
AttributeExportXMLFn export_xml,
AttributeImportXMLFn import_xml)
{
GuppiAttributeFlavorInfo *info = guppi_attribute_flavor_get_info (flavor);
g_assert (info != NULL);
g_assert (export_xml != NULL);
g_assert (import_xml != NULL);
g_assert (info->export_xml == NULL);
g_assert (info->import_xml == NULL);
info->export_xml = export_xml;
info->import_xml = import_xml;
}
void
guppi_attribute_flavor_add_signal_to_forward (GuppiAttributeFlavor flavor,
const gchar *signal_name,
gboolean queue_signal_emissions)
{
GuppiAttributeFlavorInfo *info = guppi_attribute_flavor_get_info (flavor);
GuppiSignalsToForward *stf;
g_assert (info != NULL);
stf = guppi_new0 (GuppiSignalsToForward, 1);
stf->name = guppi_strdup (signal_name);
stf->queue = queue_signal_emissions;
guppi_permanent_alloc (stf);
guppi_permanent_alloc (stf->name);
info->signals_to_forward = g_list_prepend (info->signals_to_forward, stf);
}
GuppiAttributeFlavor
guppi_attribute_flavor_get_from_name (const gchar *name)
{
GuppiAttributeFlavorInfo *info = NULL;
if (name && *name)
info = g_hash_table_lookup (flavor_name_hash, name);
return info ? info->flavor : (GuppiAttributeFlavor)-1;
}
const gchar *
guppi_attribute_flavor_get_name (GuppiAttributeFlavor flavor)
{
if (0 <= flavor && flavor < flavor_count)
return flavor_info_buffer[flavor]->name;
else
return "[UnknownFlavor]";
}
GtkWidget *
guppi_attribute_flavor_get_widget (GuppiAttributeFlavor flavor, const gchar *key)
{
if (0 <= flavor && flavor < flavor_count && flavor_info_buffer[flavor]->widget)
return flavor_info_buffer[flavor]->widget (key);
else
return gtk_label_new ("N/A");
}
GtkWidget *
guppi_attr_glade (const gchar *label, const gchar *type, const gchar *key)
{
GuppiAttributeFlavor flavor = guppi_attribute_flavor_get_from_name (type);
g_return_val_if_fail (flavor != (GuppiAttributeFlavor)-1, NULL);
return guppi_attribute_flavor_get_widget (flavor, key);
}
GuppiAttributeFlavorInfo *
guppi_attribute_flavor_get_info (GuppiAttributeFlavor flavor)
{
if (0 <= flavor && flavor < flavor_count)
return flavor_info_buffer[flavor];
else
return NULL;
}
/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */
static gpointer
boolean_create_default (void)
{
return NULL;
}
static void
boolean_destroy (gpointer ptr)
{
/* do nothing */
}
static gpointer
boolean_copy (gpointer ptr)
{
return ptr;
}
static gboolean
boolean_equality (gpointer a, gpointer b)
{
return a != NULL ? b != NULL : b == NULL;
}
static gboolean
boolean_va2p (const gchar *key, const gchar *subkey, va_list *va, gpointer *storage)
{
gpointer old_data = *storage;
*storage = GINT_TO_POINTER (va_arg (*va, gint));
return old_data != *storage;
}
static void
boolean_p2va (const gchar *key, const gchar *subkey,gpointer ptr, gpointer dest)
{
*(gboolean *)dest = (gboolean) GPOINTER_TO_INT (ptr);
}
static gboolean
boolean_str_imp (const gchar *str, gpointer *p)
{
*p = GINT_TO_POINTER ( (gint) (str && (*str == 't' || *str == 'T')));
return TRUE;
}
static gchar *
boolean_str_exp (gpointer ptr)
{
return guppi_strdup (((gboolean) GPOINTER_TO_INT (ptr)) ? "true" : "false");
}
static void
boolean_bag_to_widget_cb (GuppiAttributeWidget *gaw, gpointer closure)
{
GtkToggleButton *tb = GTK_TOGGLE_BUTTON (closure);
gboolean val;
guppi_attribute_widget_bag_get (gaw, NULL, &val);
gtk_toggle_button_set_active (tb, val);
}
static void
boolean_toggled_cb (GtkToggleButton *tb, gpointer closure)
{
GuppiAttributeWidget *gaw = GUPPI_ATTRIBUTE_WIDGET (closure);
gboolean val = gtk_toggle_button_get_active (tb);
guppi_attribute_widget_bag_set (gaw, NULL, val);
}
static GtkWidget *
boolean_widget (const gchar *key)
{
GtkWidget *gaw = guppi_attribute_widget_new (guppi_attribute_flavor_boolean (), key);
GtkWidget *w;
w = gtk_check_button_new ();
gtk_container_add (GTK_CONTAINER (gaw), w);
gtk_widget_show (w);
gtk_signal_connect (GTK_OBJECT (gaw),
"bag_to_widget",
GTK_SIGNAL_FUNC (boolean_bag_to_widget_cb),
w);
gtk_signal_connect (GTK_OBJECT (w),
"toggled",
GTK_SIGNAL_FUNC (boolean_toggled_cb),
gaw);
return gaw;
}
GuppiAttributeFlavor
guppi_attribute_flavor_boolean (void)
{
static GuppiAttributeFlavor flavor = -1;
if (flavor < 0) {
flavor = guppi_attribute_flavor_register ("boolean",
boolean_create_default,
boolean_destroy,
boolean_copy,
boolean_equality,
NULL,
boolean_va2p,
boolean_p2va);
guppi_attribute_flavor_add_widget (flavor, boolean_widget);
guppi_attribute_flavor_add_string_serialization (flavor,
boolean_str_exp,
boolean_str_imp);
g_assert (flavor >= 0);
}
return flavor;
}
/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */
static gpointer
int_create_default (void)
{
return NULL;
}
static void
int_destroy (gpointer foo)
{
/* Do nothing */
}
static gpointer
int_copy (gpointer ptr)
{
return ptr;
}
static gboolean
int_equality (gpointer a, gpointer b)
{
return GPOINTER_TO_INT (a) == GPOINTER_TO_INT (b);
}
static gboolean
int_va2p (const gchar *key, const gchar *subkey, va_list *va, gpointer *storage)
{
gpointer old_data = *storage;
*storage = GINT_TO_POINTER (va_arg (*va, gint));
return old_data != *storage;
}
static void
int_p2va (const gchar *key, const gchar *subkey, gpointer ptr, gpointer dest)
{
*(gint *) dest = GPOINTER_TO_INT (ptr);
}
static gchar *
int_exp_str (gpointer ptr)
{
return guppi_strdup_printf ("%d", GPOINTER_TO_INT (ptr));
}
static gboolean
int_imp_str (const gchar *str, gpointer *ptr)
{
gint foo;
if (sscanf (str, "%d", &foo) == 1) {
*ptr = GINT_TO_POINTER (foo);
return TRUE;
}
return FALSE;
}
static void
int_bag_to_widget_cb (GuppiAttributeWidget *gaw, gpointer closure)
{
GtkEditable *w = GTK_EDITABLE (closure);
gchar *str;
gint val, pos=0;
guppi_attribute_widget_bag_get (gaw, NULL, &val);
str = guppi_strdup_printf ("%d", val);
gtk_editable_delete_text (w, 0, -1);
gtk_editable_insert_text (w, str, strlen (str), &pos);
guppi_free (str);
}
static void
int_activate_cb (GtkEditable *w, gpointer closure)
{
GuppiAttributeWidget *gaw = GUPPI_ATTRIBUTE_WIDGET (closure);
gchar *str;
gint val;
str = gtk_editable_get_chars (w, 0, -1);
val = atoi (str);
guppi_attribute_widget_bag_set (gaw, NULL, val);
g_free (str);
}
static GtkWidget *
int_widget (const gchar *key)
{
GtkWidget *gaw = guppi_attribute_widget_new (guppi_attribute_flavor_int (), key);
GtkWidget *w = gtk_entry_new ();
gtk_container_add (GTK_CONTAINER (gaw), w);
gtk_widget_show (w);
gtk_signal_connect (GTK_OBJECT (gaw),
"bag_to_widget",
GTK_SIGNAL_FUNC (int_bag_to_widget_cb),
w);
gtk_signal_connect (GTK_OBJECT (w),
"activate",
GTK_SIGNAL_FUNC (int_activate_cb),
gaw);
return gaw;
}
GuppiAttributeFlavor
guppi_attribute_flavor_int (void)
{
static GuppiAttributeFlavor flavor = -1;
if (flavor < 0) {
flavor = guppi_attribute_flavor_register ("int",
int_create_default,
int_destroy,
int_copy,
int_equality,
NULL,
int_va2p,
int_p2va);
guppi_attribute_flavor_add_widget (flavor, int_widget);
guppi_attribute_flavor_add_string_serialization (flavor,
int_exp_str,
int_imp_str);
}
return flavor;
}
/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */
static gpointer
uint32_create_default (void)
{
return NULL;
}
static void
uint32_destroy (gpointer foo)
{
/* do nothing */
}
static gpointer
uint32_copy (gpointer ptr)
{
return ptr;
}
static gboolean
uint32_equality (gpointer a, gpointer b)
{
return GPOINTER_TO_UINT (a) == GPOINTER_TO_UINT (b);
}
static gboolean
uint32_va2p (const gchar *key, const gchar *subkey, va_list *va, gpointer *storage)
{
gpointer old_data = *storage;
*storage = GUINT_TO_POINTER ((guint32) va_arg (*va, gint));
return old_data != *storage;
}
static void
uint32_p2va (const gchar *key, const gchar *subkey, gpointer ptr, gpointer dest)
{
*(guint32 *) dest = GPOINTER_TO_UINT (ptr);
}
static gchar *
uint32_exp_str (gpointer ptr)
{
return guppi_strdup_printf ("%u", GPOINTER_TO_UINT (ptr));
}
static gboolean
uint32_imp_str (const gchar *str, gpointer *ptr)
{
guint32 foo;
if (sscanf (str, "%u", &foo) == 1) {
*ptr = GUINT_TO_POINTER (foo);
return TRUE;
}
return FALSE;
}
static void
uint32_bag_to_widget_cb (GuppiAttributeWidget *gaw, gpointer closure)
{
GtkEditable *w = GTK_EDITABLE (closure);
gchar *str;
guint32 val;
gint pos=0;
guppi_attribute_widget_bag_get (gaw, NULL, &val);
str = guppi_strdup_printf ("%u", val);
gtk_editable_delete_text (w, 0, -1);
gtk_editable_insert_text (w, str, strlen (str), &pos);
guppi_free (str);
}
static void
uint32_activate_cb (GtkEditable *w, gpointer closure)
{
GuppiAttributeWidget *gaw = GUPPI_ATTRIBUTE_WIDGET (closure);
gchar *str;
guint32 val;
str = gtk_editable_get_chars (w, 0, -1);
val = (guint32) atoi (str);
guppi_attribute_widget_bag_set (gaw, NULL, val);
g_free (str);
}
static GtkWidget *
uint32_widget (const gchar *key)
{
GtkWidget *gaw = guppi_attribute_widget_new (guppi_attribute_flavor_uint32 (), key);
GtkWidget *w = gtk_entry_new ();
gtk_container_add (GTK_CONTAINER (gaw), w);
gtk_widget_show (w);
gtk_signal_connect (GTK_OBJECT (gaw),
"bag_to_widget",
GTK_SIGNAL_FUNC (uint32_bag_to_widget_cb),
w);
gtk_signal_connect (GTK_OBJECT (w),
"activate",
GTK_SIGNAL_FUNC (uint32_activate_cb),
gaw);
return gaw;
}
GuppiAttributeFlavor
guppi_attribute_flavor_uint32 (void)
{
static GuppiAttributeFlavor flavor = -1;
if (flavor < 0) {
flavor = guppi_attribute_flavor_register ("uint32",
uint32_create_default,
uint32_destroy,
uint32_copy,
uint32_equality,
NULL,
uint32_va2p,
uint32_p2va);
guppi_attribute_flavor_add_widget (flavor, uint32_widget);
guppi_attribute_flavor_add_string_serialization (flavor,
uint32_exp_str,
uint32_imp_str);
}
return flavor;
}
/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */
static gpointer
string_create_default (void)
{
return guppi_strdup ("");
}
static void
string_destroy (gpointer ptr)
{
guppi_free (ptr);
}
static gpointer
string_copy (gpointer ptr)
{
return guppi_strdup ((gchar *) ptr);
}
static gboolean
string_equality (gpointer a, gpointer b)
{
if (a == b)
return TRUE;
if (a == NULL || b == NULL)
return FALSE;
return !strcmp ((const gchar *) a, (const gchar *) b);
}
static gboolean
string_va2p (const gchar *key, const gchar *subkey, va_list *va, gpointer *storage)
{
const gchar *str = va_arg (*va, const gchar *);
gboolean changed = !string_equality ((gpointer) str, *storage);
guppi_free (*storage);
if (subkey == NULL || !strcmp (subkey, "dup")) {
*storage = guppi_strdup (str);
} else if (!strcmp (subkey, "adopt")) {
*storage = (gpointer) str;
} else {
g_warning ("unknown subkey: '%s::%s'", key, subkey);
*storage = guppi_strdup (str);
}
return changed;
}
static void
string_p2va (const gchar *key, const gchar *subkey, gpointer ptr, gpointer dest)
{
gchar *str = (gchar *) ptr;
if (subkey == NULL || !strcmp (subkey, "dup") || !strcmp (subkey, "_default")) {
str = guppi_strdup (str);
} else if (strcmp (subkey, "raw")) {
g_warning ("unknown subkey: '%s::%s'", key, subkey);
str = guppi_strdup (str); /* also dup in this case */
}
*(gchar **)dest = str;
}
static gchar *
string_exp_str (gpointer ptr)
{
return guppi_strdup ((gchar *) ptr);
}
static gboolean
string_imp_str (const gchar *str, gpointer *ptr)
{
guppi_free (*ptr);
*ptr = guppi_strdup (str);
return TRUE;
}
static void
string_bag_to_widget_cb (GuppiAttributeWidget *gaw, gpointer closure)
{
GtkEditable *entry = GTK_EDITABLE (closure);
gchar *str;
gint pos = 0;
guppi_attribute_widget_bag_get (gaw, NULL, &str);
gtk_editable_delete_text (entry, 0, -1);
gtk_editable_insert_text (entry, str, strlen (str), &pos);
guppi_free (str);
}
static void
string_activate_cb (GtkEditable *w, gpointer closure)
{
GuppiAttributeWidget *gaw = GUPPI_ATTRIBUTE_WIDGET (closure);
gchar *str;
str = gtk_editable_get_chars (w, 0, -1);
guppi_attribute_widget_bag_set (gaw, NULL, str ? str : "");
g_free (str);
}
static GtkWidget *
string_widget (const gchar *key)
{
GtkWidget *gaw = guppi_attribute_widget_new (guppi_attribute_flavor_string (), key);
GtkWidget *w;
w = gtk_entry_new ();
gtk_container_add (GTK_CONTAINER (gaw), w);
gtk_widget_show (w);
gtk_signal_connect (GTK_OBJECT (gaw),
"bag_to_widget",
GTK_SIGNAL_FUNC (string_bag_to_widget_cb),
w);
gtk_signal_connect (GTK_OBJECT (w),
"activate",
GTK_SIGNAL_FUNC (string_activate_cb),
gaw);
return gaw;
}
GuppiAttributeFlavor
guppi_attribute_flavor_string (void)
{
static GuppiAttributeFlavor flavor = -1;
if (flavor < 0) {
flavor = guppi_attribute_flavor_register ("string",
string_create_default,
string_destroy,
string_copy,
string_equality,
NULL,
string_va2p,
string_p2va);
guppi_attribute_flavor_add_widget (flavor, string_widget);
guppi_attribute_flavor_add_string_serialization (flavor,
string_exp_str,
string_imp_str);
}
return flavor;
}
/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */
static gpointer
double_create_default (void)
{
double *p = guppi_new (double, 1);
*p = 0;
return p;
}
static void
double_destroy (gpointer ptr)
{
guppi_free (ptr);
}
static gpointer
double_copy (gpointer ptr)
{
double *p = guppi_new (double, 1);
*p = *(double *) ptr;
return p;
}
static gboolean
double_equality (gpointer a, gpointer b)
{
return *(double *) a == *(double *) b;
}
static gboolean
double_va2p (const gchar *key, const gchar *subkey, va_list *va, gpointer *storage)
{
double x = *storage ? *(double *)*storage : 0.0;
double y = va_arg (*va, double);
guppi_free (*storage);
*storage = guppi_new (double, 1);
*(double *)*storage = y;
return x != y;
}
static void
double_p2va (const gchar *key, const gchar *subkey, gpointer ptr, gpointer dest)
{
*(double *) dest = *(double *) ptr;
}
static gchar *
double_exp_str (gpointer ptr)
{
gchar *str;
gchar *locale;
locale = setlocale (LC_NUMERIC, "C");
str = guppi_strdup_printf ("%g", *(double *) ptr);
setlocale (LC_NUMERIC, locale);
return str;
}
static gboolean
double_imp_str (const gchar *str, gpointer *ptr)
{
gchar *locale;
double *p;
guppi_free (*ptr);
locale = setlocale (LC_NUMERIC, "C");
p = guppi_new (double, 1);
*p = atof (str);
*ptr = p;
setlocale (LC_NUMERIC, locale);
return TRUE;
}
GuppiAttributeFlavor
guppi_attribute_flavor_double (void)
{
static GuppiAttributeFlavor flavor = -1;
if (flavor < 0) {
flavor = guppi_attribute_flavor_register ("double",
double_create_default,
double_destroy,
double_copy,
double_equality,
NULL,
double_va2p,
double_p2va);
guppi_attribute_flavor_add_string_serialization (flavor,
double_exp_str,
double_imp_str);
}
return flavor;
}
/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */
static void
dimension_bag_to_widget_cb (GuppiAttributeWidget *gaw, gpointer closure)
{
double pt;
guppi_attribute_widget_bag_get (gaw, NULL, &pt);
guppi_metric_entry_set_pt_value (GUPPI_METRIC_ENTRY (closure), pt);
}
static void
dimension_changed_cb (GuppiMetricEntry *w, gpointer closure)
{
double pt = guppi_metric_entry_pt_value (w);
guppi_attribute_widget_bag_set (GUPPI_ATTRIBUTE_WIDGET (closure), NULL, pt);
}
static GtkWidget *
dimension_widget (const gchar *key)
{
GtkWidget *gaw;
GtkWidget *w;
gaw = guppi_attribute_widget_new (guppi_attribute_flavor_dimension (), key);
w = guppi_metric_entry_new ();
gtk_container_add (GTK_CONTAINER (gaw), w);
gtk_widget_show (w);
gtk_signal_connect (GTK_OBJECT (gaw),
"bag_to_widget",
GTK_SIGNAL_FUNC (dimension_bag_to_widget_cb),
w);
gtk_signal_connect (GTK_OBJECT (w),
"changed_value",
GTK_SIGNAL_FUNC (dimension_changed_cb),
gaw);
return gaw;
}
GuppiAttributeFlavor
guppi_attribute_flavor_dimension (void)
{
static GuppiAttributeFlavor flavor = -1;
if (flavor < 0) {
flavor = guppi_attribute_flavor_register ("dimension",
double_create_default,
double_destroy,
double_copy,
double_equality,
NULL,
double_va2p,
double_p2va);
guppi_attribute_flavor_add_widget (flavor, dimension_widget);
guppi_attribute_flavor_add_string_serialization (flavor,
double_exp_str,
double_imp_str);
}
return flavor;
}
/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */
static gpointer
date_create_default (void)
{
return g_date_new ();
}
static void
date_destroy (gpointer ptr)
{
g_date_free ((GDate *) ptr);
}
static gpointer
date_copy (gpointer ptr)
{
GDate *dt = g_date_new ();
*dt = *(GDate *) ptr;
return dt;
}
static gboolean
date_equality (gpointer a, gpointer b)
{
gboolean x = g_date_valid ((GDate *) a);
gboolean y = g_date_valid ((GDate *) b);
if ((x && !y) || (!x && y))
return FALSE;
if (!x && !y)
return TRUE;
return g_date_compare ((GDate *) a, (GDate *) b) == 0;
}
static gboolean
date_va2p (const gchar *key, const gchar *subkey, va_list *va, gpointer *storage)
{
GDate *old_date = (GDate *)*storage;
GDate *dt = g_date_new ();
*dt = *va_arg (*va, GDate *);
*storage = dt;
return old_date == NULL || g_date_compare (old_date, dt) != 0;
}
static void
date_p2va (const gchar *key, const gchar *subkey, gpointer ptr, gpointer dest)
{
*(GDate *) dest = *(GDate *) ptr;
}
static gchar *
date_exp_str (gpointer ptr)
{
GDate *dt = (GDate *) ptr;
if (g_date_valid (dt)) {
return guppi_strdup_printf ("%04d-%02d-%02d",
g_date_year (dt),
g_date_month (dt),
g_date_day (dt));
} else {
return guppi_strdup ("xxxx-xx-xx");
}
}
static gboolean
date_imp_str (const gchar *str, gpointer *ptr)
{
GDate *dt = NULL;
gint y, m, d;
if (!strcmp (str, "xxxx-xx-xx")) {
dt = g_date_new ();
} else if (sscanf (str, "%d-%d-%d", &y, &m, &d) == 3) {
dt = g_date_new ();
g_date_set_dmy (dt, d, m, y);
if (!g_date_valid (dt)) {
g_date_free (dt);
dt = NULL;
}
}
g_date_free (*ptr);
*ptr = dt;
return dt != NULL;
}
GuppiAttributeFlavor
guppi_attribute_flavor_date (void)
{
static GuppiAttributeFlavor flavor = -1;
if (flavor < 0) {
flavor = guppi_attribute_flavor_register ("date",
date_create_default,
date_destroy,
date_copy,
date_equality,
NULL,
date_va2p,
date_p2va);
guppi_attribute_flavor_add_string_serialization (flavor,
date_exp_str,
date_imp_str);
}
return flavor;
}
/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */
static gchar *
rgb_exp_str (gpointer ptr)
{
guint32 rgb = GPOINTER_TO_UINT (ptr);
gint r, g, b;
UINT_TO_RGB (rgb, &r, &g, &b);
return guppi_strdup_printf ("#%02x%02x%02x", r, g, b);
}
static gboolean
rgb_imp_str (const gchar *str, gpointer *ptr)
{
gint r, g, b;
if (str[0] == '#' && sscanf (str+1, "%2x%2x%2x", &r, &g, &b) == 3) {
*ptr = GUINT_TO_POINTER (RGB_TO_UINT (r, g, b));
return TRUE;
}
return FALSE;
}
static void
rgb_bag_to_widget_cb (GuppiAttributeWidget *gaw, gpointer closure)
{
double c[4];
guint32 rgb;
gint r, g, b;
guppi_attribute_widget_bag_get (gaw, NULL, &rgb);
UINT_TO_RGB (rgb, &r, &g, &b);
c[0] = r / 255.0;
c[1] = g / 255.0;
c[2] = b / 255.0;
c[3] = 1.0;
gtk_color_selection_set_color (GTK_COLOR_SELECTION (closure), c);
}
static void
rgb_color_changed_cb (GtkColorSelection *w, gpointer closure)
{
double c[4];
guint32 rgb;
gtk_color_selection_get_color (w, c);
rgb = RGB_TO_UINT ((gint)rint (c[0] * 255),
(gint)rint (c[1] * 255),
(gint)rint (c[2] * 255));
guppi_attribute_widget_bag_set (GUPPI_ATTRIBUTE_WIDGET (closure), NULL, c);
}
static GtkWidget *
rgb_widget (const gchar *key)
{
GtkWidget *gaw = guppi_attribute_widget_new (guppi_attribute_flavor_rgb (), key);
GtkWidget *w = gtk_color_selection_new ();
gtk_color_selection_set_opacity ((GtkColorSelection *) w, FALSE);
gtk_container_add (GTK_CONTAINER (gaw), w);
gtk_widget_show (w);
gtk_signal_connect (GTK_OBJECT (gaw),
"bag_to_widget",
GTK_SIGNAL_FUNC (rgb_bag_to_widget_cb),
w);
gtk_signal_connect (GTK_OBJECT (w),
"color_changed",
GTK_SIGNAL_FUNC (rgb_color_changed_cb),
gaw);
return gaw;
}
GuppiAttributeFlavor
guppi_attribute_flavor_rgb (void)
{
static GuppiAttributeFlavor flavor = -1;
if (flavor < 0) {
flavor = guppi_attribute_flavor_register ("rgb",
uint32_create_default,
uint32_destroy,
uint32_copy,
uint32_equality,
NULL,
uint32_va2p,
uint32_p2va);
guppi_attribute_flavor_add_widget (flavor, rgb_widget);
guppi_attribute_flavor_add_string_serialization (flavor,
rgb_exp_str,
rgb_imp_str);
}
return flavor;
}
/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */
static gchar *
rgba_exp_str (gpointer ptr)
{
guint32 rgba = GPOINTER_TO_UINT (ptr);
gint r, g, b, a;
UINT_TO_RGBA (rgba, &r, &g, &b, &a);
return guppi_strdup_printf ("#%02x%02x%02x%02x", r, g, b, a);
}
static gboolean
rgba_imp_str (const gchar *str, gpointer *ptr)
{
gint r, g, b, a;
if (str[0] == '#' && sscanf (str+1, "%2x%2x%2x%2x", &r, &g, &b, &a) == 4) {
*ptr = GUINT_TO_POINTER (RGBA_TO_UINT (r, g, b, a));
return TRUE;
}
return FALSE;
}
static void
rgba_bag_to_widget_cb (GuppiAttributeWidget *gaw, gpointer closure)
{
guint32 rgba;
gint r, g, b, a;
guppi_attribute_widget_bag_get (gaw, NULL, &rgba);
UINT_TO_RGBA (rgba, &r, &g, &b, &a);
gnome_color_picker_set_i8 (GNOME_COLOR_PICKER (closure), r, g, b, a);
}
static void
rgba_color_set_cb (GnomeColorPicker *w, guint r16, guint g16, guint b16, guint a16, gpointer closure)
{
guint32 rgba;
guint8 r, g, b, a;
gnome_color_picker_get_i8 (w, &r, &g, &b, &a);
rgba = RGBA_TO_UINT (r, g, b, a);
guppi_attribute_widget_bag_set (GUPPI_ATTRIBUTE_WIDGET (closure), NULL, rgba);
}
static GtkWidget *
rgba_widget (const gchar *key)
{
GtkWidget *gaw = guppi_attribute_widget_new (guppi_attribute_flavor_rgba (), key);
GtkWidget *w = gnome_color_picker_new ();
gnome_color_picker_set_use_alpha ((GnomeColorPicker *) w, TRUE);
gtk_container_add (GTK_CONTAINER (gaw), w);
gtk_widget_show (w);
gtk_signal_connect (GTK_OBJECT (gaw),
"bag_to_widget",
GTK_SIGNAL_FUNC (rgba_bag_to_widget_cb),
w);
gtk_signal_connect (GTK_OBJECT (w),
"color_set",
GTK_SIGNAL_FUNC (rgba_color_set_cb),
gaw);
return gaw;
}
GuppiAttributeFlavor
guppi_attribute_flavor_rgba (void)
{
static GuppiAttributeFlavor flavor = -1;
if (flavor < 0) {
flavor = guppi_attribute_flavor_register ("rgba",
uint32_create_default,
uint32_destroy,
uint32_copy,
uint32_equality,
NULL,
uint32_va2p,
uint32_p2va);
guppi_attribute_flavor_add_widget (flavor, rgba_widget);
guppi_attribute_flavor_add_string_serialization (flavor,
rgba_exp_str,
rgba_imp_str);
}
return flavor;
}
/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */
static gpointer
font_create_default (void)
{
return guppi_default_font_medium ();
}
static void
font_destroy (gpointer ptr)
{
guppi_unref (ptr);
}
static gpointer
font_copy (gpointer ptr)
{
guppi_ref (ptr);
return ptr;
}
static gboolean
font_equality (gpointer a, gpointer b)
{
gchar *sa, *sb;
gboolean eq;
if (a == b)
return TRUE;
sa = gnome_font_get_full_name (GNOME_FONT (a));
sb = gnome_font_get_full_name (GNOME_FONT (b));
eq = !strcmp (sa, sb);
g_free (sa);
g_free (sb);
return eq;
}
static gboolean
font_va2p (const gchar *key, const gchar *subkey, va_list *va, gpointer *storage)
{
GnomeFont *old_font = (GnomeFont *)*storage;
GnomeFont *font = va_arg (*va, GnomeFont *);
guppi_refcounting_assign (*storage, font);
return old_font != font;
}
static void
font_p2va (const gchar *key, const gchar *subkey, gpointer ptr, gpointer dest)
{
*(GnomeFont **) dest = (GnomeFont *) ptr;
if (subkey == NULL || !strcmp (subkey, "ref")) {
guppi_ref (ptr);
} else if (strcmp (subkey, "raw")) {
g_warning ("Unknown subkey '%s::%s'", key, subkey);
guppi_ref (ptr); /* we also ref in this case */
}
}
static gchar *
font_exp_str (gpointer ptr)
{
return gnome_font_get_full_name (GNOME_FONT (ptr));
}
static gboolean
font_imp_str (const gchar *str, gpointer *ptr)
{
GnomeFont *font = gnome_font_new_from_full_name (str);
gpointer old = *ptr;
if (font) {
*ptr = font;
} else {
*ptr = font_create_default ();
}
guppi_unref (old);
return TRUE;
}
GuppiAttributeFlavor
guppi_attribute_flavor_font (void)
{
static GuppiAttributeFlavor flavor = -1;
if (flavor < 0) {
flavor = guppi_attribute_flavor_register ("font",
font_create_default,
font_destroy,
font_copy,
font_equality,
NULL,
font_va2p,
font_p2va);
guppi_attribute_flavor_add_string_serialization (flavor,
font_exp_str,
font_imp_str);
}
return flavor;
}
syntax highlighted by Code2HTML, v. 0.9.1