Started reworking the auto layout system. uiBox is next.

This commit is contained in:
Pietro Gagliardi 2016-04-30 17:14:14 -04:00
parent 97ab0b36e0
commit 835c711a24
7 changed files with 165 additions and 53 deletions

View File

@ -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;
}

View File

@ -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];
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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");
}
}

View File

@ -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);

View File

@ -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)