Title.mui: minor code cleanup
[AROS.git] / workbench / libs / asl / buttonclass.c
blob73a47e93712e08cefb485f1a93985eb5a2dcbde1
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: english
7 */
9 #include <proto/alib.h>
10 #include <proto/exec.h>
11 #include <proto/dos.h>
12 #include <proto/utility.h>
13 #include <proto/intuition.h>
14 #include <proto/graphics.h>
15 #include <proto/cybergraphics.h>
16 #include <exec/memory.h>
17 #include <intuition/screens.h>
18 #include <intuition/icclass.h>
19 #include <intuition/cghooks.h>
20 #include <intuition/imageclass.h>
21 #include <intuition/gadgetclass.h>
22 #include <graphics/gfx.h>
23 #include <cybergraphx/cybergraphics.h>
25 #include <string.h>
27 #include "asl_intern.h"
28 #include "layout.h"
30 #if USE_SHARED_COOLIMAGES
31 #include <libraries/coolimages.h>
32 #else
33 #include "coolimages.h"
34 #endif
36 #define SDEBUG 0
37 #define DEBUG 0
39 #include <aros/debug.h>
41 #define CLASS_ASLBASE ((struct AslBase_intern *)cl->cl_UserData)
42 #define HOOK_ASLBASE ((struct AslBase_intern *)hook->h_Data)
44 #define AslBase CLASS_ASLBASE
46 /********************** ASL BUTTON CLASS **************************************************/
48 IPTR AslButton__OM_NEW(Class * cl, Object * o, struct opSet * msg)
50 struct AslButtonData *data;
51 struct TagItem fitags[] =
53 {IA_FrameType, FRAME_BUTTON},
54 {IA_EdgesOnly, TRUE },
55 {TAG_DONE, 0UL}
58 struct Gadget *g = (struct Gadget *)DoSuperMethodA(cl, o, (Msg)msg);
60 if (g)
62 data = INST_DATA(cl, g);
64 /* {GA_Image, whatever} means, a frame shall be created */
66 if (FindTagItem(GA_Image, msg->ops_AttrList))
68 if (g->GadgetText) fitags[1].ti_Tag = TAG_IGNORE;
69 data->frame = NewObjectA(NULL, FRAMEICLASS, fitags);
72 data->coolimage = (struct CoolImage *)GetTagData(ASLBT_CoolImage, 0, msg->ops_AttrList);
74 data->ld = (struct LayoutData *)GetTagData(GA_UserData, 0, msg->ops_AttrList);
76 if (!data->ld)
78 CoerceMethod(cl, (Object *)g, OM_DISPOSE);
79 g = NULL;
80 } else {
81 if (data->coolimage && data->ld->ld_TrueColor && CyberGfxBase)
83 #if SHARED_COOLIMAGES_LIBRARY
84 WORD numcols = data->coolimage->numcolors;
85 #else
86 WORD numcols = 1 << data->coolimage->depth;
87 #endif
89 if ((data->coolimagepal = AllocVec(numcols * sizeof(ULONG), MEMF_PUBLIC)))
91 ULONG *p = data->coolimagepal;
92 WORD i;
94 for(i = 0; i < numcols; i++)
96 *p++ = (data->coolimage->pal[i * 3] << 16) |
97 (data->coolimage->pal[i * 3 + 1] << 8) |
98 (data->coolimage->pal[i * 3 + 2]);
101 } else {
102 data->coolimage = NULL;
104 } else {
105 data->coolimage = NULL;
109 } /* if (g) */
111 return (IPTR)g;
114 /***********************************************************************************/
116 IPTR AslButton__OM_DISPOSE(Class * cl, Object * o, Msg msg)
118 struct AslButtonData *data;
119 IPTR retval;
121 data = INST_DATA(cl, o);
122 if (data->frame) DisposeObject(data->frame);
123 if (data->coolimagepal) FreeVec(data->coolimagepal);
125 retval = DoSuperMethodA(cl, o, msg);
127 return retval;
130 /***********************************************************************************/
132 IPTR AslButton__GM_HITTEST(Class *cl, struct Gadget *g, struct gpHitTest *msg)
134 WORD gadx, gady, gadw, gadh;
136 getgadgetcoords(g, msg->gpht_GInfo, &gadx, &gady, &gadw, &gadh);
138 return ((msg->gpht_Mouse.X >= 0) &&
139 (msg->gpht_Mouse.Y >= 0) &&
140 (msg->gpht_Mouse.X < gadw) &&
141 (msg->gpht_Mouse.Y < gadh)) ? GMR_GADGETHIT : 0;
144 /***********************************************************************************/
146 #if BUTTON_OWN_INPUT_HANDLING
148 /***********************************************************************************/
150 IPTR AslButton__GM_GOACTIVE(Class *cl, struct Gadget *g, struct gpInput *msg)
152 struct GadgetInfo *gi = msg->gpi_GInfo;
153 IPTR retval = GMR_NOREUSE;
155 if (gi)
157 struct RastPort *rp = ObtainGIRPort(gi);
159 if (rp)
161 g->Flags |= GFLG_SELECTED;
163 DoMethod((Object *)g, GM_RENDER, (IPTR) gi, (IPTR) rp, GREDRAW_REDRAW);
164 ReleaseGIRPort(rp);
166 retval = GMR_MEACTIVE;
170 return retval;
173 /***********************************************************************************/
175 IPTR AslButton__GM_HANDLEINPUT(Class *cl, struct Gadget *g, struct gpInput *msg)
177 struct GadgetInfo *gi = msg->gpi_GInfo;
178 IPTR retval = GMR_MEACTIVE;
180 if (gi)
182 struct InputEvent *ie = ((struct gpInput *)msg)->gpi_IEvent;
184 switch(ie->ie_Class)
186 case IECLASS_RAWMOUSE:
187 switch( ie->ie_Code )
189 case SELECTUP:
190 if( g->Flags & GFLG_SELECTED )
192 struct RastPort *rp;
194 /* mouse is over gadget */
195 g->Flags &= ~GFLG_SELECTED;
197 if ((rp = ObtainGIRPort(gi)))
199 DoMethod((Object *)g, GM_RENDER, (IPTR) gi, (IPTR) rp, GREDRAW_UPDATE);
200 ReleaseGIRPort(rp);
202 retval = GMR_NOREUSE | GMR_VERIFY;
203 *msg->gpi_Termination = IDCMP_GADGETUP;
205 else
207 retval = GMR_NOREUSE;
209 break;
211 case IECODE_NOBUTTON:
213 struct gpHitTest gpht;
215 gpht.MethodID = GM_HITTEST;
216 gpht.gpht_GInfo = gi;
217 gpht.gpht_Mouse.X = ((struct gpInput *)msg)->gpi_Mouse.X;
218 gpht.gpht_Mouse.Y = ((struct gpInput *)msg)->gpi_Mouse.Y;
221 This case handles selection state toggling when the
222 left button is depressed and the mouse is moved
223 around on/off the gadget bounds.
225 if ( DoMethodA((Object *)g, (Msg)&gpht) == GMR_GADGETHIT )
227 if ( (g->Flags & GFLG_SELECTED) == 0 )
229 struct RastPort *rp;
231 /* mouse is over gadget */
232 g->Flags |= GFLG_SELECTED;
234 if ((rp = ObtainGIRPort(gi)))
236 DoMethod((Object *)g, GM_RENDER, (IPTR) gi, (IPTR) rp, GREDRAW_UPDATE);
237 ReleaseGIRPort(rp);
241 else
243 if ( (g->Flags & GFLG_SELECTED) != 0 )
245 struct RastPort *rp;
247 /* mouse is not over gadget */
248 g->Flags &= ~GFLG_SELECTED;
250 if ((rp = ObtainGIRPort(gi)))
252 DoMethod((Object *)g, GM_RENDER, (IPTR) gi, (IPTR) rp, GREDRAW_UPDATE);
253 ReleaseGIRPort(rp);
257 break;
260 default:
261 retval = GMR_REUSE;
262 *((struct gpInput *)msg)->gpi_Termination = 0UL;
263 break;
265 } /* switch(ie->ie_Code) */
266 break;
268 } /* switch(ie->ie_Class) */
270 } /* if (gi) */
271 else
273 retval = GMR_NOREUSE;
276 return retval;
279 /***********************************************************************************/
281 IPTR AslButton__GM_GOINACTIVE(Class *cl, struct Gadget *g, struct gpGoInactive *msg)
283 struct GadgetInfo *gi = msg->gpgi_GInfo;
285 g->Flags &= ~GFLG_SELECTED;
287 if (gi)
289 struct RastPort *rp = ObtainGIRPort(gi);
291 if (rp)
293 DoMethod((Object *)g, GM_RENDER, (IPTR) gi, (IPTR) rp, GREDRAW_REDRAW);
294 ReleaseGIRPort(rp);
298 return 0;
301 /***********************************************************************************/
303 #else /* BUTTON_OWN_INPUT_HANDLING */
305 IPTR AslButton__GM_GOACTIVE(Class *cl, Object *o, Msg msg)
307 return DoSuperMethodA(cl, o, msg);
309 IPTR AslButton__GM_HANDLEINPUT(Class *cl, Object *o, Msg msg)
311 return DoSuperMethodA(cl, o, msg);
313 IPTR AslButton__GM_GOINACTIVE(Class *cl, Object *o, Msg msg)
315 return DoSuperMethodA(cl, o, msg);
318 #endif /* BUTTON_OWN_INPUT_HANDLING */
320 /***********************************************************************************/
322 IPTR AslButton__GM_RENDER(Class *cl, struct Gadget *g, struct gpRender *msg)
324 struct AslButtonData *data;
325 char *text = (STRPTR)g->GadgetText;
326 struct TagItem im_tags[] =
328 {IA_Width , 0 },
329 {IA_Height , 0 },
330 {TAG_DONE }
332 WORD x, y, w, h;
334 getgadgetcoords(g, msg->gpr_GInfo, &x, &y, &w, &h);
336 data = INST_DATA(cl, g);
338 if (data->frame)
340 im_tags[0].ti_Data = w;
341 im_tags[1].ti_Data = h;
343 SetAttrsA(data->frame, im_tags);
345 DrawImageState(msg->gpr_RPort,
346 (struct Image *)data->frame,
349 (!text || (g->Flags & GFLG_SELECTED)) ? IDS_SELECTED : IDS_NORMAL,
350 msg->gpr_GInfo->gi_DrInfo);
353 if (text)
355 WORD len = strlen(text);
356 WORD tx = x, ty = y;
358 SetFont(msg->gpr_RPort, data->ld->ld_Font);
360 if (data->coolimage)
362 tx += BORDERIMAGESPACINGX + data->coolimage->width + BORDERIMAGESPACINGX;
363 w -= (BORDERIMAGESPACINGX + data->coolimage->width + BORDERIMAGESPACINGX + BORDERIMAGESPACINGX);
366 tx += (w - TextLength(msg->gpr_RPort, text, len)) / 2;
367 ty += (h - msg->gpr_RPort->TxHeight) / 2 + msg->gpr_RPort->TxBaseline;
369 if (data->frame)
371 SetABPenDrMd(msg->gpr_RPort,
372 data->ld->ld_Dri->dri_Pens[(g->Flags & GFLG_SELECTED) ? FILLTEXTPEN : TEXTPEN],
374 JAM1);
376 else
378 #if AVOID_FLICKER
379 struct TextExtent te;
380 struct IBox obox, ibox;
382 getgadgetcoords(g, msg->gpr_GInfo, &obox.Left, &obox.Top, &obox.Width, &obox.Height);
384 TextExtent(msg->gpr_RPort, text, len, &te);
386 ibox.Width = te.te_Extent.MaxX - te.te_Extent.MinX + 1;
387 ibox.Height = te.te_Extent.MaxY - te.te_Extent.MinY + 1;
388 ibox.Left = te.te_Extent.MinX + tx;
389 ibox.Top = te.te_Extent.MinY + ty;
391 PaintBoxFrame(msg->gpr_RPort,
392 &obox,
393 &ibox,
394 data->ld->ld_Dri->dri_Pens[BACKGROUNDPEN],
395 AslBase);
397 #endif
398 SetABPenDrMd(msg->gpr_RPort,
399 data->ld->ld_Dri->dri_Pens[(g->Flags & GFLG_SELECTED) ? FILLTEXTPEN : TEXTPEN],
400 data->ld->ld_Dri->dri_Pens[BACKGROUNDPEN],
401 JAM2);
405 Move(msg->gpr_RPort, tx, ty);
406 Text(msg->gpr_RPort, text, len);
408 else
410 x += 3; w -= 6;
411 y += 3; h -= 6;
413 #if AVOID_FLICKER
414 if (data->frame)
416 struct IBox ibox, fbox;
418 getgadgetcoords(g, msg->gpr_GInfo, &fbox.Left, &fbox.Top, &fbox.Width, &fbox.Height);
420 ibox.Left = x;
421 ibox.Top = y;
422 ibox.Width = w;
423 ibox.Height = h;
425 PaintInnerFrame(msg->gpr_RPort,
426 data->ld->ld_Dri,
427 data->frame,
428 &fbox,
429 &ibox,
430 data->ld->ld_Dri->dri_Pens[BACKGROUNDPEN],
431 AslBase);
434 #endif
436 SetABPenDrMd(msg->gpr_RPort,
437 data->ld->ld_Dri->dri_Pens[(g->Flags & GFLG_SELECTED) ? FILLPEN : BACKGROUNDPEN],
439 JAM1);
441 RectFill(msg->gpr_RPort, x, y, x + w - 1, y + h - 1);
444 if (data->coolimage)
446 struct ColorMap *cm = msg->gpr_GInfo->gi_Screen->ViewPort.ColorMap;
447 ULONG bg[3];
449 GetRGB32(cm, data->ld->ld_Dri->dri_Pens[(g->Flags & GFLG_SELECTED) ? FILLPEN : BACKGROUNDPEN], 1, bg);
450 data->coolimagepal[0] = ((bg[0] & 0xFF000000) >> 8) + ((bg[1] & 0xFF000000) >> 16) + ((bg[2] & 0xFF000000) >> 24);
452 WriteLUTPixelArray((APTR)data->coolimage->data,
455 data->coolimage->width,
456 msg->gpr_RPort,
457 data->coolimagepal,
458 x + BORDERIMAGESPACINGX,
459 y + (h - data->coolimage->height) / 2,
460 data->coolimage->width,
461 data->coolimage->height,
462 CTABFMT_XRGB8);
466 return 0;
469 /***********************************************************************************/
471 IPTR AslButton__GM_LAYOUT(Class * cl, struct Gadget * g, struct gpLayout * msg)
473 struct AslButtonData *data;
474 IPTR retval;
475 WORD innerwidth;
476 WORD spacing;
477 WORD x;
479 data = INST_DATA(cl, g);
481 retval = DoSuperMethodA(cl, (Object *)g, (Msg)msg);
483 switch (g->GadgetID)
485 case ID_MAINBUTTON_OK:
486 case ID_MAINBUTTON_MIDDLELEFT:
487 case ID_MAINBUTTON_MIDDLERIGHT:
488 case ID_MAINBUTTON_CANCEL:
490 /* multiply width 16 for sub-pixel accuracy */
492 x = (data->ld->ld_WBorLeft + OUTERSPACINGX) * 16 + 8;
494 innerwidth = msg->gpl_GInfo->gi_Window->Width -
495 msg->gpl_GInfo->gi_Window->BorderLeft -
496 msg->gpl_GInfo->gi_Window->BorderRight -
497 OUTERSPACINGX * 2;
499 /* multiply width 16 for sub-pixel accuracy */
501 spacing = (innerwidth - data->ld->ld_ButWidth * data->ld->ld_NumButtons) * 16 /
502 (data->ld->ld_NumButtons - 1);
504 x += (g->GadgetID - ID_MAINBUTTON_OK) * (data->ld->ld_ButWidth * 16 + spacing);
505 g->LeftEdge = x / 16;
506 break;
509 return retval;
512 /***********************************************************************************/