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 Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 static void gtk_frame_class_init (GtkFrameClass *klass);
23 static void gtk_frame_init (GtkFrame *frame);
24 static void gtk_frame_destroy (GtkObject *object);
25 static void gtk_frame_paint (GtkWidget *widget,
27 static void gtk_frame_draw (GtkWidget *widget,
29 static gint gtk_frame_expose (GtkWidget *widget,
30 GdkEventExpose *event);
31 static void gtk_frame_size_request (GtkWidget *widget,
32 GtkRequisition *requisition);
33 static void gtk_frame_size_allocate (GtkWidget *widget,
34 GtkAllocation *allocation);
37 static GtkBinClass *parent_class = NULL;
43 static guint frame_type = 0;
47 GtkTypeInfo frame_info =
51 sizeof (GtkFrameClass),
52 (GtkClassInitFunc) gtk_frame_class_init,
53 (GtkObjectInitFunc) gtk_frame_init,
57 frame_type = gtk_type_unique (gtk_bin_get_type (), &frame_info);
64 gtk_frame_class_init (GtkFrameClass *class)
66 GtkObjectClass *object_class;
67 GtkWidgetClass *widget_class;
69 object_class = (GtkObjectClass*) class;
70 widget_class = (GtkWidgetClass*) class;
72 parent_class = gtk_type_class (gtk_bin_get_type ());
74 object_class->destroy = gtk_frame_destroy;
76 widget_class->draw = gtk_frame_draw;
77 widget_class->expose_event = gtk_frame_expose;
78 widget_class->size_request = gtk_frame_size_request;
79 widget_class->size_allocate = gtk_frame_size_allocate;
83 gtk_frame_init (GtkFrame *frame)
85 GTK_WIDGET_SET_FLAGS (frame, GTK_BASIC);
88 frame->shadow_type = GTK_SHADOW_ETCHED_IN;
89 frame->label_width = 0;
90 frame->label_height = 0;
91 frame->label_xalign = 0.0;
92 frame->label_yalign = 0.5;
96 gtk_frame_new (const gchar *label)
100 frame = gtk_type_new (gtk_frame_get_type ());
102 gtk_frame_set_label (frame, label);
104 return GTK_WIDGET (frame);
108 gtk_frame_set_label (GtkFrame *frame,
111 g_return_if_fail (frame != NULL);
112 g_return_if_fail (GTK_IS_FRAME (frame));
114 if ((label && frame->label && (strcmp (frame->label, label) == 0)) ||
115 (!label && !frame->label))
119 g_free (frame->label);
124 frame->label = g_strdup (label);
125 frame->label_width = gdk_string_measure (GTK_WIDGET (frame)->style->font, frame->label) + 7;
126 frame->label_height = (GTK_WIDGET (frame)->style->font->ascent +
127 GTK_WIDGET (frame)->style->font->descent + 1);
131 frame->label_width = 0;
132 frame->label_height = 0;
135 if (GTK_WIDGET_DRAWABLE (frame))
139 /* clear the old label area
141 widget = GTK_WIDGET (frame);
142 gdk_window_clear_area (widget->window,
143 widget->allocation.x + GTK_CONTAINER (frame)->border_width,
144 widget->allocation.y + GTK_CONTAINER (frame)->border_width,
145 widget->allocation.width - GTK_CONTAINER (frame)->border_width,
146 widget->allocation.y + frame->label_height);
150 gtk_widget_queue_resize (GTK_WIDGET (frame));
154 gtk_frame_set_label_align (GtkFrame *frame,
158 g_return_if_fail (frame != NULL);
159 g_return_if_fail (GTK_IS_FRAME (frame));
161 xalign = CLAMP (xalign, 0.0, 1.0);
162 yalign = CLAMP (yalign, 0.0, 1.0);
164 if ((xalign != frame->label_xalign) || (yalign != frame->label_yalign))
166 frame->label_xalign = xalign;
167 frame->label_yalign = yalign;
169 if (GTK_WIDGET_DRAWABLE (frame))
173 /* clear the old label area
175 widget = GTK_WIDGET (frame);
176 gdk_window_clear_area (widget->window,
177 widget->allocation.x + GTK_CONTAINER (frame)->border_width,
178 widget->allocation.y + GTK_CONTAINER (frame)->border_width,
179 widget->allocation.width - GTK_CONTAINER (frame)->border_width,
180 widget->allocation.y + frame->label_height);
183 gtk_widget_queue_resize (GTK_WIDGET (frame));
188 gtk_frame_set_shadow_type (GtkFrame *frame,
191 g_return_if_fail (frame != NULL);
192 g_return_if_fail (GTK_IS_FRAME (frame));
194 if ((GtkShadowType) frame->shadow_type != type)
196 frame->shadow_type = type;
198 if (GTK_WIDGET_DRAWABLE (frame))
200 gdk_window_clear_area (GTK_WIDGET (frame)->window,
201 GTK_WIDGET (frame)->allocation.x,
202 GTK_WIDGET (frame)->allocation.y,
203 GTK_WIDGET (frame)->allocation.width,
204 GTK_WIDGET (frame)->allocation.height);
206 gtk_widget_queue_resize (GTK_WIDGET (frame));
212 gtk_frame_destroy (GtkObject *object)
216 g_return_if_fail (object != NULL);
217 g_return_if_fail (GTK_IS_FRAME (object));
219 frame = GTK_FRAME (object);
222 g_free (frame->label);
224 if (GTK_OBJECT_CLASS (parent_class)->destroy)
225 (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
229 gtk_frame_paint (GtkWidget *widget,
235 gint label_area_width;
238 g_return_if_fail (widget != NULL);
239 g_return_if_fail (GTK_IS_FRAME (widget));
240 g_return_if_fail (area != NULL);
242 if (GTK_WIDGET_DRAWABLE (widget))
244 frame = GTK_FRAME (widget);
246 state = widget->state;
247 if (!GTK_WIDGET_IS_SENSITIVE (widget))
248 state = GTK_STATE_INSENSITIVE;
250 height_extra = frame->label_height - widget->style->klass->xthickness;
251 height_extra = MAX (height_extra, 0);
253 x = GTK_CONTAINER (frame)->border_width;
254 y = GTK_CONTAINER (frame)->border_width;
256 gtk_draw_shadow (widget->style, widget->window,
257 GTK_STATE_NORMAL, frame->shadow_type,
258 widget->allocation.x + x,
259 widget->allocation.y + y + height_extra / 2,
260 widget->allocation.width - x * 2,
261 widget->allocation.height - y * 2 - height_extra / 2);
265 label_area_width = (widget->allocation.width -
266 GTK_CONTAINER (frame)->border_width * 2 -
267 widget->style->klass->xthickness * 2);
269 x = ((label_area_width - frame->label_width) * frame->label_xalign +
270 GTK_CONTAINER (frame)->border_width + widget->style->klass->xthickness);
271 y = (GTK_CONTAINER (frame)->border_width + widget->style->font->ascent);
273 gdk_window_clear_area (widget->window,
274 widget->allocation.x + x + 2,
275 widget->allocation.y + GTK_CONTAINER (frame)->border_width,
276 frame->label_width - 4,
277 frame->label_height);
278 gtk_draw_string (widget->style, widget->window, state,
279 widget->allocation.x + x + 3,
280 widget->allocation.y + y,
287 gtk_frame_draw (GtkWidget *widget,
291 GdkRectangle child_area;
293 g_return_if_fail (widget != NULL);
294 g_return_if_fail (GTK_IS_FRAME (widget));
295 g_return_if_fail (area != NULL);
297 if (GTK_WIDGET_DRAWABLE (widget))
299 bin = GTK_BIN (widget);
301 gtk_frame_paint (widget, area);
303 if (bin->child && gtk_widget_intersect (bin->child, area, &child_area))
304 gtk_widget_draw (bin->child, &child_area);
309 gtk_frame_expose (GtkWidget *widget,
310 GdkEventExpose *event)
313 GdkEventExpose child_event;
315 g_return_val_if_fail (widget != NULL, FALSE);
316 g_return_val_if_fail (GTK_IS_FRAME (widget), FALSE);
317 g_return_val_if_fail (event != NULL, FALSE);
319 if (GTK_WIDGET_DRAWABLE (widget))
321 bin = GTK_BIN (widget);
323 gtk_frame_paint (widget, &event->area);
325 child_event = *event;
327 GTK_WIDGET_NO_WINDOW (bin->child) &&
328 gtk_widget_intersect (bin->child, &event->area, &child_event.area))
329 gtk_widget_event (bin->child, (GdkEvent*) &child_event);
336 gtk_frame_size_request (GtkWidget *widget,
337 GtkRequisition *requisition)
343 g_return_if_fail (widget != NULL);
344 g_return_if_fail (GTK_IS_FRAME (widget));
345 g_return_if_fail (requisition != NULL);
347 frame = GTK_FRAME (widget);
348 bin = GTK_BIN (widget);
350 requisition->width = (GTK_CONTAINER (widget)->border_width +
351 GTK_WIDGET (widget)->style->klass->xthickness) * 2;
353 tmp_height = frame->label_height - GTK_WIDGET (widget)->style->klass->ythickness;
354 tmp_height = MAX (tmp_height, 0);
356 requisition->height = tmp_height + (GTK_CONTAINER (widget)->border_width +
357 GTK_WIDGET (widget)->style->klass->ythickness) * 2;
359 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
361 gtk_widget_size_request (bin->child, &bin->child->requisition);
363 requisition->width += MAX (bin->child->requisition.width, frame->label_width);
364 requisition->height += bin->child->requisition.height;
368 requisition->width += frame->label_width;
373 gtk_frame_size_allocate (GtkWidget *widget,
374 GtkAllocation *allocation)
378 GtkAllocation child_allocation;
380 g_return_if_fail (widget != NULL);
381 g_return_if_fail (GTK_IS_FRAME (widget));
382 g_return_if_fail (allocation != NULL);
384 frame = GTK_FRAME (widget);
385 bin = GTK_BIN (widget);
387 if (GTK_WIDGET_MAPPED (widget) &&
388 ((widget->allocation.x != allocation->x) ||
389 (widget->allocation.y != allocation->y) ||
390 (widget->allocation.width != allocation->width) ||
391 (widget->allocation.height != allocation->height)) &&
392 (widget->allocation.width != 0) &&
393 (widget->allocation.height != 0))
394 gdk_window_clear_area (widget->window,
395 widget->allocation.x,
396 widget->allocation.y,
397 widget->allocation.width,
398 widget->allocation.height);
400 widget->allocation = *allocation;
402 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
404 child_allocation.x = (GTK_CONTAINER (frame)->border_width +
405 GTK_WIDGET (frame)->style->klass->xthickness);
406 child_allocation.width = MAX(0, allocation->width - child_allocation.x * 2);
408 child_allocation.y = (GTK_CONTAINER (frame)->border_width +
409 MAX (frame->label_height, GTK_WIDGET (frame)->style->klass->ythickness));
410 child_allocation.height = MAX (0, (allocation->height - child_allocation.y -
411 GTK_CONTAINER (frame)->border_width -
412 GTK_WIDGET (frame)->style->klass->ythickness));
414 child_allocation.x += allocation->x;
415 child_allocation.y += allocation->y;
417 gtk_widget_size_allocate (bin->child, &child_allocation);