grub2: bring back build of aros-side grub2 tools
[AROS.git] / workbench / classes / gadgets / arosmutualexclude / mxclass.c
blob7cc65c711217b478690f3e4d483a973ca34f6386
1 /*
2 Copyright © 1995-2005, The AROS Development Team. All rights reserved.
3 $Id$
5 AROS specific mutualexclude class implementation.
6 */
8 /***********************************************************************************/
10 #define USE_BOOPSI_STUBS
12 #include <string.h>
14 #include <exec/libraries.h>
15 #include <proto/dos.h>
16 #include <proto/intuition.h>
17 #include <intuition/classes.h>
18 #include <intuition/classusr.h>
19 #include <intuition/imageclass.h>
20 #include <intuition/intuition.h>
21 #include <proto/graphics.h>
22 #include <graphics/rastport.h>
23 #include <graphics/text.h>
24 #include <proto/utility.h>
25 #include <utility/tagitem.h>
26 #include <devices/inputevent.h>
27 #include <gadgets/arosmx.h>
28 #include <proto/alib.h>
30 #ifndef DEBUG
31 # define DEBUG 0
32 #endif
33 #include <aros/debug.h>
35 #include "arosmutualexclude_intern.h"
37 #include <clib/boopsistubs.h>
39 /***********************************************************************************/
41 static void mx_setnew(Class * cl, Object * obj, struct opSet *msg)
43 struct MXData *data = INST_DATA(cl, obj);
44 struct TagItem *tag, *taglist = msg->ops_AttrList;
46 while ((tag = NextTagItem(&taglist)))
48 switch (tag->ti_Tag)
50 case GA_DrawInfo:
51 data->dri = (struct DrawInfo *) tag->ti_Data;
52 break;
54 case GA_TextAttr:
55 data->tattr = (struct TextAttr *) tag->ti_Data;
56 break;
58 case GA_LabelPlace:
59 data->labelplace = (LONG) tag->ti_Data;
60 break;
62 case AROSMX_Active:
63 data->active = tag->ti_Data;
64 break;
66 case AROSMX_Labels:
67 data->labels = (STRPTR *) tag->ti_Data;
68 data->numlabels = 0;
69 while (data->labels[data->numlabels])
70 data->numlabels++;
71 break;
73 case AROSMX_Spacing:
74 data->spacing = tag->ti_Data;
75 break;
77 case AROSMX_TickLabelPlace:
78 data->ticklabelplace = (LONG) tag->ti_Data;
79 break;
84 /***********************************************************************************/
86 Object *AROSMX__OM_NEW(Class * cl, Class * rootcl, struct opSet *msg)
88 struct MXData *data;
89 struct TagItem tags[] =
91 {IA_Width, 0},
92 {IA_Height, 0},
93 {SYSIA_DrawInfo, (IPTR) NULL},
94 {SYSIA_Which, MXIMAGE},
95 {TAG_DONE, 0L}
97 Object *obj;
99 obj = (Object *) DoSuperMethodA(cl, (Object *) rootcl, (Msg)msg);
100 if (!obj)
101 return NULL;
103 G(obj)->Activation = GACT_IMMEDIATE;
105 data = INST_DATA(cl, obj);
106 data->dri = NULL;
107 data->tattr = NULL;
108 data->active = 0;
109 data->labels = NULL;
110 data->spacing = 1;
111 data->labelplace = GV_LabelPlace_Above;
112 data->ticklabelplace = GV_LabelPlace_Right;
113 mx_setnew(cl, obj, msg);
115 if (data->tattr)
116 data->font = OpenFont(data->tattr);
118 /* Calculate fontheight */
119 if (data->tattr)
120 data->fontheight = data->tattr->ta_YSize;
121 else if ((G(obj)->Flags & GFLG_LABELITEXT) && (G(obj)->GadgetText))
122 data->fontheight = G(obj)->GadgetText->ITextFont->ta_YSize;
123 else
124 data->fontheight = G(obj)->Height;
126 /* Calculate gadget size */
127 if (G(obj)->Width == 0)
128 G(obj)->Width = MX_WIDTH;
129 G(obj)->Height = (data->fontheight + data->spacing) * data->numlabels -
130 data->spacing;
132 tags[0].ti_Data = G(obj)->Width;
133 tags[1].ti_Data = GetTagData(AROSMX_TickHeight, MX_HEIGHT, msg->ops_AttrList);
134 tags[2].ti_Data = (IPTR) data->dri;
135 data->mximage = (struct Image *) NewObjectA(NULL, SYSICLASS, tags);
137 if ((!data->dri) || (!data->labels) || (!data->mximage) || (!data->numlabels)) {
138 CoerceMethod(cl, obj, OM_DISPOSE);
139 return NULL;
141 return obj;
144 /***********************************************************************************/
146 IPTR AROSMX__OM_SET(Class *cl, Object *obj, struct opSet *msg)
148 struct MXData *data = INST_DATA(cl, obj);
149 struct TagItem *tag, *taglist = msg->ops_AttrList;
150 IPTR retval = FALSE;
152 if (msg->MethodID != OM_NEW)
153 retval = DoSuperMethodA(cl, obj, (Msg)msg);
155 while ((tag = NextTagItem(&taglist)))
157 switch (tag->ti_Tag)
159 case GA_Disabled:
160 retval = TRUE;
161 break;
163 case AROSMX_Active:
164 if ((tag->ti_Data >= 0) && (tag->ti_Data < data->numlabels))
166 data->active = tag->ti_Data;
167 retval = TRUE;
169 break;
173 if ((retval) && ((msg->MethodID != OM_UPDATE) || (cl == OCLASS(obj))))
175 struct RastPort *rport;
177 rport = ObtainGIRPort(msg->ops_GInfo);
178 if (rport)
180 DoMethod(obj, GM_RENDER, (IPTR)msg->ops_GInfo, (IPTR)rport, GREDRAW_REDRAW);
181 ReleaseGIRPort(rport);
182 retval = FALSE;
186 return retval;
189 /***********************************************************************************/
191 IPTR AROSMX__GM_RENDER(Class * cl, Object * obj, struct gpRender * msg)
193 struct MXData *data = INST_DATA(cl, obj);
194 WORD ypos = G(obj)->TopEdge;
195 UWORD maxtextwidth;
196 int y;
198 if (msg->gpr_Redraw == GREDRAW_UPDATE)
200 /* Only redraw the current and the last tick activated */
201 DrawImageState(msg->gpr_RPort, data->mximage,
202 G(obj)->LeftEdge, ypos + data->active * (data->fontheight + data->spacing),
203 IDS_NORMAL, data->dri);
205 DrawImageState(msg->gpr_RPort, data->mximage,
206 G(obj)->LeftEdge, ypos + data->newactive * (data->fontheight + data->spacing),
207 IDS_SELECTED, data->dri);
209 else
211 /* Full redraw */
212 STRPTR *labels;
213 WORD minx, miny, maxx, maxy;
215 if (data->font)
216 SetFont(msg->gpr_RPort, data->font);
217 else
218 SetFont(msg->gpr_RPort, msg->gpr_GInfo->gi_DrInfo->dri_Font);
220 /* Draw ticks */
221 for (y=0; y<data->numlabels; y++)
223 ULONG state;
225 if (y == data->active)
226 state = IDS_SELECTED;
227 else
228 state = IDS_NORMAL;
229 DrawImageState(msg->gpr_RPort, data->mximage,
230 G(obj)->LeftEdge, ypos,
231 state, data->dri);
232 ypos += data->fontheight + data->spacing;
235 /* Draw labels */
236 SetABPenDrMd(msg->gpr_RPort,
237 data->dri->dri_Pens[TEXTPEN],
238 data->dri->dri_Pens[BACKGROUNDPEN],
239 JAM1);
241 ypos = G(obj)->TopEdge;
243 maxtextwidth = 0;
245 minx = G(obj)->LeftEdge;
246 miny = G(obj)->TopEdge;
247 maxx = minx + G(obj)->Width - 1;
248 maxy = miny + G(obj)->Height - 1;
250 for (labels=data->labels; *labels; labels++)
252 struct TextExtent te;
253 WORD x, y, width, height, len;
255 x = G(obj)->LeftEdge;
256 y = ypos;
258 len = strlen(*labels);
259 TextExtent(msg->gpr_RPort, *labels, len, &te);
260 width = te.te_Width;
261 height = te.te_Height;
263 if (width > maxtextwidth) maxtextwidth = width;
265 switch(data->ticklabelplace)
267 case GV_LabelPlace_Right:
268 x += data->mximage->Width + 5;
269 y += (data->mximage->Height - height) / 2 + 1;
270 break;
272 case GV_LabelPlace_Above:
273 x += (data->mximage->Width - width) / 2;
274 y -= (height + 2);
275 break;
277 case GV_LabelPlace_Below:
278 x += (data->mximage->Width - width) / 2;
279 y += (data->mximage->Height + 3);
280 break;
282 case GV_LabelPlace_In:
283 x += (data->mximage->Width - width) / 2;
284 y += (data->mximage->Height - height) / 2;
285 break;
287 default: /* GV_LabelPlace_Left: */
288 x -= (width + 4);
289 y += (data->mximage->Height - height) / 2 + 1;
290 break;
294 Move(msg->gpr_RPort, x, y + msg->gpr_RPort->Font->tf_Baseline);
295 Text(msg->gpr_RPort, *labels, len);
297 if (x < minx) minx = x;
298 if (y < miny) miny = y;
299 if (x + width - 1 > maxx) maxx = x + width - 1;
300 if (y + height - 1 > maxy) maxy = y + height - 1;
302 ypos += data->fontheight + data->spacing;
305 data->bbox.MinX = minx;
306 data->bbox.MinY = miny;
307 data->bbox.MaxX = maxx;
308 data->bbox.MaxY = maxy;
310 data->maxtextwidth = maxtextwidth;
312 /* Draw main label */
314 /* bug: this will not be rendered at the correct
315 position if ticklabel place and labelplace
316 are the same. I don't think any app will
317 ever do this:
319 x Item 1
320 x Item 2 Label
321 x Item 3
325 renderlabel(G(obj), msg->gpr_RPort, data);
329 /* Draw disabled pattern */
330 if (G(obj)->Flags & GFLG_DISABLED)
331 drawdisabledpattern(msg->gpr_RPort,
332 data->dri->dri_Pens[SHADOWPEN],
333 G(obj)->LeftEdge, G(obj)->TopEdge,
334 G(obj)->Width-1, G(obj)->Height-1);
336 return TRUE;
339 /***********************************************************************************/
341 IPTR AROSMX__GM_GOACTIVE(Class * cl, Object * obj, struct gpInput * msg)
343 struct MXData *data = INST_DATA(cl, obj);
344 int y, blobheight = data->spacing + data->fontheight;
345 IPTR retval = GMR_NOREUSE;
347 D(bug("blobheight: %d\n", blobheight));
349 for (y = 0; y < data->numlabels; y++)
351 D(bug("Mouse.Y: %d, y: %d\n", msg->gpi_Mouse.Y, y));
352 if (msg->gpi_Mouse.Y < blobheight * (y+1))
354 if (y != data->active)
356 struct RastPort *rport;
358 rport = ObtainGIRPort(msg->gpi_GInfo);
359 if (rport)
361 data->newactive = y;
362 DoMethod(obj, GM_RENDER, (IPTR)msg->gpi_GInfo, (IPTR)rport, GREDRAW_UPDATE);
363 ReleaseGIRPort(rport);
364 *msg->gpi_Termination = data->active = y;
365 retval |= GMR_VERIFY;
368 y = data->numlabels;
372 return retval;
375 /***********************************************************************************/
377 VOID AROSMX__OM_DISPOSE(Class *cl, Object *o, Msg msg)
379 struct MXData *data = INST_DATA(cl, o);
380 if (data->font) CloseFont(data->font);
381 DoSuperMethodA(cl, o, msg);
384 /***********************************************************************************/
386 IPTR AROSMX__OM_GET(Class *cl, Object *o, struct opGet *msg)
388 struct MXData *data = INST_DATA(cl, o);
389 if (msg->opg_AttrID == GTMX_Active)
391 *(msg->opg_Storage) = (IPTR)data->active;
392 return 1;
394 else
395 return DoSuperMethodA(cl, o, msg);
398 /***********************************************************************************/