// 27 may 2016 #include "uipriv_darwin.h" struct scrollViewData { NSLayoutConstraint *documentLeading; NSLayoutConstraint *documentTop; BOOL hscroll; NSLayoutConstraint *documentTrailing; BOOL vscroll; NSLayoutConstraint *documentBottom; }; NSScrollView *mkScrollView(struct scrollViewCreateParams *p, struct scrollViewData **dout) { NSScrollView *sv; NSBorderType border; struct scrollViewData *d; sv = [[NSScrollView alloc] initWithFrame:NSZeroRect]; if (p->BackgroundColor != nil) [sv setBackgroundColor:p->BackgroundColor]; [sv setDrawsBackground:p->DrawsBackground]; border = NSNoBorder; if (p->Bordered) border = NSBezelBorder; // document view seems to set the cursor properly [sv setBorderType:border]; [sv setAutohidesScrollers:YES]; [sv setHasHorizontalRuler:NO]; [sv setHasVerticalRuler:NO]; [sv setRulersVisible:NO]; [sv setScrollerKnobStyle:NSScrollerKnobStyleDefault]; // the scroller style is documented as being set by default for us // LONGTERM verify line and page for programmatically created NSTableView [sv setScrollsDynamically:YES]; [sv setFindBarPosition:NSScrollViewFindBarPositionAboveContent]; [sv setUsesPredominantAxisScrolling:NO]; [sv setHorizontalScrollElasticity:NSScrollElasticityAutomatic]; [sv setVerticalScrollElasticity:NSScrollElasticityAutomatic]; [sv setAllowsMagnification:NO]; [p->DocumentView setTranslatesAutoresizingMaskIntoConstraints:NO]; [sv setDocumentView:p->DocumentView]; d = uiNew(struct scrollViewData); scrollViewSetScrolling(sv, d, p->HScroll, p->VScroll); *dout = d; return sv; } static void scrollViewConstraintsRemove(NSScrollView *sv, struct scrollViewData *d) { if (d->documentLeading != nil) { [sv removeConstraint:d->documentLeading]; [d->documentLeading release]; d->documentLeading = nil; } if (d->documentTop != nil) { [sv removeConstraint:d->documentTop]; [d->documentTop release]; d->documentTop = nil; } if (d->documentTrailing != nil) { [sv removeConstraint:d->documentTrailing]; [d->documentTrailing release]; d->documentTrailing = nil; } if (d->documentBottom != nil) { [sv removeConstraint:d->documentBottom]; [d->documentBottom release]; d->documentBottom = nil; } } // based on http://blog.bjhomer.com/2014/08/nsscrollview-and-autolayout.html because (as pointed out there) Apple's official guide is really only for iOS void scrollViewSetScrolling(NSScrollView *sv, struct scrollViewData *d, BOOL hscroll, BOOL vscroll) { NSView *cv, *dv; NSLayoutRelation rel; scrollViewConstraintsRemove(sv, d); cv = [sv contentView]; dv = [sv documentView]; d->documentLeading = mkConstraint(dv, NSLayoutAttributeLeading, NSLayoutRelationEqual, cv, NSLayoutAttributeLeading, 1, 0, @"NSScrollView document leading constraint"); [sv addConstraint:d->documentLeading]; [d->documentLeading retain]; d->documentTop = mkConstraint(dv, NSLayoutAttributeTop, NSLayoutRelationEqual, cv, NSLayoutAttributeTop, 1, 0, @"NSScrollView document top constraint"); [sv addConstraint:d->documentTop]; [d->documentTop retain]; d->hscroll = hscroll; [sv setHasHorizontalScroller:d->hscroll]; rel = NSLayoutRelationGreaterThanOrEqual; if (!d->hscroll) rel = NSLayoutRelationEqual; d->documentTrailing = mkConstraint(dv, NSLayoutAttributeTrailing, rel, cv, NSLayoutAttributeTrailing, 1, 0, @"NSScrollView document trailing constraint"); [sv addConstraint:d->documentTrailing]; [d->documentTrailing retain]; d->vscroll = vscroll; [sv setHasVerticalScroller:d->vscroll]; rel = NSLayoutRelationGreaterThanOrEqual; if (!d->vscroll) rel = NSLayoutRelationEqual; d->documentBottom = mkConstraint(dv, NSLayoutAttributeBottom, rel, cv, NSLayoutAttributeBottom, 1, 0, @"NSScrollView document bottom constraint"); [sv addConstraint:d->documentBottom]; [d->documentBottom retain]; } void scrollViewFreeData(NSScrollView *sv, struct scrollViewData *d) { scrollViewConstraintsRemove(sv, d); uiFree(d); }