/* dia-variable.c
 * Copyright (C) 2001  Arjan Molenaar
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include "dia-variable.h"
#include "diamarshal.h"
#include "diatypebuiltins.h"
#include "dia-canvas-i18n.h"

///#define D(msg) G_STMT_START { g_print (G_STRLOC": "); g_print msg; g_print ("\n"); } G_STMT_END
#define D(msg)

enum
{
	CHANGED,
	INTERNAL_CHANGED,
	LAST_SIGNAL
};

enum
{
	PROP_VALUE = 1,
	PROP_STRENGTH
};

static void dia_variable_init		(DiaVariable		*variable);
static void dia_variable_class_init	(DiaVariableClass	*klass);
static void dia_variable_set_property	(GObject		*object,
					  guint			 property_id,
					  const GValue		*value,
					  GParamSpec		*pspec);
static void dia_variable_get_property	(GObject		*object,
					  guint			 property_id,
					  GValue		*value,
					  GParamSpec		*pspec);

static GObjectClass *parent_class = NULL;
static guint signals[LAST_SIGNAL] = { 0 };

GType
dia_variable_get_type (void)
{
	static GType object_type = 0;

	if (!object_type) {
		static const GTypeInfo object_info = {
			sizeof (DiaVariableClass),
			(GBaseInitFunc) NULL,
			(GBaseFinalizeFunc) NULL,
			(GClassInitFunc) dia_variable_class_init,
			(GClassFinalizeFunc) NULL,
			(gconstpointer) NULL, /* class_data */
			sizeof (DiaVariable),
			(guint16) 0, /* n_preallocs */
			(GInstanceInitFunc) dia_variable_init,
		};
		object_type = g_type_register_static (G_TYPE_OBJECT,
						      "DiaVariable",
						      &object_info,
						      0);
	}

	return object_type;
}


static void
dia_variable_class_init (DiaVariableClass *klass)
{
	GObjectClass *object_class;

	object_class = (GObjectClass*) klass;

	parent_class = g_type_class_peek_parent (klass);

	object_class->set_property = dia_variable_set_property;
	object_class->get_property = dia_variable_get_property;

	signals[CHANGED] = 
	  g_signal_new ("changed",
			G_TYPE_FROM_CLASS (klass),
			G_SIGNAL_RUN_LAST,
			G_STRUCT_OFFSET (DiaVariableClass, changed),
			NULL, NULL,
			dia_marshal_VOID__VOID,
			G_TYPE_NONE, 0);
	signals[INTERNAL_CHANGED] = 
	  g_signal_new ("changed_internal",
			G_TYPE_FROM_CLASS (klass),
			G_SIGNAL_RUN_LAST,
			G_STRUCT_OFFSET (DiaVariableClass, changed_internal),
			NULL, NULL,
			dia_marshal_VOID__VOID,
			G_TYPE_NONE, 0);

	g_object_class_install_property (object_class,
					 PROP_VALUE,
					 g_param_spec_double ("value",
						_("Value"),
						_("Value held by this variable"),
						-G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
						G_PARAM_READWRITE));
	g_object_class_install_property (object_class,
					 PROP_STRENGTH,
					 g_param_spec_enum ("strength",
						_("Strength"),
						_("Strength of the variable."),
						DIA_TYPE_STRENGTH,
						DIA_STRENGTH_WEAK,
						G_PARAM_READWRITE));
}


static void
dia_variable_init (DiaVariable *variable)
{
	variable->value = 0.0;
	variable->strength = DIA_STRENGTH_WEAK;
}


static void
dia_variable_set_property (GObject *object, guint property_id,
			   const GValue *value, GParamSpec *pspec)
{
	DiaVariable *var = DIA_VARIABLE (object);

	switch (property_id) {
	case PROP_VALUE:
		dia_variable_set_value (var, g_value_get_double (value));
		break;
	case PROP_STRENGTH:
		dia_variable_set_strength (var, g_value_get_enum (value));
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
dia_variable_get_property (GObject *object, guint property_id,
			   GValue *value, GParamSpec *pspec)
{
	DiaVariable *var = DIA_VARIABLE (object);

	switch (property_id) {
	case PROP_VALUE:
		g_value_set_double (value, var->value);
		break;
	case PROP_STRENGTH:
		g_value_set_enum (value, var->strength);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
	}
}

/**
 * dia_variable_new:
 *
 * Create a new variable.
 *
 * Return value: a newly-created variable.
 **/
DiaVariable*
dia_variable_new (void)
{
	return g_object_new (DIA_TYPE_VARIABLE, NULL);
}

/**
 * dia_variable_set_value:
 * @var: 
 * @value: 
 *
 * Set the value for the variable.
 **/
void
dia_variable_set_value (DiaVariable *var, gdouble value)
{
	g_return_if_fail (DIA_IS_VARIABLE (var));

	var->value = value;

	g_signal_emit (var, signals[INTERNAL_CHANGED], 0);
}

/**
 * dia_variable_get_value:
 * @var: 
 *
 * Get the value of the variable.
 *
 * Return value: 
 **/
gdouble
dia_variable_get_value (DiaVariable *var)
{
	g_return_val_if_fail (DIA_IS_VARIABLE (var), 0.0);

	return var->value;
}

/**
 * dia_variable_set_strength:
 * @var: 
 * @strength: 
 *
 * Set the strength of the variable. Stronger variables are less likely to
 * change if they are used in a #DiaConstraint.
 **/
void
dia_variable_set_strength (DiaVariable *var, DiaStrength strength)
{
	g_return_if_fail (DIA_IS_VARIABLE (var));

	var->strength = strength;
}

/**
 * dia_variable_get_strength:
 * @var: 
 *
 * Retrieve the strength of variable @var.
 *
 * Return value: Return the strength of the variable.
 **/
DiaStrength
dia_variable_get_strength (DiaVariable *var)
{
	g_return_val_if_fail (DIA_IS_VARIABLE (var), DIA_STRENGTH_WEAK);

	return var->strength;
}

