Making Autolayout respect NSWindow's maxSize.width

So, I have some constraints set up in IB. I normally don't do autolayout, but all seems to be working nicely. The only thing is this, I set my window to have a max width of about 800....and....


I have a NSTextfield (label) in the window. If the text being displayed gets to be too long, the window's width grows automatically (so the label doesn't truncate). I was a bit surprised to see that, because you don't really set any constraints between the views and the window itself, and I figured that the constraints I set would play inside the size of the window.


Now that I see that the window grows with the label, I realize that this behavior could be useful, but I'd expect that once the window's max width is hit, the window will stop growing, and that the label will truncate (the label is set to truncate in IB and allow expansion tool tip is also checked).


How do I tell autolayout to respeck my window's maxSize?

Answered by QuinceyMorris in 260421022

There is a constant NSLayoutPriorityWindowSizeStayPut, whose value is 500. You can control what autolayout does to your window size by setting item priorities relative to this. If I have this the right way round, constraints on objects inside the window will not force the window to resize if they're less than 500.


There are a couple of other constants that give you the priority at which window resize-by-dragging interacts with the layout of the contents. You might have to play around a bit to find exactly what level to set the internal priorities too.


Unfortunately, it's all a bit inscrutable, because you're never quite sure that you've tested all the intermediate cases, but it should be possible to find something that works by experimenting.

Well, I can subclass NSTextField and do this:


-(NSSize)intrinsicContentSize
{
    NSSize intrinsicSize = [super intrinsicContentSize];
    CGFloat windowMaxWith = self.window.contentMaxSize.width;
    if (intrinsicSize.width > windowMaxWith)
    {
        intrinsicSize.width = windowMaxWith;
    }
    return intrinsicSize;
}


And this works. But now the user cannot make the window smaller. That is, constraints prevent me from shrinking the window, which I don't like. I'd like to give users the freedom to shrink this window (until min size is hit) and just have the label truncate more.

Accepted Answer

There is a constant NSLayoutPriorityWindowSizeStayPut, whose value is 500. You can control what autolayout does to your window size by setting item priorities relative to this. If I have this the right way round, constraints on objects inside the window will not force the window to resize if they're less than 500.


There are a couple of other constants that give you the priority at which window resize-by-dragging interacts with the layout of the contents. You might have to play around a bit to find exactly what level to set the internal priorities too.


Unfortunately, it's all a bit inscrutable, because you're never quite sure that you've tested all the intermediate cases, but it should be possible to find something that works by experimenting.

I lowered the horizontal compression resistance priority to 499 and now the window does not grow when the label's text grows. The label instead truncates, and the window can be resized based on its min and max size values.


I think it may be desirable to allow the window to grow automatically with the content up to the max size though (and then the label can truncate once max size is hit). I'm sure I could achieve this by modifying the constraint as things change, but I don't know if it's worth the effort.



>Unfortunately, it's all a bit inscrutable,


I agree. Surprised this isn't just a flag on NSWindow like containsConstraintsToWindowsMaxSize; or something, instead of the priority thing.

Making Autolayout respect NSWindow's maxSize.width
 
 
Q