1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
29 static void gtk_label_class_init (GtkLabelClass *klass);
30 static void gtk_label_init (GtkLabel *label);
31 static void gtk_label_set_arg (GtkLabel *label,
34 static void gtk_label_get_arg (GtkLabel *label,
37 static void gtk_label_finalize (GtkObject *object);
38 static void gtk_label_size_request (GtkWidget *widget,
39 GtkRequisition *requisition);
40 static gint gtk_label_expose (GtkWidget *widget,
41 GdkEventExpose *event);
42 static void gtk_label_state_changed (GtkWidget *widget,
43 guint previous_state);
44 static void gtk_label_style_set (GtkWidget *widget,
45 GtkStyle *previous_style);
49 static GtkMiscClass *parent_class = NULL;
53 gtk_label_get_type (void)
55 static GtkType label_type = 0;
59 GtkTypeInfo label_info =
63 sizeof (GtkLabelClass),
64 (GtkClassInitFunc) gtk_label_class_init,
65 (GtkObjectInitFunc) gtk_label_init,
66 (GtkArgSetFunc) gtk_label_set_arg,
67 (GtkArgGetFunc) gtk_label_get_arg,
70 label_type = gtk_type_unique (gtk_misc_get_type (), &label_info);
71 gtk_type_set_chunk_alloc (label_type, 32);
78 gtk_label_class_init (GtkLabelClass *class)
80 GtkObjectClass *object_class;
81 GtkWidgetClass *widget_class;
83 object_class = (GtkObjectClass*) class;
84 widget_class = (GtkWidgetClass*) class;
86 parent_class = gtk_type_class (gtk_misc_get_type ());
88 gtk_object_add_arg_type ("GtkLabel::label", GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_LABEL);
89 gtk_object_add_arg_type ("GtkLabel::justify", GTK_TYPE_JUSTIFICATION, GTK_ARG_READWRITE, ARG_JUSTIFY);
91 object_class->finalize = gtk_label_finalize;
93 widget_class->size_request = gtk_label_size_request;
94 widget_class->expose_event = gtk_label_expose;
95 widget_class->style_set = gtk_label_style_set;
96 widget_class->state_changed = gtk_label_state_changed;
100 gtk_label_set_arg (GtkLabel *label,
107 gtk_label_set (label, GTK_VALUE_STRING (*arg));
110 gtk_label_set_justify (label, GTK_VALUE_ENUM (*arg));
118 gtk_label_get_arg (GtkLabel *label,
125 GTK_VALUE_STRING (*arg) = g_strdup (label->label);
128 GTK_VALUE_ENUM (*arg) = label->jtype;
131 arg->type = GTK_TYPE_INVALID;
137 gtk_label_init (GtkLabel *label)
139 GTK_WIDGET_SET_FLAGS (label, GTK_NO_WINDOW);
143 label->max_width = 0;
144 label->jtype = GTK_JUSTIFY_CENTER;
145 label->needs_clear = FALSE;
147 gtk_label_set (label, "");
151 gtk_label_new (const gchar *str)
155 g_return_val_if_fail (str != NULL, NULL);
157 label = gtk_type_new (gtk_label_get_type ());
159 gtk_label_set (label, str);
161 return GTK_WIDGET (label);
165 gtk_label_set (GtkLabel *label,
170 g_return_if_fail (label != NULL);
171 g_return_if_fail (GTK_IS_LABEL (label));
172 g_return_if_fail (str != NULL);
175 g_free (label->label);
176 label->label = g_strdup (str);
179 g_slist_free (label->row);
181 label->row = g_slist_append (label->row, label->label);
183 while ((p = strchr(p, '\n')))
184 label->row = g_slist_append (label->row, ++p);
186 if (GTK_WIDGET_VISIBLE (label))
188 if (GTK_WIDGET_MAPPED (label))
189 gdk_window_clear_area (GTK_WIDGET (label)->window,
190 GTK_WIDGET (label)->allocation.x,
191 GTK_WIDGET (label)->allocation.y,
192 GTK_WIDGET (label)->allocation.width,
193 GTK_WIDGET (label)->allocation.height);
195 gtk_widget_queue_resize (GTK_WIDGET (label));
200 gtk_label_set_justify (GtkLabel *label,
201 GtkJustification jtype)
203 g_return_if_fail (label != NULL);
204 g_return_if_fail (GTK_IS_LABEL (label));
206 if ((GtkJustification) label->jtype != jtype)
208 label->jtype = jtype;
210 if (GTK_WIDGET_VISIBLE (label))
212 if (GTK_WIDGET_MAPPED (label))
213 gdk_window_clear_area (GTK_WIDGET (label)->window,
214 GTK_WIDGET (label)->allocation.x,
215 GTK_WIDGET (label)->allocation.y,
216 GTK_WIDGET (label)->allocation.width,
217 GTK_WIDGET (label)->allocation.height);
219 gtk_widget_queue_resize (GTK_WIDGET (label));
225 gtk_label_get (GtkLabel *label,
228 g_return_if_fail (label != NULL);
229 g_return_if_fail (GTK_IS_LABEL (label));
230 g_return_if_fail (str != NULL);
237 gtk_label_finalize (GtkObject *object)
241 g_return_if_fail (object != NULL);
242 g_return_if_fail (GTK_IS_LABEL (object));
244 label = GTK_LABEL (object);
246 g_free (label->label);
247 g_slist_free (label->row);
249 (* GTK_OBJECT_CLASS (parent_class)->finalize) (object);
253 gtk_label_size_request (GtkWidget *widget,
254 GtkRequisition *requisition)
260 g_return_if_fail (widget != NULL);
261 g_return_if_fail (GTK_IS_LABEL (widget));
262 g_return_if_fail (requisition != NULL);
264 label = GTK_LABEL (widget);
272 gdk_text_width (GTK_WIDGET (label)->style->font,
274 (gchar*) row->next->data - (gchar*) row->data - 1));
276 width = MAX (width, gdk_string_width (GTK_WIDGET (label)->style->font, row->data));
280 label->max_width = width;
281 requisition->width = width + label->misc.xpad * 2;
282 requisition->height = ((GTK_WIDGET (label)->style->font->ascent +
283 GTK_WIDGET (label)->style->font->descent + 2) *
284 g_slist_length(label->row) +
285 label->misc.ypad * 2);
289 gtk_label_expose (GtkWidget *widget,
290 GdkEventExpose *event)
300 g_return_val_if_fail (widget != NULL, FALSE);
301 g_return_val_if_fail (GTK_IS_LABEL (widget), FALSE);
302 g_return_val_if_fail (event != NULL, FALSE);
304 if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget))
306 label = GTK_LABEL (widget);
307 misc = GTK_MISC (widget);
309 state = widget->state;
314 gdk_gc_set_clip_rectangle (widget->style->white_gc, &event->area);
315 gdk_gc_set_clip_rectangle (widget->style->fg_gc[state], &event->area);
317 /* We clear the whole allocation here so that if a partial
318 * expose is triggered we don't just clear part and mess up
319 * when the queued redraw comes along. (There will always
320 * be a complete queued redraw when the needs_clear flag
323 if (label->needs_clear)
325 gdk_window_clear_area (widget->window,
326 widget->allocation.x,
327 widget->allocation.y,
328 widget->allocation.width,
329 widget->allocation.height);
331 label->needs_clear = FALSE;
334 x = widget->allocation.x + misc->xpad +
335 (widget->allocation.width - (label->max_width + label->misc.xpad * 2))
336 * misc->xalign + 0.5;
338 y = (widget->allocation.y * (1.0 - misc->yalign) +
339 (widget->allocation.y + widget->allocation.height -
340 (widget->requisition.height - misc->ypad * 2)) *
341 misc->yalign + widget->style->font->ascent) + 1.5;
344 while (row && row->next)
346 len = (gchar*) row->next->data - (gchar*) row->data - 1;
349 if (label->jtype == GTK_JUSTIFY_CENTER)
350 offset = (label->max_width - gdk_text_width (widget->style->font, row->data, len)) / 2;
352 else if (label->jtype == GTK_JUSTIFY_RIGHT)
353 offset = (label->max_width - gdk_text_width (widget->style->font, row->data, len));
355 if (state == GTK_STATE_INSENSITIVE)
356 gdk_draw_text (widget->window, widget->style->font,
357 widget->style->white_gc,
358 offset + x + 1, y + 1, row->data, len);
360 gdk_draw_text (widget->window, widget->style->font,
361 widget->style->fg_gc[state],
362 offset + x, y, row->data, len);
364 y += widget->style->font->ascent + widget->style->font->descent + 2;
368 * COMMENT: we can avoid gdk_text_width() calls here storing in label->row
369 * the widths of the rows calculated in gtk_label_set.
370 * Once we have a wrapping interface we can support GTK_JUSTIFY_FILL.
374 if (label->jtype == GTK_JUSTIFY_CENTER)
375 offset = (label->max_width - gdk_string_width (widget->style->font, row->data)) / 2;
377 else if (label->jtype == GTK_JUSTIFY_RIGHT)
378 offset = (label->max_width - gdk_string_width (widget->style->font, row->data));
380 if (state == GTK_STATE_INSENSITIVE)
381 gdk_draw_string (widget->window, widget->style->font,
382 widget->style->white_gc,
383 offset + x + 1, y + 1, row->data);
385 gdk_draw_string (widget->window, widget->style->font,
386 widget->style->fg_gc[state],
387 offset + x, y, row->data);
389 gdk_gc_set_clip_mask (widget->style->white_gc, NULL);
390 gdk_gc_set_clip_mask (widget->style->fg_gc[state], NULL);
397 gtk_label_state_changed (GtkWidget *widget,
398 guint previous_state)
400 if (GTK_WIDGET_DRAWABLE (widget))
401 GTK_LABEL (widget)->needs_clear = TRUE;
405 gtk_label_style_set (GtkWidget *widget,
406 GtkStyle *previous_style)
408 if (GTK_WIDGET_DRAWABLE (widget))
409 GTK_LABEL (widget)->needs_clear = TRUE;