Shrink NSScroller of NSScrollView in layer-backed view - cocoa

I'm experiencing a weird problem (Bug?): Say I have a WebView, which will scroll vertically.
I now want to shrink the mainFrame's vertical scroller a little bit, so that its height is smaller than the NSScrollView itself.
The reason for this is that I want to pin two views (on top and on bottom edge) above the webview.
I did that easily in the frameLoad delegate method by altering the verticalScroller's frame (altering origin and height).
It works, but:
However once I set the webView and it's parent NSView to be layer-backed, it stops working, the scroller resets itself to the default position and height.
Now I don't know if this is a bug or not.
Is there any other way I could try to 'inset' the scroller?

Have you tried subclassing NSScroller, setting it as the vertical scroller for your NSScrollView and overriding
-(void) setFrameOrigin:(NSPoint)origin;
-(void) setFrameSize:(NSSize)size;
I assume making the NSView layer-backed causes frameSize to be set again(NSScrollView seems to take quite a bit of control on this because when you create a custom scroller, there is no "clean" way to set an NSScroller as horizontal or vertical other than calling -initWithFrame: with
height > width to automatically set it as vertical
width > height to automatically set it as horizontal
My other suggestion would be, if you want the NSScroller to not fully reflect the size of its parent NSScrollView would you be better off having an NSView as the content view of the webview. And the NSView have 3 subviews. Two views at the top and bottom pinned, and one NSScrollView in the middle. No custom NSScroller necessary in this case.

Related

How Can I Make a View, With a Tab View in It, Scrollable?

I got an NSTabView inside an NSView. That NSView is in an NSClipView, which in turn is in an NSScrollView. It looks like this (NSTabView in green, and NSView in red):
As you can see, the content of NSTabView gets clipped, and no scrollbars appear (since the view doesn't expand beyond the window).
How can I make NSTabView take up as much space as it needs (doesn't clip out), and expand the NSView with it? Then, NSScrollView can deal with the scrolling of the overgrown NSView.
Since my content changes dynamically, I don't want to put in some hard values for the width and height of NSTabView's superview.
This is only part of it; here's now the overall hierarchy looks:
I want the NSTabView's superview to be scrollable instead of clipping out, like this:
The setup I'll describe is for an NSTabView that will pin to the top, left, and right sides of the scroll view. Note the NSTabView could be replaced with any other NSView, the setup is the same.
Starting with you putting a scroll view into the xib/storyboard, you'll have NSScrollView -> NSClipView -> NSView (document view). Constrain the NSScrollView to the edges of the window. Drop your NSTabView onto the NSView instance. Add constraints so that your NSTabView edge constraints equal the NSView and define a height constraint either explicitly or implicitly with other content inside the tab view that defines it.
Personally I like to change the NSView instance (document view) layout to use constraints, by default it uses autoresizing masks and this makes it difficult to keep it in sync with the NSTabView. We want the document view to be pinned to the top, left, and right sides of the scroll view. The size of this view is what determines the scrollable region so we want it to be the same size as the NSTabView so the height of the tab view will determine the scrollable area.
To change this, select the document view, and under the Size Inspector we want to change the "Layout" type to "Automatic".
Lastly, add constraints to the top, left, and right and you should be good to go.
If you want the scroll view to start at the top rather than the bottom, you should subclass the document view and override isFlipped:
class FlippedView: NSView {
override var isFlipped: Bool { true }
}

Window becomes non-resizable after adding Autolayout constraints

I have an IKImageBrowserView inside a NSScrollView.
I added Autolayout constraints to fix the top of the scroll view to the textfield above it and the bottom of the scroll view to the bottom of the window.
The desired behaviour is, that the scroll view (and the IKImageBrowserView with it) will grow and shrink vertically when you grow and shrink the window vertically.
The actual behaviour is, as soon as i added the constraints, the window is no longer vertically resizable.
Why is that? How can I achieve the desired behaviour?
You can examine the constraints by doing:
NSArray* constraints = [window.contentView constraintsAffectingLayoutForOrientation:NSLayoutConstraintOrientationVertical];
NSLog(#"%#", constraints);
You could also do [window visualizeConstraints:constraints] to explore interactively.
See Auto Layout Guide: Resolving Auto Layout Issues – Debugging in Code.

View is moved up when using vertical autoresize

In my custom drawn window I have a NSTextView under which I'd like to have NSScrollView separated by empty space. That's how I've set it up in xib.
In interface builder it looks fine, with nice space between the two of them
But when I run the program, the scroll view gets moves upwards, actually covering the text view:
But when I disable vertical autoresize of the scroll view, everything is working as it should.
text view and scroll view are under NSView so they are siblings to each other.
Most probably it was shortcoming of the system as the scroll view was being completely hidden and so then it was probably moved.
I've worked it out by subclassing NSScrollView and overriding
- (void)resizeWithOldSuperviewSize:(NSSize)oldSize_;
So now I can position the scroll view exactly as I wish.

NSView controls not resizing?

I have a NSView with a NSTableView inside of it.
If the view looks like this:
And the size & position properties for the Scollview (and tableview) look like this:
Then why when I resize the view, does it look like this:
Are my autosizing properties not set correctly? To my understanding they should be?
To make it clearer, you won’t see autoresizing behaviour whilst designing your view in Interface Builder unless the border of the subview coincides with the corresponding border of the superview and Live Autoresizing is enabled.
This behaviour exists because resizing the superview can be used to indicate that you want a certain margin between the subview area and the superview area — for instance, you might have a 100pt margin between the subview’s right border and the superview’s right border, and then increase that margin to, say, 200pt by dragging the superview handles.
Edit: On the other hand, if you want to resize the superview whilst keeping the margins according to the autoresizing mask, you can drag the superview handles whilst holding the alt/option key.
Use Cocoa Simulator (File -> Simulate Interface) in order to test your interface, including autoresizing behaviour.
The table with its scroll view will autoresize to your view's size only if you enter dimensions in by hand in Size info panel. They will not autoresize if you drag view's handles with mouse.

setFrame created an NSView that is 15 pixels smaller in both dimensions than expected

I have a puzzling problem. I have a pointer to a vanilla NSView that was initialized in a nib. I messaged the NSView with:
[myNSView setFrame:NSMakeRect(0,0,816,1056)];
but when I step through the debugger, myNSView has a frame of {{0,0}, {801, 1041}}. The dimensions of the rectangle are 15 less than I've specified! This happens consistently. If I specify two [setFrames] in a row, everything works, but of course that's not the answer.
Why does setFrame fail?
15px is exactly the size of an NSScroller at NSRegularControlSize.
My guess is that you have your NSScrollView configured to automatically hide scrollers.
Try turning off the horizontal and vertical scrollers of your scrollView in the NIB, if that solves the problem, you'll know where to look from there.  It is something related to the clipView of the scrollView autoresizing the documentView. The clipView itself is being autoresized when the scrollers appear; directly after you set the documentView to a frameSize (the 100% setting I'd guess) that requires scrollers.

Resources