muimaster.library: be able to internally distinguish menu, menustrip and menuitem
[AROS.git] / workbench / libs / muimaster / classes / menuitem.c
bloba2c449ab9ba2beeb0ca1816257eae40e48c69548
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 #define MENUF_MENUSTRIP (1<<15)
31 #define MENUF_MENU (1<<16)
32 #define MENUF_MENUITEM (1<<17)
34 #define MUIA_Menuitem_Type (MUIB_Menuitem | 0x00000001)
36 #define MUIV_Menuitem_Type_Menustrip (-1)
37 #define MUIV_Menuitem_Type_Menu (-2)
38 #define MUIV_Menuitem_Type_Menuitem (-3)
40 struct MUI_MenuitemData
42 ULONG flags;
43 ULONG exclude;
45 char *shortcut;
46 char *title;
48 struct NewMenu *newmenu;
50 struct MenuItem *trigger;
53 static int Menuitem_GetTotalChildren(Object *obj)
55 Object *cstate;
56 Object *child;
57 struct MinList *ChildList = NULL;
58 int num = 0;
60 get(obj, MUIA_Family_List, &ChildList);
61 cstate = (Object *) ChildList->mlh_Head;
62 while ((child = NextObject(&cstate)))
64 num++;
65 num += Menuitem_GetTotalChildren(child);
67 return num;
70 static int Menuitem_FillNewMenu(Object *obj, struct NewMenu *menu,
71 int depth)
73 Object *cstate;
74 Object *child;
75 struct MinList *ChildList = NULL;
76 int num = 0;
78 if (depth > 2)
79 return 0;
81 get(obj, MUIA_Family_List, &ChildList);
82 cstate = (Object *) ChildList->mlh_Head;
83 while ((child = NextObject(&cstate)))
85 int entries;
86 ULONG checkit = 0, checked = 0, toggle = 0, enabled = 0;
88 get(child, MUIA_Menuitem_Title, &menu->nm_Label);
89 get(child, MUIA_Menuitem_Shortcut, &menu->nm_CommKey);
90 get(child, MUIA_Menuitem_Checkit, &checkit);
91 get(child, MUIA_Menuitem_Checked, &checked);
92 get(child, MUIA_Menuitem_Toggle, &toggle);
93 get(child, MUIA_Menuitem_Enabled, &enabled);
94 if (checkit)
95 menu->nm_Flags |= CHECKIT;
96 if (checked)
97 menu->nm_Flags |= CHECKED;
98 if (toggle)
99 menu->nm_Flags |= MENUTOGGLE;
100 get(child, MUIA_Menuitem_Exclude, &menu->nm_MutualExclude);
102 if (depth == 0)
104 menu->nm_Type = NM_TITLE;
105 if (!enabled)
106 menu->nm_Flags |= NM_MENUDISABLED;
108 else if (depth == 1)
110 menu->nm_Type = NM_ITEM;
111 if (!enabled)
112 menu->nm_Flags |= NM_ITEMDISABLED;
114 else if (depth == 2)
116 menu->nm_Type = NM_SUB;
117 if (!enabled)
118 menu->nm_Flags |= NM_ITEMDISABLED;
121 menu->nm_UserData = child;
123 menu++;
124 num++;
125 entries = Menuitem_FillNewMenu(child, menu, depth + 1);
127 menu += entries;
128 num += entries;
130 return num;
133 /**************************************************************************
135 **************************************************************************/
136 static struct NewMenu *Menuitem_BuildNewMenu(struct MUI_MenuitemData *data,
137 Object *obj)
139 int entries = Menuitem_GetTotalChildren(obj);
140 if (data->newmenu)
141 FreeVec(data->newmenu);
142 data->newmenu = NULL;
143 if (!entries)
144 return NULL;
146 if ((data->newmenu =
147 (struct NewMenu *)AllocVec((entries +
148 1) * sizeof(struct NewMenu), MEMF_CLEAR)))
150 Menuitem_FillNewMenu(obj, data->newmenu, 0);
152 return data->newmenu;
155 /**************************************************************************
156 OM_NEW
157 **************************************************************************/
158 IPTR Common__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
160 struct MUI_MenuitemData *data;
161 struct TagItem *tags, *tag;
163 obj = (Object *) DoSuperMethodA(cl, obj, (Msg) msg);
164 /* We need no tags */
165 if (!obj)
166 return 0;
168 data = INST_DATA(cl, obj);
170 data->flags = MENUF_ENABLED;
172 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
174 switch (tag->ti_Tag)
176 case MUIA_Menuitem_Checked:
177 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_CHECKED);
178 break;
180 case MUIA_Menuitem_Checkit:
181 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_CHECKIT);
182 break;
184 case MUIA_Menuitem_CommandString:
185 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_COMMANDSTRING);
186 break;
188 case MUIA_Menu_Enabled:
189 case MUIA_Menuitem_Enabled:
190 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_ENABLED);
191 break;
193 case MUIA_Menuitem_Toggle:
194 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_TOGGLE);
195 break;
197 case MUIA_Menuitem_Exclude:
198 data->exclude = tag->ti_Data;
199 break;
201 case MUIA_Menuitem_Shortcut:
202 data->shortcut = (char *)tag->ti_Data;
203 break;
205 case MUIA_Menu_Title:
206 case MUIA_Menuitem_Title:
207 data->title = (char *)tag->ti_Data;
208 break;
212 return (IPTR) obj;
215 IPTR Menuitem__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
217 struct MUI_MenuitemData *data;
218 obj = (Object *) Common__OM_NEW(cl, obj, msg);
219 data = INST_DATA(cl, obj);
221 data->flags |= MENUF_MENUITEM;
223 return (IPTR) obj;
226 IPTR Menu__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
228 struct MUI_MenuitemData *data;
229 obj = (Object *) Common__OM_NEW(cl, obj, msg);
230 data = INST_DATA(cl, obj);
232 data->flags |= MENUF_MENU;
234 return (IPTR) obj;
237 IPTR Menustrip__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
239 struct MUI_MenuitemData *data;
240 obj = (Object *) Common__OM_NEW(cl, obj, msg);
241 data = INST_DATA(cl, obj);
243 data->flags |= MENUF_MENUSTRIP;
245 return (IPTR) obj;
248 /**************************************************************************
249 OM_SET
250 **************************************************************************/
251 IPTR Menuitem__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
253 struct MUI_MenuitemData *data;
254 struct TagItem *tags, *tag;
256 data = INST_DATA(cl, obj);
258 BOOL rebuild = FALSE;
260 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
262 switch (tag->ti_Tag)
264 case MUIA_Menuitem_Checked:
265 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_CHECKED);
266 if (data->exclude && (data->flags & MENUF_CHECKED))
268 Object *parent = NULL;
269 get(obj, MUIA_Parent, &parent);
271 if (parent)
273 Object *child;
274 Object *cstate;
275 struct MinList *ChildList = NULL;
276 ULONG i = 1;
278 get(parent, MUIA_Family_List, &ChildList);
279 cstate = (Object *) ChildList->mlh_Head;
280 while ((child = NextObject(&cstate)))
282 if ((i & data->exclude) && (child != obj))
284 IPTR checkit = 0, checked = 0;
286 get(child, MUIA_Menuitem_Checkit, &checkit);
287 get(child, MUIA_Menuitem_Checked, &checked);
289 if (checkit && checked)
291 set(child, MUIA_Menuitem_Checked, FALSE);
295 i <<= 1;
300 rebuild = TRUE;
301 break;
303 case MUIA_Menuitem_Checkit:
304 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_CHECKIT);
305 rebuild = TRUE;
306 break;
308 case MUIA_Menuitem_CommandString:
309 _handle_bool_tag(data->flags, tag->ti_Data,
310 MENUF_COMMANDSTRING);
311 rebuild = TRUE;
312 break;
314 case MUIA_Menu_Enabled:
315 case MUIA_Menuitem_Enabled:
316 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_ENABLED);
317 tag->ti_Tag = TAG_IGNORE;
318 rebuild = TRUE;
319 break;
321 case MUIA_Menuitem_Toggle:
322 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_TOGGLE);
323 rebuild = TRUE;
324 break;
326 case MUIA_Menuitem_Exclude:
327 data->exclude = tag->ti_Data;
328 rebuild = TRUE;
329 break;
331 case MUIA_Menuitem_Shortcut:
332 data->shortcut = (char *)tag->ti_Data;
333 rebuild = TRUE;
334 break;
336 case MUIA_Menu_Title:
337 case MUIA_Menuitem_Title:
338 data->title = (char *)tag->ti_Data;
339 tag->ti_Tag = TAG_IGNORE;
340 rebuild = TRUE;
341 break;
343 case MUIA_Menuitem_Trigger:
344 data->trigger = (struct MenuItem *)tag->ti_Data;
345 rebuild = TRUE;
346 break;
350 if (rebuild)
352 if (muiNotifyData(obj) &&
353 muiNotifyData(obj)->mnd_GlobalInfo &&
354 muiNotifyData(obj)->mnd_GlobalInfo->mgi_ApplicationObject)
356 DoMethod(_app(obj), MUIM_Application_UpdateMenus);
360 return DoSuperMethodA(cl, obj, (Msg) msg);
363 /**************************************************************************
364 OM_GET
365 **************************************************************************/
366 #define STORE *(msg->opg_Storage)
367 IPTR Menuitem__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
369 struct MUI_MenuitemData *data = INST_DATA(cl, obj);
371 switch (msg->opg_AttrID)
373 case MUIA_Menuitem_Checked:
374 STORE = ((data->flags & MENUF_CHECKED) != 0);
375 return 1;
377 case MUIA_Menuitem_Checkit:
378 STORE = ((data->flags & MENUF_CHECKIT) != 0);
379 return 1;
381 case MUIA_Menuitem_CommandString:
382 STORE = ((data->flags & MENUF_COMMANDSTRING) != 0);
383 return 1;
385 case MUIA_Menu_Enabled:
386 case MUIA_Menuitem_Enabled:
387 STORE = ((data->flags & MENUF_ENABLED) != 0);
388 return 1;
390 case MUIA_Menuitem_Toggle:
391 STORE = ((data->flags & MENUF_TOGGLE) != 0);
392 return 1;
394 case MUIA_Menuitem_Exclude:
395 STORE = data->exclude;
396 return 1;
398 case MUIA_Menuitem_Shortcut:
399 STORE = (IPTR) data->shortcut;
400 return 1;
402 case MUIA_Menu_Title:
403 case MUIA_Menuitem_Title:
404 STORE = (IPTR) data->title;
405 return 1;
407 case MUIA_Menuitem_NewMenu:
408 Menuitem_BuildNewMenu(data, obj);
409 STORE = (IPTR) data->newmenu;
410 return 1;
412 case MUIA_Menuitem_Trigger:
413 STORE = (IPTR) data->trigger;
414 return 1;
416 case MUIA_Menuitem_Type:
417 if (data->flags & MENUF_MENUSTRIP)
418 STORE = (IPTR) MUIV_Menuitem_Type_Menustrip;
419 else if(data->flags & MENUF_MENU)
420 STORE = (IPTR) MUIV_Menuitem_Type_Menu;
421 else
422 STORE = (IPTR) MUIV_Menuitem_Type_Menuitem;
423 return 1;
427 return DoSuperMethodA(cl, obj, (Msg) msg);
429 #undef STORE
432 /**************************************************************************
433 OM_DISPOSE
434 **************************************************************************/
435 IPTR Menuitem__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
437 struct MUI_MenuitemData *data = INST_DATA(cl, obj);
439 FreeVec(data->newmenu);
441 return DoSuperMethodA(cl, obj, msg);
445 /**************************************************************************
446 MUIM_ConnectParent
447 **************************************************************************/
448 IPTR Menuitem__MUIM_ConnectParent(struct IClass *cl, Object *obj,
449 struct MUIP_ConnectParent *msg)
451 Object *cstate;
452 Object *child;
453 struct MinList *ChildList = NULL;
455 D(bug("Menuitem_ConnectParent(%p) %s\n", obj, OCLASS(obj)->cl_ID));
457 DoSuperMethodA(cl, obj, (Msg) msg);
459 muiNotifyData(obj)->mnd_ParentObject = msg->parent;
461 get(obj, MUIA_Family_List, &ChildList);
462 cstate = (Object *) ChildList->mlh_Head;
463 while ((child = NextObject(&cstate)))
465 DoMethod(child, MUIM_ConnectParent, (IPTR) obj);
467 return TRUE;
470 /**************************************************************************
471 MUIM_DisconnectParent
472 **************************************************************************/
473 IPTR Menuitem__MUIM_DisconnectParent(struct IClass *cl, Object *obj,
474 struct MUIP_ConnectParent *msg)
476 Object *cstate;
477 Object *child;
478 struct MinList *ChildList = NULL;
480 D(bug("Menuitem_DisconnectParent(%p) %s\n", obj, OCLASS(obj)->cl_ID));
482 get(obj, MUIA_Family_List, &ChildList);
483 cstate = (Object *) ChildList->mlh_Head;
484 while ((child = NextObject(&cstate)))
486 DoMethodA(child, (Msg) msg);
488 muiNotifyData(obj)->mnd_ParentObject = NULL;
489 DoSuperMethodA(cl, obj, (Msg) msg);
490 return TRUE;
493 /**************************************************************************
494 MUIM_Family_Insert, MUIM_Family_Remove
495 **************************************************************************/
496 IPTR Menuitem__MUIM_Update(struct IClass *cl, Object *obj, Msg msg)
498 // struct MUI_MenuitemData *data = INST_DATA(cl, obj);
500 IPTR retval = DoSuperMethodA(cl, obj, msg);
502 if (muiNotifyData(obj) &&
503 muiNotifyData(obj)->mnd_GlobalInfo &&
504 muiNotifyData(obj)->mnd_GlobalInfo->mgi_ApplicationObject)
506 DoMethod(_app(obj), MUIM_Application_UpdateMenus);
509 return retval;
512 IPTR Common_Dispatcher(Class *cl, Object *obj, Msg msg)
514 switch (msg->MethodID)
516 case OM_DISPOSE:
517 return Menuitem__OM_DISPOSE(cl, obj, msg);
518 case OM_SET:
519 return Menuitem__OM_SET(cl, obj, (struct opSet *)msg);
520 case OM_GET:
521 return Menuitem__OM_GET(cl, obj, (struct opGet *)msg);
522 case MUIM_ConnectParent:
523 return Menuitem__MUIM_ConnectParent(cl, obj, (APTR) msg);
524 case MUIM_DisconnectParent:
525 return Menuitem__MUIM_DisconnectParent(cl, obj, (APTR) msg);
526 case MUIM_Family_Insert:
527 return Menuitem__MUIM_Update(cl, obj, (APTR) msg);
528 case MUIM_Family_Remove:
529 return Menuitem__MUIM_Update(cl, obj, (APTR) msg);
530 case MUIM_Family_AddTail:
531 return Menuitem__MUIM_Update(cl, obj, (APTR) msg);
532 case MUIM_Family_AddHead:
533 return Menuitem__MUIM_Update(cl, obj, (APTR) msg);
534 case OM_ADDMEMBER:
535 return Menuitem__MUIM_Update(cl, obj, (APTR) msg);
536 case OM_REMMEMBER:
537 return Menuitem__MUIM_Update(cl, obj, (APTR) msg);
539 return DoSuperMethodA(cl, obj, msg);
542 BOOPSI_DISPATCHER(IPTR, Menuitem_Dispatcher, cl, obj, msg)
544 switch (msg->MethodID)
546 case OM_NEW:
547 return Menuitem__OM_NEW(cl, obj, (struct opSet *)msg);
550 return Common_Dispatcher(cl, obj, msg);
552 BOOPSI_DISPATCHER_END
554 BOOPSI_DISPATCHER(IPTR, Menu_Dispatcher, cl, obj, msg)
556 switch (msg->MethodID)
558 case OM_NEW:
559 return Menu__OM_NEW(cl, obj, (struct opSet *)msg);
562 return Common_Dispatcher(cl, obj, msg);
564 BOOPSI_DISPATCHER_END
566 BOOPSI_DISPATCHER(IPTR, Menustrip_Dispatcher, cl, obj, msg)
568 switch (msg->MethodID)
570 case OM_NEW:
571 return Menustrip__OM_NEW(cl, obj, (struct opSet *)msg);
574 return Common_Dispatcher(cl, obj, msg);
576 BOOPSI_DISPATCHER_END
578 * Class descriptor.
580 const struct __MUIBuiltinClass _MUI_Menuitem_desc =
582 MUIC_Menuitem,
583 MUIC_Family,
584 sizeof(struct MUI_MenuitemData),
585 (void *) Menuitem_Dispatcher
589 * Class descriptor.- this class is the same like menuitem
591 const struct __MUIBuiltinClass _MUI_Menu_desc =
593 MUIC_Menu,
594 MUIC_Family,
595 sizeof(struct MUI_MenuitemData),
596 (void *) Menu_Dispatcher
600 * Class descriptor.- this class is the same like menuitem
602 const struct __MUIBuiltinClass _MUI_Menustrip_desc =
604 MUIC_Menustrip,
605 MUIC_Family,
606 sizeof(struct MUI_MenuitemData),
607 (void *) Menustrip_Dispatcher