Neither the cxMenuSelectionFcn nor the ContextMenuOpeningFcn functions indicate the object that evoked the context menu.
Check out Adam's excellent wrapper function but you'll need to make two important modifications that I listed in the comments under his answer. Using gco or gcbo are other useful alternatives but they do not recognize ROI objects.
After some thinking, I came up with another way to identify which ROI objects evoked the context menu explained below. But this was before discovering Adam's (the other Adam) answer suggested above. I'd try that one first.
Method
- ROI object handles are saved as a private (or public) property of the app.
- Every ROI object is assigned a unique tag name.
- The context menu is assigned to every ROI object.
- A listener is added to each ROI object and responds to a button click (right or left mouse).
- When the ROI is clicked, it updates the context menu tag to match the tag of the clicked ROI.
- When the cxMenuSelectionFcn is evoked by a right-button click, the function uses the recently updated context menu tag and matches it with all ROI tags to identify what object evokes the menu.
Demo
The cxMenuSelectionFcn merely changes the color of the ROI. The full app is attached. Here are the key parts.
The variable containing the ROI handles is a private (or public) property of the app.
properties (Access = private)
The startupFcn creates the context menu, plots the ROI objects, and assigns the listeners to the ROI objects. This could be done in any callback function. Importantly, unique tags must be assigned to the ROI objects and the context menu must exist prior to assigning the listeners.
cm = uicontextmenu(app.UIFigure);
m1 = uimenu(cm,'Text','ChangeColor','MenuSelectedFcn',@(mn,ad)cxMenuSelectionFcn(app,mn,ad));
app.ROIhandles(1) = images.roi.Rectangle(app.UIAxes,'Position',[.1 .1 .2 .2],'Tag','R1');
app.ROIhandles(2) = images.roi.Rectangle(app.UIAxes,'Position',[.5 .5 .1 .2],'Tag','R2');
app.ROIhandles(3) = images.roi.Rectangle(app.UIAxes,'Position',[.1 .6 .2 .3],'Tag','R3');
set(app.ROIhandles, 'ContextMenu', cm)
for i = 1:numel(app.ROIhandles)
app.ROIhandles(i).UserData = listener(app.ROIhandles(i), 'ROIClicked', ...
@(~,~)set(app.ROIhandles(i).ContextMenu,'Tag', app.ROIhandles(i).Tag));
Define the cxMenuSelectionFcn function
This is a private (or public) method defined in the App. Two assert()'s are used to make sure a tag was successfully assigned to the context menu and that one and only one ROI object was matched to the tag. It then changes the color of the ROI object to some random color.
methods (Access = private)
function cxMenuSelectionFcn(app,menu,~)
assert(~isempty(cmtag),'Failure to assign tag to context menu.')
handleIdx = strcmp({app.ROIhandles.Tag}, cmtag);
assert(sum(handleIdx)==1, 'Failture to identify ROI.')
hRoi = app.ROIhandles(handleIdx);