Minor fixes to comments.
[AROS.git] / rom / intuition / groupgclass.c
blob00f088cc25041d82f97c0b4c7e0a69cf82fd2b62
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 Copyright © 2001-2003, The MorphOS Development Team. All Rights Reserved.
4 $Id$
5 */
7 /****************************************************************************************/
9 #include <exec/types.h>
11 #include <dos/dos.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>
29 #ifndef __MORPHOS__
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;
63 g->Width = width;
64 g->Height = height;
67 /****************************************************************************************/
69 #if SUPPORT_TABCYCLE
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;
88 if (member)
90 while ((member = NextObject(&memberstate)))
92 if ( (member->Flags & (GFLG_TABCYCLE | GFLG_DISABLED)) == GFLG_TABCYCLE )
94 rc = member;
95 break;
99 if (!member)
101 memberstate = (struct Gadget *)data->memberlist.mlh_Head;
102 while ((member = NextObject(&memberstate)))
104 if (member == actobj) break;
106 if (member->Flags & GFLG_TABCYCLE)
108 rc = member;
109 break;
113 } /* if (!rc) */
115 } /* if (member) */
117 return rc;
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;
137 break;
140 if ( (member->Flags & (GFLG_TABCYCLE | GFLG_DISABLED)) == GFLG_TABCYCLE )
142 prevmember = member;
146 if (member && !rc)
148 prevmember = NULL;
149 while ((member = NextObject(&memberstate)))
151 if (((struct Gadget *)member)->Flags & GFLG_TABCYCLE)
153 prevmember = member;
157 rc = prevmember;
159 } /* if (member && !rc) */
161 return 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);
176 if (g)
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 */
184 g->Width = 0;
185 g->Height = 0;
188 return (IPTR)g;
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;
200 IPTR rc;
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;
210 if (dx || dy)
212 struct opSet m;
213 struct TagItem tags[3];
215 m.MethodID = OM_SET;
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) */
233 return rc;
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 */
246 for(;;)
248 struct Gadget *member, *memberstate;
249 ULONG method;
251 memberstate = (struct Gadget *)data->memberlist.mlh_Head;
252 member = NextObject(&memberstate);
253 if (!member) break;
255 method = OM_REMOVE;
256 DoMethodA((Object *)member, (Msg)&method);
257 DisposeObject(member);
260 DoSuperMethodA(cl, (Object *)g, msg);
262 return 0;
265 /****************************************************************************************/
267 IPTR GroupGClass__OM_ADDMEMBER(Class *cl, struct Gadget *g, struct opMember *msg)
269 struct GroupGData *data = INST_DATA(cl, g);
270 struct opAddTail m;
271 struct opSet m2;
272 struct TagItem tags[3];
273 IPTR rc;
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;
285 m2.ops_GInfo = NULL;
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);
297 return rc;
300 /****************************************************************************************/
302 IPTR GroupGClass__OM_REMMEMBER(Class *cl, struct Gadget *g, struct opMember *msg)
304 struct opSet m2;
305 struct TagItem tags[3];
306 IPTR rc;
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;
316 m2.ops_GInfo = NULL;
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);
328 return rc;
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);
337 struct gpHitTest m;
338 struct Gadget *member, *memberstate;
339 WORD x, y;
340 IPTR rc = 0;
342 m = *msg;
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;
368 break;
373 } /* if (!(member->Flags & GFLG_DISABLED)) */
375 } /* while((member = NextObject(&memberstate))) */
377 return rc;
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);
386 struct gpInput m;
387 IPTR rc;
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);
399 m = *msg;
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);
409 #if SUPPORT_TABCYCLE
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);
441 #endif
443 return rc;
446 /****************************************************************************************/
448 IPTR GroupGClass__GM_GOINACTIVE(Class *cl, struct Gadget *g, struct gpGoInactive *msg)
450 struct GroupGData *data = INST_DATA(cl, g);
451 IPTR rc;
453 ASSERT_VALID_PTR(data->activegad);
455 rc = DoMethodA((Object *)data->activegad, (Msg)msg);
456 data->activegad = NULL;
458 return rc;
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);
475 return 0;
478 /****************************************************************************************/