NSWindow and text smoothing in NSTableView cell view - cocoa

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.

Related

How to display elements inside NSCollectionView with various shapes

I am a rookie Cocoa guy. I need to design and implement a view which will show collection of labels on Mac OS using Xamarin. These labels will have a text and color associated with them. When shown inside the view, label should expand till it covers whole text and it will be shown with background and foreground colors.
I have attached the picture of this user control on Windows, you can see that labels inside the StackPanel are expanding till they cover the whole text. Hope this gives better idea about my ask.
The $64,000 question is "are these labels controls?" In other words, do you expect the user to click on these to do something, or are they just for display?
If your answer is "just for display", the solution is super simple: Use an NSTextField and programmatically add attributed text (NSAttributedString) to it. Attributed text attaches display properties to runs of text within the field; properties like "background color".
If you want these to be buttons that you can click on, then things get a lot more complicated.
Since you apparently want the button layout to "flow", you might look into imbedding buttons (well, button cells) into an NSTextField using attachments. This is normally how non-text content (say, an image) can be inserted, but with some fiddling it can actually be anything a control cell can draw. See How to insert a NSButton into a NSTextView? (inline).
Warning: this is not a "rookie" topic and will involve control cells and custom event handling.
If I were doing this, I'd probably just create NSButton objects for each label (choosing an appropriate style/look like NSRecessedBezelStyle), create a custom subclass of NSView to contain them, and then override the layout method to position all of the buttons the way I want.
To be thorough, I'd also override the intrinsic size methods so the whole thing could participate in auto-layout, based on the number and size of buttons it contained.

NSOutlineView - Disclosure Triangle Interferes with Highlight Rectangle

I have an NSOutlineView with the highlight mode set to source list and the menu property set to a non-empty menu (I figured this last consdition is necessary to have the outline drawn).
When I right-click on a row representing an item that has children (i.e., is expandable), The blue outline around the cell has a slightly different color right above and below the disclosure triangle:
(This happens for every node, at every level of the hierarchy)
Additional information: My outline view is view based, does not use bindings (view controller is the delegate and data source).
Me cells are custom, designed on the storyboard, nothing fancy (icon image view and text field).
What can be causing this?
EDIT: The issue only appears with the round-cornerered highlight rectangle of the "Source List" highlight mode. With the straight-cornered rectangle of the "Regular" highlight mode, the stroke color is even all along.
When using the Source List style, your outline view has an NSVisualEffect view behind it, which causes the list to be composited differently. What you're seeing seems to be a bug with the vibrancy appearance. You could perhaps try to work around it by reducing the frame of the outline cell by overriding frameOfOutlineCell.

NSLevelIndicator fading when not highlighted

When the NSLevelIndicator (in star ratings mode) is interacted with it shows placeholder dots for where there are no stars. These dots however fade once the interaction with the NSLevelIndicator is seized. This brings with it obvious UI problems because the user is no longer aware that there is a NSLevelIndicator to be interacted with. Is there any way to force the continuous highlighting of the indicator so that the dots do not fade?
I found an answer here: http://www.cocoabuilder.com/archive/cocoa/202167-rating-style-levelindicator-not-showing-dots.html
Basically the control's cell needs to have its 'highlighted' property set to YES for the dots to show. Their solution involves subclassing NSLevelIndicatorCell; I found a simpler way that seems to work fine, which is to set the control's cell's highlight to YES when it's initially created, and after it's clicked and sends its action message. (You have to keep highlighting it because it loses the highlight after each click for some reason.)

Using a round rect button as a badge with a counter

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.

Validating a drag to an NSCollectionView isn't reflected visually

I have an NSCollectionView that I want to accept items dragged from elsewhere in my application.
I implement collectionView:validateDrop:proposedIndex:dropOperation: and collectionView:acceptDrop:index:dropOperation: in the collectionview's delegate and register for the appropriate dragged types. Both methods get called fine when I drag the appropriate types, but I don't get a blue focus ring over the collectionview indicating a valid drag.
Have tried both the collection view and its containing scroll view on Default and External settings for the focus ring. Both are just the standard non-derived Cocoa classes. Wondered if there was anything else I should try. Surely it isn't necessary to subclass NSCollectionView for this?
Thanks
Chris
Focus rings are not typically the correct way to provide feedback about drag destinations. Every view does it slightly differently. NSTextView shows the insertion bar. NSTableView shows a blue line in between rows for Before drop operations, and shows a bezel around the row for On drop operations. (See NSTableViewDropOperation)
NSCollectionView shows a "gap" between existing subviews to show where the items will be dropped for Before drop operations, and it will set the selected property on NSCollectionViewItem to YES for On drop operations. (Note: NSCollectionViewItem doesn't do anything by default to visibly represent the selected property. You must implement that yourself.)
Since NSCollectionView's feedback uses existing subviews only, it appears there isn't any feedback at all for empty NSCollectionView's. You would need to subclass to provide this behavior yourself. You could also file a bug to request that NSCollectionView do this itself.

Resources