Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / workbench / libs / muimaster / classes / prop.c
blob598bb913d63e3634f613ce8237c26d3e806bf8f4
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 if ((IPTR)data->entries != tag->ti_Data)
244 data->entries = tag->ti_Data;
245 refresh = 1;
247 else
249 tag->ti_Tag = TAG_IGNORE;
251 break;
253 case MUIA_Prop_First:
254 if ((IPTR)data->first != tag->ti_Data)
256 data->first = tag->ti_Data;
257 refresh = 1;
259 else
261 tag->ti_Tag = TAG_IGNORE;
263 break;
265 case MUIA_Prop_Slider:
266 break;
268 case MUIA_Prop_Visible:
269 if ((IPTR)data->visible != tag->ti_Data)
271 data->visible = tag->ti_Data;
272 refresh = 1;
274 else
276 tag->ti_Tag = TAG_IGNORE;
278 break;
280 case MUIA_Prop_OnlyTrigger:
281 only_trigger = tag->ti_Data;
282 break;
284 case MUIA_Prop_DeltaFactor:
285 data->deltafactor = tag->ti_Data;
286 break;
290 if (data->first < 0)
291 data->first = 0;
293 if (data->prop_object && refresh && !only_trigger)
295 calcscale16(data);
297 /* Rendering will happen here!! This could make problems with virtual groups, forward this to MUIM_Draw??? */
298 SetAttrs(data->prop_object, ICA_TARGET, NULL, TAG_DONE);
299 if (SetGadgetAttrs((struct Gadget*)data->prop_object,_window(obj),NULL,
300 PGA_Top,downscale(data, data->first),
301 PGA_Visible,downscale(data, data->visible),
302 PGA_Total,downscale(data, data->entries),
303 TAG_DONE))
304 RefreshGList((struct Gadget*)data->prop_object, _window(obj), NULL, 1);
305 SetAttrs(data->prop_object, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
308 return DoSuperMethodA(cl,obj,(Msg)msg);
311 #define STORE *(msg->opg_Storage)
312 IPTR Prop__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
314 struct Prop_DATA *data = INST_DATA(cl, obj);
315 switch (msg->opg_AttrID)
317 case MUIA_Prop_First:
319 if (data->prop_object)
321 IPTR v;
322 /* So we can get a more current value */
323 GetAttr(PGA_Top,data->prop_object,&v);
324 data->first = upscale(data, v);
326 STORE = data->first;
327 return 1;
329 case MUIA_Prop_Entries: STORE = data->entries; return 1;
330 case MUIA_Prop_Visible: STORE = data->visible; return 1;
332 /* CHECKME: MUIA_Prop_Release
334 TextEditor.mcc sets up notification on slider obj which is subclass
335 of group and notification on group children (the prop object) will be
336 dropped if the child does not return TRUE on OM_GET.
338 It may be that MUI handles this differently, because a quick check
339 with UAE/MUI showed that a GetAttr() of MUIA_Prop_Release on alider
340 object does not work (returns FALSE). Maybe MUI slider class is
341 similiar to for exampe NListview.mcc which overrides MUIM_Notify where
342 it checks for known attributes and forwards the Method to the correct child
343 of the group.
345 case MUIA_Prop_Release: STORE = 0; return 1;
346 default:
347 return DoSuperMethodA(cl,obj,(Msg)msg);
350 return 1;
352 #undef STORE
354 IPTR Prop__MUIM_AskMinMax(struct IClass *cl, Object *obj, struct MUIP_AskMinMax *msg)
356 struct Prop_DATA *data = INST_DATA(cl, obj);
359 ** let our superclass first fill in what it thinks about sizes.
360 ** this will e.g. add the size of frame and inner spacing.
362 DoSuperMethodA(cl, obj, (Msg)msg);
364 msg->MinMaxInfo->MinWidth += data->minwidth;
365 msg->MinMaxInfo->DefWidth += data->defwidth;
366 msg->MinMaxInfo->MaxWidth = data->maxwidth;
368 msg->MinMaxInfo->MinHeight += data->minheight;
369 msg->MinMaxInfo->DefHeight += data->defheight;
370 msg->MinMaxInfo->MaxHeight = data->maxheight;
372 D(bug("Prop %p minheigh=%d\n",
373 obj, msg->MinMaxInfo->MinHeight));
375 return TRUE;
378 IPTR Prop__MUIM_Setup(struct IClass *cl, Object *obj, struct MUIP_Setup *msg)
380 struct Prop_DATA *data = INST_DATA(cl, obj);
381 ULONG rc = DoSuperMethodA(cl, obj, (Msg)msg);
382 if (!rc) return 0;
384 DoMethod(_win(obj),MUIM_Window_AddEventHandler,(IPTR)&data->ehn);
386 data->buffer = NULL;
387 data->temp = NULL;
388 data->mapbuffer = NULL;
389 data->maptemp = NULL;
390 data->tmprp = NULL;
392 if (!data->usewinborder)
394 data->gadgetid = DoMethod(_win(obj),MUIM_Window_AllocGadgetID);
395 if (data->horiz == TRUE)
397 data->minwidth = 6;
398 data->minheight = 6;
399 data->maxwidth = MUI_MAXMAX;
400 data->maxheight = MUI_MAXMAX;
401 data->defwidth = 50;
402 data->defheight = 6;
404 else
406 data->minwidth = 6;
407 data->minheight = 6;
408 data->maxwidth = MUI_MAXMAX;
409 data->maxheight = MUI_MAXMAX;
410 data->defwidth = 6;
411 data->defheight = 50;
414 struct MUI_AreaData *adata = muiAreaData(obj);
415 struct MUI_ImageSpec_intern *spec = adata->mad_Background;
417 if (spec)
419 if (spec->type == IST_BITMAP)
421 struct dt_node *node = spec->u.bitmap.dt;
422 if (node)
424 if (node->mode == MODE_PROP)
426 set(obj, MUIA_Frame, MUIV_Frame_None);
428 if (data->horiz == TRUE)
430 data->minheight = node->img_horizontalcontainer->h >> 1;
431 data->defheight = data->minheight;
432 data->maxheight = data->minheight;
434 else
436 data->minwidth = node->img_verticalcontainer->w >> 1;
437 data->defwidth = data->minwidth;
438 data->maxwidth = data->minwidth;
446 return 1;
449 IPTR Prop__MUIM_Cleanup(struct IClass *cl, Object *obj, struct MUIP_Cleanup *msg)
451 struct Prop_DATA *data = INST_DATA(cl, obj);
452 if (!data->usewinborder)
454 DoMethod(_win(obj),MUIM_Window_FreeGadgetID,data->gadgetid);
456 else
458 data->prop_object = NULL;
459 data->gadgetid = 0;
462 DoMethod(_win(obj),MUIM_Window_RemEventHandler,(IPTR)&data->ehn);
463 return DoSuperMethodA(cl, obj, (Msg)msg);
466 void WritePixelArrayAlphaToImage(struct NewImage *in, UWORD sx, UWORD sy, struct NewImage *out, UWORD xp, UWORD yp, UWORD w, UWORD h)
468 ULONG argb, rgb;
469 UBYTE rs, gs, bs, as, rd, gd, bd;
470 UWORD r, g, b;
471 UWORD x, y;
472 for (y = 0; y < h; y++)
474 for (x = 0; x < w; x++)
476 argb = in->data[x + sx + (y + sy) * in->w];
478 as = GET_A(argb);
479 rs = GET_R(argb);
480 gs = GET_G(argb);
481 bs = GET_B(argb);
482 // as = 255;
483 rgb = out->data[x+xp+(y+yp)*out->w];
485 rd = GET_R(rgb);
486 gd = GET_G(rgb);
487 bd = GET_B(rgb);
490 r = ((rs * as) >> 8) + ((rd * (255 - as)) >> 8);
491 g = ((gs * as) >> 8) + ((gd * (255 - as)) >> 8);
492 b = ((bs * as) >> 8) + ((bd * (255 - as)) >> 8);
494 out->data[x+xp+(y+yp)*out->w] = SET_ARGB(255, r, g, b);
500 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) {
501 int w = dw;
502 int x = xp;
503 int ddw;
504 if ((sw == 0) || (dw == 0)) return xp;
506 while (w > 0) {
507 ddw = sw;
508 if (w < ddw) ddw = w;
510 if (dst != NULL) WritePixelArrayAlphaToImage(ni, sx , sy, dst, x, yp, ddw, dh);
511 if ((maprp != NULL) && (ni->bitmap != NULL))
513 if (ni->mask)
515 BltMaskBitMapRastPort(ni->bitmap, sx, sy, maprp, x, yp, ddw, dh, 0xe0, (PLANEPTR) ni->mask);
517 else BltBitMapRastPort(ni->bitmap, sx, sy, maprp, x, yp, ddw, dh, 0xc0);
519 w -= ddw;
520 x += ddw;
522 return x;
525 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) {
526 int h = dh;
527 int y = yp;
528 int ddh;
529 if ((sh == 0) || (dh == 0)) return yp;
530 while (h > 0) {
531 ddh = sh;
532 if (h < ddh) ddh = h;
534 if (dst != NULL) WritePixelArrayAlphaToImage(ni, sx , sy, dst, xp, y, dw, ddh);
535 if ((maprp != NULL) && (ni->bitmap != NULL))
537 if (ni->mask)
539 BltMaskBitMapRastPort(ni->bitmap, sx, sy, maprp, xp, y, dw, ddh, 0xe0, (PLANEPTR) ni->mask);
541 else BltBitMapRastPort(ni->bitmap, sx, sy, maprp, xp, y, dw, ddh, 0xc0);
543 h -= ddh;
544 y += ddh;
546 return y;
549 #ifdef __AROS__
550 AROS_UFH3
552 void, CustomPropRenderFunc,
553 AROS_UFHA(struct Hook *, h, A0),
554 AROS_UFHA(Object *, obj, A2),
555 AROS_UFHA(struct wdpDrawBorderPropKnob *, msg, A1)
558 AROS_USERFUNC_INIT
560 struct Prop_DATA *node = h->h_Data;
562 struct dt_node *data = node->node;
563 ULONG depth;
565 if (msg->MethodID == WDM_DRAW_BORDERPROPKNOB)
567 struct Window *window = msg->wdp_Window;
568 struct NewImage *temp;
569 struct BitMap *maptemp;
570 struct RastPort *winrp = msg->wdp_RPort;
571 struct RastPort *maprp;
572 struct Gadget *gadget = msg->wdp_Gadget;
573 struct Rectangle *r = msg->wdp_RenderRect;
574 struct PropInfo *pi = ((struct PropInfo *)gadget->SpecialInfo);
575 BOOL hit = (msg->wdp_Flags & WDF_DBPK_HIT) ? TRUE : FALSE;
576 ULONG y, x;
577 int size, is, pos;
578 UWORD MinX, MinY, MaxX, MaxY, StartX, StartY;
581 int i;
583 temp = node->temp;
584 maptemp = node->maptemp;
585 maprp = node->tmprp;
587 depth = (ULONG) GetBitMapAttr(winrp->BitMap, BMA_DEPTH);
589 if (node->buffer) for (i = 0; i < (node->buffer->w * node->buffer->h); i++) node->temp->data[i] = node->buffer->data[i];
590 if (node->mapbuffer) BltBitMap(node->mapbuffer, 0, 0, node->maptemp, 0, 0, node->propwidth, node->propheight, 0xc0, 0xff, NULL);
593 r = msg->wdp_PropRect;
594 StartX = r->MinX;
595 StartY = r->MinY;
596 MinX = 0;
597 MinY = 0;
598 MaxX = r->MaxX - r->MinX;
599 MaxY = r->MaxY - r->MinY;
601 if ((pi->Flags & FREEVERT) != 0)
603 is = data->img_verticalcontainer->w >> 1;
604 if (window->Flags & WFLG_WINDOWACTIVE) pos = 0; else pos = is;
605 y = MinY;
606 size = MaxY - MinY - data->ContainerTop_s - data->ContainerBottom_s + 1;
607 y = WriteTiledImageVertical(temp, maprp, data->img_verticalcontainer, pos, data->ContainerTop_o, is, data->ContainerTop_s, MinX, y, is, data->ContainerTop_s);
608 if (size > 0) y = WriteTiledImageVertical(temp, maprp, data->img_verticalcontainer, pos, data->ContainerVertTile_o, is, data->ContainerVertTile_s, MinX, y, is, size);
609 y = WriteTiledImageVertical(temp, maprp, data->img_verticalcontainer, pos, data->ContainerBottom_o, is, data->ContainerBottom_s, MinX, y, is, data->ContainerBottom_s);
611 else if ((pi->Flags & FREEHORIZ) != 0)
613 is = data->img_horizontalcontainer->h >> 1;
614 if (window->Flags & WFLG_WINDOWACTIVE) pos = 0; else pos = is;
615 x = MinX;
616 size = MaxX - MinX - data->ContainerLeft_s - data->ContainerRight_s + 1;
617 x = WriteTiledImageHorizontal(temp, maprp, data->img_horizontalcontainer, data->ContainerLeft_o, pos, data->ContainerLeft_s, is, x, MinY, data->ContainerLeft_s, is);
618 if (size > 0) x = WriteTiledImageHorizontal(temp, maprp, data->img_horizontalcontainer, data->ContainerHorTile_o, pos, data->ContainerHorTile_s, is, x, MinY, size, is);
619 x = WriteTiledImageHorizontal(temp, maprp, data->img_horizontalcontainer, data->ContainerRight_o, pos, data->ContainerRight_s, is, x, MinY, data->ContainerRight_s, is);
622 r = msg->wdp_RenderRect;
623 MinX = r->MinX - StartX;
624 MinY = r->MinY - StartY;
625 MaxX = r->MaxX - StartX;
626 MaxY = r->MaxY - StartY;
628 if ((pi->Flags & FREEVERT) != 0)
630 is = data->img_verticalknob->w / 3;
631 if (hit) pos = is; else if (window->Flags & WFLG_WINDOWACTIVE) pos = 0; else pos = is * 2;
632 y = MinY;
633 size = MaxY - MinY - data->KnobTop_s - data->KnobBottom_s + 1;
634 y = WriteTiledImageVertical(temp, maprp, data->img_verticalknob, pos, data->KnobTop_o, is, data->KnobTop_s, MinX, y, is, data->KnobTop_s);
635 if (size > 0) {
636 if (size > data->KnobVertGripper_s) {
637 size = size - data->KnobVertGripper_s;
638 int size_bak = size;
639 size = size / 2;
640 if (size > 0) y = WriteTiledImageVertical(temp, maprp, data->img_verticalknob, pos, data->KnobTileTop_o, is, data->KnobTileTop_s, MinX, y, is, size);
641 y = WriteTiledImageVertical(temp, maprp, data->img_verticalknob, pos, data->KnobVertGripper_o, is, data->KnobVertGripper_s, MinX, y, is, data->KnobVertGripper_s);
642 size = size_bak - size;
643 if (size > 0) y = WriteTiledImageVertical(temp, maprp, data->img_verticalknob, pos, data->KnobTileBottom_o, is, data->KnobTileBottom_s, MinX, y, is, size);
644 } else {
645 y = WriteTiledImageVertical(temp, maprp, data->img_verticalknob, pos, data->KnobTileTop_o, is, data->KnobTileTop_s, MinX, y, is, size);
648 y = WriteTiledImageVertical(temp, maprp, data->img_verticalknob, pos, data->KnobBottom_o, is, data->KnobBottom_s, MinX, y, is, data->KnobBottom_s);
650 else if ((pi->Flags & FREEHORIZ) != 0)
652 is = data->img_horizontalknob->h / 3;
653 if (hit) pos = is; else if (window->Flags & WFLG_WINDOWACTIVE) pos = 0; else pos = is * 2;
654 x = MinX;
655 size = MaxX - MinX - data->KnobLeft_s - data->KnobRight_s + 1;
656 x = WriteTiledImageHorizontal(temp, maprp, data->img_horizontalknob, data->KnobLeft_o, pos, data->KnobLeft_s, is, x, MinY, data->KnobLeft_s, is);
657 if (size > 0) {
658 if (size > data->KnobHorGripper_s) {
659 size = size - data->KnobHorGripper_s;
660 int size_bak = size;
661 size = size / 2;
662 if (size > 0) x = WriteTiledImageHorizontal(temp, maprp, data->img_horizontalknob, data->KnobTileLeft_o, pos, data->KnobTileLeft_s, is, x, MinY, size, is);
663 x = WriteTiledImageHorizontal(temp, maprp, data->img_horizontalknob, data->KnobHorGripper_o, pos, data->KnobHorGripper_s, is, x, MinY, data->KnobHorGripper_s, is);
664 size = size_bak - size;
665 if (size > 0) x = WriteTiledImageHorizontal(temp, maprp, data->img_horizontalknob, data->KnobTileRight_o, pos, data->KnobTileRight_s, is, x, MinY, size, is);
666 } else {
667 x = WriteTiledImageHorizontal(temp, maprp, data->img_horizontalknob, data->KnobTileRight_o, pos, data->KnobTileRight_s, is, x, MinY, size, is);
670 x = WriteTiledImageHorizontal(temp, maprp, data->img_horizontalknob, data->KnobRight_o, pos, data->KnobRight_s, is, x, MinY, data->KnobRight_s, is);
673 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);
674 if (node->maptemp) BltBitMapRastPort(node->maptemp, 0, 0, winrp, _left(node->obj), _top(node->obj), node->propwidth, node->propheight, 0xc0);
678 AROS_USERFUNC_EXIT
680 #endif
682 IPTR Prop__MUIM_Show(struct IClass *cl, Object *obj, struct MUIP_Show *msg)
684 struct Prop_DATA *data = INST_DATA(cl, obj);
685 struct MUI_AreaData *adata = muiAreaData(obj);
686 struct MUI_ImageSpec_intern *spec = adata->mad_Background;
688 ULONG rc = DoSuperMethodA(cl, obj, (Msg)msg);
689 #ifdef __AROS__
690 data->dhook.h_Entry = (HOOKFUNC) CustomPropRenderFunc;
691 #endif
692 if (!data->usewinborder)
694 BOOL isnewlook, completely_visible = TRUE;;
696 if (_flags(obj) & MADF_INVIRTUALGROUP)
698 Object *wnd, *parent;
700 get(obj, MUIA_WindowObject,&wnd);
701 parent = obj;
702 while (get(parent,MUIA_Parent,&parent))
704 if (!parent) break;
705 if (parent == wnd) break;
707 if (_flags(parent) & MADF_ISVIRTUALGROUP)
709 if ((_mleft(obj) < _mleft(parent)) ||
710 (_mright(obj) > _mright(parent)) ||
711 (_mtop(obj) < _mtop(parent)) ||
712 (_mbottom(obj) > _mbottom(parent)))
714 completely_visible = FALSE;
715 D(bug("=== prop object: completely visible FALSE for obj %x at %d,%d - %d,%d\n",
716 obj, _mleft(obj), _mtop(obj), _mright(obj), _mbottom(obj)));
717 break;
723 if (completely_visible)
725 if (muiGlobalInfo(obj)->mgi_Prefs->scrollbar_type == SCROLLBAR_TYPE_NEWLOOK)
726 isnewlook = TRUE;
727 else
728 isnewlook = FALSE;
730 ULONG width = _mwidth(obj);
731 ULONG height = _mheight(obj);
732 #ifdef __AROS__
733 struct Hook *dhook = NULL;
735 ULONG depth = (ULONG) GetBitMapAttr(_window(obj)->RPort->BitMap, BMA_DEPTH);
736 if (muiGlobalInfo(obj)->mgi_Prefs->scrollbar_type == SCROLLBAR_TYPE_CUSTOM)
738 if (spec)
740 if (spec->type == IST_BITMAP)
742 struct dt_node *node = spec->u.bitmap.dt;
743 if (node)
745 if (node->mode == MODE_PROP)
747 data->dhook.h_Entry = (HOOKFUNC) CustomPropRenderFunc;
748 data->node = node;
749 data->dhook.h_Data = data;
750 data->obj = obj;
751 dhook = &data->dhook;
753 if (data->horiz == TRUE) height = node->img_horizontalcontainer->h >> 1; else width = node->img_verticalcontainer->w >> 1;
754 DisposeImageContainer(data->buffer);
755 DisposeImageContainer(data->temp);
756 data->propwidth = width;
757 data->propheight = height;
758 if (data->mapbuffer) FreeBitMap(data->mapbuffer);
759 if (data->maptemp) FreeBitMap(data->maptemp);
760 if (depth >= 15)
762 data->buffer = NewImageContainer(width, height);
763 data->temp = NewImageContainer(width, height);
764 data->mapbuffer = NULL;
765 data->maptemp = NULL;
766 if ((data->buffer == NULL) || (data->temp == NULL))
768 dhook = NULL;
769 DisposeImageContainer(data->buffer);
770 DisposeImageContainer(data->temp);
771 data->buffer = NULL;
772 data->temp = NULL;
775 else
777 data->temp = NULL;
778 data->buffer = NULL;
779 data->tmprp = NULL;
780 data->mapbuffer = AllocBitMap(width, height, 1, BMF_MINPLANES, _window(obj)->RPort->BitMap);
781 data->maptemp = AllocBitMap(width, height, 1, BMF_MINPLANES, _window(obj)->RPort->BitMap);
782 data->tmprp = CreateRastPort();
783 if ((data->mapbuffer == NULL) || (data->maptemp == NULL) || (data->tmprp == NULL))
785 dhook = NULL;
786 if (data->mapbuffer) FreeBitMap(data->mapbuffer);
787 if (data->maptemp) FreeBitMap(data->maptemp);
788 if (data->tmprp) FreeRastPort(data->tmprp);
789 data->mapbuffer = NULL;
790 data->maptemp = NULL;
791 data->tmprp = NULL;
792 } else data->tmprp->BitMap = data->maptemp;
799 #endif
801 if (data->prop_object) {
802 RemoveGadget(_window(obj), (struct Gadget *) data->prop_object);
803 DisposeObject(data->prop_object);
806 if ((data->prop_object = NewObject(NULL, "propgclass",
807 GA_Left, _mleft(obj),
808 GA_Top, _mtop(obj),
809 GA_Width, width,
810 GA_Height, height,
811 GA_ID, data->gadgetid,
812 #ifdef __AROS__
813 PGA_DisplayHook, dhook, /* custom prop gadget impementation (not yet finished) */
814 #endif
815 PGA_Freedom, data->horiz?FREEHORIZ:FREEVERT,
816 PGA_Total, downscale(data, data->entries),
817 PGA_Visible, downscale(data, data->visible),
818 PGA_Top, downscale(data, data->first),
819 PGA_NewLook, isnewlook,
820 PGA_Borderless, TRUE,
821 ICA_TARGET , ICTARGET_IDCMP, /* needed for notification */
822 TAG_DONE)))
824 AddGadget(_window(obj),(struct Gadget*)data->prop_object,~0);
827 } else if (!data->prop_object)
829 switch (data->usewinborder)
831 case MUIV_Prop_UseWinBorder_Right:
832 data->prop_object = muiRenderInfo(obj)->mri_VertProp;
833 if (data->prop_object)
835 /* Store pointer to this propclass object in propgadget->UserData,
836 so that window class when receiving IDCMP_IDCMUPDATE from
837 arrow gadgets can notify propclass object */
839 ((struct Gadget *)data->prop_object)->UserData = obj;
841 break;
843 case MUIV_Prop_UseWinBorder_Bottom:
844 data->prop_object = muiRenderInfo(obj)->mri_HorizProp;
845 if (data->prop_object)
847 /* Store pointer to this propclass object in propgadget->UserData,
848 so that window class when receiving IDCMP_IDCMUPDATE from
849 arrow gadgets can notify propclass object */
851 ((struct Gadget *)data->prop_object)->UserData = obj;
853 break;
855 if (data->prop_object)
857 data->gadgetid = ((struct Gadget*)data->prop_object)->GadgetID;
859 SetAttrs(data->prop_object, ICA_TARGET, NULL, TAG_DONE);
860 if (SetGadgetAttrs((struct Gadget*)data->prop_object,_window(obj),NULL,
861 PGA_Top,downscale(data, data->first),
862 PGA_Visible,downscale(data, data->visible),
863 PGA_Total,downscale(data, data->entries),
864 TAG_DONE))
866 RefreshGList((struct Gadget*)data->prop_object, _window(obj), NULL, 1);
868 SetAttrs(data->prop_object, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
872 return rc;
875 IPTR Prop__MUIM_Draw(struct IClass *cl, Object *obj, struct MUIP_Draw *msg)
877 struct Prop_DATA *data = INST_DATA(cl, obj);
879 /* No drawings if own border */
880 if (data->usewinborder) return 0;
882 DoSuperMethodA(cl, obj, (Msg)msg);
884 if (!(msg->flags & MADF_DRAWOBJECT)) return 1;
886 if (data->buffer || data->mapbuffer)
888 // Object *p = NULL;
889 // get(obj, MUIA_Parent, &p);
890 //if (p) DoMethod(p, MUIM_DrawParentBackground, _left(obj), _top(obj), _width(obj), _height(obj), _left(obj), _top(obj), 0);
891 //else
892 DoMethod(obj, MUIM_DrawParentBackground, _left(obj), _top(obj), _width(obj), _height(obj), _left(obj), _top(obj), 0);
894 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);
895 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);
898 if (data->prop_object) RefreshGList((struct Gadget*)data->prop_object, _window(obj), NULL, 1);
899 return 1;
902 IPTR Prop__MUIM_Hide(struct IClass *cl, Object *obj, struct MUIP_Hide *msg)
904 struct Prop_DATA *data = INST_DATA(cl, obj);
906 if (data->prop_object)
908 if (!data->usewinborder)
910 RemoveGadget(_window(obj),(struct Gadget*)data->prop_object);
911 DisposeObject(data->prop_object);
912 data->prop_object = NULL;
916 return DoSuperMethodA(cl, obj, (Msg)msg);
919 IPTR Prop__MUIM_HandleEvent(struct IClass *cl, Object *obj, struct MUIP_HandleEvent *msg)
921 struct Prop_DATA *data = INST_DATA(cl, obj);
923 if (msg->imsg)
925 if (msg->imsg->Class == IDCMP_IDCMPUPDATE)
927 struct TagItem *tag;
928 ULONG v;
930 /* Check if we are meant */
931 tag = FindTagItem(GA_ID,(struct TagItem*)msg->imsg->IAddress);
932 if (!tag) return 0;
933 if (tag->ti_Data != data->gadgetid) return 0;
935 /* Check if we PGA_Top has really changed */
936 tag = FindTagItem(PGA_Top,(struct TagItem*)msg->imsg->IAddress);
937 if (!tag) return 0;
938 v = upscale(data, tag->ti_Data);
940 //kprintf("PROP_HandleEvent: PGA_Top %d upscaled %d entries %d\n", tag->ti_Data, v, data->entries);
942 if ((v == data->first) && (msg->imsg->Qualifier & IEQUALIFIER_REPEAT)) return 0;
944 if ((LONG)v < 0) v = 0;
946 SetAttrs(obj, MUIA_Prop_First, v, MUIA_Prop_OnlyTrigger, TRUE,
947 MUIA_Prop_Release, ((msg->imsg->Qualifier & IEQUALIFIER_REPEAT) ? FALSE : TRUE),
948 TAG_DONE);
952 return 0;
955 IPTR Prop__MUIM_Prop_Increase(struct IClass *cl, Object *obj, struct MUIP_Prop_Increase *msg)
957 struct Prop_DATA *data = INST_DATA(cl, obj);
958 LONG newfirst;
960 newfirst = data->first + msg->amount * data->deltafactor;
962 if (newfirst + data->visible > data->entries)
963 newfirst = data->entries - data->visible;
964 if (newfirst != data->first)
965 set(obj, MUIA_Prop_First, newfirst);
966 return 1;
969 IPTR Prop__MUIM_Prop_Decrease(struct IClass *cl, Object *obj, struct MUIP_Prop_Decrease *msg)
971 struct Prop_DATA *data = INST_DATA(cl, obj);
972 LONG newfirst;
974 /* We cannot decrease if if are on the top */
975 if (data->first <= 0)
976 return 1;
978 newfirst = data->first - msg->amount * data->deltafactor;
980 if (newfirst < 0)
981 set(obj, MUIA_Prop_First, 0);
982 else if (newfirst != data->first)
983 set(obj, MUIA_Prop_First, newfirst);
984 return 1;
988 BOOPSI_DISPATCHER(IPTR, Prop_Dispatcher, cl, obj, msg)
990 switch (msg->MethodID)
992 case OM_NEW: return Prop__OM_NEW(cl, obj, (struct opSet *) msg);
993 case OM_DISPOSE: return Prop__OM_DISPOSE(cl, obj, msg);
994 case OM_GET: return Prop__OM_GET(cl, obj, (struct opGet *)msg);
995 case OM_SET: return Prop__OM_SET(cl, obj, (struct opSet *)msg);
996 case MUIM_Setup: return Prop__MUIM_Setup(cl, obj, (APTR)msg);
997 case MUIM_Cleanup: return Prop__MUIM_Cleanup(cl, obj, (APTR)msg);
998 case MUIM_Show: return Prop__MUIM_Show(cl, obj, (APTR)msg);
999 case MUIM_Hide: return Prop__MUIM_Hide(cl, obj, (APTR)msg);
1000 case MUIM_AskMinMax: return Prop__MUIM_AskMinMax(cl, obj, (APTR)msg);
1001 case MUIM_Draw: return Prop__MUIM_Draw(cl, obj, (APTR)msg);
1002 case MUIM_HandleEvent: return Prop__MUIM_HandleEvent(cl, obj, (APTR)msg);
1003 case MUIM_Prop_Decrease: return Prop__MUIM_Prop_Decrease(cl, obj, (APTR)msg);
1004 case MUIM_Prop_Increase: return Prop__MUIM_Prop_Increase(cl, obj, (APTR)msg);
1005 default: return DoSuperMethodA(cl, obj, msg);
1009 BOOPSI_DISPATCHER_END
1011 const struct __MUIBuiltinClass _MUI_Prop_desc =
1013 MUIC_Prop,
1014 MUIC_Area,
1015 sizeof(struct Prop_DATA),
1016 (void*)Prop_Dispatcher