use m4_normalize on the output strings to remove trailing spaces/tabs and consolidate...
[AROS.git] / workbench / c / Decoration / menudecorclass.c
blob76fc69c1198cf3176d521e46cd319859646649ad
1 /*
2 Copyright 2011-2012, The AROS Development Team.
3 $Id$
4 */
6 #define DEBUG 0
7 #include <aros/debug.h>
9 #include <clib/alib_protos.h>
11 #include <intuition/intuition.h>
12 #include <intuition/extensions.h>
13 #include <intuition/imageclass.h>
14 #include <proto/intuition.h>
15 #include <proto/graphics.h>
16 #include <proto/utility.h>
17 #include <proto/exec.h>
19 #include "menudecorclass.h"
20 #include "screendecorclass.h"
21 #include "drawfuncs.h"
22 #include "config.h"
25 #define SETIMAGE_MEN(id) md->img_##id=sd->di->img_##id
27 struct menudecor_data
29 struct DecorConfig * dc;
31 /* Pointers to images used for sys images */
32 struct NewImage *img_amigakey;
33 struct NewImage *img_menucheck;
34 struct NewImage *img_submenu;
37 static IPTR menudecor_getdefsizes(Class *cl, Object *obj, struct mdpGetDefSizeSysImage *msg)
39 struct menudecor_data *data = INST_DATA(cl, obj);
41 struct NewImage *n = NULL;
42 BOOL isset = FALSE;
44 switch(msg->mdp_Which)
46 case AMIGAKEY:
47 n = data->img_amigakey;
48 if(n) isset = TRUE;
49 break;
51 case MENUCHECK:
52 n = data->img_menucheck;
53 if(n) isset = TRUE;
54 break;
56 case SUBMENUIMAGE:
57 n = data->img_submenu;
58 if(n) isset = TRUE;
59 break;
61 default:
62 return FALSE;
65 if (!isset) return DoSuperMethodA(cl, obj, (Msg) msg);
67 *msg->mdp_Width = n->w;
68 *msg->mdp_Height = n->h;
69 return TRUE;
72 static IPTR menudecor_getmenuspaces(Class *cl, Object *obj, struct mdpGetMenuSpaces *msg)
74 struct menudecor_data *data = INST_DATA(cl, obj);
76 msg->mdp_InnerLeft = data->dc->MenuInnerLeft;
77 msg->mdp_InnerTop = data->dc->MenuInnerTop;
78 msg->mdp_InnerRight = data->dc->MenuInnerRight;
79 msg->mdp_InnerBottom = data->dc->MenuInnerBottom;
80 msg->mdp_ItemInnerLeft = 1;
81 msg->mdp_ItemInnerTop = 2;
82 msg->mdp_ItemInnerRight = 2;
83 msg->mdp_ItemInnerBottom = 1;
84 if ((data->dc->MenuTileLeft + data->dc->MenuTileRight) > (data->dc->MenuInnerLeft + data->dc->MenuInnerRight))
85 msg->mdp_MinWidth = data->dc->MenuTileLeft + data->dc->MenuTileRight;
86 else
87 msg->mdp_MinWidth = data->dc->MenuInnerLeft + data->dc->MenuInnerRight;
89 if ((data->dc->MenuTileTop + data->dc->MenuTileBottom) > (data->dc->MenuInnerTop + data->dc->MenuInnerBottom))
90 msg->mdp_MinHeight = data->dc->MenuTileTop + data->dc->MenuTileBottom;
91 else
92 msg->mdp_MinHeight = data->dc->MenuInnerTop + data->dc->MenuInnerBottom;
94 return TRUE;
97 static IPTR menudecor_draw_sysimage(Class *cl, Object *obj, struct mdpDrawSysImage *msg)
99 struct ScreenData *md = (struct ScreenData *) msg->mdp_UserBuffer;
100 struct RastPort *rp = msg->mdp_RPort;
101 struct NewImage *ni = NULL;
102 LONG left = msg->mdp_X;
103 LONG top = msg->mdp_Y;
104 WORD addx = 0;
105 WORD addy = 0;
106 BOOL isset = FALSE;
108 switch(msg->mdp_Which)
110 case AMIGAKEY:
111 if (md && md->img_amigakey->ok)
113 ni = md->img_amigakey;
114 isset = TRUE;
116 break;
118 case MENUCHECK:
119 if (md && md->img_menucheck->ok)
121 ni = md->img_menucheck;
122 isset = TRUE;
124 break;
126 case SUBMENUIMAGE:
127 if (md && md->img_submenu->ok)
129 ni = md->img_submenu;
130 isset = TRUE;
132 break;
134 default:
135 return DoSuperMethodA(cl, obj, (Msg)msg);
138 if (!isset || (ni == NULL)) return DoSuperMethodA(cl, obj, (Msg)msg);
140 DrawStatefulGadgetImageToRP(rp, ni, IDS_NORMAL, left + addx, top + addy);
142 return TRUE;
145 /**************************************************************************************************/
147 static IPTR menudecor_renderbackground(Class *cl, Object *obj, struct mdpDrawBackground *msg)
149 struct menudecor_data *data = INST_DATA(cl, obj);
150 struct RastPort *rp = msg->mdp_RPort;
151 struct NewImage *ni;
152 struct MenuData *md = (struct MenuData *) msg->mdp_UserBuffer;
153 UWORD flags = msg->mdp_Flags;
155 if ((flags & HIGHITEM) && md->ni)
157 ni = NewImageContainer(msg->mdp_ItemWidth, msg->mdp_ItemHeight);
158 if (ni)
160 DrawPartToImage(md->ni, ni, msg->mdp_ItemLeft, msg->mdp_ItemTop, msg->mdp_ItemWidth, msg->mdp_ItemHeight, 0, 0);
161 SetImageTint(ni, 255 - (data->dc->MenuHighlightTint >> 24), data->dc->MenuHighlightTint & 0xffffff);
162 PutImageToRP(rp, ni, msg->mdp_ItemLeft, msg->mdp_ItemTop);
165 else
167 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 return TRUE;
173 static IPTR menudecor_initmenu(Class *cl, Object *obj, struct mdpInitMenu *msg)
175 struct menudecor_data *data = INST_DATA(cl, obj);
176 struct RastPort *rp = msg->mdp_RPort;
177 struct MenuData *md = (struct MenuData *) msg->mdp_UserBuffer;
178 struct ScreenData *sd = (struct ScreenData *) msg->mdp_ScreenUserBuffer;
180 SETIMAGE_MEN(menu);
181 SETIMAGE_MEN(amigakey);
182 SETIMAGE_MEN(menucheck);
183 SETIMAGE_MEN(submenu);
185 if (data->dc->MenuIsTiled)
187 md->img_menu_ti = AllocVec(sizeof(struct TileInfo), MEMF_ANY | MEMF_CLEAR);
188 md->img_menu_ti->TileLeft = data->dc->MenuTileLeft;
189 md->img_menu_ti->TileRight = data->dc->MenuTileRight;
190 md->img_menu_ti->TileBottom = data->dc->MenuTileBottom;
191 md->img_menu_ti->TileTop = data->dc->MenuTileTop;
194 if ((msg->mdp_MenuDecorFlags & MDP_MDF_MENU) && !(msg->mdp_MenuDecorFlags & MDP_MDF_MENUS_UNDERMOUSE))
196 /* Special handling for pulled down menu bar */
197 LONG height = msg->mdp_Height;
199 /* Increase height for rendering if needed */
200 if ((data->dc->MenuIsTiled) && (height < (md->img_menu_ti->TileBottom + md->img_menu_ti->TileTop)))
201 height = (md->img_menu_ti->TileBottom + md->img_menu_ti->TileTop);
203 md->ni = NewImageContainer(msg->mdp_Width, height);
204 if (md->ni)
206 md->ni->ok = TRUE;
207 RenderMenuBarBackground(md->ni, md->img_menu, md->img_menu_ti, 20);
209 /* Scale down if needed */
210 if (height > msg->mdp_Height)
212 struct NewImage * sni = ScaleNewImage(md->ni, msg->mdp_Width, msg->mdp_Height);
213 if (sni)
215 DisposeImageContainer(md->ni);
216 md->ni = sni;
217 md->ni->ok = TRUE;
222 else
224 md->ni = GetImageFromRP(rp, msg->mdp_Left, msg->mdp_Top, msg->mdp_Width, msg->mdp_Height);
225 if (md->ni)
227 md->ni->ok = TRUE;
228 RenderMenuBackground(md->ni, md->img_menu, md->img_menu_ti, 20);
233 return TRUE;
236 static IPTR menudecor_exitmenu(Class *cl, Object *obj, struct mdpExitMenu *msg)
238 struct MenuData *md = (struct MenuData *) msg->mdp_UserBuffer;
240 if (md->ni) DisposeImageContainer(md->ni);
241 if (md->map) FreeBitMap(md->map);
242 if (md->img_menu_ti) FreeVec(md->img_menu_ti);
244 return TRUE;
247 static void DisposeMenuSkinning(struct menudecor_data *data)
251 static BOOL InitMenuSkinning(struct menudecor_data *data, struct DecorImages * di, struct DecorConfig * dc)
253 if ((!dc) || (!di))
254 return FALSE;
256 data->dc = dc;
258 /* Set pointers to gadget images, used only to get gadget sizes as they
259 are requested prior to creation of menu object */
260 data->img_amigakey = di->img_amigakey;
261 data->img_menucheck = di->img_menucheck;
262 data->img_submenu = di->img_submenu;
264 return TRUE;
267 static IPTR menudecor__OM_NEW(Class *cl, Object *obj, struct opSet *msg)
269 struct menudecor_data *data;
271 D(bug("menudecor__OM_NEW(tags @ 0x%p)\n", msg->ops_AttrList));
273 obj = (Object *)DoSuperMethodA(cl, obj, (Msg)msg);
274 if (obj)
276 data = INST_DATA(cl, obj);
278 struct DecorImages * di = (struct DecorImages *) GetTagData(MDA_DecorImages, (IPTR) NULL, msg->ops_AttrList);
279 struct DecorConfig * dc = (struct DecorConfig *) GetTagData(MDA_DecorConfig, (IPTR) NULL, msg->ops_AttrList);
281 D(bug("menudecor__OM_NEW: DecorImages @ 0x%p\n", di));
282 D(bug("menudecor__OM_NEW: DecorConfig @ 0x%p\n", dc));
284 if (!InitMenuSkinning(data, di, dc))
286 CoerceMethod(cl, obj ,OM_DISPOSE);
287 obj = NULL;
290 return (IPTR)obj;
294 static IPTR menudecor__OM_DISPOSE(Class *cl, Object *obj, struct opSet *msg)
296 struct menudecor_data *data = INST_DATA(cl, obj);
298 DisposeMenuSkinning(data);
300 return DoSuperMethodA(cl, obj, (Msg)msg);
303 static IPTR menudecor_dispatcher(struct IClass *cl, Object *obj, Msg msg)
305 IPTR retval;
307 switch(msg->MethodID)
309 case OM_NEW:
310 retval = menudecor__OM_NEW(cl, obj, (struct opSet *) msg);
311 break;
313 case OM_DISPOSE:
314 retval = menudecor__OM_DISPOSE(cl, obj, (struct opSet *) msg);
315 break;
317 case MDM_DRAW_SYSIMAGE:
318 retval = menudecor_draw_sysimage(cl, obj, (struct mdpDrawSysImage *)msg);
319 break;
321 case MDM_GETDEFSIZE_SYSIMAGE:
322 retval = menudecor_getdefsizes(cl, obj, (struct mdpGetDefSizeSysImage *) msg);
323 break;
325 case MDM_DRAWBACKGROUND:
326 retval = menudecor_renderbackground(cl, obj, (struct mdpDrawBackground *)msg);
327 break;
329 case MDM_INITMENU:
330 retval = menudecor_initmenu(cl, obj, (struct mdpInitMenu *)msg);
331 break;
333 case MDM_EXITMENU:
334 retval = menudecor_exitmenu(cl, obj, (struct mdpExitMenu *)msg);
335 break;
337 case MDM_GETMENUSPACES:
338 retval = menudecor_getmenuspaces(cl, obj, (struct mdpGetMenuSpaces *)msg);
339 break;
341 default:
342 retval = DoSuperMethodA(cl, obj, msg);
343 break;
346 return retval;
349 struct IClass * MakeMenuDecorClass()
351 struct IClass * cl = MakeClass(NULL, MENUDECORCLASS, NULL, sizeof(struct menudecor_data), 0);
352 if (cl)
354 cl->cl_Dispatcher.h_Entry = HookEntry;
355 cl->cl_Dispatcher.h_SubEntry = (HOOKFUNC)menudecor_dispatcher;
358 return cl;