2 Copyright © 1995-2005, The AROS Development Team. All rights reserved.
5 Desc: AROS gradientslider gadget.
9 #include <exec/types.h>
12 //#define USE_BOOPSI_STUBS
13 #include <proto/utility.h>
14 #include <proto/intuition.h>
15 #include <proto/graphics.h>
16 #include <intuition/classes.h>
17 #include <intuition/classusr.h>
18 #include <intuition/cghooks.h>
19 #include <intuition/gadgetclass.h>
20 #include <intuition/imageclass.h>
21 #include <utility/tagitem.h>
22 #include <gadgets/gradientslider.h>
24 #include <aros/asmcall.h>
26 #include <stdlib.h> /* abs() */
27 #include "gradientslider_intern.h"
32 #include <aros/debug.h>
36 #include <intuition/icclass.h>
37 #include <intuition/classes.h>
38 #include <intuition/classusr.h>
39 #include <intuition/cghooks.h>
40 #include <intuition/gadgetclass.h>
41 #include <intuition/imageclass.h>
42 #include <utility/tagitem.h>
43 #include <gadgets/gradientslider.h>
45 #include <inline/graphics.h>
46 #include <inline/intuition.h>
47 #include <inline/exec.h>
48 #include <inline/utility.h>
49 #include <inline/cybergraphics.h>
51 #include "gradientslider_intern.h"
52 #include "BoopsiStubs.h"
60 void kprintf( STRPTR FormatStr
, ... )
64 struct Library
*SysBase
= (*(struct Library
**)4L);
65 RawDoFmt(FormatStr
, ((STRPTR
)(&FormatStr
))+4, (void (*)())"\x16\xc0\x4e\x75", PutChData
);
70 #define SysBase GSB(GradientSliderBase)->sysbase
74 LONG
myBltBitMap( struct BitMap
*srcBitMap
, long xSrc
, long ySrc
,
75 struct BitMap
*destBitMap
, long xDest
, long yDest
, long xSize
,
76 long ySize
, unsigned long minterm
, unsigned long mask
,
77 PLANEPTR tempA
, struct Library
*Graphics
);
82 /***************************************************************************************************/
84 STATIC VOID
notify_curval(Class
*cl
, Object
*o
, struct GadgetInfo
*gi
, BOOL interim
, BOOL userinput
)
86 struct GradientSliderData
*data
= INST_DATA(cl
, o
);
87 struct opUpdate opu
, *p_opu
= &opu
;
88 struct TagItem tags
[] =
90 {GA_ID
, EG(o
)->GadgetID
},
91 {GA_UserInput
, userinput
},
92 {GRAD_CurVal
, data
->curval
},
96 opu
.MethodID
= OM_NOTIFY
;
97 opu
.opu_AttrList
= tags
;
99 opu
.opu_Flags
= interim
? OPUF_INTERIM
: 0;
101 DoMethodA(o
, (Msg
)p_opu
);
104 /***************************************************************************************************/
106 IPTR
GradientSlider__OM_SET(Class
*cl
, Object
*o
, struct opSet
*msg
)
108 const struct TagItem
*tstate
;
111 struct GradientSliderData
*data
= INST_DATA(cl
, o
);
112 BOOL redraw_all
= data
->savebm
== NULL
;
113 LONG flags
= EG(o
)->Flags
;
115 EnterFunc(bug("GradientSlider::Set()\n"));
119 if (msg
->MethodID
!= OM_NEW
) retval
= DoSuperMethodA(cl
, o
, (Msg
)msg
);
121 tstate
= msg
->ops_AttrList
;
122 while((tag
= NextTagItem(&tstate
)))
124 IPTR tidata
= tag
->ti_Data
;
129 data
->curval
= (ULONG
)tidata
;
130 notify_curval(cl
, o
, msg
->ops_GInfo
, FALSE
, FALSE
);
135 if ((EG(o
)->Flags
&GFLG_DISABLED
) != (flags
&GFLG_DISABLED
))
143 if (tidata
> 0 && tidata
< 65536) // ReAction fix.
147 new_curval
= ( tidata
> 0L ) ? (((ULONG
)tidata
) * data
->curval
) / data
->maxval
: 0L;
148 data
->maxval
= (ULONG
)tidata
;
150 if (new_curval
!= data
->curval
)
152 data
->curval
= new_curval
;
153 notify_curval(cl
, o
, msg
->ops_GInfo
, FALSE
, FALSE
);
160 data
->skipval
= (ULONG
)tidata
;
165 if( tidata
) // REACTION_TextAttr collides with this one
167 UWORD
*pen
= (UWORD
*) tidata
;
169 if( ( pen
[0] & 0xff00 ) && ( pen
[0] != 0xffff ) )
172 if( ( pen
[1] & 0xff00 ) && ( pen
[1] != 0xffff ) )
176 data
->penarray
= (UWORD
*)tidata
;
181 UWORD
*pen
= data
->penarray
;
183 while(*pen
++ != (UWORD
)~0) data
->numpens
++;
194 } /* switch (tag->ti_Tag) */
196 } /* for (each attr in attrlist) */
202 if ((rp
= ObtainGIRPort(msg
->ops_GInfo
)))
204 DoMethod(o
, GM_RENDER
, (IPTR
)msg
->ops_GInfo
, (IPTR
)rp
, redraw_all
? GREDRAW_REDRAW
: GREDRAW_UPDATE
);
210 ReturnPtr ("GradientSlider::Set", IPTR
, retval
);
213 /***************************************************************************************************/
215 Object
*GradientSlider__OM_NEW(Class
*cl
, Object
*o
, struct opSet
*msg
)
217 EnterFunc(bug("GradientSlider::New()\n"));
219 o
= (Object
*)DoSuperMethodA(cl
, o
, (Msg
)msg
);
222 struct GradientSliderData
*data
= INST_DATA(cl
, o
);
223 static struct TagItem fitags
[]=
225 {IA_FrameType
, FRAME_BUTTON
},
229 if ((data
->frame
= NewObjectA(NULL
, FRAMEICLASS
, fitags
)))
231 data
->maxval
= 0xFFFF;
233 data
->skipval
= 0x1111;
234 data
->knobpixels
= GetTagData(GRAD_KnobPixels
, 5, msg
->ops_AttrList
);
235 data
->freedom
= GetTagData(PGA_Freedom
, LORIENT_HORIZ
, msg
->ops_AttrList
);
237 InitRastPort( &data
->trp
);
239 GradientSlider__OM_SET(cl
, o
, msg
);
242 CoerceMethod(cl
, o
, OM_DISPOSE
);
247 ReturnPtr ("GradientSlider::New", Object
*, o
);
250 /***************************************************************************************************/
252 VOID
GradientSlider__OM_DISPOSE(Class
*cl
, Object
*o
, Msg msg
)
254 struct GradientSliderData
*data
= INST_DATA(cl
, o
);
256 if (data
->frame
) DisposeObject(data
->frame
);
261 FreeBitMap(data
->savebm
);
267 FreeBitMap(data
->knobbm
);
272 FreeVec(data
->buffer
);
275 DeinitRastPort( &data
->trp
);
277 DoSuperMethodA(cl
, o
, msg
);
280 /***************************************************************************************************/
282 IPTR
GradientSlider__OM_GET(Class
*cl
, Object
*o
, struct opGet
*msg
)
284 struct GradientSliderData
*data
= INST_DATA(cl
, o
);
287 switch(msg
->opg_AttrID
)
290 *msg
->opg_Storage
= data
->maxval
;
294 *msg
->opg_Storage
= data
->curval
;
298 *msg
->opg_Storage
= data
->skipval
;
302 retval
= DoSuperMethodA(cl
, o
, (Msg
)msg
);
305 } /* switch(msg->opg_AttrID) */
310 /***************************************************************************************************/
312 VOID
GradientSlider__GM_RENDER(Class
*cl
, Object
*o
, struct gpRender
*msg
)
314 struct GradientSliderData
*data
= INST_DATA(cl
, o
);
315 struct DrawInfo
*dri
= msg
->gpr_GInfo
->gi_DrInfo
;
316 struct RastPort
*rp
= msg
->gpr_RPort
;
317 struct IBox gbox
, sbox
, kbox
;
318 LONG redraw
= msg
->gpr_Redraw
;
320 EnterFunc(bug("GradientSlider::Render()\n"));
322 GetGadgetIBox(o
, msg
->gpr_GInfo
, &gbox
);
323 GetSliderBox(&gbox
, &sbox
);
324 sbox
.Left
-= gbox
.Left
;
325 sbox
.Top
-= gbox
.Top
;
326 GetKnobBox(data
, &sbox
, &kbox
);
331 if ((kbox
.Width
<= sbox
.Width
) && (kbox
.Height
<= sbox
.Height
) && (data
->savebm
))
333 if( gbox
.Width
== data
->savebmwidth
&& gbox
.Height
== data
->savebmheight
)
335 if ((kbox
.Left
!= data
->savefromx
) || (kbox
.Top
!= data
->savefromy
))
337 /* Restore old area behind knob */
339 myBltBitMap( data
->knobbm
, 0,0, data
->savebm
, data
->savefromx
,data
->savefromy
, kbox
.Width
,kbox
.Height
, 0xc0, 0xff, NULL
, GfxBase
);
341 BltBitMap( data
->knobbm
, 0,0, data
->savebm
, data
->savefromx
,data
->savefromy
, kbox
.Width
,kbox
.Height
, 0xc0, 0xff, NULL
);
343 //BltBitMapRastPort( data->savebm, data->savefromx,data->savefromy, rp, gbox.Left+data->savefromx,gbox.Top+data->savefromy, kbox.Width,kbox.Height, 0xc0 );
345 data
->savefromx
= kbox
.Left
;
346 data
->savefromy
= kbox
.Top
;
348 myBltBitMap( data
->savebm
, kbox
.Left
,kbox
.Top
, data
->knobbm
, 0,0, kbox
.Width
,kbox
.Height
, 0xc0, 0xff, NULL
, GfxBase
);
350 BltBitMap( data
->savebm
, kbox
.Left
,kbox
.Top
, data
->knobbm
, 0,0, kbox
.Width
,kbox
.Height
, 0xc0, 0xff, NULL
);
352 data
->trp
.BitMap
= data
->savebm
;
354 DrawKnob(data
, &data
->trp
, dri
, &kbox
, 0);
355 //BltBitMapRastPort( data->savebm, kbox.Left,kbox.Top, rp, gbox.Left+kbox.Left,gbox.Top+kbox.Top, kbox.Width,kbox.Height, 0xc0 );
356 BltBitMapRastPort( data
->savebm
, sbox
.Left
,sbox
.Top
, rp
, gbox
.Left
+sbox
.Left
,gbox
.Top
+sbox
.Top
, sbox
.Width
,sbox
.Height
, 0xc0 );
357 } /* if (!data->savebm || (kbox.Left != data->savefromx) || (kbox.Top != data->savefromy)) */
362 } /* if ((kbox.Width <= sbox.Width) && (kbox.Height <= sbox.Height)) */
366 struct RastPort
*trp
= &data
->trp
;
368 if( gbox
.Width
!= data
->savebmwidth
|| gbox
.Height
!= data
->savebmheight
)
373 FreeBitMap( data
->savebm
);
380 FreeBitMap( data
->knobbm
);
386 FreeVec( data
->buffer
);
391 if( data
->savebm
== NULL
)
393 struct TagItem fitags
[] =
395 {IA_Width
, gbox
.Width
},
396 {IA_Height
, gbox
.Height
},
400 SetAttrsA(data
->frame
, fitags
);
402 if( ! ( data
->savebm
= AllocBitMap(
403 gbox
.Width
, gbox
.Height
,
404 GetBitMapAttr(rp
->BitMap
, BMA_DEPTH
),
405 BMF_MINPLANES
, rp
->BitMap
) ) )
410 data
->savebmwidth
= gbox
.Width
;
411 data
->savebmheight
= gbox
.Height
;
413 if( ! ( data
->knobbm
= AllocBitMap(
414 kbox
.Width
, kbox
.Height
,
415 GetBitMapAttr(data
->savebm
, BMA_DEPTH
),
416 BMF_MINPLANES
, data
->savebm
) ) )
418 FreeBitMap( data
->savebm
);
424 trp
->BitMap
= data
->savebm
;
425 DrawImageState( trp
, (struct Image
*) data
->frame
, 0,0, IDS_NORMAL
, dri
);
428 /* Draw slider background */
429 if( (sbox
.Width
>= 2) && (sbox
.Height
>= 2) )
431 if (data
->numpens
< 2)
433 WORD pen
= dri
->dri_Pens
[BACKGROUNDPEN
];
435 if (data
->penarray
&& (data
->numpens
== 1))
437 pen
= data
->penarray
[0];
442 RectFill(trp
, sbox
.Left
, sbox
.Top
, sbox
.Left
+ sbox
.Width
- 1, sbox
.Top
+ sbox
.Height
- 1);
443 } /* ff (data->numpens < 2) */
449 sbox
.Left
+ sbox
.Width
- 1,
450 sbox
.Top
+ sbox
.Height
- 1,
451 data
->penarray
, data
->numpens
, data
->freedom
,
452 msg
->gpr_GInfo
->gi_Screen
->ViewPort
.ColorMap
454 } /* data->numpens >= 2 */
455 } /* if ((sbox.Width >= 2) && (sbox.Height >= 2)) */
457 /* Backup area over which knob will be drawn */
458 if ((kbox
.Width
> 0) && (kbox
.Height
> 0) &&
459 (kbox
.Width
<= sbox
.Width
) && (kbox
.Height
<= sbox
.Height
))
462 myBltBitMap( data
->savebm
, kbox
.Left
,kbox
.Top
, data
->knobbm
, 0,0, kbox
.Width
,kbox
.Height
, 0xc0, 0xff, NULL
, GfxBase
);
464 BltBitMap( data
->savebm
, kbox
.Left
,kbox
.Top
, data
->knobbm
, 0,0, kbox
.Width
,kbox
.Height
, 0xc0, 0xff, NULL
);
467 data
->savefromx
= kbox
.Left
;
468 data
->savefromy
= kbox
.Top
;
471 DrawKnob(data
, trp
, dri
, &kbox
, 0);
472 } /* if ((kbox.Width > 0) && (kbox.Height > 0) && (kbox.Width <= sbox.Width) && (kbox.Height <= sbox.Height)) */
474 BltBitMapRastPort( data
->savebm
, 0,0, rp
, gbox
.Left
,gbox
.Top
,gbox
.Width
,gbox
.Height
, 0xc0 );
477 } /* switch (redraw) */
479 if( EG(o
)->Flags
& GFLG_DISABLED
)
480 DrawDisabledPattern( rp
, &gbox
, dri
->dri_Pens
[SHADOWPEN
]);
482 ReturnVoid("GradientSlider::Render");
485 /***************************************************************************************************/
487 IPTR
GradientSlider__GM_HITTEST(Class
*cl
, Object
*o
, struct gpHitTest
*msg
)
489 // struct GradientSliderData *data = INST_DATA(cl, o);
490 struct IBox gbox
, sbox
;
494 EnterFunc(bug("GradientSlider::HitTest()\n"));
496 if( EG(o
)->Flags
& GFLG_DISABLED
)
499 GetGadgetIBox(o
, msg
->gpht_GInfo
, &gbox
);
500 GetSliderBox(&gbox
, &sbox
);
502 if ((sbox
.Width
> 2) && (sbox
.Height
> 2))
504 /* calc mouse coords relative to slider box */
506 mousex
= msg
->gpht_Mouse
.X
- (sbox
.Left
- gbox
.Left
);
507 mousey
= msg
->gpht_Mouse
.Y
- (sbox
.Top
- gbox
.Top
);
509 if ((mousex
>= 0) && (mousey
>= 0) &&
510 (mousex
< sbox
.Width
) && (mousey
< sbox
.Height
)) retval
= GMR_GADGETHIT
;
513 ReturnInt("GradientSlider::HitTest", IPTR
, retval
);
516 /***************************************************************************************************/
518 IPTR
GradientSlider__GM_GOACTIVE(Class
*cl
, Object
*o
, struct gpInput
*msg
)
520 struct GradientSliderData
*data
= INST_DATA(cl
, o
);
521 struct IBox gbox
, sbox
, kbox
;
523 ULONG old_curval
= data
->curval
;
528 EnterFunc(bug("GradientSlider::GoActive()\n"));
530 if (!msg
->gpi_IEvent
) return GMR_NOREUSE
;
532 GetGadgetIBox(o
, msg
->gpi_GInfo
, &gbox
);
533 GetSliderBox(&gbox
, &sbox
);
534 GetKnobBox(data
, &sbox
, &kbox
);
536 mousex
= msg
->gpi_Mouse
.X
+ gbox
.Left
;
537 mousey
= msg
->gpi_Mouse
.Y
+ gbox
.Top
;
539 data
->x
= msg
->gpi_Mouse
.X
;
540 data
->y
= msg
->gpi_Mouse
.Y
;
542 data
->clickoffsetx
= mousex
- kbox
.Left
+ (sbox
.Left
- gbox
.Left
);
543 data
->clickoffsety
= mousey
- kbox
.Top
+ (sbox
.Top
- gbox
.Top
);
545 if ( ((data
->freedom
== LORIENT_HORIZ
) && (mousex
< kbox
.Left
)) ||
546 ((data
->freedom
== LORIENT_VERT
) && (mousey
< kbox
.Top
)) )
548 new_curval
= old_curval
- data
->skipval
;
549 if ((LONG
)new_curval
< 0) new_curval
= 0;
552 else if ( ((data
->freedom
== LORIENT_HORIZ
) && (mousex
>= kbox
.Left
+ kbox
.Width
)) ||
553 ((data
->freedom
== LORIENT_VERT
) && (mousey
>= kbox
.Top
+ kbox
.Height
)) )
556 new_curval
= old_curval
+ data
->skipval
;
557 if (new_curval
> data
->maxval
) new_curval
= (LONG
)data
->maxval
;
561 data
->saveval
= data
->curval
;
567 data
->curval
= new_curval
;
569 GetKnobBox(data
, &sbox
, &kbox
);
571 notify_curval(cl
, o
, msg
->gpi_GInfo
, FALSE
, TRUE
);
573 if ((rp
= ObtainGIRPort(msg
->gpi_GInfo
)))
575 DoMethod(o
, GM_RENDER
, (IPTR
)msg
->gpi_GInfo
, (IPTR
)rp
, GREDRAW_UPDATE
);
576 ReleaseGIRPort( rp
);
579 if( mousex >= kbox.Left &&
580 mousey >= kbox.Top &&
581 mousex < (kbox.Left+kbox.Width) &&
582 mousey < (kbox.Top+kbox.Height) )
584 data->clickoffsetx = mousex - kbox.Left + (sbox.Left - gbox.Left);
585 data->clickoffsety = mousey - kbox.Top + (sbox.Top - gbox.Top);
590 retval
= GMR_VERIFY
| GMR_NOREUSE
;
591 /* original AmigaOS gradientslider.gadget does not seem to place any meaningful
592 value into gpi_Termination :-\ */
593 *msg
->gpi_Termination
= data
->curval
;
596 retval
= GMR_MEACTIVE
;
599 ReturnInt("GradientSlider::GoActive", IPTR
, retval
);
602 /***************************************************************************************************/
604 IPTR
GradientSlider__GM_HANDLEINPUT(Class
*cl
, Object
*o
, struct gpInput
*msg
)
606 struct GradientSliderData
*data
= INST_DATA(cl
, o
);
607 struct IBox gbox
, sbox
, kbox
;
608 struct InputEvent
*ie
= msg
->gpi_IEvent
;
609 LONG new_curval
; /* use LONG instead of ULONG for easier checks against < 0 */
611 IPTR retval
= GMR_MEACTIVE
;
613 //EnterFunc(bug("GradientSlider::HandleInput\n"));
615 GetGadgetIBox(o
, msg
->gpi_GInfo
, &gbox
);
616 GetSliderBox(&gbox
, &sbox
);
617 GetKnobBox(data
, &sbox
, &kbox
);
621 case IECLASS_RAWMOUSE
:
625 retval
= GMR_VERIFY
| GMR_NOREUSE
;
626 /* original AmigaOS gradientslider.gadget does not seem to place any meaningful
627 value into gpi_Termination :-\ */
628 *msg
->gpi_Termination
= data
->curval
;
630 notify_curval(cl
, o
, msg
->gpi_GInfo
, FALSE
, TRUE
);
632 break; /* SELECTUP */
634 case IECODE_NOBUTTON
:
635 if( data
->x
== msg
->gpi_Mouse
.X
&& data
->y
== msg
->gpi_Mouse
.Y
)
638 data
->x
= msg
->gpi_Mouse
.X
;
639 data
->y
= msg
->gpi_Mouse
.Y
;
641 mousex
= msg
->gpi_Mouse
.X
- data
->clickoffsetx
;
642 mousey
= msg
->gpi_Mouse
.Y
- data
->clickoffsety
;
644 if (data
->freedom
== LORIENT_HORIZ
)
646 if (sbox
.Width
!= data
->knobpixels
) /* avoid div by 0 */
648 new_curval
= mousex
* ((LONG
)data
->maxval
) / (sbox
.Width
- (LONG
)data
->knobpixels
);
651 if (sbox
.Height
!= data
->knobpixels
) /* avoid div by 0 */
653 new_curval
= mousey
* ((LONG
)data
->maxval
) / (sbox
.Height
- (LONG
)data
->knobpixels
);
661 else if (new_curval
> data
->maxval
)
663 new_curval
= (LONG
)data
->maxval
;
666 if ((ULONG
)new_curval
!= data
->curval
)
670 data
->curval
= (ULONG
)new_curval
;
672 if ((rp
= ObtainGIRPort(msg
->gpi_GInfo
)))
674 DoMethod(o
, GM_RENDER
, (IPTR
)msg
->gpi_GInfo
, (IPTR
)rp
, GREDRAW_UPDATE
);
678 notify_curval(cl
, o
, msg
->gpi_GInfo
, TRUE
, TRUE
);
680 break; /* IECODE_NOBUTTON */
682 } /* switch(ie->ie_Code) */
684 break; /* IECLASS_RAWMOUSE */
686 } /* switch(ie->ie_Class) */
688 ReturnInt("GradientSlider::HandleInput", IPTR
, retval
);
691 /***************************************************************************************************/
693 IPTR
GradientSlider__GM_DOMAIN(Class
*cl
, Object
*o
, struct gpDomain
*msg
)
695 struct GradientSliderData
*data
= INST_DATA(cl
, o
);
696 struct DrawInfo
*dri
= (struct DrawInfo
*) GetTagData( GA_DrawInfo
, 0, msg
->gpd_Attrs
);
697 struct RastPort
*rp
= msg
->gpd_RPort
;
698 UWORD width
, height
, x
=1,y
=1;
702 y
= dri
->dri_Resolution
.X
;
703 x
= dri
->dri_Resolution
.Y
;
706 switch( msg
->gpd_Which
)
708 case GDOMAIN_MINIMUM
:
709 if( data
->freedom
== LORIENT_VERT
)
711 width
= 3 + ( ( rp
->TxHeight
* x
) / y
) + 3;
712 height
= 2 + (data
->knobpixels
*5) + 2;
716 width
= 3 + (data
->knobpixels
*5) + 3;
717 height
= 2 + rp
->TxHeight
+ 2;
721 case GDOMAIN_NOMINAL
:
722 if( data
->freedom
== LORIENT_VERT
)
724 width
= 3 + ( ( rp
->TxHeight
* x
) / y
) + 3;
725 height
= 2 + (10*data
->knobpixels
) + 2;
729 width
= 3 + (10*data
->knobpixels
) + 3;
730 height
= 2 + rp
->TxHeight
+ 2;
734 case GDOMAIN_MAXIMUM
:
735 if( data
->freedom
== LORIENT_VERT
)
737 width
= 3 + ( ( rp
->TxHeight
* x
) / y
) + 3;
743 height
= 2 + rp
->TxHeight
+ 2;
748 msg
->gpd_Domain
.Left
=
749 msg
->gpd_Domain
.Top
= 0;
750 msg
->gpd_Domain
.Width
= width
;
751 msg
->gpd_Domain
.Height
= height
;
756 /***************************************************************************************************/