1 /*
2  * Copyright (C) 2004 2009, Magnus Hjorth
3  *
4  * This file is part of mhWaveEdit.
5  *
6  * mhWaveEdit is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * mhWaveEdit is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with mhWaveEdit; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include <config.h>
22 
23 #include <gtk/gtk.h>
24 #include "main.h"
25 #include "listobject.h"
26 
27 enum { ITEM_ADDED_SIGNAL, ITEM_REMOVED_SIGNAL, ITEM_NOTIFY_SIGNAL,
28        LAST_SIGNAL };
29 static guint list_object_signals[LAST_SIGNAL] = { 0 };
30 static GtkObjectClass *parent_class;
31 
list_object_destroy(GtkObject * obj)32 static void list_object_destroy(GtkObject *obj)
33 {
34      ListObject *lo = LIST_OBJECT(obj);
35      list_object_clear(lo,FALSE);
36 }
37 
list_object_class_init(GtkObjectClass * klass)38 static void list_object_class_init(GtkObjectClass *klass)
39 {
40      ListObjectClass *loc = LIST_OBJECT_CLASS(klass);
41      parent_class = gtk_type_class( gtk_object_get_type() );
42 
43      klass->destroy = list_object_destroy;
44      loc->item_removed = NULL;
45      loc->item_added = NULL;
46 
47      list_object_signals[ITEM_ADDED_SIGNAL] =
48 	  gtk_signal_new("item-added", GTK_RUN_FIRST, GTK_CLASS_TYPE(klass),
49 			 GTK_SIGNAL_OFFSET(ListObjectClass,item_added),
50 			 gtk_marshal_NONE__POINTER, GTK_TYPE_NONE,
51 			 1, GTK_TYPE_POINTER);
52      list_object_signals[ITEM_REMOVED_SIGNAL] =
53 	  gtk_signal_new("item-removed", GTK_RUN_FIRST, GTK_CLASS_TYPE(klass),
54 			 GTK_SIGNAL_OFFSET(ListObjectClass,item_removed),
55 			 gtk_marshal_NONE__POINTER, GTK_TYPE_NONE,
56 			 1, GTK_TYPE_POINTER);
57      list_object_signals[ITEM_NOTIFY_SIGNAL] =
58 	  gtk_signal_new("item-notify", GTK_RUN_FIRST, GTK_CLASS_TYPE(klass),
59 			 GTK_SIGNAL_OFFSET(ListObjectClass,item_notify),
60 			 gtk_marshal_NONE__POINTER, GTK_TYPE_NONE,
61 			 1, GTK_TYPE_POINTER);
62      gtk_object_class_add_signals(klass,list_object_signals,LAST_SIGNAL);
63 }
64 
list_object_init(GtkObject * obj)65 static void list_object_init(GtkObject *obj)
66 {
67      ListObject *lo = LIST_OBJECT(obj);
68      lo->list = NULL;
69      lo->do_ref = FALSE;
70 }
71 
list_object_get_type(void)72 GtkType list_object_get_type(void)
73 {
74      static GtkType id=0;
75      if (!id) {
76 	  GtkTypeInfo info = {
77 	       "ListObject",
78 	       sizeof(ListObject),
79 	       sizeof(ListObjectClass),
80 	       (GtkClassInitFunc) list_object_class_init,
81 	       (GtkObjectInitFunc) list_object_init
82 	  };
83 	  id = gtk_type_unique( gtk_object_get_type(), &info );
84      }
85      return id;
86 }
87 
list_object_new(gboolean do_ref)88 ListObject *list_object_new(gboolean do_ref)
89 {
90      ListObject *lo = gtk_type_new(list_object_get_type());
91      lo->do_ref = do_ref;
92      return lo;
93 }
94 
list_object_new_from_list(GList * list,gboolean do_ref)95 ListObject *list_object_new_from_list(GList *list, gboolean do_ref)
96 {
97      ListObject *lo = gtk_type_new(list_object_get_type());
98      lo->do_ref = do_ref;
99      lo->list = list;
100      if (do_ref) {
101 	  g_list_foreach(list,(GFunc)gtk_object_ref,NULL);
102 	  g_list_foreach(list,(GFunc)gtk_object_sink,NULL);
103      }
104      return lo;
105 }
106 
list_object_add(ListObject * lo,gpointer ptr)107 void list_object_add(ListObject *lo, gpointer ptr)
108 {
109      lo->list = g_list_append(lo->list, ptr);
110      if (lo->do_ref) {
111 	  gtk_object_ref(GTK_OBJECT(ptr));
112 	  gtk_object_sink(GTK_OBJECT(ptr));
113      }
114      gtk_signal_emit(GTK_OBJECT(lo),list_object_signals[ITEM_ADDED_SIGNAL],
115 		     ptr);
116 }
117 
list_object_remove(ListObject * lo,gpointer ptr)118 gboolean list_object_remove(ListObject *lo, gpointer ptr)
119 {
120      GList *l;
121      l = g_list_find(lo->list,ptr);
122      if (l == NULL) return FALSE;
123      lo->list = g_list_remove_link( lo->list, l );
124      gtk_signal_emit(GTK_OBJECT(lo),list_object_signals[ITEM_REMOVED_SIGNAL],
125 		     ptr);
126      if (lo->do_ref) gtk_object_unref(GTK_OBJECT(ptr));
127      g_list_free_1(l);
128      return TRUE;
129 }
130 
list_object_notify(ListObject * lo,gpointer ptr)131 void list_object_notify(ListObject *lo, gpointer ptr)
132 {
133      gtk_signal_emit(GTK_OBJECT(lo),list_object_signals[ITEM_NOTIFY_SIGNAL],
134 		     ptr);
135 }
136 
list_object_clear(ListObject * lo,gboolean do_signal)137 void list_object_clear(ListObject *lo, gboolean do_signal)
138 {
139      GList *l;
140      if (do_signal)
141 	  while (lo->list != NULL) list_object_remove(lo,lo->list->data);
142      else {
143 	  l = lo->list;
144 	  lo->list = NULL;
145 	  if (lo->do_ref) g_list_foreach(l,(GFunc)gtk_object_unref,NULL);
146 	  g_list_free(l);
147      }
148 }
149 
list_object_get_size(ListObject * lo)150 guint list_object_get_size(ListObject *lo)
151 {
152      return g_list_length(lo->list);
153 }
154 
list_object_get(ListObject * lo,guint index)155 gpointer list_object_get(ListObject *lo, guint index)
156 {
157      return g_list_nth_data(lo->list, index);
158 }
159 
list_object_foreach(ListObject * lo,GFunc func,gpointer user_data)160 void list_object_foreach(ListObject *lo, GFunc func, gpointer user_data)
161 {
162      g_list_foreach(lo->list,func,user_data);
163 }
164