use dmb/dsb from asm/cpu.h file.
[AROS.git] / workbench / libs / muimaster / classes / prop.c
blobd2057c9683d6773068edfe8f1e60a13f7910a777
1 /*
2 Copyright 2002-2012, 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 =
83 ((unsigned long long)data->entries) * 0x10000 / 65535;
85 data->scale16 = (ULONG) v;
88 #endif
90 static ULONG downscale(struct Prop_DATA *data, ULONG val)
92 #if SCALE16_METHOD == 1
93 if (data->scale16 != 0x10000)
95 unsigned long long v =
96 ((unsigned long long)val) * 0x10000 / data->scale16;
97 val = (ULONG) v;
99 #else
100 if (data->entries >= 0x10000)
102 unsigned long long v =
103 ((unsigned long long)val) * 65535 / data->entries;
104 val = (ULONG) v;
107 #endif
108 return val;
111 static ULONG upscale(struct Prop_DATA *data, ULONG val)
113 #if SCALE16_METHOD == 1
114 if (data->scale16 != 0x10000)
116 unsigned long long v =
117 ((unsigned long long)val) * data->scale16 / 0x10000;
118 val = (ULONG) v;
120 #else
121 if (data->entries >= 0x10000)
123 unsigned long long v =
124 ((unsigned long long)val) * data->entries / 65535;
125 val = (ULONG) v;
127 #endif
128 return val;
131 IPTR Prop__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
133 struct Prop_DATA *data;
134 struct TagItem *tags, *tag;
136 obj = (Object *) DoSuperNewTags(cl, obj, NULL,
137 MUIA_Background, MUII_PropBack, TAG_MORE, (IPTR) msg->ops_AttrList);
139 if (!obj)
140 return FALSE;
142 data = INST_DATA(cl, obj);
143 data->deltafactor = 1;
145 /* parse initial taglist */
146 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
148 switch (tag->ti_Tag)
150 case MUIA_Prop_Entries:
151 data->entries = tag->ti_Data;
152 break;
153 case MUIA_Prop_First:
154 data->first = tag->ti_Data;
155 break;
156 case MUIA_Prop_Horiz:
157 data->horiz = tag->ti_Data != 0;
158 break;
159 case MUIA_Prop_Slider:
160 break;
161 case MUIA_Prop_UseWinBorder:
162 data->usewinborder = tag->ti_Data;
163 break;
164 case MUIA_Prop_Visible:
165 data->visible = tag->ti_Data;
166 break;
168 case MUIA_Prop_DeltaFactor:
169 data->deltafactor = tag->ti_Data;
170 break;
174 if (data->horiz)
176 data->minwidth = 6;
177 data->minheight = 6;
178 data->maxwidth = MUI_MAXMAX;
179 data->maxheight = MUI_MAXMAX;
180 data->defwidth = 50;
181 data->defheight = 6;
183 else
185 data->minwidth = 6;
186 data->minheight = 6;
187 data->maxwidth = MUI_MAXMAX;
188 data->maxheight = MUI_MAXMAX;
189 data->defwidth = 6;
190 data->defheight = 50;
193 if (data->first < 0)
194 data->first = 0;
196 data->ehn.ehn_Events = IDCMP_IDCMPUPDATE;
197 data->ehn.ehn_Priority = 0;
198 data->ehn.ehn_Flags = 0;
199 data->ehn.ehn_Object = obj;
200 data->ehn.ehn_Class = cl;
202 if (data->usewinborder)
203 _flags(obj) |= MADF_BORDERGADGET;
205 calcscale16(data);
207 return (IPTR) obj;
210 IPTR Prop__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
212 struct Prop_DATA *data = INST_DATA(cl, obj);
214 if (data->prop_object && !data->usewinborder)
216 RemoveGadget(_window(obj), (struct Gadget *)data->prop_object);
217 DisposeObject(data->prop_object);
220 DisposeImageContainer(data->buffer);
221 DisposeImageContainer(data->temp);
222 if (data->mapbuffer != NULL)
223 FreeBitMap(data->mapbuffer);
224 if (data->maptemp != NULL)
225 FreeBitMap(data->maptemp);
226 if (data->tmprp != NULL)
227 FreeRastPort(data->tmprp);
229 data->buffer = NULL;
230 data->temp = NULL;
231 data->mapbuffer = NULL;
232 data->maptemp = NULL;
233 data->tmprp = NULL;
235 return DoSuperMethodA(cl, obj, msg);
238 IPTR Prop__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
240 struct TagItem *tags, *tag;
241 struct Prop_DATA *data = INST_DATA(cl, obj);
242 int refresh = 0;
243 int only_trigger = 0;
245 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
247 switch (tag->ti_Tag)
249 case MUIA_Prop_Entries:
250 if ((IPTR) data->entries != tag->ti_Data)
252 data->entries = tag->ti_Data;
253 refresh = 1;
255 else
257 tag->ti_Tag = TAG_IGNORE;
259 break;
261 case MUIA_Prop_First:
262 if ((IPTR) data->first != tag->ti_Data)
264 data->first = tag->ti_Data;
265 refresh = 1;
267 else
269 tag->ti_Tag = TAG_IGNORE;
271 break;
273 case MUIA_Prop_Slider:
274 break;
276 case MUIA_Prop_Visible:
277 if ((IPTR) data->visible != tag->ti_Data)
279 data->visible = tag->ti_Data;
280 refresh = 1;
282 else
284 tag->ti_Tag = TAG_IGNORE;
286 break;
288 case MUIA_Prop_OnlyTrigger:
289 only_trigger = tag->ti_Data;
290 break;
292 case MUIA_Prop_DeltaFactor:
293 data->deltafactor = tag->ti_Data;
294 break;
298 if (data->first < 0)
299 data->first = 0;
301 if (data->prop_object && refresh && !only_trigger)
303 calcscale16(data);
305 /* Rendering will happen here! This could make problems with
306 * virtual groups, forward this to MUIM_Draw??? */
307 SetAttrs(data->prop_object, ICA_TARGET, NULL, TAG_DONE);
308 if (SetGadgetAttrs((struct Gadget *)data->prop_object, _window(obj),
309 NULL, PGA_Top, downscale(data, data->first), PGA_Visible,
310 downscale(data, data->visible), PGA_Total, downscale(data,
311 data->entries), TAG_DONE))
312 RefreshGList((struct Gadget *)data->prop_object, _window(obj),
313 NULL, 1);
314 SetAttrs(data->prop_object, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
317 return DoSuperMethodA(cl, obj, (Msg) msg);
320 #define STORE *(msg->opg_Storage)
321 IPTR Prop__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
323 struct Prop_DATA *data = INST_DATA(cl, obj);
324 switch (msg->opg_AttrID)
326 case MUIA_Prop_First:
328 if (data->prop_object)
330 IPTR v;
331 /* So we can get a more current value */
332 GetAttr(PGA_Top, data->prop_object, &v);
333 data->first = upscale(data, v);
335 STORE = data->first;
336 return 1;
338 case MUIA_Prop_Entries:
339 STORE = data->entries;
340 return 1;
341 case MUIA_Prop_Visible:
342 STORE = data->visible;
343 return 1;
345 /* CHECKME: MUIA_Prop_Release
347 TextEditor.mcc sets up notification on slider obj which is subclass
348 of group and notification on group children (the prop object) will
349 be dropped if the child does not return TRUE on OM_GET.
351 It may be that MUI handles this differently, because a quick check
352 with UAE/MUI showed that a GetAttr() of MUIA_Prop_Release on alider
353 object does not work (returns FALSE). Maybe MUI slider class is
354 similiar to for exampe NListview.mcc which overrides MUIM_Notify
355 where it checks for known attributes and forwards the Method to
356 the correct child of the group.
358 case MUIA_Prop_Release:
359 STORE = 0;
360 return 1;
361 default:
362 return DoSuperMethodA(cl, obj, (Msg) msg);
365 return 1;
367 #undef STORE
369 IPTR Prop__MUIM_AskMinMax(struct IClass *cl, Object *obj,
370 struct MUIP_AskMinMax *msg)
372 struct Prop_DATA *data = INST_DATA(cl, obj);
375 ** let our superclass first fill in what it thinks about sizes.
376 ** this will e.g. add the size of frame and inner spacing.
378 DoSuperMethodA(cl, obj, (Msg) msg);
380 msg->MinMaxInfo->MinWidth += data->minwidth;
381 msg->MinMaxInfo->DefWidth += data->defwidth;
382 msg->MinMaxInfo->MaxWidth = data->maxwidth;
384 msg->MinMaxInfo->MinHeight += data->minheight;
385 msg->MinMaxInfo->DefHeight += data->defheight;
386 msg->MinMaxInfo->MaxHeight = data->maxheight;
388 D(bug("Prop %p minheigh=%d\n", obj, msg->MinMaxInfo->MinHeight));
390 return TRUE;
393 IPTR Prop__MUIM_Setup(struct IClass *cl, Object *obj,
394 struct MUIP_Setup *msg)
396 struct Prop_DATA *data = INST_DATA(cl, obj);
397 ULONG rc = DoSuperMethodA(cl, obj, (Msg) msg);
398 if (!rc)
399 return 0;
401 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR) & data->ehn);
403 data->buffer = NULL;
404 data->temp = NULL;
405 data->mapbuffer = NULL;
406 data->maptemp = NULL;
407 data->tmprp = NULL;
409 if (!data->usewinborder)
411 data->gadgetid = DoMethod(_win(obj), MUIM_Window_AllocGadgetID);
412 if (data->horiz)
414 data->minwidth = 6;
415 data->minheight = 6;
416 data->maxwidth = MUI_MAXMAX;
417 data->maxheight = MUI_MAXMAX;
418 data->defwidth = 50;
419 data->defheight = 6;
421 else
423 data->minwidth = 6;
424 data->minheight = 6;
425 data->maxwidth = MUI_MAXMAX;
426 data->maxheight = MUI_MAXMAX;
427 data->defwidth = 6;
428 data->defheight = 50;
431 struct MUI_AreaData *adata = muiAreaData(obj);
432 struct MUI_ImageSpec_intern *spec = adata->mad_Background;
434 if (spec)
436 if (spec->type == IST_BITMAP)
438 struct dt_node *node = spec->u.bitmap.dt;
439 if (node)
441 if (node->mode == MODE_PROP)
443 set(obj, MUIA_Frame, MUIV_Frame_None);
445 if (data->horiz)
447 data->minheight =
448 node->img_horizontalcontainer->h >> 1;
449 data->defheight = data->minheight;
450 data->maxheight = data->minheight;
452 else
454 data->minwidth =
455 node->img_verticalcontainer->w >> 1;
456 data->defwidth = data->minwidth;
457 data->maxwidth = data->minwidth;
465 return 1;
468 IPTR Prop__MUIM_Cleanup(struct IClass *cl, Object *obj,
469 struct MUIP_Cleanup *msg)
471 struct Prop_DATA *data = INST_DATA(cl, obj);
472 if (!data->usewinborder)
474 DoMethod(_win(obj), MUIM_Window_FreeGadgetID, data->gadgetid);
476 else
478 data->prop_object = NULL;
479 data->gadgetid = 0;
482 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR) & data->ehn);
483 return DoSuperMethodA(cl, obj, (Msg) msg);
486 void WritePixelArrayAlphaToImage(struct NewImage *in, UWORD sx, UWORD sy,
487 struct NewImage *out, UWORD xp, UWORD yp, UWORD w, UWORD h)
489 ULONG argb, rgb;
490 UBYTE rs, gs, bs, as, rd, gd, bd;
491 UWORD r, g, b;
492 UWORD x, y;
493 for (y = 0; y < h; y++)
495 for (x = 0; x < w; x++)
497 argb = in->data[x + sx + (y + sy) * in->w];
499 as = GET_A(argb);
500 rs = GET_R(argb);
501 gs = GET_G(argb);
502 bs = GET_B(argb);
503 // as = 255;
504 rgb = out->data[x + xp + (y + yp) * out->w];
506 rd = GET_R(rgb);
507 gd = GET_G(rgb);
508 bd = GET_B(rgb);
511 r = ((rs * as) >> 8) + ((rd * (255 - as)) >> 8);
512 g = ((gs * as) >> 8) + ((gd * (255 - as)) >> 8);
513 b = ((bs * as) >> 8) + ((bd * (255 - as)) >> 8);
515 out->data[x + xp + (y + yp) * out->w] = SET_ARGB(255, r, g, b);
521 int WriteTiledImageHorizontal(struct NewImage *dst, struct RastPort *maprp,
522 struct NewImage *ni, int sx, int sy, int sw, int sh, int xp, int yp,
523 int dw, int dh)
525 int w = dw;
526 int x = xp;
527 int ddw;
528 if ((sw == 0) || (dw == 0))
529 return xp;
531 while (w > 0)
533 ddw = sw;
534 if (w < ddw)
535 ddw = w;
537 if (dst != NULL)
538 WritePixelArrayAlphaToImage(ni, sx, sy, dst, x, yp, ddw, dh);
539 if ((maprp != NULL) && (ni->bitmap != NULL))
541 if (ni->mask)
543 BltMaskBitMapRastPort(ni->bitmap, sx, sy, maprp, x, yp, ddw,
544 dh, 0xe0, (PLANEPTR) ni->mask);
546 else
547 BltBitMapRastPort(ni->bitmap, sx, sy, maprp, x, yp, ddw, dh,
548 0xc0);
550 w -= ddw;
551 x += ddw;
553 return x;
556 int WriteTiledImageVertical(struct NewImage *dst, struct RastPort *maprp,
557 struct NewImage *ni, int sx, int sy, int sw, int sh, int xp, int yp,
558 int dw, int dh)
560 int h = dh;
561 int y = yp;
562 int ddh;
563 if ((sh == 0) || (dh == 0))
564 return yp;
565 while (h > 0)
567 ddh = sh;
568 if (h < ddh)
569 ddh = h;
571 if (dst != NULL)
572 WritePixelArrayAlphaToImage(ni, sx, sy, dst, xp, y, dw, ddh);
573 if ((maprp != NULL) && (ni->bitmap != NULL))
575 if (ni->mask)
577 BltMaskBitMapRastPort(ni->bitmap, sx, sy, maprp, xp, y, dw,
578 ddh, 0xe0, (PLANEPTR) ni->mask);
580 else
581 BltBitMapRastPort(ni->bitmap, sx, sy, maprp, xp, y, dw, ddh,
582 0xc0);
584 h -= ddh;
585 y += ddh;
587 return y;
590 #ifdef __AROS__
591 AROS_UFH3
592 (void, CustomPropRenderFunc,
593 AROS_UFHA(struct Hook *, h, A0),
594 AROS_UFHA(Object *, obj, A2),
595 AROS_UFHA(struct wdpDrawBorderPropKnob *, msg, A1))
597 AROS_USERFUNC_INIT
599 struct Prop_DATA *node = h->h_Data;
600 struct dt_node *data = node->node;
602 if (msg->MethodID == WDM_DRAW_BORDERPROPKNOB)
604 struct Window *window = msg->wdp_Window;
605 struct NewImage *temp;
606 struct RastPort *winrp = msg->wdp_RPort;
607 struct RastPort *maprp;
608 struct Gadget *gadget = msg->wdp_Gadget;
609 struct Rectangle *r = msg->wdp_RenderRect;
610 struct PropInfo *pi = ((struct PropInfo *)gadget->SpecialInfo);
611 BOOL hit = (msg->wdp_Flags & WDF_DBPK_HIT) ? TRUE : FALSE;
612 ULONG y, x;
613 int size, is, pos;
614 UWORD MinX, MinY, MaxX, MaxY, StartX, StartY;
617 int i;
619 temp = node->temp;
620 maprp = node->tmprp;
622 if (node->buffer)
623 for (i = 0; i < (node->buffer->w * node->buffer->h); i++)
624 node->temp->data[i] = node->buffer->data[i];
625 if (node->mapbuffer)
626 BltBitMap(node->mapbuffer, 0, 0, node->maptemp, 0, 0,
627 node->propwidth, node->propheight, 0xc0, 0xff, NULL);
630 r = msg->wdp_PropRect;
631 StartX = r->MinX;
632 StartY = r->MinY;
633 MinX = 0;
634 MinY = 0;
635 MaxX = r->MaxX - r->MinX;
636 MaxY = r->MaxY - r->MinY;
638 if ((pi->Flags & FREEVERT) != 0)
640 is = data->img_verticalcontainer->w >> 1;
641 if (window->Flags & WFLG_WINDOWACTIVE)
642 pos = 0;
643 else
644 pos = is;
645 y = MinY;
646 size =
647 MaxY - MinY - data->ContainerTop_s -
648 data->ContainerBottom_s + 1;
649 y = WriteTiledImageVertical(temp, maprp,
650 data->img_verticalcontainer, pos, data->ContainerTop_o, is,
651 data->ContainerTop_s, MinX, y, is, data->ContainerTop_s);
652 if (size > 0)
653 y = WriteTiledImageVertical(temp, maprp,
654 data->img_verticalcontainer, pos,
655 data->ContainerVertTile_o, is,
656 data->ContainerVertTile_s, MinX, y, is, size);
657 y = WriteTiledImageVertical(temp, maprp,
658 data->img_verticalcontainer, pos, data->ContainerBottom_o,
659 is, data->ContainerBottom_s, MinX, y, is,
660 data->ContainerBottom_s);
662 else if ((pi->Flags & FREEHORIZ) != 0)
664 is = data->img_horizontalcontainer->h >> 1;
665 if (window->Flags & WFLG_WINDOWACTIVE)
666 pos = 0;
667 else
668 pos = is;
669 x = MinX;
670 size =
671 MaxX - MinX - data->ContainerLeft_s -
672 data->ContainerRight_s + 1;
673 x = WriteTiledImageHorizontal(temp, maprp,
674 data->img_horizontalcontainer, data->ContainerLeft_o, pos,
675 data->ContainerLeft_s, is, x, MinY, data->ContainerLeft_s,
676 is);
677 if (size > 0)
678 x = WriteTiledImageHorizontal(temp, maprp,
679 data->img_horizontalcontainer, data->ContainerHorTile_o,
680 pos, data->ContainerHorTile_s, is, x, MinY, size, is);
681 x = WriteTiledImageHorizontal(temp, maprp,
682 data->img_horizontalcontainer, data->ContainerRight_o, pos,
683 data->ContainerRight_s, is, x, MinY, data->ContainerRight_s,
684 is);
687 r = msg->wdp_RenderRect;
688 MinX = r->MinX - StartX;
689 MinY = r->MinY - StartY;
690 MaxX = r->MaxX - StartX;
691 MaxY = r->MaxY - StartY;
693 if ((pi->Flags & FREEVERT) != 0)
695 is = data->img_verticalknob->w / 3;
696 if (hit)
697 pos = is;
698 else if (window->Flags & WFLG_WINDOWACTIVE)
699 pos = 0;
700 else
701 pos = is * 2;
702 y = MinY;
703 size = MaxY - MinY - data->KnobTop_s - data->KnobBottom_s + 1;
704 y = WriteTiledImageVertical(temp, maprp, data->img_verticalknob,
705 pos, data->KnobTop_o, is, data->KnobTop_s, MinX, y, is,
706 data->KnobTop_s);
707 if (size > 0)
709 if (size > data->KnobVertGripper_s)
711 size = size - data->KnobVertGripper_s;
712 int size_bak = size;
713 size = size / 2;
714 if (size > 0)
715 y = WriteTiledImageVertical(temp, maprp,
716 data->img_verticalknob, pos,
717 data->KnobTileTop_o, is, data->KnobTileTop_s,
718 MinX, y, is, size);
719 y = WriteTiledImageVertical(temp, maprp,
720 data->img_verticalknob, pos,
721 data->KnobVertGripper_o, is,
722 data->KnobVertGripper_s, MinX, y, is,
723 data->KnobVertGripper_s);
724 size = size_bak - size;
725 if (size > 0)
726 y = WriteTiledImageVertical(temp, maprp,
727 data->img_verticalknob, pos,
728 data->KnobTileBottom_o, is,
729 data->KnobTileBottom_s, MinX, y, is, size);
731 else
733 y = WriteTiledImageVertical(temp, maprp,
734 data->img_verticalknob, pos, data->KnobTileTop_o,
735 is, data->KnobTileTop_s, MinX, y, is, size);
738 y = WriteTiledImageVertical(temp, maprp, data->img_verticalknob,
739 pos, data->KnobBottom_o, is, data->KnobBottom_s, MinX, y,
740 is, data->KnobBottom_s);
742 else if ((pi->Flags & FREEHORIZ) != 0)
744 is = data->img_horizontalknob->h / 3;
745 if (hit)
746 pos = is;
747 else if (window->Flags & WFLG_WINDOWACTIVE)
748 pos = 0;
749 else
750 pos = is * 2;
751 x = MinX;
752 size = MaxX - MinX - data->KnobLeft_s - data->KnobRight_s + 1;
753 x = WriteTiledImageHorizontal(temp, maprp,
754 data->img_horizontalknob, data->KnobLeft_o, pos,
755 data->KnobLeft_s, is, x, MinY, data->KnobLeft_s, is);
756 if (size > 0)
758 if (size > data->KnobHorGripper_s)
760 size = size - data->KnobHorGripper_s;
761 int size_bak = size;
762 size = size / 2;
763 if (size > 0)
764 x = WriteTiledImageHorizontal(temp, maprp,
765 data->img_horizontalknob, data->KnobTileLeft_o,
766 pos, data->KnobTileLeft_s, is, x, MinY, size,
767 is);
768 x = WriteTiledImageHorizontal(temp, maprp,
769 data->img_horizontalknob, data->KnobHorGripper_o,
770 pos, data->KnobHorGripper_s, is, x, MinY,
771 data->KnobHorGripper_s, is);
772 size = size_bak - size;
773 if (size > 0)
774 x = WriteTiledImageHorizontal(temp, maprp,
775 data->img_horizontalknob, data->KnobTileRight_o,
776 pos, data->KnobTileRight_s, is, x, MinY, size,
777 is);
779 else
781 x = WriteTiledImageHorizontal(temp, maprp,
782 data->img_horizontalknob, data->KnobTileRight_o,
783 pos, data->KnobTileRight_s, is, x, MinY, size, is);
786 x = WriteTiledImageHorizontal(temp, maprp,
787 data->img_horizontalknob, data->KnobRight_o, pos,
788 data->KnobRight_s, is, x, MinY, data->KnobRight_s, is);
791 if (node->temp)
792 WritePixelArray(node->temp->data, 0, 0, node->temp->w * 4,
793 winrp, _left(node->obj), _top(node->obj), node->temp->w,
794 node->temp->h, RECTFMT_ARGB);
795 if (node->maptemp)
796 BltBitMapRastPort(node->maptemp, 0, 0, winrp, _left(node->obj),
797 _top(node->obj), node->propwidth, node->propheight, 0xc0);
801 AROS_USERFUNC_EXIT
803 #endif
805 IPTR Prop__MUIM_Show(struct IClass *cl, Object *obj, struct MUIP_Show *msg)
807 struct Prop_DATA *data = INST_DATA(cl, obj);
808 struct MUI_AreaData *adata = muiAreaData(obj);
809 struct MUI_ImageSpec_intern *spec = adata->mad_Background;
811 ULONG rc = DoSuperMethodA(cl, obj, (Msg) msg);
812 #ifdef __AROS__
813 data->dhook.h_Entry = (HOOKFUNC) CustomPropRenderFunc;
814 #endif
815 if (!data->usewinborder)
817 BOOL isnewlook, completely_visible = TRUE;;
819 if (_flags(obj) & MADF_INVIRTUALGROUP)
821 Object *wnd = NULL, *parent;
823 get(obj, MUIA_WindowObject, &wnd);
824 parent = obj;
825 while (get(parent, MUIA_Parent, &parent))
827 if (!parent)
828 break;
829 if (parent == wnd)
830 break;
832 if (_flags(parent) & MADF_ISVIRTUALGROUP)
834 if ((_mleft(obj) < _mleft(parent)) ||
835 (_mright(obj) > _mright(parent)) ||
836 (_mtop(obj) < _mtop(parent)) ||
837 (_mbottom(obj) > _mbottom(parent)))
839 completely_visible = FALSE;
840 D(bug("=== prop object: completely visible FALSE "
841 "for obj %x at %d,%d - %d,%d\n",
842 obj, _mleft(obj), _mtop(obj), _mright(obj),
843 _mbottom(obj)));
844 break;
850 if (completely_visible)
852 if (muiGlobalInfo(obj)->mgi_Prefs->scrollbar_type ==
853 SCROLLBAR_TYPE_NEWLOOK)
854 isnewlook = TRUE;
855 else
856 isnewlook = FALSE;
858 ULONG width = _mwidth(obj);
859 ULONG height = _mheight(obj);
860 #ifdef __AROS__
861 struct Hook *dhook = NULL;
863 ULONG depth =
864 (ULONG) GetBitMapAttr(_window(obj)->RPort->BitMap,
865 BMA_DEPTH);
866 if (muiGlobalInfo(obj)->mgi_Prefs->scrollbar_type ==
867 SCROLLBAR_TYPE_CUSTOM)
869 if (spec)
871 if (spec->type == IST_BITMAP)
873 struct dt_node *node = spec->u.bitmap.dt;
874 if (node)
876 if (node->mode == MODE_PROP)
878 data->dhook.h_Entry =
879 (HOOKFUNC) CustomPropRenderFunc;
880 data->node = node;
881 data->dhook.h_Data = data;
882 data->obj = obj;
883 dhook = &data->dhook;
885 if (data->horiz)
886 height =
887 node->img_horizontalcontainer->
888 h >> 1;
889 else
890 width =
891 node->img_verticalcontainer->w >> 1;
892 DisposeImageContainer(data->buffer);
893 DisposeImageContainer(data->temp);
894 data->propwidth = width;
895 data->propheight = height;
896 if (data->mapbuffer)
897 FreeBitMap(data->mapbuffer);
898 if (data->maptemp)
899 FreeBitMap(data->maptemp);
900 if (depth >= 15)
902 data->buffer =
903 NewImageContainer(width, height);
904 data->temp =
905 NewImageContainer(width, height);
906 data->mapbuffer = NULL;
907 data->maptemp = NULL;
908 if ((data->buffer == NULL)
909 || (data->temp == NULL))
911 dhook = NULL;
912 DisposeImageContainer(data->buffer);
913 DisposeImageContainer(data->temp);
914 data->buffer = NULL;
915 data->temp = NULL;
918 else
920 data->temp = NULL;
921 data->buffer = NULL;
922 data->tmprp = NULL;
923 data->mapbuffer =
924 AllocBitMap(width, height, 1,
925 BMF_MINPLANES,
926 _window(obj)->RPort->BitMap);
927 data->maptemp =
928 AllocBitMap(width, height, 1,
929 BMF_MINPLANES,
930 _window(obj)->RPort->BitMap);
931 data->tmprp = CreateRastPort();
932 if ((data->mapbuffer == NULL)
933 || (data->maptemp == NULL)
934 || (data->tmprp == NULL))
936 dhook = NULL;
937 if (data->mapbuffer)
938 FreeBitMap(data->mapbuffer);
939 if (data->maptemp)
940 FreeBitMap(data->maptemp);
941 if (data->tmprp)
942 FreeRastPort(data->tmprp);
943 data->mapbuffer = NULL;
944 data->maptemp = NULL;
945 data->tmprp = NULL;
947 else
948 data->tmprp->BitMap = data->maptemp;
955 #endif
957 if (data->prop_object)
959 RemoveGadget(_window(obj),
960 (struct Gadget *)data->prop_object);
961 DisposeObject(data->prop_object);
964 if ((data->prop_object = NewObject(NULL, "propgclass",
965 GA_Left, _mleft(obj),
966 GA_Top, _mtop(obj),
967 GA_Width, width,
968 GA_Height, height, GA_ID, data->gadgetid,
969 #ifdef __AROS__
970 /* custom prop gadget implementation (not finished) */
971 PGA_DisplayHook, dhook,
972 #endif
973 PGA_Freedom, data->horiz ? FREEHORIZ : FREEVERT,
974 PGA_Total, downscale(data, data->entries),
975 PGA_Visible, downscale(data, data->visible),
976 PGA_Top, downscale(data, data->first),
977 PGA_NewLook, isnewlook,
978 PGA_Borderless, TRUE,
979 ICA_TARGET, ICTARGET_IDCMP, /* for notification */
980 TAG_DONE)))
982 AddGadget(_window(obj), (struct Gadget *)data->prop_object,
983 ~0);
987 else if (!data->prop_object)
989 switch (data->usewinborder)
991 case MUIV_Prop_UseWinBorder_Right:
992 data->prop_object = muiRenderInfo(obj)->mri_VertProp;
993 if (data->prop_object)
995 /* Store pointer to this propclass object in
996 propgadget->UserData,
997 so that window class when receiving IDCMP_IDCMUPDATE from
998 arrow gadgets can notify propclass object */
1000 ((struct Gadget *)data->prop_object)->UserData = obj;
1002 break;
1004 case MUIV_Prop_UseWinBorder_Bottom:
1005 data->prop_object = muiRenderInfo(obj)->mri_HorizProp;
1006 if (data->prop_object)
1008 /* Store pointer to this propclass object in
1009 propgadget->UserData,
1010 so that window class when receiving IDCMP_IDCMUPDATE from
1011 arrow gadgets can notify propclass object */
1013 ((struct Gadget *)data->prop_object)->UserData = obj;
1015 break;
1017 if (data->prop_object)
1019 data->gadgetid = ((struct Gadget *)data->prop_object)->GadgetID;
1021 SetAttrs(data->prop_object, ICA_TARGET, NULL, TAG_DONE);
1022 if (SetGadgetAttrs((struct Gadget *)data->prop_object,
1023 _window(obj), NULL, PGA_Top, downscale(data,
1024 data->first), PGA_Visible, downscale(data,
1025 data->visible), PGA_Total, downscale(data,
1026 data->entries), TAG_DONE))
1028 RefreshGList((struct Gadget *)data->prop_object,
1029 _window(obj), NULL, 1);
1031 SetAttrs(data->prop_object, ICA_TARGET, ICTARGET_IDCMP,
1032 TAG_DONE);
1036 return rc;
1039 IPTR Prop__MUIM_Draw(struct IClass *cl, Object *obj,
1040 struct MUIP_Draw *msg)
1042 struct Prop_DATA *data = INST_DATA(cl, obj);
1044 /* No drawings if own border */
1045 if (data->usewinborder)
1046 return 0;
1048 DoSuperMethodA(cl, obj, (Msg) msg);
1050 if (!(msg->flags & MADF_DRAWOBJECT))
1051 return 1;
1053 if (data->buffer || data->mapbuffer)
1055 // Object *p = NULL;
1056 // get(obj, MUIA_Parent, &p);
1057 //if (p)
1058 // DoMethod(p, MUIM_DrawParentBackground, _left(obj), _top(obj),
1059 // _width(obj), _height(obj), _left(obj), _top(obj), 0);
1060 //else
1061 DoMethod(obj, MUIM_DrawParentBackground, _left(obj), _top(obj),
1062 _width(obj), _height(obj), _left(obj), _top(obj), 0);
1064 if (data->buffer)
1065 ReadPixelArray(data->buffer->data, 0, 0, data->buffer->w * 4,
1066 _rp(data->obj), _mleft(data->obj), _mtop(data->obj),
1067 data->buffer->w, data->buffer->h, RECTFMT_ARGB);
1068 if (data->mapbuffer)
1069 BltBitMap(_window(data->obj)->RPort->BitMap,
1070 _window(data->obj)->LeftEdge + _mleft(data->obj),
1071 _window(data->obj)->TopEdge + _mtop(data->obj),
1072 data->mapbuffer, 0, 0, data->propwidth, data->propheight,
1073 0xc0, 0xff, NULL);
1076 if (data->prop_object)
1077 RefreshGList((struct Gadget *)data->prop_object, _window(obj), NULL,
1079 return 1;
1082 IPTR Prop__MUIM_Hide(struct IClass *cl, Object *obj,
1083 struct MUIP_Hide *msg)
1085 struct Prop_DATA *data = INST_DATA(cl, obj);
1087 if (data->prop_object)
1089 if (!data->usewinborder)
1091 RemoveGadget(_window(obj), (struct Gadget *)data->prop_object);
1092 DisposeObject(data->prop_object);
1093 data->prop_object = NULL;
1097 return DoSuperMethodA(cl, obj, (Msg) msg);
1100 IPTR Prop__MUIM_HandleEvent(struct IClass *cl, Object *obj,
1101 struct MUIP_HandleEvent *msg)
1103 struct Prop_DATA *data = INST_DATA(cl, obj);
1105 if (msg->imsg)
1107 if (msg->imsg->Class == IDCMP_IDCMPUPDATE)
1109 struct TagItem *tag;
1110 ULONG v;
1112 /* Check if we are meant */
1113 tag = FindTagItem(GA_ID, (struct TagItem *)msg->imsg->IAddress);
1114 if (!tag)
1115 return 0;
1116 if (tag->ti_Data != data->gadgetid)
1117 return 0;
1119 /* Check if we PGA_Top has really changed */
1120 tag =
1121 FindTagItem(PGA_Top, (struct TagItem *)msg->imsg->IAddress);
1122 if (!tag)
1123 return 0;
1124 v = upscale(data, tag->ti_Data);
1126 //kprintf("PROP_HandleEvent: PGA_Top %d upscaled %d entries %d\n",
1127 // tag->ti_Data, v, data->entries);
1129 if ((v == data->first)
1130 && (msg->imsg->Qualifier & IEQUALIFIER_REPEAT))
1131 return 0;
1133 if ((LONG) v < 0)
1134 v = 0;
1136 SetAttrs(obj, MUIA_Prop_First, v, MUIA_Prop_OnlyTrigger, TRUE,
1137 MUIA_Prop_Release,
1138 ((msg->imsg->
1139 Qualifier & IEQUALIFIER_REPEAT) ? FALSE : TRUE),
1140 TAG_DONE);
1144 return 0;
1147 IPTR Prop__MUIM_Prop_Increase(struct IClass *cl, Object *obj,
1148 struct MUIP_Prop_Increase *msg)
1150 struct Prop_DATA *data = INST_DATA(cl, obj);
1151 LONG newfirst;
1153 newfirst = data->first + msg->amount * data->deltafactor;
1155 if (newfirst + data->visible > data->entries)
1156 newfirst = data->entries - data->visible;
1157 if (newfirst != data->first)
1158 set(obj, MUIA_Prop_First, newfirst);
1159 return 1;
1162 IPTR Prop__MUIM_Prop_Decrease(struct IClass *cl, Object *obj,
1163 struct MUIP_Prop_Decrease *msg)
1165 struct Prop_DATA *data = INST_DATA(cl, obj);
1166 LONG newfirst;
1168 /* We cannot decrease if if are on the top */
1169 if (data->first <= 0)
1170 return 1;
1172 newfirst = data->first - msg->amount * data->deltafactor;
1174 if (newfirst < 0)
1175 set(obj, MUIA_Prop_First, 0);
1176 else if (newfirst != data->first)
1177 set(obj, MUIA_Prop_First, newfirst);
1178 return 1;
1182 BOOPSI_DISPATCHER(IPTR, Prop_Dispatcher, cl, obj, msg)
1184 switch (msg->MethodID)
1186 case OM_NEW:
1187 return Prop__OM_NEW(cl, obj, (struct opSet *)msg);
1188 case OM_DISPOSE:
1189 return Prop__OM_DISPOSE(cl, obj, msg);
1190 case OM_GET:
1191 return Prop__OM_GET(cl, obj, (struct opGet *)msg);
1192 case OM_SET:
1193 return Prop__OM_SET(cl, obj, (struct opSet *)msg);
1194 case MUIM_Setup:
1195 return Prop__MUIM_Setup(cl, obj, (APTR) msg);
1196 case MUIM_Cleanup:
1197 return Prop__MUIM_Cleanup(cl, obj, (APTR) msg);
1198 case MUIM_Show:
1199 return Prop__MUIM_Show(cl, obj, (APTR) msg);
1200 case MUIM_Hide:
1201 return Prop__MUIM_Hide(cl, obj, (APTR) msg);
1202 case MUIM_AskMinMax:
1203 return Prop__MUIM_AskMinMax(cl, obj, (APTR) msg);
1204 case MUIM_Draw:
1205 return Prop__MUIM_Draw(cl, obj, (APTR) msg);
1206 case MUIM_HandleEvent:
1207 return Prop__MUIM_HandleEvent(cl, obj, (APTR) msg);
1208 case MUIM_Prop_Decrease:
1209 return Prop__MUIM_Prop_Decrease(cl, obj, (APTR) msg);
1210 case MUIM_Prop_Increase:
1211 return Prop__MUIM_Prop_Increase(cl, obj, (APTR) msg);
1212 default:
1213 return DoSuperMethodA(cl, obj, msg);
1217 BOOPSI_DISPATCHER_END
1219 const struct __MUIBuiltinClass _MUI_Prop_desc =
1221 MUIC_Prop,
1222 MUIC_Area,
1223 sizeof(struct Prop_DATA),
1224 (void *) Prop_Dispatcher