1998-07-02 07:06:49 +08:00
|
|
|
#include "gimpsignal.h"
|
|
|
|
#include "gimpsetP.h"
|
|
|
|
|
|
|
|
/* Yep, this can be optimized quite a lot */
|
|
|
|
|
1999-01-08 03:53:05 +08:00
|
|
|
|
|
|
|
typedef struct _GimpSetHandler {
|
|
|
|
const gchar* signame;
|
|
|
|
GtkSignalFunc func;
|
|
|
|
gpointer user_data;
|
|
|
|
} GimpSetHandler;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
GimpObject* object;
|
|
|
|
GArray* handlers;
|
|
|
|
guint destroy_handler;
|
|
|
|
} Node;
|
|
|
|
|
1998-07-02 07:06:49 +08:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
ADD,
|
|
|
|
REMOVE,
|
|
|
|
LAST_SIGNAL
|
|
|
|
};
|
|
|
|
|
1999-01-08 03:53:05 +08:00
|
|
|
static Node* gimp_set_find_node (GimpSet* set, GimpObject* ob);
|
|
|
|
static Node* gimp_set_node_new (GimpSet* set, gpointer ob);
|
|
|
|
static void gimp_set_node_free (GimpSet* set, Node* n);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1998-07-02 07:06:49 +08:00
|
|
|
static guint gimp_set_signals [LAST_SIGNAL];
|
|
|
|
|
|
|
|
static GimpObjectClass* parent_class;
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_set_destroy (GtkObject* ob)
|
|
|
|
{
|
|
|
|
GimpSet* set=GIMP_SET(ob);
|
1999-01-08 03:53:05 +08:00
|
|
|
GSList* l;
|
|
|
|
for(l=set->list;l;l=l->next)
|
|
|
|
gimp_set_node_free(set, l->data);
|
1998-07-02 07:06:49 +08:00
|
|
|
g_slist_free(set->list);
|
1999-01-08 03:53:05 +08:00
|
|
|
g_array_free(set->handlers, TRUE);
|
1998-07-02 07:06:49 +08:00
|
|
|
GTK_OBJECT_CLASS(parent_class)->destroy (ob);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_set_init (GimpSet* set)
|
|
|
|
{
|
|
|
|
set->list=NULL;
|
|
|
|
set->type=GTK_TYPE_OBJECT;
|
1999-01-08 03:53:05 +08:00
|
|
|
set->handlers=g_array_new(FALSE, FALSE, sizeof(GimpSetHandler));
|
1998-07-02 07:06:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_set_class_init (GimpSetClass* klass)
|
|
|
|
{
|
|
|
|
GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass);
|
|
|
|
GtkType type = object_class->type;
|
|
|
|
|
|
|
|
parent_class=gtk_type_parent_class(type);
|
|
|
|
|
|
|
|
object_class->destroy = gimp_set_destroy;
|
|
|
|
|
|
|
|
gimp_set_signals[ADD]=
|
|
|
|
gimp_signal_new ("add", 0, type, 0, gimp_sigtype_pointer);
|
|
|
|
gimp_set_signals[REMOVE]=
|
|
|
|
gimp_signal_new ("remove", 0, type, 0, gimp_sigtype_pointer);
|
|
|
|
gtk_object_class_add_signals (object_class,
|
|
|
|
gimp_set_signals,
|
|
|
|
LAST_SIGNAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
GtkType gimp_set_get_type (void)
|
|
|
|
{
|
|
|
|
static GtkType type;
|
|
|
|
GIMP_TYPE_INIT(type,
|
|
|
|
GimpSet,
|
|
|
|
GimpSetClass,
|
|
|
|
gimp_set_init,
|
|
|
|
gimp_set_class_init,
|
|
|
|
GIMP_TYPE_OBJECT);
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GimpSet*
|
|
|
|
gimp_set_new (GtkType type, gboolean weak){
|
|
|
|
GimpSet* set=gtk_type_new (gimp_set_get_type ());
|
|
|
|
set->type=type;
|
|
|
|
set->weak=weak;
|
|
|
|
return set;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_set_destroy_cb (GtkObject* ob, gpointer data){
|
|
|
|
GimpSet* set=GIMP_SET(data);
|
|
|
|
gimp_set_remove(set, ob);
|
|
|
|
}
|
|
|
|
|
1999-01-08 03:53:05 +08:00
|
|
|
static Node*
|
|
|
|
gimp_set_find_node (GimpSet* set, GimpObject* ob)
|
|
|
|
{
|
|
|
|
GSList* l = set->list;
|
|
|
|
for(l = set->list; l; l = l->next){
|
|
|
|
Node* n = l->data;
|
|
|
|
if (n->object == ob)
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Node*
|
|
|
|
gimp_set_node_new (GimpSet* set, gpointer ob)
|
|
|
|
{
|
|
|
|
gint i;
|
|
|
|
Node* n = g_new(Node, 1);
|
|
|
|
n->object = ob;
|
|
|
|
n->handlers = g_array_new(FALSE, FALSE, sizeof(guint));
|
|
|
|
g_array_set_size(n->handlers, set->handlers->len);
|
|
|
|
for(i = 0;i < n->handlers->len; i++){
|
|
|
|
GimpSetHandler* h
|
|
|
|
= &g_array_index(set->handlers, GimpSetHandler, i);
|
|
|
|
if(h->signame)
|
|
|
|
g_array_index(n->handlers, guint, i)
|
|
|
|
= gtk_signal_connect(GTK_OBJECT(ob),
|
|
|
|
h->signame,
|
|
|
|
h->func,
|
|
|
|
h->user_data);
|
|
|
|
}
|
|
|
|
if(set->weak)
|
|
|
|
n->destroy_handler
|
|
|
|
= gtk_signal_connect(GTK_OBJECT(ob),
|
|
|
|
"destroy",
|
|
|
|
GTK_SIGNAL_FUNC(gimp_set_destroy_cb),
|
|
|
|
set);
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_set_node_free (GimpSet* set, Node* n)
|
|
|
|
{
|
|
|
|
gint i;
|
|
|
|
GimpObject* ob = n->object;
|
|
|
|
for(i=0;i < set->handlers->len; i++){
|
|
|
|
GimpSetHandler* h
|
|
|
|
= &g_array_index(set->handlers, GimpSetHandler, i);
|
|
|
|
if(h->signame)
|
|
|
|
gtk_signal_disconnect(GTK_OBJECT(ob),
|
|
|
|
g_array_index(n->handlers,
|
|
|
|
guint,
|
|
|
|
i));
|
|
|
|
}
|
|
|
|
if(set->weak)
|
|
|
|
gtk_signal_disconnect(GTK_OBJECT(ob),
|
|
|
|
n->destroy_handler);
|
|
|
|
g_array_free(n->handlers, TRUE);
|
|
|
|
g_free(n);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-07-02 07:06:49 +08:00
|
|
|
gboolean
|
|
|
|
gimp_set_add (GimpSet* set, gpointer val)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail(set, FALSE);
|
|
|
|
g_return_val_if_fail(GTK_CHECK_TYPE(val, set->type), FALSE);
|
|
|
|
|
1999-01-08 03:53:05 +08:00
|
|
|
if(gimp_set_find_node(set, val))
|
1998-07-02 07:06:49 +08:00
|
|
|
return FALSE;
|
|
|
|
|
1999-01-08 03:53:05 +08:00
|
|
|
set->list=g_slist_prepend(set->list, gimp_set_node_new(set, val));
|
1998-07-02 07:06:49 +08:00
|
|
|
|
|
|
|
gtk_signal_emit (GTK_OBJECT(set), gimp_set_signals[ADD], val);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
gimp_set_remove (GimpSet* set, gpointer val) {
|
1999-01-08 03:53:05 +08:00
|
|
|
Node* n;
|
|
|
|
|
1998-07-02 07:06:49 +08:00
|
|
|
g_return_val_if_fail(set, FALSE);
|
|
|
|
|
1999-01-08 03:53:05 +08:00
|
|
|
n = gimp_set_find_node (set, val);
|
|
|
|
g_return_val_if_fail(n, FALSE);
|
1998-07-02 07:06:49 +08:00
|
|
|
|
|
|
|
gtk_signal_emit (GTK_OBJECT(set), gimp_set_signals[REMOVE], val);
|
|
|
|
|
1999-01-08 03:53:05 +08:00
|
|
|
gimp_set_node_free(set, n);
|
|
|
|
|
|
|
|
set->list=g_slist_remove(set->list, n);
|
1998-07-02 07:06:49 +08:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
gimp_set_have (GimpSet* set, gpointer val) {
|
1999-01-08 03:53:05 +08:00
|
|
|
return !!gimp_set_find_node(set, val);
|
1998-07-02 07:06:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_set_foreach(GimpSet* set, GFunc func, gpointer user_data)
|
|
|
|
{
|
1999-01-08 03:53:05 +08:00
|
|
|
GSList* l;
|
|
|
|
for(l=set->list; l;l=l->next){
|
|
|
|
Node* n = l->data;
|
|
|
|
func(n->object, user_data);
|
|
|
|
}
|
1998-07-02 07:06:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
GtkType
|
|
|
|
gimp_set_type (GimpSet* set){
|
|
|
|
return set->type;
|
|
|
|
}
|
1999-01-08 03:53:05 +08:00
|
|
|
|
|
|
|
GimpSetHandlerId
|
|
|
|
gimp_set_add_handler(GimpSet* set, const gchar* signame,
|
|
|
|
GtkSignalFunc handler, gpointer user_data){
|
|
|
|
GimpSetHandler h;
|
|
|
|
GSList* l;
|
|
|
|
guint a;
|
|
|
|
|
|
|
|
g_assert(signame);
|
|
|
|
|
|
|
|
h.signame = signame;
|
|
|
|
h.func = handler;
|
|
|
|
h.user_data = user_data;
|
|
|
|
|
|
|
|
for(a=0;a<set->handlers->len;a++)
|
|
|
|
if(!g_array_index(set->handlers, GimpSetHandler, a).signame)
|
|
|
|
break;
|
|
|
|
if(a<set->handlers->len){
|
|
|
|
g_array_index(set->handlers, GimpSetHandler, a) = h;
|
|
|
|
for(l=set->list;l;l=l->next){
|
|
|
|
Node* n = l->data;
|
|
|
|
guint i = gtk_signal_connect(GTK_OBJECT(n->object),
|
|
|
|
signame,
|
|
|
|
handler,
|
|
|
|
user_data);
|
|
|
|
g_array_index(n->handlers, guint, a) = i;
|
|
|
|
}
|
|
|
|
} else{
|
|
|
|
g_array_append_val(set->handlers, h);
|
|
|
|
for(l=set->list;l;l=l->next){
|
|
|
|
Node* n = l->data;
|
|
|
|
guint i = gtk_signal_connect(GTK_OBJECT(n->object),
|
|
|
|
signame,
|
|
|
|
handler,
|
|
|
|
user_data);
|
|
|
|
g_array_append_val(n->handlers, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_set_remove_handler(GimpSet* set, GimpSetHandlerId id)
|
|
|
|
{
|
|
|
|
GSList* l;
|
|
|
|
for(l=set->list;l;l=l->next){
|
|
|
|
Node* n = l->data;
|
|
|
|
gtk_signal_disconnect(GTK_OBJECT(n->object),
|
|
|
|
g_array_index(n->handlers, guint, id));
|
|
|
|
}
|
|
|
|
g_array_index(set->handlers, GimpSetHandler, id).signame = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|