source: trunk/third/gtk/gtk/gtkstatusbar.c @ 14482

Revision 14482, 9.6 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r14481, which included commits to RCS files with non-trunk default branches.
Line 
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
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 */
20
21/*
22 * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
23 * file for a list of people on the GTK+ Team.  See the ChangeLog
24 * files for a list of changes.  These files are distributed with
25 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
26 */
27
28#include "gtkframe.h"
29#include "gtklabel.h"
30#include "gtksignal.h"
31#include "gtkstatusbar.h"
32
33
34enum
35{
36  SIGNAL_TEXT_PUSHED,
37  SIGNAL_TEXT_POPPED,
38  SIGNAL_LAST
39};
40
41static void gtk_statusbar_class_init               (GtkStatusbarClass *class);
42static void gtk_statusbar_init                     (GtkStatusbar      *statusbar);
43static void gtk_statusbar_destroy                  (GtkObject         *object);
44static void gtk_statusbar_finalize                 (GtkObject         *object);
45static void gtk_statusbar_update                   (GtkStatusbar      *statusbar,
46                                                    guint              context_id,
47                                                    const gchar       *text);
48     
49static GtkContainerClass *parent_class;
50static guint              statusbar_signals[SIGNAL_LAST] = { 0 };
51
52guint     
53gtk_statusbar_get_type (void)
54{
55  static guint statusbar_type = 0;
56
57  if (!statusbar_type)
58    {
59      static const GtkTypeInfo statusbar_info =
60      {
61        "GtkStatusbar",
62        sizeof (GtkStatusbar),
63        sizeof (GtkStatusbarClass),
64        (GtkClassInitFunc) gtk_statusbar_class_init,
65        (GtkObjectInitFunc) gtk_statusbar_init,
66        /* reserved_1 */ NULL,
67        /* reserved_2 */ NULL,
68        (GtkClassInitFunc) NULL,
69      };
70
71      statusbar_type = gtk_type_unique (gtk_hbox_get_type (), &statusbar_info);
72    }
73
74  return statusbar_type;
75}
76
77static void
78gtk_statusbar_class_init (GtkStatusbarClass *class)
79{
80  GtkObjectClass *object_class;
81  GtkWidgetClass *widget_class;
82  GtkContainerClass *container_class;
83
84  object_class = (GtkObjectClass *) class;
85  widget_class = (GtkWidgetClass *) class;
86  container_class = (GtkContainerClass *) class;
87
88  parent_class = gtk_type_class (gtk_hbox_get_type ());
89
90  statusbar_signals[SIGNAL_TEXT_PUSHED] =
91    gtk_signal_new ("text_pushed",
92                    GTK_RUN_LAST,
93                    object_class->type,
94                    GTK_SIGNAL_OFFSET (GtkStatusbarClass, text_pushed),
95                    gtk_marshal_NONE__UINT_STRING,
96                    GTK_TYPE_NONE, 2,
97                    GTK_TYPE_UINT,
98                    GTK_TYPE_STRING);
99  statusbar_signals[SIGNAL_TEXT_POPPED] =
100    gtk_signal_new ("text_popped",
101                    GTK_RUN_LAST,
102                    object_class->type,
103                    GTK_SIGNAL_OFFSET (GtkStatusbarClass, text_popped),
104                    gtk_marshal_NONE__UINT_STRING,
105                    GTK_TYPE_NONE, 2,
106                    GTK_TYPE_UINT,
107                    GTK_TYPE_STRING);
108  gtk_object_class_add_signals (object_class, statusbar_signals, SIGNAL_LAST);
109 
110  object_class->destroy = gtk_statusbar_destroy;
111  object_class->finalize = gtk_statusbar_finalize;
112
113  class->messages_mem_chunk = g_mem_chunk_new ("GtkStatusBar messages mem chunk",
114                                               sizeof (GtkStatusbarMsg),
115                                               sizeof (GtkStatusbarMsg) * 64,
116                                               G_ALLOC_AND_FREE);
117
118  class->text_pushed = gtk_statusbar_update;
119  class->text_popped = gtk_statusbar_update;
120}
121
122static void
123gtk_statusbar_init (GtkStatusbar *statusbar)
124{
125  GtkBox *box;
126
127  box = GTK_BOX (statusbar);
128
129  box->spacing = 2;
130  box->homogeneous = FALSE;
131
132  statusbar->frame = gtk_frame_new (NULL);
133  gtk_frame_set_shadow_type (GTK_FRAME (statusbar->frame), GTK_SHADOW_IN);
134  gtk_box_pack_start (box, statusbar->frame, TRUE, TRUE, 0);
135  gtk_widget_show (statusbar->frame);
136
137  statusbar->label = gtk_label_new ("");
138  gtk_misc_set_alignment (GTK_MISC (statusbar->label), 0.0, 0.0);
139  gtk_container_add (GTK_CONTAINER (statusbar->frame), statusbar->label);
140  gtk_widget_show (statusbar->label);
141
142  statusbar->seq_context_id = 1;
143  statusbar->seq_message_id = 1;
144  statusbar->messages = NULL;
145  statusbar->keys = NULL;
146}
147
148GtkWidget*
149gtk_statusbar_new (void)
150{
151  return gtk_type_new (gtk_statusbar_get_type ());
152}
153
154static void
155gtk_statusbar_update (GtkStatusbar *statusbar,
156                      guint         context_id,
157                      const gchar  *text)
158{
159  g_return_if_fail (statusbar != NULL);
160  g_return_if_fail (GTK_IS_STATUSBAR (statusbar));
161
162  if (!text)
163    text = "";
164
165  gtk_label_set_text (GTK_LABEL (statusbar->label), text);
166}
167
168guint
169gtk_statusbar_get_context_id (GtkStatusbar *statusbar,
170                              const gchar  *context_description)
171{
172  gchar *string;
173  guint *id;
174 
175  g_return_val_if_fail (statusbar != NULL, 0);
176  g_return_val_if_fail (GTK_IS_STATUSBAR (statusbar), 0);
177  g_return_val_if_fail (context_description != NULL, 0);
178
179  /* we need to preserve namespaces on object datas */
180  string = g_strconcat ("gtk-status-bar-context:", context_description, NULL);
181
182  id = gtk_object_get_data (GTK_OBJECT (statusbar), string);
183  if (!id)
184    {
185      id = g_new (guint, 1);
186      *id = statusbar->seq_context_id++;
187      gtk_object_set_data_full (GTK_OBJECT (statusbar), string, id, (GtkDestroyNotify) g_free);
188      statusbar->keys = g_slist_prepend (statusbar->keys, string);
189    }
190  else
191    g_free (string);
192
193  return *id;
194}
195
196guint
197gtk_statusbar_push (GtkStatusbar *statusbar,
198                    guint         context_id,
199                    const gchar  *text)
200{
201  GtkStatusbarMsg *msg;
202  GtkStatusbarClass *class;
203
204  g_return_val_if_fail (statusbar != NULL, 0);
205  g_return_val_if_fail (GTK_IS_STATUSBAR (statusbar), 0);
206  g_return_val_if_fail (text != NULL, 0);
207  g_return_val_if_fail (context_id > 0, 0);
208
209  class = GTK_STATUSBAR_CLASS (GTK_OBJECT (statusbar)->klass);
210  msg = g_chunk_new (GtkStatusbarMsg, class->messages_mem_chunk);
211  msg->text = g_strdup (text);
212  msg->context_id = context_id;
213  msg->message_id = statusbar->seq_message_id++;
214
215  statusbar->messages = g_slist_prepend (statusbar->messages, msg);
216
217  gtk_signal_emit (GTK_OBJECT (statusbar),
218                   statusbar_signals[SIGNAL_TEXT_PUSHED],
219                   msg->context_id,
220                   msg->text);
221
222  return msg->message_id;
223}
224
225void
226gtk_statusbar_pop (GtkStatusbar *statusbar,
227                   guint         context_id)
228{
229  GtkStatusbarMsg *msg;
230
231  g_return_if_fail (statusbar != NULL);
232  g_return_if_fail (GTK_IS_STATUSBAR (statusbar));
233  g_return_if_fail (context_id > 0);
234
235  if (statusbar->messages)
236    {
237      GSList *list;
238
239      for (list = statusbar->messages; list; list = list->next)
240        {
241          msg = list->data;
242
243          if (msg->context_id == context_id)
244            {
245              GtkStatusbarClass *class;
246
247              class = GTK_STATUSBAR_CLASS (GTK_OBJECT (statusbar)->klass);
248
249              statusbar->messages = g_slist_remove_link (statusbar->messages,
250                                                         list);
251              g_free (msg->text);
252              g_mem_chunk_free (class->messages_mem_chunk, msg);
253              g_slist_free_1 (list);
254              break;
255            }
256        }
257    }
258
259  msg = statusbar->messages ? statusbar->messages->data : NULL;
260
261  gtk_signal_emit (GTK_OBJECT (statusbar),
262                   statusbar_signals[SIGNAL_TEXT_POPPED],
263                   (guint) (msg ? msg->context_id : 0),
264                   msg ? msg->text : NULL);
265}
266
267void
268gtk_statusbar_remove (GtkStatusbar *statusbar,
269                      guint        context_id,
270                      guint        message_id)
271{
272  GtkStatusbarMsg *msg;
273
274  g_return_if_fail (statusbar != NULL);
275  g_return_if_fail (GTK_IS_STATUSBAR (statusbar));
276  g_return_if_fail (context_id > 0);
277  g_return_if_fail (message_id > 0);
278
279  msg = statusbar->messages ? statusbar->messages->data : NULL;
280  if (msg)
281    {
282      GSList *list;
283
284      /* care about signal emission if the topmost item is removed */
285      if (msg->context_id == context_id &&
286          msg->message_id == message_id)
287        {
288          gtk_statusbar_pop (statusbar, context_id);
289          return;
290        }
291     
292      for (list = statusbar->messages; list; list = list->next)
293        {
294          msg = list->data;
295         
296          if (msg->context_id == context_id &&
297              msg->message_id == message_id)
298            {
299              GtkStatusbarClass *class;
300             
301              class = GTK_STATUSBAR_CLASS (GTK_OBJECT (statusbar)->klass);
302              statusbar->messages = g_slist_remove_link (statusbar->messages, list);
303              g_free (msg->text);
304              g_mem_chunk_free (class->messages_mem_chunk, msg);
305              g_slist_free_1 (list);
306             
307              break;
308            }
309        }
310    }
311}
312
313static void
314gtk_statusbar_destroy (GtkObject *object)
315{
316  GtkStatusbar *statusbar;
317  GtkStatusbarClass *class;
318  GSList *list;
319
320  g_return_if_fail (object != NULL);
321  g_return_if_fail (GTK_IS_STATUSBAR (object));
322
323  statusbar = GTK_STATUSBAR (object);
324  class = GTK_STATUSBAR_CLASS (GTK_OBJECT (statusbar)->klass);
325
326  for (list = statusbar->messages; list; list = list->next)
327    {
328      GtkStatusbarMsg *msg;
329
330      msg = list->data;
331      g_free (msg->text);
332      g_mem_chunk_free (class->messages_mem_chunk, msg);
333    }
334  g_slist_free (statusbar->messages);
335  statusbar->messages = NULL;
336
337  for (list = statusbar->keys; list; list = list->next)
338    g_free (list->data);
339  g_slist_free (statusbar->keys);
340  statusbar->keys = NULL;
341
342  GTK_OBJECT_CLASS (parent_class)->destroy (object);
343}
344
345static void
346gtk_statusbar_finalize (GtkObject *object)
347{
348  GtkStatusbar *statusbar;
349
350  g_return_if_fail (object != NULL);
351  g_return_if_fail (GTK_IS_STATUSBAR (object));
352
353  statusbar = GTK_STATUSBAR (object);
354
355  GTK_OBJECT_CLASS (parent_class)->finalize (object);
356}
Note: See TracBrowser for help on using the repository browser.