Initial commit
[amiga/BoopsiListView.git] / ScrollButtonClass.c
1 /*
2 **      ScrollButtonClass.c
3 **
4 **      Copyright (C) 1998 Bernardo Innocenti
5 **
6 **      Use 4 chars wide TABs to read this file
7 **
8 **      Subclass of the buttongclass specialized for scroll buttons
9 */
10
11 #define USE_BUILTIN_MATH
12 #define INTUI_V36_NAMES_ONLY
13 #define __USE_SYSBASE
14 #define  CLIB_ALIB_PROTOS_H             /* Avoid dupe defs of boopsi funcs */
15
16
17 #include <intuition/gadgetclass.h>
18
19 #include <proto/intuition.h>
20
21
22 #ifdef __STORM__
23         #pragma header
24 #endif
25
26 #include "CompilerSpecific.h"
27 #include "Debug.h"
28 #include "BoopsiStubs.h"
29
30 #include "ScrollButtonClass.h"
31
32
33
34
35 /* Per object instance data */
36 struct ScrollButtonData
37 {
38         /* The number of ticks we still have to wait
39          * before sending any notification.
40          */
41         ULONG TickCounter;
42 };
43
44
45
46 /* Dispatcher function prototype (just to keep esigent compilers quiet) */
47
48 static ULONG HOOKCALL ScrollButtonDispatcher (
49         REG(a0, Class *cl),
50         REG(a2, struct Gadget *g),
51         REG(a1, struct gpInput *gpi));
52
53 static ULONG HOOKCALL ScrollButtonDispatcher (
54         REG(a0, Class *cl),
55         REG(a2, struct Gadget *g),
56         REG(a1, struct gpInput *gpi))
57
58 /* ScrollButton Class Dispatcher entrypoint.
59  * Handle boopsi messages.
60  */
61 {
62         struct ScrollButtonData *bd = (struct ScrollButtonData *) INST_DATA(cl, g);
63
64         switch (gpi->MethodID)
65         {
66                 case GM_GOACTIVE:
67                         /* May define an attribute to make delay configurable */
68                         bd->TickCounter = 3;
69
70                         /* Notify our target that we have initially hit. */
71                         NotifyAttrs ((Object *)g, gpi->gpi_GInfo, 0,
72                                 GA_ID,  g->GadgetID,
73                                 TAG_DONE);
74
75                         /* Send more input */
76                         return GMR_MEACTIVE;
77
78                 case GM_HANDLEINPUT:
79                 {
80                         struct RastPort *rp;
81                         ULONG retval = GMR_MEACTIVE;
82                         UWORD selected = 0;
83
84                         /* This also works with classic (non-boopsi) images. */
85                         if (PointInImage ((gpi->gpi_Mouse.X << 16) + (gpi->gpi_Mouse.Y), g->GadgetRender))
86                         {
87                                 /* We are hit */
88                                 selected = GFLG_SELECTED;
89                         }
90
91                         if (gpi->gpi_IEvent->ie_Class == IECLASS_RAWMOUSE && gpi->gpi_IEvent->ie_Code == SELECTUP)
92                         {
93                                 /* Gadgetup, time to go */
94                                 retval = GMR_NOREUSE;
95                                 /* Unselect the gadget on our way out... */
96                                 selected = 0;
97                         }
98                         else if (gpi->gpi_IEvent->ie_Class == IECLASS_TIMER)
99                         {
100                                 /* We got a tick.  Decrement counter, and if 0, send notify. */
101
102                                 if (bd->TickCounter)
103                                         bd->TickCounter--;
104                                 else if (selected)
105                                         /* Notify our target that we are still being hit */
106                                         NotifyAttrs ((Object *)g, gpi->gpi_GInfo, 0,
107                                                 GA_ID,  g->GadgetID,
108                                                 TAG_DONE);
109                         }
110
111                         if ((g->Flags & GFLG_SELECTED) != selected)
112                         {
113                                 /* Update changes in gadget render */
114                                 g->Flags ^= GFLG_SELECTED;
115                                 if (rp = ObtainGIRPort (gpi->gpi_GInfo))
116                                 {
117                                         DoMethod ((Object *) g, GM_RENDER, gpi->gpi_GInfo, rp, GREDRAW_UPDATE);
118                                         ReleaseGIRPort (rp);
119                                 }
120                         }
121                         return retval;
122                 }
123
124                 default:
125                         /* Super class handles everything else */
126                         return (DoSuperMethodA (cl, (Object *)g, (Msg) gpi));
127         }
128 }
129
130
131
132 Class *MakeScrollButtonClass (void)
133 {
134         Class *class;
135
136         if (class = MakeClass (NULL, BUTTONGCLASS, NULL, sizeof(struct ScrollButtonData), 0))
137                 class->cl_Dispatcher.h_Entry = (ULONG (*)()) ScrollButtonDispatcher;
138
139         return class;
140 }
141
142
143
144 BOOL FreeScrollButtonClass (Class *cl)
145 {
146         return (FreeClass (cl));
147 }