2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 Copyright © 2001-2003, The MorphOS Development Team. All Rights Reserved.
7 /****************************************************************************************/
9 #include <exec/types.h>
12 #include <dos/dosextens.h>
14 #include <intuition/intuition.h>
15 #include <intuition/intuitionbase.h>
16 #include <intuition/classes.h>
17 #include <intuition/classusr.h>
18 #include <intuition/gadgetclass.h>
20 #include <utility/tagitem.h>
21 #include <utility/hooks.h>
23 #include <clib/macros.h>
25 #include <proto/exec.h>
26 #include <proto/intuition.h>
27 #include <proto/utility.h>
30 #include <aros/asmcall.h>
31 #include <proto/alib.h>
32 #include "intuition_intern.h"
33 #endif /* !__MORPHOS__ */
35 /****************************************************************************************/
37 /* On the Amiga tabcycling between member (string) gadgets of a group
38 gadget does not work at all -> freeze */
40 #define SUPPORT_TABCYCLE 1
42 /****************************************************************************************/
44 static void recalcgroupsize(Class
*cl
, struct Gadget
*g
)
46 struct IntuitionBase
*IntuitionBase
= (struct IntuitionBase
*)cl
->cl_UserData
;
47 struct GroupGData
*data
= INST_DATA(cl
, g
);
48 struct Gadget
*member
, *memberstate
;
49 WORD w
, h
, width
= 0/*g->Width*/, height
= 0/*g->Height*/;
51 memberstate
= (struct Gadget
*)data
->memberlist
.mlh_Head
;
52 while((member
= NextObject(&memberstate
)))
54 /* No "width - 1" / "height - 1" here! Coords of members are absolute here! */
56 w
= member
->LeftEdge
- g
->LeftEdge
+ member
->Width
;
57 h
= member
->TopEdge
- g
->TopEdge
+ member
->Height
;
59 if (w
> width
) width
= w
;
60 if (h
> height
) height
= h
;
67 /****************************************************************************************/
71 /****************************************************************************************/
73 struct Gadget
*next_tabcycleobject(Class
*cl
, struct Gadget
*g
)
75 struct IntuitionBase
*IntuitionBase
= (struct IntuitionBase
*)cl
->cl_UserData
;
76 struct GroupGData
*data
= INST_DATA(cl
, g
);
77 struct Gadget
*member
, *memberstate
, *actobj
;
78 struct Gadget
*rc
= NULL
;
80 actobj
= data
->activegad
;
82 memberstate
= (struct Gadget
*)data
->memberlist
.mlh_Head
;
83 while ((member
= NextObject(&memberstate
)))
85 if (member
== actobj
) break;
90 while ((member
= NextObject(&memberstate
)))
92 if ( (member
->Flags
& (GFLG_TABCYCLE
| GFLG_DISABLED
)) == GFLG_TABCYCLE
)
101 memberstate
= (struct Gadget
*)data
->memberlist
.mlh_Head
;
102 while ((member
= NextObject(&memberstate
)))
104 if (member
== actobj
) break;
106 if (member
->Flags
& GFLG_TABCYCLE
)
120 /****************************************************************************************/
122 struct Gadget
*prev_tabcycleobject(Class
*cl
, struct Gadget
*g
)
124 struct IntuitionBase
*IntuitionBase
= (struct IntuitionBase
*)cl
->cl_UserData
;
125 struct GroupGData
*data
= INST_DATA(cl
, g
);
126 struct Gadget
*member
, *memberstate
, *actobj
;
127 struct Gadget
*prevmember
= NULL
, *rc
= NULL
;
129 actobj
= data
->activegad
;
131 memberstate
= (struct Gadget
*)data
->memberlist
.mlh_Head
;
132 while ((member
= NextObject(&memberstate
)))
134 if (member
== actobj
)
136 if (prevmember
) rc
= prevmember
;
140 if ( (member
->Flags
& (GFLG_TABCYCLE
| GFLG_DISABLED
)) == GFLG_TABCYCLE
)
149 while ((member
= NextObject(&memberstate
)))
151 if (((struct Gadget
*)member
)->Flags
& GFLG_TABCYCLE
)
159 } /* if (member && !rc) */
165 /****************************************************************************************/
167 #endif /* SUPPORT_TABCYCLE */
169 /****************************************************************************************/
171 IPTR
GroupGClass__OM_NEW(Class
*cl
, Object
*obj
, struct opSet
*msg
)
173 struct GroupGData
*data
;
175 struct Gadget
*g
= (struct Gadget
*)DoSuperMethodA(cl
, obj
, (Msg
)msg
);
178 data
= INST_DATA(cl
, g
);
180 NEWLIST(&data
->memberlist
);
182 /* Width and height of group gadget is determined by members. No members -> 0 size */
191 /****************************************************************************************/
193 IPTR
GroupGClass__OM_SET(Class
*cl
, struct Gadget
*g
, struct opSet
*msg
)
195 struct IntuitionBase
*IntuitionBase
= (struct IntuitionBase
*)cl
->cl_UserData
;
196 struct GroupGData
*data
= INST_DATA(cl
, g
);
197 struct Gadget
*member
, *memberstate
;
198 WORD dx
, new_groupleft
, old_groupleft
= g
->LeftEdge
;
199 WORD dy
, new_grouptop
, old_grouptop
= g
->TopEdge
;
202 rc
= DoSuperMethodA(cl
, (Object
*)g
, (Msg
)msg
);
204 new_groupleft
= g
->LeftEdge
;
205 new_grouptop
= g
->TopEdge
;
207 dx
= new_groupleft
- old_groupleft
;
208 dy
= new_grouptop
- old_grouptop
;
213 struct TagItem tags
[3];
216 m
.ops_AttrList
= tags
;
217 m
.ops_GInfo
= msg
->ops_GInfo
;
219 tags
[0].ti_Tag
= GA_Left
;
220 tags
[1].ti_Tag
= GA_Top
;
221 tags
[2].ti_Tag
= TAG_DONE
;
223 memberstate
= (struct Gadget
*)data
->memberlist
.mlh_Head
;
224 while((member
= NextObject(&memberstate
)))
226 tags
[0].ti_Data
= member
->LeftEdge
+ dx
;
227 tags
[1].ti_Data
= member
->TopEdge
+ dy
;
228 DoMethodA((Object
*)member
, (Msg
)&m
);
231 } /* if (dx || dy) */
237 /****************************************************************************************/
239 IPTR
GroupGClass__OM_DISPOSE(Class
*cl
, struct Gadget
*g
, Msg msg
)
241 struct IntuitionBase
*IntuitionBase
= (struct IntuitionBase
*)cl
->cl_UserData
;
242 struct GroupGData
*data
= INST_DATA(cl
, g
);
244 /* Free all members */
248 struct Gadget
*member
, *memberstate
;
251 memberstate
= (struct Gadget
*)data
->memberlist
.mlh_Head
;
252 member
= NextObject(&memberstate
);
256 DoMethodA((Object
*)member
, (Msg
)&method
);
257 DisposeObject(member
);
260 DoSuperMethodA(cl
, (Object
*)g
, msg
);
265 /****************************************************************************************/
267 IPTR
GroupGClass__OM_ADDMEMBER(Class
*cl
, struct Gadget
*g
, struct opMember
*msg
)
269 struct GroupGData
*data
= INST_DATA(cl
, g
);
272 struct TagItem tags
[3];
275 m
.MethodID
= OM_ADDTAIL
;
276 m
.opat_List
= (struct List
*)&data
->memberlist
;
278 rc
= DoMethodA(msg
->opam_Object
, (Msg
)&m
);
280 /* Member gadget had its coords relative to group gadget.
281 Convert the coords to absolute coords. */
283 m2
.MethodID
= OM_SET
;
284 m2
.ops_AttrList
= tags
;
287 tags
[0].ti_Tag
= GA_Left
;
288 tags
[0].ti_Data
= ((struct Gadget
*)msg
->opam_Object
)->LeftEdge
+ g
->LeftEdge
;
289 tags
[1].ti_Tag
= GA_Top
;
290 tags
[1].ti_Data
= ((struct Gadget
*)msg
->opam_Object
)->TopEdge
+ g
->TopEdge
;
291 tags
[2].ti_Tag
= TAG_DONE
;
293 DoMethodA(msg
->opam_Object
, (Msg
)&m2
);
295 recalcgroupsize(cl
, g
);
300 /****************************************************************************************/
302 IPTR
GroupGClass__OM_REMMEMBER(Class
*cl
, struct Gadget
*g
, struct opMember
*msg
)
305 struct TagItem tags
[3];
307 STACKULONG method
= OM_REMOVE
;
309 rc
= DoMethodA(msg
->opam_Object
, (Msg
)&method
);
311 /* Member gadget had its coords absolute here.
312 Convert the coords back to relative coords. */
314 m2
.MethodID
= OM_SET
;
315 m2
.ops_AttrList
= tags
;
318 tags
[0].ti_Tag
= GA_Left
;
319 tags
[0].ti_Data
= ((struct Gadget
*)msg
->opam_Object
)->LeftEdge
- g
->LeftEdge
;
320 tags
[1].ti_Tag
= GA_Top
;
321 tags
[1].ti_Data
= ((struct Gadget
*)msg
->opam_Object
)->TopEdge
- g
->TopEdge
;
322 tags
[2].ti_Tag
= TAG_DONE
;
324 DoMethodA(msg
->opam_Object
, (Msg
)&m2
);
326 recalcgroupsize(cl
, g
);
331 /****************************************************************************************/
333 IPTR
GroupGClass__GM_HITTEST(Class
*cl
, struct Gadget
*g
, struct gpHitTest
*msg
)
335 struct IntuitionBase
*IntuitionBase
= (struct IntuitionBase
*)cl
->cl_UserData
;
336 struct GroupGData
*data
= INST_DATA(cl
, g
);
338 struct Gadget
*member
, *memberstate
;
344 /* gpht_Mouse.X/Y are relative to (group) gadget */
346 x
= msg
->gpht_Mouse
.X
+ g
->LeftEdge
;
347 y
= msg
->gpht_Mouse
.Y
+ g
->TopEdge
;
349 memberstate
= (struct Gadget
*)data
->memberlist
.mlh_Head
;
350 while((member
= NextObject(&memberstate
)))
352 if (!(member
->Flags
& GFLG_DISABLED
))
354 /* make mouse coords relative to member gadget */
356 m
.gpht_Mouse
.X
= x
- member
->LeftEdge
;
357 m
.gpht_Mouse
.Y
= y
- member
->TopEdge
;
359 if ((m
.gpht_Mouse
.X
>= 0) &&
360 (m
.gpht_Mouse
.Y
>= 0) &&
361 (m
.gpht_Mouse
.X
< member
->Width
) &&
362 (m
.gpht_Mouse
.Y
< member
->Height
))
364 rc
= DoMethodA((Object
*)member
, (Msg
)&m
);
365 if (rc
== GMR_GADGETHIT
)
367 data
->activegad
= member
;
373 } /* if (!(member->Flags & GFLG_DISABLED)) */
375 } /* while((member = NextObject(&memberstate))) */
380 /****************************************************************************************/
382 IPTR
GroupGClass__GM_HANDLEINPUT(Class
*cl
, struct Gadget
*g
, struct gpInput
*msg
)
384 struct IntuitionBase
*IntuitionBase
= (struct IntuitionBase
*)cl
->cl_UserData
;
385 struct GroupGData
*data
= INST_DATA(cl
, g
);
389 /* If someone activates us with ActivateGadget(), activegad will be NULL.
390 * In that case, activate the first object.
392 if (!data
->activegad
)
394 struct Gadget
*memberstate
= (struct Gadget
*)data
->memberlist
.mlh_Head
;
396 data
->activegad
= NextObject(&memberstate
);
401 /* gpi_Mouse coords are relative to group gadget. Make them relative
402 to activate object */
404 m
.gpi_Mouse
.X
= g
->LeftEdge
+ msg
->gpi_Mouse
.X
- data
->activegad
->LeftEdge
;
405 m
.gpi_Mouse
.Y
= g
->TopEdge
+ msg
->gpi_Mouse
.Y
- data
->activegad
->TopEdge
;
407 rc
= DoMethodA((Object
*)data
->activegad
, (Msg
)&m
);
411 struct Gadget
*newgad
= NULL
;
413 if (rc
& GMR_NEXTACTIVE
) newgad
= next_tabcycleobject(cl
, g
);
414 if (rc
& GMR_PREVACTIVE
) newgad
= prev_tabcycleobject(cl
, g
);
416 if (newgad
&& (newgad
!= data
->activegad
))
418 struct gpGoInactive im
;
420 /* Make old member gadget inactive */
422 im
.MethodID
= GM_GOINACTIVE
;
423 im
.gpgi_GInfo
= msg
->gpi_GInfo
;
424 im
.gpgi_Abort
= 0; /* The gadget itself wanted to be deactivated */
426 DoMethodA((Object
*)data
->activegad
, (Msg
)&im
);
428 /* Make new member gadget active */
430 data
->activegad
= newgad
;
432 m
.MethodID
= GM_GOACTIVE
;
433 m
.gpi_Mouse
.X
= g
->LeftEdge
+ msg
->gpi_Mouse
.X
- newgad
->LeftEdge
;
434 m
.gpi_Mouse
.Y
= g
->TopEdge
+ msg
->gpi_Mouse
.Y
- newgad
->TopEdge
;
436 rc
= DoMethodA((Object
*)newgad
, (Msg
)&m
);
446 /****************************************************************************************/
448 IPTR
GroupGClass__GM_GOINACTIVE(Class
*cl
, struct Gadget
*g
, struct gpGoInactive
*msg
)
450 struct GroupGData
*data
= INST_DATA(cl
, g
);
453 ASSERT_VALID_PTR(data
->activegad
);
455 rc
= DoMethodA((Object
*)data
->activegad
, (Msg
)msg
);
456 data
->activegad
= NULL
;
461 /****************************************************************************************/
463 IPTR
GroupGClass__GM_RENDER(Class
*cl
, struct Gadget
*g
, struct gpRender
*msg
)
465 struct IntuitionBase
*IntuitionBase
= (struct IntuitionBase
*)cl
->cl_UserData
;
466 struct GroupGData
*data
= INST_DATA(cl
, g
);
467 struct Gadget
*member
, *memberstate
;
469 memberstate
= (struct Gadget
*)data
->memberlist
.mlh_Head
;
470 while((member
= NextObject(&memberstate
)))
472 DoMethodA((Object
*)member
, (Msg
)msg
);
478 /****************************************************************************************/