2 Copyright 2011-2012, The AROS Development Team.
6 #include <clib/alib_protos.h>
8 #include <intuition/intuition.h>
9 #include <intuition/extensions.h>
10 #include <intuition/imageclass.h>
11 #include <proto/intuition.h>
12 #include <proto/graphics.h>
13 #include <proto/utility.h>
14 #include <proto/exec.h>
16 #include "menudecorclass.h"
17 #include "screendecorclass.h"
18 #include "drawfuncs.h"
22 #define SETIMAGE_MEN(id) md->img_##id=sd->di->img_##id
26 struct DecorConfig
* dc
;
28 /* Pointers to images used for sys images */
29 struct NewImage
*img_amigakey
;
30 struct NewImage
*img_menucheck
;
31 struct NewImage
*img_submenu
;
34 static IPTR
menudecor_getdefsizes(Class
*cl
, Object
*obj
, struct mdpGetDefSizeSysImage
*msg
)
36 struct menudecor_data
*data
= INST_DATA(cl
, obj
);
38 struct NewImage
*n
= NULL
;
41 switch(msg
->mdp_Which
)
44 n
= data
->img_amigakey
;
49 n
= data
->img_menucheck
;
54 n
= data
->img_submenu
;
62 if (!isset
) return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
64 *msg
->mdp_Width
= n
->w
;
65 *msg
->mdp_Height
= n
->h
;
69 static IPTR
menudecor_getmenuspaces(Class
*cl
, Object
*obj
, struct mdpGetMenuSpaces
*msg
)
71 struct menudecor_data
*data
= INST_DATA(cl
, obj
);
73 msg
->mdp_InnerLeft
= data
->dc
->MenuInnerLeft
;
74 msg
->mdp_InnerTop
= data
->dc
->MenuInnerTop
;
75 msg
->mdp_InnerRight
= data
->dc
->MenuInnerRight
;
76 msg
->mdp_InnerBottom
= data
->dc
->MenuInnerBottom
;
77 msg
->mdp_ItemInnerLeft
= 1;
78 msg
->mdp_ItemInnerTop
= 2;
79 msg
->mdp_ItemInnerRight
= 2;
80 msg
->mdp_ItemInnerBottom
= 1;
81 if ((data
->dc
->MenuTileLeft
+ data
->dc
->MenuTileRight
) > (data
->dc
->MenuInnerLeft
+ data
->dc
->MenuInnerRight
))
82 msg
->mdp_MinWidth
= data
->dc
->MenuTileLeft
+ data
->dc
->MenuTileRight
;
84 msg
->mdp_MinWidth
= data
->dc
->MenuInnerLeft
+ data
->dc
->MenuInnerRight
;
86 if ((data
->dc
->MenuTileTop
+ data
->dc
->MenuTileBottom
) > (data
->dc
->MenuInnerTop
+ data
->dc
->MenuInnerBottom
))
87 msg
->mdp_MinHeight
= data
->dc
->MenuTileTop
+ data
->dc
->MenuTileBottom
;
89 msg
->mdp_MinHeight
= data
->dc
->MenuInnerTop
+ data
->dc
->MenuInnerBottom
;
94 static IPTR
menudecor_draw_sysimage(Class
*cl
, Object
*obj
, struct mdpDrawSysImage
*msg
)
96 struct ScreenData
*md
= (struct ScreenData
*) msg
->mdp_UserBuffer
;
97 struct RastPort
*rp
= msg
->mdp_RPort
;
98 struct NewImage
*ni
= NULL
;
99 LONG left
= msg
->mdp_X
;
100 LONG top
= msg
->mdp_Y
;
105 switch(msg
->mdp_Which
)
108 if (md
&& md
->img_amigakey
->ok
)
110 ni
= md
->img_amigakey
;
116 if (md
&& md
->img_menucheck
->ok
)
118 ni
= md
->img_menucheck
;
124 if (md
&& md
->img_submenu
->ok
)
126 ni
= md
->img_submenu
;
132 return DoSuperMethodA(cl
, obj
, (Msg
)msg
);
135 if (!isset
|| (ni
== NULL
)) return DoSuperMethodA(cl
, obj
, (Msg
)msg
);
137 DrawStatefulGadgetImageToRP(rp
, ni
, IDS_NORMAL
, left
+ addx
, top
+ addy
);
142 /**************************************************************************************************/
144 static IPTR
menudecor_renderbackground(Class
*cl
, Object
*obj
, struct mdpDrawBackground
*msg
)
146 struct menudecor_data
*data
= INST_DATA(cl
, obj
);
147 struct RastPort
*rp
= msg
->mdp_RPort
;
149 struct MenuData
*md
= (struct MenuData
*) msg
->mdp_UserBuffer
;
150 UWORD flags
= msg
->mdp_Flags
;
152 if ((flags
& HIGHITEM
) && md
->ni
)
154 ni
= NewImageContainer(msg
->mdp_ItemWidth
, msg
->mdp_ItemHeight
);
157 DrawPartToImage(md
->ni
, ni
, msg
->mdp_ItemLeft
, msg
->mdp_ItemTop
, msg
->mdp_ItemWidth
, msg
->mdp_ItemHeight
, 0, 0);
158 SetImageTint(ni
, 255 - (data
->dc
->MenuHighlightTint
>> 24), data
->dc
->MenuHighlightTint
& 0xffffff);
159 PutImageToRP(rp
, ni
, msg
->mdp_ItemLeft
, msg
->mdp_ItemTop
);
164 if (md
->ni
) DrawPartImageToRP(rp
, md
->ni
, msg
->mdp_ItemLeft
, msg
->mdp_ItemTop
, msg
->mdp_ItemLeft
, msg
->mdp_ItemTop
, msg
->mdp_ItemWidth
, msg
->mdp_ItemHeight
);
170 static IPTR
menudecor_initmenu(Class
*cl
, Object
*obj
, struct mdpInitMenu
*msg
)
172 struct menudecor_data
*data
= INST_DATA(cl
, obj
);
173 struct RastPort
*rp
= msg
->mdp_RPort
;
174 struct MenuData
*md
= (struct MenuData
*) msg
->mdp_UserBuffer
;
175 struct ScreenData
*sd
= (struct ScreenData
*) msg
->mdp_ScreenUserBuffer
;
178 SETIMAGE_MEN(amigakey
);
179 SETIMAGE_MEN(menucheck
);
180 SETIMAGE_MEN(submenu
);
182 if (data
->dc
->MenuIsTiled
)
184 md
->img_menu_ti
= AllocVec(sizeof(struct TileInfo
), MEMF_ANY
| MEMF_CLEAR
);
185 md
->img_menu_ti
->TileLeft
= data
->dc
->MenuTileLeft
;
186 md
->img_menu_ti
->TileRight
= data
->dc
->MenuTileRight
;
187 md
->img_menu_ti
->TileBottom
= data
->dc
->MenuTileBottom
;
188 md
->img_menu_ti
->TileTop
= data
->dc
->MenuTileTop
;
191 if ((msg
->mdp_MenuDecorFlags
& MDP_MDF_MENU
) && !(msg
->mdp_MenuDecorFlags
& MDP_MDF_MENUS_UNDERMOUSE
))
193 /* Special handling for pulled down menu bar */
194 LONG height
= msg
->mdp_Height
;
196 /* Increase height for rendering if needed */
197 if ((data
->dc
->MenuIsTiled
) && (height
< (md
->img_menu_ti
->TileBottom
+ md
->img_menu_ti
->TileTop
)))
198 height
= (md
->img_menu_ti
->TileBottom
+ md
->img_menu_ti
->TileTop
);
200 md
->ni
= NewImageContainer(msg
->mdp_Width
, height
);
204 RenderMenuBarBackground(md
->ni
, md
->img_menu
, md
->img_menu_ti
, 20);
206 /* Scale down if needed */
207 if (height
> msg
->mdp_Height
)
209 struct NewImage
* sni
= ScaleNewImage(md
->ni
, msg
->mdp_Width
, msg
->mdp_Height
);
212 DisposeImageContainer(md
->ni
);
221 md
->ni
= GetImageFromRP(rp
, msg
->mdp_Left
, msg
->mdp_Top
, msg
->mdp_Width
, msg
->mdp_Height
);
225 RenderMenuBackground(md
->ni
, md
->img_menu
, md
->img_menu_ti
, 20);
233 static IPTR
menudecor_exitmenu(Class
*cl
, Object
*obj
, struct mdpExitMenu
*msg
)
235 struct MenuData
*md
= (struct MenuData
*) msg
->mdp_UserBuffer
;
237 if (md
->ni
) DisposeImageContainer(md
->ni
);
238 if (md
->map
) FreeBitMap(md
->map
);
239 if (md
->img_menu_ti
) FreeVec(md
->img_menu_ti
);
244 static void DisposeMenuSkinning(struct menudecor_data
*data
)
248 static BOOL
InitMenuSkinning(struct menudecor_data
*data
, struct DecorImages
* di
, struct DecorConfig
* dc
)
255 /* Set pointers to gadget images, used only to get gadget sizes as they
256 are requested prior to creation of menu object */
257 data
->img_amigakey
= di
->img_amigakey
;
258 data
->img_menucheck
= di
->img_menucheck
;
259 data
->img_submenu
= di
->img_submenu
;
264 static IPTR
menudecor__OM_NEW(Class
*cl
, Object
*obj
, struct opSet
*msg
)
266 struct menudecor_data
*data
;
268 obj
= (Object
*)DoSuperMethodA(cl
, obj
, (Msg
)msg
);
271 data
= INST_DATA(cl
, obj
);
273 struct DecorImages
* di
= (struct DecorImages
*) GetTagData(MDA_DecorImages
, (IPTR
) NULL
, msg
->ops_AttrList
);
274 struct DecorConfig
* dc
= (struct DecorConfig
*) GetTagData(MDA_DecorConfig
, (IPTR
) NULL
, msg
->ops_AttrList
);
276 if (!InitMenuSkinning(data
, di
, dc
))
278 CoerceMethod(cl
, obj
,OM_DISPOSE
);
286 static IPTR
menudecor__OM_DISPOSE(Class
*cl
, Object
*obj
, struct opSet
*msg
)
288 struct menudecor_data
*data
= INST_DATA(cl
, obj
);
290 DisposeMenuSkinning(data
);
292 return DoSuperMethodA(cl
, obj
, (Msg
)msg
);
295 static IPTR
menudecor_dispatcher(struct IClass
*cl
, Object
*obj
, Msg msg
)
299 switch(msg
->MethodID
)
302 retval
= menudecor__OM_NEW(cl
, obj
, (struct opSet
*) msg
);
306 retval
= menudecor__OM_DISPOSE(cl
, obj
, (struct opSet
*) msg
);
309 case MDM_DRAW_SYSIMAGE
:
310 retval
= menudecor_draw_sysimage(cl
, obj
, (struct mdpDrawSysImage
*)msg
);
313 case MDM_GETDEFSIZE_SYSIMAGE
:
314 retval
= menudecor_getdefsizes(cl
, obj
, (struct mdpGetDefSizeSysImage
*) msg
);
317 case MDM_DRAWBACKGROUND
:
318 retval
= menudecor_renderbackground(cl
, obj
, (struct mdpDrawBackground
*)msg
);
322 retval
= menudecor_initmenu(cl
, obj
, (struct mdpInitMenu
*)msg
);
326 retval
= menudecor_exitmenu(cl
, obj
, (struct mdpExitMenu
*)msg
);
329 case MDM_GETMENUSPACES
:
330 retval
= menudecor_getmenuspaces(cl
, obj
, (struct mdpGetMenuSpaces
*)msg
);
334 retval
= DoSuperMethodA(cl
, obj
, msg
);
341 struct IClass
* MakeMenuDecorClass()
343 struct IClass
* cl
= MakeClass(NULL
, MENUDECORCLASS
, NULL
, sizeof(struct menudecor_data
), 0);
346 cl
->cl_Dispatcher
.h_Entry
= HookEntry
;
347 cl
->cl_Dispatcher
.h_SubEntry
= (HOOKFUNC
)menudecor_dispatcher
;