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 struct TagItem
*tag
, *tstate
;
110 struct GradientSliderData
*data
= INST_DATA(cl
, o
);
111 BOOL redraw_all
= data
->savebm
== NULL
;
112 LONG flags
= EG(o
)->Flags
;
114 EnterFunc(bug("GradientSlider::Set()\n"));
118 if (msg
->MethodID
!= OM_NEW
) retval
= DoSuperMethodA(cl
, o
, (Msg
)msg
);
120 tstate
= msg
->ops_AttrList
;
121 while((tag
= NextTagItem(&tstate
)))
123 IPTR tidata
= tag
->ti_Data
;
128 data
->curval
= (ULONG
)tidata
;
129 notify_curval(cl
, o
, msg
->ops_GInfo
, FALSE
, FALSE
);
134 if ((EG(o
)->Flags
&GFLG_DISABLED
) != (flags
&GFLG_DISABLED
))
142 if (tidata
> 0 && tidata
< 65536) // ReAction fix.
146 new_curval
= ( tidata
> 0L ) ? (((ULONG
)tidata
) * data
->curval
) / data
->maxval
: 0L;
147 data
->maxval
= (ULONG
)tidata
;
149 if (new_curval
!= data
->curval
)
151 data
->curval
= new_curval
;
152 notify_curval(cl
, o
, msg
->ops_GInfo
, FALSE
, FALSE
);
159 data
->skipval
= (ULONG
)tidata
;
164 if( tidata
) // REACTION_TextAttr collides with this one
166 UWORD
*pen
= (UWORD
*) tidata
;
168 if( ( pen
[0] & 0xff00 ) && ( pen
[0] != 0xffff ) )
171 if( ( pen
[1] & 0xff00 ) && ( pen
[1] != 0xffff ) )
175 data
->penarray
= (UWORD
*)tidata
;
180 UWORD
*pen
= data
->penarray
;
182 while(*pen
++ != (UWORD
)~0) data
->numpens
++;
193 } /* switch (tag->ti_Tag) */
195 } /* for (each attr in attrlist) */
201 if ((rp
= ObtainGIRPort(msg
->ops_GInfo
)))
203 DoMethod(o
, GM_RENDER
, (IPTR
)msg
->ops_GInfo
, (IPTR
)rp
, redraw_all
? GREDRAW_REDRAW
: GREDRAW_UPDATE
);
209 ReturnPtr ("GradientSlider::Set", IPTR
, retval
);
212 /***************************************************************************************************/
214 Object
*GradientSlider__OM_NEW(Class
*cl
, Object
*o
, struct opSet
*msg
)
216 EnterFunc(bug("GradientSlider::New()\n"));
218 o
= (Object
*)DoSuperMethodA(cl
, o
, (Msg
)msg
);
221 struct GradientSliderData
*data
= INST_DATA(cl
, o
);
222 static struct TagItem fitags
[]=
224 {IA_FrameType
, FRAME_BUTTON
},
228 if ((data
->frame
= NewObjectA(NULL
, FRAMEICLASS
, fitags
)))
230 data
->maxval
= 0xFFFF;
232 data
->skipval
= 0x1111;
233 data
->knobpixels
= GetTagData(GRAD_KnobPixels
, 5, msg
->ops_AttrList
);
234 data
->freedom
= GetTagData(PGA_Freedom
, LORIENT_HORIZ
, msg
->ops_AttrList
);
236 InitRastPort( &data
->trp
);
238 GradientSlider__OM_SET(cl
, o
, msg
);
241 CoerceMethod(cl
, o
, OM_DISPOSE
);
246 ReturnPtr ("GradientSlider::New", Object
*, o
);
249 /***************************************************************************************************/
251 VOID
GradientSlider__OM_DISPOSE(Class
*cl
, Object
*o
, Msg msg
)
253 struct GradientSliderData
*data
= INST_DATA(cl
, o
);
255 if (data
->frame
) DisposeObject(data
->frame
);
260 FreeBitMap(data
->savebm
);
266 FreeBitMap(data
->knobbm
);
271 FreeVec(data
->buffer
);
274 DeinitRastPort( &data
->trp
);
276 DoSuperMethodA(cl
, o
, msg
);
279 /***************************************************************************************************/
281 IPTR
GradientSlider__OM_GET(Class
*cl
, Object
*o
, struct opGet
*msg
)
283 struct GradientSliderData
*data
= INST_DATA(cl
, o
);
286 switch(msg
->opg_AttrID
)
289 *msg
->opg_Storage
= data
->maxval
;
293 *msg
->opg_Storage
= data
->curval
;
297 *msg
->opg_Storage
= data
->skipval
;
301 retval
= DoSuperMethodA(cl
, o
, (Msg
)msg
);
304 } /* switch(msg->opg_AttrID) */
309 /***************************************************************************************************/
311 VOID
GradientSlider__GM_RENDER(Class
*cl
, Object
*o
, struct gpRender
*msg
)
313 struct GradientSliderData
*data
= INST_DATA(cl
, o
);
314 struct DrawInfo
*dri
= msg
->gpr_GInfo
->gi_DrInfo
;
315 struct RastPort
*rp
= msg
->gpr_RPort
;
316 struct IBox gbox
, sbox
, kbox
;
317 LONG redraw
= msg
->gpr_Redraw
;
319 EnterFunc(bug("GradientSlider::Render()\n"));
321 GetGadgetIBox(o
, msg
->gpr_GInfo
, &gbox
);
322 GetSliderBox(&gbox
, &sbox
);
323 sbox
.Left
-= gbox
.Left
;
324 sbox
.Top
-= gbox
.Top
;
325 GetKnobBox(data
, &sbox
, &kbox
);
330 if ((kbox
.Width
<= sbox
.Width
) && (kbox
.Height
<= sbox
.Height
) && (data
->savebm
))
332 if( gbox
.Width
== data
->savebmwidth
&& gbox
.Height
== data
->savebmheight
)
334 if ((kbox
.Left
!= data
->savefromx
) || (kbox
.Top
!= data
->savefromy
))
336 /* Restore old area behind knob */
338 myBltBitMap( data
->knobbm
, 0,0, data
->savebm
, data
->savefromx
,data
->savefromy
, kbox
.Width
,kbox
.Height
, 0xc0, 0xff, NULL
, GfxBase
);
340 BltBitMap( data
->knobbm
, 0,0, data
->savebm
, data
->savefromx
,data
->savefromy
, kbox
.Width
,kbox
.Height
, 0xc0, 0xff, NULL
);
342 //BltBitMapRastPort( data->savebm, data->savefromx,data->savefromy, rp, gbox.Left+data->savefromx,gbox.Top+data->savefromy, kbox.Width,kbox.Height, 0xc0 );
344 data
->savefromx
= kbox
.Left
;
345 data
->savefromy
= kbox
.Top
;
347 myBltBitMap( data
->savebm
, kbox
.Left
,kbox
.Top
, data
->knobbm
, 0,0, kbox
.Width
,kbox
.Height
, 0xc0, 0xff, NULL
, GfxBase
);
349 BltBitMap( data
->savebm
, kbox
.Left
,kbox
.Top
, data
->knobbm
, 0,0, kbox
.Width
,kbox
.Height
, 0xc0, 0xff, NULL
);
351 data
->trp
.BitMap
= data
->savebm
;
353 DrawKnob(data
, &data
->trp
, dri
, &kbox
, 0);
354 //BltBitMapRastPort( data->savebm, kbox.Left,kbox.Top, rp, gbox.Left+kbox.Left,gbox.Top+kbox.Top, kbox.Width,kbox.Height, 0xc0 );
355 BltBitMapRastPort( data
->savebm
, sbox
.Left
,sbox
.Top
, rp
, gbox
.Left
+sbox
.Left
,gbox
.Top
+sbox
.Top
, sbox
.Width
,sbox
.Height
, 0xc0 );
356 } /* if (!data->savebm || (kbox.Left != data->savefromx) || (kbox.Top != data->savefromy)) */
361 } /* if ((kbox.Width <= sbox.Width) && (kbox.Height <= sbox.Height)) */
365 struct RastPort
*trp
= &data
->trp
;
367 if( gbox
.Width
!= data
->savebmwidth
|| gbox
.Height
!= data
->savebmheight
)
372 FreeBitMap( data
->savebm
);
379 FreeBitMap( data
->knobbm
);
385 FreeVec( data
->buffer
);
390 if( data
->savebm
== NULL
)
392 struct TagItem fitags
[] =
394 {IA_Width
, gbox
.Width
},
395 {IA_Height
, gbox
.Height
},
399 SetAttrsA(data
->frame
, fitags
);
401 if( ! ( data
->savebm
= AllocBitMap(
402 gbox
.Width
, gbox
.Height
,
403 GetBitMapAttr(rp
->BitMap
, BMA_DEPTH
),
404 BMF_MINPLANES
, rp
->BitMap
) ) )
409 data
->savebmwidth
= gbox
.Width
;
410 data
->savebmheight
= gbox
.Height
;
412 if( ! ( data
->knobbm
= AllocBitMap(
413 kbox
.Width
, kbox
.Height
,
414 GetBitMapAttr(data
->savebm
, BMA_DEPTH
),
415 BMF_MINPLANES
, data
->savebm
) ) )
417 FreeBitMap( data
->savebm
);
423 trp
->BitMap
= data
->savebm
;
424 DrawImageState( trp
, (struct Image
*) data
->frame
, 0,0, IDS_NORMAL
, dri
);
427 /* Draw slider background */
428 if( (sbox
.Width
>= 2) && (sbox
.Height
>= 2) )
430 if (data
->numpens
< 2)
432 WORD pen
= dri
->dri_Pens
[BACKGROUNDPEN
];
434 if (data
->penarray
&& (data
->numpens
== 1))
436 pen
= data
->penarray
[0];
441 RectFill(trp
, sbox
.Left
, sbox
.Top
, sbox
.Left
+ sbox
.Width
- 1, sbox
.Top
+ sbox
.Height
- 1);
442 } /* ff (data->numpens < 2) */
448 sbox
.Left
+ sbox
.Width
- 1,
449 sbox
.Top
+ sbox
.Height
- 1,
450 data
->penarray
, data
->numpens
, data
->freedom
,
451 msg
->gpr_GInfo
->gi_Screen
->ViewPort
.ColorMap
453 } /* data->numpens >= 2 */
454 } /* if ((sbox.Width >= 2) && (sbox.Height >= 2)) */
456 /* Backup area over which knob will be drawn */
457 if ((kbox
.Width
> 0) && (kbox
.Height
> 0) &&
458 (kbox
.Width
<= sbox
.Width
) && (kbox
.Height
<= sbox
.Height
))
461 myBltBitMap( data
->savebm
, kbox
.Left
,kbox
.Top
, data
->knobbm
, 0,0, kbox
.Width
,kbox
.Height
, 0xc0, 0xff, NULL
, GfxBase
);
463 BltBitMap( data
->savebm
, kbox
.Left
,kbox
.Top
, data
->knobbm
, 0,0, kbox
.Width
,kbox
.Height
, 0xc0, 0xff, NULL
);
466 data
->savefromx
= kbox
.Left
;
467 data
->savefromy
= kbox
.Top
;
470 DrawKnob(data
, trp
, dri
, &kbox
, 0);
471 } /* if ((kbox.Width > 0) && (kbox.Height > 0) && (kbox.Width <= sbox.Width) && (kbox.Height <= sbox.Height)) */
473 BltBitMapRastPort( data
->savebm
, 0,0, rp
, gbox
.Left
,gbox
.Top
,gbox
.Width
,gbox
.Height
, 0xc0 );
476 } /* switch (redraw) */
478 if( EG(o
)->Flags
& GFLG_DISABLED
)
479 DrawDisabledPattern( rp
, &gbox
, dri
->dri_Pens
[SHADOWPEN
]);
481 ReturnVoid("GradientSlider::Render");
484 /***************************************************************************************************/
486 IPTR
GradientSlider__GM_HITTEST(Class
*cl
, Object
*o
, struct gpHitTest
*msg
)
488 // struct GradientSliderData *data = INST_DATA(cl, o);
489 struct IBox gbox
, sbox
;
493 EnterFunc(bug("GradientSlider::HitTest()\n"));
495 if( EG(o
)->Flags
& GFLG_DISABLED
)
498 GetGadgetIBox(o
, msg
->gpht_GInfo
, &gbox
);
499 GetSliderBox(&gbox
, &sbox
);
501 if ((sbox
.Width
> 2) && (sbox
.Height
> 2))
503 /* calc mouse coords relative to slider box */
505 mousex
= msg
->gpht_Mouse
.X
- (sbox
.Left
- gbox
.Left
);
506 mousey
= msg
->gpht_Mouse
.Y
- (sbox
.Top
- gbox
.Top
);
508 if ((mousex
>= 0) && (mousey
>= 0) &&
509 (mousex
< sbox
.Width
) && (mousey
< sbox
.Height
)) retval
= GMR_GADGETHIT
;
512 ReturnInt("GradientSlider::HitTest", IPTR
, retval
);
515 /***************************************************************************************************/
517 IPTR
GradientSlider__GM_GOACTIVE(Class
*cl
, Object
*o
, struct gpInput
*msg
)
519 struct GradientSliderData
*data
= INST_DATA(cl
, o
);
520 struct IBox gbox
, sbox
, kbox
;
522 ULONG old_curval
= data
->curval
;
527 EnterFunc(bug("GradientSlider::GoActive()\n"));
529 if (!msg
->gpi_IEvent
) return GMR_NOREUSE
;
531 GetGadgetIBox(o
, msg
->gpi_GInfo
, &gbox
);
532 GetSliderBox(&gbox
, &sbox
);
533 GetKnobBox(data
, &sbox
, &kbox
);
535 mousex
= msg
->gpi_Mouse
.X
+ gbox
.Left
;
536 mousey
= msg
->gpi_Mouse
.Y
+ gbox
.Top
;
538 data
->x
= msg
->gpi_Mouse
.X
;
539 data
->y
= msg
->gpi_Mouse
.Y
;
541 data
->clickoffsetx
= mousex
- kbox
.Left
+ (sbox
.Left
- gbox
.Left
);
542 data
->clickoffsety
= mousey
- kbox
.Top
+ (sbox
.Top
- gbox
.Top
);
544 if ( ((data
->freedom
== LORIENT_HORIZ
) && (mousex
< kbox
.Left
)) ||
545 ((data
->freedom
== LORIENT_VERT
) && (mousey
< kbox
.Top
)) )
547 new_curval
= old_curval
- data
->skipval
;
548 if ((LONG
)new_curval
< 0) new_curval
= 0;
551 else if ( ((data
->freedom
== LORIENT_HORIZ
) && (mousex
>= kbox
.Left
+ kbox
.Width
)) ||
552 ((data
->freedom
== LORIENT_VERT
) && (mousey
>= kbox
.Top
+ kbox
.Height
)) )
555 new_curval
= old_curval
+ data
->skipval
;
556 if (new_curval
> data
->maxval
) new_curval
= (LONG
)data
->maxval
;
560 data
->saveval
= data
->curval
;
566 data
->curval
= new_curval
;
568 GetKnobBox(data
, &sbox
, &kbox
);
570 notify_curval(cl
, o
, msg
->gpi_GInfo
, FALSE
, TRUE
);
572 if ((rp
= ObtainGIRPort(msg
->gpi_GInfo
)))
574 DoMethod(o
, GM_RENDER
, (IPTR
)msg
->gpi_GInfo
, (IPTR
)rp
, GREDRAW_UPDATE
);
575 ReleaseGIRPort( rp
);
578 if( mousex >= kbox.Left &&
579 mousey >= kbox.Top &&
580 mousex < (kbox.Left+kbox.Width) &&
581 mousey < (kbox.Top+kbox.Height) )
583 data->clickoffsetx = mousex - kbox.Left + (sbox.Left - gbox.Left);
584 data->clickoffsety = mousey - kbox.Top + (sbox.Top - gbox.Top);
589 retval
= GMR_VERIFY
| GMR_NOREUSE
;
590 /* original AmigaOS gradientslider.gadget does not seem to place any meaningful
591 value into gpi_Termination :-\ */
592 *msg
->gpi_Termination
= data
->curval
;
595 retval
= GMR_MEACTIVE
;
598 ReturnInt("GradientSlider::GoActive", IPTR
, retval
);
601 /***************************************************************************************************/
603 IPTR
GradientSlider__GM_HANDLEINPUT(Class
*cl
, Object
*o
, struct gpInput
*msg
)
605 struct GradientSliderData
*data
= INST_DATA(cl
, o
);
606 struct IBox gbox
, sbox
, kbox
;
607 struct InputEvent
*ie
= msg
->gpi_IEvent
;
608 LONG new_curval
; /* use LONG instead of ULONG for easier checks against < 0 */
610 IPTR retval
= GMR_MEACTIVE
;
612 //EnterFunc(bug("GradientSlider::HandleInput\n"));
614 GetGadgetIBox(o
, msg
->gpi_GInfo
, &gbox
);
615 GetSliderBox(&gbox
, &sbox
);
616 GetKnobBox(data
, &sbox
, &kbox
);
620 case IECLASS_RAWMOUSE
:
624 retval
= GMR_VERIFY
| GMR_NOREUSE
;
625 /* original AmigaOS gradientslider.gadget does not seem to place any meaningful
626 value into gpi_Termination :-\ */
627 *msg
->gpi_Termination
= data
->curval
;
629 notify_curval(cl
, o
, msg
->gpi_GInfo
, FALSE
, TRUE
);
631 break; /* SELECTUP */
633 case IECODE_NOBUTTON
:
634 if( data
->x
== msg
->gpi_Mouse
.X
&& data
->y
== msg
->gpi_Mouse
.Y
)
637 data
->x
= msg
->gpi_Mouse
.X
;
638 data
->y
= msg
->gpi_Mouse
.Y
;
640 mousex
= msg
->gpi_Mouse
.X
- data
->clickoffsetx
;
641 mousey
= msg
->gpi_Mouse
.Y
- data
->clickoffsety
;
643 if (data
->freedom
== LORIENT_HORIZ
)
645 if (sbox
.Width
!= data
->knobpixels
) /* avoid div by 0 */
647 new_curval
= mousex
* ((LONG
)data
->maxval
) / (sbox
.Width
- (LONG
)data
->knobpixels
);
650 if (sbox
.Height
!= data
->knobpixels
) /* avoid div by 0 */
652 new_curval
= mousey
* ((LONG
)data
->maxval
) / (sbox
.Height
- (LONG
)data
->knobpixels
);
660 else if (new_curval
> data
->maxval
)
662 new_curval
= (LONG
)data
->maxval
;
665 if ((ULONG
)new_curval
!= data
->curval
)
669 data
->curval
= (ULONG
)new_curval
;
671 if ((rp
= ObtainGIRPort(msg
->gpi_GInfo
)))
673 DoMethod(o
, GM_RENDER
, (IPTR
)msg
->gpi_GInfo
, (IPTR
)rp
, GREDRAW_UPDATE
);
677 notify_curval(cl
, o
, msg
->gpi_GInfo
, TRUE
, TRUE
);
679 break; /* IECODE_NOBUTTON */
681 } /* switch(ie->ie_Code) */
683 break; /* IECLASS_RAWMOUSE */
685 } /* switch(ie->ie_Class) */
687 ReturnInt("GradientSlider::HandleInput", IPTR
, retval
);
690 /***************************************************************************************************/
692 IPTR
GradientSlider__GM_DOMAIN(Class
*cl
, Object
*o
, struct gpDomain
*msg
)
694 struct GradientSliderData
*data
= INST_DATA(cl
, o
);
695 struct DrawInfo
*dri
= (struct DrawInfo
*) GetTagData( GA_DrawInfo
, NULL
, msg
->gpd_Attrs
);
696 struct RastPort
*rp
= msg
->gpd_RPort
;
697 UWORD width
, height
, x
=1,y
=1;
701 y
= dri
->dri_Resolution
.X
;
702 x
= dri
->dri_Resolution
.Y
;
705 switch( msg
->gpd_Which
)
707 case GDOMAIN_MINIMUM
:
708 if( data
->freedom
== LORIENT_VERT
)
710 width
= 3 + ( ( rp
->TxHeight
* x
) / y
) + 3;
711 height
= 2 + (data
->knobpixels
*5) + 2;
715 width
= 3 + (data
->knobpixels
*5) + 3;
716 height
= 2 + rp
->TxHeight
+ 2;
720 case GDOMAIN_NOMINAL
:
721 if( data
->freedom
== LORIENT_VERT
)
723 width
= 3 + ( ( rp
->TxHeight
* x
) / y
) + 3;
724 height
= 2 + (10*data
->knobpixels
) + 2;
728 width
= 3 + (10*data
->knobpixels
) + 3;
729 height
= 2 + rp
->TxHeight
+ 2;
733 case GDOMAIN_MAXIMUM
:
734 if( data
->freedom
== LORIENT_VERT
)
736 width
= 3 + ( ( rp
->TxHeight
* x
) / y
) + 3;
742 height
= 2 + rp
->TxHeight
+ 2;
747 msg
->gpd_Domain
.Left
=
748 msg
->gpd_Domain
.Top
= 0;
749 msg
->gpd_Domain
.Width
= width
;
750 msg
->gpd_Domain
.Height
= height
;
755 /***************************************************************************************************/