NSMenuItem actions overriding NSPopUpButton actions - objective-c

I've noticed an interesting behavior and I wonder if it's something I'm doing wrong. I have an NSPopUpButton with several NSMenuItems on an NSMenu on the NSPopUpButton. When I click the popup button and select an item the action that I've linked to the NSPopUpButton gets triggered UNLESS the menu item I select defines it's own action:#selector(method). In that case, the method in the selector gets fired and the other action does not. I would think both should happen.
Also related to this, if I have selectors on menu items, and I call [popUpButton selectItemAtIndex:index] shouldn't that call the selector on the appropriate menu item?
Is this the correct behavior?

Related

Can I conditionally disable an NSMenuItem that is only enabled when the first responder responds to a selector?

I have an NSMenuItem that is enabled/disabled based on whether or not the first responder responds to a specific selector.
My problem is that there are conditions in which I do not want the item enabled for the first responder.
But I can't just conditionally remove a method definition during runtime to disable the menu item
For an example of what I mean:
I have a NSDocument-based application, and I have two main subclasses-- an ImageDocument and a VideoDocument
I have an NSMenuItem called "Capture Frame", which turns a frame of a video into an image. But obviously this should be disabled on an ImageDocument, and only enabled on a VideoDocument.
The NSMenuItem is enabled if the first responder responds to -captureFrame
The VideoDocumentController has a method, -captureFrame, so it's enabled.
The ImageDocumentController does not, so the menu item is never enabled.
But, there are specific VideoDocuments that I do not want to have that menu item enabled for. What could be the best way for me to disable this menu item in order to handle special cases?
In your VideoDocument class, override the NSDocument method validateUserInterfaceItem:. Alternatively, you can override validateUserInterfaceItem: in a subclass of NSDocumentController. Be sure to call super to keep the built-in functionality of this method. See Apple's docs on UI validation for an example.

Objective-C does not execute change method for a NSPopUpButton

I have a view with a popup menu. In the view controller I implemented a method for reading which tag/item is selected by the user.
- (IBAction)popUpChanged:(id)sender
{
self.item = [sender selectedTag];
}
If I choose a menu entry/item the method popUpChanged is executed.
In another class I have a button. By clicking this button the popup menu of the view controller should be set to the item no. 1. Therefore the button-action executes the following line.
[_viewController.popUp selectItemWithTag: 1];
After executing the selectItemWithTag:1 the popup menu is set to the item 1, like expected. The state/item of the popup menu is change, but the button click does not result in the execution of the method popUpChanged?
Can somebody please explain it to me why the method popUpChanged is not executed?
-popUpChanged: is what you set as the action method for the pop-up menu. Programmatically changing the pop-up menu is not an "action" on that pop-up menu. The action is only triggered for user interactions with the pop-up menu.
It is a fairly general pattern within Cocoa that programmatic operations on controls don't go through the same pathways as user manipulations of those controls. For example, a control can be disabled so the user can't change it, but you can still change it programmatically. Or a window's delegate can prevent closing the window in its -windowShouldClose:, but programmatically closing the window with -close is not subject to that (although -performClose: is).
In any case, given that you're programmatically changing the selected item in the pop-up menu, you can programmatically invoke the action method or, more usually, do the same operation as the action method would (e.g. [_viewController.popUp selectItemWithTag: 1]; _viewController.item = 1;).
Or, even better, bind the pop-up button's selectedTag binding to the view controller's item property and a) eliminate the action method, and b) replace your programmatic manipulation of the pop-up with programmatic setting of the view controller's item property.

Simulate a mouse click on a menu item in Cocoa?

For example, I have an NSMenuItem type variable whose title is "History". I need a keyboard shortcut Meta+h to do the same thing as to click this menu item (pop up a submenu list)..
I think there might be two ways to implement this:
1.bind this menu item to a keyboard shortcut, then the Cocoa will fire the execute the action belongs to the item when the shortcut is fired
2.not binding keyboard shortcut to the item. Create an EventHandler for Meta+h, when the event activated, simulate a mouse click on the menu item.
However, both methods don't work for now.
For the keyboard shortcut, there is a method called setKeyEquivalent, but it uses Command instead of Meta as the modifier. And its result is executing the action binds to the menu item, instead of poping up a submenu.
For the simulating of mouse click, in Cocoa's NSMenuItem reference, I haven't see how to send event like click to a NSMenuItem..
Does anyone have ideas about this? Thanks!
[menuItem setKeyEquivalent:#" "];
[menuItem setKeyEquivalentModifierMask:0];
with any of these modifier key masks (combined using the C bitwise OR operator):
NSShiftKeyMask
NSAlternateKeyMask
NSCommandKeyMask
NSControlKeyMask
(BTW, Apple's docs can be really useful!)
Your question is slightly unclear -
If you set a shortcut Cocoa will invoke the command for you and your code will never know whether the user used the mouse or hit the key equivalent.
If you'd like to invoke the same command by some other means (key in an NSView, etc). you'd want to manually call the same method that's hooked up to your menu definition.

NSOutlineView select with the first click

I have an NSPanel with a NSOutlineView to display my data. I want to select a row with a first click inside the NSOutlineView even if the panel is not in focus (i.e. not the key window) I have a delegate that allows selection and I have overridden the NSOutlineView class to override the acceptsFirstMouse: method, but I could not get the first click selection.
I checked the mouseDown event and it fired without any problems (in my class that overrides) when the panel was and wasn't the key window. But when the panel is not key, NSOutlineViewDelegate method shouldSelectItem: is not called.
What am I missing/doing wrong?
You just need to subclass your NSTableOutlineView and override:
- (BOOL)needsPanelToBecomeKey
to return NO.
NSView class reference states:
Overridden by subclasses to determine if the receiver requires its
panel, which might otherwise avoid becoming key, to become the key
window so that it can handle keyboard input and navigation.
Discussion
Such a subclass should also override acceptsFirstResponder
to return YES.
This method is also used in keyboard navigation. It determines if a
mouse click should give focus to a view (make it first responder).
Some views will want to get keyboard focus when you click in them, for
example text fields. Other views should only get focus if you tab to
them, for example, buttons. You wouldn't want focus to shift from a
textfield that has editing in progress simply because you clicked on a
check box.
Source: Apple documentation

use UIMenuController with text

So i would like to use the UIMenuController to display text. i would like to add in help buttons (press a little button and something will pop up describing what something does) that would display either a UIMenuController or something that looks similar to it. it would just display a few lines of text and dismiss when pressed.
it kinda looks like UIMenuController is only meant for button selection. i could just use one button and set the title to the message i wish to display, but am doubtful on how well that would work. are there any other options available?
A UIMenuController takes it content from its menuItems property and the documentation says :
The default value is nil (no custom menu items). Each menu item is an
instance of the UIMenuItem class. You may create your own menu items,
each with its own title and action selector, and add them to the
editing menu through this property. Custom items appear in the menu
after any system menu items.
So you are obliged to use UIMenuItem objects as content for your UIMenuController. UIMenuItem only inherits from NSObject, and stores only a title and an action, both required. This make you unable to use any other kind of data as UIMenuItem.
As it is not an UIView, you can give it a UIButton or a UIImageView.
You could think to override UIMenuController but again it is a direct child of NSObject, so it doesn't have any behavior for customization.
The only solution left to you, is to rewrite your own UIMenuController, deriving it from UIToolbar for example. This would give you more or less the same look, you just have to customize the arrow and the round corner.