2 Copyright © 1995-2005, 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__ */
39 /****************************************************************************************/
41 /* On the Amiga tabcycling between member (string) gadgets of a group
42 gadget does not work at all -> freeze */
44 #define SUPPORT_TABCYCLE 1
46 #define IntuitionBase ((struct IntuitionBase *)(cl->cl_UserData))
48 /****************************************************************************************/
50 static void recalcgroupsize(Class
*cl
, struct Gadget
*g
)
52 struct GroupGData
*data
= INST_DATA(cl
, g
);
53 struct Gadget
*member
, *memberstate
;
54 WORD w
, h
, width
= 0/*g->Width*/, height
= 0/*g->Height*/;
56 memberstate
= (struct Gadget
*)data
->memberlist
.mlh_Head
;
57 while((member
= NextObject(&memberstate
)))
59 /* No "width - 1" / "height - 1" here! Coords of members are absolute here! */
61 w
= member
->LeftEdge
- g
->LeftEdge
+ member
->Width
;
62 h
= member
->TopEdge
- g
->TopEdge
+ member
->Height
;
64 if (w
> width
) width
= w
;
65 if (h
> height
) height
= h
;
72 /****************************************************************************************/
76 /****************************************************************************************/
78 struct Gadget
*next_tabcycleobject(Class
*cl
, struct Gadget
*g
)
80 struct GroupGData
*data
= INST_DATA(cl
, g
);
81 struct Gadget
*member
, *memberstate
, *actobj
;
82 struct Gadget
*rc
= NULL
;
84 actobj
= data
->activegad
;
86 memberstate
= (struct Gadget
*)data
->memberlist
.mlh_Head
;
87 while ((member
= NextObject(&memberstate
)))
89 if (member
== actobj
) break;
94 while ((member
= NextObject(&memberstate
)))
96 if ( (member
->Flags
& (GFLG_TABCYCLE
| GFLG_DISABLED
)) == GFLG_TABCYCLE
)
105 memberstate
= (struct Gadget
*)data
->memberlist
.mlh_Head
;
106 while ((member
= NextObject(&memberstate
)))
108 if (member
== actobj
) break;
110 if (member
->Flags
& GFLG_TABCYCLE
)
124 /****************************************************************************************/
126 struct Gadget
*prev_tabcycleobject(Class
*cl
, struct Gadget
*g
)
128 struct GroupGData
*data
= INST_DATA(cl
, g
);
129 struct Gadget
*member
, *memberstate
, *actobj
;
130 struct Gadget
*prevmember
= NULL
, *rc
= NULL
;
132 actobj
= data
->activegad
;
134 memberstate
= (struct Gadget
*)data
->memberlist
.mlh_Head
;
135 while ((member
= NextObject(&memberstate
)))
137 if (member
== actobj
)
139 if (prevmember
) rc
= prevmember
;
143 if ( (member
->Flags
& (GFLG_TABCYCLE
| GFLG_DISABLED
)) == GFLG_TABCYCLE
)
152 while ((member
= NextObject(&memberstate
)))
154 if (((struct Gadget
*)member
)->Flags
& GFLG_TABCYCLE
)
162 } /* if (member && !rc) */
168 /****************************************************************************************/
170 #endif /* SUPPORT_TABCYCLE */
172 /****************************************************************************************/
174 IPTR
GroupGClass__OM_NEW(Class
*cl
, Object
*obj
, struct opSet
*msg
)
176 struct GroupGData
*data
;
178 struct Gadget
*g
= (struct Gadget
*)DoSuperMethodA(cl
, obj
, (Msg
)msg
);
181 data
= INST_DATA(cl
, g
);
183 NEWLIST(&data
->memberlist
);
185 /* Width and height of group gadget is determined by members. No members -> 0 size */
194 /****************************************************************************************/
196 IPTR
GroupGClass__OM_SET(Class
*cl
, struct Gadget
*g
, struct opSet
*msg
)
198 struct GroupGData
*data
= INST_DATA(cl
, g
);
199 struct Gadget
*member
, *memberstate
;
200 WORD dx
, new_groupleft
, old_groupleft
= g
->LeftEdge
;
201 WORD dy
, new_grouptop
, old_grouptop
= g
->TopEdge
;
204 rc
= DoSuperMethodA(cl
, (Object
*)g
, (Msg
)msg
);
206 new_groupleft
= g
->LeftEdge
;
207 new_grouptop
= g
->TopEdge
;
209 dx
= new_groupleft
- old_groupleft
;
210 dy
= new_grouptop
- old_grouptop
;
215 struct TagItem tags
[3];
218 m
.ops_AttrList
= tags
;
219 m
.ops_GInfo
= msg
->ops_GInfo
;
221 tags
[0].ti_Tag
= GA_Left
;
222 tags
[1].ti_Tag
= GA_Top
;
223 tags
[2].ti_Tag
= TAG_DONE
;
225 memberstate
= (struct Gadget
*)data
->memberlist
.mlh_Head
;
226 while((member
= NextObject(&memberstate
)))
228 tags
[0].ti_Data
= member
->LeftEdge
+ dx
;
229 tags
[1].ti_Data
= member
->TopEdge
+ dy
;
230 DoMethodA((Object
*)member
, (Msg
)&m
);
233 } /* if (dx || dy) */
239 /****************************************************************************************/
241 IPTR
GroupGClass__OM_DISPOSE(Class
*cl
, struct Gadget
*g
, Msg msg
)
243 struct GroupGData
*data
= INST_DATA(cl
, g
);
245 /* Free all members */
249 struct Gadget
*member
, *memberstate
;
252 memberstate
= (struct Gadget
*)data
->memberlist
.mlh_Head
;
253 member
= NextObject(&memberstate
);
257 DoMethodA((Object
*)member
, (Msg
)&method
);
258 DisposeObject(member
);
261 DoSuperMethodA(cl
, (Object
*)g
, msg
);
266 /****************************************************************************************/
268 IPTR
GroupGClass__OM_ADDMEMBER(Class
*cl
, struct Gadget
*g
, struct opMember
*msg
)
270 struct GroupGData
*data
= INST_DATA(cl
, g
);
273 struct TagItem tags
[3];
276 m
.MethodID
= OM_ADDTAIL
;
277 m
.opat_List
= (struct List
*)&data
->memberlist
;
279 rc
= DoMethodA(msg
->opam_Object
, (Msg
)&m
);
281 /* Member gadget had its coords relative to group gadget.
282 Convert the coords to absolute coords. */
284 m2
.MethodID
= OM_SET
;
285 m2
.ops_AttrList
= tags
;
288 tags
[0].ti_Tag
= GA_Left
;
289 tags
[0].ti_Data
= ((struct Gadget
*)msg
->opam_Object
)->LeftEdge
+ g
->LeftEdge
;
290 tags
[1].ti_Tag
= GA_Top
;
291 tags
[1].ti_Data
= ((struct Gadget
*)msg
->opam_Object
)->TopEdge
+ g
->TopEdge
;
292 tags
[2].ti_Tag
= TAG_DONE
;
294 DoMethodA(msg
->opam_Object
, (Msg
)&m2
);
296 recalcgroupsize(cl
, g
);
301 /****************************************************************************************/
303 IPTR
GroupGClass__OM_REMMEMBER(Class
*cl
, struct Gadget
*g
, struct opMember
*msg
)
306 struct TagItem tags
[3];
308 STACKULONG method
= OM_REMOVE
;
310 rc
= DoMethodA(msg
->opam_Object
, (Msg
)&method
);
312 /* Member gadget had its coords absolute here.
313 Convert the coords back to relative coords. */
315 m2
.MethodID
= OM_SET
;
316 m2
.ops_AttrList
= tags
;
319 tags
[0].ti_Tag
= GA_Left
;
320 tags
[0].ti_Data
= ((struct Gadget
*)msg
->opam_Object
)->LeftEdge
- g
->LeftEdge
;
321 tags
[1].ti_Tag
= GA_Top
;
322 tags
[1].ti_Data
= ((struct Gadget
*)msg
->opam_Object
)->TopEdge
- g
->TopEdge
;
323 tags
[2].ti_Tag
= TAG_DONE
;
325 DoMethodA(msg
->opam_Object
, (Msg
)&m2
);
327 recalcgroupsize(cl
, g
);
332 /****************************************************************************************/
334 IPTR
GroupGClass__GM_HITTEST(Class
*cl
, struct Gadget
*g
, struct gpHitTest
*msg
)
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 GroupGData
*data
= INST_DATA(cl
, g
);
388 /* If someone activates us with ActivateGadget(), activegad will be NULL.
389 * In that case, activate the first object.
391 if (!data
->activegad
)
393 struct Gadget
*memberstate
= (struct Gadget
*)data
->memberlist
.mlh_Head
;
395 data
->activegad
= NextObject(&memberstate
);
400 /* gpi_Mouse coords are relative to group gadget. Make them relative
401 to activate object */
403 m
.gpi_Mouse
.X
= g
->LeftEdge
+ msg
->gpi_Mouse
.X
- data
->activegad
->LeftEdge
;
404 m
.gpi_Mouse
.Y
= g
->TopEdge
+ msg
->gpi_Mouse
.Y
- data
->activegad
->TopEdge
;
406 rc
= DoMethodA((Object
*)data
->activegad
, (Msg
)&m
);
410 struct Gadget
*newgad
= NULL
;
412 if (rc
& GMR_NEXTACTIVE
) newgad
= next_tabcycleobject(cl
, g
);
413 if (rc
& GMR_PREVACTIVE
) newgad
= prev_tabcycleobject(cl
, g
);
415 if (newgad
&& (newgad
!= data
->activegad
))
417 struct gpGoInactive im
;
419 /* Make old member gadget inactive */
421 im
.MethodID
= GM_GOINACTIVE
;
422 im
.gpgi_GInfo
= msg
->gpi_GInfo
;
423 im
.gpgi_Abort
= 0; /* The gadget itself wanted to be deactivated */
425 DoMethodA((Object
*)data
->activegad
, (Msg
)&im
);
427 /* Make new member gadget active */
429 data
->activegad
= newgad
;
431 m
.MethodID
= GM_GOACTIVE
;
432 m
.gpi_Mouse
.X
= g
->LeftEdge
+ msg
->gpi_Mouse
.X
- newgad
->LeftEdge
;
433 m
.gpi_Mouse
.Y
= g
->TopEdge
+ msg
->gpi_Mouse
.Y
- newgad
->TopEdge
;
435 rc
= DoMethodA((Object
*)newgad
, (Msg
)&m
);
445 /****************************************************************************************/
447 IPTR
GroupGClass__GM_GOINACTIVE(Class
*cl
, struct Gadget
*g
, struct gpGoInactive
*msg
)
449 struct GroupGData
*data
= INST_DATA(cl
, g
);
452 ASSERT_VALID_PTR(data
->activegad
);
454 rc
= DoMethodA((Object
*)data
->activegad
, (Msg
)msg
);
455 data
->activegad
= NULL
;
460 /****************************************************************************************/
462 IPTR
GroupGClass__GM_RENDER(Class
*cl
, struct Gadget
*g
, struct gpRender
*msg
)
464 struct GroupGData
*data
= INST_DATA(cl
, g
);
465 struct Gadget
*member
, *memberstate
;
467 memberstate
= (struct Gadget
*)data
->memberlist
.mlh_Head
;
468 while((member
= NextObject(&memberstate
)))
470 DoMethodA((Object
*)member
, (Msg
)msg
);
476 /****************************************************************************************/