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

Revision 14482, 14.2 KB checked in by ghudson, 25 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.
RevLine 
[14481]1/* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
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.
8 *
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.
13 *
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.
18 */
19
20/*
21 * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
22 * file for a list of people on the GTK+ Team.  See the ChangeLog
23 * files for a list of changes.  These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
25 */
26
27#include <string.h>
28#include "gtkframe.h"
29
30enum {
31  ARG_0,
32  ARG_LABEL,
33  ARG_LABEL_XALIGN,
34  ARG_LABEL_YALIGN,
35  ARG_SHADOW
36};
37
38
39static void gtk_frame_class_init    (GtkFrameClass  *klass);
40static void gtk_frame_init          (GtkFrame       *frame);
41static void gtk_frame_set_arg       (GtkObject      *object,
42                                     GtkArg         *arg,
43                                     guint           arg_id);
44static void gtk_frame_get_arg       (GtkObject      *object,
45                                     GtkArg         *arg,
46                                     guint           arg_id);
47static void gtk_frame_finalize      (GtkObject      *object);
48static void gtk_frame_paint         (GtkWidget      *widget,
49                                     GdkRectangle   *area);
50static void gtk_frame_draw          (GtkWidget      *widget,
51                                     GdkRectangle   *area);
52static gint gtk_frame_expose        (GtkWidget      *widget,
53                                     GdkEventExpose *event);
54static void gtk_frame_size_request  (GtkWidget      *widget,
55                                     GtkRequisition *requisition);
56static void gtk_frame_size_allocate (GtkWidget      *widget,
57                                     GtkAllocation  *allocation);
58static void gtk_frame_style_set     (GtkWidget      *widget,
59                                     GtkStyle       *previous_style);
60
61
62static GtkBinClass *parent_class = NULL;
63
64
65GtkType
66gtk_frame_get_type (void)
67{
68  static GtkType frame_type = 0;
69
70  if (!frame_type)
71    {
72      static const GtkTypeInfo frame_info =
73      {
74        "GtkFrame",
75        sizeof (GtkFrame),
76        sizeof (GtkFrameClass),
77        (GtkClassInitFunc) gtk_frame_class_init,
78        (GtkObjectInitFunc) gtk_frame_init,
79        /* reserved_1 */ NULL,
80        /* reserved_2 */ NULL,
81        (GtkClassInitFunc) NULL,
82      };
83
84      frame_type = gtk_type_unique (gtk_bin_get_type (), &frame_info);
85    }
86
87  return frame_type;
88}
89
90static void
91gtk_frame_class_init (GtkFrameClass *class)
92{
93  GtkObjectClass *object_class;
94  GtkWidgetClass *widget_class;
95
96  object_class = (GtkObjectClass*) class;
97  widget_class = (GtkWidgetClass*) class;
98
99  parent_class = gtk_type_class (gtk_bin_get_type ());
100
101  gtk_object_add_arg_type ("GtkFrame::label", GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_LABEL);
102  gtk_object_add_arg_type ("GtkFrame::label_xalign", GTK_TYPE_FLOAT, GTK_ARG_READWRITE, ARG_LABEL_XALIGN);
103  gtk_object_add_arg_type ("GtkFrame::label_yalign", GTK_TYPE_FLOAT, GTK_ARG_READWRITE, ARG_LABEL_YALIGN);
104  gtk_object_add_arg_type ("GtkFrame::shadow", GTK_TYPE_SHADOW_TYPE, GTK_ARG_READWRITE, ARG_SHADOW);
105
106  object_class->set_arg = gtk_frame_set_arg;
107  object_class->get_arg = gtk_frame_get_arg;
108  object_class->finalize = gtk_frame_finalize;
109
110  widget_class->draw = gtk_frame_draw;
111  widget_class->expose_event = gtk_frame_expose;
112  widget_class->size_request = gtk_frame_size_request;
113  widget_class->size_allocate = gtk_frame_size_allocate;
114  widget_class->style_set = gtk_frame_style_set;
115}
116
117static void
118gtk_frame_init (GtkFrame *frame)
119{
120  frame->label = NULL;
121  frame->shadow_type = GTK_SHADOW_ETCHED_IN;
122  frame->label_width = 0;
123  frame->label_height = 0;
124  frame->label_xalign = 0.0;
125  frame->label_yalign = 0.5;
126}
127
128static void
129gtk_frame_set_arg (GtkObject      *object,
130                   GtkArg         *arg,
131                   guint           arg_id)
132{
133  GtkFrame *frame;
134
135  frame = GTK_FRAME (object);
136
137  switch (arg_id)
138    {
139    case ARG_LABEL:
140      gtk_frame_set_label (frame, GTK_VALUE_STRING (*arg));
141      break;
142    case ARG_LABEL_XALIGN:
143      gtk_frame_set_label_align (frame, GTK_VALUE_FLOAT (*arg), frame->label_yalign);
144      break;
145    case ARG_LABEL_YALIGN:
146      gtk_frame_set_label_align (frame, frame->label_xalign, GTK_VALUE_FLOAT (*arg));
147      break;
148    case ARG_SHADOW:
149      gtk_frame_set_shadow_type (frame, GTK_VALUE_ENUM (*arg));
150      break;
151    default:
152      break;
153    }
154}
155
156static void
157gtk_frame_get_arg (GtkObject      *object,
158                   GtkArg         *arg,
159                   guint           arg_id)
160{
161  GtkFrame *frame;
162
163  frame = GTK_FRAME (object);
164
165  switch (arg_id)
166    {
167    case ARG_LABEL:
168      GTK_VALUE_STRING (*arg) = g_strdup (frame->label);
169      break;
170    case ARG_LABEL_XALIGN:
171      GTK_VALUE_FLOAT (*arg) = frame->label_xalign;
172      break;
173    case ARG_LABEL_YALIGN:
174      GTK_VALUE_FLOAT (*arg) = frame->label_yalign;
175      break;
176    case ARG_SHADOW:
177      GTK_VALUE_ENUM (*arg) = frame->shadow_type;
178      break;
179    default:
180      arg->type = GTK_TYPE_INVALID;
181      break;
182    }
183}
184
185GtkWidget*
186gtk_frame_new (const gchar *label)
187{
188  GtkFrame *frame;
189
190  frame = gtk_type_new (gtk_frame_get_type ());
191
192  gtk_frame_set_label (frame, label);
193
194  return GTK_WIDGET (frame);
195}
196
197static void
198gtk_frame_style_set (GtkWidget      *widget,
199                     GtkStyle       *previous_style)
200{
201  GtkFrame *frame;
202
203  frame = GTK_FRAME (widget);
204
205  if (frame->label)
206    {
207      frame->label_width = gdk_string_measure (GTK_WIDGET (frame)->style->font, frame->label) + 7;
208      frame->label_height = (GTK_WIDGET (frame)->style->font->ascent +
209                             GTK_WIDGET (frame)->style->font->descent + 1);
210    }
211
212  if (GTK_WIDGET_CLASS (parent_class)->style_set)
213    GTK_WIDGET_CLASS (parent_class)->style_set (widget, previous_style);
214}
215
216void
217gtk_frame_set_label (GtkFrame *frame,
218                     const gchar *label)
219{
220  g_return_if_fail (frame != NULL);
221  g_return_if_fail (GTK_IS_FRAME (frame));
222
223  if ((label && frame->label && (strcmp (frame->label, label) == 0)) ||
224      (!label && !frame->label))
225    return;
226
227  if (frame->label)
228    g_free (frame->label);
229  frame->label = NULL;
230
231  if (label)
232    {
233      frame->label = g_strdup (label);
234      frame->label_width = gdk_string_measure (GTK_WIDGET (frame)->style->font, frame->label) + 7;
235      frame->label_height = (GTK_WIDGET (frame)->style->font->ascent +
236                             GTK_WIDGET (frame)->style->font->descent + 1);
237    }
238  else
239    {
240      frame->label_width = 0;
241      frame->label_height = 0;
242    }
243
244  if (GTK_WIDGET_DRAWABLE (frame))
245    {
246      GtkWidget *widget;
247
248      /* clear the old label area
249      */
250      widget = GTK_WIDGET (frame);
251      gtk_widget_queue_clear_area (widget,
252                                   widget->allocation.x + GTK_CONTAINER (frame)->border_width,
253                                   widget->allocation.y + GTK_CONTAINER (frame)->border_width,
254                                   widget->allocation.width - GTK_CONTAINER (frame)->border_width,
255                                   widget->allocation.y + frame->label_height);
256
257    }
258 
259  gtk_widget_queue_resize (GTK_WIDGET (frame));
260}
261
262void
263gtk_frame_set_label_align (GtkFrame *frame,
264                           gfloat    xalign,
265                           gfloat    yalign)
266{
267  g_return_if_fail (frame != NULL);
268  g_return_if_fail (GTK_IS_FRAME (frame));
269
270  xalign = CLAMP (xalign, 0.0, 1.0);
271  yalign = CLAMP (yalign, 0.0, 1.0);
272
273  if ((xalign != frame->label_xalign) || (yalign != frame->label_yalign))
274    {
275      frame->label_xalign = xalign;
276      frame->label_yalign = yalign;
277
278      if (GTK_WIDGET_DRAWABLE (frame))
279        {
280          GtkWidget *widget;
281
282          /* clear the old label area
283          */
284          widget = GTK_WIDGET (frame);
285          gtk_widget_queue_clear_area (widget,
286                                       widget->allocation.x + GTK_CONTAINER (frame)->border_width,
287                                       widget->allocation.y + GTK_CONTAINER (frame)->border_width,
288                                       widget->allocation.width - GTK_CONTAINER (frame)->border_width,
289                                       widget->allocation.y + frame->label_height);
290
291        }
292      gtk_widget_queue_resize (GTK_WIDGET (frame));
293    }
294}
295
296void
297gtk_frame_set_shadow_type (GtkFrame      *frame,
298                           GtkShadowType  type)
299{
300  g_return_if_fail (frame != NULL);
301  g_return_if_fail (GTK_IS_FRAME (frame));
302
303  if ((GtkShadowType) frame->shadow_type != type)
304    {
305      frame->shadow_type = type;
306
307      if (GTK_WIDGET_DRAWABLE (frame))
308        {
309          gtk_widget_queue_clear (GTK_WIDGET (frame));
310        }
311      gtk_widget_queue_resize (GTK_WIDGET (frame));
312    }
313}
314
315
316static void
317gtk_frame_finalize (GtkObject *object)
318{
319  GtkFrame *frame;
320
321  g_return_if_fail (object != NULL);
322  g_return_if_fail (GTK_IS_FRAME (object));
323
324  frame = GTK_FRAME (object);
325
326  if (frame->label)
327    g_free (frame->label);
328
329  (* GTK_OBJECT_CLASS (parent_class)->finalize) (object);
330}
331
332static void
333gtk_frame_paint (GtkWidget    *widget,
334                 GdkRectangle *area)
335{
336  GtkFrame *frame;
337  gint height_extra;
338  gint label_area_width;
339  gint x, y, x2, y2;
340
341  g_return_if_fail (widget != NULL);
342  g_return_if_fail (GTK_IS_FRAME (widget));
343  g_return_if_fail (area != NULL);
344
345  if (GTK_WIDGET_DRAWABLE (widget))
346    {
347      frame = GTK_FRAME (widget);
348
349      height_extra = frame->label_height - widget->style->klass->xthickness;
350      height_extra = MAX (height_extra, 0);
351
352      x = GTK_CONTAINER (frame)->border_width;
353      y = GTK_CONTAINER (frame)->border_width;
354
355      if (frame->label)
356        {
357           label_area_width = (widget->allocation.width -
358                               GTK_CONTAINER (frame)->border_width * 2 -
359                               widget->style->klass->xthickness * 2);
360           
361           x2 = ((label_area_width - frame->label_width) * frame->label_xalign +
362                GTK_CONTAINER (frame)->border_width + widget->style->klass->xthickness);
363           y2 = (GTK_CONTAINER (frame)->border_width + widget->style->font->ascent);
364
365           gtk_paint_shadow_gap (widget->style, widget->window,
366                                 GTK_STATE_NORMAL, frame->shadow_type,
367                                 area, widget, "frame",
368                                 widget->allocation.x + x,
369                                 widget->allocation.y + y + height_extra / 2,
370                                 widget->allocation.width - x * 2,
371                                 widget->allocation.height - y * 2 - height_extra / 2,
372                                 GTK_POS_TOP,
373                                 x2 + 2 - x, frame->label_width - 4);
374           
375           gtk_paint_string (widget->style, widget->window, GTK_WIDGET_STATE (widget),
376                             area, widget, "frame",
377                             widget->allocation.x + x2 + 3,
378                             widget->allocation.y + y2,
379                             frame->label);
380        }
381       else
382         gtk_paint_shadow (widget->style, widget->window,
383                           GTK_STATE_NORMAL, frame->shadow_type,
384                           area, widget, "frame",
385                           widget->allocation.x + x,
386                           widget->allocation.y + y + height_extra / 2,
387                           widget->allocation.width - x * 2,
388                           widget->allocation.height - y * 2 - height_extra / 2);
389    }
390}
391
392static void
393gtk_frame_draw (GtkWidget    *widget,
394                GdkRectangle *area)
395{
396  GtkBin *bin;
397  GdkRectangle child_area;
398
399  g_return_if_fail (widget != NULL);
400  g_return_if_fail (GTK_IS_FRAME (widget));
401  g_return_if_fail (area != NULL);
402
403  if (GTK_WIDGET_DRAWABLE (widget))
404    {
405      bin = GTK_BIN (widget);
406
407      gtk_frame_paint (widget, area);
408
409      if (bin->child && gtk_widget_intersect (bin->child, area, &child_area))
410        gtk_widget_draw (bin->child, &child_area);
411    }
412}
413
414static gint
415gtk_frame_expose (GtkWidget      *widget,
416                  GdkEventExpose *event)
417{
418  GtkBin *bin;
419  GdkEventExpose child_event;
420
421  g_return_val_if_fail (widget != NULL, FALSE);
422  g_return_val_if_fail (GTK_IS_FRAME (widget), FALSE);
423  g_return_val_if_fail (event != NULL, FALSE);
424
425  if (GTK_WIDGET_DRAWABLE (widget))
426    {
427      bin = GTK_BIN (widget);
428
429      gtk_frame_paint (widget, &event->area);
430
431      child_event = *event;
432      if (bin->child &&
433          GTK_WIDGET_NO_WINDOW (bin->child) &&
434          gtk_widget_intersect (bin->child, &event->area, &child_event.area))
435        gtk_widget_event (bin->child, (GdkEvent*) &child_event);
436    }
437
438  return FALSE;
439}
440
441static void
442gtk_frame_size_request (GtkWidget      *widget,
443                        GtkRequisition *requisition)
444{
445  GtkFrame *frame;
446  GtkBin *bin;
447  gint tmp_height;
448
449  g_return_if_fail (widget != NULL);
450  g_return_if_fail (GTK_IS_FRAME (widget));
451  g_return_if_fail (requisition != NULL);
452
453  frame = GTK_FRAME (widget);
454  bin = GTK_BIN (widget);
455
456  requisition->width = (GTK_CONTAINER (widget)->border_width +
457                        GTK_WIDGET (widget)->style->klass->xthickness) * 2;
458
459  tmp_height = frame->label_height - GTK_WIDGET (widget)->style->klass->ythickness;
460  tmp_height = MAX (tmp_height, 0);
461
462  requisition->height = tmp_height + (GTK_CONTAINER (widget)->border_width +
463                                      GTK_WIDGET (widget)->style->klass->ythickness) * 2;
464
465  if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
466    {
467      GtkRequisition child_requisition;
468     
469      gtk_widget_size_request (bin->child, &child_requisition);
470
471      requisition->width += MAX (child_requisition.width, frame->label_width);
472      requisition->height += child_requisition.height;
473    }
474  else
475    {
476      requisition->width += frame->label_width;
477    }
478}
479
480static void
481gtk_frame_size_allocate (GtkWidget     *widget,
482                         GtkAllocation *allocation)
483{
484  GtkFrame *frame;
485  GtkBin *bin;
486  GtkAllocation child_allocation;
487
488  g_return_if_fail (widget != NULL);
489  g_return_if_fail (GTK_IS_FRAME (widget));
490  g_return_if_fail (allocation != NULL);
491
492  frame = GTK_FRAME (widget);
493  bin = GTK_BIN (widget);
494
495  if (GTK_WIDGET_MAPPED (widget) &&
496      ((widget->allocation.x != allocation->x) ||
497       (widget->allocation.y != allocation->y) ||
498       (widget->allocation.width != allocation->width) ||
499       (widget->allocation.height != allocation->height)) &&
500      (widget->allocation.width != 0) &&
501      (widget->allocation.height != 0))
502     gtk_widget_queue_clear (widget);
503
504  widget->allocation = *allocation;
505
506  if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
507    {
508      child_allocation.x = (GTK_CONTAINER (frame)->border_width +
509                            GTK_WIDGET (frame)->style->klass->xthickness);
510      child_allocation.width = MAX(1, (gint)allocation->width - child_allocation.x * 2);
511
512      child_allocation.y = (GTK_CONTAINER (frame)->border_width +
513                            MAX (frame->label_height, GTK_WIDGET (frame)->style->klass->ythickness));
514      child_allocation.height = MAX (1, ((gint)allocation->height - child_allocation.y -
515                                         (gint)GTK_CONTAINER (frame)->border_width -
516                                         (gint)GTK_WIDGET (frame)->style->klass->ythickness));
517
518      child_allocation.x += allocation->x;
519      child_allocation.y += allocation->y;
520
521      gtk_widget_size_allocate (bin->child, &child_allocation);
522    }
523}
Note: See TracBrowser for help on using the repository browser.