Rewrote darwin/box.m's layout code to create constraints directly. Let's try this out.
This commit is contained in:
parent
835c711a24
commit
c87a932a6d
|
@ -18,6 +18,11 @@ NSLayoutConstraint *mkConstraint(id view1, NSLayoutAttribute attr1, NSLayoutRela
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setHuggingPri(NSView *view, NSLayoutPriority priority, NSLayoutConstraintOrientation orientation)
|
||||||
|
{
|
||||||
|
[view setContentHuggingPriority:priority forOrientation:orientation];
|
||||||
|
}
|
||||||
|
|
||||||
NSLayoutPriority horzHuggingPri(NSView *view)
|
NSLayoutPriority horzHuggingPri(NSView *view)
|
||||||
{
|
{
|
||||||
return [view contentHuggingPriorityForOrientation:NSLayoutConstraintOrientationHorizontal];
|
return [view contentHuggingPriorityForOrientation:NSLayoutConstraintOrientationHorizontal];
|
||||||
|
|
226
darwin/box.m
226
darwin/box.m
|
@ -17,8 +17,11 @@ struct uiBox {
|
||||||
NSMutableArray *stretchy; // []NSNumber
|
NSMutableArray *stretchy; // []NSNumber
|
||||||
// this view is made stretchy if there are no stretchy views
|
// this view is made stretchy if there are no stretchy views
|
||||||
NSView *noStretchyView;
|
NSView *noStretchyView;
|
||||||
NSString *primaryDirPrefix;
|
NSLayoutAttribute primaryStart;
|
||||||
NSString *secondaryDirPrefix;
|
NSLayoutAttribute primaryEnd;
|
||||||
|
NSLayoutAttribute secondaryStart;
|
||||||
|
NSLayoutAttribute secondaryEnd;
|
||||||
|
NSLayoutAttribute primarySize;
|
||||||
NSLayoutConstraintOrientation primaryOrientation;
|
NSLayoutConstraintOrientation primaryOrientation;
|
||||||
NSLayoutConstraintOrientation secondaryOrientation;
|
NSLayoutConstraintOrientation secondaryOrientation;
|
||||||
};
|
};
|
||||||
|
@ -85,21 +88,6 @@ static void uiBoxSyncEnableState(uiDarwinControl *c, int enabled)
|
||||||
|
|
||||||
uiDarwinControlDefaultSetSuperview(uiBox, view)
|
uiDarwinControlDefaultSetSuperview(uiBox, view)
|
||||||
|
|
||||||
static NSString *viewName(uintmax_t n)
|
|
||||||
{
|
|
||||||
return [NSString stringWithFormat:@"view%ju", n];
|
|
||||||
}
|
|
||||||
|
|
||||||
static NSString *widthMetricName(uintmax_t n)
|
|
||||||
{
|
|
||||||
return [NSString stringWithFormat:@"view%juwidth", n];
|
|
||||||
}
|
|
||||||
|
|
||||||
static NSString *heightMetricName(uintmax_t n)
|
|
||||||
{
|
|
||||||
return [NSString stringWithFormat:@"view%juheight", n];
|
|
||||||
}
|
|
||||||
|
|
||||||
static int isStretchy(uiBox *b, uintmax_t n)
|
static int isStretchy(uiBox *b, uintmax_t n)
|
||||||
{
|
{
|
||||||
NSNumber *num;
|
NSNumber *num;
|
||||||
|
@ -108,117 +96,135 @@ static int isStretchy(uiBox *b, uintmax_t n)
|
||||||
return [num intValue];
|
return [num intValue];
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO do we still need to set hugging? I think we do for stretchy controls...
|
static NSView *boxView(uiBox *b, uintmax_t n)
|
||||||
// TODO try unsetting spinbox intrinsics and seeing what happens
|
|
||||||
static void relayout(uiBox *b)
|
|
||||||
{
|
{
|
||||||
NSMutableDictionary *metrics;
|
NSValue *val;
|
||||||
NSMutableDictionary *views;
|
uiControl *c;
|
||||||
uintmax_t i, n;
|
|
||||||
BOOL hasStretchy;
|
|
||||||
uintmax_t firstStretchy;
|
|
||||||
NSMutableString *constraint;
|
|
||||||
|
|
||||||
if ([b->children count] == 0)
|
val = (NSValue *) [b->children objectAtIndex:n];
|
||||||
return;
|
c = (uiControl *) [val pointerValue];
|
||||||
|
return (NSView *) uiControlHandle(c);
|
||||||
[b->view removeConstraints:[b->view constraints]];
|
|
||||||
|
|
||||||
// first lay out all children, collect the views and their fitting sizes (for non-stretchy controls)
|
|
||||||
// also figure out which is the first stretchy control, if any
|
|
||||||
metrics = [NSMutableDictionary new];
|
|
||||||
views = [NSMutableDictionary new];
|
|
||||||
hasStretchy = NO;
|
|
||||||
n = 0;
|
|
||||||
while (n < [b->children count]) {
|
|
||||||
uiControl *child;
|
|
||||||
uiDarwinControl *cc;
|
|
||||||
NSView *childView;
|
|
||||||
NSSize fittingSize;
|
|
||||||
|
|
||||||
child = childAt(b, n);
|
|
||||||
cc = uiDarwinControl(child);
|
|
||||||
childView = (NSView *) uiControlHandle(child);
|
|
||||||
[views setObject:childView forKey:viewName(n)];
|
|
||||||
//TODO (*(cc->Relayout))(cc);
|
|
||||||
fittingSize = fittingAlignmentSize(childView);
|
|
||||||
[metrics setObject:[NSNumber numberWithDouble:fittingSize.width]
|
|
||||||
forKey:widthMetricName(n)];
|
|
||||||
[metrics setObject:[NSNumber numberWithDouble:fittingSize.height]
|
|
||||||
forKey:heightMetricName(n)];
|
|
||||||
if (!hasStretchy && isStretchy(b, n)) {
|
|
||||||
hasStretchy = YES;
|
|
||||||
firstStretchy = n;
|
|
||||||
}
|
|
||||||
n++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if there are no stretchy controls, we must add the no-stretchy view
|
static void addRemoveNoStretchyView(uiBox *b, BOOL hasStretchy)
|
||||||
// if there are, we must remove it
|
{
|
||||||
if (!hasStretchy) {
|
if (!hasStretchy) {
|
||||||
if ([b->noStretchyView superview] == nil)
|
if ([b->noStretchyView superview] == nil)
|
||||||
[b->view addSubview:b->noStretchyView];
|
[b->view addSubview:b->noStretchyView];
|
||||||
[views setObject:b->noStretchyView forKey:@"noStretchyView"];
|
|
||||||
} else {
|
} else {
|
||||||
if ([b->noStretchyView superview] != nil)
|
if ([b->noStretchyView superview] != nil)
|
||||||
[b->noStretchyView removeFromSuperview];
|
[b->noStretchyView removeFromSuperview];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO do we still need to set hugging? I think we do for stretchy controls...
|
||||||
|
// TODO try unsetting spinbox intrinsics and seeing what happens
|
||||||
|
static void relayout(uiBox *b)
|
||||||
|
{
|
||||||
|
NSLayoutConstraint *constraint;
|
||||||
|
uintmax_t i, n;
|
||||||
|
BOOL hasStretchy;
|
||||||
|
NSView *firstStretchy = nil;
|
||||||
|
CGFloat padding;
|
||||||
|
NSView *prev, *next;
|
||||||
|
|
||||||
|
if ([b->children count] == 0)
|
||||||
|
return;
|
||||||
|
padding = 0;
|
||||||
|
if (b->padded)
|
||||||
|
padding = 8.0; // TODO named constant
|
||||||
|
|
||||||
|
[b->view removeConstraints:[b->view constraints]];
|
||||||
|
|
||||||
|
// first, attach the first view to the leading
|
||||||
|
prev = boxView(b, 0);
|
||||||
|
[b->view addConstraint:mkConstraint(prev, b->primaryStart,
|
||||||
|
NSLayoutRelationEqual,
|
||||||
|
b->view, b->primaryStart,
|
||||||
|
1, 0,
|
||||||
|
@"uiBox first primary constraint")];
|
||||||
|
|
||||||
// next, assemble the views in the primary direction
|
// next, assemble the views in the primary direction
|
||||||
// they all go in a straight line
|
// they all go in a straight line
|
||||||
constraint = [NSMutableString new];
|
// also figure out whether we have stretchy controls, and which is the first
|
||||||
[constraint appendString:b->primaryDirPrefix];
|
if (isStretchy(b, 0)) {
|
||||||
[constraint appendString:@"|"];
|
hasStretchy = YES;
|
||||||
for (i = 0; i < n; i++) {
|
firstStretchy = prev;
|
||||||
if (b->padded && i != 0)
|
} else
|
||||||
[constraint appendString:@"-"];
|
hasStretchy = NO;
|
||||||
[constraint appendString:@"["];
|
for (i = 1; i < n; i++) {
|
||||||
[constraint appendString:viewName(i)];
|
next = boxView(b, i);
|
||||||
// implement multiple stretchiness properly
|
if (!hasStretchy && isStretchy(b, i)) {
|
||||||
if (isStretchy(b, i) && i != firstStretchy) {
|
hasStretchy = YES;
|
||||||
[constraint appendString:@"(=="];
|
firstStretchy = next;
|
||||||
[constraint appendString:viewName(firstStretchy)];
|
|
||||||
[constraint appendString:@")"];
|
|
||||||
}
|
}
|
||||||
// if the control is not stretchy, restrict it to the fitting size
|
[b->view addConstraint:mkConstraint(next, b->primaryStart,
|
||||||
if (!isStretchy(b, i)) {
|
NSLayoutRelationEqual,
|
||||||
[constraint appendString:@"(=="];
|
prev, b->primaryEnd,
|
||||||
if (b->vertical)
|
1, padding,
|
||||||
[constraint appendString:heightMetricName(i)];
|
@"uiBox later primary constraint")];
|
||||||
else
|
prev = next;
|
||||||
[constraint appendString:widthMetricName(i)];
|
|
||||||
[constraint appendString:@")"];
|
|
||||||
}
|
}
|
||||||
[constraint appendString:@"]"];
|
|
||||||
|
// if there is a stretchy control, add the no-stretchy view
|
||||||
|
addRemoveNoStretchyView(b, hasStretchy);
|
||||||
|
if (hasStretchy)
|
||||||
|
[b->view addConstraint:mkConstraint(b->noStretchyView, b->primaryStart,
|
||||||
|
NSLayoutRelationEqual,
|
||||||
|
prev, b->primaryEnd,
|
||||||
|
1, 0, // don't space between the last control and the no-stretchy view
|
||||||
|
@"uiBox no-stretchy primary constraint")];
|
||||||
|
prev = b->noStretchyView;
|
||||||
}
|
}
|
||||||
if (!hasStretchy)
|
|
||||||
// don't space between the last control and the no-stretchy view
|
// and finally end the primary direction
|
||||||
[constraint appendString:@"[noStretchyView]"];
|
[b->view addConstraint:mkConstraint(prev, p->primaryEnd,
|
||||||
[constraint appendString:@"|"];
|
NSLayoutRelationEqual,
|
||||||
addConstraint(b->view, constraint, metrics, views);
|
b->view, b->primaryEnd,
|
||||||
[constraint release];
|
1, 0,
|
||||||
|
@"uiBox last primary constraint"];
|
||||||
|
|
||||||
// next: assemble the views in the secondary direction
|
// next: assemble the views in the secondary direction
|
||||||
// each of them will span the secondary direction
|
// each of them will span the secondary direction
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
constraint = [NSMutableString new];
|
[b->view addConstraint:mkConstraint(boxView(b, i), b->secondaryStart,
|
||||||
[constraint appendString:b->secondaryDirPrefix];
|
NSLayoutRelationEqual,
|
||||||
[constraint appendString:@"|["];
|
b->view, b->secondaryStart,
|
||||||
[constraint appendString:viewName(i)];
|
1, 0,
|
||||||
[constraint appendString:@"]|"];
|
@"uiBox start secondary constraint")];
|
||||||
addConstraint(b->view, constraint, nil, views);
|
[b->view addConstraint:mkConstraint(boxView(b, i), b->secondaryEnd,
|
||||||
[constraint release];
|
NSLayoutRelationEqual,
|
||||||
|
b->view, b->secondaryEnd,
|
||||||
|
1, 0,
|
||||||
|
@"uiBox start secondary constraint")];
|
||||||
}
|
}
|
||||||
if (!hasStretchy) { // and again to the no-stretchy view
|
if (!hasStretchy) { // and again to the no-stretchy view
|
||||||
constraint = [NSMutableString new];
|
[b->view addConstraint:mkConstraint(b->noStretchyView, b->secondaryStart,
|
||||||
[constraint appendString:b->secondaryDirPrefix];
|
NSLayoutRelationEqual,
|
||||||
[constraint appendString:@"|[noStretchyView]|"];
|
b->view, b->secondaryStart,
|
||||||
addConstraint(b->view, constraint, nil, views);
|
1, 0,
|
||||||
[constraint release];
|
@"uiBox no-stretchy view start secondary constraint")];
|
||||||
|
[b->view addConstraint:mkConstraint(b->noStretchyView, b->secondaryEnd,
|
||||||
|
NSLayoutRelationEqual,
|
||||||
|
b->view, b->secondaryEnd,
|
||||||
|
1, 0,
|
||||||
|
@"uiBox no-stretchy view start secondary constraint")];
|
||||||
}
|
}
|
||||||
|
|
||||||
[metrics release];
|
// finally, set sizes for stretchy controls
|
||||||
[views release];
|
if (hasStretchy)
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
if (!isStretchy(b, i))
|
||||||
|
continue;
|
||||||
|
prev = boxView(b, i);
|
||||||
|
if (prev == firstStretchy)
|
||||||
|
continue;
|
||||||
|
[b->view addConstraint:mkConstraint(prev, b->primarySize,
|
||||||
|
NSLayoutRelationEqual,
|
||||||
|
firstStretchy, b->primarySize,
|
||||||
|
1, 0,
|
||||||
|
@"uiBox stretchy sizing")];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void uiBoxAppend(uiBox *b, uiControl *c, int stretchy)
|
void uiBoxAppend(uiBox *b, uiControl *c, int stretchy)
|
||||||
|
@ -287,13 +293,19 @@ static uiBox *finishNewBox(BOOL vertical)
|
||||||
|
|
||||||
b->vertical = vertical;
|
b->vertical = vertical;
|
||||||
if (b->vertical) {
|
if (b->vertical) {
|
||||||
b->primaryDirPrefix = @"V:";
|
b->primaryStart = NSLayoutAttributeTop;
|
||||||
b->secondaryDirPrefix = @"H:";
|
b->primaryEnd = NSLayoutAttributeBottom;
|
||||||
|
b->secondaryStart = NSLayoutAttributeLeading;
|
||||||
|
b->secondaryEnd = NSLayoutAttributeTrailing;
|
||||||
|
b->primarySize = NSLayoutAttributeHeight;
|
||||||
b->primaryOrientation = NSLayoutConstraintOrientationVertical;
|
b->primaryOrientation = NSLayoutConstraintOrientationVertical;
|
||||||
b->secondaryOrientation = NSLayoutConstraintOrientationHorizontal;
|
b->secondaryOrientation = NSLayoutConstraintOrientationHorizontal;
|
||||||
} else {
|
} else {
|
||||||
b->primaryDirPrefix = @"H:";
|
b->primaryStart = NSLayoutAttributeLeading;
|
||||||
b->secondaryDirPrefix = @"V:";
|
b->primaryEnd = NSLayoutAttributeTrailing;
|
||||||
|
b->secondaryStart = NSLayoutAttributeTop;
|
||||||
|
b->secondaryEnd = NSLayoutAttributeBottom;
|
||||||
|
b->primarySize = NSLayoutAttributeWidth;
|
||||||
b->primaryOrientation = NSLayoutConstraintOrientationHorizontal;
|
b->primaryOrientation = NSLayoutConstraintOrientationHorizontal;
|
||||||
b->secondaryOrientation = NSLayoutConstraintOrientationVertical;
|
b->secondaryOrientation = NSLayoutConstraintOrientationVertical;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,8 @@ extern void uninitAlloc(void);
|
||||||
// autolayout.m
|
// autolayout.m
|
||||||
extern NSLayoutConstraint *mkConstraint(id view1, NSLayoutAttribute attr1, NSLayoutRelation relation, id view2, NSLayoutAttribute attr2, CGFloat multiplier, CGFloat c, NSString *desc);
|
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 NSLayoutPriority horzHuggingPri(NSView *view);
|
||||||
|
extern void setHuggingPri(NSView *view, NSLayoutPriority priority, NSLayoutConstraintOrientation orientation);
|
||||||
|
extern NSLayoutPriority horzHuggingPri(NSView *view);
|
||||||
extern void setHorzHuggingPri(NSView *view, NSLayoutPriority priority);
|
extern void setHorzHuggingPri(NSView *view, NSLayoutPriority priority);
|
||||||
extern NSLayoutPriority vertHuggingPri(NSView *view);
|
extern NSLayoutPriority vertHuggingPri(NSView *view);
|
||||||
extern void setVertHuggingPri(NSView *view, NSLayoutPriority priority);
|
extern void setVertHuggingPri(NSView *view, NSLayoutPriority priority);
|
||||||
|
|
Loading…
Reference in New Issue