2 Copyright 1995-2011, 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 /***********************************************************************************/
45 static VOID
notifypressed(Class
*cl
, struct Gadget
*g
, struct GadgetInfo
*ginfo
, ULONG flags
)
47 struct opUpdate method
;
49 struct TagItem ntags
[] =
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
;
74 g
= (struct Gadget
*)DoSuperMethodA(cl
, o
, (Msg
)msg
);
77 ti
= FindTagItem(GA_Image
, msg
->ops_AttrList
);
80 struct Image
*im
= (struct Image
*)g
->GadgetRender
;
85 g
->Height
= im
->Height
;
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
;
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
);
113 struct Image
*im
= (struct Image
*)g
->GadgetRender
;
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
;
128 struct RastPort
*rp
= ObtainGIRPort(gi
);
132 DoMethod((Object
*)g
, GM_RENDER
, (IPTR
) gi
, (IPTR
) rp
, GREDRAW_REDRAW
);
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",
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)
167 if ((g
->Flags
& GFLG_GADGIMAGE
) == 0) /* not an image-button */
170 if ((g
->SelectRender
!= NULL
) && (g
->Flags
& GFLG_SELECTED
))
172 ((struct Border
*)g
->SelectRender
),
175 else if (g
->GadgetRender
!= NULL
)
177 ((struct Border
*)g
->GadgetRender
),
182 else /* GFLG_GADGIMAGE set */
186 if (g
->Activation
& (GACT_LEFTBORDER
|
192 if (msg
->gpr_GInfo
->gi_Window
->Flags
& (WFLG_WINDOWACTIVE
| WFLG_TOOLBOX
))
198 state
= IDS_INACTIVENORMAL
;
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! */
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! */
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
);
230 /*#warning Amiga buttongclass does not seem to render gadgetlabel at all*/
233 printgadgetlabel(cl
, (Object
*)g
, msg
, IntuitionBase
);
236 if ( g
->Flags
& GFLG_DISABLED
)
238 UWORD pattern
[] = { 0x8888, 0x2222 };
241 SetAPen( rp
, pens
[SHADOWPEN
] );
242 SetAfPt( rp
, pattern
, 1);
244 /* render disable pattern */
248 container
.Left
+ container
.Width
- 1,
249 container
.Top
+ container
.Height
- 1 );
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
;
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;
278 DEBUG_BUTTON(dprintf("buttong_hittest without customimage called\n");)
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
;
296 struct RastPort
*rp
= ObtainGIRPort(gi
);
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
);
312 /* Let's support toggleselect buttons too, for SnoopDos (DIE!),
313 * which creates gadtools buttons and sets the toggleselect flag
316 if (!(g
->Activation
& GACT_TOGGLESELECT
))
318 notifypressed(cl
, g
, gi
, OPUF_INTERIM
);
319 retval
= GMR_MEACTIVE
;
323 notifypressed(cl
, g
, gi
, 0);
324 retval
= GMR_NOREUSE
| GMR_VERIFY
;
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
;
343 struct InputEvent
*ie
= ((struct gpInput
*)msg
)->gpi_IEvent
;
345 switch( ie
->ie_Class
)
347 case IECLASS_RAWMOUSE
:
348 switch( ie
->ie_Code
)
351 if( g
->Flags
& GFLG_SELECTED
)
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
);
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
377 *msg
->gpi_Termination
= IDCMP_GADGETUP
;
380 retval
= GMR_NOREUSE
;
382 notifypressed(cl
, g
, gi
, 0);
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 )
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
);
425 if ( (g
->Flags
& GFLG_SELECTED
) != 0 )
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
);
453 *((struct gpInput
*)msg
)->gpi_Termination
= 0UL;
456 } /* switch( ie->ie_Code ) */
460 notifypressed(cl
, g
, msg
->gpi_GInfo
, OPUF_INTERIM
);
463 } /* switch( ie->ie_Class ) */
468 retval
= GMR_NOREUSE
;
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
;
487 struct RastPort
*rp
= ObtainGIRPort(gi
);
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
);
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
);
516 /***********************************************************************************/