~ubuntu-branches/ubuntu/intrepid/gnome-games/intrepid-updates

« back to all changes in this revision

Viewing changes to aisleriot/scroll-menu.c

  • Committer: Package Import Robot
  • Author(s): Jose Carlos Garcia Sogo
  • Date: 2002-02-15 20:12:21 UTC
  • Revision ID: package-import@ubuntu.com-20020215201221-pntf81dxhsatz4qy
Tags: upstream-1.4.0.3
ImportĀ upstreamĀ versionĀ 1.4.0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Scroll menu: a scrolling menu (if it's beyond screen size)
 
2
 * (C) 2000  Eazel, Inc.
 
3
 *
 
4
 * Authors:  George Lebl
 
5
 */
 
6
 
 
7
#include <gtk/gtk.h>
 
8
 
 
9
#include "scroll-menu.h"
 
10
 
 
11
static void scroll_menu_class_init      (ScrollMenuClass  *klass);
 
12
static void scroll_menu_init            (ScrollMenu       *self);
 
13
static void scroll_menu_size_request    (GtkWidget        *widget,
 
14
                                         GtkRequisition   *requisition);
 
15
static void scroll_menu_size_allocate   (GtkWidget        *widget,
 
16
                                         GtkAllocation    *allocation);
 
17
static void scroll_menu_map             (GtkWidget        *widget);
 
18
static void scroll_menu_unmap           (GtkWidget        *widget);
 
19
static void scroll_menu_destroy         (GtkObject        *object);
 
20
static void scroll_menu_move_current    (GtkMenuShell     *menu_shell,
 
21
                                         GtkMenuDirectionType direction);
 
22
static void scroll_menu_remove          (GtkContainer     *container,
 
23
                                         GtkWidget        *widget);
 
24
static gboolean scroll_menu_enter_notify(GtkWidget        *widget,
 
25
                                         GdkEventCrossing *event);
 
26
static gboolean scroll_menu_leave_notify(GtkWidget        *widget,
 
27
                                         GdkEventCrossing *event);
 
28
 
 
29
static GtkMenuClass *parent_class = NULL;
 
30
 
 
31
enum {
 
32
        SCROLL_UP,
 
33
        SCROLL_DOWN
 
34
};
 
35
 
 
36
#define SCROLLER_HEIGHT 15
 
37
#define SCROLL_BY 15
 
38
#define SCROLL_TIMEOUT 150
 
39
#define ARROW_PAD 3
 
40
 
 
41
GtkType
 
42
scroll_menu_get_type (void)
 
43
{
 
44
        static GtkType scroll_menu_type = 0;
 
45
 
 
46
        if (scroll_menu_type == 0) {
 
47
                GtkType menu_type;
 
48
 
 
49
                GtkTypeInfo scroll_menu_info = {
 
50
                        "ScrollMenu",
 
51
                        sizeof (ScrollMenu),
 
52
                        sizeof (ScrollMenuClass),
 
53
                        (GtkClassInitFunc) scroll_menu_class_init,
 
54
                        (GtkObjectInitFunc) scroll_menu_init,
 
55
                        (GtkArgSetFunc) NULL,
 
56
                        (GtkArgGetFunc) NULL,
 
57
                        NULL
 
58
                };
 
59
 
 
60
                menu_type = gtk_menu_get_type ();
 
61
 
 
62
                scroll_menu_type = gtk_type_unique (menu_type,
 
63
                                                    &scroll_menu_info);
 
64
                parent_class = gtk_type_class (menu_type);
 
65
        }
 
66
 
 
67
        return scroll_menu_type;
 
68
}
 
69
 
 
70
static void
 
71
scroll_menu_class_init (ScrollMenuClass *klass)
 
72
{
 
73
        GtkObjectClass *object_class = (GtkObjectClass*) klass;
 
74
        GtkWidgetClass *widget_class = (GtkWidgetClass*) klass;
 
75
        GtkContainerClass *container_class = (GtkContainerClass*) klass;
 
76
        GtkMenuShellClass *menushell_class = (GtkMenuShellClass*) klass;
 
77
        
 
78
        widget_class->size_request = scroll_menu_size_request;
 
79
        widget_class->size_allocate = scroll_menu_size_allocate;
 
80
        widget_class->map = scroll_menu_map;
 
81
        widget_class->unmap = scroll_menu_unmap;
 
82
        widget_class->enter_notify_event = scroll_menu_enter_notify;
 
83
        widget_class->leave_notify_event = scroll_menu_leave_notify;
 
84
 
 
85
        menushell_class->move_current = scroll_menu_move_current;
 
86
 
 
87
        container_class->remove = scroll_menu_remove;
 
88
 
 
89
        object_class->destroy = scroll_menu_destroy;
 
90
}
 
91
 
 
92
static void
 
93
scroll_by (ScrollMenu *self, int move)
 
94
{
 
95
        GtkMenuShell *menu_shell = GTK_MENU_SHELL (self);
 
96
        GtkAllocation allocation;
 
97
        GList *children;
 
98
        GtkWidget *child;
 
99
 
 
100
        if (self->offset + move < 0) {
 
101
                move = - self->offset;
 
102
        } else if (self->offset + move > self->max_offset) {
 
103
                move = self->max_offset - self->offset;
 
104
        }
 
105
 
 
106
        if (move == 0)
 
107
                return;
 
108
 
 
109
        self->offset += move;
 
110
 
 
111
        children = menu_shell->children;
 
112
        while (children) {
 
113
                child = children->data;
 
114
                children = children->next;
 
115
 
 
116
                if (GTK_WIDGET_VISIBLE (child)) {
 
117
                        allocation = child->allocation;
 
118
                        allocation.y -= move;
 
119
 
 
120
                        gtk_widget_size_allocate (child, &allocation);
 
121
                        gtk_widget_queue_draw (child);
 
122
                }
 
123
        }
 
124
}
 
125
 
 
126
static gboolean
 
127
scroll_timeout (gpointer data)
 
128
{
 
129
        ScrollMenu *self = SCROLL_MENU (data);
 
130
        GtkMenuShell *menu_shell = GTK_MENU_SHELL (self);
 
131
 
 
132
        if (self->scroll_by == 0 ||
 
133
            menu_shell->children == NULL) {
 
134
                return TRUE;
 
135
        }
 
136
 
 
137
        scroll_by (self, self->scroll_by);
 
138
 
 
139
        return TRUE;
 
140
}
 
141
 
 
142
static void
 
143
scroll_draw (GtkWidget *scroll, gboolean active, int direction)
 
144
{
 
145
        GtkArrowType arrow_type;
 
146
 
 
147
        if( ! GTK_WIDGET_DRAWABLE(scroll))
 
148
                return;
 
149
 
 
150
        gdk_window_clear_area (scroll->window,
 
151
                               0, 0,
 
152
                               scroll->allocation.width,
 
153
                               scroll->allocation.height);
 
154
 
 
155
        gtk_draw_shadow (scroll->style,
 
156
                         scroll->window,
 
157
                         scroll->state,
 
158
                         active ? GTK_SHADOW_IN : GTK_SHADOW_OUT,
 
159
                         0, 0,
 
160
                         scroll->allocation.width,
 
161
                         scroll->allocation.height);
 
162
 
 
163
        if (direction == SCROLL_UP) {
 
164
                arrow_type = GTK_ARROW_UP;
 
165
        } else {
 
166
                arrow_type = GTK_ARROW_DOWN;
 
167
        }
 
168
 
 
169
        gtk_draw_arrow (scroll->style,
 
170
                        scroll->window,
 
171
                        scroll->state,
 
172
                        active ? GTK_SHADOW_IN : GTK_SHADOW_OUT,
 
173
                        arrow_type,
 
174
                        TRUE,
 
175
                        (scroll->allocation.width / 2) - 
 
176
                          SCROLLER_HEIGHT / 2 - ARROW_PAD,
 
177
                        ARROW_PAD,
 
178
                        SCROLLER_HEIGHT - ARROW_PAD * 2,
 
179
                        SCROLLER_HEIGHT - ARROW_PAD * 2);
 
180
}
 
181
 
 
182
static gboolean
 
183
scroll_expose (GtkWidget *scroll, GdkEventExpose *event, gpointer data)
 
184
{
 
185
        ScrollMenu *self = SCROLL_MENU (gtk_object_get_user_data (GTK_OBJECT (scroll)));
 
186
        int direction = GPOINTER_TO_INT (data);
 
187
        gboolean active = FALSE;
 
188
 
 
189
        if (direction == SCROLL_UP) {
 
190
                active = self->in_up;
 
191
        } else {
 
192
                active = self->in_down;
 
193
        }
 
194
 
 
195
        scroll_draw (scroll, active, direction);
 
196
        
 
197
        return FALSE;
 
198
}
 
199
 
 
200
static void
 
201
scroll_realize (GtkWidget *scroll, gpointer data)
 
202
{
 
203
        ScrollMenu *self = SCROLL_MENU (gtk_object_get_user_data (GTK_OBJECT (scroll)));
 
204
        int direction = GPOINTER_TO_INT (data);
 
205
        gboolean active = FALSE;
 
206
 
 
207
        if (direction == SCROLL_UP) {
 
208
                active = self->in_up;
 
209
        } else {
 
210
                active = self->in_down;
 
211
        }
 
212
 
 
213
        scroll_draw (scroll, active, direction);
 
214
}
 
215
 
 
216
static gboolean
 
217
scroll_enter_notify (GtkWidget *scroll, GdkEventCrossing *event, gpointer data)
 
218
{
 
219
        ScrollMenu *self = SCROLL_MENU (gtk_object_get_user_data (GTK_OBJECT (scroll)));
 
220
        int direction = GPOINTER_TO_INT (data);
 
221
 
 
222
        if (direction == SCROLL_UP) {
 
223
                self->in_up = TRUE;
 
224
                self->scroll_by = -(SCROLL_BY);
 
225
        } else {
 
226
                self->in_down = TRUE;
 
227
                self->scroll_by = SCROLL_BY;
 
228
        }
 
229
 
 
230
        gtk_widget_queue_draw (scroll);
 
231
 
 
232
        if (self->scroll_timeout == 0) {
 
233
                self->scroll_timeout = gtk_timeout_add (SCROLL_TIMEOUT,
 
234
                                                        scroll_timeout,
 
235
                                                        self);
 
236
        }
 
237
        
 
238
        return FALSE;
 
239
}
 
240
 
 
241
static gboolean
 
242
scroll_leave_notify (GtkWidget *scroll, GdkEventCrossing *event, gpointer data)
 
243
{
 
244
        ScrollMenu *self = SCROLL_MENU (gtk_object_get_user_data (GTK_OBJECT (scroll)));
 
245
        int direction = GPOINTER_TO_INT (data);
 
246
 
 
247
        self->scroll_by = 0;
 
248
 
 
249
        if (direction == SCROLL_UP) {
 
250
                self->in_up = FALSE;
 
251
        } else {
 
252
                self->in_down = FALSE;
 
253
        }
 
254
 
 
255
        gtk_widget_queue_draw (scroll);
 
256
 
 
257
        if (self->scroll_timeout != 0) {
 
258
                gtk_timeout_remove (self->scroll_timeout);
 
259
                self->scroll_timeout = 0;
 
260
        }
 
261
        
 
262
        return FALSE;
 
263
}
 
264
 
 
265
static GtkWidget *
 
266
make_scroller (ScrollMenu *self, int direction)
 
267
{
 
268
        GtkWidget *scroll;
 
269
 
 
270
        scroll = gtk_drawing_area_new ();
 
271
        gtk_widget_set_events(scroll,
 
272
                              gtk_widget_get_events(scroll) |
 
273
                              GDK_BUTTON_PRESS_MASK |
 
274
                              GDK_ENTER_NOTIFY_MASK |
 
275
                              GDK_LEAVE_NOTIFY_MASK);
 
276
        gtk_widget_set_usize (scroll, 0, SCROLLER_HEIGHT);
 
277
        gtk_widget_show (scroll);
 
278
 
 
279
        gtk_object_set_user_data (GTK_OBJECT (scroll), self);
 
280
 
 
281
        gtk_signal_connect (GTK_OBJECT (scroll), "enter_notify_event",
 
282
                            GTK_SIGNAL_FUNC (scroll_enter_notify),
 
283
                            GINT_TO_POINTER (direction));
 
284
        gtk_signal_connect (GTK_OBJECT (scroll), "leave_notify_event",
 
285
                            GTK_SIGNAL_FUNC (scroll_leave_notify),
 
286
                            GINT_TO_POINTER (direction));
 
287
 
 
288
        gtk_signal_connect_after(GTK_OBJECT(scroll), "realize",
 
289
                                 GTK_SIGNAL_FUNC(scroll_realize),
 
290
                                 GINT_TO_POINTER (direction));
 
291
        gtk_signal_connect(GTK_OBJECT(scroll), "expose_event",
 
292
                           GTK_SIGNAL_FUNC(scroll_expose),
 
293
                           GINT_TO_POINTER (direction));
 
294
 
 
295
        return scroll;
 
296
}
 
297
 
 
298
static void
 
299
scroll_menu_init (ScrollMenu *self)
 
300
{
 
301
        self->up_scroll = make_scroller (self, SCROLL_UP);
 
302
        gtk_widget_ref (self->up_scroll);
 
303
        gtk_object_sink (GTK_OBJECT (self->up_scroll));
 
304
        gtk_widget_set_parent (self->up_scroll, GTK_WIDGET(self));
 
305
 
 
306
        self->down_scroll = make_scroller (self, SCROLL_DOWN);
 
307
        gtk_widget_ref (self->down_scroll);
 
308
        gtk_object_sink (GTK_OBJECT (self->up_scroll));
 
309
        gtk_widget_set_parent (self->down_scroll, GTK_WIDGET(self));
 
310
 
 
311
        self->scroll = FALSE;
 
312
 
 
313
        self->offset = 0;
 
314
        self->max_offset = 0;
 
315
        self->scroll_by = 0;
 
316
        self->scroll_timeout = 0;
 
317
}
 
318
 
 
319
static void
 
320
scroll_menu_destroy (GtkObject *object)
 
321
{
 
322
        ScrollMenu *self = SCROLL_MENU (object);
 
323
 
 
324
        if (self->up_scroll != NULL) {
 
325
                /* this should remove the widget and thus cause
 
326
                 * a NULL and an unref */
 
327
                gtk_widget_destroy (self->up_scroll);
 
328
                g_assert (self->up_scroll == NULL);
 
329
        }
 
330
 
 
331
        if (self->down_scroll != NULL) {
 
332
                /* this should remove the widget and thus cause
 
333
                 * a NULL and an unref */
 
334
                gtk_widget_destroy (self->down_scroll);
 
335
                g_assert (self->down_scroll == NULL);
 
336
        }
 
337
 
 
338
        if (self->scroll_timeout != 0) {
 
339
                gtk_timeout_remove (self->scroll_timeout);
 
340
                self->scroll_timeout = 0;
 
341
        }
 
342
 
 
343
        if (GTK_OBJECT_CLASS (parent_class)->destroy)
 
344
                GTK_OBJECT_CLASS (parent_class)->destroy (object);
 
345
}
 
346
 
 
347
static void
 
348
scroll_menu_size_request (GtkWidget *widget,
 
349
                          GtkRequisition *requisition)
 
350
{
 
351
        ScrollMenu *self = SCROLL_MENU (widget);
 
352
        GtkRequisition child_requisition;
 
353
        int screen_height;
 
354
 
 
355
        if (GTK_WIDGET_CLASS (parent_class)->size_request)
 
356
                GTK_WIDGET_CLASS (parent_class)->size_request (widget,
 
357
                                                               requisition);
 
358
 
 
359
        screen_height = gdk_screen_height ();
 
360
 
 
361
        if (requisition->height > screen_height) {
 
362
                int button_height;
 
363
 
 
364
                button_height = 0;
 
365
                gtk_widget_size_request (self->up_scroll, &child_requisition);
 
366
                button_height += child_requisition.height;
 
367
                gtk_widget_size_request (self->down_scroll, &child_requisition);
 
368
                button_height += child_requisition.height;
 
369
 
 
370
                self->max_offset =
 
371
                        (requisition->height - screen_height) + button_height;
 
372
 
 
373
                if (self->offset > self->max_offset)
 
374
                        self->offset = self->max_offset;
 
375
 
 
376
                requisition->height = screen_height;
 
377
                self->scroll = TRUE;
 
378
        } else {
 
379
                self->offset = 0;
 
380
                self->max_offset = 0;
 
381
                self->scroll = FALSE;
 
382
        }
 
383
}
 
384
 
 
385
static void
 
386
scroll_menu_size_allocate (GtkWidget *widget,
 
387
                           GtkAllocation *allocation)
 
388
{
 
389
        ScrollMenu *self;
 
390
        GtkMenu *menu;
 
391
        GtkMenuShell *menu_shell;
 
392
        GtkWidget *child;
 
393
        GtkAllocation child_allocation;
 
394
        GtkRequisition child_requisition;
 
395
        GList *children;
 
396
        int top_scroller_height;
 
397
 
 
398
        g_return_if_fail (widget != NULL);
 
399
        g_return_if_fail (IS_SCROLL_MENU (widget));
 
400
        g_return_if_fail (allocation != NULL);
 
401
 
 
402
        self = SCROLL_MENU (widget);
 
403
        menu = GTK_MENU (widget);
 
404
        menu_shell = GTK_MENU_SHELL (widget);
 
405
 
 
406
        widget->allocation = *allocation;
 
407
        if (GTK_WIDGET_REALIZED (widget)) {
 
408
                gdk_window_move_resize (widget->window,
 
409
                                        allocation->x, allocation->y,
 
410
                                        allocation->width, allocation->height);
 
411
        }
 
412
 
 
413
        top_scroller_height = 0;
 
414
 
 
415
        if (self->scroll) {
 
416
                if (GTK_WIDGET_MAPPED (widget) &&
 
417
                    ! GTK_WIDGET_MAPPED (self->up_scroll))
 
418
                        gtk_widget_map (self->up_scroll);
 
419
                if (self->up_scroll->window)
 
420
                        gdk_window_raise (self->up_scroll->window);
 
421
 
 
422
                if (GTK_WIDGET_MAPPED (widget) &&
 
423
                    ! GTK_WIDGET_MAPPED (self->down_scroll))
 
424
                        gtk_widget_map (self->down_scroll);
 
425
                if (self->down_scroll->window)
 
426
                        gdk_window_raise (self->down_scroll->window);
 
427
 
 
428
                gtk_widget_get_child_requisition (self->up_scroll, &child_requisition);
 
429
                child_allocation.x = 0;
 
430
                child_allocation.y = 0;
 
431
                child_allocation.width = allocation->width;
 
432
                child_allocation.height = child_requisition.height;
 
433
                gtk_widget_size_allocate (self->up_scroll, &child_allocation);
 
434
 
 
435
                top_scroller_height = child_requisition.height;
 
436
 
 
437
                gtk_widget_get_child_requisition (self->down_scroll, &child_requisition);
 
438
                child_allocation.x = 0;
 
439
                child_allocation.y = allocation->height - child_requisition.height;
 
440
                child_allocation.width = allocation->width;
 
441
                child_allocation.height = child_requisition.height;
 
442
                gtk_widget_size_allocate (self->down_scroll, &child_allocation);
 
443
        } else {
 
444
                if (GTK_WIDGET_MAPPED (widget)) {
 
445
                        if (GTK_WIDGET_MAPPED (self->up_scroll))
 
446
                                gtk_widget_unmap (self->up_scroll);
 
447
                        if (GTK_WIDGET_MAPPED (self->down_scroll))
 
448
                                gtk_widget_unmap (self->down_scroll);
 
449
                }
 
450
        }
 
451
 
 
452
        if (menu_shell->children) {
 
453
                child_allocation.x = (GTK_CONTAINER (menu)->border_width +
 
454
                                      widget->style->klass->xthickness);
 
455
                child_allocation.y = (GTK_CONTAINER (menu)->border_width +
 
456
                                      widget->style->klass->ythickness) - self->offset + top_scroller_height;
 
457
                child_allocation.width = MAX (1, (gint)allocation->width - child_allocation.x * 2);
 
458
 
 
459
                children = menu_shell->children;
 
460
                while (children) {
 
461
                        child = children->data;
 
462
                        children = children->next;
 
463
 
 
464
                        if (GTK_WIDGET_VISIBLE (child)) {
 
465
                                gtk_widget_get_child_requisition (child, &child_requisition);
 
466
 
 
467
                                child_allocation.height = child_requisition.height;
 
468
 
 
469
                                gtk_widget_size_allocate (child, &child_allocation);
 
470
                                gtk_widget_queue_draw (child);
 
471
 
 
472
                                child_allocation.y += child_allocation.height;
 
473
                        }
 
474
                }
 
475
        }
 
476
}
 
477
 
 
478
static void
 
479
scroll_menu_map (GtkWidget *widget)
 
480
{
 
481
        ScrollMenu *self = SCROLL_MENU (widget);
 
482
 
 
483
        if (GTK_WIDGET_CLASS (parent_class)->map)
 
484
                GTK_WIDGET_CLASS (parent_class)->map (widget);
 
485
 
 
486
        if (self->scroll) {
 
487
                if ( ! GTK_WIDGET_MAPPED (self->up_scroll))
 
488
                        gtk_widget_map (self->up_scroll);
 
489
                if ( ! GTK_WIDGET_MAPPED (self->down_scroll))
 
490
                        gtk_widget_map (self->down_scroll);
 
491
        }
 
492
 
 
493
}
 
494
 
 
495
static void
 
496
scroll_menu_unmap (GtkWidget *widget)
 
497
{
 
498
        ScrollMenu *self = SCROLL_MENU (widget);
 
499
 
 
500
        if (GTK_WIDGET_CLASS (parent_class)->unmap)
 
501
                GTK_WIDGET_CLASS (parent_class)->unmap (widget);
 
502
 
 
503
        if (GTK_WIDGET_MAPPED (self->up_scroll))
 
504
                gtk_widget_unmap (self->up_scroll);
 
505
        if (GTK_WIDGET_MAPPED (self->down_scroll))
 
506
                gtk_widget_unmap (self->down_scroll);
 
507
}
 
508
 
 
509
static void
 
510
adjust_item (ScrollMenu *self, GtkWidget *widget)
 
511
{
 
512
        GtkWidget *menu = GTK_WIDGET (self);
 
513
        GtkRequisition requisition;
 
514
        int top;
 
515
        int bottom;
 
516
        int move;
 
517
 
 
518
        if ( ! self->scroll)
 
519
                return;
 
520
 
 
521
        top = (GTK_CONTAINER (self)->border_width +
 
522
               menu->style->klass->ythickness);
 
523
 
 
524
        bottom = menu->allocation.height -
 
525
                (GTK_CONTAINER (self)->border_width +
 
526
                 menu->style->klass->ythickness);
 
527
 
 
528
        gtk_widget_get_child_requisition (self->up_scroll, &requisition);
 
529
        top += requisition.height;
 
530
 
 
531
        gtk_widget_get_child_requisition (self->down_scroll, &requisition);
 
532
        bottom -= requisition.height;
 
533
 
 
534
        move = 0;
 
535
 
 
536
        if (widget->allocation.y < top) {
 
537
                move = - (top - widget->allocation.y);
 
538
        } else if (widget->allocation.y + widget->allocation.height > bottom) {
 
539
                move = (widget->allocation.y +
 
540
                        widget->allocation.height -
 
541
                        bottom);
 
542
        }
 
543
 
 
544
        if (move != 0)
 
545
                scroll_by (self, move);
 
546
}
 
547
 
 
548
static void
 
549
scroll_menu_move_current (GtkMenuShell *menu_shell, GtkMenuDirectionType direction)
 
550
{
 
551
        GtkWidget *current_active = menu_shell->active_menu_item;
 
552
 
 
553
        if (GTK_MENU_SHELL_CLASS (parent_class)->move_current)
 
554
                GTK_MENU_SHELL_CLASS (parent_class)->move_current (menu_shell, direction);
 
555
 
 
556
        if (menu_shell->active_menu_item != NULL &&
 
557
            menu_shell->active_menu_item != current_active)
 
558
                adjust_item (SCROLL_MENU (menu_shell), menu_shell->active_menu_item);
 
559
}
 
560
 
 
561
static void
 
562
scroll_menu_remove (GtkContainer *container, GtkWidget *widget)
 
563
{
 
564
        ScrollMenu *self = SCROLL_MENU (container);
 
565
 
 
566
        if (self->up_scroll == widget) {
 
567
                gtk_widget_unref (self->up_scroll);
 
568
                self->up_scroll = NULL;
 
569
        } else if (self->down_scroll == widget) {
 
570
                gtk_widget_unref (self->down_scroll);
 
571
                self->down_scroll = NULL;
 
572
        } else if (GTK_CONTAINER_CLASS (parent_class)->remove) {
 
573
                GTK_CONTAINER_CLASS (parent_class)->remove (container, widget);
 
574
        }
 
575
}
 
576
 
 
577
static gboolean
 
578
scroll_menu_leave_notify (GtkWidget *widget, GdkEventCrossing *event)
 
579
{
 
580
        ScrollMenu *self = SCROLL_MENU (widget);
 
581
        GtkWidget *event_widget;
 
582
 
 
583
        event_widget = gtk_get_event_widget ((GdkEvent*) event);
 
584
 
 
585
        if (widget == event_widget ||
 
586
            widget == self->up_scroll ||
 
587
            widget == self->down_scroll) {
 
588
                if (self->in_up) {
 
589
                        scroll_leave_notify (self->up_scroll, event,
 
590
                                             GINT_TO_POINTER (SCROLL_UP));
 
591
                } else if (self->in_down) {
 
592
                        scroll_leave_notify (self->down_scroll, event,
 
593
                                             GINT_TO_POINTER (SCROLL_DOWN));
 
594
                }
 
595
        }
 
596
 
 
597
        if (GTK_WIDGET_CLASS (parent_class)->leave_notify_event)
 
598
                return GTK_WIDGET_CLASS (parent_class)->leave_notify_event (widget, event);
 
599
 
 
600
        return FALSE;
 
601
}
 
602
 
 
603
static gboolean
 
604
scroll_menu_enter_notify (GtkWidget *widget, GdkEventCrossing *event)
 
605
{
 
606
        ScrollMenu *self = SCROLL_MENU (widget);
 
607
        GtkWidget *event_widget;
 
608
 
 
609
        event_widget = gtk_get_event_widget ((GdkEvent*) event);
 
610
 
 
611
        if (self->up_scroll == event_widget) {
 
612
                return scroll_enter_notify (self->up_scroll, event,
 
613
                                            GINT_TO_POINTER (SCROLL_UP));
 
614
        } else if (self->down_scroll == event_widget) {
 
615
                return scroll_enter_notify (self->down_scroll, event,
 
616
                                            GINT_TO_POINTER (SCROLL_DOWN));
 
617
        }
 
618
 
 
619
        if (self->in_up) {
 
620
                GdkWindow *window = gdk_window_at_pointer (NULL, NULL);
 
621
                if (window != self->up_scroll->window)
 
622
                        scroll_leave_notify (self->up_scroll, event,
 
623
                                             GINT_TO_POINTER (SCROLL_UP));
 
624
        } else if (self->in_down) {
 
625
                GdkWindow *window = gdk_window_at_pointer (NULL, NULL);
 
626
                if (window != self->down_scroll->window)
 
627
                        scroll_leave_notify (self->down_scroll, event,
 
628
                                             GINT_TO_POINTER (SCROLL_DOWN));
 
629
        }
 
630
 
 
631
        
 
632
        if (GTK_WIDGET_CLASS (parent_class)->enter_notify_event)
 
633
                return GTK_WIDGET_CLASS (parent_class)->enter_notify_event (widget, event);
 
634
 
 
635
        return FALSE;
 
636
}
 
637
 
 
638
GtkWidget *
 
639
scroll_menu_new (void)
 
640
{
 
641
        return (GtkWidget *)gtk_type_new (scroll_menu_get_type ());
 
642
}