~ubuntu-branches/debian/jessie/gpaint/jessie

« back to all changes in this revision

Viewing changes to src/gtkscrollframe.c

  • Committer: Bazaar Package Importer
  • Author(s): Goedson Teixeira Paixao
  • Date: 2002-03-17 12:27:19 UTC
  • Revision ID: james.westby@ubuntu.com-20020317122719-a6mowwhvvtbmcxow
Tags: upstream-0.2.2
ImportĀ upstreamĀ versionĀ 0.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 <config.h>
 
28
#include <gtk/gtkhscrollbar.h>
 
29
#include <gtk/gtkvscrollbar.h>
 
30
#include <gtk/gtksignal.h>
 
31
#include <gtk/gtkviewport.h>
 
32
#include "gtkscrollframe.h"
 
33
 
 
34
 
 
35
/* scrolled window policy and size requisition handling:
 
36
 *
 
37
 * gtk size requisition works as follows:
 
38
 *   a widget upon size-request reports the width and height that it finds
 
39
 *   to be best suited to display its contents, including children.
 
40
 *   the width and/or height reported from a widget upon size requisition
 
41
 *   may be overidden by the user by specifying a width and/or height
 
42
 *   other than 0 through gtk_widget_set_usize().
 
43
 *
 
44
 * a scrolled window needs (for imlementing all three policy types) to
 
45
 * request its width and height based on two different rationales.
 
46
 * 1)   the user wants the scrolled window to just fit into the space
 
47
 *      that it gets allocated for a specifc dimension.
 
48
 * 1.1) this does not apply if the user specified a concrete value
 
49
 *      value for that specific dimension by either specifying usize for the
 
50
 *      scrolled window or for its child.
 
51
 * 2)   the user wants the scrolled window to take as much space up as
 
52
 *      is desired by the child for a specifc dimension (i.e. POLICY_NEVER).
 
53
 *
 
54
 * also, kinda obvious:
 
55
 * 3)   a user would certainly not have choosen a scrolled window as a container
 
56
 *      for the child, if the resulting allocation takes up more space than the
 
57
 *      child would have allocated without the scrolled window.
 
58
 *
 
59
 * conclusions:
 
60
 * A) from 1) follows: the scrolled window shouldn't request more space for a
 
61
 *    specifc dimension than is required at minimum.
 
62
 * B) from 1.1) follows: the requisition may be overidden by usize of the scrolled
 
63
 *    window (done automatically) or by usize of the child (needs to be checked).
 
64
 * C) from 2) follows: for POLICY_NEVER, the scrolled window simply reports the
 
65
 *    child's dimension.
 
66
 * D) from 3) follows: the scrolled window child's minimum width and minimum height
 
67
 *    under A) at least correspond to the space taken up by its scrollbars.
 
68
 */
 
69
 
 
70
/* Object argument IDs */
 
71
enum {
 
72
        ARG_0,
 
73
        ARG_HADJUSTMENT,
 
74
        ARG_VADJUSTMENT,
 
75
        ARG_HSCROLLBAR_POLICY,
 
76
        ARG_VSCROLLBAR_POLICY,
 
77
        ARG_FRAME_PLACEMENT,
 
78
        ARG_SHADOW_TYPE,
 
79
        ARG_SCROLLBAR_SPACING
 
80
};
 
81
 
 
82
/* Private part of the GtkScrollFrame structure */
 
83
typedef struct {
 
84
        /* Horizontal and vertical scrollbars */
 
85
        GtkWidget *hsb;
 
86
        GtkWidget *vsb;
 
87
 
 
88
        /* Space between scrollbars and frame */
 
89
        guint sb_spacing;
 
90
 
 
91
        /* Allocation for frame */
 
92
        guint frame_x;
 
93
        guint frame_y;
 
94
        guint frame_w;
 
95
        guint frame_h;
 
96
 
 
97
        /* Scrollbar policy */
 
98
        guint hsb_policy : 2;
 
99
        guint vsb_policy : 2;
 
100
 
 
101
        /* Whether scrollbars are visible */
 
102
        guint hsb_visible : 1;
 
103
        guint vsb_visible : 1;
 
104
 
 
105
        /* Placement of frame wrt scrollbars */
 
106
        guint frame_placement : 2;
 
107
 
 
108
        /* Shadow type for frame */
 
109
        guint shadow_type : 3;
 
110
} ScrollFramePrivate;
 
111
 
 
112
 
 
113
static void gtk_scroll_frame_class_init (GtkScrollFrameClass *class);
 
114
static void gtk_scroll_frame_init (GtkScrollFrame *sf);
 
115
static void gtk_scroll_frame_set_arg (GtkObject *object, GtkArg *arg, guint arg_id);
 
116
static void gtk_scroll_frame_get_arg (GtkObject *object, GtkArg *arg, guint arg_id);
 
117
static void gtk_scroll_frame_destroy (GtkObject *object);
 
118
static void gtk_scroll_frame_finalize (GtkObject *object);
 
119
 
 
120
static void gtk_scroll_frame_map (GtkWidget *widget);
 
121
static void gtk_scroll_frame_unmap (GtkWidget *widget);
 
122
static void gtk_scroll_frame_draw (GtkWidget *widget, GdkRectangle *area);
 
123
static void gtk_scroll_frame_size_request (GtkWidget *widget, GtkRequisition *requisition);
 
124
static void gtk_scroll_frame_size_allocate (GtkWidget *widget, GtkAllocation *allocation);
 
125
static gint gtk_scroll_frame_expose (GtkWidget *widget, GdkEventExpose *event);
 
126
static gint gtk_scroll_frame_button_press (GtkWidget *widget, GdkEventButton *event);
 
127
 
 
128
static void gtk_scroll_frame_add (GtkContainer *container, GtkWidget *widget);
 
129
static void gtk_scroll_frame_remove (GtkContainer *container, GtkWidget *widget);
 
130
static void gtk_scroll_frame_forall (GtkContainer *container, gboolean include_internals,
 
131
                                     GtkCallback callback, gpointer callback_data);
 
132
 
 
133
static GtkBinClass *parent_class;
 
134
 
 
135
 
 
136
/**
 
137
 * gtk_scroll_frame_get_type:
 
138
 * @void:
 
139
 *
 
140
 * Registers the #GtkScrollFrame class if necessary, and returns the type ID
 
141
 * associated to it.
 
142
 *
 
143
 * Return value: The type ID of the #GtkScrollFrame class.
 
144
 **/
 
145
GtkType
 
146
gtk_scroll_frame_get_type (void)
 
147
{
 
148
        static GtkType scroll_frame_type = 0;
 
149
 
 
150
        if (!scroll_frame_type) {
 
151
                static const GtkTypeInfo scroll_frame_info = {
 
152
                        "GtkScrollFrame",
 
153
                        sizeof (GtkScrollFrame),
 
154
                        sizeof (GtkScrollFrameClass),
 
155
                        (GtkClassInitFunc) gtk_scroll_frame_class_init,
 
156
                        (GtkObjectInitFunc) gtk_scroll_frame_init,
 
157
                        NULL, /* reserved_1 */
 
158
                        NULL, /* reserved_2 */
 
159
                        (GtkClassInitFunc) NULL
 
160
                };
 
161
 
 
162
                scroll_frame_type = gtk_type_unique (GTK_TYPE_BIN, &scroll_frame_info);
 
163
        }
 
164
 
 
165
        return scroll_frame_type;
 
166
}
 
167
 
 
168
/* Class initialization function for the scroll frame widget */
 
169
static void
 
170
gtk_scroll_frame_class_init (GtkScrollFrameClass *class)
 
171
{
 
172
        GtkObjectClass *object_class;
 
173
        GtkWidgetClass *widget_class;
 
174
        GtkContainerClass *container_class;
 
175
 
 
176
        object_class = (GtkObjectClass *) class;
 
177
        widget_class = (GtkWidgetClass *) class;
 
178
        container_class = (GtkContainerClass *) class;
 
179
 
 
180
        parent_class = gtk_type_class (GTK_TYPE_BIN);
 
181
 
 
182
        gtk_object_add_arg_type ("GtkScrollFrame::hadjustment",
 
183
                                 GTK_TYPE_ADJUSTMENT,
 
184
                                 GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT,
 
185
                                 ARG_HADJUSTMENT);
 
186
        gtk_object_add_arg_type ("GtkScrollFrame::vadjustment",
 
187
                                 GTK_TYPE_ADJUSTMENT,
 
188
                                 GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT,
 
189
                                 ARG_VADJUSTMENT);
 
190
        gtk_object_add_arg_type ("GtkScrollFrame::hscrollbar_policy",
 
191
                                 GTK_TYPE_POLICY_TYPE,
 
192
                                 GTK_ARG_READWRITE,
 
193
                                 ARG_HSCROLLBAR_POLICY);
 
194
        gtk_object_add_arg_type ("GtkScrollFrame::vscrollbar_policy",
 
195
                                 GTK_TYPE_POLICY_TYPE,
 
196
                                 GTK_ARG_READWRITE,
 
197
                                 ARG_VSCROLLBAR_POLICY);
 
198
        gtk_object_add_arg_type ("GtkScrollFrame::frame_placement",
 
199
                                 GTK_TYPE_CORNER_TYPE,
 
200
                                 GTK_ARG_READWRITE,
 
201
                                 ARG_FRAME_PLACEMENT);
 
202
        gtk_object_add_arg_type ("GtkScrollFrame::shadow_type",
 
203
                                 GTK_TYPE_SHADOW_TYPE,
 
204
                                 GTK_ARG_READWRITE,
 
205
                                 ARG_SHADOW_TYPE);
 
206
        gtk_object_add_arg_type ("GtkScrollFrame::scrollbar_spacing",
 
207
                                 GTK_TYPE_UINT,
 
208
                                 GTK_ARG_READWRITE,
 
209
                                 ARG_SCROLLBAR_SPACING);
 
210
 
 
211
        object_class->set_arg = gtk_scroll_frame_set_arg;
 
212
        object_class->get_arg = gtk_scroll_frame_get_arg;
 
213
        object_class->destroy = gtk_scroll_frame_destroy;
 
214
        object_class->finalize = gtk_scroll_frame_finalize;
 
215
 
 
216
        widget_class->map = gtk_scroll_frame_map;
 
217
        widget_class->unmap = gtk_scroll_frame_unmap;
 
218
        widget_class->draw = gtk_scroll_frame_draw;
 
219
        widget_class->size_request = gtk_scroll_frame_size_request;
 
220
        widget_class->size_allocate = gtk_scroll_frame_size_allocate;
 
221
        widget_class->expose_event = gtk_scroll_frame_expose;
 
222
        widget_class->button_press_event = gtk_scroll_frame_button_press;
 
223
        
 
224
        container_class->add = gtk_scroll_frame_add;
 
225
        container_class->remove = gtk_scroll_frame_remove;
 
226
        container_class->forall = gtk_scroll_frame_forall;
 
227
}
 
228
 
 
229
/* Object initialization function for the scroll frame widget */
 
230
static void
 
231
gtk_scroll_frame_init (GtkScrollFrame *sf)
 
232
{
 
233
        ScrollFramePrivate *priv;
 
234
 
 
235
        priv = g_new0 (ScrollFramePrivate, 1);
 
236
        sf->priv = priv;
 
237
 
 
238
        GTK_WIDGET_SET_FLAGS (sf, GTK_NO_WINDOW);
 
239
 
 
240
        gtk_container_set_resize_mode (GTK_CONTAINER (sf), GTK_RESIZE_QUEUE);
 
241
 
 
242
        priv->sb_spacing = 3;
 
243
        priv->hsb_policy = GTK_POLICY_ALWAYS;
 
244
        priv->vsb_policy = GTK_POLICY_ALWAYS;
 
245
        priv->frame_placement = GTK_CORNER_TOP_LEFT;
 
246
        priv->shadow_type = GTK_SHADOW_NONE;
 
247
}
 
248
 
 
249
/* Set_arg handler for the scroll frame widget */
 
250
static void
 
251
gtk_scroll_frame_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
 
252
{
 
253
        GtkScrollFrame *sf;
 
254
        ScrollFramePrivate *priv;
 
255
 
 
256
        sf = GTK_SCROLL_FRAME (object);
 
257
        priv = sf->priv;
 
258
 
 
259
        switch (arg_id) {
 
260
        case ARG_HADJUSTMENT:
 
261
                gtk_scroll_frame_set_hadjustment (sf, GTK_VALUE_POINTER (*arg));
 
262
                break;
 
263
 
 
264
        case ARG_VADJUSTMENT:
 
265
                gtk_scroll_frame_set_vadjustment (sf, GTK_VALUE_POINTER (*arg));
 
266
                break;
 
267
 
 
268
        case ARG_HSCROLLBAR_POLICY:
 
269
                gtk_scroll_frame_set_policy (sf, GTK_VALUE_ENUM (*arg), priv->vsb_policy);
 
270
                break;
 
271
 
 
272
        case ARG_VSCROLLBAR_POLICY:
 
273
                gtk_scroll_frame_set_policy (sf, priv->hsb_policy, GTK_VALUE_ENUM (*arg));
 
274
                break;
 
275
 
 
276
        case ARG_FRAME_PLACEMENT:
 
277
                gtk_scroll_frame_set_placement (sf, GTK_VALUE_ENUM (*arg));
 
278
                break;
 
279
 
 
280
        case ARG_SHADOW_TYPE:
 
281
                gtk_scroll_frame_set_shadow_type (sf, GTK_VALUE_ENUM (*arg));
 
282
                break;
 
283
 
 
284
        case ARG_SCROLLBAR_SPACING:
 
285
                gtk_scroll_frame_set_scrollbar_spacing (sf, GTK_VALUE_UINT (*arg));
 
286
                break;
 
287
 
 
288
        default:
 
289
                break;
 
290
        }
 
291
}
 
292
 
 
293
/* Get_arg handler for the scroll frame widget */
 
294
static void
 
295
gtk_scroll_frame_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
 
296
{
 
297
        GtkScrollFrame *sf;
 
298
        ScrollFramePrivate *priv;
 
299
 
 
300
        sf = GTK_SCROLL_FRAME (object);
 
301
        priv = sf->priv;
 
302
 
 
303
        switch (arg_id) {
 
304
        case ARG_HADJUSTMENT:
 
305
                GTK_VALUE_POINTER (*arg) = gtk_scroll_frame_get_hadjustment (sf);
 
306
                break;
 
307
 
 
308
        case ARG_VADJUSTMENT:
 
309
                GTK_VALUE_POINTER (*arg) = gtk_scroll_frame_get_vadjustment (sf);
 
310
                break;
 
311
 
 
312
        case ARG_HSCROLLBAR_POLICY:
 
313
                GTK_VALUE_ENUM (*arg) = priv->hsb_policy;
 
314
                break;
 
315
 
 
316
        case ARG_VSCROLLBAR_POLICY:
 
317
                GTK_VALUE_ENUM (*arg) = priv->vsb_policy;
 
318
                break;
 
319
 
 
320
        case ARG_FRAME_PLACEMENT:
 
321
                GTK_VALUE_ENUM (*arg) = priv->frame_placement;
 
322
                break;
 
323
 
 
324
        case ARG_SHADOW_TYPE:
 
325
                GTK_VALUE_ENUM (*arg) = priv->shadow_type;
 
326
                break;
 
327
 
 
328
        case ARG_SCROLLBAR_SPACING:
 
329
                GTK_VALUE_UINT (*arg) = priv->sb_spacing;
 
330
                break;
 
331
 
 
332
        default:
 
333
                arg->type = GTK_TYPE_INVALID;
 
334
                break;
 
335
        }
 
336
}
 
337
 
 
338
/* Destroy handler for the scroll frame widget */
 
339
static void
 
340
gtk_scroll_frame_destroy (GtkObject *object)
 
341
{
 
342
        GtkScrollFrame *sf;
 
343
        ScrollFramePrivate *priv;
 
344
 
 
345
        g_return_if_fail (object != NULL);
 
346
        g_return_if_fail (GTK_IS_SCROLL_FRAME (object));
 
347
 
 
348
        sf = GTK_SCROLL_FRAME (object);
 
349
        priv = sf->priv;
 
350
 
 
351
        gtk_widget_unparent (priv->hsb);
 
352
        gtk_widget_unparent (priv->vsb);
 
353
        gtk_widget_destroy (priv->hsb);
 
354
        gtk_widget_destroy (priv->vsb);
 
355
 
 
356
        if (GTK_OBJECT_CLASS (parent_class)->destroy)
 
357
                (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
 
358
}
 
359
 
 
360
/* Finalize handler for the scroll frame widget */
 
361
static void
 
362
gtk_scroll_frame_finalize (GtkObject *object)
 
363
{
 
364
        GtkScrollFrame *sf;
 
365
        ScrollFramePrivate *priv;
 
366
 
 
367
        sf = GTK_SCROLL_FRAME (object);
 
368
        priv = sf->priv;
 
369
 
 
370
        gtk_widget_unref (priv->hsb);
 
371
        gtk_widget_unref (priv->vsb);
 
372
 
 
373
        g_free (priv);
 
374
 
 
375
        if (GTK_OBJECT_CLASS (parent_class)->finalize)
 
376
                (* GTK_OBJECT_CLASS (parent_class)->finalize) (object);
 
377
}
 
378
 
 
379
/* Map handler for the scroll frame widget */
 
380
static void
 
381
gtk_scroll_frame_map (GtkWidget *widget)
 
382
{
 
383
        GtkScrollFrame *sf;
 
384
        ScrollFramePrivate *priv;
 
385
 
 
386
        g_return_if_fail (widget != NULL);
 
387
        g_return_if_fail (GTK_IS_SCROLL_FRAME (widget));
 
388
 
 
389
        sf = GTK_SCROLL_FRAME (widget);
 
390
        priv = sf->priv;
 
391
 
 
392
        /* chain parent class handler to map self and child */
 
393
        if (GTK_WIDGET_CLASS (parent_class)->map)
 
394
                (* GTK_WIDGET_CLASS (parent_class)->map) (widget);
 
395
 
 
396
        if (GTK_WIDGET_VISIBLE (priv->hsb) && !GTK_WIDGET_MAPPED (priv->hsb))
 
397
                gtk_widget_map (priv->hsb);
 
398
 
 
399
        if (GTK_WIDGET_VISIBLE (priv->vsb) && !GTK_WIDGET_MAPPED (priv->vsb))
 
400
                gtk_widget_map (priv->vsb);
 
401
}
 
402
 
 
403
/* Unmap handler for the scroll frame widget */
 
404
static void
 
405
gtk_scroll_frame_unmap (GtkWidget *widget)
 
406
{
 
407
        GtkScrollFrame *sf;
 
408
        ScrollFramePrivate *priv;
 
409
 
 
410
        g_return_if_fail (widget != NULL);
 
411
        g_return_if_fail (GTK_IS_SCROLL_FRAME (widget));
 
412
 
 
413
        sf = GTK_SCROLL_FRAME (widget);
 
414
        priv = sf->priv;
 
415
 
 
416
        /* chain parent class handler to unmap self and child */
 
417
        if (GTK_WIDGET_CLASS (parent_class)->unmap)
 
418
                (* GTK_WIDGET_CLASS (parent_class)->unmap) (widget);
 
419
 
 
420
        if (GTK_WIDGET_MAPPED (priv->hsb))
 
421
                gtk_widget_unmap (priv->hsb);
 
422
 
 
423
        if (GTK_WIDGET_MAPPED (priv->vsb))
 
424
                gtk_widget_unmap (priv->vsb);
 
425
}
 
426
 
 
427
/* Draws the shadow of a scroll frame widget */
 
428
static void
 
429
draw_shadow (GtkScrollFrame *sf, GdkRectangle *area)
 
430
{
 
431
        ScrollFramePrivate *priv;
 
432
 
 
433
        g_assert (area != NULL);
 
434
 
 
435
        priv = sf->priv;
 
436
 
 
437
        gtk_paint_shadow (GTK_WIDGET (sf)->style,
 
438
                          GTK_WIDGET (sf)->window,
 
439
                          GTK_STATE_NORMAL, priv->shadow_type,
 
440
                          area, GTK_WIDGET (sf),
 
441
                          "scroll_frame",
 
442
                          priv->frame_x, priv->frame_y,
 
443
                          priv->frame_w, priv->frame_h);
 
444
}
 
445
 
 
446
/* Draw handler for the scroll frame widget */
 
447
static void
 
448
gtk_scroll_frame_draw (GtkWidget *widget, GdkRectangle *area)
 
449
{
 
450
        GtkScrollFrame *sf;
 
451
        ScrollFramePrivate *priv;
 
452
        GtkBin *bin;
 
453
        GdkRectangle child_area;
 
454
 
 
455
        g_return_if_fail (widget != NULL);
 
456
        g_return_if_fail (GTK_IS_SCROLL_FRAME (widget));
 
457
        g_return_if_fail (area != NULL);
 
458
 
 
459
        sf = GTK_SCROLL_FRAME (widget);
 
460
        priv = sf->priv;
 
461
        bin = GTK_BIN (widget);
 
462
 
 
463
        if (GTK_WIDGET_DRAWABLE (widget))
 
464
                draw_shadow (sf, area);
 
465
 
 
466
        if (bin->child && GTK_WIDGET_VISIBLE (bin->child)
 
467
            && gtk_widget_intersect (bin->child, area, &child_area))
 
468
                gtk_widget_draw (bin->child, &child_area);
 
469
 
 
470
        if (GTK_WIDGET_VISIBLE (priv->hsb)
 
471
            && gtk_widget_intersect (priv->hsb, area, &child_area))
 
472
                gtk_widget_draw (priv->hsb, &child_area);
 
473
 
 
474
        if (GTK_WIDGET_VISIBLE (priv->vsb)
 
475
            && gtk_widget_intersect (priv->vsb, area, &child_area))
 
476
                gtk_widget_draw (priv->vsb, &child_area);
 
477
}
 
478
 
 
479
/* Forall handler for the scroll frame widget */
 
480
static void
 
481
gtk_scroll_frame_forall (GtkContainer *container, gboolean include_internals,
 
482
                         GtkCallback callback, gpointer callback_data)
 
483
{
 
484
        GtkScrollFrame *sf;
 
485
        ScrollFramePrivate *priv;
 
486
 
 
487
        g_return_if_fail (container != NULL);
 
488
        g_return_if_fail (GTK_IS_SCROLL_FRAME (container));
 
489
        g_return_if_fail (callback != NULL);
 
490
 
 
491
        sf = GTK_SCROLL_FRAME (container);
 
492
        priv = sf->priv;
 
493
 
 
494
        if (GTK_CONTAINER_CLASS (parent_class)->forall)
 
495
                (* GTK_CONTAINER_CLASS (parent_class)->forall) (
 
496
                        container, include_internals,
 
497
                        callback, callback_data);
 
498
 
 
499
        if (include_internals) {
 
500
                if (priv->vsb)
 
501
                        (* callback) (priv->vsb, callback_data);
 
502
 
 
503
                if (priv->hsb)
 
504
                        (* callback) (priv->hsb, callback_data);
 
505
        }
 
506
}
 
507
 
 
508
/* Size_request handler for the scroll frame widget */
 
509
static void
 
510
gtk_scroll_frame_size_request (GtkWidget *widget, GtkRequisition *requisition)
 
511
{
 
512
        GtkScrollFrame *sf;
 
513
        ScrollFramePrivate *priv;
 
514
        GtkBin *bin;
 
515
        int extra_width;
 
516
        int extra_height;
 
517
        GtkRequisition hsb_requisition;
 
518
        GtkRequisition vsb_requisition;
 
519
        GtkRequisition child_requisition;
 
520
 
 
521
        g_return_if_fail (widget != NULL);
 
522
        g_return_if_fail (GTK_IS_SCROLL_FRAME (widget));
 
523
        g_return_if_fail (requisition != NULL);
 
524
 
 
525
        sf = GTK_SCROLL_FRAME (widget);
 
526
        priv = sf->priv;
 
527
        bin = GTK_BIN (widget);
 
528
 
 
529
        extra_width = 0;
 
530
        extra_height = 0;
 
531
 
 
532
        requisition->width = GTK_CONTAINER (widget)->border_width * 2;
 
533
        requisition->height = GTK_CONTAINER (widget)->border_width * 2;
 
534
 
 
535
        if (priv->shadow_type != GTK_SHADOW_NONE) {
 
536
                requisition->width += 2 * widget->style->klass->xthickness;
 
537
                requisition->height += 2 * widget->style->klass->ythickness;
 
538
        }
 
539
 
 
540
        gtk_widget_size_request (priv->hsb, &hsb_requisition);
 
541
        gtk_widget_size_request (priv->vsb, &vsb_requisition);
 
542
 
 
543
        if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) {
 
544
                static guint quark_aux_info;
 
545
 
 
546
                if (!quark_aux_info)
 
547
                        quark_aux_info = g_quark_from_static_string ("gtk-aux-info");
 
548
 
 
549
                gtk_widget_size_request (bin->child, &child_requisition);
 
550
 
 
551
                if (priv->hsb_policy == GTK_POLICY_NEVER)
 
552
                        requisition->width += child_requisition.width;
 
553
                else {
 
554
                        GtkWidgetAuxInfo *aux_info;
 
555
 
 
556
                        aux_info = gtk_object_get_data_by_id (GTK_OBJECT (bin->child),
 
557
                                                              quark_aux_info);
 
558
                        if (aux_info && aux_info->width > 0) {
 
559
                                requisition->width += aux_info->width;
 
560
                                extra_width = -1;
 
561
                        } else
 
562
                                requisition->width += vsb_requisition.width;
 
563
                }
 
564
 
 
565
                if (priv->vsb_policy == GTK_POLICY_NEVER)
 
566
                        requisition->height += child_requisition.height;
 
567
                else {
 
568
                        GtkWidgetAuxInfo *aux_info;
 
569
 
 
570
                        aux_info = gtk_object_get_data_by_id (GTK_OBJECT (bin->child),
 
571
                                                              quark_aux_info);
 
572
                        if (aux_info && aux_info->height > 0) {
 
573
                                requisition->height += aux_info->height;
 
574
                                extra_height = -1;
 
575
                        } else
 
576
                                requisition->height += hsb_requisition.height;
 
577
                }
 
578
        }
 
579
 
 
580
        if (priv->hsb_policy == GTK_POLICY_AUTOMATIC || GTK_WIDGET_VISIBLE (priv->hsb)) {
 
581
                requisition->width = MAX (requisition->width, hsb_requisition.width);
 
582
                if (!extra_height || GTK_WIDGET_VISIBLE (priv->hsb))
 
583
                        extra_height = priv->sb_spacing + hsb_requisition.height;
 
584
        }
 
585
 
 
586
        if (priv->vsb_policy == GTK_POLICY_AUTOMATIC || GTK_WIDGET_VISIBLE (priv->vsb)) {
 
587
                requisition->height = MAX (requisition->height, vsb_requisition.height);
 
588
                if (!extra_width || GTK_WIDGET_VISIBLE (priv->vsb))
 
589
                        extra_width = priv->sb_spacing + vsb_requisition.width;
 
590
        }
 
591
 
 
592
        requisition->width += MAX (0, extra_width);
 
593
        requisition->height += MAX (0, extra_height);
 
594
}
 
595
 
 
596
/* Computes the relative allocation for the scroll frame widget */
 
597
static void
 
598
compute_relative_allocation (GtkWidget *widget, GtkAllocation *allocation)
 
599
{
 
600
        GtkScrollFrame *sf;
 
601
        ScrollFramePrivate *priv;
 
602
 
 
603
        g_assert (widget != NULL);
 
604
        g_assert (GTK_IS_SCROLL_FRAME (widget));
 
605
        g_assert (allocation != NULL);
 
606
 
 
607
        sf = GTK_SCROLL_FRAME (widget);
 
608
        priv = sf->priv;
 
609
 
 
610
        allocation->x = GTK_CONTAINER (widget)->border_width;
 
611
        allocation->y = GTK_CONTAINER (widget)->border_width;
 
612
        allocation->width = MAX (1, (int) widget->allocation.width - (int) allocation->x * 2);
 
613
        allocation->height = MAX (1, (int) widget->allocation.height - (int) allocation->y * 2);
 
614
 
 
615
        if (priv->vsb_visible) {
 
616
                GtkRequisition vsb_requisition;
 
617
 
 
618
                gtk_widget_get_child_requisition (priv->vsb, &vsb_requisition);
 
619
 
 
620
                if (priv->frame_placement == GTK_CORNER_TOP_RIGHT
 
621
                    || priv->frame_placement == GTK_CORNER_BOTTOM_RIGHT)
 
622
                        allocation->x += vsb_requisition.width + priv->sb_spacing;
 
623
 
 
624
                allocation->width = MAX (1,
 
625
                                         ((int) allocation->width
 
626
                                          - (int) (vsb_requisition.width + priv->sb_spacing)));
 
627
        }
 
628
 
 
629
        if (priv->hsb_visible) {
 
630
                GtkRequisition hsb_requisition;
 
631
 
 
632
                gtk_widget_get_child_requisition (priv->hsb, &hsb_requisition);
 
633
 
 
634
                if (priv->frame_placement == GTK_CORNER_BOTTOM_LEFT
 
635
                    || priv->frame_placement == GTK_CORNER_BOTTOM_RIGHT)
 
636
                        allocation->y += hsb_requisition.height + priv->sb_spacing;
 
637
 
 
638
                allocation->height = MAX (1,
 
639
                                          ((int) allocation->height
 
640
                                           - (int) (hsb_requisition.height + priv->sb_spacing)));
 
641
        }
 
642
}
 
643
 
 
644
/* Size_allocate handler for the scroll frame widget */
 
645
static void
 
646
gtk_scroll_frame_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
 
647
{
 
648
        GtkScrollFrame *sf;
 
649
        ScrollFramePrivate *priv;
 
650
        GtkBin *bin;
 
651
        GtkAllocation relative_allocation;
 
652
        GtkAllocation child_allocation;
 
653
        int xthickness, ythickness;
 
654
 
 
655
        g_return_if_fail (widget != NULL);
 
656
        g_return_if_fail (GTK_IS_SCROLL_FRAME (widget));
 
657
        g_return_if_fail (allocation != NULL);
 
658
 
 
659
        sf = GTK_SCROLL_FRAME (widget);
 
660
        priv = sf->priv;
 
661
        bin = GTK_BIN (widget);
 
662
 
 
663
        widget->allocation = *allocation;
 
664
 
 
665
        if (priv->hsb_policy == GTK_POLICY_ALWAYS)
 
666
                priv->hsb_visible = TRUE;
 
667
        else if (priv->hsb_policy == GTK_POLICY_NEVER)
 
668
                priv->hsb_visible = FALSE;
 
669
 
 
670
        if (priv->vsb_policy == GTK_POLICY_ALWAYS)
 
671
                priv->vsb_visible = TRUE;
 
672
        else if (priv->vsb_policy == GTK_POLICY_NEVER)
 
673
                priv->vsb_visible = FALSE;
 
674
 
 
675
        if (priv->shadow_type == GTK_SHADOW_NONE) {
 
676
                xthickness = 0;
 
677
                ythickness = 0;
 
678
        } else {
 
679
                xthickness = widget->style->klass->xthickness;
 
680
                ythickness = widget->style->klass->ythickness;
 
681
        }
 
682
 
 
683
        if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) {
 
684
                gboolean previous_hvis;
 
685
                gboolean previous_vvis;
 
686
                guint count = 0;
 
687
 
 
688
                do {
 
689
                        compute_relative_allocation (widget, &relative_allocation);
 
690
 
 
691
                        priv->frame_x = relative_allocation.x + allocation->x;
 
692
                        priv->frame_y = relative_allocation.y + allocation->y;
 
693
                        priv->frame_w = relative_allocation.width;
 
694
                        priv->frame_h = relative_allocation.height;
 
695
 
 
696
                        child_allocation.x = priv->frame_x + xthickness;
 
697
                        child_allocation.y = priv->frame_y + ythickness;
 
698
                        child_allocation.width = MAX ((int) priv->frame_w - 2 * xthickness, 0);
 
699
                        child_allocation.height = MAX ((int) priv->frame_h - 2 * ythickness, 0);
 
700
 
 
701
                        previous_hvis = priv->hsb_visible;
 
702
                        previous_vvis = priv->vsb_visible;
 
703
 
 
704
                        gtk_widget_size_allocate (bin->child, &child_allocation);
 
705
 
 
706
                        /* If, after the first iteration, the hscrollbar and the
 
707
                         * vscrollbar flip visiblity, then we need both.
 
708
                         */
 
709
                        if (count
 
710
                            && previous_hvis != priv->hsb_visible
 
711
                            && previous_vvis != priv->vsb_visible) {
 
712
                                priv->hsb_visible = TRUE;
 
713
                                priv->vsb_visible = TRUE;
 
714
 
 
715
                                /* a new resize is already queued at this point,
 
716
                                 * so we will immediatedly get reinvoked
 
717
                                 */
 
718
                                return;
 
719
                        }
 
720
 
 
721
                        count++;
 
722
                } while (previous_hvis != priv->hsb_visible
 
723
                         || previous_vvis != priv->vsb_visible);
 
724
        } else
 
725
                compute_relative_allocation (widget, &relative_allocation);
 
726
 
 
727
        if (priv->hsb_visible) {
 
728
                GtkRequisition hscrollbar_requisition;
 
729
 
 
730
                gtk_widget_get_child_requisition (priv->hsb, &hscrollbar_requisition);
 
731
 
 
732
                if (!GTK_WIDGET_VISIBLE (priv->hsb))
 
733
                        gtk_widget_show (priv->hsb);
 
734
 
 
735
                child_allocation.x = relative_allocation.x;
 
736
                if (priv->frame_placement == GTK_CORNER_TOP_LEFT
 
737
                    || priv->frame_placement == GTK_CORNER_TOP_RIGHT)
 
738
                        child_allocation.y = (relative_allocation.y
 
739
                                              + relative_allocation.height
 
740
                                              + priv->sb_spacing);
 
741
                else
 
742
                        child_allocation.y = GTK_CONTAINER (sf)->border_width;
 
743
 
 
744
                child_allocation.width = relative_allocation.width;
 
745
                child_allocation.height = hscrollbar_requisition.height;
 
746
                child_allocation.x += allocation->x;
 
747
                child_allocation.y += allocation->y;
 
748
 
 
749
                gtk_widget_size_allocate (priv->hsb, &child_allocation);
 
750
        } else if (GTK_WIDGET_VISIBLE (priv->hsb))
 
751
                gtk_widget_hide (priv->hsb);
 
752
 
 
753
        if (priv->vsb_visible) {
 
754
                GtkRequisition vscrollbar_requisition;
 
755
 
 
756
                if (!GTK_WIDGET_VISIBLE (priv->vsb))
 
757
                        gtk_widget_show (priv->vsb);
 
758
 
 
759
                gtk_widget_get_child_requisition (priv->vsb, &vscrollbar_requisition);
 
760
 
 
761
                if (priv->frame_placement == GTK_CORNER_TOP_LEFT
 
762
                    || priv->frame_placement == GTK_CORNER_BOTTOM_LEFT)
 
763
                        child_allocation.x = (relative_allocation.x
 
764
                                              + relative_allocation.width
 
765
                                              + priv->sb_spacing);
 
766
                else
 
767
                        child_allocation.x = GTK_CONTAINER (sf)->border_width;
 
768
 
 
769
                child_allocation.y = relative_allocation.y;
 
770
                child_allocation.width = vscrollbar_requisition.width;
 
771
                child_allocation.height = relative_allocation.height;
 
772
                child_allocation.x += allocation->x;
 
773
                child_allocation.y += allocation->y;
 
774
 
 
775
                gtk_widget_size_allocate (priv->vsb, &child_allocation);
 
776
        } else if (GTK_WIDGET_VISIBLE (priv->vsb))
 
777
                gtk_widget_hide (priv->vsb);
 
778
}
 
779
 
 
780
/* Button press handler for the scroll framw diget */
 
781
static gint
 
782
gtk_scroll_frame_button_press (GtkWidget *widget, GdkEventButton *event)
 
783
{
 
784
        g_return_val_if_fail (widget != NULL, FALSE);
 
785
        g_return_val_if_fail (GTK_IS_SCROLL_FRAME (widget), FALSE);
 
786
        g_return_val_if_fail (event != NULL, FALSE);
 
787
 
 
788
        /* This is to handle mouse wheel scrolling */
 
789
        if (event->button == 4 || event->button == 5) {
 
790
                GtkAdjustment *adj;
 
791
                gfloat new_value;
 
792
 
 
793
                gtk_object_get (GTK_OBJECT (widget),
 
794
                                (event->state & GDK_CONTROL_MASK) ?
 
795
                                 "hadjustment" : "vadjustment", 
 
796
                                 &adj,
 
797
                                 NULL);
 
798
 
 
799
                new_value = adj->value + ((event->button == 4) ? 
 
800
                                          -adj->page_increment / 2: 
 
801
                                          adj->page_increment / 2);
 
802
                new_value = CLAMP (new_value, adj->lower, adj->upper - adj->page_size);
 
803
                gtk_adjustment_set_value (adj, new_value);
 
804
 
 
805
                return TRUE;
 
806
        }
 
807
 
 
808
        return FALSE;
 
809
}
 
810
 
 
811
/* Expose handler for the scroll frame widget */
 
812
static gint
 
813
gtk_scroll_frame_expose (GtkWidget *widget, GdkEventExpose *event)
 
814
{
 
815
        GtkScrollFrame *sf;
 
816
 
 
817
        g_return_val_if_fail (widget != NULL, FALSE);
 
818
        g_return_val_if_fail (GTK_IS_SCROLL_FRAME (widget), FALSE);
 
819
        g_return_val_if_fail (event != NULL, FALSE);
 
820
 
 
821
        sf = GTK_SCROLL_FRAME (widget);
 
822
 
 
823
        if (GTK_WIDGET_DRAWABLE (widget))
 
824
                draw_shadow (sf, &event->area);
 
825
 
 
826
        if (GTK_WIDGET_CLASS (parent_class)->expose_event)
 
827
                (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
 
828
 
 
829
        return FALSE;
 
830
}
 
831
 
 
832
/* Add handler for the scroll frame widget */
 
833
static void
 
834
gtk_scroll_frame_add (GtkContainer *container, GtkWidget *child)
 
835
{
 
836
        GtkScrollFrame *sf;
 
837
        ScrollFramePrivate *priv;
 
838
        GtkBin *bin;
 
839
 
 
840
        sf = GTK_SCROLL_FRAME (container);
 
841
        priv = sf->priv;
 
842
        bin = GTK_BIN (container);
 
843
        g_return_if_fail (bin->child == NULL);
 
844
 
 
845
        bin->child = child;
 
846
        gtk_widget_set_parent (child, GTK_WIDGET (bin));
 
847
 
 
848
        /* this is a temporary message */
 
849
        if (!gtk_widget_set_scroll_adjustments (child,
 
850
                                                gtk_range_get_adjustment (GTK_RANGE (priv->hsb)),
 
851
                                                gtk_range_get_adjustment (GTK_RANGE (priv->vsb))))
 
852
                g_warning ("gtk_scroll_frame_add(): cannot add non scrollable widget "
 
853
                           "use gtk_scroll_frame_add_with_viewport() instead");
 
854
 
 
855
        if (GTK_WIDGET_REALIZED (child->parent))
 
856
                gtk_widget_realize (child);
 
857
 
 
858
        if (GTK_WIDGET_VISIBLE (child->parent) && GTK_WIDGET_VISIBLE (child)) {
 
859
                if (GTK_WIDGET_MAPPED (child->parent))
 
860
                        gtk_widget_map (child);
 
861
 
 
862
                gtk_widget_queue_resize (child);
 
863
        }
 
864
}
 
865
 
 
866
/* Remove method for the scroll frame widget */
 
867
static void
 
868
gtk_scroll_frame_remove (GtkContainer *container, GtkWidget *child)
 
869
{
 
870
        g_return_if_fail (container != NULL);
 
871
        g_return_if_fail (GTK_IS_SCROLL_FRAME (container));
 
872
        g_return_if_fail (child != NULL);
 
873
        g_return_if_fail (GTK_BIN (container)->child == child);
 
874
 
 
875
        gtk_widget_set_scroll_adjustments (child, NULL, NULL);
 
876
 
 
877
        /* chain parent class handler to remove child */
 
878
        if (GTK_CONTAINER_CLASS (parent_class)->remove)
 
879
                (* GTK_CONTAINER_CLASS (parent_class)->remove) (container, child);
 
880
}
 
881
 
 
882
/**
 
883
 * gtk_scroll_frame_new:
 
884
 * @hadj: If non-NULL, the adjustment to use for horizontal scrolling.
 
885
 * @vadj: If non-NULL, the adjustment to use for vertical scrolling.
 
886
 *
 
887
 * Creates a new scroll frame widget.
 
888
 *
 
889
 * Return value: The newly-created scroll frame widget.
 
890
 **/
 
891
GtkWidget *
 
892
gtk_scroll_frame_new (GtkAdjustment *hadj, GtkAdjustment *vadj)
 
893
{
 
894
        if (hadj)
 
895
                g_return_val_if_fail (GTK_IS_ADJUSTMENT (hadj), NULL);
 
896
 
 
897
        if (vadj)
 
898
                g_return_val_if_fail (GTK_IS_ADJUSTMENT (vadj), NULL);
 
899
 
 
900
        return gtk_widget_new (GTK_TYPE_SCROLL_FRAME,
 
901
                               "hadjustment", hadj,
 
902
                               "vadjustment", vadj,
 
903
                               NULL);
 
904
}
 
905
 
 
906
/* Callback used when one of the scroll frame widget's adjustments changes */
 
907
static void
 
908
adjustment_changed (GtkAdjustment *adj, gpointer data)
 
909
{
 
910
        GtkScrollFrame *sf;
 
911
        ScrollFramePrivate *priv;
 
912
 
 
913
        g_return_if_fail (adj != NULL);
 
914
        g_return_if_fail (GTK_IS_ADJUSTMENT (adj));
 
915
        g_return_if_fail (data != NULL);
 
916
 
 
917
        sf = GTK_SCROLL_FRAME (data);
 
918
        priv = sf->priv;
 
919
 
 
920
        if (adj == gtk_range_get_adjustment (GTK_RANGE (priv->hsb))) {
 
921
                if (priv->hsb_policy == GTK_POLICY_AUTOMATIC) {
 
922
                        gboolean visible;
 
923
 
 
924
                        visible = priv->hsb_visible;
 
925
                        priv->hsb_visible = (adj->upper - adj->lower > adj->page_size);
 
926
                        if (priv->hsb_visible != visible)
 
927
                                gtk_widget_queue_resize (GTK_WIDGET (sf));
 
928
                }
 
929
        } else if (adj == gtk_range_get_adjustment (GTK_RANGE (priv->vsb))) {
 
930
                if (priv->vsb_policy == GTK_POLICY_AUTOMATIC) {
 
931
                        gboolean visible;
 
932
 
 
933
                        visible = priv->vsb_visible;
 
934
                        priv->vsb_visible = (adj->upper - adj->lower > adj->page_size);
 
935
                        if (priv->vsb_visible != visible)
 
936
                                gtk_widget_queue_resize (GTK_WIDGET (sf));
 
937
                }
 
938
        }
 
939
}
 
940
 
 
941
/**
 
942
 * gtk_scroll_frame_set_hadjustment:
 
943
 * @sf: A scroll frame widget.
 
944
 * @adj: An adjustment.
 
945
 *
 
946
 * Sets the adjustment to be used for horizontal scrolling in a scroll frame
 
947
 * widget.
 
948
 **/
 
949
void
 
950
gtk_scroll_frame_set_hadjustment (GtkScrollFrame *sf, GtkAdjustment *adj)
 
951
{
 
952
        ScrollFramePrivate *priv;
 
953
 
 
954
        g_return_if_fail (sf != NULL);
 
955
        g_return_if_fail (GTK_IS_SCROLL_FRAME (sf));
 
956
 
 
957
        priv = sf->priv;
 
958
 
 
959
        if (adj)
 
960
                g_return_if_fail (GTK_IS_ADJUSTMENT (adj));
 
961
        else
 
962
                adj = GTK_ADJUSTMENT (gtk_object_new (GTK_TYPE_ADJUSTMENT, NULL));
 
963
 
 
964
        if (!priv->hsb) {
 
965
                gtk_widget_push_composite_child ();
 
966
                priv->hsb = gtk_hscrollbar_new (adj);
 
967
                gtk_widget_set_composite_name (priv->hsb, "hscrollbar");
 
968
                gtk_widget_pop_composite_child ();
 
969
 
 
970
                gtk_widget_set_parent (priv->hsb, GTK_WIDGET (sf));
 
971
                gtk_widget_ref (priv->hsb);
 
972
                gtk_widget_show (priv->hsb);
 
973
        } else {
 
974
                GtkAdjustment *old_adj;
 
975
 
 
976
                old_adj = gtk_range_get_adjustment (GTK_RANGE (priv->hsb));
 
977
                if (old_adj == adj)
 
978
                        return;
 
979
 
 
980
                gtk_signal_disconnect_by_func (GTK_OBJECT (old_adj),
 
981
                                               GTK_SIGNAL_FUNC (adjustment_changed),
 
982
                                               sf);
 
983
                gtk_range_set_adjustment (GTK_RANGE (priv->hsb), adj);
 
984
        }
 
985
 
 
986
        adj = gtk_range_get_adjustment (GTK_RANGE (priv->hsb));
 
987
        gtk_signal_connect (GTK_OBJECT (adj),
 
988
                            "changed",
 
989
                            GTK_SIGNAL_FUNC (adjustment_changed),
 
990
                            sf);
 
991
        adjustment_changed (adj, sf);
 
992
 
 
993
        if (GTK_BIN (sf)->child)
 
994
                gtk_widget_set_scroll_adjustments (
 
995
                        GTK_BIN (sf)->child,
 
996
                        gtk_range_get_adjustment (GTK_RANGE (priv->hsb)),
 
997
                        gtk_range_get_adjustment (GTK_RANGE (priv->vsb)));
 
998
}
 
999
 
 
1000
/**
 
1001
 * gtk_scroll_frame_set_vadjustment:
 
1002
 * @sf: A scroll frame widget.
 
1003
 * @adj: An adjustment.
 
1004
 *
 
1005
 * Sets the adjustment to be used for vertical scrolling in a scroll frame
 
1006
 * widget.
 
1007
 **/
 
1008
void
 
1009
gtk_scroll_frame_set_vadjustment (GtkScrollFrame *sf, GtkAdjustment *adj)
 
1010
{
 
1011
        ScrollFramePrivate *priv;
 
1012
 
 
1013
        g_return_if_fail (sf != NULL);
 
1014
        g_return_if_fail (GTK_IS_SCROLL_FRAME (sf));
 
1015
 
 
1016
        priv = sf->priv;
 
1017
 
 
1018
        if (adj)
 
1019
                g_return_if_fail (GTK_IS_ADJUSTMENT (adj));
 
1020
        else
 
1021
                adj = GTK_ADJUSTMENT (gtk_object_new (GTK_TYPE_ADJUSTMENT, NULL));
 
1022
 
 
1023
        if (!priv->vsb) {
 
1024
                gtk_widget_push_composite_child ();
 
1025
                priv->vsb = gtk_vscrollbar_new (adj);
 
1026
                gtk_widget_set_composite_name (priv->vsb, "vscrollbar");
 
1027
                gtk_widget_pop_composite_child ();
 
1028
 
 
1029
                gtk_widget_set_parent (priv->vsb, GTK_WIDGET (sf));
 
1030
                gtk_widget_ref (priv->vsb);
 
1031
                gtk_widget_show (priv->vsb);
 
1032
        } else {
 
1033
                GtkAdjustment *old_adj;
 
1034
 
 
1035
                old_adj = gtk_range_get_adjustment (GTK_RANGE (priv->vsb));
 
1036
                if (old_adj == adj)
 
1037
                        return;
 
1038
 
 
1039
                gtk_signal_disconnect_by_func (GTK_OBJECT (old_adj),
 
1040
                                               GTK_SIGNAL_FUNC (adjustment_changed),
 
1041
                                               sf);
 
1042
                gtk_range_set_adjustment (GTK_RANGE (priv->vsb), adj);
 
1043
        }
 
1044
 
 
1045
        adj = gtk_range_get_adjustment (GTK_RANGE (priv->vsb));
 
1046
        gtk_signal_connect (GTK_OBJECT (adj),
 
1047
                            "changed",
 
1048
                            GTK_SIGNAL_FUNC (adjustment_changed),
 
1049
                            sf);
 
1050
        adjustment_changed (adj, sf);
 
1051
 
 
1052
        if (GTK_BIN (sf)->child)
 
1053
                gtk_widget_set_scroll_adjustments (
 
1054
                        GTK_BIN (sf)->child,
 
1055
                        gtk_range_get_adjustment (GTK_RANGE (priv->hsb)),
 
1056
                        gtk_range_get_adjustment (GTK_RANGE (priv->vsb)));
 
1057
}
 
1058
 
 
1059
/**
 
1060
 * gtk_scroll_frame_get_hadjustment:
 
1061
 * @sf: A scroll frame widget.
 
1062
 *
 
1063
 * Queries the horizontal adjustment of a scroll frame widget.
 
1064
 *
 
1065
 * Return value: The horizontal adjustment of the scroll frame, or NULL if none.
 
1066
 **/
 
1067
GtkAdjustment *
 
1068
gtk_scroll_frame_get_hadjustment (GtkScrollFrame *sf)
 
1069
{
 
1070
        ScrollFramePrivate *priv;
 
1071
 
 
1072
        g_return_val_if_fail (sf != NULL, NULL);
 
1073
        g_return_val_if_fail (GTK_IS_SCROLL_FRAME (sf), NULL);
 
1074
 
 
1075
        priv = sf->priv;
 
1076
 
 
1077
        return priv->hsb ? gtk_range_get_adjustment (GTK_RANGE (priv->hsb)) : NULL;
 
1078
}
 
1079
 
 
1080
/**
 
1081
 * gtk_scroll_frame_get_vadjustment:
 
1082
 * @sf: A scroll frame widget.
 
1083
 *
 
1084
 * Queries the vertical adjustment of a scroll frame widget.
 
1085
 *
 
1086
 * Return value: The vertical adjustment of the scroll frame, or NULL if none.
 
1087
 **/
 
1088
GtkAdjustment *
 
1089
gtk_scroll_frame_get_vadjustment (GtkScrollFrame *sf)
 
1090
{
 
1091
        ScrollFramePrivate *priv;
 
1092
 
 
1093
        g_return_val_if_fail (sf != NULL, NULL);
 
1094
        g_return_val_if_fail (GTK_IS_SCROLL_FRAME (sf), NULL);
 
1095
 
 
1096
        priv = sf->priv;
 
1097
 
 
1098
        return priv->vsb ? gtk_range_get_adjustment (GTK_RANGE (priv->vsb)) : NULL;
 
1099
}
 
1100
 
 
1101
/**
 
1102
 * gtk_scroll_frame_set_policy:
 
1103
 * @sf: A scroll frame widget.
 
1104
 * @hsb_policy: Policy for the horizontal scrollbar.
 
1105
 * @vsb_policy: Policy for the vertical scrollbar.
 
1106
 *
 
1107
 * Sets the scrollbar policies of a scroll frame widget.  These determine when
 
1108
 * the scrollbars are to be shown or hidden.
 
1109
 **/
 
1110
void
 
1111
gtk_scroll_frame_set_policy (GtkScrollFrame *sf,
 
1112
                             GtkPolicyType hsb_policy,
 
1113
                             GtkPolicyType vsb_policy)
 
1114
{
 
1115
        ScrollFramePrivate *priv;
 
1116
 
 
1117
        g_return_if_fail (sf != NULL);
 
1118
        g_return_if_fail (GTK_IS_SCROLL_FRAME (sf));
 
1119
 
 
1120
        priv = sf->priv;
 
1121
 
 
1122
        if (priv->hsb_policy == hsb_policy && priv->vsb_policy == vsb_policy)
 
1123
                return;
 
1124
 
 
1125
        priv->hsb_policy = hsb_policy;
 
1126
        priv->vsb_policy = vsb_policy;
 
1127
 
 
1128
        gtk_widget_queue_resize (GTK_WIDGET (sf));
 
1129
}
 
1130
 
 
1131
/**
 
1132
 * gtk_scroll_frame_get_policy:
 
1133
 * @sf: A scroll frame widget.
 
1134
 * @hsb_policy: Return value for the horizontal scrollbar's policy.
 
1135
 * @vsb_policy: Return value for the vertical scrollbar's policy.
 
1136
 * 
 
1137
 * Queries the scrollbar policies of a scroll frame widget.
 
1138
 **/
 
1139
void
 
1140
gtk_scroll_frame_get_policy (GtkScrollFrame *sf,
 
1141
                             GtkPolicyType *hsb_policy,
 
1142
                             GtkPolicyType *vsb_policy)
 
1143
{
 
1144
        ScrollFramePrivate *priv;
 
1145
 
 
1146
        g_return_if_fail (sf != NULL);
 
1147
        g_return_if_fail (GTK_IS_SCROLL_FRAME (sf));
 
1148
 
 
1149
        priv = sf->priv;
 
1150
 
 
1151
        if (hsb_policy)
 
1152
                *hsb_policy = priv->hsb_policy;
 
1153
 
 
1154
        if (vsb_policy)
 
1155
                *vsb_policy = priv->vsb_policy;
 
1156
}
 
1157
 
 
1158
/**
 
1159
 * gtk_scroll_frame_set_placement:
 
1160
 * @sf: A scroll frame widget.
 
1161
 * @frame_placement: Placement for the frame.
 
1162
 *
 
1163
 * Sets the placement of a scroll frame widget's frame with respect to its
 
1164
 * scrollbars.
 
1165
 **/
 
1166
void
 
1167
gtk_scroll_frame_set_placement (GtkScrollFrame *sf, GtkCornerType frame_placement)
 
1168
{
 
1169
        ScrollFramePrivate *priv;
 
1170
 
 
1171
        g_return_if_fail (sf != NULL);
 
1172
        g_return_if_fail (GTK_IS_SCROLL_FRAME (sf));
 
1173
 
 
1174
        priv = sf->priv;
 
1175
 
 
1176
        if (priv->frame_placement == frame_placement)
 
1177
                return;
 
1178
 
 
1179
        priv->frame_placement = frame_placement;
 
1180
        gtk_widget_queue_resize (GTK_WIDGET (sf));
 
1181
}
 
1182
 
 
1183
/**
 
1184
 * gtk_scroll_frame_set_shadow_type:
 
1185
 * @sf: A scroll frame widget.
 
1186
 * @shadow_type: A shadow type.
 
1187
 *
 
1188
 * Sets the shadow type of a scroll frame widget.  You can use this when you
 
1189
 * insert a child that does not paint a frame on its own.
 
1190
 **/
 
1191
void
 
1192
gtk_scroll_frame_set_shadow_type (GtkScrollFrame *sf, GtkShadowType shadow_type)
 
1193
{
 
1194
        ScrollFramePrivate *priv;
 
1195
 
 
1196
        g_return_if_fail (sf != NULL);
 
1197
        g_return_if_fail (GTK_IS_SCROLL_FRAME (sf));
 
1198
        g_return_if_fail (shadow_type >= GTK_SHADOW_NONE && shadow_type <= GTK_SHADOW_ETCHED_OUT);
 
1199
 
 
1200
        priv = sf->priv;
 
1201
 
 
1202
        if (priv->shadow_type == shadow_type)
 
1203
                return;
 
1204
 
 
1205
        priv->shadow_type = shadow_type;
 
1206
        gtk_widget_queue_resize (GTK_WIDGET (sf));
 
1207
}
 
1208
 
 
1209
/**
 
1210
 * gtk_scroll_frame_get_shadow_type:
 
1211
 * @sf: A scroll frame widget.
 
1212
 * 
 
1213
 * Queries the shadow type of a scroll frame widget.
 
1214
 * 
 
1215
 * Return value: Shadow type.
 
1216
 **/
 
1217
GtkShadowType
 
1218
gtk_scroll_frame_get_shadow_type (GtkScrollFrame *sf)
 
1219
{
 
1220
        ScrollFramePrivate *priv;
 
1221
 
 
1222
        g_return_val_if_fail (sf != NULL, GTK_SHADOW_NONE);
 
1223
        g_return_val_if_fail (GTK_IS_SCROLL_FRAME (sf), GTK_SHADOW_NONE);
 
1224
 
 
1225
        priv = sf->priv;
 
1226
 
 
1227
        return priv->shadow_type;
 
1228
}
 
1229
 
 
1230
/**
 
1231
 * gtk_scroll_frame_set_scrollbar_spacing:
 
1232
 * @sf: A scroll frame widget.
 
1233
 * @spacing: Desired spacing in pixels.
 
1234
 *
 
1235
 * Sets the spacing between the frame and the scrollbars of a scroll frame
 
1236
 * widget.
 
1237
 **/
 
1238
void
 
1239
gtk_scroll_frame_set_scrollbar_spacing (GtkScrollFrame *sf, guint spacing)
 
1240
{
 
1241
        ScrollFramePrivate *priv;
 
1242
 
 
1243
        g_return_if_fail (sf != NULL);
 
1244
        g_return_if_fail (GTK_IS_SCROLL_FRAME (sf));
 
1245
 
 
1246
        priv = sf->priv;
 
1247
 
 
1248
        if (priv->sb_spacing == spacing)
 
1249
                return;
 
1250
 
 
1251
        priv->sb_spacing = spacing;
 
1252
        gtk_widget_queue_resize (GTK_WIDGET (sf));
 
1253
}
 
1254
 
 
1255
/**
 
1256
 * gtk_scroll_frame_add_with_viewport:
 
1257
 * @sf: A scroll frame widget.
 
1258
 * @child: A widget.
 
1259
 *
 
1260
 * Creates a #GtkViewport and puts the specified child inside it, thus allowing
 
1261
 * the viewport to be scrolled by the scroll frame widget.  This is meant to be
 
1262
 * used only when a child does not support the scrolling interface.
 
1263
 **/
 
1264
void
 
1265
gtk_scroll_frame_add_with_viewport (GtkScrollFrame *sf, GtkWidget *child)
 
1266
{
 
1267
        ScrollFramePrivate *priv;
 
1268
        GtkBin *bin;
 
1269
        GtkWidget *viewport;
 
1270
 
 
1271
        g_return_if_fail (sf != NULL);
 
1272
        g_return_if_fail (GTK_IS_SCROLL_FRAME (sf));
 
1273
        g_return_if_fail (child != NULL);
 
1274
        g_return_if_fail (GTK_IS_WIDGET (child));
 
1275
        g_return_if_fail (child->parent == NULL);
 
1276
 
 
1277
        priv = sf->priv;
 
1278
        bin = GTK_BIN (sf);
 
1279
 
 
1280
        if (bin->child != NULL) {
 
1281
                g_return_if_fail (GTK_IS_VIEWPORT (bin->child));
 
1282
                g_return_if_fail (GTK_BIN (bin->child)->child == NULL);
 
1283
 
 
1284
                viewport = bin->child;
 
1285
        } else {
 
1286
                viewport = gtk_viewport_new (gtk_scroll_frame_get_hadjustment (sf),
 
1287
                                             gtk_scroll_frame_get_vadjustment (sf));
 
1288
                gtk_container_add (GTK_CONTAINER (sf), viewport);
 
1289
        }
 
1290
 
 
1291
        gtk_widget_show (viewport);
 
1292
        gtk_container_add (GTK_CONTAINER (viewport), child);
 
1293
}