First Commit
This commit is contained in:
commit
ae0fab9400
424 files changed
+71006
No files matched your search
@@ -0,0 +1,480 @@
|
||||
// 15 august 2015
|
||||
#import "uipriv_darwin.h"
|
||||
|
||||
// TODO hiding all stretchy controls still hugs trailing edge
|
||||
|
||||
@interface boxChild : NSObject
|
||||
@property uiControl *c;
|
||||
@property BOOL stretchy;
|
||||
@property NSLayoutPriority oldPrimaryHuggingPri;
|
||||
@property NSLayoutPriority oldSecondaryHuggingPri;
|
||||
- (NSView *)view;
|
||||
@end
|
||||
|
||||
@interface boxView : NSView {
|
||||
uiBox *b;
|
||||
NSMutableArray *children;
|
||||
BOOL vertical;
|
||||
int padded;
|
||||
|
||||
NSLayoutConstraint *first;
|
||||
NSMutableArray *inBetweens;
|
||||
NSLayoutConstraint *last;
|
||||
NSMutableArray *otherConstraints;
|
||||
|
||||
NSLayoutAttribute primaryStart;
|
||||
NSLayoutAttribute primaryEnd;
|
||||
NSLayoutAttribute secondaryStart;
|
||||
NSLayoutAttribute secondaryEnd;
|
||||
NSLayoutAttribute primarySize;
|
||||
NSLayoutConstraintOrientation primaryOrientation;
|
||||
NSLayoutConstraintOrientation secondaryOrientation;
|
||||
}
|
||||
- (id)initWithVertical:(BOOL)vert b:(uiBox *)bb;
|
||||
- (void)onDestroy;
|
||||
- (void)removeOurConstraints;
|
||||
- (void)syncEnableStates:(int)enabled;
|
||||
- (CGFloat)paddingAmount;
|
||||
- (void)establishOurConstraints;
|
||||
- (void)append:(uiControl *)c stretchy:(int)stretchy;
|
||||
- (void)delete:(int)n;
|
||||
- (int)numChildren;
|
||||
- (int)isPadded;
|
||||
- (void)setPadded:(int)p;
|
||||
- (BOOL)hugsTrailing;
|
||||
- (BOOL)hugsBottom;
|
||||
- (int)nStretchy;
|
||||
@end
|
||||
|
||||
struct uiBox {
|
||||
uiDarwinControl c;
|
||||
boxView *view;
|
||||
};
|
||||
|
||||
@implementation boxChild
|
||||
|
||||
- (NSView *)view
|
||||
{
|
||||
return (NSView *) uiControlHandle(self.c);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation boxView
|
||||
|
||||
- (id)initWithVertical:(BOOL)vert b:(uiBox *)bb
|
||||
{
|
||||
self = [super initWithFrame:NSZeroRect];
|
||||
if (self != nil) {
|
||||
// the weird names vert and bb are to shut the compiler up about shadowing because implicit this/self is stupid
|
||||
self->b = bb;
|
||||
self->vertical = vert;
|
||||
self->padded = 0;
|
||||
self->children = [NSMutableArray new];
|
||||
|
||||
self->inBetweens = [NSMutableArray new];
|
||||
self->otherConstraints = [NSMutableArray new];
|
||||
|
||||
if (self->vertical) {
|
||||
self->primaryStart = NSLayoutAttributeTop;
|
||||
self->primaryEnd = NSLayoutAttributeBottom;
|
||||
self->secondaryStart = NSLayoutAttributeLeading;
|
||||
self->secondaryEnd = NSLayoutAttributeTrailing;
|
||||
self->primarySize = NSLayoutAttributeHeight;
|
||||
self->primaryOrientation = NSLayoutConstraintOrientationVertical;
|
||||
self->secondaryOrientation = NSLayoutConstraintOrientationHorizontal;
|
||||
} else {
|
||||
self->primaryStart = NSLayoutAttributeLeading;
|
||||
self->primaryEnd = NSLayoutAttributeTrailing;
|
||||
self->secondaryStart = NSLayoutAttributeTop;
|
||||
self->secondaryEnd = NSLayoutAttributeBottom;
|
||||
self->primarySize = NSLayoutAttributeWidth;
|
||||
self->primaryOrientation = NSLayoutConstraintOrientationHorizontal;
|
||||
self->secondaryOrientation = NSLayoutConstraintOrientationVertical;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)onDestroy
|
||||
{
|
||||
boxChild *bc;
|
||||
|
||||
[self removeOurConstraints];
|
||||
[self->inBetweens release];
|
||||
[self->otherConstraints release];
|
||||
|
||||
for (bc in self->children) {
|
||||
uiControlSetParent(bc.c, NULL);
|
||||
uiDarwinControlSetSuperview(uiDarwinControl(bc.c), nil);
|
||||
uiControlDestroy(bc.c);
|
||||
}
|
||||
[self->children release];
|
||||
}
|
||||
|
||||
- (void)removeOurConstraints
|
||||
{
|
||||
if (self->first != nil) {
|
||||
[self removeConstraint:self->first];
|
||||
[self->first release];
|
||||
self->first = nil;
|
||||
}
|
||||
if ([self->inBetweens count] != 0) {
|
||||
[self removeConstraints:self->inBetweens];
|
||||
[self->inBetweens removeAllObjects];
|
||||
}
|
||||
if (self->last != nil) {
|
||||
[self removeConstraint:self->last];
|
||||
[self->last release];
|
||||
self->last = nil;
|
||||
}
|
||||
if ([self->otherConstraints count] != 0) {
|
||||
[self removeConstraints:self->otherConstraints];
|
||||
[self->otherConstraints removeAllObjects];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)syncEnableStates:(int)enabled
|
||||
{
|
||||
boxChild *bc;
|
||||
|
||||
for (bc in self->children)
|
||||
uiDarwinControlSyncEnableState(uiDarwinControl(bc.c), enabled);
|
||||
}
|
||||
|
||||
- (CGFloat)paddingAmount
|
||||
{
|
||||
if (!self->padded)
|
||||
return 0.0;
|
||||
return uiDarwinPaddingAmount(NULL);
|
||||
}
|
||||
|
||||
- (void)establishOurConstraints
|
||||
{
|
||||
boxChild *bc;
|
||||
CGFloat padding;
|
||||
NSView *prev;
|
||||
NSLayoutConstraint *c;
|
||||
BOOL (*hugsSecondary)(uiDarwinControl *);
|
||||
|
||||
[self removeOurConstraints];
|
||||
if ([self->children count] == 0)
|
||||
return;
|
||||
padding = [self paddingAmount];
|
||||
|
||||
// first arrange in the primary direction
|
||||
prev = nil;
|
||||
for (bc in self->children) {
|
||||
if (!uiControlVisible(bc.c))
|
||||
continue;
|
||||
if (prev == nil) { // first view
|
||||
self->first = uiprivMkConstraint(self, self->primaryStart,
|
||||
NSLayoutRelationEqual,
|
||||
[bc view], self->primaryStart,
|
||||
1, 0,
|
||||
@"uiBox first primary constraint");
|
||||
[self addConstraint:self->first];
|
||||
[self->first retain];
|
||||
prev = [bc view];
|
||||
continue;
|
||||
}
|
||||
// not the first; link it
|
||||
c = uiprivMkConstraint(prev, self->primaryEnd,
|
||||
NSLayoutRelationEqual,
|
||||
[bc view], self->primaryStart,
|
||||
1, -padding,
|
||||
@"uiBox in-between primary constraint");
|
||||
[self addConstraint:c];
|
||||
[self->inBetweens addObject:c];
|
||||
prev = [bc view];
|
||||
}
|
||||
if (prev == nil) // no control visible; act as if no controls
|
||||
return;
|
||||
self->last = uiprivMkConstraint(prev, self->primaryEnd,
|
||||
NSLayoutRelationEqual,
|
||||
self, self->primaryEnd,
|
||||
1, 0,
|
||||
@"uiBox last primary constraint");
|
||||
[self addConstraint:self->last];
|
||||
[self->last retain];
|
||||
|
||||
// then arrange in the secondary direction
|
||||
hugsSecondary = uiDarwinControlHugsTrailingEdge;
|
||||
if (!self->vertical)
|
||||
hugsSecondary = uiDarwinControlHugsBottom;
|
||||
for (bc in self->children) {
|
||||
if (!uiControlVisible(bc.c))
|
||||
continue;
|
||||
c = uiprivMkConstraint(self, self->secondaryStart,
|
||||
NSLayoutRelationEqual,
|
||||
[bc view], self->secondaryStart,
|
||||
1, 0,
|
||||
@"uiBox secondary start constraint");
|
||||
[self addConstraint:c];
|
||||
[self->otherConstraints addObject:c];
|
||||
c = uiprivMkConstraint([bc view], self->secondaryEnd,
|
||||
NSLayoutRelationLessThanOrEqual,
|
||||
self, self->secondaryEnd,
|
||||
1, 0,
|
||||
@"uiBox secondary end <= constraint");
|
||||
if ((*hugsSecondary)(uiDarwinControl(bc.c)))
|
||||
[c setPriority:NSLayoutPriorityDefaultLow];
|
||||
[self addConstraint:c];
|
||||
[self->otherConstraints addObject:c];
|
||||
c = uiprivMkConstraint([bc view], self->secondaryEnd,
|
||||
NSLayoutRelationEqual,
|
||||
self, self->secondaryEnd,
|
||||
1, 0,
|
||||
@"uiBox secondary end == constraint");
|
||||
if (!(*hugsSecondary)(uiDarwinControl(bc.c)))
|
||||
[c setPriority:NSLayoutPriorityDefaultLow];
|
||||
[self addConstraint:c];
|
||||
[self->otherConstraints addObject:c];
|
||||
}
|
||||
|
||||
// and make all stretchy controls the same size
|
||||
if ([self nStretchy] == 0)
|
||||
return;
|
||||
prev = nil; // first stretchy view
|
||||
for (bc in self->children) {
|
||||
if (!uiControlVisible(bc.c))
|
||||
continue;
|
||||
if (!bc.stretchy)
|
||||
continue;
|
||||
if (prev == nil) {
|
||||
prev = [bc view];
|
||||
continue;
|
||||
}
|
||||
c = uiprivMkConstraint(prev, self->primarySize,
|
||||
NSLayoutRelationEqual,
|
||||
[bc view], self->primarySize,
|
||||
1, 0,
|
||||
@"uiBox stretchy size constraint");
|
||||
[self addConstraint:c];
|
||||
[self->otherConstraints addObject:c];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)append:(uiControl *)c stretchy:(int)stretchy
|
||||
{
|
||||
boxChild *bc;
|
||||
NSLayoutPriority priority;
|
||||
int oldnStretchy;
|
||||
|
||||
bc = [boxChild new];
|
||||
bc.c = c;
|
||||
bc.stretchy = stretchy;
|
||||
bc.oldPrimaryHuggingPri = uiDarwinControlHuggingPriority(uiDarwinControl(bc.c), self->primaryOrientation);
|
||||
bc.oldSecondaryHuggingPri = uiDarwinControlHuggingPriority(uiDarwinControl(bc.c), self->secondaryOrientation);
|
||||
|
||||
uiControlSetParent(bc.c, uiControl(self->b));
|
||||
uiDarwinControlSetSuperview(uiDarwinControl(bc.c), self);
|
||||
uiDarwinControlSyncEnableState(uiDarwinControl(bc.c), uiControlEnabledToUser(uiControl(self->b)));
|
||||
|
||||
// if a control is stretchy, it should not hug in the primary direction
|
||||
// otherwise, it should *forcibly* hug
|
||||
if (bc.stretchy)
|
||||
priority = NSLayoutPriorityDefaultLow;
|
||||
else
|
||||
// LONGTERM will default high work?
|
||||
priority = NSLayoutPriorityRequired;
|
||||
uiDarwinControlSetHuggingPriority(uiDarwinControl(bc.c), priority, self->primaryOrientation);
|
||||
// make sure controls don't hug their secondary direction so they fill the width of the view
|
||||
uiDarwinControlSetHuggingPriority(uiDarwinControl(bc.c), NSLayoutPriorityDefaultLow, self->secondaryOrientation);
|
||||
|
||||
oldnStretchy = [self nStretchy];
|
||||
[self->children addObject:bc];
|
||||
|
||||
[self establishOurConstraints];
|
||||
if (bc.stretchy)
|
||||
if (oldnStretchy == 0)
|
||||
uiDarwinNotifyEdgeHuggingChanged(uiDarwinControl(self->b));
|
||||
|
||||
[bc release]; // we don't need the initial reference now
|
||||
}
|
||||
|
||||
- (void)delete:(int)n
|
||||
{
|
||||
boxChild *bc;
|
||||
int stretchy;
|
||||
|
||||
bc = (boxChild *) [self->children objectAtIndex:n];
|
||||
stretchy = bc.stretchy;
|
||||
|
||||
uiControlSetParent(bc.c, NULL);
|
||||
uiDarwinControlSetSuperview(uiDarwinControl(bc.c), nil);
|
||||
|
||||
uiDarwinControlSetHuggingPriority(uiDarwinControl(bc.c), bc.oldPrimaryHuggingPri, self->primaryOrientation);
|
||||
uiDarwinControlSetHuggingPriority(uiDarwinControl(bc.c), bc.oldSecondaryHuggingPri, self->secondaryOrientation);
|
||||
|
||||
[self->children removeObjectAtIndex:n];
|
||||
|
||||
[self establishOurConstraints];
|
||||
if (stretchy)
|
||||
if ([self nStretchy] == 0)
|
||||
uiDarwinNotifyEdgeHuggingChanged(uiDarwinControl(self->b));
|
||||
}
|
||||
|
||||
- (int)numChildren
|
||||
{
|
||||
return (int) [self->children count];
|
||||
}
|
||||
|
||||
- (int)isPadded
|
||||
{
|
||||
return self->padded;
|
||||
}
|
||||
|
||||
- (void)setPadded:(int)p
|
||||
{
|
||||
CGFloat padding;
|
||||
NSLayoutConstraint *c;
|
||||
|
||||
self->padded = p;
|
||||
padding = [self paddingAmount];
|
||||
for (c in self->inBetweens)
|
||||
[c setConstant:-padding];
|
||||
}
|
||||
|
||||
- (BOOL)hugsTrailing
|
||||
{
|
||||
if (self->vertical) // always hug if vertical
|
||||
return YES;
|
||||
return [self nStretchy] != 0;
|
||||
}
|
||||
|
||||
- (BOOL)hugsBottom
|
||||
{
|
||||
if (!self->vertical) // always hug if horizontal
|
||||
return YES;
|
||||
return [self nStretchy] != 0;
|
||||
}
|
||||
|
||||
- (int)nStretchy
|
||||
{
|
||||
boxChild *bc;
|
||||
int n;
|
||||
|
||||
n = 0;
|
||||
for (bc in self->children) {
|
||||
if (!uiControlVisible(bc.c))
|
||||
continue;
|
||||
if (bc.stretchy)
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
static void uiBoxDestroy(uiControl *c)
|
||||
{
|
||||
uiBox *b = uiBox(c);
|
||||
|
||||
[b->view onDestroy];
|
||||
[b->view release];
|
||||
uiFreeControl(uiControl(b));
|
||||
}
|
||||
|
||||
uiDarwinControlDefaultHandle(uiBox, view)
|
||||
uiDarwinControlDefaultParent(uiBox, view)
|
||||
uiDarwinControlDefaultSetParent(uiBox, view)
|
||||
uiDarwinControlDefaultToplevel(uiBox, view)
|
||||
uiDarwinControlDefaultVisible(uiBox, view)
|
||||
uiDarwinControlDefaultShow(uiBox, view)
|
||||
uiDarwinControlDefaultHide(uiBox, view)
|
||||
uiDarwinControlDefaultEnabled(uiBox, view)
|
||||
uiDarwinControlDefaultEnable(uiBox, view)
|
||||
uiDarwinControlDefaultDisable(uiBox, view)
|
||||
|
||||
static void uiBoxSyncEnableState(uiDarwinControl *c, int enabled)
|
||||
{
|
||||
uiBox *b = uiBox(c);
|
||||
|
||||
if (uiDarwinShouldStopSyncEnableState(uiDarwinControl(b), enabled))
|
||||
return;
|
||||
[b->view syncEnableStates:enabled];
|
||||
}
|
||||
|
||||
uiDarwinControlDefaultSetSuperview(uiBox, view)
|
||||
|
||||
static BOOL uiBoxHugsTrailingEdge(uiDarwinControl *c)
|
||||
{
|
||||
uiBox *b = uiBox(c);
|
||||
|
||||
return [b->view hugsTrailing];
|
||||
}
|
||||
|
||||
static BOOL uiBoxHugsBottom(uiDarwinControl *c)
|
||||
{
|
||||
uiBox *b = uiBox(c);
|
||||
|
||||
return [b->view hugsBottom];
|
||||
}
|
||||
|
||||
static void uiBoxChildEdgeHuggingChanged(uiDarwinControl *c)
|
||||
{
|
||||
uiBox *b = uiBox(c);
|
||||
|
||||
[b->view establishOurConstraints];
|
||||
}
|
||||
|
||||
uiDarwinControlDefaultHuggingPriority(uiBox, view)
|
||||
uiDarwinControlDefaultSetHuggingPriority(uiBox, view)
|
||||
|
||||
static void uiBoxChildVisibilityChanged(uiDarwinControl *c)
|
||||
{
|
||||
uiBox *b = uiBox(c);
|
||||
|
||||
[b->view establishOurConstraints];
|
||||
}
|
||||
|
||||
void uiBoxAppend(uiBox *b, uiControl *c, int stretchy)
|
||||
{
|
||||
// LONGTERM on other platforms
|
||||
// or at leat allow this and implicitly turn it into a spacer
|
||||
if (c == NULL)
|
||||
uiprivUserBug("You cannot add NULL to a uiBox.");
|
||||
[b->view append:c stretchy:stretchy];
|
||||
}
|
||||
|
||||
void uiBoxDelete(uiBox *b, int n)
|
||||
{
|
||||
[b->view delete:n];
|
||||
}
|
||||
|
||||
int uiBoxNumChildren(uiBox *b)
|
||||
{
|
||||
return [b->view numChildren];
|
||||
}
|
||||
|
||||
int uiBoxPadded(uiBox *b)
|
||||
{
|
||||
return [b->view isPadded];
|
||||
}
|
||||
|
||||
void uiBoxSetPadded(uiBox *b, int padded)
|
||||
{
|
||||
[b->view setPadded:padded];
|
||||
}
|
||||
|
||||
static uiBox *finishNewBox(BOOL vertical)
|
||||
{
|
||||
uiBox *b;
|
||||
|
||||
uiDarwinNewControl(uiBox, b);
|
||||
|
||||
b->view = [[boxView alloc] initWithVertical:vertical b:b];
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
uiBox *uiNewHorizontalBox(void)
|
||||
{
|
||||
return finishNewBox(NO);
|
||||
}
|
||||
|
||||
uiBox *uiNewVerticalBox(void)
|
||||
{
|
||||
return finishNewBox(YES);
|
||||
}
|
||||
Reference in new issue
Block a user