Added memory-stored debug output to safe mode.
[cake.git] / workbench / libs / asl / buttonclass.c
blobdd00334b1d3731577fda6a4494f1c025a39bfb62
1 /*
2 Copyright © 1995-2005, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: english
7 */
9 #include <proto/exec.h>
10 #include <proto/dos.h>
11 #include <proto/utility.h>
12 #include <proto/intuition.h>
13 #include <proto/graphics.h>
14 #include <proto/cybergraphics.h>
15 #include <exec/memory.h>
16 #include <intuition/screens.h>
17 #include <intuition/icclass.h>
18 #include <intuition/cghooks.h>
19 #include <intuition/imageclass.h>
20 #include <intuition/gadgetclass.h>
21 #include <graphics/gfx.h>
22 #include <cybergraphx/cybergraphics.h>
24 #include <string.h>
26 #include "asl_intern.h"
27 #include "layout.h"
29 #if USE_SHARED_COOLIMAGES
30 #include <libraries/coolimages.h>
31 #else
32 #include "coolimages.h"
33 #endif
35 #define SDEBUG 0
36 #define DEBUG 0
38 #include <aros/debug.h>
40 #define CLASS_ASLBASE ((struct AslBase_intern *)cl->cl_UserData)
41 #define HOOK_ASLBASE ((struct AslBase_intern *)hook->h_Data)
43 #define AslBase CLASS_ASLBASE
45 /********************** ASL BUTTON CLASS **************************************************/
47 IPTR AslButton__OM_NEW(Class * cl, Object * o, struct opSet * msg)
49 struct AslButtonData *data;
50 struct TagItem fitags[] =
52 {IA_FrameType, FRAME_BUTTON},
53 {IA_EdgesOnly, TRUE },
54 {TAG_DONE, 0UL}
57 struct Gadget *g = (struct Gadget *)DoSuperMethodA(cl, o, (Msg)msg);
59 if (g)
61 data = INST_DATA(cl, g);
63 /* {GA_Image, whatever} means, a frame shall be created */
65 if (FindTagItem(GA_Image, msg->ops_AttrList))
67 if (g->GadgetText) fitags[1].ti_Tag = TAG_IGNORE;
68 data->frame = NewObjectA(NULL, FRAMEICLASS, fitags);
71 data->coolimage = (struct CoolImage *)GetTagData(ASLBT_CoolImage, 0, msg->ops_AttrList);
73 data->ld = (struct LayoutData *)GetTagData(GA_UserData, 0, msg->ops_AttrList);
75 if (!data->ld)
77 CoerceMethod(cl, (Object *)g, OM_DISPOSE);
78 g = NULL;
79 } else {
80 if (data->coolimage && data->ld->ld_TrueColor && CyberGfxBase)
82 #if SHARED_COOLIMAGES_LIBRARY
83 WORD numcols = data->coolimage->numcolors;
84 #else
85 WORD numcols = 1 << data->coolimage->depth;
86 #endif
88 if ((data->coolimagepal = AllocVec(numcols * sizeof(ULONG), MEMF_PUBLIC)))
90 ULONG *p = data->coolimagepal;
91 WORD i;
93 for(i = 0; i < numcols; i++)
95 *p++ = (data->coolimage->pal[i * 3] << 16) |
96 (data->coolimage->pal[i * 3 + 1] << 8) |
97 (data->coolimage->pal[i * 3 + 2]);
100 } else {
101 data->coolimage = NULL;
103 } else {
104 data->coolimage = NULL;
108 } /* if (g) */
110 return (IPTR)g;
113 /***********************************************************************************/
115 IPTR AslButton__OM_DISPOSE(Class * cl, Object * o, Msg msg)
117 struct AslButtonData *data;
118 IPTR retval;
120 data = INST_DATA(cl, o);
121 if (data->frame) DisposeObject(data->frame);
122 if (data->coolimagepal) FreeVec(data->coolimagepal);
124 retval = DoSuperMethodA(cl, o, msg);
126 return retval;
129 /***********************************************************************************/
131 IPTR AslButton__GM_HITTEST(Class *cl, struct Gadget *g, struct gpHitTest *msg)
133 WORD gadx, gady, gadw, gadh;
135 getgadgetcoords(g, msg->gpht_GInfo, &gadx, &gady, &gadw, &gadh);
137 return ((msg->gpht_Mouse.X >= 0) &&
138 (msg->gpht_Mouse.Y >= 0) &&
139 (msg->gpht_Mouse.X < gadw) &&
140 (msg->gpht_Mouse.Y < gadh)) ? GMR_GADGETHIT : 0;
143 /***********************************************************************************/
145 #if BUTTON_OWN_INPUT_HANDLING
147 /***********************************************************************************/
149 IPTR AslButton__GM_GOACTIVE(Class *cl, struct Gadget *g, struct gpInput *msg)
151 struct GadgetInfo *gi = msg->gpi_GInfo;
152 IPTR retval = GMR_NOREUSE;
154 if (gi)
156 struct RastPort *rp = ObtainGIRPort(gi);
158 if (rp)
160 g->Flags |= GFLG_SELECTED;
162 DoMethod((Object *)g, GM_RENDER, (IPTR) gi, (IPTR) rp, GREDRAW_REDRAW);
163 ReleaseGIRPort(rp);
165 retval = GMR_MEACTIVE;
169 return retval;
172 /***********************************************************************************/
174 IPTR AslButton__GM_HANDLEINPUT(Class *cl, struct Gadget *g, struct gpInput *msg)
176 struct GadgetInfo *gi = msg->gpi_GInfo;
177 IPTR retval = GMR_MEACTIVE;
179 if (gi)
181 struct InputEvent *ie = ((struct gpInput *)msg)->gpi_IEvent;
183 switch(ie->ie_Class)
185 case IECLASS_RAWMOUSE:
186 switch( ie->ie_Code )
188 case SELECTUP:
189 if( g->Flags & GFLG_SELECTED )
191 struct RastPort *rp;
193 /* mouse is over gadget */
194 g->Flags &= ~GFLG_SELECTED;
196 if ((rp = ObtainGIRPort(gi)))
198 DoMethod((Object *)g, GM_RENDER, (IPTR) gi, (IPTR) rp, GREDRAW_UPDATE);
199 ReleaseGIRPort(rp);
201 retval = GMR_NOREUSE | GMR_VERIFY;
202 *msg->gpi_Termination = IDCMP_GADGETUP;
204 else
206 retval = GMR_NOREUSE;
208 break;
210 case IECODE_NOBUTTON:
212 struct gpHitTest gpht;
214 gpht.MethodID = GM_HITTEST;
215 gpht.gpht_GInfo = gi;
216 gpht.gpht_Mouse.X = ((struct gpInput *)msg)->gpi_Mouse.X;
217 gpht.gpht_Mouse.Y = ((struct gpInput *)msg)->gpi_Mouse.Y;
220 This case handles selection state toggling when the
221 left button is depressed and the mouse is moved
222 around on/off the gadget bounds.
224 if ( DoMethodA((Object *)g, (Msg)&gpht) == GMR_GADGETHIT )
226 if ( (g->Flags & GFLG_SELECTED) == 0 )
228 struct RastPort *rp;
230 /* mouse is over gadget */
231 g->Flags |= GFLG_SELECTED;
233 if ((rp = ObtainGIRPort(gi)))
235 DoMethod((Object *)g, GM_RENDER, (IPTR) gi, (IPTR) rp, GREDRAW_UPDATE);
236 ReleaseGIRPort(rp);
240 else
242 if ( (g->Flags & GFLG_SELECTED) != 0 )
244 struct RastPort *rp;
246 /* mouse is not over gadget */
247 g->Flags &= ~GFLG_SELECTED;
249 if ((rp = ObtainGIRPort(gi)))
251 DoMethod((Object *)g, GM_RENDER, (IPTR) gi, (IPTR) rp, GREDRAW_UPDATE);
252 ReleaseGIRPort(rp);
256 break;
259 default:
260 retval = GMR_REUSE;
261 *((struct gpInput *)msg)->gpi_Termination = 0UL;
262 break;
264 } /* switch(ie->ie_Code) */
265 break;
267 } /* switch(ie->ie_Class) */
269 } /* if (gi) */
270 else
272 retval = GMR_NOREUSE;
275 return retval;
278 /***********************************************************************************/
280 IPTR AslButton__GM_GOINACTIVE(Class *cl, struct Gadget *g, struct gpGoInactive *msg)
282 struct GadgetInfo *gi = msg->gpgi_GInfo;
284 g->Flags &= ~GFLG_SELECTED;
286 if (gi)
288 struct RastPort *rp = ObtainGIRPort(gi);
290 if (rp)
292 DoMethod((Object *)g, GM_RENDER, (IPTR) gi, (IPTR) rp, GREDRAW_REDRAW);
293 ReleaseGIRPort(rp);
297 return 0;
300 /***********************************************************************************/
302 #else /* BUTTON_OWN_INPUT_HANDLING */
304 IPTR AslButton__GM_GOACTIVE(Class *cl, Object *o, Msg msg)
306 return DoSuperMethodA(cl, o, msg);
308 IPTR AslButton__GM_HANDLEINPUT(Class *cl, Object *o, Msg msg)
310 return DoSuperMethodA(cl, o, msg);
312 IPTR AslButton__GM_GOINACTIVE(Class *cl, Object *o, Msg msg)
314 return DoSuperMethodA(cl, o, msg);
317 #endif /* BUTTON_OWN_INPUT_HANDLING */
319 /***********************************************************************************/
321 IPTR AslButton__GM_RENDER(Class *cl, struct Gadget *g, struct gpRender *msg)
323 struct AslButtonData *data;
324 char *text = (STRPTR)g->GadgetText;
325 struct TagItem im_tags[] =
327 {IA_Width , 0 },
328 {IA_Height , 0 },
329 {TAG_DONE }
331 WORD x, y, w, h;
333 getgadgetcoords(g, msg->gpr_GInfo, &x, &y, &w, &h);
335 data = INST_DATA(cl, g);
337 if (data->frame)
339 im_tags[0].ti_Data = w;
340 im_tags[1].ti_Data = h;
342 SetAttrsA(data->frame, im_tags);
344 DrawImageState(msg->gpr_RPort,
345 (struct Image *)data->frame,
348 (!text || (g->Flags & GFLG_SELECTED)) ? IDS_SELECTED : IDS_NORMAL,
349 msg->gpr_GInfo->gi_DrInfo);
352 if (text)
354 WORD len = strlen(text);
355 WORD tx = x, ty = y;
357 SetFont(msg->gpr_RPort, data->ld->ld_Font);
359 if (data->coolimage)
361 tx += BORDERIMAGESPACINGX + data->coolimage->width + BORDERIMAGESPACINGX;
362 w -= (BORDERIMAGESPACINGX + data->coolimage->width + BORDERIMAGESPACINGX + BORDERIMAGESPACINGX);
365 tx += (w - TextLength(msg->gpr_RPort, text, len)) / 2;
366 ty += (h - msg->gpr_RPort->TxHeight) / 2 + msg->gpr_RPort->TxBaseline;
368 if (data->frame)
370 SetABPenDrMd(msg->gpr_RPort,
371 data->ld->ld_Dri->dri_Pens[(g->Flags & GFLG_SELECTED) ? FILLTEXTPEN : TEXTPEN],
373 JAM1);
375 else
377 #if AVOID_FLICKER
378 struct TextExtent te;
379 struct IBox obox, ibox;
381 getgadgetcoords(g, msg->gpr_GInfo, &obox.Left, &obox.Top, &obox.Width, &obox.Height);
383 TextExtent(msg->gpr_RPort, text, len, &te);
385 ibox.Width = te.te_Extent.MaxX - te.te_Extent.MinX + 1;
386 ibox.Height = te.te_Extent.MaxY - te.te_Extent.MinY + 1;
387 ibox.Left = te.te_Extent.MinX + tx;
388 ibox.Top = te.te_Extent.MinY + ty;
390 PaintBoxFrame(msg->gpr_RPort,
391 &obox,
392 &ibox,
393 data->ld->ld_Dri->dri_Pens[BACKGROUNDPEN],
394 AslBase);
396 #endif
397 SetABPenDrMd(msg->gpr_RPort,
398 data->ld->ld_Dri->dri_Pens[(g->Flags & GFLG_SELECTED) ? FILLTEXTPEN : TEXTPEN],
399 data->ld->ld_Dri->dri_Pens[BACKGROUNDPEN],
400 JAM2);
404 Move(msg->gpr_RPort, tx, ty);
405 Text(msg->gpr_RPort, text, len);
407 else
409 x += 3; w -= 6;
410 y += 3; h -= 6;
412 #if AVOID_FLICKER
413 if (data->frame)
415 struct IBox ibox, fbox;
417 getgadgetcoords(g, msg->gpr_GInfo, &fbox.Left, &fbox.Top, &fbox.Width, &fbox.Height);
419 ibox.Left = x;
420 ibox.Top = y;
421 ibox.Width = w;
422 ibox.Height = h;
424 PaintInnerFrame(msg->gpr_RPort,
425 data->ld->ld_Dri,
426 data->frame,
427 &fbox,
428 &ibox,
429 data->ld->ld_Dri->dri_Pens[BACKGROUNDPEN],
430 AslBase);
433 #endif
435 SetABPenDrMd(msg->gpr_RPort,
436 data->ld->ld_Dri->dri_Pens[(g->Flags & GFLG_SELECTED) ? FILLPEN : BACKGROUNDPEN],
438 JAM1);
440 RectFill(msg->gpr_RPort, x, y, x + w - 1, y + h - 1);
443 if (data->coolimage)
445 struct ColorMap *cm = msg->gpr_GInfo->gi_Screen->ViewPort.ColorMap;
446 ULONG bg[3];
448 GetRGB32(cm, data->ld->ld_Dri->dri_Pens[(g->Flags & GFLG_SELECTED) ? FILLPEN : BACKGROUNDPEN], 1, bg);
449 data->coolimagepal[0] = ((bg[0] & 0xFF000000) >> 8) + ((bg[1] & 0xFF000000) >> 16) + ((bg[2] & 0xFF000000) >> 24);
451 WriteLUTPixelArray((APTR)data->coolimage->data,
454 data->coolimage->width,
455 msg->gpr_RPort,
456 data->coolimagepal,
457 x + BORDERIMAGESPACINGX,
458 y + (h - data->coolimage->height) / 2,
459 data->coolimage->width,
460 data->coolimage->height,
461 CTABFMT_XRGB8);
465 return 0;
468 /***********************************************************************************/
470 IPTR AslButton__GM_LAYOUT(Class * cl, struct Gadget * g, struct gpLayout * msg)
472 struct AslButtonData *data;
473 IPTR retval;
474 WORD innerwidth;
475 WORD spacing;
476 WORD x;
478 data = INST_DATA(cl, g);
480 retval = DoSuperMethodA(cl, (Object *)g, (Msg)msg);
482 switch (g->GadgetID)
484 case ID_MAINBUTTON_OK:
485 case ID_MAINBUTTON_MIDDLELEFT:
486 case ID_MAINBUTTON_MIDDLERIGHT:
487 case ID_MAINBUTTON_CANCEL:
489 /* multiply width 16 for sub-pixel accuracy */
491 x = (data->ld->ld_WBorLeft + OUTERSPACINGX) * 16 + 8;
493 innerwidth = msg->gpl_GInfo->gi_Window->Width -
494 msg->gpl_GInfo->gi_Window->BorderLeft -
495 msg->gpl_GInfo->gi_Window->BorderRight -
496 OUTERSPACINGX * 2;
498 /* multiply width 16 for sub-pixel accuracy */
500 spacing = (innerwidth - data->ld->ld_ButWidth * data->ld->ld_NumButtons) * 16 /
501 (data->ld->ld_NumButtons - 1);
503 x += (g->GadgetID - ID_MAINBUTTON_OK) * (data->ld->ld_ButWidth * 16 + spacing);
504 g->LeftEdge = x / 16;
505 break;
508 return retval;
511 /***********************************************************************************/