2 Copyright © 1995-2005, The AROS Development Team. All rights reserved.
5 AROS specific mutualexclude class implementation.
8 /***********************************************************************************/
10 #define USE_BOOPSI_STUBS
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>
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
)))
51 data
->dri
= (struct DrawInfo
*) tag
->ti_Data
;
55 data
->tattr
= (struct TextAttr
*) tag
->ti_Data
;
59 data
->labelplace
= (LONG
) tag
->ti_Data
;
63 data
->active
= tag
->ti_Data
;
67 data
->labels
= (STRPTR
*) tag
->ti_Data
;
69 while (data
->labels
[data
->numlabels
])
74 data
->spacing
= tag
->ti_Data
;
77 case AROSMX_TickLabelPlace
:
78 data
->ticklabelplace
= (LONG
) tag
->ti_Data
;
84 /***********************************************************************************/
86 Object
*AROSMX__OM_NEW(Class
* cl
, Class
* rootcl
, struct opSet
*msg
)
89 struct TagItem tags
[] =
93 {SYSIA_DrawInfo
, (IPTR
) NULL
},
94 {SYSIA_Which
, MXIMAGE
},
99 obj
= (Object
*) DoSuperMethodA(cl
, (Object
*) rootcl
, (Msg
)msg
);
103 G(obj
)->Activation
= GACT_IMMEDIATE
;
105 data
= INST_DATA(cl
, obj
);
111 data
->labelplace
= GV_LabelPlace_Above
;
112 data
->ticklabelplace
= GV_LabelPlace_Right
;
113 mx_setnew(cl
, obj
, msg
);
116 data
->font
= OpenFont(data
->tattr
);
118 /* Calculate fontheight */
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
;
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
-
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
);
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
;
152 if (msg
->MethodID
!= OM_NEW
)
153 retval
= DoSuperMethodA(cl
, obj
, (Msg
)msg
);
155 while ((tag
= NextTagItem(&taglist
)))
164 if ((tag
->ti_Data
>= 0) && (tag
->ti_Data
< data
->numlabels
))
166 data
->active
= tag
->ti_Data
;
173 if ((retval
) && ((msg
->MethodID
!= OM_UPDATE
) || (cl
== OCLASS(obj
))))
175 struct RastPort
*rport
;
177 rport
= ObtainGIRPort(msg
->ops_GInfo
);
180 DoMethod(obj
, GM_RENDER
, (IPTR
)msg
->ops_GInfo
, (IPTR
)rport
, GREDRAW_REDRAW
);
181 ReleaseGIRPort(rport
);
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
;
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
);
213 WORD minx
, miny
, maxx
, maxy
;
216 SetFont(msg
->gpr_RPort
, data
->font
);
218 SetFont(msg
->gpr_RPort
, msg
->gpr_GInfo
->gi_DrInfo
->dri_Font
);
221 for (y
=0; y
<data
->numlabels
; y
++)
225 if (y
== data
->active
)
226 state
= IDS_SELECTED
;
229 DrawImageState(msg
->gpr_RPort
, data
->mximage
,
230 G(obj
)->LeftEdge
, ypos
,
232 ypos
+= data
->fontheight
+ data
->spacing
;
236 SetABPenDrMd(msg
->gpr_RPort
,
237 data
->dri
->dri_Pens
[TEXTPEN
],
238 data
->dri
->dri_Pens
[BACKGROUNDPEN
],
241 ypos
= G(obj
)->TopEdge
;
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
;
258 len
= strlen(*labels
);
259 TextExtent(msg
->gpr_RPort
, *labels
, len
, &te
);
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;
272 case GV_LabelPlace_Above
:
273 x
+= (data
->mximage
->Width
- width
) / 2;
277 case GV_LabelPlace_Below
:
278 x
+= (data
->mximage
->Width
- width
) / 2;
279 y
+= (data
->mximage
->Height
+ 3);
282 case GV_LabelPlace_In
:
283 x
+= (data
->mximage
->Width
- width
) / 2;
284 y
+= (data
->mximage
->Height
- height
) / 2;
287 default: /* GV_LabelPlace_Left: */
289 y
+= (data
->mximage
->Height
- height
) / 2 + 1;
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
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);
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
);
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
;
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
;
395 return DoSuperMethodA(cl
, o
, msg
);
398 /***********************************************************************************/