2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: AROS gradientslider gadget.
14 #include <aros/asmcall.h>
15 #include <aros/debug.h>
19 #include <intuition/icclass.h>
20 #include <intuition/classes.h>
21 #include <intuition/classusr.h>
22 #include <intuition/cghooks.h>
23 #include <intuition/gadgetclass.h>
24 #include <intuition/imageclass.h>
25 #include <utility/tagitem.h>
26 #include <gadgets/gradientslider.h>
28 #include <clib/alib_protos.h>
29 #include <proto/utility.h>
30 #include <proto/intuition.h>
31 #include <proto/graphics.h>
33 #include <stdlib.h> /* abs() */
35 #include "gradientslider_intern.h"
41 void kprintf( STRPTR FormatStr
, ... )
45 struct Library
*SysBase
= (*(struct Library
**)4L);
46 RawDoFmt(FormatStr
, ((STRPTR
)(&FormatStr
))+4, (void (*)())"\x16\xc0\x4e\x75", PutChData
);
51 #define SysBase GSB(GradientSliderBase)->sysbase
55 LONG
myBltBitMap( struct BitMap
*srcBitMap
, long xSrc
, long ySrc
,
56 struct BitMap
*destBitMap
, long xDest
, long yDest
, long xSize
,
57 long ySize
, unsigned long minterm
, unsigned long mask
,
58 PLANEPTR tempA
, struct Library
*Graphics
);
63 /***************************************************************************************************/
65 STATIC VOID
notify_curval(Class
*cl
, Object
*o
, struct GadgetInfo
*gi
, BOOL interim
, BOOL userinput
)
67 struct GradientSliderData
*data
= INST_DATA(cl
, o
);
68 struct opUpdate opu
, *p_opu
= &opu
;
69 struct TagItem tags
[] =
71 {GA_ID
, EG(o
)->GadgetID
},
72 {GA_UserInput
, userinput
},
73 {GRAD_CurVal
, data
->curval
},
77 opu
.MethodID
= OM_NOTIFY
;
78 opu
.opu_AttrList
= tags
;
80 opu
.opu_Flags
= interim
? OPUF_INTERIM
: 0;
82 DoMethodA(o
, (Msg
)p_opu
);
85 /***************************************************************************************************/
87 IPTR
GradientSlider__OM_SET(Class
*cl
, Object
*o
, struct opSet
*msg
)
89 struct TagItem
*tstate
;
92 struct GradientSliderData
*data
= INST_DATA(cl
, o
);
93 BOOL redraw_all
= data
->savebm
== NULL
;
94 LONG flags
= EG(o
)->Flags
;
96 EnterFunc(bug("GradientSlider::Set()\n"));
100 if (msg
->MethodID
!= OM_NEW
) retval
= DoSuperMethodA(cl
, o
, (Msg
)msg
);
102 tstate
= msg
->ops_AttrList
;
103 while((tag
= NextTagItem(&tstate
)))
105 IPTR tidata
= tag
->ti_Data
;
110 data
->curval
= (ULONG
)tidata
;
111 notify_curval(cl
, o
, msg
->ops_GInfo
, FALSE
, FALSE
);
116 if ((EG(o
)->Flags
&GFLG_DISABLED
) != (flags
&GFLG_DISABLED
))
124 if (tidata
> 0 && tidata
< 65536) // ReAction fix.
128 new_curval
= ( tidata
> 0L ) ? (((ULONG
)tidata
) * data
->curval
) / data
->maxval
: 0L;
129 data
->maxval
= (ULONG
)tidata
;
131 if (new_curval
!= data
->curval
)
133 data
->curval
= new_curval
;
134 notify_curval(cl
, o
, msg
->ops_GInfo
, FALSE
, FALSE
);
141 data
->skipval
= (ULONG
)tidata
;
146 if( tidata
) // REACTION_TextAttr collides with this one
148 UWORD
*pen
= (UWORD
*) tidata
;
150 if( ( pen
[0] & 0xff00 ) && ( pen
[0] != 0xffff ) )
153 if( ( pen
[1] & 0xff00 ) && ( pen
[1] != 0xffff ) )
157 data
->penarray
= (UWORD
*)tidata
;
162 UWORD
*pen
= data
->penarray
;
164 while(*pen
++ != (UWORD
)~0) data
->numpens
++;
175 } /* switch (tag->ti_Tag) */
177 } /* for (each attr in attrlist) */
183 if ((rp
= ObtainGIRPort(msg
->ops_GInfo
)))
185 DoMethod(o
, GM_RENDER
, (IPTR
)msg
->ops_GInfo
, (IPTR
)rp
, redraw_all
? GREDRAW_REDRAW
: GREDRAW_UPDATE
);
191 ReturnPtr ("GradientSlider::Set", IPTR
, retval
);
194 /***************************************************************************************************/
196 Object
*GradientSlider__OM_NEW(Class
*cl
, Object
*o
, struct opSet
*msg
)
198 EnterFunc(bug("GradientSlider::New()\n"));
200 o
= (Object
*)DoSuperMethodA(cl
, o
, (Msg
)msg
);
203 struct GradientSliderData
*data
= INST_DATA(cl
, o
);
204 static struct TagItem fitags
[]=
206 {IA_FrameType
, FRAME_BUTTON
},
210 if ((data
->frame
= NewObjectA(NULL
, FRAMEICLASS
, fitags
)))
212 data
->maxval
= 0xFFFF;
214 data
->skipval
= 0x1111;
215 data
->knobpixels
= GetTagData(GRAD_KnobPixels
, 5, msg
->ops_AttrList
);
216 data
->freedom
= GetTagData(PGA_Freedom
, LORIENT_HORIZ
, msg
->ops_AttrList
);
218 InitRastPort( &data
->trp
);
220 GradientSlider__OM_SET(cl
, o
, msg
);
223 CoerceMethod(cl
, o
, OM_DISPOSE
);
228 ReturnPtr ("GradientSlider::New", Object
*, o
);
231 /***************************************************************************************************/
233 VOID
GradientSlider__OM_DISPOSE(Class
*cl
, Object
*o
, Msg msg
)
235 struct GradientSliderData
*data
= INST_DATA(cl
, o
);
237 if (data
->frame
) DisposeObject(data
->frame
);
242 FreeBitMap(data
->savebm
);
248 FreeBitMap(data
->knobbm
);
253 FreeVec(data
->buffer
);
256 DoSuperMethodA(cl
, o
, msg
);
259 /***************************************************************************************************/
261 IPTR
GradientSlider__OM_GET(Class
*cl
, Object
*o
, struct opGet
*msg
)
263 struct GradientSliderData
*data
= INST_DATA(cl
, o
);
266 switch(msg
->opg_AttrID
)
269 *msg
->opg_Storage
= data
->maxval
;
273 *msg
->opg_Storage
= data
->curval
;
277 *msg
->opg_Storage
= data
->skipval
;
281 retval
= DoSuperMethodA(cl
, o
, (Msg
)msg
);
284 } /* switch(msg->opg_AttrID) */
289 /***************************************************************************************************/
291 VOID
GradientSlider__GM_RENDER(Class
*cl
, Object
*o
, struct gpRender
*msg
)
293 struct GradientSliderData
*data
= INST_DATA(cl
, o
);
294 struct DrawInfo
*dri
= msg
->gpr_GInfo
->gi_DrInfo
;
295 struct RastPort
*rp
= msg
->gpr_RPort
;
296 struct IBox gbox
, sbox
, kbox
;
297 LONG redraw
= msg
->gpr_Redraw
;
299 EnterFunc(bug("GradientSlider::Render()\n"));
301 GetGadgetIBox(o
, msg
->gpr_GInfo
, &gbox
);
302 GetSliderBox(&gbox
, &sbox
);
303 sbox
.Left
-= gbox
.Left
;
304 sbox
.Top
-= gbox
.Top
;
305 GetKnobBox(data
, &sbox
, &kbox
);
310 if ((kbox
.Width
<= sbox
.Width
) && (kbox
.Height
<= sbox
.Height
) && (data
->savebm
))
312 if( gbox
.Width
== data
->savebmwidth
&& gbox
.Height
== data
->savebmheight
)
314 if ((kbox
.Left
!= data
->savefromx
) || (kbox
.Top
!= data
->savefromy
))
316 /* Restore old area behind knob */
318 myBltBitMap( data
->knobbm
, 0,0, data
->savebm
, data
->savefromx
,data
->savefromy
, kbox
.Width
,kbox
.Height
, 0xc0, 0xff, NULL
, GfxBase
);
320 BltBitMap( data
->knobbm
, 0,0, data
->savebm
, data
->savefromx
,data
->savefromy
, kbox
.Width
,kbox
.Height
, 0xc0, 0xff, NULL
);
322 //BltBitMapRastPort( data->savebm, data->savefromx,data->savefromy, rp, gbox.Left+data->savefromx,gbox.Top+data->savefromy, kbox.Width,kbox.Height, 0xc0 );
324 data
->savefromx
= kbox
.Left
;
325 data
->savefromy
= kbox
.Top
;
327 myBltBitMap( data
->savebm
, kbox
.Left
,kbox
.Top
, data
->knobbm
, 0,0, kbox
.Width
,kbox
.Height
, 0xc0, 0xff, NULL
, GfxBase
);
329 BltBitMap( data
->savebm
, kbox
.Left
,kbox
.Top
, data
->knobbm
, 0,0, kbox
.Width
,kbox
.Height
, 0xc0, 0xff, NULL
);
331 data
->trp
.BitMap
= data
->savebm
;
333 DrawKnob(data
, &data
->trp
, dri
, &kbox
, 0);
334 //BltBitMapRastPort( data->savebm, kbox.Left,kbox.Top, rp, gbox.Left+kbox.Left,gbox.Top+kbox.Top, kbox.Width,kbox.Height, 0xc0 );
335 BltBitMapRastPort( data
->savebm
, sbox
.Left
,sbox
.Top
, rp
, gbox
.Left
+sbox
.Left
,gbox
.Top
+sbox
.Top
, sbox
.Width
,sbox
.Height
, 0xc0 );
336 } /* if (!data->savebm || (kbox.Left != data->savefromx) || (kbox.Top != data->savefromy)) */
341 } /* if ((kbox.Width <= sbox.Width) && (kbox.Height <= sbox.Height)) */
345 struct RastPort
*trp
= &data
->trp
;
347 if( gbox
.Width
!= data
->savebmwidth
|| gbox
.Height
!= data
->savebmheight
)
352 FreeBitMap( data
->savebm
);
359 FreeBitMap( data
->knobbm
);
365 FreeVec( data
->buffer
);
370 if( data
->savebm
== NULL
)
372 struct TagItem fitags
[] =
374 {IA_Width
, gbox
.Width
},
375 {IA_Height
, gbox
.Height
},
379 SetAttrsA(data
->frame
, fitags
);
381 if( ! ( data
->savebm
= AllocBitMap(
382 gbox
.Width
, gbox
.Height
,
383 GetBitMapAttr(rp
->BitMap
, BMA_DEPTH
),
384 BMF_MINPLANES
, rp
->BitMap
) ) )
389 data
->savebmwidth
= gbox
.Width
;
390 data
->savebmheight
= gbox
.Height
;
392 if( ! ( data
->knobbm
= AllocBitMap(
393 kbox
.Width
, kbox
.Height
,
394 GetBitMapAttr(data
->savebm
, BMA_DEPTH
),
395 BMF_MINPLANES
, data
->savebm
) ) )
397 FreeBitMap( data
->savebm
);
403 trp
->BitMap
= data
->savebm
;
404 DrawImageState( trp
, (struct Image
*) data
->frame
, 0,0, IDS_NORMAL
, dri
);
407 /* Draw slider background */
408 if( (sbox
.Width
>= 2) && (sbox
.Height
>= 2) )
410 if (data
->numpens
< 2)
412 WORD pen
= dri
->dri_Pens
[BACKGROUNDPEN
];
414 if (data
->penarray
&& (data
->numpens
== 1))
416 pen
= data
->penarray
[0];
421 RectFill(trp
, sbox
.Left
, sbox
.Top
, sbox
.Left
+ sbox
.Width
- 1, sbox
.Top
+ sbox
.Height
- 1);
422 } /* ff (data->numpens < 2) */
428 sbox
.Left
+ sbox
.Width
- 1,
429 sbox
.Top
+ sbox
.Height
- 1,
430 data
->penarray
, data
->numpens
, data
->freedom
,
431 msg
->gpr_GInfo
->gi_Screen
->ViewPort
.ColorMap
433 } /* data->numpens >= 2 */
434 } /* if ((sbox.Width >= 2) && (sbox.Height >= 2)) */
436 /* Backup area over which knob will be drawn */
437 if ((kbox
.Width
> 0) && (kbox
.Height
> 0) &&
438 (kbox
.Width
<= sbox
.Width
) && (kbox
.Height
<= sbox
.Height
))
441 myBltBitMap( data
->savebm
, kbox
.Left
,kbox
.Top
, data
->knobbm
, 0,0, kbox
.Width
,kbox
.Height
, 0xc0, 0xff, NULL
, GfxBase
);
443 BltBitMap( data
->savebm
, kbox
.Left
,kbox
.Top
, data
->knobbm
, 0,0, kbox
.Width
,kbox
.Height
, 0xc0, 0xff, NULL
);
446 data
->savefromx
= kbox
.Left
;
447 data
->savefromy
= kbox
.Top
;
450 DrawKnob(data
, trp
, dri
, &kbox
, 0);
451 } /* if ((kbox.Width > 0) && (kbox.Height > 0) && (kbox.Width <= sbox.Width) && (kbox.Height <= sbox.Height)) */
453 BltBitMapRastPort( data
->savebm
, 0,0, rp
, gbox
.Left
,gbox
.Top
,gbox
.Width
,gbox
.Height
, 0xc0 );
456 } /* switch (redraw) */
458 if( EG(o
)->Flags
& GFLG_DISABLED
)
459 DrawDisabledPattern( rp
, &gbox
, dri
->dri_Pens
[SHADOWPEN
]);
461 ReturnVoid("GradientSlider::Render");
464 /***************************************************************************************************/
466 IPTR
GradientSlider__GM_HITTEST(Class
*cl
, Object
*o
, struct gpHitTest
*msg
)
468 // struct GradientSliderData *data = INST_DATA(cl, o);
469 struct IBox gbox
, sbox
;
473 EnterFunc(bug("GradientSlider::HitTest()\n"));
475 if( EG(o
)->Flags
& GFLG_DISABLED
)
478 GetGadgetIBox(o
, msg
->gpht_GInfo
, &gbox
);
479 GetSliderBox(&gbox
, &sbox
);
481 if ((sbox
.Width
> 2) && (sbox
.Height
> 2))
483 /* calc mouse coords relative to slider box */
485 mousex
= msg
->gpht_Mouse
.X
- (sbox
.Left
- gbox
.Left
);
486 mousey
= msg
->gpht_Mouse
.Y
- (sbox
.Top
- gbox
.Top
);
488 if ((mousex
>= 0) && (mousey
>= 0) &&
489 (mousex
< sbox
.Width
) && (mousey
< sbox
.Height
)) retval
= GMR_GADGETHIT
;
492 ReturnInt("GradientSlider::HitTest", IPTR
, retval
);
495 /***************************************************************************************************/
497 IPTR
GradientSlider__GM_GOACTIVE(Class
*cl
, Object
*o
, struct gpInput
*msg
)
499 struct GradientSliderData
*data
= INST_DATA(cl
, o
);
500 struct IBox gbox
, sbox
, kbox
;
502 ULONG old_curval
= data
->curval
;
503 ULONG new_curval
= data
->curval
;
507 EnterFunc(bug("GradientSlider::GoActive()\n"));
509 if (!msg
->gpi_IEvent
) return GMR_NOREUSE
;
511 GetGadgetIBox(o
, msg
->gpi_GInfo
, &gbox
);
512 GetSliderBox(&gbox
, &sbox
);
513 GetKnobBox(data
, &sbox
, &kbox
);
515 mousex
= msg
->gpi_Mouse
.X
+ gbox
.Left
;
516 mousey
= msg
->gpi_Mouse
.Y
+ gbox
.Top
;
518 data
->x
= msg
->gpi_Mouse
.X
;
519 data
->y
= msg
->gpi_Mouse
.Y
;
521 data
->clickoffsetx
= mousex
- kbox
.Left
+ (sbox
.Left
- gbox
.Left
);
522 data
->clickoffsety
= mousey
- kbox
.Top
+ (sbox
.Top
- gbox
.Top
);
524 if ( ((data
->freedom
== LORIENT_HORIZ
) && (mousex
< kbox
.Left
)) ||
525 ((data
->freedom
== LORIENT_VERT
) && (mousey
< kbox
.Top
)) )
527 new_curval
= old_curval
- data
->skipval
;
528 if ((LONG
)new_curval
< 0) new_curval
= 0;
531 else if ( ((data
->freedom
== LORIENT_HORIZ
) && (mousex
>= kbox
.Left
+ kbox
.Width
)) ||
532 ((data
->freedom
== LORIENT_VERT
) && (mousey
>= kbox
.Top
+ kbox
.Height
)) )
535 new_curval
= old_curval
+ data
->skipval
;
536 if (new_curval
> data
->maxval
) new_curval
= (LONG
)data
->maxval
;
540 data
->saveval
= data
->curval
;
546 data
->curval
= new_curval
;
548 GetKnobBox(data
, &sbox
, &kbox
);
550 notify_curval(cl
, o
, msg
->gpi_GInfo
, FALSE
, TRUE
);
552 if ((rp
= ObtainGIRPort(msg
->gpi_GInfo
)))
554 DoMethod(o
, GM_RENDER
, (IPTR
)msg
->gpi_GInfo
, (IPTR
)rp
, GREDRAW_UPDATE
);
555 ReleaseGIRPort( rp
);
558 if( mousex >= kbox.Left &&
559 mousey >= kbox.Top &&
560 mousex < (kbox.Left+kbox.Width) &&
561 mousey < (kbox.Top+kbox.Height) )
563 data->clickoffsetx = mousex - kbox.Left + (sbox.Left - gbox.Left);
564 data->clickoffsety = mousey - kbox.Top + (sbox.Top - gbox.Top);
569 retval
= GMR_VERIFY
| GMR_NOREUSE
;
570 /* original AmigaOS gradientslider.gadget does not seem to place any meaningful
571 value into gpi_Termination :-\ */
572 *msg
->gpi_Termination
= data
->curval
;
575 retval
= GMR_MEACTIVE
;
578 ReturnInt("GradientSlider::GoActive", IPTR
, retval
);
581 /***************************************************************************************************/
583 IPTR
GradientSlider__GM_HANDLEINPUT(Class
*cl
, Object
*o
, struct gpInput
*msg
)
585 struct GradientSliderData
*data
= INST_DATA(cl
, o
);
586 struct IBox gbox
, sbox
, kbox
;
587 struct InputEvent
*ie
= msg
->gpi_IEvent
;
588 LONG new_curval
= 0; /* use LONG instead of ULONG for easier checks against < 0 */
590 IPTR retval
= GMR_MEACTIVE
;
592 //EnterFunc(bug("GradientSlider::HandleInput\n"));
594 GetGadgetIBox(o
, msg
->gpi_GInfo
, &gbox
);
595 GetSliderBox(&gbox
, &sbox
);
596 GetKnobBox(data
, &sbox
, &kbox
);
600 case IECLASS_RAWMOUSE
:
604 retval
= GMR_VERIFY
| GMR_NOREUSE
;
605 /* original AmigaOS gradientslider.gadget does not seem to place any meaningful
606 value into gpi_Termination :-\ */
607 *msg
->gpi_Termination
= data
->curval
;
609 notify_curval(cl
, o
, msg
->gpi_GInfo
, FALSE
, TRUE
);
611 break; /* SELECTUP */
613 case IECODE_NOBUTTON
:
614 if( data
->x
== msg
->gpi_Mouse
.X
&& data
->y
== msg
->gpi_Mouse
.Y
)
617 data
->x
= msg
->gpi_Mouse
.X
;
618 data
->y
= msg
->gpi_Mouse
.Y
;
620 mousex
= msg
->gpi_Mouse
.X
- data
->clickoffsetx
;
621 mousey
= msg
->gpi_Mouse
.Y
- data
->clickoffsety
;
623 if (data
->freedom
== LORIENT_HORIZ
)
625 if (sbox
.Width
!= data
->knobpixels
) /* avoid div by 0 */
627 new_curval
= mousex
* ((LONG
)data
->maxval
) / (sbox
.Width
- (LONG
)data
->knobpixels
);
630 if (sbox
.Height
!= data
->knobpixels
) /* avoid div by 0 */
632 new_curval
= mousey
* ((LONG
)data
->maxval
) / (sbox
.Height
- (LONG
)data
->knobpixels
);
640 else if (new_curval
> data
->maxval
)
642 new_curval
= (LONG
)data
->maxval
;
645 if ((ULONG
)new_curval
!= data
->curval
)
649 data
->curval
= (ULONG
)new_curval
;
651 if ((rp
= ObtainGIRPort(msg
->gpi_GInfo
)))
653 DoMethod(o
, GM_RENDER
, (IPTR
)msg
->gpi_GInfo
, (IPTR
)rp
, GREDRAW_UPDATE
);
657 notify_curval(cl
, o
, msg
->gpi_GInfo
, TRUE
, TRUE
);
659 break; /* IECODE_NOBUTTON */
661 } /* switch(ie->ie_Code) */
663 break; /* IECLASS_RAWMOUSE */
665 } /* switch(ie->ie_Class) */
667 ReturnInt("GradientSlider::HandleInput", IPTR
, retval
);
670 /***************************************************************************************************/
672 IPTR
GradientSlider__GM_DOMAIN(Class
*cl
, Object
*o
, struct gpDomain
*msg
)
674 struct GradientSliderData
*data
= INST_DATA(cl
, o
);
675 struct DrawInfo
*dri
= (struct DrawInfo
*) GetTagData( GA_DrawInfo
, 0, msg
->gpd_Attrs
);
676 struct RastPort
*rp
= msg
->gpd_RPort
;
677 UWORD width
= 0, height
= 0, x
=1,y
=1;
681 y
= dri
->dri_Resolution
.X
;
682 x
= dri
->dri_Resolution
.Y
;
685 switch( msg
->gpd_Which
)
687 case GDOMAIN_MINIMUM
:
688 if( data
->freedom
== LORIENT_VERT
)
690 width
= 3 + ( ( rp
->TxHeight
* x
) / y
) + 3;
691 height
= 2 + (data
->knobpixels
*5) + 2;
695 width
= 3 + (data
->knobpixels
*5) + 3;
696 height
= 2 + rp
->TxHeight
+ 2;
700 case GDOMAIN_NOMINAL
:
701 if( data
->freedom
== LORIENT_VERT
)
703 width
= 3 + ( ( rp
->TxHeight
* x
) / y
) + 3;
704 height
= 2 + (10*data
->knobpixels
) + 2;
708 width
= 3 + (10*data
->knobpixels
) + 3;
709 height
= 2 + rp
->TxHeight
+ 2;
713 case GDOMAIN_MAXIMUM
:
714 if( data
->freedom
== LORIENT_VERT
)
716 width
= 3 + ( ( rp
->TxHeight
* x
) / y
) + 3;
722 height
= 2 + rp
->TxHeight
+ 2;
727 msg
->gpd_Domain
.Left
=
728 msg
->gpd_Domain
.Top
= 0;
729 msg
->gpd_Domain
.Width
= width
;
730 msg
->gpd_Domain
.Height
= height
;
735 /***************************************************************************************************/