diff --git a/darwin/autolayout.m b/darwin/autolayout.m index 58203738..2e685190 100644 --- a/darwin/autolayout.m +++ b/darwin/autolayout.m @@ -1,15 +1,21 @@ // 15 august 2015 #import "uipriv_darwin.h" -void addConstraint(NSView *view, NSString *constraint, NSDictionary *metrics, NSDictionary *views) +NSLayoutConstraint *mkConstraint(id view1, NSLayoutAttribute attr1, NSLayoutRelation relation, id view2, NSLayoutAttribute attr2, CGFloat multiplier, CGFloat c, NSString *desc) { - NSArray *constraints; + NSLayoutConstraint *c; - constraints = [NSLayoutConstraint constraintsWithVisualFormat:constraint - options:0 - metrics:metrics - views:views]; - [view addConstraints:constraints]; + c = [NSLayoutConstraint constraintWithItem:view1 + attribute:attr1 + relatedBy:relation + toItem:view2 + attribute:attr2 + multiplier:multiplier + constant:c]; + // apparently only added in 10.9 + if ([c respondsToSelector:@selector(setIdentifier:)]) + [((id) c) setIdentifier:desc]; + return c; } NSLayoutPriority horzHuggingPri(NSView *view) @@ -17,44 +23,124 @@ NSLayoutPriority horzHuggingPri(NSView *view) return [view contentHuggingPriorityForOrientation:NSLayoutConstraintOrientationHorizontal]; } +void setHorzHuggingPri(NSView *view, NSLayoutPriority priority) +{ + [view setContentHuggingPriority:priority forOrientation:NSLayoutConstraintOrientationHorizontal]; +} + NSLayoutPriority vertHuggingPri(NSView *view) { return [view contentHuggingPriorityForOrientation:NSLayoutConstraintOrientationVertical]; } -void setHuggingPri(NSView *view, NSLayoutPriority priority, NSLayoutConstraintOrientation orientation) +void setVertHuggingPri(NSView *view, NSLayoutPriority priority) { - [view setContentHuggingPriority:priority forOrientation:orientation]; + [view setContentHuggingPriority:priority forOrientation:NSLayoutConstraintOrientationVertical]; } -// precondition: constraints must have been removed from superview already -void layoutSingleView(NSView *superview, NSView *subview, int margined) +// precondition: subview is a subview of superview already +void layoutSingleView(NSView *superview, NSView *subview, int margined, NSString *desc) { - NSDictionary *views; - NSString *constraint; + NSLayoutConstraint *constraint; + CGFloat margin; - views = NSDictionaryOfVariableBindings(subview); + [superview removeConstraints:[superview constraints]]; - constraint = @"H:|[subview]|"; + margin = 0; if (margined) - constraint = @"H:|-[subview]-|"; - addConstraint(superview, constraint, nil, views); + margin = 20; // TODO named constant - constraint = @"V:|[subview]|"; - if (margined) - constraint = @"V:|-[subview]-|"; - addConstraint(superview, constraint, nil, views); + constraint = mkConstraint(subview, NSLayoutAttributeLeading, + NSLayoutRelationEqual, + superview, NSLayoutAttributeLeading, + 1, margin, + [desc stringByAppendingString:@" single child horizontal leading"]); + [superview addConstraint:constraint]; + + constraint = mkConstraint(superview, NSLayoutAttributeTrailing, + NSLayoutRelationEqual, + subview, NSLayoutAttributeTrailing, + 1, margin, + [desc stringByAppendingString:@" single child horizontal trailing"]); + [superview addConstraint:constraint]; + + constraint = mkConstraint(subview, NSLayoutAttributeTop, + NSLayoutRelationEqual, + superview, NSLayoutAttributeTop, + 1, margin, + [desc stringByAppendingString:@" single child top"]); + [superview addConstraint:constraint]; + + constraint = mkConstraint(superview, NSLayoutAttributeBottom, + NSLayoutRelationEqual, + subview, NSLayoutAttributeBottom, + 1, margin, + [desc stringByAppendingString:@" single child bottom"]); + [superview addConstraint:constraint]; } -// use the fitting size, not the intrinsic content size, for the case of recursive views without an intrinsic content size -NSSize fittingAlignmentSize(NSView *view) +// via https://developer.apple.com/library/mac/documentation/UserExperience/Conceptual/AutolayoutPG/WorkingwithScrollViews.html#//apple_ref/doc/uid/TP40010853-CH24-SW1 +NSMutableArray *layoutScrollViewContents(NSScrollView *sv, BOOL noHScroll, BOOL noVScroll NSString *desc) { - NSSize s; - NSRect r; + NSView *dv; + NSLayoutConstraint *constraint; + NSMutableArray *array; - s = [view fittingSize]; - // the fitting size is for a frame rect; we need an alignment rect - r = NSMakeRect(0, 0, s.width, s.height); - r = [view alignmentRectForFrame:r]; - return r.size; + dv = [sv documentView]; + + array = [NSMutableArray new]; + + constraint = mkConstraint(dv, NSLayoutAttributeLeading, + NSLayoutRelationEqual, + sv, NSLayoutAttributeLeading, + 1, 0, + [desc stringByAppendingString:@" scroll view horizontal leading"]); + [array addObject:constraint]; + [sv addConstraint:constraint]; + + constraint = mkConstraint(dv, NSLayoutAttributeTrailing, + NSLayoutRelationEqual, + sv, NSLayoutAttributeTrailing, + 1, 0, + [desc stringByAppendingString:@" scroll view horizontal trailing"]); + [array addObject:constraint]; + [sv addConstraint:constraint]; + + constraint = mkConstraint(dv, NSLayoutAttributeTop, + NSLayoutRelationEqual, + sv, NSLayoutAttributeTop, + 1, 0, + [desc stringByAppendingString:@" scroll view top"]); + [array addObject:constraint]; + [sv addConstraint:constraint]; + + constraint = mkConstraint(dv, NSLayoutAttributeBottom, + NSLayoutRelationEqual, + sv, NSLayoutAttributeBottom, + 1, 0, + [desc stringByAppendingString:@" scroll view bottom"]); + [array addObject:constraint]; + [sv addConstraint:constraint]; + + if (noHScroll) { + constraint = mkConstraint(dv, NSLayoutAttributeWidth, + NSLayoutRelationEqual, + sv, NSLayoutAttributeWidth, + 1, 0, + [desc stringByAppendingString:@" scroll view width"]); + [array addObject:constraint]; + [sv addConstraint:constraint]; + } + + if (noVScroll) { + constraint = mkConstraint(dv, NSLayoutAttributeHeight, + NSLayoutRelationEqual, + sv, NSLayoutAttributeHeight, + 1, 0, + [desc stringByAppendingString:@" scroll view height"]); + [array addObject:constraint]; + [sv addConstraint:constraint]; + } + + return array; } diff --git a/darwin/group.m b/darwin/group.m index f67036be..f79dc9c2 100644 --- a/darwin/group.m +++ b/darwin/group.m @@ -50,14 +50,13 @@ static void groupRelayout(uiGroup *g) if (g->child == NULL) return; - [g->box removeConstraints:[g->box constraints]]; cc = uiDarwinControl(g->child); childView = (NSView *) uiControlHandle(g->child); // first relayout the child //TODO (*(cc->Relayout))(cc); // now relayout ourselves // see below on using the content view - layoutSingleView(g->box, childView, g->margined); + layoutSingleView(g->box, childView, g->margined, @"uiGroup"); // we need to explicitly tell the NSBox to recompute its own size based on the new content layout [g->box sizeToFit]; } diff --git a/darwin/multilineentry.m b/darwin/multilineentry.m index 141c29c7..ecdfcd68 100644 --- a/darwin/multilineentry.m +++ b/darwin/multilineentry.m @@ -119,12 +119,11 @@ uiMultilineEntry *uiNewMultilineEntry(void) // let's just set it to the standard control font anyway, just to be safe [e->tv setFont:font]; - // TODO this (via https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/TextUILayer/Tasks/TextInScrollView.html) is the magic incantation needed to get things to show up; figure out why - // it especially seems weird we're mixing this with auto layout... - [e->tv setAutoresizingMask:NSViewWidthSizable]; - //TODO [e->tv setTranslatesAutoresizingMaskIntoConstraints:NO]; [e->sv setDocumentView:e->tv]; + [e->tv setTranslatesAutoresizingMaskIntoConstraints:NO]; + // we don't need to save the NSMutableArray + [layoutScrollViewContents(e->sv, @"uiMultilineEntry") release]; //TODO:void printinfo(NSScrollView *sv, NSTextView *tv); //printinfo(e->sv, e->tv); diff --git a/darwin/spinbox.m b/darwin/spinbox.m index 308851ab..b47b888f 100644 --- a/darwin/spinbox.m +++ b/darwin/spinbox.m @@ -60,13 +60,42 @@ struct uiSpinbox { [self addSubview:self->tf]; [self addSubview:self->stepper]; - views = [NSDictionary - dictionaryWithObjectsAndKeys:self->tf, @"textfield", - self->stepper, @"stepper", - nil]; - addConstraint(self, @"H:|[textfield]-[stepper]|", nil, views); - addConstraint(self, @"V:|[textfield]|", nil, views); - addConstraint(self, @"V:|[stepper]|", nil, views); + + [self addConstraint:mkConstraint(self->tf, NSLayoutAttributeLeading, + NSLayoutRelationEqual, + self, NSLayoutAttributeLeading, + 1, 0, + @"uiSpinbox left edge")]; + [self addConstraint:mkConstraint(self->stepper, NSLayoutAttributeTrailing, + NSLayoutRelationEqual, + self, NSLayoutAttributeTrailing, + 1, 0, + @"uiSpinbox right edge")]; + [self addConstraint:mkConstraint(self->tf, NSLayoutAttributeTop, + NSLayoutRelationEqual, + self, NSLayoutAttributeTop, + 1, 0, + @"uiSpinbox top edge text field")]; + [self addConstraint:mkConstraint(self->tf, NSLayoutAttributeBottom, + NSLayoutRelationEqual, + self, NSLayoutAttributeBottom, + 1, 0, + @"uiSpinbox bottom edge text field")]; + [self addConstraint:mkConstraint(self->stepper, NSLayoutAttributeTop, + NSLayoutRelationEqual, + self, NSLayoutAttributeTop, + 1, 0, + @"uiSpinbox top edge stepper")]; + [self addConstraint:mkConstraint(self->stepper, NSLayoutAttributeBottom, + NSLayoutRelationEqual, + self, NSLayoutAttributeBottom, + 1, 0, + @"uiSpinbox bottom edge stepper")]; + [self addConstraint:mkConstraint(self->stepper, NSLayoutAttributeTrailingEdge, + NSLayoutRelationEqual, + self->stepper, NSLayoutAttributeLeadingEdge, + 1, -3, // TODO + @"uiSpinbox space between text field and stepper")]; self->spinbox = sb; } diff --git a/darwin/tab.m b/darwin/tab.m index 660ef012..cd287840 100644 --- a/darwin/tab.m +++ b/darwin/tab.m @@ -71,13 +71,12 @@ static void tabRelayout(uiTab *t) child = (uiControl *) [v pointerValue]; view = (NSView *) [t->views objectAtIndex:i]; childView = (NSView *) uiControlHandle(child); - [view removeConstraints:[view constraints]]; margined = (NSNumber *) [t->margined objectAtIndex:i]; // first lay out the child cc = uiDarwinControl(child); //TODO (*(cc->Relayout))(cc); // then lay out the page - layoutSingleView(view, childView, [margined intValue]); + layoutSingleView(view, childView, [margined intValue], @"uiTab"); } } diff --git a/darwin/uipriv_darwin.h b/darwin/uipriv_darwin.h index 5c439a0f..a4e90b6e 100644 --- a/darwin/uipriv_darwin.h +++ b/darwin/uipriv_darwin.h @@ -56,12 +56,13 @@ extern void initAlloc(void); extern void uninitAlloc(void); // autolayout.m -extern void addConstraint(NSView *, NSString *, NSDictionary *, NSDictionary *); -extern NSLayoutPriority horzHuggingPri(NSView *); -extern NSLayoutPriority vertHuggingPri(NSView *); -extern void setHuggingPri(NSView *, NSLayoutPriority, NSLayoutConstraintOrientation); -extern void layoutSingleView(NSView *, NSView *, int); -extern NSSize fittingAlignmentSize(NSView *); +extern NSLayoutConstraint *mkConstraint(id view1, NSLayoutAttribute attr1, NSLayoutRelation relation, id view2, NSLayoutAttribute attr2, CGFloat multiplier, CGFloat c, NSString *desc); +extern NSLayoutPriority horzHuggingPri(NSView *view); +extern void setHorzHuggingPri(NSView *view, NSLayoutPriority priority); +extern NSLayoutPriority vertHuggingPri(NSView *view); +extern void setVertHuggingPri(NSView *view, NSLayoutPriority priority); +extern void layoutSingleView(NSView *superview, NSView *subview, int margined, NSString *desc); +extern NSMutableArray *layoutScrollViewContents(NSScrollView *sv, BOOL noHScroll, BOOL noVScroll NSString *desc); // map.m extern struct mapTable *newMap(void); diff --git a/darwin/window.m b/darwin/window.m index c3160f76..59379550 100644 --- a/darwin/window.m +++ b/darwin/window.m @@ -152,11 +152,10 @@ static void windowRelayout(uiWindow *w) cc = uiDarwinControl(w->child); childView = (NSView *) uiControlHandle(w->child); contentView = [w->window contentView]; - [contentView removeConstraints:[contentView constraints]]; // first relayout the child //TODO (*(cc->Relayout))(cc); // now relayout ourselves - layoutSingleView(contentView, childView, w->margined); + layoutSingleView(contentView, childView, w->margined, @"uiWindow"); } char *uiWindowTitle(uiWindow *w)