Using a round rect button as a badge with a counter - cocoa

I'm using a view based NSOutlineView with two different views (both views are custom subclasses of NSTableCellView). In the top level view I display a badge with a counter. The counter indicates the number of entries on the lower level. The counter is implemented as a rounded rect NSButton, following Apple's SidebarDemo project.
As you can see from the images the behaviour of the button upon selection of the cell is not the behaviour you would expect. My button turns black, while in Apple's sample it turns white. I've tracked down the method that sets this particular behaviour for a button to the setHighlightsBy method:
[[self.button cell] setHighlightsBy: 0];
I use the above in the awakeFromNib method of the custom cell class. In the same awakeFromNib I also set the button's bezel:
[[self.button cell] setBezelStyle: NSInlineBezelStyle];
The bezel style works just fine, but the highlighting seems to be ignored.
Further information I can give: The outline view uses bindings to gets its contents, its highlight mode is set to "Source List".
Why is my highlighting being ignored?

Is your button set up in IB (like in the demo project)? If so, do you have the "enable" box checked in the control section of the attributes inspector? I got the behavior you're seeing if I unchecked that box.

I found the cause of the described behaviour, thanks to the suggestion made by #rdelmar in his answer. The button is bound to the Cell View using the "Argument" binding inspector.
One of the settings there is "Conditionally sets enabled", which was enabled and apparently causes auto-disabling of my button. Once you disable this setting, the problem disappears.

Related

NSToolbarItem and Auto Layout

I have a window with a programmatically created toolbar, which is populated with an NSToolbarItem that has a custom view defined in a xib file. If I check "Translate Masks into Contraints" for the view, then it doesn't resize itself correctly, so its content gets squashed even though I set its compression resistance priority to 750. If I uncheck that on the other hand, then I get a "Detected missing constraints" error at runtime. Also, the content of my view then resizes itself correctly, but it ends up clipped like so:
So it looks like the toolbar sticks my view into a container view and, in order to get the correct behaviour, I should set up layout constraints that allow my view to position itself correctly. However, I don't see how to access that container view... Any idea what I am doing wrong?
I am probably missing something obvious since one would think that this is a very standard setup, but Google didn't come up with anything.
Answering my own question, I opened a support request with Apple, the outcome of which is that this is now being treated as a bug by Apple.
In case anyone else runs into this, a good workaround is to create an intermediate view which contains the toolbar view as a subview with constraints #"H:|[toolbarView]" and #"V:|[toolbarView]", has translatesAutoresizingMaskIntoConstraints=YES and to use this view as the toolbar item. It then suffices to listen for size change notifications of toolbarView and to adjust the size of its superview accordingly.

NSImageViewl Highlighting/Selection

(using Xcode 8b0 on 10.11.5, but the problem also occurs under 7.3)
My app uses an NSColorWell and two NSImageWells to allow users to set a background (colour, image, pattern). The colourWell behaves just fine. The two image wells do not: if you click on one, it will be selected and it is impossible to deselect both (which is what I want if I am using the colourWell.)
NSImageView does not have a deactivate or deselect method. isHighlighted is false even when the imageWell is clearly marked as selected; setting the highlight on either the imageWell or its cell has no visual effect.
The memory of selection persists even between restarts of the app which makes me think it must be stored in the storyboard somehow, only I cannot work out which property is responsible (I've read through the documentation for NSImageView and NSControl without luck).
By employing a ridiculous dance of disabling and enabling my image wells in specific order (you need to enable the one you want to show up as selected first) combined with subclassing NSImageView to override 'mouseDown' so it sends a notification that I capture to trigger the imageWell's action I have got the behaviour I want, but I would really appreciate an easier way of doing this since 'enable/disable controls in specific order' feels like a hack. (So, alas, feels adding the appropriate drag-and-drop support to a NSButton; I really like the 'drop image, have background change' functionality).
Who or what is causing my NSImageViews to be highlighted and how can I take control of this behaviour?
The answer is that this is not a highlight, which is why setting isHighlighted to false does nothing at all. NSImageView has a property named allowsCutCopyPaste- and if this is set to 'true', the imageWell - or the currently active imageWell if you have more than one - will show this 'highlight'.

NSWindow and text smoothing in NSTableView cell view

I'm writing an OS X app and have a problem with font smoothing in separate window.
I have a text field where you put text and suggestion window which pops up with a list of suggestions according to what you wrote. I'm using View-cell based NSTableView to display those suggestions and SFBPopoverWindowController to display it as a "popup" window (tried other classes with the same effect). When rows are first drawn they look fine but after I select them (keyboard or mouse) the font changes it's weight. It's only visual - like you would change smoothing method on the font, not it's bold setting.
"Music note" is the selected cell here
What's even more strange is that after I hide and show the window 3 times everything works fine from that point on.
Again - "Music note" is the selected cell.
The selection is done by overwriting NSTableRowView class and its drawSelectionInRect: method but I tried with drawing everything inside custom NSTableCellView class and it didn't help. The text is standard NSTextField - nothing's changed there.
The SFBPopoverWindow (and it's controller) are created once and reused with styleMask NSBorderlessWindowMask, backing NSBackingStoreBuffered, defer set to YES. The only change in SFBPopoverWindowController I made was to turn off window becoming key window but it doesn't change anything.
It might be related to the way a table view draws it's selected cells (setSelectionHightLightStyle:). Try to set the style to None/ NSTableViewSelectionHighlightStyleNone in your code or IB / Storyboard-file and draw the selection yourself (in a NSTableRowView subclass).
Background: When you use NSTableViewSelectionHighlightStyleRegular or NSTableViewSelectionHighlightStyleSourceList the table view assumes that you use the standard selection behaviour and appearance and does some magic to support that.
==========
UPDATE
==========
My previous answer is still valid but since it only describes the problem and hints at a workaround, I wanted to add a real solution. If you want to use NSTableViewSelectionHighlightStyleRegular for your table view (with custom font and colors), you need a way to 'disable' the system magic that comes into place once your row is highlighted. One proposed solution is to decline the first responder status. It has a lot of drawbacks and isn't a good solution at all.
So, let's have a closer look at the system 'magic' that kicks in as soon as the row will be highlighted: NSTableRowView has a property interiorBackgroundStyle that is – according to the documentation – 'an indication of how the subviews should draw'. Furthermore 'This value is dynamically computed based on the set of properties set for the NSTableRowView. Subclassers can override this value when they draw differently based on the currently displayed properties. This method can also be called to determine what color a subview should use, or alternatively, NSControls can have the -backgroundStyle set on their cell to this value.'
I assume that this style will be handed down the subview hierarchy and causes your text fields to look odd. The system assumes that a highlighted cell has a dark background and changes the interiorBackgroundStyle to dark. Other controls try to adapt accordingly.
I think there are two solutions to this problem:
1) Override interiorBackgroundStyle in your NSTableRowView subclass and return the style that fits your interface (in my case it's .light because my highlight color is a very bright blue). This worked for me.
2) If changing the whole style is a bit too much because you only want certain elements to not change their style, you may only need to adjust these subclasses. I haven't tried this yet.

How can I get a two-row toolbar like in Mail.app and Xcode?

I'm trying to add a "second row" after my NSToolbar in my app, that remains part of the title bar. As an example, Mail has a thin gray divider line below the NSToolbar with some extras items below that. Very specifically, when the window is put into fullscreen mode, that second "row" stays attached to the title bar as it slides down under the system menu bar. Xcode has a similar story.
I tried setting my NSWindow to textured and placing my second row controls directly in the content view of the window. While this mostly looks correct in windowed mode, those controls of course won't appear attached to the toolbar when it slides down in fullscreen mode. So how can I achieve the same behavior that Mail and Xcode do? I've looked at a lot of toolbar customization code but none of them really cover this specific case.
fullScreenAccessoryView is deprecated in macOS 10.10
In order to do this in recent versions of macOS, use the addTitlebarAccessoryViewController method on your NSWindow and pass in a subclass of NSTitlebarAccessoryViewController.
For example:
NSTitlebarAccessoryViewController *accessoryViewController = [[NSStoryboard storyboardWithName:#"Main" bundle:nil] instantiateControllerWithIdentifier:#"AccessoryViewController"];
[self.mainWindowController.window addTitlebarAccessoryViewController:accessoryViewController];
What I needed to do was call [NSToolbar setFullScreenAccessoryView:] on the view below my toolbar. This results in the behavior I was aiming for. See the NSToolbar documentation for this method.
First one is normal toolbar. For second toolbar you can create a separate view of your desired height and add it in the main landing-window.

NSToolbar special area

I like to try to completely take over the area where the NSToolbar resides so I can put my own custom controls, views and background. The advantages of using this area are:
Any sliding panels appear below the toolbar area instead of just the title bar.
In Lion, the toolbar area comes down along with the menu bar when the mouse is at the top of the screen.
I have tried using a borderless window, and implementing my own custom views within it but unfortunately I lose the above advantages as well as having a few other minor problems.
My current method is to use the undocumented method '_toolbarView' with the NSToolbar and add my custom view into its subviews. This works fine as I can turn off toolbar customisation. Unfortunately, the size of the toolbar is initialised with the items within that toolbar. Does anyone know if I can change the size of toolbar without adding a fake ToolbarItem?
Maybe there's also a better way of doing this that I am currently unaware of.
Thanks for any suggestions and comments.
No need to use any undocumented APIs. Just create a toolbar item with a custom view:
- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag {
NSToolbarItem *item = [[[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier] autorelease];
…
[item setView:myCustomToolbarView];
…
}
You can control your custom toolbar’s size using the item’s minSize and maxSize properties (e. g. in your NSWindowDelegate’s -windowDidResize:).
Remember to also update the toolbar display mode so it doesn't show item labels:
[toolbar setDisplayMode: NSToolbarDisplayModeIconOnly];

Resources