menuclass not as dynamic as suggested

This forum is for general developer support questions.
Post Reply
chris
Posts: 562
Joined: Sat Jun 18, 2011 11:05 am
Contact:

menuclass not as dynamic as suggested

Post by chris »

The wiki says:
A BOOPSI menu tree built with menuclass allows for dynamic addition and removal of menus and items at any time. As with other modifications, there's no need to detach the menu tree from the window in order to perform these operations; it's menuclass that takes care of synchronizing each change with Intuition and doing any necessary relayout afterwards.
This appears to not be the case. I've removed a bunch of items (T_ITEM) under a menu (T_MENU) using both OM_REMMEMBER and MA_RemChild, and in neither case does the menu physically update. It does something, because all the strings I've freed end up showing as random garbage, but the menu items themselves persist.

I've re-added the same items and the same garbage stays in the menu, despite my new items being created pointing at valid strings.

So, menuclass isn't doing what it is supposed to.

I can't figure out how to force the menu to refresh to workaround this bug. Re-applying WINDOW_MenuStrip doesn't help. Anyone?
User avatar
mritter0
Posts: 214
Joined: Mon Aug 25, 2014 9:41 pm
Location: Bettendorf, IA, USA

Re: menuclass not as dynamic as suggested

Post by mritter0 »

This is how I do it, no extra refresh needed:

Code: Select all

BOOL
SAK_AddMenuItem(Object *MenuObj,uint32 Parent,Object *AddItem)
{
	Object							*item;

	if ((item=(Object *)IIntuition->IDoMethod(MenuObj,MM_FINDID,0,Parent)))
	{
		IIntuition->SetAttrs(item,
			MA_AddChild,						AddItem,
		TAG_END);

		return(TRUE);
	}

	return(FALSE);
}


VOID
SAK_RemoveMenuItem(Object *MenuObj,uint32 ID)
{
	Object							*item;

	if ((item=(Object *)IIntuition->IDoMethod(MenuObj,MM_FINDID,0,ID)))
	{
		IIntuition->SetAttrs(MenuObj,
			MA_RemoveChild,						item,
		TAG_END);
		IIntuition->DisposeObject(item);
	}
}


		SAK_RemoveMenuItem(MenuStripObj,LocalDevicesNode->GoMenuID);

Workbench Explorer - A better way to browse drawers
User avatar
broadblues
AmigaOS Core Developer
AmigaOS Core Developer
Posts: 600
Joined: Sat Jun 18, 2011 2:40 am
Location: Portsmouth, UK
Contact:

Re: menuclass not as dynamic as suggested

Post by broadblues »

chris wrote:The wiki says:
A BOOPSI menu tree built with menuclass allows for dynamic addition and removal of menus and items at any time. As with other modifications, there's no need to detach the menu tree from the window in order to perform these operations; it's menuclass that takes care of synchronizing each change with Intuition and doing any necessary relayout afterwards.
This appears to not be the case. I've removed a bunch of items (T_ITEM) under a menu (T_MENU) using both OM_REMMEMBER and MA_RemChild, and in neither case does the menu physically update. It does something, because all the strings I've freed end up showing as random garbage, but the menu items themselves persist.

I've re-added the same items and the same garbage stays in the menu, despite my new items being created pointing at valid strings.

So, menuclass isn't doing what it is supposed to.

I can't figure out how to force the menu to refresh to workaround this bug. Re-applying WINDOW_MenuStrip doesn't help. Anyone?
Post a code snippet, if you can, as this definetly works in general, so you either have a mistake in your code, or an edge case where it broken...
chris
Posts: 562
Joined: Sat Jun 18, 2011 11:05 am
Contact:

Re: menuclass not as dynamic as suggested

Post by chris »

Hmm, odd, I must be doing something wrong then.

This is the function which deletes and re-adds the items:

Code: Select all

void ami_menu_refresh(struct Menu *menu, struct ami_menu_data **md, int menu_item, int max,
	nserror (*cb)(struct ami_menu_data **md))
{
#ifdef __amigaos4__
	Object *restrict obj;
	Object *restrict menu_item_obj;
	int i;

	if(menu == NULL) return;

	if(LIB_IS_AT_LEAST((struct Library *)IntuitionBase, 54, 6)) {
		/* find the address of the menu */
		menu_item_obj = (Object *)IDoMethod((Object *)menu, MM_FINDID, 0, menu_item);

		/* remove all children */
		while((obj = (Object *)IDoMethod(menu_item_obj, MM_NEXTCHILD, 0, NULL)) != NULL) {
			IDoMethod(menu_item_obj, OM_REMMEMBER, obj);
			DisposeObject(obj);
		}

		/* free associated data */
		for(i = (menu_item + 1); i <= max; i++) {
			if(md[i] == NULL) continue;
			ami_menu_free_lab_item(md, i);
		}

		/* get current data */
		cb(md);

		/* re-add items to menu */
		ami_menu_layout_mc_recursive(menu_item_obj, md, NM_ITEM, (menu_item + 1), max);
	}
#endif
}
I know for a fact that the callback and the addition code works, and I get the corrupted menu even without those two lines, so I think the problem is above them.

I'm calling this function with something like:
ami_menu_refresh(root menuclass obj, menu-data array, ID of a menu (T_MENU/NM_TITLE), max ID to process, callback which re-populates the menu-data array)

I suspect it's something stupid!
chris
Posts: 562
Joined: Sat Jun 18, 2011 11:05 am
Contact:

Re: menuclass not as dynamic as suggested

Post by chris »

Ah, fixed it. I'd taken out the MA_ID of my T_MENU items at one point to try to solve another problem, so it wasn't finding the ID in the menu and hence not removing the items.

Thanks anyway. :oops:
Post Reply