2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
9 #include <proto/alib.h>
10 #include <proto/exec.h>
11 #include <proto/dos.h>
12 #include <proto/utility.h>
13 #include <proto/intuition.h>
14 #include <proto/graphics.h>
15 #include <proto/cybergraphics.h>
16 #include <exec/memory.h>
17 #include <intuition/screens.h>
18 #include <intuition/icclass.h>
19 #include <intuition/cghooks.h>
20 #include <intuition/imageclass.h>
21 #include <intuition/gadgetclass.h>
22 #include <graphics/gfx.h>
23 #include <cybergraphx/cybergraphics.h>
27 #include "asl_intern.h"
33 #include <aros/debug.h>
35 #define CLASS_ASLBASE ((struct AslBase_intern *)cl->cl_UserData)
36 #define HOOK_ASLBASE ((struct AslBase_intern *)hook->h_Data)
38 #define AslBase CLASS_ASLBASE
40 /********************** ASL CYCLE CLASS **************************************************/
42 #define CYCLEIMAGEWIDTH 19
49 /* it is possible to scroll faster through the
50 ** popup after TURBOCOUNTDOWN intuiticks
51 ** (= 1/10 sec) by moving around the mouse
52 ** (to force mousemove events to be sent to
56 #define TURBOCOUNTDOWN 5
58 /***********************************************************************************/
60 IPTR
AslCycle__OM_SET(Class
* cl
, Object
* o
, struct opSet
*msg
);
62 /***********************************************************************************/
64 static void RenderObject_Update(Class
*cl
, Object
*o
, struct GadgetInfo
*gi
)
68 if ((rp
= ObtainGIRPort(gi
)))
70 DoMethod(o
, GM_RENDER
,
79 /***********************************************************************************/
81 static void DrawArrow(Class
*cl
, struct RastPort
*rp
, WORD x1
, WORD y1
, WORD type
)
90 RectFill(rp
, x1
, y1
, x1
+ 6, y1
); y1
+= dy
;
91 RectFill(rp
, x1
+ 1, y1
, x1
+ 5, y1
); y1
+= dy
;
92 RectFill(rp
, x1
+ 2, y1
, x1
+ 4, y1
); y1
+= dy
;
93 WritePixel(rp
, x1
+ 3, y1
);
96 /***********************************************************************************/
98 static void DrawUpArrow(Class
*cl
, struct AslCycleData
*data
, struct DrawInfo
*dri
, BOOL force
)
103 if (data
->visible
== data
->numitems
) return;
105 black
= data
->top
> 0 ? TRUE
: FALSE
;
106 if (force
|| (black
!= data
->uparrowblack
))
108 data
->uparrowblack
= black
;
110 SetAPen(data
->rp
, dri
->dri_Pens
[black
? SHADOWPEN
: BACKGROUNDPEN
]);
112 x
= data
->borderleft
+ (data
->itemwidth
- ARROWWIDTH
) / 2;
114 DrawArrow(cl
, data
->rp
, data
->menuleft
+ x
, data
->menutop
+ data
->menuy1
- ARROWHEIGHT
- 1, ARROW_UP
);
118 /***********************************************************************************/
120 static void DrawDownArrow(Class
*cl
, struct AslCycleData
*data
, struct DrawInfo
*dri
, BOOL force
)
125 if (data
->visible
== data
->numitems
) return;
127 black
= data
->top
+ data
->visible
< data
->numitems
? TRUE
: FALSE
;
128 if (force
|| (black
!= data
->downarrowblack
))
130 data
->downarrowblack
= black
;
132 SetAPen(data
->rp
, dri
->dri_Pens
[black
? SHADOWPEN
: BACKGROUNDPEN
]);
134 x
= data
->borderleft
+ (data
->itemwidth
- ARROWWIDTH
) / 2;
136 DrawArrow(cl
, data
->rp
, data
->menuleft
+ x
, data
->menutop
+ data
->menuy2
+ 2, ARROW_DOWN
);
140 /***********************************************************************************/
142 static void DrawItem(Class
*cl
, struct AslCycleData
*data
, struct DrawInfo
*dri
, WORD num
, BOOL nowhitefill
)
144 struct CycleItem
*item
;
147 off
= num
- data
->top
;
149 if ((off
>= 0) && (off
< data
->visible
))
151 item
= &data
->itemmemory
[num
];
153 x
= data
->menuleft
+ data
->menux1
;
154 y
= data
->menutop
+ data
->menuy1
+ off
* data
->itemheight
;
156 if ((num
== data
->selected
) || !nowhitefill
)
158 SetAPen(data
->rp
, dri
->dri_Pens
[(num
== data
->selected
) ? SHADOWPEN
: SHINEPEN
]);
159 RectFill(data
->rp
, x
, y
,
160 x
+ data
->itemwidth
- 1,
161 y
+ data
->itemheight
- 1);
164 x
= (x
+ x
+ data
->itemwidth
- item
->pixellen
) / 2;
165 y
+= data
->font
->tf_Baseline
+ 1;
167 SetAPen(data
->rp
, dri
->dri_Pens
[(num
== data
->selected
) ? SHINEPEN
: TEXTPEN
]);
168 Move(data
->rp
, x
, y
);
169 Text(data
->rp
, item
->string
, item
->charlen
);
171 } /* if ((off >= 0) && (off < data->visible)) */
174 /***********************************************************************************/
176 static void DrawMenu(Class
*cl
, struct AslCycleData
*data
, struct DrawInfo
*dri
)
178 WORD i
, x1
, y1
, x2
, y2
;
183 x2
= x1
+ data
->menuwidth
- 1;
184 y2
= y1
+ data
->menuheight
- 1;
186 SetAPen(data
->rp
, dri
->dri_Pens
[SHADOWPEN
]);
187 RectFill(data
->rp
, x1
, y1
, x2
, y1
);
188 RectFill(data
->rp
, x2
, y1
+ 1, x2
, y2
);
189 RectFill(data
->rp
, x1
, y2
, x2
- 1, y2
);
190 RectFill(data
->rp
, x1
, y1
+ 1, x1
, y2
- 1);
192 SetAPen (data
->rp
, dri
->dri_Pens
[SHINEPEN
]);
193 RectFill(data
->rp
, x1
+ 1, y1
+ 1, x2
- 1, y2
- 1);
195 for(i
= data
->top
;i
< data
->top
+ data
->visible
;i
++)
197 DrawItem(cl
, data
, dri
, i
,TRUE
);
200 DrawUpArrow(cl
, data
, dri
, TRUE
);
201 DrawDownArrow(cl
, data
, dri
,TRUE
);
204 /***********************************************************************************/
206 static void UnselectActiveItem(Class
*cl
, struct AslCycleData
*data
, struct DrawInfo
*dri
)
210 old
= data
->selected
;
212 DrawItem(cl
, data
, dri
, old
, FALSE
);
215 /***********************************************************************************/
217 IPTR
AslCycle__OM_NEW(Class
* cl
, Object
* o
, struct opSet
*msg
)
219 struct AslCycleData
*data
;
220 struct TagItem fitags
[] =
222 {IA_FrameType
, FRAME_BUTTON
},
223 {IA_EdgesOnly
, FALSE
},
227 struct Gadget
*g
= (struct Gadget
*)DoSuperMethodA(cl
, o
, (Msg
)msg
);
230 data
= INST_DATA(cl
, g
);
232 /* We want to get a GM_LAYOUT message, no matter if gadget is GFLG_RELRIGHT/RELBOTTOM/
233 RELWIDTH/RELHEIGHT or not */
234 g
->Flags
|= GFLG_RELSPECIAL
;
236 data
->frame
= NewObjectA(NULL
, FRAMEICLASS
, fitags
);
239 AslCycle__OM_SET(cl
, (Object
*)g
, msg
);
242 CoerceMethod(cl
, (Object
*)g
, OM_DISPOSE
);
250 /***********************************************************************************/
252 IPTR
AslCycle__OM_DISPOSE(Class
* cl
, Object
* o
, Msg msg
)
254 struct AslCycleData
*data
= INST_DATA(cl
, o
);
256 if (data
->itemmemory
) FreeVec(data
->itemmemory
);
257 if (data
->frame
) DisposeObject(data
->frame
);
259 return DoSuperMethodA(cl
, o
, msg
);
262 /***********************************************************************************/
264 IPTR
AslCycle__OM_SET(Class
* cl
, Object
* o
, struct opSet
*msg
)
266 struct AslCycleData
*data
= INST_DATA(cl
, o
);
267 struct TagItem
*tag
, *tstate
= msg
->ops_AttrList
;
270 retval
= DoSuperMethod(cl
, o
, OM_SET
, (IPTR
) msg
->ops_AttrList
, (IPTR
) msg
->ops_GInfo
);
272 while((tag
= NextTagItem(&tstate
)))
274 tidata
= tag
->ti_Data
;
279 data
->active
= tidata
;
284 data
->labels
= (char **)tidata
;
286 if (data
->itemmemory
)
288 FreeVec(data
->itemmemory
);
289 data
->itemmemory
= 0;
299 for(i
= 0; data
->labels
[i
]; i
++)
303 if (i
) data
->itemmemory
= AllocVec(i
* sizeof(struct CycleItem
), MEMF_PUBLIC
| MEMF_CLEAR
);
305 if (!data
->itemmemory
)
309 struct CycleItem
*item
= data
->itemmemory
;
313 for(i
= 0; i
< data
->numitems
;i
++,item
++)
315 item
->string
= data
->labels
[i
];
316 item
->charlen
= strlen(item
->string
);
323 gpl
.MethodID
= GM_LAYOUT
;
324 gpl
.gpl_GInfo
= msg
->ops_GInfo
;
327 DoMethodA(o
, (Msg
)&gpl
);
330 } /* if (data->itemmemory) */
332 } /* if (data->labels) */
338 data
->font
= (struct TextFont
*)tidata
;
342 } /* switch(tag->ti_Tag) */
344 } /* while((tag = NextTagItem(&tstate))) */
348 RenderObject_Update(cl
, o
, msg
->ops_GInfo
);
355 /***********************************************************************************/
357 IPTR
AslCycle__OM_GET(Class
* cl
, Object
* o
, struct opGet
*msg
)
359 struct AslCycleData
*data
= INST_DATA(cl
, o
);
363 switch(msg
->opg_AttrID
)
366 *msg
->opg_Storage
= data
->active
;
370 retval
= DoSuperMethodA(cl
, o
, (Msg
)msg
);
377 /***********************************************************************************/
379 IPTR
AslCycle__GM_LAYOUT(Class
* cl
, struct Gadget
* g
, struct gpLayout
*msg
)
381 struct AslCycleData
*data
= INST_DATA(cl
, g
);
382 struct CycleItem
*item
;
386 getgadgetcoords(g
, msg
->gpl_GInfo
, &x
, &y
, &w
, &h
);
388 if (!data
->font
) data
->font
= msg
->gpl_GInfo
->gi_DrInfo
->dri_Font
;
390 item
= data
->itemmemory
;
393 InitRastPort(&data
->clonerp
);
394 SetFont(&data
->clonerp
, data
->font
);
396 for (i
= 0; i
< data
->numitems
; i
++, item
++)
398 item
->pixellen
= TextLength(&data
->clonerp
, item
->string
, item
->charlen
);
399 if (item
->pixellen
> len
) len
= item
->pixellen
;
402 data
->itemwidth
= len
+ 2;
403 i
= w
- CYCLEIMAGEWIDTH
- BORDERCYCLESPACINGX
;
404 if (data
->itemwidth
< i
) data
->itemwidth
= i
;
406 data
->itemheight
= data
->font
->tf_YSize
+ 2;
408 data
->borderleft
= 4;
409 data
->borderright
= 4;
411 data
->borderbottom
= 4;
413 data
->menuwidth
= data
->itemwidth
+ data
->borderleft
+ data
->borderright
;
415 data
->menuheight
= data
->numitems
* data
->itemheight
+
419 data
->menux1
= data
->borderleft
;
421 data
->maypopup
= TRUE
;
423 if (data
->menuheight
> msg
->gpl_GInfo
->gi_Screen
->Height
)
425 data
->visible
= (msg
->gpl_GInfo
->gi_Screen
->Height
-
428 (ARROWHEIGHT
+ 2) * 2) / data
->itemheight
;
430 if (data
->visible
< 2)
432 data
->maypopup
= FALSE
;
434 data
->menuheight
= data
->bordertop
+
435 data
->visible
* data
->itemheight
+
437 (ARROWHEIGHT
+ 2) * 2;
439 data
->menuy1
= data
->bordertop
+ ARROWHEIGHT
+ 2;
442 data
->visible
= data
->numitems
;
443 data
->menuy1
= data
->bordertop
;
446 data
->menux2
= data
->menux1
+ data
->itemwidth
- 1;
447 data
->menuy2
= data
->menuy1
+ data
->visible
* data
->itemheight
- 1;
452 /***********************************************************************************/
454 IPTR
AslCycle__GM_RENDER(Class
* cl
, struct Gadget
* g
, struct gpRender
*msg
)
456 struct AslCycleData
*data
= INST_DATA(cl
, g
);
457 struct RastPort
*rp
= msg
->gpr_RPort
;
458 struct DrawInfo
*dri
= msg
->gpr_GInfo
->gi_DrInfo
;
459 struct CycleItem
*item
;
460 WORD gadx
, gady
, gadw
, gadh
, x
, y
, y2
, a1
, a2
;
466 struct TagItem im_tags
[] =
473 getgadgetcoords(g
, msg
->gpr_GInfo
, &gadx
, &gady
, &gadw
, &gadh
);
475 im_tags
[0].ti_Data
= gadw
;
476 im_tags
[1].ti_Data
= gadh
;
478 SetAttrsA(data
->frame
, im_tags
);
480 DrawImageState(msg
->gpr_RPort
,
481 (struct Image
*)data
->frame
,
484 (g
->Flags
& GFLG_SELECTED
) ? IDS_SELECTED
: IDS_NORMAL
,
485 msg
->gpr_GInfo
->gi_DrInfo
);
490 selected
= (g
->Flags
& GFLG_SELECTED
) ? TRUE
: FALSE
;
491 SetABPenDrMd(rp
, dri
->dri_Pens
[selected
? FILLTEXTPEN
: TEXTPEN
], 0, JAM1
);
493 item
= &data
->itemmemory
[data
->active
];
495 a1
= gadx
+ BORDERCYCLESPACINGX
;
496 a2
= gadx
+ gadw
- CYCLEIMAGEWIDTH
- BORDERCYCLESPACINGX
;
497 x
= (a1
+ a2
- item
->pixellen
) / 2;
499 y
= gady
+ (gadh
- data
->font
->tf_YSize
) / 2 + data
->font
->tf_Baseline
;
501 SetFont(rp
, data
->font
);
504 Text(rp
, item
->string
, item
->charlen
);
507 x
= gadx
+ gadw
- CYCLEIMAGEWIDTH
;
509 y2
= gady
+ gadh
- 1 - 2;
513 SetAPen(rp
, dri
->dri_Pens
[SHINEPEN
]);
514 RectFill(rp
, x
+ 1, y
, x
+ 1, y2
);
515 SetAPen(rp
, dri
->dri_Pens
[SHADOWPEN
]);
516 RectFill(rp
, x
, y
, x
, y2
);
518 y
= gady
+ (gadh
- 4) / 2;
521 DrawArrow(cl
, rp
, x
, y
, ARROW_DOWN
);
528 /***********************************************************************************/
530 IPTR
AslCycle__GM_GOACTIVE(Class
* cl
, struct Gadget
* g
, struct gpInput
*msg
)
532 struct AslCycleData
*data
= INST_DATA(cl
, g
);
533 WORD x
, y
, x2
, y2
, gadx
, gady
, gadw
, gadh
;
535 IPTR rc
= GMR_MEACTIVE
;
537 if (!data
->labels
|| !msg
->gpi_IEvent
) return GMR_NOREUSE
;
540 data
->sentgadgetup
= FALSE
;
541 data
->turbocountdown
= TURBOCOUNTDOWN
;
543 getgadgetcoords(g
, msg
->gpi_GInfo
, &gadx
, &gady
, &gadw
, &gadh
);
545 x
= msg
->gpi_GInfo
->gi_Window
->MouseX
;
547 if (data
->maypopup
&& (data
->numitems
> 2) && (x
< gadx
+ gadw
- CYCLEIMAGEWIDTH
))
549 x
= msg
->gpi_GInfo
->gi_Window
->LeftEdge
+ gadx
;
550 y
= msg
->gpi_GInfo
->gi_Window
->TopEdge
+ gady
+ gadh
;
553 if ((x
+ data
->menuwidth
) > msg
->gpi_GInfo
->gi_Screen
->Width
)
555 x
= msg
->gpi_GInfo
->gi_Screen
->Width
- data
->menuwidth
;
559 if ((y
+ data
->menuheight
) > msg
->gpi_GInfo
->gi_Screen
->Height
)
561 y
= msg
->gpi_GInfo
->gi_Screen
->Height
- data
->menuheight
;
564 x2
= x
+ data
->menuwidth
- 1;
565 y2
= y
+ data
->menuheight
- 1;
567 if ((data
->popupwindow
= OpenWindowTags(0,WA_CustomScreen
, (IPTR
) msg
->gpi_GInfo
->gi_Screen
,
570 WA_Width
, data
->menuwidth
,
571 WA_Height
, data
->menuheight
,
572 WA_Flags
, WFLG_BORDERLESS
,
573 WA_BackFill
, (IPTR
) LAYERS_NOBACKFILL
,
578 data
->rp
= data
->popupwindow
->RPort
;
582 if (data
->popupwindow
)
584 data
->layerx1
= x
; data
->layery1
= y
;
585 data
->layerx2
= x2
; data
->layery2
= y2
;
589 SetDrMd(data
->rp
, JAM1
);
590 SetFont(data
->rp
, data
->font
);
593 DrawMenu(cl
, data
, msg
->gpi_GInfo
->gi_DrInfo
);
596 } /* if (data->maypopup && (data->numitems > 2) && (x < gadx + gadw - CYCLEIMAGEWIDTH)) */
599 g
->Flags
|= GFLG_SELECTED
;
600 RenderObject_Update(cl
, (Object
*)g
, msg
->gpi_GInfo
);
606 /***********************************************************************************/
608 IPTR
AslCycle__GM_HANDLEINPUT(Class
* cl
, struct Gadget
* g
, struct gpInput
*msg
)
610 struct AslCycleData
*data
= INST_DATA(cl
, g
);
611 WORD gadx
, gady
, gadw
, gadh
, x
, y
, i
;
612 IPTR rc
= GMR_MEACTIVE
;
614 getgadgetcoords(g
, msg
->gpi_GInfo
, &gadx
, &gady
, &gadw
, &gadh
);
618 if ((msg
->gpi_IEvent
->ie_Class
== IECLASS_RAWMOUSE
) &&
619 (msg
->gpi_IEvent
->ie_Code
== (IECODE_LBUTTON
| IECODE_UP_PREFIX
)))
622 if (data
->selected
!= -1)
624 data
->active
= data
->selected
;
625 data
->sentgadgetup
= TRUE
;
628 *msg
->gpi_Termination
= data
->active
;
634 x
= msg
->gpi_GInfo
->gi_Screen
->MouseX
- data
->layerx1
;
635 y
= msg
->gpi_GInfo
->gi_Screen
->MouseY
- data
->layery1
;
637 if ((x
< data
->menux1
) || (x
> data
->menux2
))
639 UnselectActiveItem(cl
, data
, msg
->gpi_GInfo
->gi_DrInfo
);
641 i
= (y
- data
->menuy1
) / data
->itemheight
;
643 if ((i
>= data
->visible
) || (y
< data
->menuy1
))
645 UnselectActiveItem(cl
, data
, msg
->gpi_GInfo
->gi_DrInfo
);
647 if (data
->turbocountdown
&& (msg
->gpi_IEvent
->ie_Class
== IECLASS_TIMER
))
649 data
->turbocountdown
--;
652 if (!data
->turbocountdown
|| (msg
->gpi_IEvent
->ie_Class
== IECLASS_TIMER
))
654 if (i
>= data
->visible
)
657 if (data
->top
+ data
->visible
< data
->numitems
)
659 ClipBlit(data
->rp
, data
->menux1
+ data
->menuleft
, data
->menuy1
+ data
->menutop
+ data
->itemheight
,
660 data
->rp
, data
->menux1
+ data
->menuleft
, data
->menuy1
+ data
->menutop
, data
->itemwidth
, data
->itemheight
* (data
->visible
- 1), 192);
662 DrawItem(cl
, data
, msg
->gpi_GInfo
->gi_DrInfo
, data
->top
+ data
->visible
- 1, FALSE
);
663 DrawUpArrow(cl
, data
, msg
->gpi_GInfo
->gi_DrInfo
, FALSE
);
664 DrawDownArrow(cl
, data
, msg
->gpi_GInfo
->gi_DrInfo
, FALSE
);
670 ClipBlit(data
->rp
, data
->menux1
+ data
->menuleft
, data
->menuy1
+ data
->menutop
,
671 data
->rp
, data
->menux1
+ data
->menuleft
, data
->menuy1
+ data
->menutop
+ data
->itemheight
, data
->itemwidth
, data
->itemheight
* (data
->visible
- 1), 192);
673 DrawItem(cl
, data
, msg
->gpi_GInfo
->gi_DrInfo
, data
->top
, FALSE
);
674 DrawUpArrow(cl
, data
, msg
->gpi_GInfo
->gi_DrInfo
, FALSE
);
675 DrawDownArrow(cl
, data
, msg
->gpi_GInfo
->gi_DrInfo
, FALSE
);
678 } /* if (!data->turbocountdown || (msg->gpi_IEvent->ie_Class == IECLASS_TIMER)) */
682 data
->turbocountdown
= TURBOCOUNTDOWN
;
684 data
->selected
= data
->top
+ i
;
685 if (data
->selected
!= x
)
687 DrawItem(cl
, data
, msg
->gpi_GInfo
->gi_DrInfo
, x
, FALSE
);
688 DrawItem(cl
, data
, msg
->gpi_GInfo
->gi_DrInfo
, data
->selected
, FALSE
);
693 } else { /* if (data->popup) */
695 /* like a GadTools cycle gadget */
697 switch(msg
->gpi_IEvent
->ie_Class
)
699 case IECLASS_RAWMOUSE
:
700 switch(msg
->gpi_IEvent
->ie_Code
)
702 case IECODE_LBUTTON
| IECODE_UP_PREFIX
:
703 if (g
->Flags
& GFLG_SELECTED
)
706 if (data
->active
>= data
->numitems
) data
->active
= 0;
708 g
->Flags
&= (~GFLG_SELECTED
);
709 RenderObject_Update(cl
, (Object
*)g
, msg
->gpi_GInfo
);
711 *msg
->gpi_Termination
= g
->GadgetID
;
717 if ((msg
->gpi_Mouse
.X
>= 0 ) &&
718 (msg
->gpi_Mouse
.Y
>= 0 ) &&
719 (msg
->gpi_Mouse
.X
< gadw
) &&
720 (msg
->gpi_Mouse
.Y
< gadh
))
722 if (!(g
->Flags
& GFLG_SELECTED
))
724 g
->Flags
|= GFLG_SELECTED
;
725 RenderObject_Update(cl
, (Object
*)g
, msg
->gpi_GInfo
);
728 if (g
->Flags
& GFLG_SELECTED
)
730 g
->Flags
&= (~GFLG_SELECTED
);
731 RenderObject_Update(cl
, (Object
*)g
, msg
->gpi_GInfo
);
738 } /* switch(msg->gpi_IEvent->ie_Code) */
740 } /* switch(msg->gpi_IEvent->ie_Class) */
742 } /* if (data->popup) {...} else { */
750 /***********************************************************************************/
752 IPTR
AslCycle__GM_GOINACTIVE(Class
* cl
, Object
* o
, struct gpGoInactive
*msg
)
754 struct AslCycleData
*data
= INST_DATA(cl
, o
);
756 if (data
->popupwindow
)
758 CloseWindow(data
->popupwindow
);
759 data
->popupwindow
= 0;
762 if (data
->sentgadgetup
)
764 RenderObject_Update(cl
, o
, msg
->gpgi_GInfo
);
770 /***********************************************************************************/