Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / libs / gadtools / mxclass.c
blob8b76f0af780241171bbd5fa63fe329e4a255fd67
1 /*
2 Copyright © 1995-2005, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Internal GadTools mx class.
6 Lang: English
7 */
10 #include <proto/exec.h>
11 #include <exec/libraries.h>
12 #include <exec/memory.h>
13 #include <proto/dos.h>
14 #include <intuition/classes.h>
15 #include <intuition/classusr.h>
16 #include <intuition/gadgetclass.h>
17 #include <intuition/imageclass.h>
18 #include <intuition/intuition.h>
19 #include <intuition/cghooks.h>
20 #include <graphics/rastport.h>
21 #include <graphics/text.h>
22 #include <utility/tagitem.h>
23 #include <devices/inputevent.h>
24 #include <proto/alib.h>
25 #include <proto/utility.h>
26 #include <gadgets/arosmx.h>
28 #include <string.h> /* memset() */
30 #define SDEBUG 0
31 #define DEBUG 0
32 #include <aros/debug.h>
34 #include "gadtools_intern.h"
36 /**********************************************************************************************/
38 #define GadToolsBase ((struct GadToolsBase_intern *)cl->cl_UserData)
40 /**********************************************************************************************/
42 STATIC VOID mx_setnew(Class *cl, Object *o, struct opSet *msg)
44 struct MXData *data = INST_DATA(cl, o);
45 struct TagItem *tag;
46 struct TagItem *taglist = msg->ops_AttrList;
48 while ((tag = NextTagItem(&taglist)))
50 switch (tag->ti_Tag)
52 case GA_DrawInfo:
53 data->dri = (struct DrawInfo *) tag->ti_Data;
54 break;
56 case GA_TextAttr:
57 data->tattr = (struct TextAttr *) tag->ti_Data;
58 break;
60 case GA_LabelPlace:
61 data->labelplace = (LONG) tag->ti_Data;
62 break;
64 case GTMX_Active:
65 data->active = tag->ti_Data;
66 break;
68 case GTMX_Labels:
69 data->labels = (STRPTR *) tag->ti_Data;
70 data->numlabels = 0;
71 while (data->labels[data->numlabels])
72 data->numlabels++;
73 break;
75 case GTMX_Spacing:
76 data->spacing = tag->ti_Data;
77 break;
79 case GTMX_TickLabelPlace:
80 data->ticklabelplace = (LONG) tag->ti_Data;
81 break;
86 /**********************************************************************************************/
88 IPTR GTMX__OM_NEW(Class *cl, Object *objcl, struct opSet *msg)
90 struct MXData *data;
91 struct TagItem tags[] =
93 {IA_Width , 0 },
94 {IA_Height , 0 },
95 {SYSIA_DrawInfo , (IPTR) NULL },
96 {SYSIA_Which , MXIMAGE },
97 {TAG_DONE , 0L }
99 struct Gadget *g;
101 g = (struct Gadget *) DoSuperMethodA(cl, objcl, (Msg)msg);
102 if (!g)
103 return (IPTR)NULL;
105 g->Activation = GACT_IMMEDIATE;
107 data = INST_DATA(cl, g);
109 data->dri = NULL;
110 data->tattr = NULL;
111 data->active = 0;
112 data->labels = NULL;
113 data->spacing = 1;
114 data->labelplace = GV_LabelPlace_Above;
115 data->ticklabelplace = GV_LabelPlace_Right;
117 mx_setnew(cl, (Object *)g, msg);
119 if (data->tattr)
120 data->font = OpenFont(data->tattr);
122 /* Calculate fontheight */
123 if (data->tattr)
124 data->fontheight = data->tattr->ta_YSize;
125 else if ((g->Flags & GFLG_LABELITEXT) && (g->GadgetText))
126 data->fontheight = g->GadgetText->ITextFont->ta_YSize;
127 else
128 data->fontheight = g->Height;
130 /* Calculate gadget size */
131 if (g->Width == 0)
132 g->Width = MX_WIDTH;
134 g->Height = (data->fontheight + data->spacing) *data->numlabels -
135 data->spacing;
137 tags[0].ti_Data = g->Width;
138 tags[1].ti_Data = GetTagData(GTMX_TickHeight, MX_HEIGHT, msg->ops_AttrList);
139 tags[2].ti_Data = (IPTR) data->dri;
140 data->mximage = (struct Image *) NewObjectA(NULL, SYSICLASS, tags);
142 if ((!data->dri) || (!data->labels) || (!data->mximage) || (!data->numlabels))
144 CoerceMethod(cl, (Object *)g, OM_DISPOSE);
145 g = NULL;
148 return (IPTR)g;
151 /**********************************************************************************************/
153 IPTR GTMX__OM_DISPOSE(Class *cl, Object *o, Msg msg)
155 struct MXData *data = INST_DATA(cl, o);
156 IPTR retval;
158 if (data->font) CloseFont(data->font);
159 if (data->mximage) DisposeObject(data->mximage);
161 retval = DoSuperMethodA(cl, o, msg);
163 return retval;
166 /**********************************************************************************************/
168 IPTR GTMX__OM_SET(Class *cl, Object *o, struct opSet *msg)
170 struct MXData *data = INST_DATA(cl, o);
171 struct TagItem *tag;
172 struct TagItem *taglist = msg->ops_AttrList;
173 IPTR retval = FALSE;
175 if (msg->MethodID != OM_NEW)
176 retval = DoSuperMethodA(cl, o, (Msg)msg);
178 while ((tag = NextTagItem(&taglist)))
180 switch (tag->ti_Tag)
182 case GA_Disabled:
183 retval = TRUE;
184 break;
186 case GTMX_Active:
187 if ((tag->ti_Data >= 0) && (tag->ti_Data < data->numlabels))
189 data->active = tag->ti_Data;
190 retval = TRUE;
192 break;
196 if ((retval) && ((msg->MethodID != OM_UPDATE) || (cl == OCLASS(o))))
198 struct RastPort *rp;
200 rp = ObtainGIRPort(msg->ops_GInfo);
201 if (rp)
203 DoMethod(o, GM_RENDER, (IPTR)msg->ops_GInfo, (IPTR)rp, GREDRAW_REDRAW);
204 ReleaseGIRPort(rp);
205 retval = FALSE;
209 return retval;
212 /**********************************************************************************************/
214 IPTR GTMX__OM_GET(Class *cl, Object *o, struct opGet *msg)
216 struct MXData *data;
217 IPTR retval;
219 data = INST_DATA(cl, o);
221 switch (msg->opg_AttrID)
223 case GTA_GadgetKind:
224 case GTA_ChildGadgetKind:
225 *(msg->opg_Storage) = MX_KIND;
226 retval = 1UL;
227 break;
229 case GTMX_Active:
230 *(msg->opg_Storage) = data->active;
231 retval = 1UL;
232 break;
234 default:
235 retval = DoSuperMethodA(cl, o, (Msg)msg);
236 break;
239 return retval;
242 /**********************************************************************************************/
244 IPTR GTMX__GM_RENDER(Class *cl, struct ExtGadget *g, struct gpRender *msg)
246 struct MXData *data = INST_DATA(cl, g);
247 WORD ypos = g->TopEdge;
248 UWORD maxtextwidth;
249 int y;
251 if (msg->gpr_Redraw == GREDRAW_UPDATE)
253 /* Only redraw the current and the last tick activated */
254 DrawImageState(msg->gpr_RPort, data->mximage,
255 g->LeftEdge, ypos + data->active *(data->fontheight + data->spacing),
256 IDS_NORMAL, data->dri);
258 DrawImageState(msg->gpr_RPort, data->mximage,
259 g->LeftEdge, ypos + data->newactive *(data->fontheight + data->spacing),
260 IDS_SELECTED, data->dri);
262 else
264 /* Full redraw */
265 STRPTR *labels;
266 WORD minx, miny, maxx, maxy;
268 if (data->font)
269 SetFont(msg->gpr_RPort, data->font);
270 else
271 SetFont(msg->gpr_RPort, msg->gpr_GInfo->gi_DrInfo->dri_Font);
273 /* Draw ticks */
274 for (y=0; y<data->numlabels; y++)
276 ULONG state;
278 if (y == data->active)
279 state = IDS_SELECTED;
280 else
281 state = IDS_NORMAL;
282 DrawImageState(msg->gpr_RPort, data->mximage,
283 g->LeftEdge, ypos,
284 state, data->dri);
285 ypos += data->fontheight + data->spacing;
288 /* Draw labels */
289 SetABPenDrMd(msg->gpr_RPort,
290 data->dri->dri_Pens[TEXTPEN],
291 data->dri->dri_Pens[BACKGROUNDPEN],
292 JAM1);
294 ypos = g->TopEdge;
296 maxtextwidth = 0;
298 minx = g->LeftEdge;
299 miny = g->TopEdge;
300 maxx = minx + g->Width - 1;
301 maxy = miny + g->Height - 1;
303 for (labels = data->labels; *labels; labels++)
305 struct TextExtent te;
306 WORD x, y, width, height, len;
308 x = g->LeftEdge;
309 y = ypos;
311 len = strlen(*labels);
312 TextExtent(msg->gpr_RPort, *labels, len, &te);
313 width = te.te_Width;
314 height = te.te_Height;
316 if (width > maxtextwidth) maxtextwidth = width;
318 switch(data->ticklabelplace)
320 case GV_LabelPlace_Right:
321 x += data->mximage->Width + 5;
322 y += (data->mximage->Height - height) / 2 + 1;
323 break;
325 case GV_LabelPlace_Above:
326 x += (data->mximage->Width - width) / 2;
327 y -= (height + 2);
328 break;
330 case GV_LabelPlace_Below:
331 x += (data->mximage->Width - width) / 2;
332 y += (data->mximage->Height + 3);
333 break;
335 case GV_LabelPlace_In:
336 x += (data->mximage->Width - width) / 2;
337 y += (data->mximage->Height - height) / 2;
338 break;
340 default: /* GV_LabelPlace_Left: */
341 x -= (width + 4);
342 y += (data->mximage->Height - height) / 2 + 1;
343 break;
346 Move(msg->gpr_RPort, x, y + msg->gpr_RPort->Font->tf_Baseline);
347 Text(msg->gpr_RPort, *labels, len);
349 if (x < minx) minx = x;
350 if (y < miny) miny = y;
351 if (x + width - 1 > maxx) maxx = x + width - 1;
352 if (y + height - 1 > maxy) maxy = y + height - 1;
354 ypos += data->fontheight + data->spacing;
357 g->BoundsLeftEdge = minx;
358 g->BoundsTopEdge = miny;
359 g->BoundsWidth = maxx - minx + 1;
360 g->BoundsHeight = maxy - miny + 1;
361 g->MoreFlags |= GMORE_BOUNDS;
363 data->maxtextwidth = maxtextwidth;
365 /* Draw main label */
367 /* bug: this will not be rendered at the correct
368 position if ticklabel place and labelplace
369 are the same. I don't think any app will
370 ever do this:
372 x Item 1
373 x Item 2 Label
374 x Item 3
378 renderlabel(GadToolsBase,
379 (struct Gadget *)g,
380 msg->gpr_RPort,
381 data->labelplace);
385 /* Draw disabled pattern */
386 if (g->Flags & GFLG_DISABLED)
387 DoDisabledPattern(msg->gpr_RPort,
388 g->LeftEdge,
389 g->TopEdge,
390 g->LeftEdge + g->Width - 1,
391 g->TopEdge + g->Height - 1,
392 data->dri->dri_Pens[SHADOWPEN],
393 GadToolsBase);
395 return TRUE;
398 /**********************************************************************************************/
400 IPTR GTMX__GM_GOACTIVE(Class *cl, Object *o, struct gpInput *msg)
402 struct MXData *data = INST_DATA(cl, o);
403 int y, blobheight = data->spacing + data->fontheight;
404 IPTR retval = GMR_NOREUSE;
406 D(bug("blobheight: %d\n", blobheight));
408 for (y = 0; y < data->numlabels; y++)
410 D(bug("Mouse.Y: %d, y: %d\n", msg->gpi_Mouse.Y, y));
411 if (msg->gpi_Mouse.Y < blobheight *(y + 1))
413 if (y != data->active)
415 struct RastPort *rp;
417 rp = ObtainGIRPort(msg->gpi_GInfo);
418 if (rp)
420 data->newactive = y;
421 DoMethod(o, GM_RENDER, (IPTR)msg->gpi_GInfo, (IPTR)rp, GREDRAW_UPDATE);
422 ReleaseGIRPort(rp);
423 *msg->gpi_Termination = data->active = y;
424 retval |= GMR_VERIFY;
427 y = data->numlabels;
431 return retval;
434 /**********************************************************************************************/