Tabs to spaces, more consistent formatting.
[AROS.git] / workbench / libs / muimaster / classes / menuitem.c
blobc49135191e6675117be8483386018ca19fd17f61
1 /*
2 Copyright © 2002-2007, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <exec/memory.h>
7 #include <intuition/icclass.h>
8 #include <intuition/gadgetclass.h>
9 #include <libraries/gadtools.h>
10 #include <clib/alib_protos.h>
11 #include <proto/exec.h>
12 #include <proto/intuition.h>
13 #include <proto/utility.h>
14 #include <proto/muimaster.h>
16 /* #define MYDEBUG 1 */
17 #include "debug.h"
18 #include "mui.h"
19 #include "muimaster_intern.h"
20 #include "support.h"
22 extern struct Library *MUIMasterBase;
24 #define MENUF_CHECKED (1<<0)
25 #define MENUF_CHECKIT (1<<1)
26 #define MENUF_COMMANDSTRING (1<<2)
27 #define MENUF_ENABLED (1<<3)
28 #define MENUF_TOGGLE (1<<4)
30 struct MUI_MenuitemData
32 ULONG flags;
33 ULONG exclude;
35 char *shortcut;
36 char *title;
38 struct NewMenu *newmenu;
40 struct MenuItem *trigger;
43 static int Menuitem_GetTotalChildren(Object *obj)
45 Object *cstate;
46 Object *child;
47 struct MinList *ChildList = NULL;
48 int num = 0;
50 get(obj, MUIA_Family_List, &ChildList);
51 cstate = (Object *) ChildList->mlh_Head;
52 while ((child = NextObject(&cstate)))
54 num++;
55 num += Menuitem_GetTotalChildren(child);
57 return num;
60 static int Menuitem_FillNewMenu(Object *obj, struct NewMenu *menu,
61 int depth)
63 Object *cstate;
64 Object *child;
65 struct MinList *ChildList = NULL;
66 int num = 0;
68 if (depth > 2)
69 return 0;
71 get(obj, MUIA_Family_List, &ChildList);
72 cstate = (Object *) ChildList->mlh_Head;
73 while ((child = NextObject(&cstate)))
75 int entries;
76 ULONG checkit = 0, checked = 0, toggle = 0, enabled = 0;
78 get(child, MUIA_Menuitem_Title, &menu->nm_Label);
79 get(child, MUIA_Menuitem_Shortcut, &menu->nm_CommKey);
80 get(child, MUIA_Menuitem_Checkit, &checkit);
81 get(child, MUIA_Menuitem_Checked, &checked);
82 get(child, MUIA_Menuitem_Toggle, &toggle);
83 get(child, MUIA_Menuitem_Enabled, &enabled);
84 if (checkit)
85 menu->nm_Flags |= CHECKIT;
86 if (checked)
87 menu->nm_Flags |= CHECKED;
88 if (toggle)
89 menu->nm_Flags |= MENUTOGGLE;
90 get(child, MUIA_Menuitem_Exclude, &menu->nm_MutualExclude);
92 if (depth == 0)
94 menu->nm_Type = NM_TITLE;
95 if (!enabled)
96 menu->nm_Flags |= NM_MENUDISABLED;
98 else if (depth == 1)
100 menu->nm_Type = NM_ITEM;
101 if (!enabled)
102 menu->nm_Flags |= NM_ITEMDISABLED;
104 else if (depth == 2)
106 menu->nm_Type = NM_SUB;
107 if (!enabled)
108 menu->nm_Flags |= NM_ITEMDISABLED;
111 menu->nm_UserData = child;
113 menu++;
114 num++;
115 entries = Menuitem_FillNewMenu(child, menu, depth + 1);
117 menu += entries;
118 num += entries;
120 return num;
123 /**************************************************************************
125 **************************************************************************/
126 static struct NewMenu *Menuitem_BuildNewMenu(struct MUI_MenuitemData *data,
127 Object *obj)
129 int entries = Menuitem_GetTotalChildren(obj);
130 if (data->newmenu)
131 FreeVec(data->newmenu);
132 data->newmenu = NULL;
133 if (!entries)
134 return NULL;
136 if ((data->newmenu =
137 (struct NewMenu *)AllocVec((entries +
138 1) * sizeof(struct NewMenu), MEMF_CLEAR)))
140 Menuitem_FillNewMenu(obj, data->newmenu, 0);
142 return data->newmenu;
145 /**************************************************************************
146 OM_NEW
147 **************************************************************************/
148 IPTR Menuitem__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
150 struct MUI_MenuitemData *data;
151 struct TagItem *tags, *tag;
153 obj = (Object *) DoSuperMethodA(cl, obj, (Msg) msg);
154 /* We need no tags */
155 if (!obj)
156 return 0;
158 data = INST_DATA(cl, obj);
160 data->flags = MENUF_ENABLED;
162 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
164 switch (tag->ti_Tag)
166 case MUIA_Menuitem_Checked:
167 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_CHECKED);
168 break;
170 case MUIA_Menuitem_Checkit:
171 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_CHECKIT);
172 break;
174 case MUIA_Menuitem_CommandString:
175 _handle_bool_tag(data->flags, tag->ti_Data,
176 MENUF_COMMANDSTRING);
177 break;
179 case MUIA_Menu_Enabled:
180 case MUIA_Menuitem_Enabled:
181 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_ENABLED);
182 break;
184 case MUIA_Menuitem_Toggle:
185 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_TOGGLE);
186 break;
188 case MUIA_Menuitem_Exclude:
189 data->exclude = tag->ti_Data;
190 break;
192 case MUIA_Menuitem_Shortcut:
193 data->shortcut = (char *)tag->ti_Data;
194 break;
196 case MUIA_Menu_Title:
197 case MUIA_Menuitem_Title:
198 data->title = (char *)tag->ti_Data;
199 break;
203 return (IPTR) obj;
206 /**************************************************************************
207 OM_SET
208 **************************************************************************/
209 IPTR Menuitem__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
211 struct MUI_MenuitemData *data;
212 struct TagItem *tags, *tag;
214 data = INST_DATA(cl, obj);
216 BOOL rebuild = FALSE;
218 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
220 switch (tag->ti_Tag)
222 case MUIA_Menuitem_Checked:
223 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_CHECKED);
224 if (data->exclude && (data->flags & MENUF_CHECKED))
226 Object *parent = NULL;
227 get(obj, MUIA_Parent, &parent);
229 if (parent)
231 Object *child;
232 Object *cstate;
233 struct MinList *ChildList = NULL;
234 ULONG i = 1;
236 get(parent, MUIA_Family_List, &ChildList);
237 cstate = (Object *) ChildList->mlh_Head;
238 while ((child = NextObject(&cstate)))
240 if ((i & data->exclude) && (child != obj))
242 IPTR checkit = 0, checked = 0;
244 get(child, MUIA_Menuitem_Checkit, &checkit);
245 get(child, MUIA_Menuitem_Checked, &checked);
247 if (checkit && checked)
249 set(child, MUIA_Menuitem_Checked, FALSE);
253 i <<= 1;
258 rebuild = TRUE;
259 break;
261 case MUIA_Menuitem_Checkit:
262 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_CHECKIT);
263 rebuild = TRUE;
264 break;
266 case MUIA_Menuitem_CommandString:
267 _handle_bool_tag(data->flags, tag->ti_Data,
268 MENUF_COMMANDSTRING);
269 rebuild = TRUE;
270 break;
272 case MUIA_Menu_Enabled:
273 case MUIA_Menuitem_Enabled:
274 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_ENABLED);
275 tag->ti_Tag = TAG_IGNORE;
276 rebuild = TRUE;
277 break;
279 case MUIA_Menuitem_Toggle:
280 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_TOGGLE);
281 rebuild = TRUE;
282 break;
284 case MUIA_Menuitem_Exclude:
285 data->exclude = tag->ti_Data;
286 rebuild = TRUE;
287 break;
289 case MUIA_Menuitem_Shortcut:
290 data->shortcut = (char *)tag->ti_Data;
291 rebuild = TRUE;
292 break;
294 case MUIA_Menu_Title:
295 case MUIA_Menuitem_Title:
296 data->title = (char *)tag->ti_Data;
297 tag->ti_Tag = TAG_IGNORE;
298 rebuild = TRUE;
299 break;
301 case MUIA_Menuitem_Trigger:
302 data->trigger = (struct MenuItem *)tag->ti_Data;
303 rebuild = TRUE;
304 break;
308 if (rebuild)
310 if (muiNotifyData(obj) &&
311 muiNotifyData(obj)->mnd_GlobalInfo &&
312 muiNotifyData(obj)->mnd_GlobalInfo->mgi_ApplicationObject)
314 DoMethod(_app(obj), MUIM_Application_UpdateMenus);
318 return DoSuperMethodA(cl, obj, (Msg) msg);
321 /**************************************************************************
322 OM_GET
323 **************************************************************************/
324 #define STORE *(msg->opg_Storage)
325 IPTR Menuitem__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
327 struct MUI_MenuitemData *data = INST_DATA(cl, obj);
329 switch (msg->opg_AttrID)
331 case MUIA_Menuitem_Checked:
332 STORE = ((data->flags & MENUF_CHECKED) != 0);
333 return 1;
335 case MUIA_Menuitem_Checkit:
336 STORE = ((data->flags & MENUF_CHECKIT) != 0);
337 return 1;
339 case MUIA_Menuitem_CommandString:
340 STORE = ((data->flags & MENUF_COMMANDSTRING) != 0);
341 return 1;
343 case MUIA_Menu_Enabled:
344 case MUIA_Menuitem_Enabled:
345 STORE = ((data->flags & MENUF_ENABLED) != 0);
346 return 1;
348 case MUIA_Menuitem_Toggle:
349 STORE = ((data->flags & MENUF_TOGGLE) != 0);
350 return 1;
352 case MUIA_Menuitem_Exclude:
353 STORE = data->exclude;
354 return 1;
356 case MUIA_Menuitem_Shortcut:
357 STORE = (IPTR) data->shortcut;
358 return 1;
360 case MUIA_Menu_Title:
361 case MUIA_Menuitem_Title:
362 STORE = (IPTR) data->title;
363 return 1;
365 case MUIA_Menuitem_NewMenu:
366 Menuitem_BuildNewMenu(data, obj);
367 STORE = (IPTR) data->newmenu;
368 return 1;
370 case MUIA_Menuitem_Trigger:
371 STORE = (IPTR) data->trigger;
372 return 1;
375 return DoSuperMethodA(cl, obj, (Msg) msg);
377 #undef STORE
380 /**************************************************************************
381 OM_DISPOSE
382 **************************************************************************/
383 IPTR Menuitem__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
385 struct MUI_MenuitemData *data = INST_DATA(cl, obj);
387 FreeVec(data->newmenu);
389 return DoSuperMethodA(cl, obj, msg);
393 /**************************************************************************
394 MUIM_ConnectParent
395 **************************************************************************/
396 IPTR Menuitem__MUIM_ConnectParent(struct IClass *cl, Object *obj,
397 struct MUIP_ConnectParent *msg)
399 Object *cstate;
400 Object *child;
401 struct MinList *ChildList = NULL;
403 D(bug("Menuitem_ConnectParent(%p) %s\n", obj, OCLASS(obj)->cl_ID));
405 DoSuperMethodA(cl, obj, (Msg) msg);
407 muiNotifyData(obj)->mnd_ParentObject = msg->parent;
409 get(obj, MUIA_Family_List, &ChildList);
410 cstate = (Object *) ChildList->mlh_Head;
411 while ((child = NextObject(&cstate)))
413 DoMethod(child, MUIM_ConnectParent, (IPTR) obj);
415 return TRUE;
418 /**************************************************************************
419 MUIM_DisconnectParent
420 **************************************************************************/
421 IPTR Menuitem__MUIM_DisconnectParent(struct IClass *cl, Object *obj,
422 struct MUIP_ConnectParent *msg)
424 Object *cstate;
425 Object *child;
426 struct MinList *ChildList = NULL;
428 D(bug("Menuitem_DisconnectParent(%p) %s\n", obj, OCLASS(obj)->cl_ID));
430 get(obj, MUIA_Family_List, &ChildList);
431 cstate = (Object *) ChildList->mlh_Head;
432 while ((child = NextObject(&cstate)))
434 DoMethodA(child, (Msg) msg);
436 muiNotifyData(obj)->mnd_ParentObject = NULL;
437 DoSuperMethodA(cl, obj, (Msg) msg);
438 return TRUE;
441 /**************************************************************************
442 MUIM_Family_Insert, MUIM_Family_Remove
443 **************************************************************************/
444 IPTR Menuitem__MUIM_Update(struct IClass *cl, Object *obj, Msg msg)
446 // struct MUI_MenuitemData *data = INST_DATA(cl, obj);
448 IPTR retval = DoSuperMethodA(cl, obj, msg);
450 if (muiNotifyData(obj) &&
451 muiNotifyData(obj)->mnd_GlobalInfo &&
452 muiNotifyData(obj)->mnd_GlobalInfo->mgi_ApplicationObject)
454 DoMethod(_app(obj), MUIM_Application_UpdateMenus);
457 return retval;
461 BOOPSI_DISPATCHER(IPTR, Menuitem_Dispatcher, cl, obj, msg)
463 switch (msg->MethodID)
465 case OM_NEW:
466 return Menuitem__OM_NEW(cl, obj, (struct opSet *)msg);
467 case OM_DISPOSE:
468 return Menuitem__OM_DISPOSE(cl, obj, msg);
469 case OM_SET:
470 return Menuitem__OM_SET(cl, obj, (struct opSet *)msg);
471 case OM_GET:
472 return Menuitem__OM_GET(cl, obj, (struct opGet *)msg);
473 case MUIM_ConnectParent:
474 return Menuitem__MUIM_ConnectParent(cl, obj, (APTR) msg);
475 case MUIM_DisconnectParent:
476 return Menuitem__MUIM_DisconnectParent(cl, obj, (APTR) msg);
477 case MUIM_Family_Insert:
478 return Menuitem__MUIM_Update(cl, obj, (APTR) msg);
479 case MUIM_Family_Remove:
480 return Menuitem__MUIM_Update(cl, obj, (APTR) msg);
481 case MUIM_Family_AddTail:
482 return Menuitem__MUIM_Update(cl, obj, (APTR) msg);
483 case MUIM_Family_AddHead:
484 return Menuitem__MUIM_Update(cl, obj, (APTR) msg);
485 case OM_ADDMEMBER:
486 return Menuitem__MUIM_Update(cl, obj, (APTR) msg);
487 case OM_REMMEMBER:
488 return Menuitem__MUIM_Update(cl, obj, (APTR) msg);
490 return DoSuperMethodA(cl, obj, msg);
492 BOOPSI_DISPATCHER_END
495 * Class descriptor.
497 const struct __MUIBuiltinClass _MUI_Menuitem_desc =
499 MUIC_Menuitem,
500 MUIC_Family,
501 sizeof(struct MUI_MenuitemData),
502 (void *) Menuitem_Dispatcher
506 * Class descriptor.- this class is the same like menuitem
508 const struct __MUIBuiltinClass _MUI_Menu_desc =
510 MUIC_Menu,
511 MUIC_Family,
512 sizeof(struct MUI_MenuitemData),
513 (void *) Menuitem_Dispatcher
517 * Class descriptor.- this class is the same like menuitem
519 const struct __MUIBuiltinClass _MUI_Menustrip_desc =
521 MUIC_Menustrip,
522 MUIC_Family,
523 sizeof(struct MUI_MenuitemData),
524 (void *) Menuitem_Dispatcher