Minor fixes to comments.
[AROS.git] / rom / intuition / buttongclass.c
blob94232411898673df9c965b3d2ee8545e49f49e75
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$
6 AROS buttongclass implementation.
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>
19 #include <intuition/cghooks.h>
20 #include <intuition/icclass.h>
21 #include <intuition/imageclass.h>
23 #include <graphics/gfxbase.h>
24 #include <graphics/gfxmacros.h>
26 #include <utility/tagitem.h>
27 #include <utility/hooks.h>
29 #include <clib/macros.h>
30 #include <proto/exec.h>
31 #include <proto/intuition.h>
32 #include <proto/graphics.h>
33 #include <proto/utility.h>
35 #ifndef __MORPHOS__
36 #include "intuition_intern.h"
37 #include <aros/asmcall.h>
38 #include <proto/alib.h>
39 #include "gadgets.h"
40 #endif /* !__MORPHOS__ */
42 #define DEBUG_BUTTON(x) ;
43 /***********************************************************************************/
45 static VOID notifypressed(Class *cl, struct Gadget *g, struct GadgetInfo *ginfo, ULONG flags)
47 struct opUpdate method;
49 struct TagItem ntags[] =
51 { GA_ID , 0UL },
52 { TAG_DONE }
55 method.MethodID = OM_NOTIFY;
56 method.opu_AttrList = ntags;
57 method.opu_GInfo = ginfo;
58 method.opu_Flags = flags;
60 ntags[0].ti_Data = ((g->Flags & GFLG_SELECTED) ? g->GadgetID : - g->GadgetID);
62 DoMethodA((Object *)g, (Msg)&method);
65 /***********************************************************************************/
67 IPTR ButtonGClass__OM_NEW(Class *cl, Object *o, struct opSet *msg)
69 struct IntuitionBase *IntuitionBase = (struct IntuitionBase *)cl->cl_UserData;
70 struct Library *UtilityBase = GetPrivIBase(IntuitionBase)->UtilityBase;
71 struct TagItem *ti;
72 struct Gadget *g;
74 g = (struct Gadget *)DoSuperMethodA(cl, o, (Msg)msg);
75 if (g)
77 ti = FindTagItem(GA_Image, msg->ops_AttrList);
78 if (ti)
80 struct Image *im = (struct Image *)g->GadgetRender;
82 if (im)
84 g->Width = im->Width;
85 g->Height = im->Height;
87 };
90 return (IPTR)g;
93 /***********************************************************************************/
95 IPTR ButtonGClass__OM_SET(Class *cl, struct Gadget *g, struct opSet *msg)
97 struct IntuitionBase *IntuitionBase = (struct IntuitionBase *)cl->cl_UserData;
98 struct Library *UtilityBase = GetPrivIBase(IntuitionBase)->UtilityBase;
99 struct TagItem *ti;
100 IPTR retval;
102 retval = DoSuperMethodA(cl, (Object *)g, (Msg)msg);
104 /* If we have been subclassed, OM_UPDATE should not cause a GM_RENDER
105 * because it would circumvent the subclass from fully overriding it.
106 * The check of cl == OCLASS(o) should fail if we have been
107 * subclassed, and we have gotten here via DoSuperMethodA().
110 ti = FindTagItem(GA_Image, msg->ops_AttrList);
111 if (ti)
113 struct Image *im = (struct Image *)g->GadgetRender;
115 if (im)
117 g->Width = im->Width;
118 g->Height = im->Height;
122 if ( retval && ( (msg->MethodID != OM_UPDATE) || (cl == OCLASS(g)) ) )
124 struct GadgetInfo *gi = msg->ops_GInfo;
126 if (gi)
128 struct RastPort *rp = ObtainGIRPort(gi);
130 if (rp)
132 DoMethod((Object *)g, GM_RENDER, (IPTR) gi, (IPTR) rp, GREDRAW_REDRAW);
133 ReleaseGIRPort(rp);
138 return retval;
141 /***********************************************************************************/
143 IPTR ButtonGClass__GM_RENDER(Class *cl, struct Gadget *g, struct gpRender *msg)
145 struct IntuitionBase *IntuitionBase = (struct IntuitionBase *)cl->cl_UserData;
146 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
147 /* We will let the AROS gadgetclass test if it is safe to render */
148 if ( DoSuperMethodA(cl, (Object *)g, (Msg)msg) != 0 && msg->gpr_GInfo)
150 UWORD *pens = msg->gpr_GInfo->gi_DrInfo->dri_Pens;
151 struct RastPort *rp = msg->gpr_RPort;
152 struct IBox container;
154 SANITY_CHECKR(msg->gpr_RPort, 0)
156 /*dprintf("button_render: rp %p[%p] win %p[%p] req %p[%p] gi->rp %p[%p]\n",
157 rp, rp->Layer,
158 msg->gpr_GInfo->gi_Window, msg->gpr_GInfo->gi_Window->WLayer,
159 msg->gpr_GInfo->gi_Requester, msg->gpr_GInfo->gi_Requester->ReqLayer,
160 msg->gpr_GInfo->gi_RastPort, msg->gpr_GInfo->gi_RastPort->Layer);*/
162 GetGadgetIBox((struct Gadget *)g, msg->gpr_GInfo, &container);
164 if (container.Width <= 1 || container.Height <= 1)
165 return (IPTR)0;
167 if ((g->Flags & GFLG_GADGIMAGE) == 0) /* not an image-button */
169 /* draw border */
170 if ((g->SelectRender != NULL ) && (g->Flags & GFLG_SELECTED))
171 DrawBorder(rp,
172 ((struct Border *)g->SelectRender),
173 container.Left,
174 container.Top);
175 else if (g->GadgetRender != NULL)
176 DrawBorder(rp,
177 ((struct Border *)g->GadgetRender),
178 container.Left,
179 container.Top);
182 else /* GFLG_GADGIMAGE set */
184 ULONG state;
186 if (g->Activation & (GACT_LEFTBORDER |
187 GACT_TOPBORDER |
188 GACT_RIGHTBORDER |
189 GACT_BOTTOMBORDER |
190 GACT_BORDERSNIFF))
192 if (msg->gpr_GInfo->gi_Window->Flags & (WFLG_WINDOWACTIVE | WFLG_TOOLBOX))
194 state = IDS_NORMAL;
196 else
198 state = IDS_INACTIVENORMAL;
201 else
203 state = IDS_NORMAL;
206 if ((g->SelectRender != NULL) &&
207 (g->Flags & GFLG_SELECTED)) /* render selected image */
209 /* No centering of the image inside the gadget to be done! */
211 DrawImageState(rp,
212 (struct Image *)g->SelectRender,
213 container.Left, container.Top,
214 state + IDS_SELECTED,
215 msg->gpr_GInfo->gi_DrInfo );
217 else if ( g->GadgetRender != NULL ) /* render normal image */
219 /* No centering of the image inside the gadget to be done! */
221 DrawImageState(rp,
222 (struct Image *)g->GadgetRender,
223 container.Left, container.Top,
224 state + ((g->Flags & GFLG_SELECTED) ? IDS_SELECTED : IDS_NORMAL ),
225 msg->gpr_GInfo->gi_DrInfo);
229 #if 0
230 /*#warning Amiga buttongclass does not seem to render gadgetlabel at all*/
232 /* print label */
233 printgadgetlabel(cl, (Object *)g, msg, IntuitionBase);
234 #endif
236 if ( g->Flags & GFLG_DISABLED )
238 UWORD pattern[] = { 0x8888, 0x2222 };
240 SetDrMd( rp, JAM1 );
241 SetAPen( rp, pens[SHADOWPEN] );
242 SetAfPt( rp, pattern, 1);
244 /* render disable pattern */
245 RectFill(rp,
246 container.Left,
247 container.Top,
248 container.Left + container.Width - 1,
249 container.Top + container.Height - 1 );
253 return (IPTR)0;
256 /***********************************************************************************/
258 IPTR ButtonGClass__GM_HITTEST(Class *cl, struct Gadget *g, struct gpHitTest * msg)
260 struct Image *image = (struct Image *)g->GadgetRender;
262 IPTR retval = GMR_GADGETHIT;
264 if (image)
266 if (image->Depth == CUSTOMIMAGEDEPTH)
268 struct impHitTest imph;
270 imph.MethodID = IM_HITTEST;
271 imph.imp_Point.X = msg->gpht_Mouse.X;
272 imph.imp_Point.Y = msg->gpht_Mouse.Y;
274 retval = DoMethodA((Object *)image, (Msg)&imph) ? GMR_GADGETHIT : 0;
276 else
278 DEBUG_BUTTON(dprintf("buttong_hittest without customimage called\n");)
282 return retval;
285 /***********************************************************************************/
287 IPTR ButtonGClass__GM_GOACTIVE(Class * cl, struct Gadget * g, struct gpInput * msg)
289 struct IntuitionBase *IntuitionBase = (struct IntuitionBase *)cl->cl_UserData;
290 struct GadgetInfo *gi = msg->gpi_GInfo;
291 IPTR retval = GMR_NOREUSE;
294 if (gi)
296 struct RastPort *rp = ObtainGIRPort(gi);
297 if (rp)
299 struct gpRender method;
301 g->Flags ^= GFLG_SELECTED;
303 method.MethodID = GM_RENDER;
304 method.gpr_GInfo = gi;
305 method.gpr_RPort = rp;
306 method.gpr_Redraw = GREDRAW_REDRAW;
309 DoMethodA((Object *)g, (Msg)&method);
310 ReleaseGIRPort(rp);
312 /* Let's support toggleselect buttons too, for SnoopDos (DIE!),
313 * which creates gadtools buttons and sets the toggleselect flag
314 * afterwards (spit).
316 if (!(g->Activation & GACT_TOGGLESELECT))
318 notifypressed(cl, g, gi, OPUF_INTERIM);
319 retval = GMR_MEACTIVE;
321 else
323 notifypressed(cl, g, gi, 0);
324 retval = GMR_NOREUSE | GMR_VERIFY;
329 return retval;
333 /***********************************************************************************/
335 IPTR ButtonGClass__GM_HANDLEINPUT(Class * cl, struct Gadget * g, struct gpInput * msg)
337 struct IntuitionBase *IntuitionBase = (struct IntuitionBase *)cl->cl_UserData;
338 struct GadgetInfo *gi = msg->gpi_GInfo;
339 IPTR retval = GMR_MEACTIVE;
341 if (gi)
343 struct InputEvent *ie = ((struct gpInput *)msg)->gpi_IEvent;
345 switch( ie->ie_Class )
347 case IECLASS_RAWMOUSE:
348 switch( ie->ie_Code )
350 case SELECTUP:
351 if( g->Flags & GFLG_SELECTED )
353 struct RastPort *rp;
355 /* mouse is over gadget */
356 g->Flags &= ~GFLG_SELECTED;
358 if ((rp = ObtainGIRPort(gi)))
360 struct gpRender method;
362 method.MethodID = GM_RENDER;
363 method.gpr_GInfo = gi;
364 method.gpr_RPort = rp;
365 method.gpr_Redraw = GREDRAW_UPDATE;
367 DoMethodA((Object *)g, (Msg)&method);
369 ReleaseGIRPort(rp);
372 retval = GMR_NOREUSE | GMR_VERIFY;
373 /* This doesn't really make sense, as Termination will
374 * be sent in msg->Code. The original intuition puts
375 * junk here.
377 *msg->gpi_Termination = IDCMP_GADGETUP;
379 else
380 retval = GMR_NOREUSE;
382 notifypressed(cl, g, gi, 0);
383 break;
385 case IECODE_NOBUTTON:
387 struct gpHitTest gpht;
389 gpht.MethodID = GM_HITTEST;
390 gpht.gpht_GInfo = gi;
391 gpht.gpht_Mouse.X = ((struct gpInput *)msg)->gpi_Mouse.X;
392 gpht.gpht_Mouse.Y = ((struct gpInput *)msg)->gpi_Mouse.Y;
395 This case handles selection state toggling when the
396 left button is depressed and the mouse is moved
397 around on/off the gadget bounds.
399 if ( DoMethodA((Object *)g, (Msg)&gpht) == GMR_GADGETHIT )
401 if ( (g->Flags & GFLG_SELECTED) == 0 )
403 struct RastPort *rp;
405 /* mouse is over gadget */
406 g->Flags |= GFLG_SELECTED;
408 if ((rp = ObtainGIRPort(gi)))
410 struct gpRender method;
412 method.MethodID = GM_RENDER;
413 method.gpr_GInfo = gi;
414 method.gpr_RPort = rp;
415 method.gpr_Redraw = GREDRAW_UPDATE;
417 DoMethodA((Object *)g, (Msg)&method);
419 ReleaseGIRPort(rp);
423 else
425 if ( (g->Flags & GFLG_SELECTED) != 0 )
427 struct RastPort *rp;
429 /* mouse is not over gadget */
430 g->Flags &= ~GFLG_SELECTED;
432 if ((rp = ObtainGIRPort(gi)))
434 struct gpRender method;
436 method.MethodID = GM_RENDER;
437 method.gpr_GInfo = gi;
438 method.gpr_RPort = rp;
439 method.gpr_Redraw = GREDRAW_UPDATE;
441 DoMethodA((Object *)g, (Msg)&method);
443 ReleaseGIRPort(rp);
447 break;
449 } /**/
451 default:
452 retval = GMR_REUSE;
453 *((struct gpInput *)msg)->gpi_Termination = 0UL;
454 break;
456 } /* switch( ie->ie_Code ) */
457 break;
459 case IECLASS_TIMER:
460 notifypressed(cl, g, msg->gpi_GInfo, OPUF_INTERIM);
461 break;
463 } /* switch( ie->ie_Class ) */
465 } /* if (gi) */
466 else
468 retval = GMR_NOREUSE;
471 return retval;
474 /***********************************************************************************/
476 IPTR ButtonGClass__GM_GOINACTIVE(Class * cl, struct Gadget *g, struct gpGoInactive * msg)
478 struct IntuitionBase *IntuitionBase = (struct IntuitionBase *)cl->cl_UserData;
479 struct GadgetInfo *gi = msg->gpgi_GInfo;
481 if (!(g->Activation & GACT_TOGGLESELECT))
483 g->Flags &= ~GFLG_SELECTED;
485 if (gi)
487 struct RastPort *rp = ObtainGIRPort(gi);
489 if (rp)
491 struct gpRender method;
492 struct opUpdate method2;
494 method.MethodID = GM_RENDER;
495 method.gpr_GInfo = gi;
496 method.gpr_RPort = rp;
497 method.gpr_Redraw = GREDRAW_REDRAW;
499 DoMethodA((Object *)g, (Msg)&method);
501 ReleaseGIRPort(rp);
503 method2.MethodID = OM_NOTIFY;
504 method2.opu_AttrList = NULL;
505 method2.opu_GInfo = gi;
506 method2.opu_Flags = 0;
508 DoMethodA((Object *)g, (Msg)&method2);
513 return (IPTR)0;
516 /***********************************************************************************/