Belarusian
[AROS.git] / rom / intuition / buttongclass.c
blobacc0267516adf3a4ec1f78bd98fc73d5fa76d5ba
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$
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 #undef IntuitionBase
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[] =
56 { GA_ID , 0UL },
57 { TAG_DONE }
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)
74 struct TagItem *ti;
75 struct Gadget *g;
77 g = (struct Gadget *)DoSuperMethodA(cl, o, (Msg)msg);
78 if (g)
80 ti = FindTagItem(GA_Image, msg->ops_AttrList);
81 if (ti)
83 struct Image *im = (struct Image *)g->GadgetRender;
85 if (im)
87 g->Width = im->Width;
88 g->Height = im->Height;
90 };
93 return (IPTR)g;
96 /***********************************************************************************/
98 IPTR ButtonGClass__OM_SET(Class *cl, struct Gadget *g, struct opSet *msg)
100 struct TagItem *ti;
101 IPTR retval;
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);
112 if (ti)
114 struct Image *im = (struct Image *)g->GadgetRender;
116 if (im)
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;
127 if (gi)
129 struct RastPort *rp = ObtainGIRPort(gi);
131 if (rp)
133 DoMethod((Object *)g, GM_RENDER, (IPTR) gi, (IPTR) rp, GREDRAW_REDRAW);
134 ReleaseGIRPort(rp);
139 return retval;
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",
156 rp, rp->Layer,
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)
164 return (IPTR)0;
166 if ((g->Flags & GFLG_GADGIMAGE) == 0) /* not an image-button */
168 /* draw border */
169 if ((g->SelectRender != NULL ) && (g->Flags & GFLG_SELECTED))
170 DrawBorder(rp,
171 ((struct Border *)g->SelectRender),
172 container.Left,
173 container.Top);
174 else if (g->GadgetRender != NULL)
175 DrawBorder(rp,
176 ((struct Border *)g->GadgetRender),
177 container.Left,
178 container.Top);
181 else /* GFLG_GADGIMAGE set */
183 ULONG state;
185 if (g->Activation & (GACT_LEFTBORDER |
186 GACT_TOPBORDER |
187 GACT_RIGHTBORDER |
188 GACT_BOTTOMBORDER |
189 GACT_BORDERSNIFF))
191 if (msg->gpr_GInfo->gi_Window->Flags & (WFLG_WINDOWACTIVE | WFLG_TOOLBOX))
193 state = IDS_NORMAL;
195 else
197 state = IDS_INACTIVENORMAL;
200 else
202 state = IDS_NORMAL;
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! */
210 DrawImageState(rp,
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! */
220 DrawImageState(rp,
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);
228 #if 0
229 /*#warning Amiga buttongclass does not seem to render gadgetlabel at all*/
231 /* print label */
232 printgadgetlabel(cl, (Object *)g, msg, IntuitionBase);
233 #endif
235 if ( g->Flags & GFLG_DISABLED )
237 UWORD pattern[] = { 0x8888, 0x2222 };
239 SetDrMd( rp, JAM1 );
240 SetAPen( rp, pens[SHADOWPEN] );
241 SetAfPt( rp, pattern, 1);
243 /* render disable pattern */
244 RectFill(rp,
245 container.Left,
246 container.Top,
247 container.Left + container.Width - 1,
248 container.Top + container.Height - 1 );
252 return (IPTR)0;
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;
263 if (image)
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;
275 else
277 DEBUG_BUTTON(dprintf("buttong_hittest without customimage called\n");)
281 return retval;
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;
292 if (gi)
294 struct RastPort *rp = ObtainGIRPort(gi);
295 if (rp)
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);
308 ReleaseGIRPort(rp);
310 /* Let's support toggleselect buttons too, for SnoopDos (DIE!),
311 * which creates gadtools buttons and sets the toggleselect flag
312 * afterwards (spit).
314 if (!(g->Activation & GACT_TOGGLESELECT))
316 notifypressed(cl, g, gi, OPUF_INTERIM);
317 retval = GMR_MEACTIVE;
319 else
321 notifypressed(cl, g, gi, 0);
322 retval = GMR_NOREUSE | GMR_VERIFY;
327 return retval;
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;
338 if (gi)
340 struct InputEvent *ie = ((struct gpInput *)msg)->gpi_IEvent;
342 switch( ie->ie_Class )
344 case IECLASS_RAWMOUSE:
345 switch( ie->ie_Code )
347 case SELECTUP:
348 if( g->Flags & GFLG_SELECTED )
350 struct RastPort *rp;
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);
366 ReleaseGIRPort(rp);
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
372 * junk here.
374 *msg->gpi_Termination = IDCMP_GADGETUP;
376 else
377 retval = GMR_NOREUSE;
379 notifypressed(cl, g, gi, 0);
380 break;
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 )
400 struct RastPort *rp;
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);
416 ReleaseGIRPort(rp);
420 else
422 if ( (g->Flags & GFLG_SELECTED) != 0 )
424 struct RastPort *rp;
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);
440 ReleaseGIRPort(rp);
444 break;
446 } /**/
448 default:
449 retval = GMR_REUSE;
450 *((struct gpInput *)msg)->gpi_Termination = 0UL;
451 break;
453 } /* switch( ie->ie_Code ) */
454 break;
456 case IECLASS_TIMER:
457 notifypressed(cl, g, msg->gpi_GInfo, OPUF_INTERIM);
458 break;
460 } /* switch( ie->ie_Class ) */
462 } /* if (gi) */
463 else
465 retval = GMR_NOREUSE;
468 return retval;
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;
481 if (gi)
483 struct RastPort *rp = ObtainGIRPort(gi);
485 if (rp)
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);
497 ReleaseGIRPort(rp);
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);
509 return (IPTR)0;
512 /***********************************************************************************/