2 Copyright © 2002-2015, The AROS Development Team. All rights reserved.
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 */
19 #include "muimaster_intern.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
48 struct NewMenu
*newmenu
;
50 struct MenuItem
*trigger
;
53 static int Menuitem_GetTotalChildren(Object
*obj
)
57 struct MinList
*ChildList
= NULL
;
60 get(obj
, MUIA_Family_List
, &ChildList
);
61 cstate
= (Object
*) ChildList
->mlh_Head
;
62 while ((child
= NextObject(&cstate
)))
65 num
+= Menuitem_GetTotalChildren(child
);
70 static int Menuitem_FillNewMenu(Object
*obj
, struct NewMenu
*menu
,
75 struct MinList
*ChildList
= NULL
;
81 get(obj
, MUIA_Family_List
, &ChildList
);
82 cstate
= (Object
*) ChildList
->mlh_Head
;
83 while ((child
= NextObject(&cstate
)))
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
);
95 menu
->nm_Flags
|= CHECKIT
;
97 menu
->nm_Flags
|= CHECKED
;
99 menu
->nm_Flags
|= MENUTOGGLE
;
100 get(child
, MUIA_Menuitem_Exclude
, &menu
->nm_MutualExclude
);
105 get(child
, MUIA_Menuitem_Type
, &type
);
107 if (type
== MUIV_Menuitem_Type_Menuitem
)
108 /* Depth 0 Menuitems are to become items of current menu,
109 * not menus. MUI behavior */
110 menu
->nm_Type
= NM_ITEM
;
112 menu
->nm_Type
= NM_TITLE
;
115 menu
->nm_Type
= NM_ITEM
;
117 menu
->nm_Type
= NM_SUB
;
121 if (menu
->nm_Type
== NM_TITLE
)
122 menu
->nm_Flags
|= NM_MENUDISABLED
;
124 menu
->nm_Flags
|= NM_ITEMDISABLED
;
127 menu
->nm_UserData
= child
;
131 entries
= Menuitem_FillNewMenu(child
, menu
, depth
+ 1);
139 /**************************************************************************
141 **************************************************************************/
142 static struct NewMenu
*Menuitem_BuildNewMenu(struct MUI_MenuitemData
*data
,
145 int entries
= Menuitem_GetTotalChildren(obj
);
147 FreeVec(data
->newmenu
);
148 data
->newmenu
= NULL
;
153 (struct NewMenu
*)AllocVec((entries
+
154 1) * sizeof(struct NewMenu
), MEMF_CLEAR
)))
156 Menuitem_FillNewMenu(obj
, data
->newmenu
, 0);
158 return data
->newmenu
;
161 /**************************************************************************
163 **************************************************************************/
164 IPTR
Common__OM_NEW(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
166 struct MUI_MenuitemData
*data
;
167 struct TagItem
*tags
, *tag
;
169 obj
= (Object
*) DoSuperMethodA(cl
, obj
, (Msg
) msg
);
170 /* We need no tags */
174 data
= INST_DATA(cl
, obj
);
176 data
->flags
= MENUF_ENABLED
;
178 for (tags
= msg
->ops_AttrList
; (tag
= NextTagItem(&tags
));)
182 case MUIA_Menuitem_Checked
:
183 _handle_bool_tag(data
->flags
, tag
->ti_Data
, MENUF_CHECKED
);
186 case MUIA_Menuitem_Checkit
:
187 _handle_bool_tag(data
->flags
, tag
->ti_Data
, MENUF_CHECKIT
);
190 case MUIA_Menuitem_CommandString
:
191 _handle_bool_tag(data
->flags
, tag
->ti_Data
, MENUF_COMMANDSTRING
);
194 case MUIA_Menu_Enabled
:
195 case MUIA_Menuitem_Enabled
:
196 _handle_bool_tag(data
->flags
, tag
->ti_Data
, MENUF_ENABLED
);
199 case MUIA_Menuitem_Toggle
:
200 _handle_bool_tag(data
->flags
, tag
->ti_Data
, MENUF_TOGGLE
);
203 case MUIA_Menuitem_Exclude
:
204 data
->exclude
= tag
->ti_Data
;
207 case MUIA_Menuitem_Shortcut
:
208 data
->shortcut
= (char *)tag
->ti_Data
;
211 case MUIA_Menu_Title
:
212 case MUIA_Menuitem_Title
:
213 data
->title
= (char *)tag
->ti_Data
;
221 IPTR
Menuitem__OM_NEW(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
223 struct MUI_MenuitemData
*data
;
224 obj
= (Object
*) Common__OM_NEW(cl
, obj
, msg
);
225 data
= INST_DATA(cl
, obj
);
227 data
->flags
|= MENUF_MENUITEM
;
232 IPTR
Menu__OM_NEW(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
234 struct MUI_MenuitemData
*data
;
235 obj
= (Object
*) Common__OM_NEW(cl
, obj
, msg
);
236 data
= INST_DATA(cl
, obj
);
238 data
->flags
|= MENUF_MENU
;
243 IPTR
Menustrip__OM_NEW(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
245 struct MUI_MenuitemData
*data
;
246 obj
= (Object
*) Common__OM_NEW(cl
, obj
, msg
);
247 data
= INST_DATA(cl
, obj
);
249 data
->flags
|= MENUF_MENUSTRIP
;
254 /**************************************************************************
256 **************************************************************************/
257 IPTR
Menuitem__OM_SET(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
259 struct MUI_MenuitemData
*data
;
260 struct TagItem
*tags
, *tag
;
262 data
= INST_DATA(cl
, obj
);
264 BOOL rebuild
= FALSE
;
266 for (tags
= msg
->ops_AttrList
; (tag
= NextTagItem(&tags
));)
270 case MUIA_Menuitem_Checked
:
271 _handle_bool_tag(data
->flags
, tag
->ti_Data
, MENUF_CHECKED
);
272 if (data
->exclude
&& (data
->flags
& MENUF_CHECKED
))
274 Object
*parent
= NULL
;
275 get(obj
, MUIA_Parent
, &parent
);
281 struct MinList
*ChildList
= NULL
;
284 get(parent
, MUIA_Family_List
, &ChildList
);
285 cstate
= (Object
*) ChildList
->mlh_Head
;
286 while ((child
= NextObject(&cstate
)))
288 if ((i
& data
->exclude
) && (child
!= obj
))
290 IPTR checkit
= 0, checked
= 0;
292 get(child
, MUIA_Menuitem_Checkit
, &checkit
);
293 get(child
, MUIA_Menuitem_Checked
, &checked
);
295 if (checkit
&& checked
)
297 set(child
, MUIA_Menuitem_Checked
, FALSE
);
309 case MUIA_Menuitem_Checkit
:
310 _handle_bool_tag(data
->flags
, tag
->ti_Data
, MENUF_CHECKIT
);
314 case MUIA_Menuitem_CommandString
:
315 _handle_bool_tag(data
->flags
, tag
->ti_Data
,
316 MENUF_COMMANDSTRING
);
320 case MUIA_Menu_Enabled
:
321 case MUIA_Menuitem_Enabled
:
322 _handle_bool_tag(data
->flags
, tag
->ti_Data
, MENUF_ENABLED
);
323 tag
->ti_Tag
= TAG_IGNORE
;
327 case MUIA_Menuitem_Toggle
:
328 _handle_bool_tag(data
->flags
, tag
->ti_Data
, MENUF_TOGGLE
);
332 case MUIA_Menuitem_Exclude
:
333 data
->exclude
= tag
->ti_Data
;
337 case MUIA_Menuitem_Shortcut
:
338 data
->shortcut
= (char *)tag
->ti_Data
;
342 case MUIA_Menu_Title
:
343 case MUIA_Menuitem_Title
:
344 data
->title
= (char *)tag
->ti_Data
;
345 tag
->ti_Tag
= TAG_IGNORE
;
349 case MUIA_Menuitem_Trigger
:
350 data
->trigger
= (struct MenuItem
*)tag
->ti_Data
;
358 if (muiNotifyData(obj
) &&
359 muiNotifyData(obj
)->mnd_GlobalInfo
&&
360 muiNotifyData(obj
)->mnd_GlobalInfo
->mgi_ApplicationObject
)
362 DoMethod(_app(obj
), MUIM_Application_UpdateMenus
);
366 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
369 /**************************************************************************
371 **************************************************************************/
372 #define STORE *(msg->opg_Storage)
373 IPTR
Menuitem__OM_GET(struct IClass
*cl
, Object
*obj
, struct opGet
*msg
)
375 struct MUI_MenuitemData
*data
= INST_DATA(cl
, obj
);
377 switch (msg
->opg_AttrID
)
379 case MUIA_Menuitem_Checked
:
380 STORE
= ((data
->flags
& MENUF_CHECKED
) != 0);
383 case MUIA_Menuitem_Checkit
:
384 STORE
= ((data
->flags
& MENUF_CHECKIT
) != 0);
387 case MUIA_Menuitem_CommandString
:
388 STORE
= ((data
->flags
& MENUF_COMMANDSTRING
) != 0);
391 case MUIA_Menu_Enabled
:
392 case MUIA_Menuitem_Enabled
:
393 STORE
= ((data
->flags
& MENUF_ENABLED
) != 0);
396 case MUIA_Menuitem_Toggle
:
397 STORE
= ((data
->flags
& MENUF_TOGGLE
) != 0);
400 case MUIA_Menuitem_Exclude
:
401 STORE
= data
->exclude
;
404 case MUIA_Menuitem_Shortcut
:
405 STORE
= (IPTR
) data
->shortcut
;
408 case MUIA_Menu_Title
:
409 case MUIA_Menuitem_Title
:
410 STORE
= (IPTR
) data
->title
;
413 case MUIA_Menuitem_NewMenu
:
414 Menuitem_BuildNewMenu(data
, obj
);
415 STORE
= (IPTR
) data
->newmenu
;
418 case MUIA_Menuitem_Trigger
:
419 STORE
= (IPTR
) data
->trigger
;
422 case MUIA_Menuitem_Type
:
423 if (data
->flags
& MENUF_MENUSTRIP
)
424 STORE
= (IPTR
) MUIV_Menuitem_Type_Menustrip
;
425 else if(data
->flags
& MENUF_MENU
)
426 STORE
= (IPTR
) MUIV_Menuitem_Type_Menu
;
428 STORE
= (IPTR
) MUIV_Menuitem_Type_Menuitem
;
433 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
438 /**************************************************************************
440 **************************************************************************/
441 IPTR
Menuitem__OM_DISPOSE(struct IClass
*cl
, Object
*obj
, Msg msg
)
443 struct MUI_MenuitemData
*data
= INST_DATA(cl
, obj
);
445 FreeVec(data
->newmenu
);
447 return DoSuperMethodA(cl
, obj
, msg
);
451 /**************************************************************************
453 **************************************************************************/
454 IPTR
Menuitem__MUIM_ConnectParent(struct IClass
*cl
, Object
*obj
,
455 struct MUIP_ConnectParent
*msg
)
459 struct MinList
*ChildList
= NULL
;
461 D(bug("Menuitem_ConnectParent(%p) %s\n", obj
, OCLASS(obj
)->cl_ID
));
463 DoSuperMethodA(cl
, obj
, (Msg
) msg
);
465 muiNotifyData(obj
)->mnd_ParentObject
= msg
->parent
;
467 get(obj
, MUIA_Family_List
, &ChildList
);
468 cstate
= (Object
*) ChildList
->mlh_Head
;
469 while ((child
= NextObject(&cstate
)))
471 DoMethod(child
, MUIM_ConnectParent
, (IPTR
) obj
);
476 /**************************************************************************
477 MUIM_DisconnectParent
478 **************************************************************************/
479 IPTR
Menuitem__MUIM_DisconnectParent(struct IClass
*cl
, Object
*obj
,
480 struct MUIP_ConnectParent
*msg
)
484 struct MinList
*ChildList
= NULL
;
486 D(bug("Menuitem_DisconnectParent(%p) %s\n", obj
, OCLASS(obj
)->cl_ID
));
488 get(obj
, MUIA_Family_List
, &ChildList
);
489 cstate
= (Object
*) ChildList
->mlh_Head
;
490 while ((child
= NextObject(&cstate
)))
492 DoMethodA(child
, (Msg
) msg
);
494 muiNotifyData(obj
)->mnd_ParentObject
= NULL
;
495 DoSuperMethodA(cl
, obj
, (Msg
) msg
);
499 /**************************************************************************
500 MUIM_Family_Insert, MUIM_Family_Remove
501 **************************************************************************/
502 IPTR
Menuitem__MUIM_Update(struct IClass
*cl
, Object
*obj
, Msg msg
)
504 // struct MUI_MenuitemData *data = INST_DATA(cl, obj);
506 IPTR retval
= DoSuperMethodA(cl
, obj
, msg
);
508 if (muiNotifyData(obj
) &&
509 muiNotifyData(obj
)->mnd_GlobalInfo
&&
510 muiNotifyData(obj
)->mnd_GlobalInfo
->mgi_ApplicationObject
)
512 DoMethod(_app(obj
), MUIM_Application_UpdateMenus
);
518 IPTR
Common_Dispatcher(Class
*cl
, Object
*obj
, Msg msg
)
520 switch (msg
->MethodID
)
523 return Menuitem__OM_DISPOSE(cl
, obj
, msg
);
525 return Menuitem__OM_SET(cl
, obj
, (struct opSet
*)msg
);
527 return Menuitem__OM_GET(cl
, obj
, (struct opGet
*)msg
);
528 case MUIM_ConnectParent
:
529 return Menuitem__MUIM_ConnectParent(cl
, obj
, (APTR
) msg
);
530 case MUIM_DisconnectParent
:
531 return Menuitem__MUIM_DisconnectParent(cl
, obj
, (APTR
) msg
);
532 case MUIM_Family_Insert
:
533 return Menuitem__MUIM_Update(cl
, obj
, (APTR
) msg
);
534 case MUIM_Family_Remove
:
535 return Menuitem__MUIM_Update(cl
, obj
, (APTR
) msg
);
536 case MUIM_Family_AddTail
:
537 return Menuitem__MUIM_Update(cl
, obj
, (APTR
) msg
);
538 case MUIM_Family_AddHead
:
539 return Menuitem__MUIM_Update(cl
, obj
, (APTR
) msg
);
541 return Menuitem__MUIM_Update(cl
, obj
, (APTR
) msg
);
543 return Menuitem__MUIM_Update(cl
, obj
, (APTR
) msg
);
545 return DoSuperMethodA(cl
, obj
, msg
);
548 BOOPSI_DISPATCHER(IPTR
, Menuitem_Dispatcher
, cl
, obj
, msg
)
550 switch (msg
->MethodID
)
553 return Menuitem__OM_NEW(cl
, obj
, (struct opSet
*)msg
);
556 return Common_Dispatcher(cl
, obj
, msg
);
558 BOOPSI_DISPATCHER_END
560 BOOPSI_DISPATCHER(IPTR
, Menu_Dispatcher
, cl
, obj
, msg
)
562 switch (msg
->MethodID
)
565 return Menu__OM_NEW(cl
, obj
, (struct opSet
*)msg
);
568 return Common_Dispatcher(cl
, obj
, msg
);
570 BOOPSI_DISPATCHER_END
572 BOOPSI_DISPATCHER(IPTR
, Menustrip_Dispatcher
, cl
, obj
, msg
)
574 switch (msg
->MethodID
)
577 return Menustrip__OM_NEW(cl
, obj
, (struct opSet
*)msg
);
580 return Common_Dispatcher(cl
, obj
, msg
);
582 BOOPSI_DISPATCHER_END
586 const struct __MUIBuiltinClass _MUI_Menuitem_desc
=
590 sizeof(struct MUI_MenuitemData
),
591 (void *) Menuitem_Dispatcher
595 * Class descriptor.- this class is the same like menuitem
597 const struct __MUIBuiltinClass _MUI_Menu_desc
=
601 sizeof(struct MUI_MenuitemData
),
602 (void *) Menu_Dispatcher
606 * Class descriptor.- this class is the same like menuitem
608 const struct __MUIBuiltinClass _MUI_Menustrip_desc
=
612 sizeof(struct MUI_MenuitemData
),
613 (void *) Menustrip_Dispatcher