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 // 15 august 2015
#import "uipriv_darwin.h" #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 c = [NSLayoutConstraint constraintWithItem:view1
options:0 attribute:attr1
metrics:metrics relatedBy:relation
views:views]; toItem:view2
[view addConstraints:constraints]; 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) NSLayoutPriority horzHuggingPri(NSView *view)
@ -17,44 +23,124 @@ NSLayoutPriority horzHuggingPri(NSView *view)
return [view contentHuggingPriorityForOrientation:NSLayoutConstraintOrientationHorizontal]; return [view contentHuggingPriorityForOrientation:NSLayoutConstraintOrientationHorizontal];
} }
void setHorzHuggingPri(NSView *view, NSLayoutPriority priority)
{
[view setContentHuggingPriority:priority forOrientation:NSLayoutConstraintOrientationHorizontal];
}
NSLayoutPriority vertHuggingPri(NSView *view) NSLayoutPriority vertHuggingPri(NSView *view)
{ {
return [view contentHuggingPriorityForOrientation:NSLayoutConstraintOrientationVertical]; 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 // precondition: subview is a subview of superview already
void layoutSingleView(NSView *superview, NSView *subview, int margined) void layoutSingleView(NSView *superview, NSView *subview, int margined, NSString *desc)
{ {
NSDictionary *views; NSLayoutConstraint *constraint;
NSString *constraint; CGFloat margin;
views = NSDictionaryOfVariableBindings(subview); [superview removeConstraints:[superview constraints]];
constraint = @"H:|[subview]|"; margin = 0;
if (margined) if (margined)
constraint = @"H:|-[subview]-|"; margin = 20; // TODO named constant
addConstraint(superview, constraint, nil, views);
constraint = @"V:|[subview]|"; constraint = mkConstraint(subview, NSLayoutAttributeLeading,
if (margined) NSLayoutRelationEqual,
constraint = @"V:|-[subview]-|"; superview, NSLayoutAttributeLeading,
addConstraint(superview, constraint, nil, views); 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 // via https://developer.apple.com/library/mac/documentation/UserExperience/Conceptual/AutolayoutPG/WorkingwithScrollViews.html#//apple_ref/doc/uid/TP40010853-CH24-SW1
NSSize fittingAlignmentSize(NSView *view) NSMutableArray *layoutScrollViewContents(NSScrollView *sv, BOOL noHScroll, BOOL noVScroll NSString *desc)
{ {
NSSize s; NSView *dv;
NSRect r; NSLayoutConstraint *constraint;
NSMutableArray *array;
s = [view fittingSize]; dv = [sv documentView];
// the fitting size is for a frame rect; we need an alignment rect
r = NSMakeRect(0, 0, s.width, s.height); array = [NSMutableArray new];
r = [view alignmentRectForFrame:r];
return r.size; 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) if (g->child == NULL)
return; return;
[g->box removeConstraints:[g->box constraints]];
cc = uiDarwinControl(g->child); cc = uiDarwinControl(g->child);
childView = (NSView *) uiControlHandle(g->child); childView = (NSView *) uiControlHandle(g->child);
// first relayout the child // first relayout the child
//TODO (*(cc->Relayout))(cc); //TODO (*(cc->Relayout))(cc);
// now relayout ourselves // now relayout ourselves
// see below on using the content view // 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 // we need to explicitly tell the NSBox to recompute its own size based on the new content layout
[g->box sizeToFit]; [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 // let's just set it to the standard control font anyway, just to be safe
[e->tv setFont:font]; [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]; //TODO [e->tv setTranslatesAutoresizingMaskIntoConstraints:NO];
[e->sv setDocumentView:e->tv]; [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); //TODO:void printinfo(NSScrollView *sv, NSTextView *tv);
//printinfo(e->sv, e->tv); //printinfo(e->sv, e->tv);

View File

@ -60,13 +60,42 @@ struct uiSpinbox {
[self addSubview:self->tf]; [self addSubview:self->tf];
[self addSubview:self->stepper]; [self addSubview:self->stepper];
views = [NSDictionary
dictionaryWithObjectsAndKeys:self->tf, @"textfield", [self addConstraint:mkConstraint(self->tf, NSLayoutAttributeLeading,
self->stepper, @"stepper", NSLayoutRelationEqual,
nil]; self, NSLayoutAttributeLeading,
addConstraint(self, @"H:|[textfield]-[stepper]|", nil, views); 1, 0,
addConstraint(self, @"V:|[textfield]|", nil, views); @"uiSpinbox left edge")];
addConstraint(self, @"V:|[stepper]|", nil, views); [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; self->spinbox = sb;
} }

View File

@ -71,13 +71,12 @@ static void tabRelayout(uiTab *t)
child = (uiControl *) [v pointerValue]; child = (uiControl *) [v pointerValue];
view = (NSView *) [t->views objectAtIndex:i]; view = (NSView *) [t->views objectAtIndex:i];
childView = (NSView *) uiControlHandle(child); childView = (NSView *) uiControlHandle(child);
[view removeConstraints:[view constraints]];
margined = (NSNumber *) [t->margined objectAtIndex:i]; margined = (NSNumber *) [t->margined objectAtIndex:i];
// first lay out the child // first lay out the child
cc = uiDarwinControl(child); cc = uiDarwinControl(child);
//TODO (*(cc->Relayout))(cc); //TODO (*(cc->Relayout))(cc);
// then lay out the page // 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); extern void uninitAlloc(void);
// autolayout.m // autolayout.m
extern void addConstraint(NSView *, NSString *, NSDictionary *, NSDictionary *); extern NSLayoutConstraint *mkConstraint(id view1, NSLayoutAttribute attr1, NSLayoutRelation relation, id view2, NSLayoutAttribute attr2, CGFloat multiplier, CGFloat c, NSString *desc);
extern NSLayoutPriority horzHuggingPri(NSView *); extern NSLayoutPriority horzHuggingPri(NSView *view);
extern NSLayoutPriority vertHuggingPri(NSView *); extern void setHorzHuggingPri(NSView *view, NSLayoutPriority priority);
extern void setHuggingPri(NSView *, NSLayoutPriority, NSLayoutConstraintOrientation); extern NSLayoutPriority vertHuggingPri(NSView *view);
extern void layoutSingleView(NSView *, NSView *, int); extern void setVertHuggingPri(NSView *view, NSLayoutPriority priority);
extern NSSize fittingAlignmentSize(NSView *); extern void layoutSingleView(NSView *superview, NSView *subview, int margined, NSString *desc);
extern NSMutableArray *layoutScrollViewContents(NSScrollView *sv, BOOL noHScroll, BOOL noVScroll NSString *desc);
// map.m // map.m
extern struct mapTable *newMap(void); extern struct mapTable *newMap(void);

View File

@ -152,11 +152,10 @@ static void windowRelayout(uiWindow *w)
cc = uiDarwinControl(w->child); cc = uiDarwinControl(w->child);
childView = (NSView *) uiControlHandle(w->child); childView = (NSView *) uiControlHandle(w->child);
contentView = [w->window contentView]; contentView = [w->window contentView];
[contentView removeConstraints:[contentView constraints]];
// first relayout the child // first relayout the child
//TODO (*(cc->Relayout))(cc); //TODO (*(cc->Relayout))(cc);
// now relayout ourselves // now relayout ourselves
layoutSingleView(contentView, childView, w->margined); layoutSingleView(contentView, childView, w->margined, @"uiWindow");
} }
char *uiWindowTitle(uiWindow *w) char *uiWindowTitle(uiWindow *w)