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, 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
);
96 menu
->nm_Flags
|= CHECKIT
;
98 menu
->nm_Flags
|= CHECKED
;
100 menu
->nm_Flags
|= MENUTOGGLE
;
102 menu
->nm_Flags
|= COMMSEQ
;
103 get(child
, MUIA_Menuitem_Exclude
, &menu
->nm_MutualExclude
);
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
;
115 menu
->nm_Type
= NM_TITLE
;
118 menu
->nm_Type
= NM_ITEM
;
120 menu
->nm_Type
= NM_SUB
;
124 if (menu
->nm_Type
== NM_TITLE
)
125 menu
->nm_Flags
|= NM_MENUDISABLED
;
127 menu
->nm_Flags
|= NM_ITEMDISABLED
;
130 menu
->nm_UserData
= child
;
134 entries
= Menuitem_FillNewMenu(child
, menu
, depth
+ 1);
142 /**************************************************************************
144 **************************************************************************/
145 static struct NewMenu
*Menuitem_BuildNewMenu(struct MUI_MenuitemData
*data
,
148 int entries
= Menuitem_GetTotalChildren(obj
);
150 FreeVec(data
->newmenu
);
151 data
->newmenu
= NULL
;
156 (struct NewMenu
*)AllocVec((entries
+
157 1) * sizeof(struct NewMenu
), MEMF_CLEAR
)))
159 Menuitem_FillNewMenu(obj
, data
->newmenu
, 0);
161 return data
->newmenu
;
164 /**************************************************************************
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 */
177 data
= INST_DATA(cl
, obj
);
179 data
->flags
= MENUF_ENABLED
;
181 for (tags
= msg
->ops_AttrList
; (tag
= NextTagItem(&tags
));)
185 case MUIA_Menuitem_Checked
:
186 _handle_bool_tag(data
->flags
, tag
->ti_Data
, MENUF_CHECKED
);
189 case MUIA_Menuitem_Checkit
:
190 _handle_bool_tag(data
->flags
, tag
->ti_Data
, MENUF_CHECKIT
);
193 case MUIA_Menuitem_CommandString
:
194 _handle_bool_tag(data
->flags
, tag
->ti_Data
, MENUF_COMMANDSTRING
);
197 case MUIA_Menu_Enabled
:
198 case MUIA_Menuitem_Enabled
:
199 _handle_bool_tag(data
->flags
, tag
->ti_Data
, MENUF_ENABLED
);
202 case MUIA_Menuitem_Toggle
:
203 _handle_bool_tag(data
->flags
, tag
->ti_Data
, MENUF_TOGGLE
);
206 case MUIA_Menuitem_Exclude
:
207 data
->exclude
= tag
->ti_Data
;
210 case MUIA_Menuitem_Shortcut
:
211 data
->shortcut
= (char *)tag
->ti_Data
;
214 case MUIA_Menu_Title
:
215 case MUIA_Menuitem_Title
:
216 data
->title
= (char *)tag
->ti_Data
;
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
;
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
;
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
;
257 /**************************************************************************
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
));)
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
);
284 struct MinList
*ChildList
= NULL
;
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
);
312 case MUIA_Menuitem_Checkit
:
313 _handle_bool_tag(data
->flags
, tag
->ti_Data
, MENUF_CHECKIT
);
317 case MUIA_Menuitem_CommandString
:
318 _handle_bool_tag(data
->flags
, tag
->ti_Data
,
319 MENUF_COMMANDSTRING
);
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
;
330 case MUIA_Menuitem_Toggle
:
331 _handle_bool_tag(data
->flags
, tag
->ti_Data
, MENUF_TOGGLE
);
335 case MUIA_Menuitem_Exclude
:
336 data
->exclude
= tag
->ti_Data
;
340 case MUIA_Menuitem_Shortcut
:
341 data
->shortcut
= (char *)tag
->ti_Data
;
345 case MUIA_Menu_Title
:
346 case MUIA_Menuitem_Title
:
347 data
->title
= (char *)tag
->ti_Data
;
348 tag
->ti_Tag
= TAG_IGNORE
;
352 case MUIA_Menuitem_Trigger
:
353 data
->trigger
= (struct MenuItem
*)tag
->ti_Data
;
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 /**************************************************************************
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);
386 case MUIA_Menuitem_Checkit
:
387 STORE
= ((data
->flags
& MENUF_CHECKIT
) != 0);
390 case MUIA_Menuitem_CommandString
:
391 STORE
= ((data
->flags
& MENUF_COMMANDSTRING
) != 0);
394 case MUIA_Menu_Enabled
:
395 case MUIA_Menuitem_Enabled
:
396 STORE
= ((data
->flags
& MENUF_ENABLED
) != 0);
399 case MUIA_Menuitem_Toggle
:
400 STORE
= ((data
->flags
& MENUF_TOGGLE
) != 0);
403 case MUIA_Menuitem_Exclude
:
404 STORE
= data
->exclude
;
407 case MUIA_Menuitem_Shortcut
:
408 STORE
= (IPTR
) data
->shortcut
;
411 case MUIA_Menu_Title
:
412 case MUIA_Menuitem_Title
:
413 STORE
= (IPTR
) data
->title
;
416 case MUIA_Menuitem_NewMenu
:
417 Menuitem_BuildNewMenu(data
, obj
);
418 STORE
= (IPTR
) data
->newmenu
;
421 case MUIA_Menuitem_Trigger
:
422 STORE
= (IPTR
) data
->trigger
;
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
;
431 STORE
= (IPTR
) MUIV_Menuitem_Type_Menuitem
;
436 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
441 /**************************************************************************
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 /**************************************************************************
456 **************************************************************************/
457 IPTR
Menuitem__MUIM_ConnectParent(struct IClass
*cl
, Object
*obj
,
458 struct MUIP_ConnectParent
*msg
)
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
);
479 /**************************************************************************
480 MUIM_DisconnectParent
481 **************************************************************************/
482 IPTR
Menuitem__MUIM_DisconnectParent(struct IClass
*cl
, Object
*obj
,
483 struct MUIP_ConnectParent
*msg
)
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
);
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
);
521 IPTR
Common_Dispatcher(Class
*cl
, Object
*obj
, Msg msg
)
523 switch (msg
->MethodID
)
526 return Menuitem__OM_DISPOSE(cl
, obj
, msg
);
528 return Menuitem__OM_SET(cl
, obj
, (struct opSet
*)msg
);
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
);
544 return Menuitem__MUIM_Update(cl
, obj
, (APTR
) msg
);
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
)
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
)
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
)
580 return Menustrip__OM_NEW(cl
, obj
, (struct opSet
*)msg
);
583 return Common_Dispatcher(cl
, obj
, msg
);
585 BOOPSI_DISPATCHER_END
589 const struct __MUIBuiltinClass _MUI_Menuitem_desc
=
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
=
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
=
615 sizeof(struct MUI_MenuitemData
),
616 (void *) Menustrip_Dispatcher