Add vertical scroll bar to document-based Mac app's window - cocoa

I'm looking at MyDocument.xib in Interface Builder and I can't for the life of me find how to add a vertical scrollbar.
It's set to 768x756 minimum size and 768x1024 maximum size. It starts out at minimum size (to support schools that use older MacBooks with 800px high screens), but the content does occupy 1024 height. So I need a vertical scrollbar to scroll the rest of the app window contents into view.
I tried setting the window contentSize, but that just makes the window larger.
Bit baffled by this as in every other environment in the world, not necessarily IDEs, it's a matter of ticking a box...

Select your document view object in Interface Builder and select Editor->Embed In->Scroll View.
Or you can just drag an NSScrollView from the object palette into your window.

Related

How can I make window zooming respect auto layout constraints?

To keep things simple, let's say I have a window containing a single view, which has auto layout constraints binding all 4 sides to the window container view with offset 0. And assume that this view also has a constraint setting its aspect ratio to a constant value. If I resize the window manually, then then window nicely maintains the desired aspect ratio. But if I click the little green zoom widget, then the window fills up the whole screen, regardless of the aspect ratio, with part of the view being above the top of the screen. Is there some way I can make zooming resize the window as big as it can be, without violating auto layout constraints?
I couldn't very well detect this problem in the delegate method windowWillResize:toSize:, because that doesn't tell me which screen it's thinking about putting the window on. I could try to fix the window size in the windowDidResize: delegate method, at which time I do know what screen it's on, but I'm not sure exactly how to do that without reinventing Auto Layout's wheel.
Apparently someone thinks I wasn't explicit enough, so I'll try again. Steps to reproduce:
In Xcode, create a new macOS App project using XIB interface.
Open MainMenu.xib and select the window.
Reshape the window to be approximately square.
Using the Attribute Inspector, set the Full Screen behavior for the window to Auxiliary Window.
Drag an Image View from the library and drop it in the window.
In the Attributes Inspector, set the image view to show the NSComputer image and scale axes independently.
Expand the image view to fill up the window content area.
With the image view selected, click the button to add new layout constraints.
Add 5 constraints, binding the 4 sides to the container, and setting the aspect ratio. (see screen shot)
Build and Run.
Observe that if you resize the window by dragging an edge or corner, the aspect ratio remains fixed.
Click the green zoom widget in the title bar of the window, and observe that the window expands without regard for the aspect ratio constraint, cutting off part of the image.
I just set up a test project exactly as you specified, and when I invoke the window zoom widget, the window expands and retains its aspect ratio i.e. it works as expected. The only thing I can think of that might be causing your issue: maybe your content hugging and content compression resistance priorities are at odds with your constraints? Mind you, I just left them at the default values and it worked fine. Unfortunately Mac/AppKit development (esp. when using IB) is rife with these kind of odd bugs and weird behaviour, probably because Apple has not given it any love in years, so bugs creep in/fester and they are clearly so DONE with developing UI the 'old fashioned way'. (Using SwiftUI to make a Mac app is just as frustrating, in different ways, so I'll stick with what I know). FYI, I used Xcode 13.4.1 to create this test project. Good luck!

OS X App - Cannot Resize App Window

I have an OS X app originally built using Xcode 4, now using Xcode 7. When "springs-and-struts" was superseded by constraints, I reworked the UI to use constraints. Simple enough, and seemed to work well.
Fast forward two years after first release, and for the second release I needed to add controls and increase the height of the main app view. Unfortunately, my test team is using smaller screens and cannot see the whole view. They need to resize vertically.
Problem - even though the resize controls box is checked, the window cannot be resized. The controls do not show at run time. I tried
Setting lower minimum window content size height, but that did not change anything.
Changing content compression resistance did not change anything.
I am thinking this issue has something to do with constraints.... Any ideas on how to get resize to work?
Edit: After playing with a new test app some, I am more certain the problem is due to constraints. I have a control where I have constrained leading and trailing space to superview and width - there went horizontal resize.
I really need to have a view where the user can resize the window, but scroll the content. However, in this case, the content is other controls. I think on iOS, I would use a UIScrollView. On OS X, I have tried a scroll view control and have tried embedding in a scroll view, and neither have the desired effect.
I had the same issue and solved it by adding a view to be used as a "container" in the view controller.
Pin the top left corner of the "container view" to the view controller (leading space 0 and top space 0). Add equal width and height constraints on the "container view" to the view controller. Then move all your objects into the "container view" and add your object constraints on the "container view" not the view controller.
In my case, it happened in this way (Xcode 13.1).
I mistakenly added a view from IB outside of the window view hierarchy. The new view was added as a separated object (a top node in the interface builder file). I added the new view into the window by drag-n-drop.
I found the new view had different behaviours, for example, I couldn't set the top space constraint. With this view in the view hierarchy, I couldn't change the window size (content view size) at all.
I removed the view and added another in the view hierarchy, it worked as normal.
I think IB initialises the view differently if it is a separated object (top node of the interface builder file).

Can't change height of NSTextField in Interface Builder

When I do something simple, like add a Wrapping Text Field in Interface builder (drag and drop method), I find that I'm unable to size the object as I would like using the mouse pointer.
For example, once I've placed this Wrapping Text Field into the upper left hand corner of my Document, I can't adjust the height of the object by dragging down on the bottom-middle sizing tool.
This happens all the time when sizing different objects in Interface Builder, it's really frustrating! The only workaround seems to be to open the Size Inspector and to manually adjust the height of the object by increasing the value.
What am I doing wrong? Is it because the object clamps to the top-left corner of the Document when I place it there? I'm not adding any constraints, merely dragging and dropping elements onto the Document in the xib.
I'm using Xcode Version 5.1.1 (5B1008) on OS X 10.9.2 (13C1021)
OK so after a bit of playing around in Interface Builder, I've noticed that I can switch off the "Use Auto Layout" feature in the File Inspector. Now when I switch to the Sizing Inspector I have an easy to use "Auto Sizing" feature that when I hover over the preview, shows me exactly how the NSTextField will size when re-sizing the parent document.
Also once I've switched off "Use Auto Layout", I can use the mouse pointer to adjust the NSTextField height and width in the Interface Builder.
I guess the "Use Auto Layout" is constraining the height of the NSTextField to the appropriate height it thinks it should be but I can't tell where it get's this value from.

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.

Mac OS X/Cocoa: create "docked" sidebar that reduces maximizable area, like the Dock

When the OS X dock is shown, it "reserves" some screen area and prevents maximized windows from going behind the dock when maximized. How do I make my own Cocoa application do the same?
A window's "maximizable area" is based on the screen's visibleFrame.
[[NSScreen mainScreen] visibleFrame]
The returned rectangle is always based on the current user-interface settings and does not include the area currently occupied by the dock and menu bar.
Because it is based on the current user -interface settings, the returned rectangle can change between calls and should not be cached.
The rectangle defining the portion of the screen in which it is currently safe to draw your application content.
There is no mention of being able to adjust this visibleFrame rectangle, so I do not think you will have any success influencing the "global" Zoom size.
However, if you only want to adjust the Zoomed size of your app's window, return a smaller rectangle in the NSWindowDelegate method windowWillUseStandardFrame:defaultFrame:.
The standard frame for a window should supply the size and location that are “best” for the type of information shown in the window, taking into account the available display or displays. For example, the best width for a window that displays a word-processing document is the width of a page or the width of the display, whichever is smaller. The best height can be determined similarly. On return from this method, the zoom: method modifies the returned standard frame, if necessary, to fit on the current screen.
This will allow you to take into account a "docked sidebar" when Zooming your app's windows. Other apps will be resized on top of the docked sidebar.

Resources