make sure existing propgadgets are removed/disposed of correctly
[tangerine.git] / workbench / libs / muimaster / classes / prop.c
blob2bae1577e28b3a15814a069aa6eeba8c4ff879b8
1 /*
2 Copyright 2002-2003, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <exec/memory.h>
7 #include <intuition/icclass.h>
8 #include <intuition/gadgetclass.h>
9 #include <clib/alib_protos.h>
10 #include <proto/exec.h>
11 #include <proto/graphics.h>
12 #include <proto/intuition.h>
13 #include <proto/utility.h>
14 #include <proto/muimaster.h>
15 #include <proto/cybergraphics.h>
17 #ifdef __AROS__
18 #include <intuition/windecorclass.h>
19 #endif
20 #include <cybergraphx/cybergraphics.h>
21 #include <graphics/rpattr.h>
23 #include "../datatypescache.h"
24 #include "../imspec_intern.h"
26 #include "mui.h"
27 #include "muimaster_intern.h"
28 #include "support.h"
29 #include "prefs.h"
31 /* #define MYDEBUG 1 */
32 #include "debug.h"
34 extern struct Library *MUIMasterBase;
36 #define SCALE16_METHOD 2 /* 1 or 2 */
38 #if SCALE16_METHOD != 1
39 #define calcscale16(x)
40 #endif
42 struct Prop_DATA
44 ULONG entries;
45 LONG first;
46 ULONG visible;
47 LONG deltafactor;
48 #if SCALE16_METHOD == 1
49 ULONG scale16;
50 #endif
51 LONG gadgetid;
53 int horiz;
54 int usewinborder;
55 int sb_type;
56 UWORD minwidth, minheight;
57 UWORD maxwidth, maxheight;
58 UWORD defwidth, defheight;
59 UWORD propwidth, propheight;
61 Object *prop_object;
62 struct MUI_EventHandlerNode ehn;
63 struct Hook dhook;
64 struct dt_node *node;
65 Object *obj;
66 struct NewImage *buffer;
67 struct NewImage *temp;
68 struct BitMap *mapbuffer;
69 struct BitMap *maptemp;
70 struct RastPort *tmprp;
73 #if SCALE16_METHOD == 1
74 static void calcscale16(struct Prop_DATA *data)
76 if (data->entries < 65535)
78 data->scale16 = 0x10000;
80 else
82 unsigned long long v = ((unsigned long long)data->entries) * 0x10000 / 65535;
84 data->scale16 = (ULONG)v;
87 #endif
89 static ULONG downscale(struct Prop_DATA *data, ULONG val)
91 #if SCALE16_METHOD == 1
92 if (data->scale16 != 0x10000)
94 unsigned long long v = ((unsigned long long)val) * 0x10000 / data->scale16;
95 val = (ULONG)v;
97 #else
98 if (data->entries >= 0x10000)
100 unsigned long long v = ((unsigned long long)val) * 65535 / data->entries;
101 val = (ULONG)v;
104 #endif
105 return val;
108 static ULONG upscale(struct Prop_DATA *data, ULONG val)
110 #if SCALE16_METHOD == 1
111 if (data->scale16 != 0x10000)
113 unsigned long long v = ((unsigned long long)val) * data->scale16 / 0x10000;
114 val = (ULONG)v;
116 #else
117 if (data->entries >= 0x10000)
119 unsigned long long v = ((unsigned long long)val) * data->entries / 65535;
120 val = (ULONG)v;
122 #endif
123 return val;
126 IPTR Prop__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
128 struct Prop_DATA *data;
129 struct TagItem *tags,*tag;
131 obj = (Object *)DoSuperNewTags(cl, obj, NULL,
132 MUIA_Background, MUII_PropBack,
133 TAG_MORE, (IPTR) msg->ops_AttrList);
135 if (!obj)
136 return FALSE;
138 data = INST_DATA(cl, obj);
139 data->deltafactor = 1;
141 /* parse initial taglist */
142 for (tags = msg->ops_AttrList; (tag = NextTagItem((const struct TagItem **)&tags)); )
144 switch (tag->ti_Tag)
146 case MUIA_Prop_Entries:
147 data->entries = tag->ti_Data;
148 break;
149 case MUIA_Prop_First:
150 data->first = tag->ti_Data;
151 break;
152 case MUIA_Prop_Horiz:
153 data->horiz = tag->ti_Data;
154 break;
155 case MUIA_Prop_Slider:
156 break;
157 case MUIA_Prop_UseWinBorder:
158 data->usewinborder = tag->ti_Data;
159 break;
160 case MUIA_Prop_Visible:
161 data->visible = tag->ti_Data;
162 break;
164 case MUIA_Prop_DeltaFactor:
165 data->deltafactor = tag->ti_Data;
166 break;
170 if (data->horiz == TRUE)
172 data->minwidth = 6;
173 data->minheight = 6;
174 data->maxwidth = MUI_MAXMAX;
175 data->maxheight = MUI_MAXMAX;
176 data->defwidth = 50;
177 data->defheight = 6;
179 else
181 data->minwidth = 6;
182 data->minheight = 6;
183 data->maxwidth = MUI_MAXMAX;
184 data->maxheight = MUI_MAXMAX;
185 data->defwidth = 6;
186 data->defheight = 50;
189 if (data->first < 0)
190 data->first = 0;
192 data->ehn.ehn_Events = IDCMP_IDCMPUPDATE;
193 data->ehn.ehn_Priority = 0;
194 data->ehn.ehn_Flags = 0;
195 data->ehn.ehn_Object = obj;
196 data->ehn.ehn_Class = cl;
198 if (data->usewinborder)
199 _flags(obj) |= MADF_BORDERGADGET;
201 calcscale16(data);
203 return (IPTR)obj;
206 IPTR Prop__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
208 struct Prop_DATA *data = INST_DATA(cl, obj);
210 if (data->prop_object && !data->usewinborder) {
211 RemoveGadget(_window(obj), (struct Gadget *) data->prop_object);
212 DisposeObject(data->prop_object);
215 DisposeImageContainer(data->buffer);
216 DisposeImageContainer(data->temp);
217 if (data->mapbuffer != NULL) FreeBitMap(data->mapbuffer);
218 if (data->maptemp != NULL) FreeBitMap(data->maptemp);
219 if (data->tmprp != NULL) FreeRastPort(data->tmprp);
221 data->buffer = NULL;
222 data->temp = NULL;
223 data->mapbuffer = NULL;
224 data->maptemp = NULL;
225 data->tmprp = NULL;
227 return DoSuperMethodA(cl, obj, msg);
230 IPTR Prop__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
232 struct TagItem *tags,*tag;
233 struct Prop_DATA *data = INST_DATA(cl, obj);
234 int refresh = 0;
235 int only_trigger = 0;
237 for (tags = msg->ops_AttrList; (tag = NextTagItem((const struct TagItem **)&tags)); )
239 switch (tag->ti_Tag)
241 case MUIA_Prop_Entries:
242 data->entries = tag->ti_Data;
243 refresh = 1;
244 break;
246 case MUIA_Prop_First:
247 data->first = tag->ti_Data;
248 refresh = 1;
249 break;
251 case MUIA_Prop_Slider:
252 break;
254 case MUIA_Prop_Visible:
255 data->visible = tag->ti_Data;
256 refresh = 1;
257 break;
259 case MUIA_Prop_OnlyTrigger:
260 only_trigger = tag->ti_Data;
261 break;
263 case MUIA_Prop_DeltaFactor:
264 data->deltafactor = tag->ti_Data;
265 break;
269 if (data->first < 0)
270 data->first = 0;
272 if (data->prop_object && refresh && !only_trigger)
274 calcscale16(data);
276 /* Rendering will happen here!! This could make problems with virtual groups, forward this to MUIM_Draw??? */
277 SetAttrs(data->prop_object, ICA_TARGET, NULL, TAG_DONE);
278 if (SetGadgetAttrs((struct Gadget*)data->prop_object,_window(obj),NULL,
279 PGA_Top,downscale(data, data->first),
280 PGA_Visible,downscale(data, data->visible),
281 PGA_Total,downscale(data, data->entries),
282 TAG_DONE))
283 RefreshGList((struct Gadget*)data->prop_object, _window(obj), NULL, 1);
284 SetAttrs(data->prop_object, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
287 return DoSuperMethodA(cl,obj,(Msg)msg);
290 #define STORE *(msg->opg_Storage)
291 IPTR Prop__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
293 struct Prop_DATA *data = INST_DATA(cl, obj);
294 switch (msg->opg_AttrID)
296 case MUIA_Prop_First:
298 if (data->prop_object)
300 IPTR v;
301 /* So we can get a more current value */
302 GetAttr(PGA_Top,data->prop_object,&v);
303 data->first = upscale(data, v);
305 STORE = data->first;
306 return 1;
308 case MUIA_Prop_Entries: STORE = data->entries; return 1;
309 case MUIA_Prop_Visible: STORE = data->visible; return 1;
311 default:
312 return DoSuperMethodA(cl,obj,(Msg)msg);
315 return 1;
317 #undef STORE
319 IPTR Prop__MUIM_AskMinMax(struct IClass *cl, Object *obj, struct MUIP_AskMinMax *msg)
321 struct Prop_DATA *data = INST_DATA(cl, obj);
324 ** let our superclass first fill in what it thinks about sizes.
325 ** this will e.g. add the size of frame and inner spacing.
327 DoSuperMethodA(cl, obj, (Msg)msg);
329 msg->MinMaxInfo->MinWidth += data->minwidth;
330 msg->MinMaxInfo->DefWidth += data->defwidth;
331 msg->MinMaxInfo->MaxWidth = data->maxwidth;
333 msg->MinMaxInfo->MinHeight += data->minheight;
334 msg->MinMaxInfo->DefHeight += data->defheight;
335 msg->MinMaxInfo->MaxHeight = data->maxheight;
337 D(bug("Prop %p minheigh=%d\n",
338 obj, msg->MinMaxInfo->MinHeight));
340 return TRUE;
343 IPTR Prop__MUIM_Setup(struct IClass *cl, Object *obj, struct MUIP_Setup *msg)
345 struct Prop_DATA *data = INST_DATA(cl, obj);
346 ULONG rc = DoSuperMethodA(cl, obj, (Msg)msg);
347 if (!rc) return 0;
349 DoMethod(_win(obj),MUIM_Window_AddEventHandler,(IPTR)&data->ehn);
351 data->buffer = NULL;
352 data->temp = NULL;
353 data->mapbuffer = NULL;
354 data->maptemp = NULL;
355 data->tmprp = NULL;
357 if (!data->usewinborder)
359 data->gadgetid = DoMethod(_win(obj),MUIM_Window_AllocGadgetID);
360 if (data->horiz == TRUE)
362 data->minwidth = 6;
363 data->minheight = 6;
364 data->maxwidth = MUI_MAXMAX;
365 data->maxheight = MUI_MAXMAX;
366 data->defwidth = 50;
367 data->defheight = 6;
369 else
371 data->minwidth = 6;
372 data->minheight = 6;
373 data->maxwidth = MUI_MAXMAX;
374 data->maxheight = MUI_MAXMAX;
375 data->defwidth = 6;
376 data->defheight = 50;
379 struct MUI_AreaData *adata = muiAreaData(obj);
380 struct MUI_ImageSpec_intern *spec = adata->mad_Background;
382 if (spec)
384 if (spec->type == IST_BITMAP)
386 struct dt_node *node = spec->u.bitmap.dt;
387 if (node)
389 if (node->mode == MODE_PROP)
391 set(obj, MUIA_Frame, MUIV_Frame_None);
393 if (data->horiz == TRUE)
395 data->minheight = node->img_horizontalcontainer->h >> 1;
396 data->defheight = data->minheight;
397 data->maxheight = data->minheight;
399 else
401 data->minwidth = node->img_verticalcontainer->w >> 1;
402 data->defwidth = data->minwidth;
403 data->maxwidth = data->minwidth;
411 return 1;
414 IPTR Prop__MUIM_Cleanup(struct IClass *cl, Object *obj, struct MUIP_Cleanup *msg)
416 struct Prop_DATA *data = INST_DATA(cl, obj);
417 if (!data->usewinborder)
419 DoMethod(_win(obj),MUIM_Window_FreeGadgetID,data->gadgetid);
421 DoMethod(_win(obj),MUIM_Window_RemEventHandler,(IPTR)&data->ehn);
422 return DoSuperMethodA(cl, obj, (Msg)msg);
425 void WritePixelArrayAlphaToImage(struct NewImage *in, UWORD sx, UWORD sy, struct NewImage *out, UWORD xp, UWORD yp, UWORD w, UWORD h)
427 ULONG argb, rgb;
428 UBYTE rs, gs, bs, as, rd, gd, bd;
429 UWORD r, g, b;
430 UWORD x, y;
431 for (y = 0; y < h; y++)
433 for (x = 0; x < w; x++)
435 argb = in->data[x + sx + (y + sy) * in->w];
437 as = GET_A(argb);
438 rs = GET_R(argb);
439 gs = GET_G(argb);
440 bs = GET_B(argb);
441 // as = 255;
442 rgb = out->data[x+xp+(y+yp)*out->w];
444 rd = GET_R(rgb);
445 gd = GET_G(rgb);
446 bd = GET_B(rgb);
449 r = ((rs * as) >> 8) + ((rd * (255 - as)) >> 8);
450 g = ((gs * as) >> 8) + ((gd * (255 - as)) >> 8);
451 b = ((bs * as) >> 8) + ((bd * (255 - as)) >> 8);
453 out->data[x+xp+(y+yp)*out->w] = SET_ARGB(255, r, g, b);
459 int WriteTiledImageHorizontal(struct NewImage *dst, struct RastPort *maprp, struct NewImage *ni, int sx, int sy, int sw, int sh, int xp, int yp, int dw, int dh) {
460 int w = dw;
461 int x = xp;
462 int ddw;
463 if ((sw == 0) || (dw == 0)) return xp;
465 while (w > 0) {
466 ddw = sw;
467 if (w < ddw) ddw = w;
469 if (dst != NULL) WritePixelArrayAlphaToImage(ni, sx , sy, dst, x, yp, ddw, dh);
470 if ((maprp != NULL) && (ni->bitmap != NULL))
472 if (ni->mask)
474 BltMaskBitMapRastPort(ni->bitmap, sx, sy, maprp, x, yp, ddw, dh, 0xe0, (PLANEPTR) ni->mask);
476 else BltBitMapRastPort(ni->bitmap, sx, sy, maprp, x, yp, ddw, dh, 0xc0);
478 w -= ddw;
479 x += ddw;
481 return x;
484 int WriteTiledImageVertical(struct NewImage *dst, struct RastPort *maprp, struct NewImage *ni, int sx, int sy, int sw, int sh, int xp, int yp, int dw, int dh) {
485 int h = dh;
486 int y = yp;
487 int ddh;
488 if ((sh == 0) || (dh == 0)) return yp;
489 while (h > 0) {
490 ddh = sh;
491 if (h < ddh) ddh = h;
493 if (dst != NULL) WritePixelArrayAlphaToImage(ni, sx , sy, dst, xp, y, dw, ddh);
494 if ((maprp != NULL) && (ni->bitmap != NULL))
496 if (ni->mask)
498 BltMaskBitMapRastPort(ni->bitmap, sx, sy, maprp, xp, y, dw, ddh, 0xe0, (PLANEPTR) ni->mask);
500 else BltBitMapRastPort(ni->bitmap, sx, sy, maprp, xp, y, dw, ddh, 0xc0);
502 h -= ddh;
503 y += ddh;
505 return y;
508 #ifdef __AROS__
509 AROS_UFH3
511 void, CustomPropRenderFunc,
512 AROS_UFHA(struct Hook *, h, A0),
513 AROS_UFHA(Object *, obj, A2),
514 AROS_UFHA(struct wdpDrawBorderPropKnob *, msg, A1)
517 AROS_USERFUNC_INIT
519 struct Prop_DATA *node = h->h_Data;
521 struct dt_node *data = node->node;
522 ULONG depth;
524 if (msg->MethodID == WDM_DRAW_BORDERPROPKNOB)
526 struct Window *window = msg->wdp_Window;
527 struct NewImage *temp;
528 struct BitMap *maptemp;
529 struct RastPort *winrp = msg->wdp_RPort;
530 struct RastPort *maprp;
531 struct Gadget *gadget = msg->wdp_Gadget;
532 struct Rectangle *r = msg->wdp_RenderRect;
533 struct PropInfo *pi = ((struct PropInfo *)gadget->SpecialInfo);
534 BOOL hit = (msg->wdp_Flags & WDF_DBPK_HIT) ? TRUE : FALSE;
535 ULONG y, x;
536 int size, is, pos;
537 UWORD MinX, MinY, MaxX, MaxY, StartX, StartY;
540 int i;
542 temp = node->temp;
543 maptemp = node->maptemp;
544 maprp = node->tmprp;
546 depth = (ULONG) GetBitMapAttr(winrp->BitMap, BMA_DEPTH);
548 if (node->buffer) for (i = 0; i < (node->buffer->w * node->buffer->h); i++) node->temp->data[i] = node->buffer->data[i];
549 if (node->mapbuffer) BltBitMap(node->mapbuffer, 0, 0, node->maptemp, 0, 0, node->propwidth, node->propheight, 0xc0, 0xff, NULL);
552 r = msg->wdp_PropRect;
553 StartX = r->MinX;
554 StartY = r->MinY;
555 MinX = 0;
556 MinY = 0;
557 MaxX = r->MaxX - r->MinX;
558 MaxY = r->MaxY - r->MinY;
560 if ((pi->Flags & FREEVERT) != 0)
562 is = data->img_verticalcontainer->w >> 1;
563 if (window->Flags & WFLG_WINDOWACTIVE) pos = 0; else pos = is;
564 y = MinY;
565 size = MaxY - MinY - data->ContainerTop_s - data->ContainerBottom_s + 1;
566 y = WriteTiledImageVertical(temp, maprp, data->img_verticalcontainer, pos, data->ContainerTop_o, is, data->ContainerTop_s, MinX, y, is, data->ContainerTop_s);
567 if (size > 0) y = WriteTiledImageVertical(temp, maprp, data->img_verticalcontainer, pos, data->ContainerVertTile_o, is, data->ContainerVertTile_s, MinX, y, is, size);
568 y = WriteTiledImageVertical(temp, maprp, data->img_verticalcontainer, pos, data->ContainerBottom_o, is, data->ContainerBottom_s, MinX, y, is, data->ContainerBottom_s);
570 else if ((pi->Flags & FREEHORIZ) != 0)
572 is = data->img_horizontalcontainer->h >> 1;
573 if (window->Flags & WFLG_WINDOWACTIVE) pos = 0; else pos = is;
574 x = MinX;
575 size = MaxX - MinX - data->ContainerLeft_s - data->ContainerRight_s + 1;
576 x = WriteTiledImageHorizontal(temp, maprp, data->img_horizontalcontainer, data->ContainerLeft_o, pos, data->ContainerLeft_s, is, x, MinY, data->ContainerLeft_s, is);
577 if (size > 0) x = WriteTiledImageHorizontal(temp, maprp, data->img_horizontalcontainer, data->ContainerHorTile_o, pos, data->ContainerHorTile_s, is, x, MinY, size, is);
578 x = WriteTiledImageHorizontal(temp, maprp, data->img_horizontalcontainer, data->ContainerRight_o, pos, data->ContainerRight_s, is, x, MinY, data->ContainerRight_s, is);
581 r = msg->wdp_RenderRect;
582 MinX = r->MinX - StartX;
583 MinY = r->MinY - StartY;
584 MaxX = r->MaxX - StartX;
585 MaxY = r->MaxY - StartY;
587 if ((pi->Flags & FREEVERT) != 0)
589 is = data->img_verticalknob->w / 3;
590 if (hit) pos = is; else if (window->Flags & WFLG_WINDOWACTIVE) pos = 0; else pos = is * 2;
591 y = MinY;
592 size = MaxY - MinY - data->KnobTop_s - data->KnobBottom_s + 1;
593 y = WriteTiledImageVertical(temp, maprp, data->img_verticalknob, pos, data->KnobTop_o, is, data->KnobTop_s, MinX, y, is, data->KnobTop_s);
594 if (size > 0) {
595 if (size > data->KnobVertGripper_s) {
596 size = size - data->KnobVertGripper_s;
597 int size_bak = size;
598 size = size / 2;
599 if (size > 0) y = WriteTiledImageVertical(temp, maprp, data->img_verticalknob, pos, data->KnobTileTop_o, is, data->KnobTileTop_s, MinX, y, is, size);
600 y = WriteTiledImageVertical(temp, maprp, data->img_verticalknob, pos, data->KnobVertGripper_o, is, data->KnobVertGripper_s, MinX, y, is, data->KnobVertGripper_s);
601 size = size_bak - size;
602 if (size > 0) y = WriteTiledImageVertical(temp, maprp, data->img_verticalknob, pos, data->KnobTileBottom_o, is, data->KnobTileBottom_s, MinX, y, is, size);
603 } else {
604 y = WriteTiledImageVertical(temp, maprp, data->img_verticalknob, pos, data->KnobTileTop_o, is, data->KnobTileTop_s, MinX, y, is, size);
607 y = WriteTiledImageVertical(temp, maprp, data->img_verticalknob, pos, data->KnobBottom_o, is, data->KnobBottom_s, MinX, y, is, data->KnobBottom_s);
609 else if ((pi->Flags & FREEHORIZ) != 0)
611 is = data->img_horizontalknob->h / 3;
612 if (hit) pos = is; else if (window->Flags & WFLG_WINDOWACTIVE) pos = 0; else pos = is * 2;
613 x = MinX;
614 size = MaxX - MinX - data->KnobLeft_s - data->KnobRight_s + 1;
615 x = WriteTiledImageHorizontal(temp, maprp, data->img_horizontalknob, data->KnobLeft_o, pos, data->KnobLeft_s, is, x, MinY, data->KnobLeft_s, is);
616 if (size > 0) {
617 if (size > data->KnobHorGripper_s) {
618 size = size - data->KnobHorGripper_s;
619 int size_bak = size;
620 size = size / 2;
621 if (size > 0) x = WriteTiledImageHorizontal(temp, maprp, data->img_horizontalknob, data->KnobTileLeft_o, pos, data->KnobTileLeft_s, is, x, MinY, size, is);
622 x = WriteTiledImageHorizontal(temp, maprp, data->img_horizontalknob, data->KnobHorGripper_o, pos, data->KnobHorGripper_s, is, x, MinY, data->KnobHorGripper_s, is);
623 size = size_bak - size;
624 if (size > 0) x = WriteTiledImageHorizontal(temp, maprp, data->img_horizontalknob, data->KnobTileRight_o, pos, data->KnobTileRight_s, is, x, MinY, size, is);
625 } else {
626 x = WriteTiledImageHorizontal(temp, maprp, data->img_horizontalknob, data->KnobTileRight_o, pos, data->KnobTileRight_s, is, x, MinY, size, is);
629 x = WriteTiledImageHorizontal(temp, maprp, data->img_horizontalknob, data->KnobRight_o, pos, data->KnobRight_s, is, x, MinY, data->KnobRight_s, is);
632 if (node->temp) WritePixelArray(node->temp->data, 0, 0, node->temp->w*4, winrp, _left(node->obj), _top(node->obj), node->temp->w, node->temp->h, RECTFMT_ARGB);
633 if (node->maptemp) BltBitMapRastPort(node->maptemp, 0, 0, winrp, _left(node->obj), _top(node->obj), node->propwidth, node->propheight, 0xc0);
637 AROS_USERFUNC_EXIT
639 #endif
641 IPTR Prop__MUIM_Show(struct IClass *cl, Object *obj, struct MUIP_Show *msg)
643 struct Prop_DATA *data = INST_DATA(cl, obj);
644 struct MUI_AreaData *adata = muiAreaData(obj);
645 struct MUI_ImageSpec_intern *spec = adata->mad_Background;
647 ULONG rc = DoSuperMethodA(cl, obj, (Msg)msg);
648 #ifdef __AROS__
649 data->dhook.h_Entry = (HOOKFUNC) CustomPropRenderFunc;
650 #endif
651 if (!data->usewinborder)
653 BOOL isnewlook, completely_visible = TRUE;;
655 if (_flags(obj) & MADF_INVIRTUALGROUP)
657 Object *wnd, *parent;
659 get(obj, MUIA_WindowObject,&wnd);
660 parent = obj;
661 while (get(parent,MUIA_Parent,&parent))
663 if (!parent) break;
664 if (parent == wnd) break;
666 if (_flags(parent) & MADF_ISVIRTUALGROUP)
668 if ((_mleft(obj) < _mleft(parent)) ||
669 (_mright(obj) > _mright(parent)) ||
670 (_mtop(obj) < _mtop(parent)) ||
671 (_mbottom(obj) > _mbottom(parent)))
673 completely_visible = FALSE;
674 D(bug("=== prop object: completely visible FALSE for obj %x at %d,%d - %d,%d\n",
675 obj, _mleft(obj), _mtop(obj), _mright(obj), _mbottom(obj)));
676 break;
682 if (completely_visible)
684 if (muiGlobalInfo(obj)->mgi_Prefs->scrollbar_type == SCROLLBAR_TYPE_NEWLOOK)
685 isnewlook = TRUE;
686 else
687 isnewlook = FALSE;
689 ULONG width = _mwidth(obj);
690 ULONG height = _mheight(obj);
691 #ifdef __AROS__
692 struct Hook *dhook = NULL;
694 ULONG depth = (ULONG) GetBitMapAttr(_window(obj)->RPort->BitMap, BMA_DEPTH);
695 if (muiGlobalInfo(obj)->mgi_Prefs->scrollbar_type == SCROLLBAR_TYPE_CUSTOM)
697 if (spec)
699 if (spec->type == IST_BITMAP)
701 struct dt_node *node = spec->u.bitmap.dt;
702 if (node)
704 if (node->mode == MODE_PROP)
706 data->dhook.h_Entry = (HOOKFUNC) CustomPropRenderFunc;
707 data->node = node;
708 data->dhook.h_Data = data;
709 data->obj = obj;
710 dhook = &data->dhook;
712 if (data->horiz == TRUE) height = node->img_horizontalcontainer->h >> 1; else width = node->img_verticalcontainer->w >> 1;
713 DisposeImageContainer(data->buffer);
714 DisposeImageContainer(data->temp);
715 data->propwidth = width;
716 data->propheight = height;
717 if (data->mapbuffer) FreeBitMap(data->mapbuffer);
718 if (data->maptemp) FreeBitMap(data->maptemp);
719 if (depth >= 15)
721 data->buffer = NewImageContainer(width, height);
722 data->temp = NewImageContainer(width, height);
723 data->mapbuffer = NULL;
724 data->maptemp = NULL;
725 if ((data->buffer == NULL) || (data->temp == NULL))
727 dhook = NULL;
728 DisposeImageContainer(data->buffer);
729 DisposeImageContainer(data->temp);
730 data->buffer = NULL;
731 data->temp = NULL;
734 else
736 data->temp = NULL;
737 data->buffer = NULL;
738 data->tmprp = NULL;
739 data->mapbuffer = AllocBitMap(width, height, 1, BMF_MINPLANES, _window(obj)->RPort->BitMap);
740 data->maptemp = AllocBitMap(width, height, 1, BMF_MINPLANES, _window(obj)->RPort->BitMap);
741 data->tmprp = CreateRastPort();
742 if ((data->mapbuffer == NULL) || (data->maptemp == NULL) || (data->tmprp == NULL))
744 dhook = NULL;
745 if (data->mapbuffer) FreeBitMap(data->mapbuffer);
746 if (data->maptemp) FreeBitMap(data->maptemp);
747 if (data->tmprp) FreeRastPort(data->tmprp);
748 data->mapbuffer = NULL;
749 data->maptemp = NULL;
750 data->tmprp = NULL;
751 } else data->tmprp->BitMap = data->maptemp;
758 #endif
760 if (data->prop_object) {
761 RemoveGadget(_window(obj), (struct Gadget *) data->prop_object);
762 DisposeObject(data->prop_object);
765 if ((data->prop_object = NewObject(NULL, "propgclass",
766 GA_Left, _mleft(obj),
767 GA_Top, _mtop(obj),
768 GA_Width, width,
769 GA_Height, height,
770 GA_ID, data->gadgetid,
771 #ifdef __AROS__
772 PGA_DisplayHook, dhook, /* custom prop gadget impementation (not yet finished) */
773 #endif
774 PGA_Freedom, data->horiz?FREEHORIZ:FREEVERT,
775 PGA_Total, downscale(data, data->entries),
776 PGA_Visible, downscale(data, data->visible),
777 PGA_Top, downscale(data, data->first),
778 PGA_NewLook, isnewlook,
779 PGA_Borderless, TRUE,
780 ICA_TARGET , ICTARGET_IDCMP, /* needed for notification */
781 TAG_DONE)))
783 AddGadget(_window(obj),(struct Gadget*)data->prop_object,~0);
786 } else
788 switch (data->usewinborder)
790 case MUIV_Prop_UseWinBorder_Right:
791 data->prop_object = muiRenderInfo(obj)->mri_VertProp;
792 if (data->prop_object)
794 /* Store pointer to this propclass object in propgadget->UserData,
795 so that window class when receiving IDCMP_IDCMUPDATE from
796 arrow gadgets can notify propclass object */
798 ((struct Gadget *)data->prop_object)->UserData = obj;
800 break;
802 case MUIV_Prop_UseWinBorder_Bottom:
803 data->prop_object = muiRenderInfo(obj)->mri_HorizProp;
804 if (data->prop_object)
806 /* Store pointer to this propclass object in propgadget->UserData,
807 so that window class when receiving IDCMP_IDCMUPDATE from
808 arrow gadgets can notify propclass object */
810 ((struct Gadget *)data->prop_object)->UserData = obj;
812 break;
814 if (data->prop_object)
816 data->gadgetid = ((struct Gadget*)data->prop_object)->GadgetID;
818 SetAttrs(data->prop_object, ICA_TARGET, NULL, TAG_DONE);
819 if (SetGadgetAttrs((struct Gadget*)data->prop_object,_window(obj),NULL,
820 PGA_Top,downscale(data, data->first),
821 PGA_Visible,downscale(data, data->visible),
822 PGA_Total,downscale(data, data->entries),
823 TAG_DONE))
825 RefreshGList((struct Gadget*)data->prop_object, _window(obj), NULL, 1);
827 SetAttrs(data->prop_object, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
831 return rc;
834 IPTR Prop__MUIM_Draw(struct IClass *cl, Object *obj, struct MUIP_Draw *msg)
836 struct Prop_DATA *data = INST_DATA(cl, obj);
838 /* No drawings if own border */
839 if (data->usewinborder) return 0;
841 DoSuperMethodA(cl, obj, (Msg)msg);
843 if (!(msg->flags & MADF_DRAWOBJECT)) return 1;
845 if (data->buffer || data->mapbuffer)
847 // Object *p = NULL;
848 // get(obj, MUIA_Parent, &p);
849 //if (p) DoMethod(p, MUIM_DrawParentBackground, _left(obj), _top(obj), _width(obj), _height(obj), _left(obj), _top(obj), 0);
850 //else
851 DoMethod(obj, MUIM_DrawParentBackground, _left(obj), _top(obj), _width(obj), _height(obj), _left(obj), _top(obj), 0);
853 if (data->buffer) ReadPixelArray(data->buffer->data, 0, 0, data->buffer->w*4, _rp(data->obj), _mleft(data->obj), _mtop(data->obj), data->buffer->w, data->buffer->h, RECTFMT_ARGB);
854 if (data->mapbuffer) BltBitMap(_window(data->obj)->RPort->BitMap, _window(data->obj)->LeftEdge + _mleft(data->obj), _window(data->obj)->TopEdge + _mtop(data->obj), data->mapbuffer, 0, 0, data->propwidth, data->propheight, 0xc0, 0xff, NULL);
857 if (data->prop_object) RefreshGList((struct Gadget*)data->prop_object, _window(obj), NULL, 1);
858 return 1;
861 IPTR Prop__MUIM_Hide(struct IClass *cl, Object *obj, struct MUIP_Hide *msg)
863 struct Prop_DATA *data = INST_DATA(cl, obj);
865 if (data->prop_object)
867 if (!data->usewinborder)
869 RemoveGadget(_window(obj),(struct Gadget*)data->prop_object);
870 DisposeObject(data->prop_object);
871 } else
873 data->gadgetid = 0;
875 data->prop_object = NULL;
878 return DoSuperMethodA(cl, obj, (Msg)msg);
881 IPTR Prop__MUIM_HandleEvent(struct IClass *cl, Object *obj, struct MUIP_HandleEvent *msg)
883 struct Prop_DATA *data = INST_DATA(cl, obj);
884 if (msg->imsg)
886 if (msg->imsg->Class == IDCMP_IDCMPUPDATE)
888 struct TagItem *tag;
889 ULONG v;
891 /* Check if we are meant */
892 tag = FindTagItem(GA_ID,(struct TagItem*)msg->imsg->IAddress);
893 if (!tag) return 0;
894 if (tag->ti_Data != data->gadgetid) return 0;
896 /* Check if we PGA_Top has really changed */
897 tag = FindTagItem(PGA_Top,(struct TagItem*)msg->imsg->IAddress);
898 if (!tag) return 0;
899 v = upscale(data, tag->ti_Data);
901 //kprintf("PROP_HandleEvent: PGA_Top %d upscaled %d entries %d\n", tag->ti_Data, v, data->entries);
903 if ((v == data->first) && (msg->imsg->Qualifier & IEQUALIFIER_REPEAT)) return 0;
904 data->first = v;
905 if (data->first < 0)
906 data->first = 0;
907 SetAttrs(obj, MUIA_Prop_First, data->first, MUIA_Prop_OnlyTrigger, TRUE,
908 MUIA_Prop_Release, ((msg->imsg->Qualifier & IEQUALIFIER_REPEAT) ? FALSE : TRUE),
909 TAG_DONE);
913 return 0;
916 IPTR Prop__MUIM_Prop_Increase(struct IClass *cl, Object *obj, struct MUIP_Prop_Increase *msg)
918 struct Prop_DATA *data = INST_DATA(cl, obj);
919 LONG newfirst;
921 newfirst = data->first + msg->amount * data->deltafactor;
923 if (newfirst + data->visible > data->entries)
924 newfirst = data->entries - data->visible;
925 if (newfirst != data->first)
926 set(obj, MUIA_Prop_First, newfirst);
927 return 1;
930 IPTR Prop__MUIM_Prop_Decrease(struct IClass *cl, Object *obj, struct MUIP_Prop_Decrease *msg)
932 struct Prop_DATA *data = INST_DATA(cl, obj);
933 LONG newfirst;
935 /* We cannot decrease if if are on the top */
936 if (data->first <= 0)
937 return 1;
939 newfirst = data->first - msg->amount * data->deltafactor;
941 if (newfirst < 0)
942 set(obj, MUIA_Prop_First, 0);
943 else if (newfirst != data->first)
944 set(obj, MUIA_Prop_First, newfirst);
945 return 1;
949 BOOPSI_DISPATCHER(IPTR, Prop_Dispatcher, cl, obj, msg)
951 switch (msg->MethodID)
953 case OM_NEW: return Prop__OM_NEW(cl, obj, (struct opSet *) msg);
954 case OM_DISPOSE: return Prop__OM_DISPOSE(cl, obj, msg);
955 case OM_GET: return Prop__OM_GET(cl, obj, (struct opGet *)msg);
956 case OM_SET: return Prop__OM_SET(cl, obj, (struct opSet *)msg);
957 case MUIM_Setup: return Prop__MUIM_Setup(cl, obj, (APTR)msg);
958 case MUIM_Cleanup: return Prop__MUIM_Cleanup(cl, obj, (APTR)msg);
959 case MUIM_Show: return Prop__MUIM_Show(cl, obj, (APTR)msg);
960 case MUIM_Hide: return Prop__MUIM_Hide(cl, obj, (APTR)msg);
961 case MUIM_AskMinMax: return Prop__MUIM_AskMinMax(cl, obj, (APTR)msg);
962 case MUIM_Draw: return Prop__MUIM_Draw(cl, obj, (APTR)msg);
963 case MUIM_HandleEvent: return Prop__MUIM_HandleEvent(cl, obj, (APTR)msg);
964 case MUIM_Prop_Decrease: return Prop__MUIM_Prop_Decrease(cl, obj, (APTR)msg);
965 case MUIM_Prop_Increase: return Prop__MUIM_Prop_Increase(cl, obj, (APTR)msg);
966 default: return DoSuperMethodA(cl, obj, msg);
970 BOOPSI_DISPATCHER_END
972 const struct __MUIBuiltinClass _MUI_Prop_desc =
974 MUIC_Prop,
975 MUIC_Area,
976 sizeof(struct Prop_DATA),
977 (void*)Prop_Dispatcher