2 Copyright 1995-2005, The AROS Development Team. All rights reserved.
3 Copyright 2001-2003, The MorphOS Development Team. All Rights Reserved.
6 AROS buttongclass implementation.
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>
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>
36 #include "intuition_intern.h"
37 #include <aros/asmcall.h>
38 #include <proto/alib.h>
40 #endif /* !__MORPHOS__ */
42 #define DEBUG_BUTTON(x) ;
43 /***********************************************************************************/
46 #define IntuitionBase ((struct IntuitionBase *)(cl->cl_UserData))
48 /***********************************************************************************/
50 static VOID
notifypressed(Class
*cl
, struct Gadget
*g
, struct GadgetInfo
*ginfo
, ULONG flags
)
52 struct opUpdate method
;
54 struct TagItem ntags
[] =
60 method
.MethodID
= OM_NOTIFY
;
61 method
.opu_AttrList
= ntags
;
62 method
.opu_GInfo
= ginfo
;
63 method
.opu_Flags
= flags
;
65 ntags
[0].ti_Data
= ((g
->Flags
& GFLG_SELECTED
) ? g
->GadgetID
: - g
->GadgetID
);
67 DoMethodA((Object
*)g
, (Msg
)&method
);
70 /***********************************************************************************/
72 IPTR
ButtonGClass__OM_NEW(Class
*cl
, Object
*o
, struct opSet
*msg
)
77 g
= (struct Gadget
*)DoSuperMethodA(cl
, o
, (Msg
)msg
);
80 ti
= FindTagItem(GA_Image
, msg
->ops_AttrList
);
83 struct Image
*im
= (struct Image
*)g
->GadgetRender
;
88 g
->Height
= im
->Height
;
96 /***********************************************************************************/
98 IPTR
ButtonGClass__OM_SET(Class
*cl
, struct Gadget
*g
, struct opSet
*msg
)
103 retval
= DoSuperMethodA(cl
, (Object
*)g
, (Msg
)msg
);
105 /* If we have been subclassed, OM_UPDATE should not cause a GM_RENDER
106 * because it would circumvent the subclass from fully overriding it.
107 * The check of cl == OCLASS(o) should fail if we have been
108 * subclassed, and we have gotten here via DoSuperMethodA().
111 ti
= FindTagItem(GA_Image
, msg
->ops_AttrList
);
114 struct Image
*im
= (struct Image
*)g
->GadgetRender
;
118 g
->Width
= im
->Width
;
119 g
->Height
= im
->Height
;
123 if ( retval
&& ( (msg
->MethodID
!= OM_UPDATE
) || (cl
== OCLASS(g
)) ) )
125 struct GadgetInfo
*gi
= msg
->ops_GInfo
;
129 struct RastPort
*rp
= ObtainGIRPort(gi
);
133 DoMethod((Object
*)g
, GM_RENDER
, (IPTR
) gi
, (IPTR
) rp
, GREDRAW_REDRAW
);
142 /***********************************************************************************/
144 IPTR
ButtonGClass__GM_RENDER(Class
*cl
, struct Gadget
*g
, struct gpRender
*msg
)
146 /* We will let the AROS gadgetclass test if it is safe to render */
147 if ( DoSuperMethodA(cl
, (Object
*)g
, (Msg
)msg
) != 0 && msg
->gpr_GInfo
)
149 UWORD
*pens
= msg
->gpr_GInfo
->gi_DrInfo
->dri_Pens
;
150 struct RastPort
*rp
= msg
->gpr_RPort
;
151 struct IBox container
;
153 SANITY_CHECKR(msg
->gpr_RPort
, 0)
155 /*dprintf("button_render: rp %p[%p] win %p[%p] req %p[%p] gi->rp %p[%p]\n",
157 msg->gpr_GInfo->gi_Window, msg->gpr_GInfo->gi_Window->WLayer,
158 msg->gpr_GInfo->gi_Requester, msg->gpr_GInfo->gi_Requester->ReqLayer,
159 msg->gpr_GInfo->gi_RastPort, msg->gpr_GInfo->gi_RastPort->Layer);*/
161 GetGadgetIBox((struct Gadget
*)g
, msg
->gpr_GInfo
, &container
);
163 if (container
.Width
<= 1 || container
.Height
<= 1)
166 if ((g
->Flags
& GFLG_GADGIMAGE
) == 0) /* not an image-button */
169 if ((g
->SelectRender
!= NULL
) && (g
->Flags
& GFLG_SELECTED
))
171 ((struct Border
*)g
->SelectRender
),
174 else if (g
->GadgetRender
!= NULL
)
176 ((struct Border
*)g
->GadgetRender
),
181 else /* GFLG_GADGIMAGE set */
185 if (g
->Activation
& (GACT_LEFTBORDER
|
191 if (msg
->gpr_GInfo
->gi_Window
->Flags
& (WFLG_WINDOWACTIVE
| WFLG_TOOLBOX
))
197 state
= IDS_INACTIVENORMAL
;
205 if ((g
->SelectRender
!= NULL
) &&
206 (g
->Flags
& GFLG_SELECTED
)) /* render selected image */
208 /* No centering of the image inside the gadget to be done! */
211 (struct Image
*)g
->SelectRender
,
212 container
.Left
, container
.Top
,
213 state
+ IDS_SELECTED
,
214 msg
->gpr_GInfo
->gi_DrInfo
);
216 else if ( g
->GadgetRender
!= NULL
) /* render normal image */
218 /* No centering of the image inside the gadget to be done! */
221 (struct Image
*)g
->GadgetRender
,
222 container
.Left
, container
.Top
,
223 state
+ ((g
->Flags
& GFLG_SELECTED
) ? IDS_SELECTED
: IDS_NORMAL
),
224 msg
->gpr_GInfo
->gi_DrInfo
);
229 /*#warning Amiga buttongclass does not seem to render gadgetlabel at all*/
232 printgadgetlabel(cl
, (Object
*)g
, msg
, IntuitionBase
);
235 if ( g
->Flags
& GFLG_DISABLED
)
237 UWORD pattern
[] = { 0x8888, 0x2222 };
240 SetAPen( rp
, pens
[SHADOWPEN
] );
241 SetAfPt( rp
, pattern
, 1);
243 /* render disable pattern */
247 container
.Left
+ container
.Width
- 1,
248 container
.Top
+ container
.Height
- 1 );
255 /***********************************************************************************/
257 IPTR
ButtonGClass__GM_HITTEST(Class
*cl
, struct Gadget
*g
, struct gpHitTest
* msg
)
259 struct Image
*image
= (struct Image
*)g
->GadgetRender
;
261 IPTR retval
= GMR_GADGETHIT
;
265 if (image
->Depth
== CUSTOMIMAGEDEPTH
)
267 struct impHitTest imph
;
269 imph
.MethodID
= IM_HITTEST
;
270 imph
.imp_Point
.X
= msg
->gpht_Mouse
.X
;
271 imph
.imp_Point
.Y
= msg
->gpht_Mouse
.Y
;
273 retval
= DoMethodA((Object
*)image
, (Msg
)&imph
) ? GMR_GADGETHIT
: 0;
277 DEBUG_BUTTON(dprintf("buttong_hittest without customimage called\n");)
284 /***********************************************************************************/
286 IPTR
ButtonGClass__GM_GOACTIVE(Class
* cl
, struct Gadget
* g
, struct gpInput
* msg
)
288 struct GadgetInfo
*gi
= msg
->gpi_GInfo
;
289 IPTR retval
= GMR_NOREUSE
;
294 struct RastPort
*rp
= ObtainGIRPort(gi
);
297 struct gpRender method
;
299 g
->Flags
^= GFLG_SELECTED
;
301 method
.MethodID
= GM_RENDER
;
302 method
.gpr_GInfo
= gi
;
303 method
.gpr_RPort
= rp
;
304 method
.gpr_Redraw
= GREDRAW_REDRAW
;
307 DoMethodA((Object
*)g
, (Msg
)&method
);
310 /* Let's support toggleselect buttons too, for SnoopDos (DIE!),
311 * which creates gadtools buttons and sets the toggleselect flag
314 if (!(g
->Activation
& GACT_TOGGLESELECT
))
316 notifypressed(cl
, g
, gi
, OPUF_INTERIM
);
317 retval
= GMR_MEACTIVE
;
321 notifypressed(cl
, g
, gi
, 0);
322 retval
= GMR_NOREUSE
| GMR_VERIFY
;
331 /***********************************************************************************/
333 IPTR
ButtonGClass__GM_HANDLEINPUT(Class
* cl
, struct Gadget
* g
, struct gpInput
* msg
)
335 struct GadgetInfo
*gi
= msg
->gpi_GInfo
;
336 IPTR retval
= GMR_MEACTIVE
;
340 struct InputEvent
*ie
= ((struct gpInput
*)msg
)->gpi_IEvent
;
342 switch( ie
->ie_Class
)
344 case IECLASS_RAWMOUSE
:
345 switch( ie
->ie_Code
)
348 if( g
->Flags
& GFLG_SELECTED
)
352 /* mouse is over gadget */
353 g
->Flags
&= ~GFLG_SELECTED
;
355 if ((rp
= ObtainGIRPort(gi
)))
357 struct gpRender method
;
359 method
.MethodID
= GM_RENDER
;
360 method
.gpr_GInfo
= gi
;
361 method
.gpr_RPort
= rp
;
362 method
.gpr_Redraw
= GREDRAW_UPDATE
;
364 DoMethodA((Object
*)g
, (Msg
)&method
);
369 retval
= GMR_NOREUSE
| GMR_VERIFY
;
370 /* This doesn't really make sense, as Termination will
371 * be sent in msg->Code. The original intuition puts
374 *msg
->gpi_Termination
= IDCMP_GADGETUP
;
377 retval
= GMR_NOREUSE
;
379 notifypressed(cl
, g
, gi
, 0);
382 case IECODE_NOBUTTON
:
384 struct gpHitTest gpht
;
386 gpht
.MethodID
= GM_HITTEST
;
387 gpht
.gpht_GInfo
= gi
;
388 gpht
.gpht_Mouse
.X
= ((struct gpInput
*)msg
)->gpi_Mouse
.X
;
389 gpht
.gpht_Mouse
.Y
= ((struct gpInput
*)msg
)->gpi_Mouse
.Y
;
392 This case handles selection state toggling when the
393 left button is depressed and the mouse is moved
394 around on/off the gadget bounds.
396 if ( DoMethodA((Object
*)g
, (Msg
)&gpht
) == GMR_GADGETHIT
)
398 if ( (g
->Flags
& GFLG_SELECTED
) == 0 )
402 /* mouse is over gadget */
403 g
->Flags
|= GFLG_SELECTED
;
405 if ((rp
= ObtainGIRPort(gi
)))
407 struct gpRender method
;
409 method
.MethodID
= GM_RENDER
;
410 method
.gpr_GInfo
= gi
;
411 method
.gpr_RPort
= rp
;
412 method
.gpr_Redraw
= GREDRAW_UPDATE
;
414 DoMethodA((Object
*)g
, (Msg
)&method
);
422 if ( (g
->Flags
& GFLG_SELECTED
) != 0 )
426 /* mouse is not over gadget */
427 g
->Flags
&= ~GFLG_SELECTED
;
429 if ((rp
= ObtainGIRPort(gi
)))
431 struct gpRender method
;
433 method
.MethodID
= GM_RENDER
;
434 method
.gpr_GInfo
= gi
;
435 method
.gpr_RPort
= rp
;
436 method
.gpr_Redraw
= GREDRAW_UPDATE
;
438 DoMethodA((Object
*)g
, (Msg
)&method
);
450 *((struct gpInput
*)msg
)->gpi_Termination
= 0UL;
453 } /* switch( ie->ie_Code ) */
457 notifypressed(cl
, g
, msg
->gpi_GInfo
, OPUF_INTERIM
);
460 } /* switch( ie->ie_Class ) */
465 retval
= GMR_NOREUSE
;
471 /***********************************************************************************/
473 IPTR
ButtonGClass__GM_GOINACTIVE(Class
* cl
, struct Gadget
*g
, struct gpGoInactive
* msg
)
475 struct GadgetInfo
*gi
= msg
->gpgi_GInfo
;
477 if (!(g
->Activation
& GACT_TOGGLESELECT
))
479 g
->Flags
&= ~GFLG_SELECTED
;
483 struct RastPort
*rp
= ObtainGIRPort(gi
);
487 struct gpRender method
;
488 struct opUpdate method2
;
490 method
.MethodID
= GM_RENDER
;
491 method
.gpr_GInfo
= gi
;
492 method
.gpr_RPort
= rp
;
493 method
.gpr_Redraw
= GREDRAW_REDRAW
;
495 DoMethodA((Object
*)g
, (Msg
)&method
);
499 method2
.MethodID
= OM_NOTIFY
;
500 method2
.opu_AttrList
= NULL
;
501 method2
.opu_GInfo
= gi
;
502 method2
.opu_Flags
= 0;
504 DoMethodA((Object
*)g
, (Msg
)&method2
);
512 /***********************************************************************************/