Updated PCI IDs to latest snapshot.
[tangerine.git] / rom / intuition / groupgclass.c
blobdeb1077490e7fb6eed5cb64e92273f0358e40be3
1 /*
2 Copyright © 1995-2005, 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 #ifdef IntuitionBase
36 # undef IntuitionBase
37 #endif
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;
68 g->Width = width;
69 g->Height = height;
72 /****************************************************************************************/
74 #if SUPPORT_TABCYCLE
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;
92 if (member)
94 while ((member = NextObject(&memberstate)))
96 if ( (member->Flags & (GFLG_TABCYCLE | GFLG_DISABLED)) == GFLG_TABCYCLE )
98 rc = member;
99 break;
103 if (!member)
105 memberstate = (struct Gadget *)data->memberlist.mlh_Head;
106 while ((member = NextObject(&memberstate)))
108 if (member == actobj) break;
110 if (member->Flags & GFLG_TABCYCLE)
112 rc = member;
113 break;
117 } /* if (!rc) */
119 } /* if (member) */
121 return rc;
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;
140 break;
143 if ( (member->Flags & (GFLG_TABCYCLE | GFLG_DISABLED)) == GFLG_TABCYCLE )
145 prevmember = member;
149 if (member && !rc)
151 prevmember = NULL;
152 while ((member = NextObject(&memberstate)))
154 if (((struct Gadget *)member)->Flags & GFLG_TABCYCLE)
156 prevmember = member;
160 rc = prevmember;
162 } /* if (member && !rc) */
164 return 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);
179 if (g)
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 */
187 g->Width = 0;
188 g->Height = 0;
191 return (IPTR)g;
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;
202 IPTR rc;
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;
212 if (dx || dy)
214 struct opSet m;
215 struct TagItem tags[3];
217 m.MethodID = OM_SET;
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) */
235 return rc;
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 */
247 for(;;)
249 struct Gadget *member, *memberstate;
250 ULONG method;
252 memberstate = (struct Gadget *)data->memberlist.mlh_Head;
253 member = NextObject(&memberstate);
254 if (!member) break;
256 method = OM_REMOVE;
257 DoMethodA((Object *)member, (Msg)&method);
258 DisposeObject(member);
261 DoSuperMethodA(cl, (Object *)g, msg);
263 return 0;
266 /****************************************************************************************/
268 IPTR GroupGClass__OM_ADDMEMBER(Class *cl, struct Gadget *g, struct opMember *msg)
270 struct GroupGData *data = INST_DATA(cl, g);
271 struct opAddTail m;
272 struct opSet m2;
273 struct TagItem tags[3];
274 IPTR rc;
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;
286 m2.ops_GInfo = NULL;
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);
298 return rc;
301 /****************************************************************************************/
303 IPTR GroupGClass__OM_REMMEMBER(Class *cl, struct Gadget *g, struct opMember *msg)
305 struct opSet m2;
306 struct TagItem tags[3];
307 IPTR rc;
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;
317 m2.ops_GInfo = NULL;
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);
329 return rc;
332 /****************************************************************************************/
334 IPTR GroupGClass__GM_HITTEST(Class *cl, struct Gadget *g, struct gpHitTest *msg)
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 GroupGData *data = INST_DATA(cl, g);
385 struct gpInput m;
386 IPTR rc;
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);
398 m = *msg;
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);
408 #if SUPPORT_TABCYCLE
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);
440 #endif
442 return rc;
445 /****************************************************************************************/
447 IPTR GroupGClass__GM_GOINACTIVE(Class *cl, struct Gadget *g, struct gpGoInactive *msg)
449 struct GroupGData *data = INST_DATA(cl, g);
450 IPTR rc;
452 ASSERT_VALID_PTR(data->activegad);
454 rc = DoMethodA((Object *)data->activegad, (Msg)msg);
455 data->activegad = NULL;
457 return rc;
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);
473 return 0;
476 /****************************************************************************************/