- Allow menu highlight colour to be configured through an ARGB hex value in
[AROS.git] / workbench / c / Decoration / menudecorclass.c
blob619208cd818886580c7244972a8273230baf2114
1 /*
2 Copyright 2011-2012, The AROS Development Team.
3 $Id$
4 */
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"
19 #include "config.h"
22 #define SETIMAGE_MEN(id) md->img_##id=sd->di->img_##id
24 struct menudecor_data
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;
39 BOOL isset = FALSE;
41 switch(msg->mdp_Which)
43 case AMIGAKEY:
44 n = data->img_amigakey;
45 if(n) isset = TRUE;
46 break;
48 case MENUCHECK:
49 n = data->img_menucheck;
50 if(n) isset = TRUE;
51 break;
53 case SUBMENUIMAGE:
54 n = data->img_submenu;
55 if(n) isset = TRUE;
56 break;
58 default:
59 return FALSE;
62 if (!isset) return DoSuperMethodA(cl, obj, (Msg) msg);
64 *msg->mdp_Width = n->w;
65 *msg->mdp_Height = n->h;
66 return TRUE;
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;
83 else
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;
88 else
89 msg->mdp_MinHeight = data->dc->MenuInnerTop + data->dc->MenuInnerBottom;
91 return TRUE;
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;
101 WORD addx = 0;
102 WORD addy = 0;
103 BOOL isset = FALSE;
105 switch(msg->mdp_Which)
107 case AMIGAKEY:
108 if (md && md->img_amigakey->ok)
110 ni = md->img_amigakey;
111 isset = TRUE;
113 break;
115 case MENUCHECK:
116 if (md && md->img_menucheck->ok)
118 ni = md->img_menucheck;
119 isset = TRUE;
121 break;
123 case SUBMENUIMAGE:
124 if (md && md->img_submenu->ok)
126 ni = md->img_submenu;
127 isset = TRUE;
129 break;
131 default:
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);
139 return TRUE;
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;
148 struct NewImage *ni;
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);
155 if (ni)
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);
162 else
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);
167 return TRUE;
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;
177 SETIMAGE_MEN(menu);
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);
201 if (md->ni)
203 md->ni->ok = TRUE;
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);
210 if (sni)
212 DisposeImageContainer(md->ni);
213 md->ni = sni;
214 md->ni->ok = TRUE;
219 else
221 md->ni = GetImageFromRP(rp, msg->mdp_Left, msg->mdp_Top, msg->mdp_Width, msg->mdp_Height);
222 if (md->ni)
224 md->ni->ok = TRUE;
225 RenderMenuBackground(md->ni, md->img_menu, md->img_menu_ti, 20);
230 return TRUE;
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);
241 return TRUE;
244 static void DisposeMenuSkinning(struct menudecor_data *data)
248 static BOOL InitMenuSkinning(struct menudecor_data *data, struct DecorImages * di, struct DecorConfig * dc)
250 if ((!dc) || (!di))
251 return FALSE;
253 data->dc = 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;
261 return TRUE;
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);
269 if (obj)
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);
279 obj = NULL;
282 return (IPTR)obj;
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)
297 IPTR retval;
299 switch(msg->MethodID)
301 case OM_NEW:
302 retval = menudecor__OM_NEW(cl, obj, (struct opSet *) msg);
303 break;
305 case OM_DISPOSE:
306 retval = menudecor__OM_DISPOSE(cl, obj, (struct opSet *) msg);
307 break;
309 case MDM_DRAW_SYSIMAGE:
310 retval = menudecor_draw_sysimage(cl, obj, (struct mdpDrawSysImage *)msg);
311 break;
313 case MDM_GETDEFSIZE_SYSIMAGE:
314 retval = menudecor_getdefsizes(cl, obj, (struct mdpGetDefSizeSysImage *) msg);
315 break;
317 case MDM_DRAWBACKGROUND:
318 retval = menudecor_renderbackground(cl, obj, (struct mdpDrawBackground *)msg);
319 break;
321 case MDM_INITMENU:
322 retval = menudecor_initmenu(cl, obj, (struct mdpInitMenu *)msg);
323 break;
325 case MDM_EXITMENU:
326 retval = menudecor_exitmenu(cl, obj, (struct mdpExitMenu *)msg);
327 break;
329 case MDM_GETMENUSPACES:
330 retval = menudecor_getmenuspaces(cl, obj, (struct mdpGetMenuSpaces *)msg);
331 break;
333 default:
334 retval = DoSuperMethodA(cl, obj, msg);
335 break;
338 return retval;
341 struct IClass * MakeMenuDecorClass()
343 struct IClass * cl = MakeClass(NULL, MENUDECORCLASS, NULL, sizeof(struct menudecor_data), 0);
344 if (cl)
346 cl->cl_Dispatcher.h_Entry = HookEntry;
347 cl->cl_Dispatcher.h_SubEntry = (HOOKFUNC)menudecor_dispatcher;
350 return cl;