2 Copyright © 1995-2005, The AROS Development Team. All rights reserved.
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
);
268 const struct TagItem
*tstate
= msg
->ops_AttrList
;
271 retval
= DoSuperMethod(cl
, o
, OM_SET
, (IPTR
) msg
->ops_AttrList
, (IPTR
) msg
->ops_GInfo
);
273 while((tag
= NextTagItem(&tstate
)))
275 tidata
= tag
->ti_Data
;
280 data
->active
= tidata
;
285 data
->labels
= (char **)tidata
;
287 if (data
->itemmemory
)
289 FreeVec(data
->itemmemory
);
290 data
->itemmemory
= 0;
300 for(i
= 0; data
->labels
[i
]; i
++)
304 if (i
) data
->itemmemory
= AllocVec(i
* sizeof(struct CycleItem
), MEMF_PUBLIC
| MEMF_CLEAR
);
306 if (!data
->itemmemory
)
310 struct CycleItem
*item
= data
->itemmemory
;
314 for(i
= 0; i
< data
->numitems
;i
++,item
++)
316 item
->string
= data
->labels
[i
];
317 item
->charlen
= strlen(item
->string
);
324 gpl
.MethodID
= GM_LAYOUT
;
325 gpl
.gpl_GInfo
= msg
->ops_GInfo
;
328 DoMethodA(o
, (Msg
)&gpl
);
331 } /* if (data->itemmemory) */
333 } /* if (data->labels) */
339 data
->font
= (struct TextFont
*)tidata
;
343 } /* switch(tag->ti_Tag) */
345 } /* while((tag = NextTagItem(&tstate))) */
349 RenderObject_Update(cl
, o
, msg
->ops_GInfo
);
356 /***********************************************************************************/
358 IPTR
AslCycle__OM_GET(Class
* cl
, Object
* o
, struct opGet
*msg
)
360 struct AslCycleData
*data
= INST_DATA(cl
, o
);
364 switch(msg
->opg_AttrID
)
367 *msg
->opg_Storage
= data
->active
;
371 retval
= DoSuperMethodA(cl
, o
, (Msg
)msg
);
378 /***********************************************************************************/
380 IPTR
AslCycle__GM_LAYOUT(Class
* cl
, struct Gadget
* g
, struct gpLayout
*msg
)
382 struct AslCycleData
*data
= INST_DATA(cl
, g
);
383 struct CycleItem
*item
;
387 getgadgetcoords(g
, msg
->gpl_GInfo
, &x
, &y
, &w
, &h
);
389 if (!data
->font
) data
->font
= msg
->gpl_GInfo
->gi_DrInfo
->dri_Font
;
391 item
= data
->itemmemory
;
394 InitRastPort(&data
->clonerp
);
395 SetFont(&data
->clonerp
, data
->font
);
397 for (i
= 0; i
< data
->numitems
; i
++, item
++)
399 item
->pixellen
= TextLength(&data
->clonerp
, item
->string
, item
->charlen
);
400 if (item
->pixellen
> len
) len
= item
->pixellen
;
403 data
->itemwidth
= len
+ 2;
404 i
= w
- CYCLEIMAGEWIDTH
- BORDERCYCLESPACINGX
;
405 if (data
->itemwidth
< i
) data
->itemwidth
= i
;
407 data
->itemheight
= data
->font
->tf_YSize
+ 2;
409 data
->borderleft
= 4;
410 data
->borderright
= 4;
412 data
->borderbottom
= 4;
414 data
->menuwidth
= data
->itemwidth
+ data
->borderleft
+ data
->borderright
;
416 data
->menuheight
= data
->numitems
* data
->itemheight
+
420 data
->menux1
= data
->borderleft
;
422 data
->maypopup
= TRUE
;
424 if (data
->menuheight
> msg
->gpl_GInfo
->gi_Screen
->Height
)
426 data
->visible
= (msg
->gpl_GInfo
->gi_Screen
->Height
-
429 (ARROWHEIGHT
+ 2) * 2) / data
->itemheight
;
431 if (data
->visible
< 2)
433 data
->maypopup
= FALSE
;
435 data
->menuheight
= data
->bordertop
+
436 data
->visible
* data
->itemheight
+
438 (ARROWHEIGHT
+ 2) * 2;
440 data
->menuy1
= data
->bordertop
+ ARROWHEIGHT
+ 2;
443 data
->visible
= data
->numitems
;
444 data
->menuy1
= data
->bordertop
;
447 data
->menux2
= data
->menux1
+ data
->itemwidth
- 1;
448 data
->menuy2
= data
->menuy1
+ data
->visible
* data
->itemheight
- 1;
453 /***********************************************************************************/
455 IPTR
AslCycle__GM_RENDER(Class
* cl
, struct Gadget
* g
, struct gpRender
*msg
)
457 struct AslCycleData
*data
= INST_DATA(cl
, g
);
458 struct RastPort
*rp
= msg
->gpr_RPort
;
459 struct DrawInfo
*dri
= msg
->gpr_GInfo
->gi_DrInfo
;
460 struct CycleItem
*item
;
461 WORD gadx
, gady
, gadw
, gadh
, x
, y
, y2
, a1
, a2
;
467 struct TagItem im_tags
[] =
474 getgadgetcoords(g
, msg
->gpr_GInfo
, &gadx
, &gady
, &gadw
, &gadh
);
476 im_tags
[0].ti_Data
= gadw
;
477 im_tags
[1].ti_Data
= gadh
;
479 SetAttrsA(data
->frame
, im_tags
);
481 DrawImageState(msg
->gpr_RPort
,
482 (struct Image
*)data
->frame
,
485 (g
->Flags
& GFLG_SELECTED
) ? IDS_SELECTED
: IDS_NORMAL
,
486 msg
->gpr_GInfo
->gi_DrInfo
);
491 selected
= (g
->Flags
& GFLG_SELECTED
) ? TRUE
: FALSE
;
492 SetABPenDrMd(rp
, dri
->dri_Pens
[selected
? FILLTEXTPEN
: TEXTPEN
], 0, JAM1
);
494 item
= &data
->itemmemory
[data
->active
];
496 a1
= gadx
+ BORDERCYCLESPACINGX
;
497 a2
= gadx
+ gadw
- CYCLEIMAGEWIDTH
- BORDERCYCLESPACINGX
;
498 x
= (a1
+ a2
- item
->pixellen
) / 2;
500 y
= gady
+ (gadh
- data
->font
->tf_YSize
) / 2 + data
->font
->tf_Baseline
;
502 SetFont(rp
, data
->font
);
505 Text(rp
, item
->string
, item
->charlen
);
508 x
= gadx
+ gadw
- CYCLEIMAGEWIDTH
;
510 y2
= gady
+ gadh
- 1 - 2;
514 SetAPen(rp
, dri
->dri_Pens
[SHINEPEN
]);
515 RectFill(rp
, x
+ 1, y
, x
+ 1, y2
);
516 SetAPen(rp
, dri
->dri_Pens
[SHADOWPEN
]);
517 RectFill(rp
, x
, y
, x
, y2
);
519 y
= gady
+ (gadh
- 4) / 2;
522 DrawArrow(cl
, rp
, x
, y
, ARROW_DOWN
);
529 /***********************************************************************************/
531 IPTR
AslCycle__GM_GOACTIVE(Class
* cl
, struct Gadget
* g
, struct gpInput
*msg
)
533 struct AslCycleData
*data
= INST_DATA(cl
, g
);
534 WORD x
, y
, x2
, y2
, gadx
, gady
, gadw
, gadh
;
536 IPTR rc
= GMR_MEACTIVE
;
538 if (!data
->labels
|| !msg
->gpi_IEvent
) return GMR_NOREUSE
;
541 data
->sentgadgetup
= FALSE
;
542 data
->turbocountdown
= TURBOCOUNTDOWN
;
544 getgadgetcoords(g
, msg
->gpi_GInfo
, &gadx
, &gady
, &gadw
, &gadh
);
546 x
= msg
->gpi_GInfo
->gi_Window
->MouseX
;
548 if (data
->maypopup
&& (data
->numitems
> 2) && (x
< gadx
+ gadw
- CYCLEIMAGEWIDTH
))
550 x
= msg
->gpi_GInfo
->gi_Window
->LeftEdge
+ gadx
;
551 y
= msg
->gpi_GInfo
->gi_Window
->TopEdge
+ gady
+ gadh
;
554 if ((x
+ data
->menuwidth
) > msg
->gpi_GInfo
->gi_Screen
->Width
)
556 x
= msg
->gpi_GInfo
->gi_Screen
->Width
- data
->menuwidth
;
560 if ((y
+ data
->menuheight
) > msg
->gpi_GInfo
->gi_Screen
->Height
)
562 y
= msg
->gpi_GInfo
->gi_Screen
->Height
- data
->menuheight
;
565 x2
= x
+ data
->menuwidth
- 1;
566 y2
= y
+ data
->menuheight
- 1;
568 if ((data
->popupwindow
= OpenWindowTags(0,WA_CustomScreen
, (IPTR
) msg
->gpi_GInfo
->gi_Screen
,
571 WA_Width
, data
->menuwidth
,
572 WA_Height
, data
->menuheight
,
573 WA_Flags
, WFLG_BORDERLESS
,
574 WA_BackFill
, (IPTR
) LAYERS_NOBACKFILL
,
579 data
->rp
= data
->popupwindow
->RPort
;
583 if (data
->popupwindow
)
585 data
->layerx1
= x
; data
->layery1
= y
;
586 data
->layerx2
= x2
; data
->layery2
= y2
;
590 SetDrMd(data
->rp
, JAM1
);
591 SetFont(data
->rp
, data
->font
);
594 DrawMenu(cl
, data
, msg
->gpi_GInfo
->gi_DrInfo
);
597 } /* if (data->maypopup && (data->numitems > 2) && (x < gadx + gadw - CYCLEIMAGEWIDTH)) */
600 g
->Flags
|= GFLG_SELECTED
;
601 RenderObject_Update(cl
, (Object
*)g
, msg
->gpi_GInfo
);
607 /***********************************************************************************/
609 IPTR
AslCycle__GM_HANDLEINPUT(Class
* cl
, struct Gadget
* g
, struct gpInput
*msg
)
611 struct AslCycleData
*data
= INST_DATA(cl
, g
);
612 WORD gadx
, gady
, gadw
, gadh
, x
, y
, i
;
613 IPTR rc
= GMR_MEACTIVE
;
615 getgadgetcoords(g
, msg
->gpi_GInfo
, &gadx
, &gady
, &gadw
, &gadh
);
619 if ((msg
->gpi_IEvent
->ie_Class
== IECLASS_RAWMOUSE
) &&
620 (msg
->gpi_IEvent
->ie_Code
== (IECODE_LBUTTON
| IECODE_UP_PREFIX
)))
623 if (data
->selected
!= -1)
625 data
->active
= data
->selected
;
626 data
->sentgadgetup
= TRUE
;
629 *msg
->gpi_Termination
= data
->active
;
635 x
= msg
->gpi_GInfo
->gi_Screen
->MouseX
- data
->layerx1
;
636 y
= msg
->gpi_GInfo
->gi_Screen
->MouseY
- data
->layery1
;
638 if ((x
< data
->menux1
) || (x
> data
->menux2
))
640 UnselectActiveItem(cl
, data
, msg
->gpi_GInfo
->gi_DrInfo
);
642 i
= (y
- data
->menuy1
) / data
->itemheight
;
644 if ((i
>= data
->visible
) || (y
< data
->menuy1
))
646 UnselectActiveItem(cl
, data
, msg
->gpi_GInfo
->gi_DrInfo
);
648 if (data
->turbocountdown
&& (msg
->gpi_IEvent
->ie_Class
== IECLASS_TIMER
))
650 data
->turbocountdown
--;
653 if (!data
->turbocountdown
|| (msg
->gpi_IEvent
->ie_Class
== IECLASS_TIMER
))
655 if (i
>= data
->visible
)
658 if (data
->top
+ data
->visible
< data
->numitems
)
660 ClipBlit(data
->rp
, data
->menux1
+ data
->menuleft
, data
->menuy1
+ data
->menutop
+ data
->itemheight
,
661 data
->rp
, data
->menux1
+ data
->menuleft
, data
->menuy1
+ data
->menutop
, data
->itemwidth
, data
->itemheight
* (data
->visible
- 1), 192);
663 DrawItem(cl
, data
, msg
->gpi_GInfo
->gi_DrInfo
, data
->top
+ data
->visible
- 1, FALSE
);
664 DrawUpArrow(cl
, data
, msg
->gpi_GInfo
->gi_DrInfo
, FALSE
);
665 DrawDownArrow(cl
, data
, msg
->gpi_GInfo
->gi_DrInfo
, FALSE
);
671 ClipBlit(data
->rp
, data
->menux1
+ data
->menuleft
, data
->menuy1
+ data
->menutop
,
672 data
->rp
, data
->menux1
+ data
->menuleft
, data
->menuy1
+ data
->menutop
+ data
->itemheight
, data
->itemwidth
, data
->itemheight
* (data
->visible
- 1), 192);
674 DrawItem(cl
, data
, msg
->gpi_GInfo
->gi_DrInfo
, data
->top
, FALSE
);
675 DrawUpArrow(cl
, data
, msg
->gpi_GInfo
->gi_DrInfo
, FALSE
);
676 DrawDownArrow(cl
, data
, msg
->gpi_GInfo
->gi_DrInfo
, FALSE
);
679 } /* if (!data->turbocountdown || (msg->gpi_IEvent->ie_Class == IECLASS_TIMER)) */
683 data
->turbocountdown
= TURBOCOUNTDOWN
;
685 data
->selected
= data
->top
+ i
;
686 if (data
->selected
!= x
)
688 DrawItem(cl
, data
, msg
->gpi_GInfo
->gi_DrInfo
, x
, FALSE
);
689 DrawItem(cl
, data
, msg
->gpi_GInfo
->gi_DrInfo
, data
->selected
, FALSE
);
694 } else { /* if (data->popup) */
696 /* like a GadTools cycle gadget */
698 switch(msg
->gpi_IEvent
->ie_Class
)
700 case IECLASS_RAWMOUSE
:
701 switch(msg
->gpi_IEvent
->ie_Code
)
703 case IECODE_LBUTTON
| IECODE_UP_PREFIX
:
704 if (g
->Flags
& GFLG_SELECTED
)
707 if (data
->active
>= data
->numitems
) data
->active
= 0;
709 g
->Flags
&= (~GFLG_SELECTED
);
710 RenderObject_Update(cl
, (Object
*)g
, msg
->gpi_GInfo
);
712 *msg
->gpi_Termination
= g
->GadgetID
;
718 if ((msg
->gpi_Mouse
.X
>= 0 ) &&
719 (msg
->gpi_Mouse
.Y
>= 0 ) &&
720 (msg
->gpi_Mouse
.X
< gadw
) &&
721 (msg
->gpi_Mouse
.Y
< gadh
))
723 if (!(g
->Flags
& GFLG_SELECTED
))
725 g
->Flags
|= GFLG_SELECTED
;
726 RenderObject_Update(cl
, (Object
*)g
, msg
->gpi_GInfo
);
729 if (g
->Flags
& GFLG_SELECTED
)
731 g
->Flags
&= (~GFLG_SELECTED
);
732 RenderObject_Update(cl
, (Object
*)g
, msg
->gpi_GInfo
);
739 } /* switch(msg->gpi_IEvent->ie_Code) */
741 } /* switch(msg->gpi_IEvent->ie_Class) */
743 } /* if (data->popup) {...} else { */
751 /***********************************************************************************/
753 IPTR
AslCycle__GM_GOINACTIVE(Class
* cl
, Object
* o
, struct gpGoInactive
*msg
)
755 struct AslCycleData
*data
= INST_DATA(cl
, o
);
757 if (data
->popupwindow
)
759 CloseWindow(data
->popupwindow
);
760 data
->popupwindow
= 0;
763 if (data
->sentgadgetup
)
765 RenderObject_Update(cl
, o
, msg
->gpgi_GInfo
);
771 /***********************************************************************************/