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.
Related
I'm working on a Cocoa application that has editable text fields. These text fields need to accept values but don't need to be spell checked or use any of the other options given in the default context menu. I've read that the easiest way to remove the right click/ opt + click context menu is to override the function:
rightMouseDown:(NSEvent *)
I've done this in a custom NSTextfield class. This fix blocks the user from right clicking when the text box is enabled and unselected, but as soon as the user double clicks/enters the text field for editing the default right click functionality returns.
Is this because the firstResponder switches to a class in the inheritance chain upon trying to edit the field? Is this approach the right way to disable all context menu functionality for this NSTextField?
Thanks!
When a text field is editing, the actual first responder is the "field editor", an NSTextView supplied by the window. The field editor always uses the control on whose behalf it is acting as its delegate.
So, in order to influence its behavior with respect to the contextual menu, you need to use a custom subclass of NSTextField. (I guess you already are to override -rightMouseDown:.) Then, implement the text view delegate method -textView:menu:forEvent:atIndex: and return nil (i.e. no menu).
This is kinda long but I want to give as many details as possible.
I have created a status bar app. One of the things I've done is made it to where there is a "Settings" menu item that if you click on, an NSWindow pops up with 5 different buttons -- these buttons are tied to their own custom NSViewController so that if you click them, the View Controller changes, but the window remains the same, just like any other StatusBar app.
On one of the view controllers is a popup button with several user selectable options. If I add a button to the specific VC (view controller) and link that to an ibaction that pulls the selected index of the popup button, it works just fine (i.e. I select item 2, it logs item 2).
Now here's where things get. . . odd. I've created a submenu that would in theory allow the user to quickly change the selected item of the popup linked to my custom view controller. Think of this submenu as being labeled 1-4 and clicking one of those items would change the index of the popup button, however every time I try this and follow it up with a NSLog to ensure the button has changed, it ALWAYS reads zero, in other words, it NEVER changes.
Here's what I tried.
Just like with every other view controller I've ever used, I create a new object of my view controller (alloc, init), and reference the popup button object that i've created as a property. This compiles just fine, but returns only zero no matter what is selected.
I've tried calling the method that I know works (the button that is on the view controller containing the popup), but again, this returns only zero no matter what is selected.
Any advice would be greatly appreciated.
tl;dr: can't change a popupbutton on a view controller from the app delegate or nsstatusmenu item, it just always returns zero.
EDIT: I have found a work around since I can communicate to my app delegate just fine, I created an int property and set it to zero. From there, whenever my popupbutton on my VC changes, I change the value of the app delegate int property and just ensure that whenever the nib launches, it set's the selected item to the app delegate property. I feel there has to be a more straight forward way to just get the value of the popup and change it from the app delegate.
EDIT 2: Some code as requested. I realized I needed to point the the view controller by using initwithnibname from the app delegate and then load the view. Doing so allows me to pull the first object in the popup button, any subsequent changes are not recognized unless I do so via my test button on the view controller itself. Also, I'm adding values to my popup in my awakefromnib in the view controller.
searches_VC = [[Searches_ViewController alloc] initWithNibName:#"Searches_ViewController" bundle:nil];
[searches_VC loadView];
NSLog(#"Selected Title: %#",[[searches_VC profilePopupOutlet] titleOfSelectedItem]);
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
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?
Having wrestled with NSPopUpButton in a previous question here I am now trying to place a NSPopUpButton inside an NSToolbar. Essentially I want to create something similar to what XCode has by default on the left hand side of it's toolbar. E.g. a pop up button with an action button next to it.
I have seen a method that show's a programmatic way of creating an NSPopUpButton and then adding it to an NSToolbar, but then I can't work out how to do all the Binding stuff that was so handy last time.
Interface Builder hasn't been very helpful, so any help gratefully received.
P.S. Could I solve this by creating a custom view (containing an NSPopUpButton with the usual bindings) and then adding the custom view to the toolbar?
It's actually pretty easy to do what you want here. In Interface Builder, switch to the tree view (the second button on the View Mode segmented control). Expand the window and the toolbar. Then, from the library, drag a popup button onto the toolbar. Interface Builder will embed a new popup button in a custom view for you automatically.
To actually put the button on the toolbar, double click on the toolbar in the window. This will bring up the customization sheet. You can drag the popup button to the desired location on the toolbar.
If you wanted to do this programmatically, you would create a custom view containing your popup button. Then, you'd need to assign it to a new outlet so you can refer to it programmatically. In the toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar method, you would create a new NSToolbarItem per usual, and call setView: to assign the custom view to the toolbar item.
Old post, but note you can also double-click the toolbar in the window and drag straight into the "Allowed Toolbar Items".
You will want to open up the toolbar view anyway so you can drag things in or out of the default toolbar items.