NSPopUpButton in a toolbar with fixed image similar to Pages.app UI - objective-c

The toolbar in Pages (Numbers, Keynote) has a NSPopUpButton with a fixed image (irrespective of the menu that is selected). Using view debugging it turns out that this is a standard NSPopUpButton with a fixed image.
According to the NSPopUpButton docs regarding setImage:,
This method has no effect.
The image displayed in a pop up button cell is taken from the selected
menu item (in the case of a pop up menu) or from the first menu item
(in the case of a pull-down menu).
This means that this standard NSPopUpButton has non-standard behaviour.
How could this be implemented? Because setImage: has no effect, subclass the NSPopUpButtonCell and overriding -drawImage:withFrame:inView: has no effect (because it is never called).

The problem here is confusion: Pull down menus display their menu's first menu item as the image/title.
Don't use -setImage: to display a static image in a -pull down menu. Instead set the first element of the menu to be the image/title that you want to display and add the selection options as additional menu items.
#Volker is absolutely correct. This is the built-in behaviour but you set the image by setting the first element in the menu not using setImage: or setTitle:.
Example, https://github.com/danieljfarrell/Toolbar-with-Pull-Down-Menu

Related

How to display show/Hide button in highlight regular mode of NSOutlineView?

How to display show/Hide button in highlight regular mode of NSOutlineView?
I have a grop item at the top of NSOutlineview. I try to display show/hide button in that group item, but I can't find any method to do it. The source list mode can display it but regular mode doesn't.
Is it possible to display show/hide button in highlight regular mode of NSOutlineview?
thanks for helping
This behavior is specific to the source list appearance. There is no public API for getting around this, as it's an intentional enforcement (on Apple's part) of standardized appearances. You could dig around in the headers to look for a way to "hotwire" things, but use of private API bars you from distributing your app through the App Store.
The easier (non-private-API-using) route is to create your own cell view with a borderless button with show/hide title. Use a mouse tracking area (see NSTrackingArea) on the cell view (the superview of your button) to set the button's alpha (via its animator) to fade the button in/out on mouse in/out. Your button would tell the outline view to expand/collapse its cell view's represented item (the easiest way would be to define an outlet to the button via your custom NSView cell view class and configure the button's target/action when the cell view is created for the item).

How to create the NSMenuItem view for a menu item with an embedded NSProgressIndicator?

I would like to create a menu item with an embedded NSProgressIndicator, similar to the "Wi-Fi: Looking for Networks…" menu item of the Wi-Fi status menu:
I think that I will need to use the setView: method as discussed at: Views in Menu Items. However, when I call setView: and pass an NSProgressIndicator, only the NSProgressIndicator is displayed.
How can the custom menu item view be created to get a similar result as the "Wi-Fi: Looking for Networks…" menu item of the Wi-Fi status menu?
As noted in the document to which you linked:
A menu item with a view does not draw its title, state, font, or other standard drawing attributes, and assigns drawing responsibility entirely to the view.
So, if you want your menu item to look like a normal menu item plus some other stuff, your view has to draw the normal menu item features in addition to the other stuff. So, you could set the menu item's view to a custom view. The progress indicator would be one subview of that custom view, but you would need other subviews for the other features. For example, a text field for the text of the menu item and an image view for a state indicator (if your item shows state).
You'll have to draw highlighting as the item is selected or tracked. You'll also have to do mouse tracking. Apple has some sample code which demonstrates various parts of this:
MenuItemView
CustomMenus
GridMenu

Disclosure button displaying a menu

Please give me an advice how to implement this kind of disclosure button as on my screenshot - a disclosure "arrow down" button displaying a menu on click:
I've tried two approaches, using NSPopupButton and NSButton with disclosure style and manual menu displaying:
NSPopupButton keeps displaying default value text and can't be resized in Interface Builder to a narrow size.
NSButton displays a menu, but it's obviously misplaced to the point where I click the button, not at the bottom edge. I'm using the following code:
- (IBAction)handleShowMenu:(id)sender
{
[NSMenu popUpContextMenu:profileMenu
withEvent:[NSApp currentEvent]
forView:sender];
}
So what's the right way to display such a menu?
I've managed with it! The correct setup is to use NSPopupButton with "No Arrow" and "Disclosure" bezel style, "Momentary Push In" type.
Changing the bezel style of your popup button to "Textured" and the arrow to "Center" will give you the appearance of your first screenshot. If you don't want the title of the selected item to appear, you also need to set the "Position" to "image only" (the white square).
Edit: I tried this in IB 3 and only simulated the interface. It seems that the "Textured" style looks different in Xcode 4. "Round Textured" is close, but it doesn't center the triangle horizontally.

Is there a way to control the NSMenuItem item that is initially highlighted when opening a menu?

I'm working on the details of a symbols pop up button, similar to what Xcode 3 at the top of its editor window.
My controller object is the delegate of the NSMenu that is shown when the NSPopUpButton is shown. I implement the two methods numberOfItemsInMenu: and menu:updateItem:atIndex:shouldCancel: to populate the menu right before it's about to be displayed.
However, the title and image of the selected NSMenuItem have to change each time the user changes the selection in the editor NSTextView, or makes changes to the text; just as is the case with Xcode.
The problem I'm having is when the user goes to click on the NSPopUpButton to display the NSMenu, the selected NSMenuItem and the item that should be selected do not match up, since the menu doesn't have the proper number of items yet.
I'm wondering if there is a way to control which NSMenuItem is initially highlighted and tracked when the user clicks to open the menu. As it stands, the first item it always highlighted and tracked or, if the user had previously selected a item, that item is highlighted and tracked.
I tried explaining as best I could, but here is a image illustrating my problem:
I want the highlighted item to be the same as the selected item when the user opens the menu. Any ideas?
I would use a NSPopupbutton - it can do what you want. maybe you even hide it?
I am not very sure that I understood your problem but If we can add tags to these menu Items.
e.g.
[mMenuItemOne setTag : 1];
[mMenuItemTwo setTag : 2];
[mMenuItemThree setTag : 3];
[mMenuItemFour setTag : 4];}
we can select any Menu item using
[_popUp selectItemWithTag: _selectedItem];
Just a hint not a full solution.
Try to post an NSMouseMoved event to your app right after the menu shown.
Main problem is here to detect the position of the item you want to be highlighted.
Just a starting point.
Have you tried this NSMenuDelegate method:Handling Highlighting
– menu:willHighlightItem:
NSMenuDelegate Protocol Reference
Also you can store the NSMenuItem index in some var to keep track of the selected item for later use.
I'm not sure, do you want to move the mouse selection highlight (the blue stuff) or the checkmark?
In general, the checkmark is the thing you want to change. You can do so from your validateMenuItem: method (or at any other time if your item is set not to take part in validation) using the -setState: method.
The blue highlight is an indicator of the user's keyboard input or mouse location, and you should not mess with it. Changing it does not make any sense, as it would be changed back the moment the user moves the mouse even a single pixel.
That said, you can set the selectedItem of the NSPopUpButton, which will cause the entire menu to be moved so the selectedItem is under the mouse (assuming the mouse just clicked the popup button).
If your menu delegate method is called after the pop up button has decided what item to select, you can't use it. Instead, you could probably set the selectedItem and menu of the popup button from a NSPopUpButtonWillPopUpNotification handler.
If that is also called too late, you'll probably have to subclass NSPopupButtonCell and do it in an override of -attachPopUpWithFrame:inView: (I think that's the spot that should also work when you don't click and just hit the space key while the popup button is selected).

NSCollectionView as NSPopUpButton "drawer"

I would like to have something similar to the "List mode" of the stacks in the Dock.
But it should have the behavior of NSPopUpButton, in terms of displaying the selected object still, when the "drawer" is collapsed.
Each row should contain an image and to text columns.
How would you realize this?
Maybe subclassing NSPopUpButton, to display a CollectionView?
Or having an ordanary button and attaching a window containing a CollectionView to it, when clicked?
Oh and this up and down bars, instead of scrollbars on the side - how's that done?
Why not use a regular NSPopUpButton whose menu assembly is replaced with subclassed NSMenu/NSMenuItem that draws things the way you want? You get all the scrolling behavior for free.
If you insist on using NSCollectionView, however:
1 - Don't subclass NSPopUpButton if you're planning on popping up anything other than a menu. It's built to display a menu. Just use a regular NSButton and manage its -state (NSOnState while the collection view is displayed; NSOffState otherwise) manually.
2 - You could show a borderless transparent window (many examples available online) with a standard collection view / scroll view assembly minus the scroll bars. The borderless window could host the up/down areas (which can be simple views with NSTrackingAreas to detect mouse over). These areas could manually scroll the NSScrollView a bit every n milliseconds using an NSTimer while hovered.