Copy link to clipboard
Copied
I am trying to make a pop menu ("conext menu"?) when the user right clicks on a selected path object. I have looked through the docs and found that the basic suite claims to be able to do this. Using the create function, I see that it doesn't do anything noticable. I have tried passing the ADMListRef object that buffers the reference to the menu to the List Suite, but I can't seem to get it to do anything.
How do you make/add to menu's that the user gets when they right click?
Am I on the right track?
Is there any better documentation on these suites that I can look to for answers?
Thanks in advance,
Jeremy
Well, I don't use the same method for creating my pop-up menu. I do something slightly different, and maybe it makes a difference. I should note that I'm using the IADM* objects too, so there may be subtle differences -- they generally wrap to the obvious suite call though. Note also that I'm updating a list based on other events, so you can probably ignore clearing part
--------- snip ---------
IADMItem button(GetItem(kChangeMapViewButton));
IADMList list(button.GetList());
const int count = list.N
...Copy link to clipboard
Copied
Illustrator has no support for context menus of any kind unfortunately. I'm curious though, what suite did you find that you think provides this support? From what you're describing it sounds like you're talking about pop-up menus from certain widgets, or perhaps the fly-out menu for a panel.
At any rate, I sympathize -- I've wanted to customize those context menus forever but I'm afraid short of hacking in with OS-level calls (and I'm not reccommending that!) there's no way to change those.
Copy link to clipboard
Copied
The ADMBasicSuite10 us defined in the documentation as:
struct ADMBasicSuite10 This suite provides utility functions that allow you to work with platform string and cursor resources, tool tips, and context menus. More..
Maybe I have a diffrent definition of a context menu. What im looking for is the ability to right click a vector shape, have a menu there where I can preform some action. Is that at all possible?
Jeremy
Copy link to clipboard
Copied
I'll be damned. And no, we are talking about the same thing, but every time we asked Adobe for the ability to mess with or create context menus they told us no. I just might play around with this, see what is capable of.
It sounds like they want you to do something like this:
ADMListRef menu;
sADMBasic->CreateMenu(&menu);
ADMEntryRef entry = ADMList->InsertEntry(menu, 0);
ADMEntry->SetText(entry, "Hi!");
sADMBasic->DisplayMenu(menu, dialog, location);
But that's just a guess. Probably need to manually hook up notifications in there somewhere as well.
Copy link to clipboard
Copied
I've spoken to my employer, he agrees that a menu attached to one of my dialog boxes would be sufficent. I've created a button on one of the dialog's
ADMRect button;
button.top = 0;
button.left = 0;
button.right = 20;
button.bottom = 20;
g->cMenu = sADMDialog->CreateItem(reference,kADMUniqueItemID,kADMPopupMenuType,&button,ChanMenuInit,NULL,0);
but nothing happens when I click it (obviously). How do I add a menu to this button, and further add actions to these menu items?
Thanks,
Jeremy
Copy link to clipboard
Copied
Sorry, I meant to come back to this and I forgot ![]()
You're just trying to get the fly-out menu on the Panel working I take it? Here's the code from my InitMenu() call:
void CADMPaletteDialog::InitMenu()
{
ADMInt32 menuId = GetMenuId();
// make sure we have one
if (menuId < 1) {
// error
return;
}
// first we need the special item that represents the panel menu
ADMItemRef menuItem = sADMDialog->GetItem(GetDialog(), kADMMenuItemID);
ASSERT(menuItem);
// then we get the item in list form (this is special for list controls, usually you wouldn't do this)
ADMListRef menuList = sADMItem->GetList(menuItem);
ASSERT(menuList);
// now we hack it a little bit to tell the list to use the menu resource id;
// kPaletteMenuName can (I think) be anything -- check the documentation to be sure
sADMList->SetMenuID(menuList, GetPluginRef(), menuId, kPaletteMenuName.toLocal8Bit().constData());
// MenuNotifyProc is a static callback inside my object; it can just be a normal function
// for you, but you need to have this or you won't get notified about clicks!
ADMItemNotifyProc pMenuNotifyProc = MenuNotifyProc;
sADMItem->SetNotifyProc(menuItem, pMenuNotifyProc);
}
A few words on the above code to explain. First, CADMPaletteDialog is our base class for panel dialogs. It ultimately derives off of IADMDialog, though its actually my own class that provides GetMenuId(), GetDialog() & GetPluginRef. Fortunately, I assume those are fairly self-explanantory and you won't need my help getting them
Well, GetMenuId() I should mention would return the resource ID for the menu. As you can see, its important to have it. Second, this needs to be done inside the initialization callback for the dialog; I have an Init() method that gets invoked on my class, and it calls InitMenu() inside there.
Hopfully that helps. If you're trying to do a context menu, it will be different and I'll have to figure that out for myself as I've never actually done that.
Copy link to clipboard
Copied
What I'm trying to do is get some kind of a menu to pop out from the side of a button when pressed (a fly out menu?).
From your code posted, is this for the dialog that will be hosting the menu? or for the dialog that is hosting the button where the menu will be comming from?
Thanks,
Jeremy
Copy link to clipboard
Copied
Oh, sorry. The code I posted was for a panel's fly-out or pop-up menu (the little circle with the arrow at the top-right corner of a floating panel).
I have done it for a button, bit it requires a lot of pieces to be right, any of which being wrong causes nothing to happen. The first and most critical step is to make sure you've correctly created a widget that supports the pop-up menu. This means you've either created the button in code, or you've created a custom widget and correctly identified it in your resources (easier for Windows than Mac).
Next, you have to make sure the widget's item styles is set correctly, if the widget requires that to make a menu work. Then you should check the 'sub-control' enum in ADMItem.h -- does your widget have a specific ID for the menu portion? If so, you should use that to get the ADMItemRef for that sub-control. You may not need to, but I think some do (for example, I think you can use a special ID to get the scroll bar on a list widget).
Once you have the ADMItemRef for whatever has the menu, you use the same bit of code I posted earlier to convert it into a list. sADMItem->GetList() to get an ADMListRef. Once you have that, you should be good to go -- just populate it and make sure its setup to send you clicks (SetNotifiyProc).
I'm about to head to lunch -- I know I have an ADM control doing that somewhere and I'll see if I can dig up the code when I get back.
Copy link to clipboard
Copied
Ok, I've got the menu but for some reason notfications are being sent back to the Item, not the entry/list's. This is what I have so far
In the dialog i create the Item:
g->cMenu = sADMDialog->CreateItem(reference,kADMUniqueItemID,kADMPopupMenuType,&button,ChanMenuInit,NULL,0);
The item is a button with an arrow that points to the right. when clicked it pops a menu out to the right that has two columns.
The Item's init function is this:
static
ADMErr ADMAPI ChanMenuInit(ADMItemRef inItem){
g->list = sADMItem->GetList(inItem);
for(inti = 0; i < g->numChannels; i ++){
g->MenuItems = sADMEntry->Create(g->list);
}
sADMList->SetNotifyProc(g->list,MenuChannelCatch);
sADMEntry->SetText(g->MenuItems[1],
"1");
sADMEntry->SetText(g->MenuItems[2],
"2");
sADMEntry->SetText(g->MenuItems[3],
"3");
sADMEntry->SetText(g->MenuItems[4],
"4");
sADMEntry->SetText(g->MenuItems[5],
"5");
returnkNoErr;
}
This shoudl create 5 Entries into the list (which it does); however, each entry is blank with no value. When clicked a notifier for the button is triggered, not the list (I put the button notifier after noticing that that the list wasn't doing anything). I'm probibly missing some kind of Init procedure, any ideas?
Copy link to clipboard
Copied
Well, I don't use the same method for creating my pop-up menu. I do something slightly different, and maybe it makes a difference. I should note that I'm using the IADM* objects too, so there may be subtle differences -- they generally wrap to the obvious suite call though. Note also that I'm updating a list based on other events, so you can probably ignore clearing part
--------- snip ---------
IADMItem button(GetItem(kChangeMapViewButton));
IADMList list(button.GetList());
const int count = list.NumberOfEntries();
// clear list
for (int i = 0; i < count; i++) {
list.RemoveEntry(0);
}
// get my view list (what the views are is unimportant to you!)
const CString kSentToTemplate = QObject::tr("Switch to \"%1\"");
MapViewList::iterator index;
for (index = viewList.begin(); index != viewList.end(); ++index) {
int position = list.NumberOfEntries();
IADMEntry entry(list.InsertEntry(position));
CMapView* view = *index;
// CPlatformString is my own home-cooked class for converting between our
// internal string object & Adobe's ASUnicode (returned via au_atr())
CPlatformString text = kSentToTemplate.arg(view->GetName());
entry.SetText(text.au_str());
entry.SetUserData((void*)view);
entry.SetID(position);
}
--------- snip ---------
I think that setting the ID is critical to actually knowing which menuitem was hit -- I think they're all zero by default, which is part of the problem. I could be wrong though. I remember I wrestled with this a fair bit before I got it right. It maybe that asking for the ActiveEntry() is sufficient (as you'll see below). Still, setting an ID that means something is bound to be useful if you're not using the Get/SetUserData() calls.
To determine which entry was clicked, I respond to the item changed notifier (which you said you're getting). That looks kind of like this:
--------- snip ---------
IADMItem button(GetItem(kChangeMapViewButton));
IADMList list(button.GetList());
ADMEntryRef entryRef = list.GetActiveEntry();
if (entryRef) {
IADMEntry entry(entryRef);
// I'm using the user data so I don't actually care which entry was clicked
void* data = entry.GetUserData();
// you could ask for the ID at this point and that would tell you the index into the list;
// nothing stops you from making the IDs whatever you want though, if they're
// hard-coded
const int id = entry.GetID();
// respond
}
--------- snip ---------
FYI, the button in question is of type "ADM Popup Menu Type", at least in my resource file. I'm pretty sure that corresponds to a type in the ADMItem.h header if you search for it though. I don't know if you're using the same type of button or not though. Still, it's likely very similar.
Get ready! An upgraded Adobe Community experience is coming in January.
Learn more