revert between 56095 -> 55830 in arch
[AROS.git] / workbench / libs / muimaster / classes / menuitem.c
blob5b18237b2a1fc108e388c467010cd873a2cb3e3b
1 /*
2 Copyright © 2002-2015, 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, cmdstring = 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 get(child, MUIA_Menuitem_CommandString, &cmdstring);
95 if (checkit)
96 menu->nm_Flags |= CHECKIT;
97 if (checked)
98 menu->nm_Flags |= CHECKED;
99 if (toggle)
100 menu->nm_Flags |= MENUTOGGLE;
101 if (cmdstring)
102 menu->nm_Flags |= COMMSEQ;
103 get(child, MUIA_Menuitem_Exclude, &menu->nm_MutualExclude);
105 if (depth == 0)
107 LONG type = 0;
108 get(child, MUIA_Menuitem_Type, &type);
110 if (type == MUIV_Menuitem_Type_Menuitem)
111 /* Depth 0 Menuitems are to become items of current menu,
112 * not menus. MUI behavior */
113 menu->nm_Type = NM_ITEM;
114 else
115 menu->nm_Type = NM_TITLE;
117 else if (depth == 1)
118 menu->nm_Type = NM_ITEM;
119 else if (depth == 2)
120 menu->nm_Type = NM_SUB;
122 if (!enabled)
124 if (menu->nm_Type == NM_TITLE)
125 menu->nm_Flags |= NM_MENUDISABLED;
126 else
127 menu->nm_Flags |= NM_ITEMDISABLED;
130 menu->nm_UserData = child;
132 menu++;
133 num++;
134 entries = Menuitem_FillNewMenu(child, menu, depth + 1);
136 menu += entries;
137 num += entries;
139 return num;
142 /**************************************************************************
144 **************************************************************************/
145 static struct NewMenu *Menuitem_BuildNewMenu(struct MUI_MenuitemData *data,
146 Object *obj)
148 int entries = Menuitem_GetTotalChildren(obj);
149 if (data->newmenu)
150 FreeVec(data->newmenu);
151 data->newmenu = NULL;
152 if (!entries)
153 return NULL;
155 if ((data->newmenu =
156 (struct NewMenu *)AllocVec((entries +
157 1) * sizeof(struct NewMenu), MEMF_CLEAR)))
159 Menuitem_FillNewMenu(obj, data->newmenu, 0);
161 return data->newmenu;
164 /**************************************************************************
165 OM_NEW
166 **************************************************************************/
167 IPTR Common__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
169 struct MUI_MenuitemData *data;
170 struct TagItem *tags, *tag;
172 obj = (Object *) DoSuperMethodA(cl, obj, (Msg) msg);
173 /* We need no tags */
174 if (!obj)
175 return 0;
177 data = INST_DATA(cl, obj);
179 data->flags = MENUF_ENABLED;
181 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
183 switch (tag->ti_Tag)
185 case MUIA_Menuitem_Checked:
186 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_CHECKED);
187 break;
189 case MUIA_Menuitem_Checkit:
190 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_CHECKIT);
191 break;
193 case MUIA_Menuitem_CommandString:
194 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_COMMANDSTRING);
195 break;
197 case MUIA_Menu_Enabled:
198 case MUIA_Menuitem_Enabled:
199 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_ENABLED);
200 break;
202 case MUIA_Menuitem_Toggle:
203 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_TOGGLE);
204 break;
206 case MUIA_Menuitem_Exclude:
207 data->exclude = tag->ti_Data;
208 break;
210 case MUIA_Menuitem_Shortcut:
211 data->shortcut = (char *)tag->ti_Data;
212 break;
214 case MUIA_Menu_Title:
215 case MUIA_Menuitem_Title:
216 data->title = (char *)tag->ti_Data;
217 break;
221 return (IPTR) obj;
224 IPTR Menuitem__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
226 struct MUI_MenuitemData *data;
227 obj = (Object *) Common__OM_NEW(cl, obj, msg);
228 data = INST_DATA(cl, obj);
230 data->flags |= MENUF_MENUITEM;
232 return (IPTR) obj;
235 IPTR Menu__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
237 struct MUI_MenuitemData *data;
238 obj = (Object *) Common__OM_NEW(cl, obj, msg);
239 data = INST_DATA(cl, obj);
241 data->flags |= MENUF_MENU;
243 return (IPTR) obj;
246 IPTR Menustrip__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
248 struct MUI_MenuitemData *data;
249 obj = (Object *) Common__OM_NEW(cl, obj, msg);
250 data = INST_DATA(cl, obj);
252 data->flags |= MENUF_MENUSTRIP;
254 return (IPTR) obj;
257 /**************************************************************************
258 OM_SET
259 **************************************************************************/
260 IPTR Menuitem__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
262 struct MUI_MenuitemData *data;
263 struct TagItem *tags, *tag;
265 data = INST_DATA(cl, obj);
267 BOOL rebuild = FALSE;
269 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
271 switch (tag->ti_Tag)
273 case MUIA_Menuitem_Checked:
274 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_CHECKED);
275 if (data->exclude && (data->flags & MENUF_CHECKED))
277 Object *parent = NULL;
278 get(obj, MUIA_Parent, &parent);
280 if (parent)
282 Object *child;
283 Object *cstate;
284 struct MinList *ChildList = NULL;
285 ULONG i = 1;
287 get(parent, MUIA_Family_List, &ChildList);
288 cstate = (Object *) ChildList->mlh_Head;
289 while ((child = NextObject(&cstate)))
291 if ((i & data->exclude) && (child != obj))
293 IPTR checkit = 0, checked = 0;
295 get(child, MUIA_Menuitem_Checkit, &checkit);
296 get(child, MUIA_Menuitem_Checked, &checked);
298 if (checkit && checked)
300 set(child, MUIA_Menuitem_Checked, FALSE);
304 i <<= 1;
309 rebuild = TRUE;
310 break;
312 case MUIA_Menuitem_Checkit:
313 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_CHECKIT);
314 rebuild = TRUE;
315 break;
317 case MUIA_Menuitem_CommandString:
318 _handle_bool_tag(data->flags, tag->ti_Data,
319 MENUF_COMMANDSTRING);
320 rebuild = TRUE;
321 break;
323 case MUIA_Menu_Enabled:
324 case MUIA_Menuitem_Enabled:
325 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_ENABLED);
326 tag->ti_Tag = TAG_IGNORE;
327 rebuild = TRUE;
328 break;
330 case MUIA_Menuitem_Toggle:
331 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_TOGGLE);
332 rebuild = TRUE;
333 break;
335 case MUIA_Menuitem_Exclude:
336 data->exclude = tag->ti_Data;
337 rebuild = TRUE;
338 break;
340 case MUIA_Menuitem_Shortcut:
341 data->shortcut = (char *)tag->ti_Data;
342 rebuild = TRUE;
343 break;
345 case MUIA_Menu_Title:
346 case MUIA_Menuitem_Title:
347 data->title = (char *)tag->ti_Data;
348 tag->ti_Tag = TAG_IGNORE;
349 rebuild = TRUE;
350 break;
352 case MUIA_Menuitem_Trigger:
353 data->trigger = (struct MenuItem *)tag->ti_Data;
354 rebuild = TRUE;
355 break;
359 if (rebuild)
361 if (muiNotifyData(obj) &&
362 muiNotifyData(obj)->mnd_GlobalInfo &&
363 muiNotifyData(obj)->mnd_GlobalInfo->mgi_ApplicationObject)
365 DoMethod(_app(obj), MUIM_Application_UpdateMenus);
369 return DoSuperMethodA(cl, obj, (Msg) msg);
372 /**************************************************************************
373 OM_GET
374 **************************************************************************/
375 #define STORE *(msg->opg_Storage)
376 IPTR Menuitem__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
378 struct MUI_MenuitemData *data = INST_DATA(cl, obj);
380 switch (msg->opg_AttrID)
382 case MUIA_Menuitem_Checked:
383 STORE = ((data->flags & MENUF_CHECKED) != 0);
384 return 1;
386 case MUIA_Menuitem_Checkit:
387 STORE = ((data->flags & MENUF_CHECKIT) != 0);
388 return 1;
390 case MUIA_Menuitem_CommandString:
391 STORE = ((data->flags & MENUF_COMMANDSTRING) != 0);
392 return 1;
394 case MUIA_Menu_Enabled:
395 case MUIA_Menuitem_Enabled:
396 STORE = ((data->flags & MENUF_ENABLED) != 0);
397 return 1;
399 case MUIA_Menuitem_Toggle:
400 STORE = ((data->flags & MENUF_TOGGLE) != 0);
401 return 1;
403 case MUIA_Menuitem_Exclude:
404 STORE = data->exclude;
405 return 1;
407 case MUIA_Menuitem_Shortcut:
408 STORE = (IPTR) data->shortcut;
409 return 1;
411 case MUIA_Menu_Title:
412 case MUIA_Menuitem_Title:
413 STORE = (IPTR) data->title;
414 return 1;
416 case MUIA_Menuitem_NewMenu:
417 Menuitem_BuildNewMenu(data, obj);
418 STORE = (IPTR) data->newmenu;
419 return 1;
421 case MUIA_Menuitem_Trigger:
422 STORE = (IPTR) data->trigger;
423 return 1;
425 case MUIA_Menuitem_Type:
426 if (data->flags & MENUF_MENUSTRIP)
427 STORE = (IPTR) MUIV_Menuitem_Type_Menustrip;
428 else if(data->flags & MENUF_MENU)
429 STORE = (IPTR) MUIV_Menuitem_Type_Menu;
430 else
431 STORE = (IPTR) MUIV_Menuitem_Type_Menuitem;
432 return 1;
436 return DoSuperMethodA(cl, obj, (Msg) msg);
438 #undef STORE
441 /**************************************************************************
442 OM_DISPOSE
443 **************************************************************************/
444 IPTR Menuitem__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
446 struct MUI_MenuitemData *data = INST_DATA(cl, obj);
448 FreeVec(data->newmenu);
450 return DoSuperMethodA(cl, obj, msg);
454 /**************************************************************************
455 MUIM_ConnectParent
456 **************************************************************************/
457 IPTR Menuitem__MUIM_ConnectParent(struct IClass *cl, Object *obj,
458 struct MUIP_ConnectParent *msg)
460 Object *cstate;
461 Object *child;
462 struct MinList *ChildList = NULL;
464 D(bug("Menuitem_ConnectParent(%p) %s\n", obj, OCLASS(obj)->cl_ID));
466 DoSuperMethodA(cl, obj, (Msg) msg);
468 muiNotifyData(obj)->mnd_ParentObject = msg->parent;
470 get(obj, MUIA_Family_List, &ChildList);
471 cstate = (Object *) ChildList->mlh_Head;
472 while ((child = NextObject(&cstate)))
474 DoMethod(child, MUIM_ConnectParent, (IPTR) obj);
476 return TRUE;
479 /**************************************************************************
480 MUIM_DisconnectParent
481 **************************************************************************/
482 IPTR Menuitem__MUIM_DisconnectParent(struct IClass *cl, Object *obj,
483 struct MUIP_ConnectParent *msg)
485 Object *cstate;
486 Object *child;
487 struct MinList *ChildList = NULL;
489 D(bug("Menuitem_DisconnectParent(%p) %s\n", obj, OCLASS(obj)->cl_ID));
491 get(obj, MUIA_Family_List, &ChildList);
492 cstate = (Object *) ChildList->mlh_Head;
493 while ((child = NextObject(&cstate)))
495 DoMethodA(child, (Msg) msg);
497 muiNotifyData(obj)->mnd_ParentObject = NULL;
498 DoSuperMethodA(cl, obj, (Msg) msg);
499 return TRUE;
502 /**************************************************************************
503 MUIM_Family_Insert, MUIM_Family_Remove
504 **************************************************************************/
505 IPTR Menuitem__MUIM_Update(struct IClass *cl, Object *obj, Msg msg)
507 // struct MUI_MenuitemData *data = INST_DATA(cl, obj);
509 IPTR retval = DoSuperMethodA(cl, obj, msg);
511 if (muiNotifyData(obj) &&
512 muiNotifyData(obj)->mnd_GlobalInfo &&
513 muiNotifyData(obj)->mnd_GlobalInfo->mgi_ApplicationObject)
515 DoMethod(_app(obj), MUIM_Application_UpdateMenus);
518 return retval;
521 IPTR Common_Dispatcher(Class *cl, Object *obj, Msg msg)
523 switch (msg->MethodID)
525 case OM_DISPOSE:
526 return Menuitem__OM_DISPOSE(cl, obj, msg);
527 case OM_SET:
528 return Menuitem__OM_SET(cl, obj, (struct opSet *)msg);
529 case OM_GET:
530 return Menuitem__OM_GET(cl, obj, (struct opGet *)msg);
531 case MUIM_ConnectParent:
532 return Menuitem__MUIM_ConnectParent(cl, obj, (APTR) msg);
533 case MUIM_DisconnectParent:
534 return Menuitem__MUIM_DisconnectParent(cl, obj, (APTR) msg);
535 case MUIM_Family_Insert:
536 return Menuitem__MUIM_Update(cl, obj, (APTR) msg);
537 case MUIM_Family_Remove:
538 return Menuitem__MUIM_Update(cl, obj, (APTR) msg);
539 case MUIM_Family_AddTail:
540 return Menuitem__MUIM_Update(cl, obj, (APTR) msg);
541 case MUIM_Family_AddHead:
542 return Menuitem__MUIM_Update(cl, obj, (APTR) msg);
543 case OM_ADDMEMBER:
544 return Menuitem__MUIM_Update(cl, obj, (APTR) msg);
545 case OM_REMMEMBER:
546 return Menuitem__MUIM_Update(cl, obj, (APTR) msg);
548 return DoSuperMethodA(cl, obj, msg);
551 BOOPSI_DISPATCHER(IPTR, Menuitem_Dispatcher, cl, obj, msg)
553 switch (msg->MethodID)
555 case OM_NEW:
556 return Menuitem__OM_NEW(cl, obj, (struct opSet *)msg);
559 return Common_Dispatcher(cl, obj, msg);
561 BOOPSI_DISPATCHER_END
563 BOOPSI_DISPATCHER(IPTR, Menu_Dispatcher, cl, obj, msg)
565 switch (msg->MethodID)
567 case OM_NEW:
568 return Menu__OM_NEW(cl, obj, (struct opSet *)msg);
571 return Common_Dispatcher(cl, obj, msg);
573 BOOPSI_DISPATCHER_END
575 BOOPSI_DISPATCHER(IPTR, Menustrip_Dispatcher, cl, obj, msg)
577 switch (msg->MethodID)
579 case OM_NEW:
580 return Menustrip__OM_NEW(cl, obj, (struct opSet *)msg);
583 return Common_Dispatcher(cl, obj, msg);
585 BOOPSI_DISPATCHER_END
587 * Class descriptor.
589 const struct __MUIBuiltinClass _MUI_Menuitem_desc =
591 MUIC_Menuitem,
592 MUIC_Family,
593 sizeof(struct MUI_MenuitemData),
594 (void *) Menuitem_Dispatcher
598 * Class descriptor.- this class is the same like menuitem
600 const struct __MUIBuiltinClass _MUI_Menu_desc =
602 MUIC_Menu,
603 MUIC_Family,
604 sizeof(struct MUI_MenuitemData),
605 (void *) Menu_Dispatcher
609 * Class descriptor.- this class is the same like menuitem
611 const struct __MUIBuiltinClass _MUI_Menustrip_desc =
613 MUIC_Menustrip,
614 MUIC_Family,
615 sizeof(struct MUI_MenuitemData),
616 (void *) Menustrip_Dispatcher