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.
30 static void gtk_frame_class_init (GtkFrameClass *klass);
31 static void gtk_frame_init (GtkFrame *frame);
32 static void gtk_frame_set_arg (GtkFrame *frame,
35 static void gtk_frame_get_arg (GtkFrame *frame,
38 static void gtk_frame_finalize (GtkObject *object);
39 static void gtk_frame_paint (GtkWidget *widget,
41 static void gtk_frame_draw (GtkWidget *widget,
43 static gint gtk_frame_expose (GtkWidget *widget,
44 GdkEventExpose *event);
45 static void gtk_frame_size_request (GtkWidget *widget,
46 GtkRequisition *requisition);
47 static void gtk_frame_size_allocate (GtkWidget *widget,
48 GtkAllocation *allocation);
49 static void gtk_frame_style_set (GtkWidget *widget,
50 GtkStyle *previous_style);
53 static GtkBinClass *parent_class = NULL;
59 static guint frame_type = 0;
63 GtkTypeInfo frame_info =
67 sizeof (GtkFrameClass),
68 (GtkClassInitFunc) gtk_frame_class_init,
69 (GtkObjectInitFunc) gtk_frame_init,
70 (GtkArgSetFunc) gtk_frame_set_arg,
71 (GtkArgGetFunc) gtk_frame_get_arg,
74 frame_type = gtk_type_unique (gtk_bin_get_type (), &frame_info);
81 gtk_frame_class_init (GtkFrameClass *class)
83 GtkObjectClass *object_class;
84 GtkWidgetClass *widget_class;
86 object_class = (GtkObjectClass*) class;
87 widget_class = (GtkWidgetClass*) class;
89 parent_class = gtk_type_class (gtk_bin_get_type ());
91 gtk_object_add_arg_type ("GtkFrame::label", GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_LABEL);
92 gtk_object_add_arg_type ("GtkFrame::label_xalign", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_LABEL_XALIGN);
93 gtk_object_add_arg_type ("GtkFrame::label_yalign", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_LABEL_YALIGN);
94 gtk_object_add_arg_type ("GtkFrame::shadow", GTK_TYPE_ENUM, GTK_ARG_READWRITE, ARG_SHADOW);
96 object_class->finalize = gtk_frame_finalize;
98 widget_class->draw = gtk_frame_draw;
99 widget_class->expose_event = gtk_frame_expose;
100 widget_class->size_request = gtk_frame_size_request;
101 widget_class->size_allocate = gtk_frame_size_allocate;
102 widget_class->style_set = gtk_frame_style_set;
106 gtk_frame_init (GtkFrame *frame)
108 GTK_WIDGET_SET_FLAGS (frame, GTK_BASIC);
111 frame->shadow_type = GTK_SHADOW_ETCHED_IN;
112 frame->label_width = 0;
113 frame->label_height = 0;
114 frame->label_xalign = 0.0;
115 frame->label_yalign = 0.5;
119 gtk_frame_set_arg (GtkFrame *frame,
126 gtk_frame_set_label (frame, GTK_VALUE_STRING (*arg));
128 case ARG_LABEL_XALIGN:
129 gtk_frame_set_label_align (frame, GTK_VALUE_DOUBLE (*arg), frame->label_yalign);
131 case ARG_LABEL_YALIGN:
132 gtk_frame_set_label_align (frame, frame->label_xalign, GTK_VALUE_DOUBLE (*arg));
135 gtk_frame_set_shadow_type (frame, GTK_VALUE_ENUM (*arg));
138 arg->type = GTK_TYPE_INVALID;
144 gtk_frame_get_arg (GtkFrame *frame,
151 GTK_VALUE_STRING (*arg) = g_strdup (frame->label);
153 case ARG_LABEL_XALIGN:
154 GTK_VALUE_DOUBLE (*arg) = frame->label_xalign;
156 case ARG_LABEL_YALIGN:
157 GTK_VALUE_DOUBLE (*arg) = frame->label_yalign;
160 GTK_VALUE_ENUM (*arg) = frame->shadow_type;
163 arg->type = GTK_TYPE_INVALID;
169 gtk_frame_new (const gchar *label)
173 frame = gtk_type_new (gtk_frame_get_type ());
175 gtk_frame_set_label (frame, label);
177 return GTK_WIDGET (frame);
181 gtk_frame_style_set (GtkWidget *widget,
182 GtkStyle *previous_style)
186 frame = GTK_FRAME (widget);
190 frame->label_width = gdk_string_measure (GTK_WIDGET (frame)->style->font, frame->label) + 7;
191 frame->label_height = (GTK_WIDGET (frame)->style->font->ascent +
192 GTK_WIDGET (frame)->style->font->descent + 1);
195 if (GTK_WIDGET_CLASS (parent_class)->style_set)
196 GTK_WIDGET_CLASS (parent_class)->style_set (widget, previous_style);
200 gtk_frame_set_label (GtkFrame *frame,
203 g_return_if_fail (frame != NULL);
204 g_return_if_fail (GTK_IS_FRAME (frame));
206 if ((label && frame->label && (strcmp (frame->label, label) == 0)) ||
207 (!label && !frame->label))
211 g_free (frame->label);
216 frame->label = g_strdup (label);
217 frame->label_width = gdk_string_measure (GTK_WIDGET (frame)->style->font, frame->label) + 7;
218 frame->label_height = (GTK_WIDGET (frame)->style->font->ascent +
219 GTK_WIDGET (frame)->style->font->descent + 1);
223 frame->label_width = 0;
224 frame->label_height = 0;
227 if (GTK_WIDGET_DRAWABLE (frame))
231 /* clear the old label area
233 widget = GTK_WIDGET (frame);
234 gdk_window_clear_area (widget->window,
235 widget->allocation.x + GTK_CONTAINER (frame)->border_width,
236 widget->allocation.y + GTK_CONTAINER (frame)->border_width,
237 widget->allocation.width - GTK_CONTAINER (frame)->border_width,
238 widget->allocation.y + frame->label_height);
242 gtk_widget_queue_resize (GTK_WIDGET (frame));
246 gtk_frame_set_label_align (GtkFrame *frame,
250 g_return_if_fail (frame != NULL);
251 g_return_if_fail (GTK_IS_FRAME (frame));
253 xalign = CLAMP (xalign, 0.0, 1.0);
254 yalign = CLAMP (yalign, 0.0, 1.0);
256 if ((xalign != frame->label_xalign) || (yalign != frame->label_yalign))
258 frame->label_xalign = xalign;
259 frame->label_yalign = yalign;
261 if (GTK_WIDGET_DRAWABLE (frame))
265 /* clear the old label area
267 widget = GTK_WIDGET (frame);
268 gdk_window_clear_area (widget->window,
269 widget->allocation.x + GTK_CONTAINER (frame)->border_width,
270 widget->allocation.y + GTK_CONTAINER (frame)->border_width,
271 widget->allocation.width - GTK_CONTAINER (frame)->border_width,
272 widget->allocation.y + frame->label_height);
275 gtk_widget_queue_resize (GTK_WIDGET (frame));
280 gtk_frame_set_shadow_type (GtkFrame *frame,
283 g_return_if_fail (frame != NULL);
284 g_return_if_fail (GTK_IS_FRAME (frame));
286 if ((GtkShadowType) frame->shadow_type != type)
288 frame->shadow_type = type;
290 if (GTK_WIDGET_DRAWABLE (frame))
292 gdk_window_clear_area (GTK_WIDGET (frame)->window,
293 GTK_WIDGET (frame)->allocation.x,
294 GTK_WIDGET (frame)->allocation.y,
295 GTK_WIDGET (frame)->allocation.width,
296 GTK_WIDGET (frame)->allocation.height);
298 gtk_widget_queue_resize (GTK_WIDGET (frame));
304 gtk_frame_finalize (GtkObject *object)
308 g_return_if_fail (object != NULL);
309 g_return_if_fail (GTK_IS_FRAME (object));
311 frame = GTK_FRAME (object);
314 g_free (frame->label);
316 (* GTK_OBJECT_CLASS (parent_class)->finalize) (object);
320 gtk_frame_paint (GtkWidget *widget,
325 gint label_area_width;
328 g_return_if_fail (widget != NULL);
329 g_return_if_fail (GTK_IS_FRAME (widget));
330 g_return_if_fail (area != NULL);
332 if (GTK_WIDGET_DRAWABLE (widget))
334 frame = GTK_FRAME (widget);
336 height_extra = frame->label_height - widget->style->klass->xthickness;
337 height_extra = MAX (height_extra, 0);
339 x = GTK_CONTAINER (frame)->border_width;
340 y = GTK_CONTAINER (frame)->border_width;
342 gtk_draw_shadow (widget->style, widget->window,
343 GTK_STATE_NORMAL, frame->shadow_type,
344 widget->allocation.x + x,
345 widget->allocation.y + y + height_extra / 2,
346 widget->allocation.width - x * 2,
347 widget->allocation.height - y * 2 - height_extra / 2);
351 label_area_width = (widget->allocation.width -
352 GTK_CONTAINER (frame)->border_width * 2 -
353 widget->style->klass->xthickness * 2);
355 x = ((label_area_width - frame->label_width) * frame->label_xalign +
356 GTK_CONTAINER (frame)->border_width + widget->style->klass->xthickness);
357 y = (GTK_CONTAINER (frame)->border_width + widget->style->font->ascent);
359 gdk_window_clear_area (widget->window,
360 widget->allocation.x + x + 2,
361 widget->allocation.y + GTK_CONTAINER (frame)->border_width,
362 frame->label_width - 4,
363 frame->label_height);
364 gtk_draw_string (widget->style, widget->window, GTK_WIDGET_STATE (widget),
365 widget->allocation.x + x + 3,
366 widget->allocation.y + y,
373 gtk_frame_draw (GtkWidget *widget,
377 GdkRectangle child_area;
379 g_return_if_fail (widget != NULL);
380 g_return_if_fail (GTK_IS_FRAME (widget));
381 g_return_if_fail (area != NULL);
383 if (GTK_WIDGET_DRAWABLE (widget))
385 bin = GTK_BIN (widget);
387 gtk_frame_paint (widget, area);
389 if (bin->child && gtk_widget_intersect (bin->child, area, &child_area))
390 gtk_widget_draw (bin->child, &child_area);
395 gtk_frame_expose (GtkWidget *widget,
396 GdkEventExpose *event)
399 GdkEventExpose child_event;
401 g_return_val_if_fail (widget != NULL, FALSE);
402 g_return_val_if_fail (GTK_IS_FRAME (widget), FALSE);
403 g_return_val_if_fail (event != NULL, FALSE);
405 if (GTK_WIDGET_DRAWABLE (widget))
407 bin = GTK_BIN (widget);
409 gtk_frame_paint (widget, &event->area);
411 child_event = *event;
413 GTK_WIDGET_NO_WINDOW (bin->child) &&
414 gtk_widget_intersect (bin->child, &event->area, &child_event.area))
415 gtk_widget_event (bin->child, (GdkEvent*) &child_event);
422 gtk_frame_size_request (GtkWidget *widget,
423 GtkRequisition *requisition)
429 g_return_if_fail (widget != NULL);
430 g_return_if_fail (GTK_IS_FRAME (widget));
431 g_return_if_fail (requisition != NULL);
433 frame = GTK_FRAME (widget);
434 bin = GTK_BIN (widget);
436 requisition->width = (GTK_CONTAINER (widget)->border_width +
437 GTK_WIDGET (widget)->style->klass->xthickness) * 2;
439 tmp_height = frame->label_height - GTK_WIDGET (widget)->style->klass->ythickness;
440 tmp_height = MAX (tmp_height, 0);
442 requisition->height = tmp_height + (GTK_CONTAINER (widget)->border_width +
443 GTK_WIDGET (widget)->style->klass->ythickness) * 2;
445 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
447 gtk_widget_size_request (bin->child, &bin->child->requisition);
449 requisition->width += MAX (bin->child->requisition.width, frame->label_width);
450 requisition->height += bin->child->requisition.height;
454 requisition->width += frame->label_width;
459 gtk_frame_size_allocate (GtkWidget *widget,
460 GtkAllocation *allocation)
464 GtkAllocation child_allocation;
466 g_return_if_fail (widget != NULL);
467 g_return_if_fail (GTK_IS_FRAME (widget));
468 g_return_if_fail (allocation != NULL);
470 frame = GTK_FRAME (widget);
471 bin = GTK_BIN (widget);
473 if (GTK_WIDGET_MAPPED (widget) &&
474 ((widget->allocation.x != allocation->x) ||
475 (widget->allocation.y != allocation->y) ||
476 (widget->allocation.width != allocation->width) ||
477 (widget->allocation.height != allocation->height)) &&
478 (widget->allocation.width != 0) &&
479 (widget->allocation.height != 0))
480 gdk_window_clear_area (widget->window,
481 widget->allocation.x,
482 widget->allocation.y,
483 widget->allocation.width,
484 widget->allocation.height);
486 widget->allocation = *allocation;
488 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
490 child_allocation.x = (GTK_CONTAINER (frame)->border_width +
491 GTK_WIDGET (frame)->style->klass->xthickness);
492 child_allocation.width = MAX(0, allocation->width - child_allocation.x * 2);
494 child_allocation.y = (GTK_CONTAINER (frame)->border_width +
495 MAX (frame->label_height, GTK_WIDGET (frame)->style->klass->ythickness));
496 child_allocation.height = MAX (1, (allocation->height - child_allocation.y -
497 GTK_CONTAINER (frame)->border_width -
498 GTK_WIDGET (frame)->style->klass->ythickness));
500 child_allocation.x += allocation->x;
501 child_allocation.y += allocation->y;
503 gtk_widget_size_allocate (bin->child, &child_allocation);