How to fix NSTextView's weird sizing inside a magnified NSScrollView - xcode

I have an NSTextView inside NSScrollView/NSClipView, the usual setup. When I magnify the scroll view with [NSScrollView setMagnification:...] and resize the window, the width of text view's frame gets constantly larger, regardless of whether I stretch or shrink the window.
If the scroll view is not magnified, text view behaves normally. I have tried removing constraints and disabled subview autoresizing, but nothing helps. Whenever i set any sort of magnification, text view size changes on every call to resize. If the magnification is under 1, it shrinks.
Any bugs in TextContainer shouldn't make it wider either, as I've set textContainer.widthTracksTextView = false;
I am trying to keep the textContainer centered in my NSTextView by setting insets to it, but it gets impossible with the varying sizes. I've gone through my code and nothing should make it resize. Is this a bug or does the setMagnify: cause problems with constraints or some other math in LayoutManager?

For anyone trying to figure this out:
This is caused by a minimum width constraint for the magnified view, or any of its subviews. Seems like a bug, as I can't wrap my head around how this would be intended behaviour.
Just remove the >= constraint and do something to limit the size in run-time if needed.

Related

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.

Adding an NSView at top left and filling window

I am programmatically adding an NSView to an NSWindow. I want to have the new view appear at the top left and fill the entire window.
I have been messing around with autolayout and manually setting frames and autoresizing masks (not at the same time, obviously), but I'm getting nowhere. Either the view doesn't resize at all, or it resizes proportionally (using autoresizing masks) but it won't fill the entire space. I must be missing something basic.
I am new to Mac Cocoa, although I'm quite experienced at iOS Cocoa Touch. On iOS, CGPoint 0,0 is top left. I assume on Mac from what I'm seeing that it's bottom left. How do you figure out what top left is?
Using the autoresizing mask like below should do the trick:
view.autoresizingMask = NSViewHeightSizable|NSViewWidthSizable
Absence of other resizing masks makes the margins inflexible. So whatever is the current margin (which is zero on all sides, when you add it to the window - Assuming the view occupies the full window frame when being added) is retained.
And top left would be the window's content view's height.
[[self.window.contentView frame].size.height]
I guess you already knew that. :)

How to stop interface builder resetting user constraints on UIScrollView?

I'm having trouble getting a UIScrollView to respect the constraints I put in interface builder.
All I need to be able to do is set the content size of the scroll view from within IB.
The UIScrollView contains a single UIView.
Constraints on the UIScrollView:
Constraints on the UIView:
I've read through the documentation, and so have set things up as follows:
the UIScrollView has constraints pinning it to its superview, thus defining its size from outside
the UIView (content) has a fixed size (through width and height constraints)
the UIView is pinned to the UIScrollView, thus defining the content size
However, IB won't let me enter these constraints. If I change the 'Bottom Space' constraint between the view and the scroll view, shown in the image as -2196, to 0 (thus pinning the lower edge of the scroll view), then the 'Top Space' constraint resets to a non-zero value. The same happens in reverse. (I haven't yet tried in Xcode 5, which has a far saner approach to invalid constraints in that it doesn't just throw yours away when it feels like it.)
What am I missing?
Every time I've tried to do something even mildly sophisticated with constraints in Xcode 4's Interface Builder, I've eventually given up and either written the constraints in code or switched back to springs'n'struts and layoutSubviews (usually after crashing Xcode a few times).
That said, there is another approach to laying out a scroll view with content in IB. Just make the scroll view as big as its content size, and rely on the view controller (or some containing view controller) to resize the scroll view (or its superview) and let the constraints shrink down the scroll view's frame at runtime. The window's root view controller will always set its view's frame to the screen size, regardless of its size in the nib or storyboard, and that resizing flows down the view hierarchy.
I described this approach in more detail in this answer.
If your scroll view's content size is really supposed to be 2196 points tall, this probably won't work so well. I don't have anything better to suggest in that case.

Height constraint prevents resizing of NSWindow

I'm trying to get the hang of NSViewConstraints. I like them a lot; they make a lot more sense to me than the previous system.
I have a window, a 22 pixel-tall subview spanning the top of it, and a tabless, borderless NSTabView beneath it. The goal is to have the top subview never resize its height.
Without any constraints, auto formatting takes care of most of the work. The only trouble is resizing the window causes the upper subview to change its height. My seemingly logical response was to pin the height at 22. I left margin constraints alone, since the NSTabView was already handling resizing well.
By pinning the height of the upper subview, the window now refuses to resize vertically! I don't see any documentation anywhere saying this is expected or the logic behind it. I've messed with various constraint configurations to overcome it but nothing works.
Two questions:
Why is pinning the height of one subview freezing window height resizing? What is Xcode's logic?
What constraint setup will achieve the desired positioning?
I just tested creating a window as you describe, and pinning the height of the 22px view. This created one user constraint on the view for it's height.
However, it also created 2 constraints on the parent view (the window's content view), one for the Top Space to the 22px view, and a second for the Bottom Space to the 22px view. These constraints are what's preventing you from resizing your window. You should select the second constraint and delete it (but leave the first one in place as it's fine).

Why would NSWindow with NSTableView not resize?

Here is my IB setup:
http://img145.imageshack.us/img145/5929/picture1gxr.png
When both NSScrollView and NSTableView are set to autoresize and autofill (all the arrows in the Autosizing section are checked) my window does not resize. Actually it resizes, but by a pixel, as if it remembers that it is not supposed to resize after I start dragging the corner. If I uncheck the autofill arrows (disabling NSViewWidthSizable and NSViewHeightSizable) on the NSScrollView, the window resizes fine, but of course, the scroll view does not resize with it.
The weird thing is that in the situation where the window is "rigid" if I resize one of the NSTableView's columns beyond the view (thus causing a horizontal scroll bar to appear), I can resize the window but only until it reaches the size big enough to accommodate all the columns and then becomes rigid again.
Maybe you have set a fixed minimum/maximum size for the window?
Is this a feature or bug of BWSplitView? What if you make it an NSSplitView?
If it turns out to be a bug, you should report it.
Ah, I've reverted to my last good commit and rebuilt the view hierarchy and everything worked. It is probably a bug in BWSplitView, but I can't reproduce it anymore, so can't report really.

Resources