Indentation fix, cleanup.
[AROS.git] / workbench / classes / gadgets / gradientslider / gradientsliderclass.c
blob626e7662c1e1bf22361201ed189b4a512e692c7b
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: AROS gradientslider gadget.
6 Lang: english
7 */
9 #ifdef __AROS__
11 #define SDEBUG 0
12 #define DEBUG 0
14 #include <aros/asmcall.h>
15 #include <aros/debug.h>
17 #endif
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"
37 #ifndef __AROS__
39 #if 1
40 #undef SysBase
41 void kprintf( STRPTR FormatStr, ... )
43 TEXT PutChData[64];
44 STRPTR p = PutChData;
45 struct Library *SysBase = (*(struct Library **)4L);
46 RawDoFmt(FormatStr, ((STRPTR)(&FormatStr))+4, (void (*)())"\x16\xc0\x4e\x75", PutChData);
48 do RawPutChar( *p );
49 while( *p++ );
51 #define SysBase GSB(GradientSliderBase)->sysbase
52 #endif
54 #ifdef __STORMGCC__
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 );
59 #endif
61 #endif
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 },
74 {TAG_DONE }
77 opu.MethodID = OM_NOTIFY;
78 opu.opu_AttrList = tags;
79 opu.opu_GInfo = gi;
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;
90 struct TagItem *tag;
91 IPTR retval;
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"));
98 retval = 0;
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;
107 switch (tag->ti_Tag)
109 case GRAD_CurVal:
110 data->curval = (ULONG)tidata;
111 notify_curval(cl, o, msg->ops_GInfo, FALSE, FALSE);
112 retval += 1UL;
113 break;
115 case GA_Disabled:
116 if ((EG(o)->Flags&GFLG_DISABLED) != (flags&GFLG_DISABLED))
118 retval += 1UL;
119 redraw_all = TRUE;
121 break;
123 case GRAD_MaxVal:
124 if (tidata > 0 && tidata < 65536) // ReAction fix.
126 ULONG new_curval;
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);
136 retval += 1UL;
138 break;
140 case GRAD_SkipVal:
141 data->skipval = (ULONG)tidata;
142 break;
144 case GRAD_PenArray:
146 if( tidata ) // REACTION_TextAttr collides with this one
148 UWORD *pen = (UWORD *) tidata;
150 if( ( pen[0] & 0xff00 ) && ( pen[0] != 0xffff ) )
151 break;
153 if( ( pen[1] & 0xff00 ) && ( pen[1] != 0xffff ) )
154 break;
157 data->penarray = (UWORD *)tidata;
158 data->numpens = 0;
160 if (data->penarray)
162 UWORD *pen = data->penarray;
164 while(*pen++ != (UWORD)~0) data->numpens++;
167 retval += 1UL;
168 redraw_all = TRUE;
170 break;
172 default:
173 break;
175 } /* switch (tag->ti_Tag) */
177 } /* for (each attr in attrlist) */
179 if (retval)
181 struct RastPort *rp;
183 if ((rp = ObtainGIRPort(msg->ops_GInfo)))
185 DoMethod(o, GM_RENDER, (IPTR)msg->ops_GInfo, (IPTR)rp, redraw_all ? GREDRAW_REDRAW : GREDRAW_UPDATE);
186 ReleaseGIRPort(rp);
187 retval = 0L;
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);
201 if (o)
203 struct GradientSliderData *data = INST_DATA(cl, o);
204 static struct TagItem fitags[]=
206 {IA_FrameType , FRAME_BUTTON },
207 {TAG_DONE }
210 if ((data->frame = NewObjectA(NULL, FRAMEICLASS, fitags)))
212 data->maxval = 0xFFFF;
213 data->curval = 0;
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);
222 } else {
223 CoerceMethod(cl, o, OM_DISPOSE);
224 o = NULL;
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);
239 if (data->savebm)
241 WaitBlit();
242 FreeBitMap(data->savebm);
245 if (data->knobbm)
247 WaitBlit();
248 FreeBitMap(data->knobbm);
251 if (data->buffer)
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);
264 IPTR retval = 1UL;
266 switch(msg->opg_AttrID)
268 case GRAD_MaxVal:
269 *msg->opg_Storage = data->maxval;
270 break;
272 case GRAD_CurVal:
273 *msg->opg_Storage = data->curval;
274 break;
276 case GRAD_SkipVal:
277 *msg->opg_Storage = data->skipval;
278 break;
280 default:
281 retval = DoSuperMethodA(cl, o, (Msg)msg);
282 break;
284 } /* switch(msg->opg_AttrID) */
286 return retval;
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);
307 switch (redraw)
309 case GREDRAW_UPDATE:
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 */
317 #ifdef __STORMGCC__
318 myBltBitMap( data->knobbm, 0,0, data->savebm, data->savefromx,data->savefromy, kbox.Width,kbox.Height, 0xc0, 0xff, NULL, GfxBase);
319 #else
320 BltBitMap( data->knobbm, 0,0, data->savebm, data->savefromx,data->savefromy, kbox.Width,kbox.Height, 0xc0, 0xff, NULL);
321 #endif
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;
326 #ifdef __STORMGCC__
327 myBltBitMap( data->savebm, kbox.Left,kbox.Top, data->knobbm, 0,0, kbox.Width,kbox.Height, 0xc0, 0xff, NULL, GfxBase );
328 #else
329 BltBitMap( data->savebm, kbox.Left,kbox.Top, data->knobbm, 0,0, kbox.Width,kbox.Height, 0xc0, 0xff, NULL );
330 #endif
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)) */
338 break;
341 } /* if ((kbox.Width <= sbox.Width) && (kbox.Height <= sbox.Height)) */
343 case GREDRAW_REDRAW:
345 struct RastPort *trp = &data->trp;
347 if( gbox.Width != data->savebmwidth || gbox.Height != data->savebmheight )
349 if( data->savebm )
351 WaitBlit();
352 FreeBitMap( data->savebm );
353 data->savebm = NULL;
356 if( data->knobbm )
358 WaitBlit();
359 FreeBitMap( data->knobbm );
360 data->knobbm = NULL;
363 if( data->buffer )
365 FreeVec( data->buffer );
366 data->buffer = NULL;
370 if( data->savebm == NULL )
372 struct TagItem fitags[] =
374 {IA_Width , gbox.Width },
375 {IA_Height , gbox.Height },
376 {TAG_DONE }
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 ) ) )
386 break;
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 );
398 data->savebm = NULL;
399 break;
402 /* Draw frame */
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];
419 SetDrMd(trp, JAM1);
420 SetAPen(trp, pen);
421 RectFill(trp, sbox.Left, sbox.Top, sbox.Left + sbox.Width - 1, sbox.Top + sbox.Height - 1);
422 } /* ff (data->numpens < 2) */
423 else
425 DrawGradient(trp,
426 sbox.Left,
427 sbox.Top,
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))
440 #ifdef __STORMGCC__
441 myBltBitMap( data->savebm, kbox.Left,kbox.Top, data->knobbm, 0,0, kbox.Width,kbox.Height, 0xc0, 0xff, NULL, GfxBase );
442 #else
443 BltBitMap( data->savebm, kbox.Left,kbox.Top, data->knobbm, 0,0, kbox.Width,kbox.Height, 0xc0, 0xff, NULL );
444 #endif
446 data->savefromx = kbox.Left;
447 data->savefromy = kbox.Top;
449 /* Render knob */
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 );
455 break;
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;
470 WORD mousex, mousey;
471 IPTR retval = 0UL;
473 EnterFunc(bug("GradientSlider::HitTest()\n"));
475 if( EG(o)->Flags & GFLG_DISABLED )
476 return 0UL;
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;
501 WORD mousex, mousey;
502 ULONG old_curval = data->curval;
503 ULONG new_curval = data->curval;
504 BOOL knobhit = TRUE;
505 IPTR retval = 0UL;
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;
529 knobhit = FALSE;
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;
537 knobhit = FALSE;
540 data->saveval = data->curval;
542 if (!knobhit)
544 struct RastPort *rp;
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);
565 return GMR_MEACTIVE;
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;
574 } else {
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 */
589 WORD mousex, mousey;
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);
598 switch(ie->ie_Class)
600 case IECLASS_RAWMOUSE:
601 switch(ie->ie_Code)
603 case SELECTUP:
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 )
615 break;
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);
629 } else {
630 if (sbox.Height != data->knobpixels) /* avoid div by 0 */
632 new_curval = mousey * ((LONG)data->maxval) / (sbox.Height - (LONG)data->knobpixels);
636 if (new_curval < 0)
638 new_curval = 0;
640 else if (new_curval > data->maxval)
642 new_curval = (LONG)data->maxval;
645 if ((ULONG)new_curval != data->curval)
647 struct RastPort *rp;
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);
654 ReleaseGIRPort(rp);
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;
679 if( dri )
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;
693 else
695 width = 3 + (data->knobpixels*5) + 3;
696 height = 2 + rp->TxHeight + 2;
698 break;
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;
706 else
708 width = 3 + (10*data->knobpixels) + 3;
709 height = 2 + rp->TxHeight + 2;
711 break;
713 case GDOMAIN_MAXIMUM:
714 if( data->freedom == LORIENT_VERT )
716 width = 3 + ( ( rp->TxHeight * x ) / y ) + 3;
717 height = 0x7fff;
719 else
721 width = 0x7fff;
722 height = 2 + rp->TxHeight + 2;
724 break;
727 msg->gpd_Domain.Left =
728 msg->gpd_Domain.Top = 0;
729 msg->gpd_Domain.Width = width;
730 msg->gpd_Domain.Height = height;
732 return 1L;
735 /***************************************************************************************************/