NSOutlineView, expansion and collapsing can cause cells to clip content - macos

I am experiencing weird visual artefacts during rapid expansion and collapsing of a view based NSOutlineView's groups. If a group is expanded, and I double click (collapse followed quickly by expansion) the expand arrow, the content is clipped.
My cells contain a simple image and a label to the image's right, and on rapid expansion, the textfield is clipped in some cases, and squashed in other cases, as though the cell when being collapsed gets a zero width frame and doesn't re-expand.
I have altered the auto-resizing masks for the cellView, the outlineRowView, the column, but no combination appears to change the behaviour.
Has anyone come across similar strange behaviour?

Have you tried calling setNeedsDisplay:YES on the views after they have been unfolded?
This will tell the view to redraw itself.

Related

How can I make a UITextField with padding on the left of the content?

UITextField shows its content text bang against the left edge of the field, which is ugly and can be hard to read if the field has a visible border. UITextView, on the other hand, automatically has padding (blank space) around the text. I examined and experimented with all the UITextField properties but I don't see any way they can be used to get padding around the text.
I also tried calling drawText(in:CGRect) on the text field but it had no effect. But I'm not sure what CGRect is needed in that call. I tried different border styles including .none. I also tried making a blank UIView and assigning that to the text field's leftView property but that also had no effect. And I tried doing these things in viewDidLoad, viewDidAppear, and at the point where I'm writing the text into the textField. The text shows in the textField as expected but none of these other things seem to affect the textField's appearance in any way. It seems to me lots of people must show text in a UITextField and somehow get it padded on the left so I'm misunderstanding something but what???
The following works for a field called "textField". It inserts padding by shifting the left side of the field's content 8 pixels right relative to the left edge of the textField:
textField.layer.sublayerTransform = CATransform3DMakeTranslation(8, 0, 0);
This is given in an answer to a different question by user Dhiru (reputation 1285) in Nov. 2016. Thank you Dhiru!
I have to add that I am not familiar with either sublayerTransform or CATransform3DMakeTranslation so I can't be sure that this doesn't have some side effect that isn't immediately obvious. I'm a little worried that it's called "3D transform" whereas there is nothing 3D about my application. But at least for now this seems to answer the question.

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.

Auto layout NSWindow respects minimum size in IB simulator, but not when running for real

I have a window I'm setting up with auto layout. There is a view in the middle of the window that contains three controls, and I would like the window to refuse to resize horizontally smaller than the intrinsic size of those three controls.
The outer buttons both have horizontal space constraints to "stick" them to the outside of their superview, and the checkbox in the middle has a horizontal space constraint sticking it to the left side of the "Sync text" button. There is also a >= constraint between the "Sync outline" button and the checkbox, to make sure they don't overlap, but the checkbox prefers to hang to the right. All these constraints have a priority of 1000. The window itself has no minimum size specified.
When I use the "Simulate Document" command in Xcode, everything works as I'd expect, and the window won't let you size it smaller than in the screenshot above. However, when I run my application, the window does allow resizing smaller than that width, so that the buttons start to shrink and eventually the controls overlap each other. I'm not implementing any of the size related window delegate methods, so I don't see any place in the app's code where it might be influencing the resizing.
Any ideas on what could be causing this difference in behavior?
OK, I finally figured out what the heck was going on here. It turns out the problem was that I was implementing the -splitView:constraintMinCoordinate:ofSubviewAt: delegate method (as well as the maxCoordinate one) to restrict the size of the split subviews in the vertical direction. Yes, restricting the vertical resizing of the split view affected the horizontal layout of the buttons.
It appears that what happens is that, if you implement those delegate methods, NSSplitView reverts back to using autoresizing masks to layout the subviews rather than auto layout constraints. Since the view containing those buttons is no longer participating in auto layout, the buttons smush together when you resize the window small. In the simulator, the split view doesn't have a delegate set, so all the auto layout stuff works fine in that environment. Note that merely having the methods implemented is enough to trigger this, even if they just return the proposed coordinates unchanged.
The solution ended up being quite easy, which was to delete the delegate methods and replace it with a vertical constraint on the subview to restrict its size instead.

How do you use NSScrollView with auto layout?

Ok. I've been at this over and over. I've seen blogs and cocoa dev threads.
I've seen Kyle Sluder's proposed solution, but have yet to find a solution that really works.
How can you position subviews of an NSScrollView with auto layout?
Is it just silently broken ?
Nothing seems to work.
Ok, old question, but this particular issue is a personal bugbear of mine so I'll answer it anyway!
The first thing to note is that an NSScrollView contains an NSClipView, which itself has a view outlet called documentView. These are all added for you when you drag a new scroll view into your storyboard or nib file. By default, the document view is an NSView called simply "View". If you're using a custom view, you can just select this and set its type in the inspector on the right to whatever you want. Otherwise, you'll be adding subviews to it.
The big thing that is easy to miss here is that, by default, the document view has its layout set to 'Translates Mask Into Constraints'. This is fine if the content size will never, ever change, and if that's the case you can simply set the frame of the document view to whatever you want and leave it at that. If you want it to automatically resize itself to fit its content however, there's a few things you'll need to do.
First off, that document view needs to have a completely unambiguous size. If you're using a custom view, I'd recommend giving it an intrinsicContentSize. You should also set 'Intrinsic Size' in IB's inspector to 'Placeholder' and give it a suitable value, or you'll get a bunch of autolayout warnings. If your document view gets its size from its content, all of the subviews must be linked in an unbroken chain from top to bottom, and from left to right, such that the content knows exactly how big it ought to be. This is quite an art in itself, so I won't go into it. A simple example where you have only one subview would be to pin its top, bottom, leading and trailing constraints to its parent, but as noted above if you're doing this, you might as well just set the type of the document view.
Now the fun bit. Select your document view and set its layout to 'Automatic'. Next, add top, bottom, leading and trailing constraints to its superview with a suitable value. I'm using zero, but you might want a small border. Finally, select the TRAILING and BOTTOM constraints you just made and set them to '>=' (greater than or equal) and a priority of 500 or less. The priority is very important, as it has to be less than the priority that the clip view uses to determine its own minimum size. Too high and the clip view will be forced to remain larger than its content, making it impossible in turn for the scroll view to be smaller than its content, rendering it useless.
The technical details aren't important. Just remember to set the document view to layout: automatic, pin all edges, and make the trailing and bottom constraints >= and priority 500.
Note that this will cause your content to hug the top-left corner.
Have you tried setting the document view's setTranslatesAutoresizingMaskIntoConstraints to TRUE?
[_scrollView.documentView setTranslatesAutoresizingMaskIntoConstraints:YES];

Unexpected behavior using Autolayout with NSSplitView

I have the following implemented with springs and struts along with several NSSplitViewDelegate resizing and constraint methods and it all works as desired. I am now trying to adopt autolayout for this same scenario by replacing all of the setFrame messages and NSSplitViewDelegate methods with proper autolayout constraints.
My main window's view contains a vertical split view (I call OuterSplitter) with the top, bottom, left and right leading and trailing space constraints set to zero for OuterSplitter to its superview.
The right pane of OuterSplitter contains (among a few other things) another vertical split view (I call InnerSplitter) which also has the top, bottom, left and right leading and trailing space constraints set to zero for InnerSplitter to its superview (i.e. OuterSplitter's right pane).
I have set nominal minimum width constraints for OuterSplitter's left pane, and also for both the left and right panes of InnerSplitter.
When the main window is being resized, the desired behavior is for all (or most) of the expansion and contraction to be applied to InnerSplitter's left pane, unless one of the minimum width constraints takes effect. Therefore, I have set the split view Holding Priority for OuterSplitter's left pane to 260 (highest) and 250 for the right pane. Also, the Holding Priority for InnerSplitter's left pane to 245 (lowest) and 255 for the right pane.
I have watched the video for session 232 from WWDC 2012 and thought I was on the right track. My autolayout constraints work mostly as desired, but there is one very strange behavior that does not occur with my springs and struts version.
If the split bar of the InnerSplitter is as far right as it will go (InnerSplitter right pane is at its minimum size) AND the OuterSplitter split bar is NOT as far left as it can go, then if you try to drag InnerSplitter's splitter bar farther to the right, then unexpectedly the OuterSplitter's split bar moves to the left causing the InnerSplitter's Left pane to grow and OuterSplitter's left pane to shrink. My expectation is that no resizing should take place in that case.
It is possible to stop the OuterSplitter's split bar from moving when tugging on the InnerSplitter's split bar that is pinned to the right? If so, what constraints should be added? Or are some of the NSSplitViewDelegate methods still required? Thanks.
BTW, I'm using Xcode 4.6.3 and targeting OSX 10.8.
I had the same problem and got around it by using NSViewControllers within each split view pane so that I didn't directly have split views embedded in split views. It's more code and more complex but it does seem to work.
I never found a solution for when split views are embedded in split views so I'll be interested if anyone has an answer.
To fix this, you could add an explicit width constraint on -mouseDown: in the NSSplitView before calling through to super, then remove it immediately after.
Also, it looks like this is fixed in the 10.11 beta!

Resources