20100530

NSMenu popup location

NSMenu has a class method popUpContextMenu:withEvent:forView:, which I initially thought was the only way to cause a menu to pop-up where I wanted. In order to give it a useful event, I took the event I had and created a new one from it, with a different mouse location, to try to trick the menu's position. The goal is that the menu should normally appear under the control, with the left of the menu aligned to the left of the control. If there isn't enough room under the control, the menu should appear above the control and not obscure it from view. Similarly, if there isn't enough space to the right of the control for the entire menu to display, the menu should right-align to the control.
I had gotten the above/below positioning sorted out using the NSMenuDelegate method confinementRectForMenu:onScreen:, but I could not get the left/right alignment switch to work. If I would set the menu rect's origin to the left of the control, the upper-right of the menu would be there; and if I set it to the right of the control, the menu's upper-left would be there.
I put the menu to the left of the control entirely and then moved the x field of the origin over by the width of the menu. No good.
I tried moving it over incrementally over several test runs. It eventually became clear that I could not move the x coordinate of the menu's origin past 5/6 of the width of the control without the menu aligning its left to the left of the control.

I then discovered that NSMenu has an instance method popUpMenuPositioningItem:atLocation:inView:. This method had much better documentation, saying that I could pass nil for the item and the view, and then I could control the upper-left corner of the menu rect, and it would pop-up unattached to any other window. I tried this out, and it worked, with less code (no longer needed to fake an NSEvent).
I went back and used a nil view for the class method, and this also worked.

My recommendation is to use the class method, since it provides the flexibility to position an arbitrary item in the menu or the entire menu at a certain point, and it has much better documentation.