2 Copyright © 2002-2007, 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
);
104 menu
->nm_Type
= NM_TITLE
;
106 menu
->nm_Flags
|= NM_MENUDISABLED
;
110 menu
->nm_Type
= NM_ITEM
;
112 menu
->nm_Flags
|= NM_ITEMDISABLED
;
116 menu
->nm_Type
= NM_SUB
;
118 menu
->nm_Flags
|= NM_ITEMDISABLED
;
121 menu
->nm_UserData
= child
;
125 entries
= Menuitem_FillNewMenu(child
, menu
, depth
+ 1);
133 /**************************************************************************
135 **************************************************************************/
136 static struct NewMenu
*Menuitem_BuildNewMenu(struct MUI_MenuitemData
*data
,
139 int entries
= Menuitem_GetTotalChildren(obj
);
141 FreeVec(data
->newmenu
);
142 data
->newmenu
= NULL
;
147 (struct NewMenu
*)AllocVec((entries
+
148 1) * sizeof(struct NewMenu
), MEMF_CLEAR
)))
150 Menuitem_FillNewMenu(obj
, data
->newmenu
, 0);
152 return data
->newmenu
;
155 /**************************************************************************
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 */
168 data
= INST_DATA(cl
, obj
);
170 data
->flags
= MENUF_ENABLED
;
172 for (tags
= msg
->ops_AttrList
; (tag
= NextTagItem(&tags
));)
176 case MUIA_Menuitem_Checked
:
177 _handle_bool_tag(data
->flags
, tag
->ti_Data
, MENUF_CHECKED
);
180 case MUIA_Menuitem_Checkit
:
181 _handle_bool_tag(data
->flags
, tag
->ti_Data
, MENUF_CHECKIT
);
184 case MUIA_Menuitem_CommandString
:
185 _handle_bool_tag(data
->flags
, tag
->ti_Data
, MENUF_COMMANDSTRING
);
188 case MUIA_Menu_Enabled
:
189 case MUIA_Menuitem_Enabled
:
190 _handle_bool_tag(data
->flags
, tag
->ti_Data
, MENUF_ENABLED
);
193 case MUIA_Menuitem_Toggle
:
194 _handle_bool_tag(data
->flags
, tag
->ti_Data
, MENUF_TOGGLE
);
197 case MUIA_Menuitem_Exclude
:
198 data
->exclude
= tag
->ti_Data
;
201 case MUIA_Menuitem_Shortcut
:
202 data
->shortcut
= (char *)tag
->ti_Data
;
205 case MUIA_Menu_Title
:
206 case MUIA_Menuitem_Title
:
207 data
->title
= (char *)tag
->ti_Data
;
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
;
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
;
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
;
248 /**************************************************************************
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
));)
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
);
275 struct MinList
*ChildList
= NULL
;
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
);
303 case MUIA_Menuitem_Checkit
:
304 _handle_bool_tag(data
->flags
, tag
->ti_Data
, MENUF_CHECKIT
);
308 case MUIA_Menuitem_CommandString
:
309 _handle_bool_tag(data
->flags
, tag
->ti_Data
,
310 MENUF_COMMANDSTRING
);
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
;
321 case MUIA_Menuitem_Toggle
:
322 _handle_bool_tag(data
->flags
, tag
->ti_Data
, MENUF_TOGGLE
);
326 case MUIA_Menuitem_Exclude
:
327 data
->exclude
= tag
->ti_Data
;
331 case MUIA_Menuitem_Shortcut
:
332 data
->shortcut
= (char *)tag
->ti_Data
;
336 case MUIA_Menu_Title
:
337 case MUIA_Menuitem_Title
:
338 data
->title
= (char *)tag
->ti_Data
;
339 tag
->ti_Tag
= TAG_IGNORE
;
343 case MUIA_Menuitem_Trigger
:
344 data
->trigger
= (struct MenuItem
*)tag
->ti_Data
;
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 /**************************************************************************
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);
377 case MUIA_Menuitem_Checkit
:
378 STORE
= ((data
->flags
& MENUF_CHECKIT
) != 0);
381 case MUIA_Menuitem_CommandString
:
382 STORE
= ((data
->flags
& MENUF_COMMANDSTRING
) != 0);
385 case MUIA_Menu_Enabled
:
386 case MUIA_Menuitem_Enabled
:
387 STORE
= ((data
->flags
& MENUF_ENABLED
) != 0);
390 case MUIA_Menuitem_Toggle
:
391 STORE
= ((data
->flags
& MENUF_TOGGLE
) != 0);
394 case MUIA_Menuitem_Exclude
:
395 STORE
= data
->exclude
;
398 case MUIA_Menuitem_Shortcut
:
399 STORE
= (IPTR
) data
->shortcut
;
402 case MUIA_Menu_Title
:
403 case MUIA_Menuitem_Title
:
404 STORE
= (IPTR
) data
->title
;
407 case MUIA_Menuitem_NewMenu
:
408 Menuitem_BuildNewMenu(data
, obj
);
409 STORE
= (IPTR
) data
->newmenu
;
412 case MUIA_Menuitem_Trigger
:
413 STORE
= (IPTR
) data
->trigger
;
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
;
422 STORE
= (IPTR
) MUIV_Menuitem_Type_Menuitem
;
427 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
432 /**************************************************************************
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 /**************************************************************************
447 **************************************************************************/
448 IPTR
Menuitem__MUIM_ConnectParent(struct IClass
*cl
, Object
*obj
,
449 struct MUIP_ConnectParent
*msg
)
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
);
470 /**************************************************************************
471 MUIM_DisconnectParent
472 **************************************************************************/
473 IPTR
Menuitem__MUIM_DisconnectParent(struct IClass
*cl
, Object
*obj
,
474 struct MUIP_ConnectParent
*msg
)
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
);
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
);
512 IPTR
Common_Dispatcher(Class
*cl
, Object
*obj
, Msg msg
)
514 switch (msg
->MethodID
)
517 return Menuitem__OM_DISPOSE(cl
, obj
, msg
);
519 return Menuitem__OM_SET(cl
, obj
, (struct opSet
*)msg
);
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
);
535 return Menuitem__MUIM_Update(cl
, obj
, (APTR
) msg
);
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
)
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
)
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
)
571 return Menustrip__OM_NEW(cl
, obj
, (struct opSet
*)msg
);
574 return Common_Dispatcher(cl
, obj
, msg
);
576 BOOPSI_DISPATCHER_END
580 const struct __MUIBuiltinClass _MUI_Menuitem_desc
=
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
=
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
=
606 sizeof(struct MUI_MenuitemData
),
607 (void *) Menustrip_Dispatcher