]> Pileus Git - ~andy/gtk/blob - gtk/gtkstatusbar.c
forgot to remove a printf
[~andy/gtk] / gtk / gtkstatusbar.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  * GtkStatusbar Copyright (C) 1998 Shawn T. Amundson
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the Free
17  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19
20 #include "gtkframe.h"
21 #include "gtklabel.h"
22 #include "gtksignal.h"
23 #include "gtkstatusbar.h"
24
25
26 enum
27 {
28   SIGNAL_TEXT_PUSHED,
29   SIGNAL_TEXT_POPPED,
30   SIGNAL_LAST
31 };
32
33 typedef void    (*SignalTextP)                    (GtkObject          *object,
34                                                    guint               context_id,
35                                                    const gchar        *text,
36                                                    gpointer            func_data);
37
38 static void gtk_statusbar_class_init               (GtkStatusbarClass *class);
39 static void gtk_statusbar_init                     (GtkStatusbar      *statusbar);
40 static void gtk_statusbar_destroy                  (GtkObject         *object);
41 static void gtk_statusbar_finalize                 (GtkObject         *object);
42 static void gtk_statusbar_update                   (GtkStatusbar      *statusbar,
43                                                     guint              context_id,
44                                                     const gchar       *text);
45      
46 static GtkContainerClass *parent_class;
47 static gint              statusbar_signals[SIGNAL_LAST] = { 0 };
48
49 guint      
50 gtk_statusbar_get_type ()
51 {
52   static guint statusbar_type = 0;
53
54   if (!statusbar_type)
55     {
56       GtkTypeInfo statusbar_info =
57       {
58         "GtkStatusbar",
59         sizeof (GtkStatusbar),
60         sizeof (GtkStatusbarClass),
61         (GtkClassInitFunc) gtk_statusbar_class_init,
62         (GtkObjectInitFunc) gtk_statusbar_init,
63         (GtkArgSetFunc) NULL,
64         (GtkArgGetFunc) NULL,
65       };
66
67       statusbar_type = gtk_type_unique (gtk_hbox_get_type (), &statusbar_info);
68     }
69
70   return statusbar_type;
71 };
72
73 static void
74 gtk_statusbar_marshal_text_p (GtkObject      *object,
75                               GtkSignalFunc  func,
76                               gpointer       func_data,
77                               GtkArg         *args)
78 {
79   SignalTextP sfunc = (SignalTextP) func;
80
81   (* sfunc) (object,
82              GTK_VALUE_UINT (args[0]),
83              GTK_VALUE_STRING (args[1]),
84              func_data);
85 }
86
87 static void
88 gtk_statusbar_class_init (GtkStatusbarClass *class)
89 {
90   GtkObjectClass *object_class;
91   GtkWidgetClass *widget_class;
92   GtkContainerClass *container_class;
93
94   object_class = (GtkObjectClass *) class;
95   widget_class = (GtkWidgetClass *) class;
96   container_class = (GtkContainerClass *) class;
97
98   parent_class = gtk_type_class (gtk_hbox_get_type ());
99
100   statusbar_signals[SIGNAL_TEXT_PUSHED] =
101     gtk_signal_new ("text_pushed",
102                     GTK_RUN_LAST,
103                     object_class->type,
104                     GTK_SIGNAL_OFFSET (GtkStatusbarClass, text_pushed),
105                     gtk_statusbar_marshal_text_p,
106                     GTK_TYPE_NONE, 2,
107                     GTK_TYPE_UINT,
108                     GTK_TYPE_STRING);
109   statusbar_signals[SIGNAL_TEXT_POPPED] =
110     gtk_signal_new ("text_popped",
111                     GTK_RUN_LAST,
112                     object_class->type,
113                     GTK_SIGNAL_OFFSET (GtkStatusbarClass, text_popped),
114                     gtk_statusbar_marshal_text_p,
115                     GTK_TYPE_NONE, 2,
116                     GTK_TYPE_UINT,
117                     GTK_TYPE_STRING);
118   gtk_object_class_add_signals (object_class, statusbar_signals, SIGNAL_LAST);
119   
120   object_class->destroy = gtk_statusbar_destroy;
121   object_class->finalize = gtk_statusbar_finalize;
122
123   class->messages_mem_chunk = g_mem_chunk_new ("GtkStatusBar messages mem chunk",
124                                                sizeof (GtkStatusbarMsg),
125                                                sizeof (GtkStatusbarMsg) * 64,
126                                                G_ALLOC_AND_FREE);
127
128   class->text_pushed = gtk_statusbar_update;
129   class->text_popped = gtk_statusbar_update;
130 }
131
132 static void
133 gtk_statusbar_init (GtkStatusbar *statusbar)
134 {
135   GtkBox *box;
136
137   box = GTK_BOX (statusbar);
138
139   box->spacing = 2;
140   box->homogeneous = FALSE;
141
142   statusbar->frame = gtk_frame_new (NULL);
143   gtk_frame_set_shadow_type (GTK_FRAME (statusbar->frame), GTK_SHADOW_IN);
144   gtk_box_pack_start (box, statusbar->frame, TRUE, TRUE, 0);
145   gtk_widget_show (statusbar->frame);
146
147   statusbar->label = gtk_label_new ("");
148   gtk_misc_set_alignment (GTK_MISC (statusbar->label), 0.0, 0.0);
149   gtk_container_add (GTK_CONTAINER (statusbar->frame), statusbar->label);
150   gtk_widget_show (statusbar->label);
151
152   statusbar->seq_context_id = 1;
153   statusbar->seq_message_id = 1;
154   statusbar->messages = NULL;
155   statusbar->keys = NULL;
156 }
157
158 GtkWidget* 
159 gtk_statusbar_new ()
160 {
161   return gtk_type_new (gtk_statusbar_get_type ());
162 }
163
164 static void
165 gtk_statusbar_update (GtkStatusbar *statusbar,
166                       guint         context_id,
167                       const gchar  *text)
168 {
169   g_return_if_fail (statusbar != NULL);
170   g_return_if_fail (GTK_IS_STATUSBAR (statusbar));
171
172   if (!text)
173     text = "";
174
175   gtk_label_set (GTK_LABEL (statusbar->label), text);
176 }
177
178 guint
179 gtk_statusbar_get_context_id (GtkStatusbar *statusbar,
180                               const gchar  *context_description)
181 {
182   gchar *string;
183   guint *id;
184   
185   g_return_val_if_fail (statusbar != NULL, 0);
186   g_return_val_if_fail (GTK_IS_STATUSBAR (statusbar), 0);
187   g_return_val_if_fail (context_description != NULL, 0);
188
189   /* we need to preserve namespaces on object datas */
190   string = g_strconcat ("gtk-status-bar-context:", context_description, NULL);
191
192   id = gtk_object_get_data (GTK_OBJECT (statusbar), string);
193   if (!id)
194     {
195       id = g_new (guint, 1);
196       *id = statusbar->seq_context_id++;
197       gtk_object_set_data_full (GTK_OBJECT (statusbar), string, id, (GtkDestroyNotify) g_free);
198       statusbar->keys = g_slist_prepend (statusbar->keys, string);
199     }
200   else
201     g_free (string);
202
203   return *id;
204 }
205
206 guint
207 gtk_statusbar_push (GtkStatusbar *statusbar,
208                     guint         context_id,
209                     const gchar  *text)
210 {
211   GtkStatusbarMsg *msg;
212   GtkStatusbarClass *class;
213
214   g_return_val_if_fail (statusbar != NULL, 0);
215   g_return_val_if_fail (GTK_IS_STATUSBAR (statusbar), 0);
216   g_return_val_if_fail (text != NULL, 0);
217   g_return_val_if_fail (context_id > 0, 0);
218
219   class = GTK_STATUSBAR_CLASS (GTK_OBJECT (statusbar)->klass);
220   msg = g_chunk_new (GtkStatusbarMsg, class->messages_mem_chunk);
221   msg->text = g_strdup (text);
222   msg->context_id = context_id;
223   msg->message_id = statusbar->seq_message_id++;
224
225   statusbar->messages = g_slist_prepend (statusbar->messages, msg);
226
227   gtk_signal_emit (GTK_OBJECT (statusbar),
228                    statusbar_signals[SIGNAL_TEXT_PUSHED],
229                    msg->context_id,
230                    msg->text);
231
232   return msg->message_id;
233 }
234
235 void
236 gtk_statusbar_pop (GtkStatusbar *statusbar,
237                    guint         context_id)
238 {
239   GtkStatusbarMsg *msg;
240
241   g_return_if_fail (statusbar != NULL);
242   g_return_if_fail (GTK_IS_STATUSBAR (statusbar));
243   g_return_if_fail (context_id > 0);
244
245   if (statusbar->messages)
246     {
247       GSList *list;
248       GtkStatusbarClass *class;
249
250       list = statusbar->messages;
251       msg = list->data;
252       class = GTK_STATUSBAR_CLASS (GTK_OBJECT (statusbar)->klass);
253       
254       statusbar->messages = g_slist_remove_link (statusbar->messages, list);
255       g_free (msg->text);
256       g_mem_chunk_free (class->messages_mem_chunk, msg);
257       g_slist_free_1 (list);
258     }
259
260   msg = statusbar->messages ? statusbar->messages->data : NULL;
261
262   gtk_signal_emit (GTK_OBJECT (statusbar),
263                    statusbar_signals[SIGNAL_TEXT_POPPED],
264                    (guint) (msg ? msg->context_id : 0),
265                    msg ? msg->text : NULL);
266 }
267
268 void
269 gtk_statusbar_remove (GtkStatusbar *statusbar,
270                       guint        context_id,
271                       guint        message_id)
272 {
273   GtkStatusbarMsg *msg;
274
275   g_return_if_fail (statusbar != NULL);
276   g_return_if_fail (GTK_IS_STATUSBAR (statusbar));
277   g_return_if_fail (context_id > 0);
278   g_return_if_fail (message_id > 0);
279
280   msg = statusbar->messages ? statusbar->messages->data : NULL;
281   if (msg)
282     {
283       GSList *list;
284
285       /* care about signal emission if the topmost item is removed */
286       if (msg->context_id == context_id &&
287           msg->message_id == message_id)
288         {
289           gtk_statusbar_pop (statusbar, context_id);
290           return;
291         }
292       
293       for (list = statusbar->messages; list; list = list->next)
294         {
295           msg = list->data;
296           
297           if (msg->context_id == context_id &&
298               msg->message_id == message_id)
299             {
300               GtkStatusbarClass *class;
301               
302               class = GTK_STATUSBAR_CLASS (GTK_OBJECT (statusbar)->klass);
303               statusbar->messages = g_slist_remove_link (statusbar->messages, list);
304               g_free (msg->text);
305               g_mem_chunk_free (class->messages_mem_chunk, msg);
306               g_slist_free_1 (list);
307               
308               break;
309             }
310         }
311     }
312 }
313
314 static void
315 gtk_statusbar_destroy (GtkObject *object)
316 {
317   GtkStatusbar *statusbar;
318   GtkStatusbarClass *class;
319   GSList *list;
320
321   g_return_if_fail (object != NULL);
322   g_return_if_fail (GTK_IS_STATUSBAR (object));
323
324   statusbar = GTK_STATUSBAR (object);
325   class = GTK_STATUSBAR_CLASS (GTK_OBJECT (statusbar)->klass);
326
327   for (list = statusbar->messages; list; list = list->next)
328     {
329       GtkStatusbarMsg *msg;
330
331       msg = list->data;
332       g_free (msg->text);
333       g_mem_chunk_free (class->messages_mem_chunk, msg);
334     }
335   g_slist_free (statusbar->messages);
336   statusbar->messages = NULL;
337
338   GTK_OBJECT_CLASS (parent_class)->destroy (object);
339 }
340
341 static void
342 gtk_statusbar_finalize (GtkObject *object)
343 {
344   GtkStatusbar *statusbar;
345   GSList *list;
346
347   g_return_if_fail (object != NULL);
348   g_return_if_fail (GTK_IS_STATUSBAR (object));
349
350   statusbar = GTK_STATUSBAR (object);
351
352   for (list = statusbar->keys; list; list = list->next)
353     g_free (list->data);
354   g_slist_free (statusbar->messages);
355   statusbar->keys = NULL;
356
357   GTK_OBJECT_CLASS (parent_class)->finalize (object);
358 }