2016-06-11 22:09:53 -05:00
|
|
|
// 11 june 2016
|
|
|
|
#import "uipriv_darwin.h"
|
|
|
|
|
|
|
|
// TODO wrap the child in a view if its align isn't fill
|
|
|
|
// maybe it's easier to do it regardless of align
|
2016-06-11 22:28:51 -05:00
|
|
|
@interface gridChild : NSObject
|
2016-06-11 22:09:53 -05:00
|
|
|
@property uiControl *c;
|
|
|
|
@property intmax_t left;
|
|
|
|
@property intmax_t top;
|
2016-06-11 22:28:51 -05:00
|
|
|
@property intmax_t xspan;
|
|
|
|
@property intmax_t yspan;
|
2016-06-11 22:09:53 -05:00
|
|
|
@property int hexpand;
|
|
|
|
@property uiAlign halign;
|
|
|
|
@property int vexpand;
|
|
|
|
@property uiAlign valign;
|
|
|
|
|
|
|
|
@property NSLayoutPriority oldHorzHuggingPri;
|
|
|
|
@property NSLayoutPriority oldVertHuggingPri;
|
|
|
|
- (NSView *)view;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@interface gridView : NSView {
|
|
|
|
uiGrid *g;
|
|
|
|
NSMutableArray *children;
|
|
|
|
int padded;
|
|
|
|
uintmax_t nhexpand;
|
|
|
|
uintmax_t nvexpand;
|
|
|
|
|
|
|
|
NSMutableArray *edges;
|
|
|
|
NSMutableArray *inBetweens;
|
|
|
|
}
|
|
|
|
- (id)initWithG:(uiGrid *)gg;
|
|
|
|
- (void)onDestroy;
|
|
|
|
- (void)removeOurConstraints;
|
|
|
|
- (void)syncEnableStates:(int)enabled;
|
|
|
|
- (CGFloat)paddingAmount;
|
|
|
|
- (void)establishOurConstraints;
|
|
|
|
- (void)append:(gridChild *)gc;
|
|
|
|
- (void)insert:(gridChild *)gc after:(uiControl *)c at:(uiAt)at;
|
|
|
|
- (int)isPadded;
|
|
|
|
- (void)setPadded:(int)p;
|
|
|
|
- (BOOL)hugsTrailing;
|
|
|
|
- (BOOL)hugsBottom;
|
|
|
|
@end
|
|
|
|
|
|
|
|
struct uiGrid {
|
|
|
|
uiDarwinControl c;
|
|
|
|
gridView *view;
|
|
|
|
};
|
|
|
|
|
2016-06-11 22:28:51 -05:00
|
|
|
@implementation gridChild
|
2016-06-11 22:09:53 -05:00
|
|
|
|
|
|
|
- (NSView *)view
|
|
|
|
{
|
|
|
|
return (NSView *) uiControlHandle(self.c);
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation gridView
|
|
|
|
|
|
|
|
- (id)initWithG:(uiGrid *)gg
|
|
|
|
{
|
|
|
|
self = [super initWithFrame:NSZeroRect];
|
|
|
|
if (self != nil) {
|
|
|
|
self->g = gg;
|
|
|
|
self->padded = 0;
|
|
|
|
self->children = [NSMutableArray new];
|
2016-06-11 22:28:51 -05:00
|
|
|
self->nhexpand = 0;
|
|
|
|
self->nvexpand = 0;
|
2016-06-11 22:09:53 -05:00
|
|
|
|
|
|
|
self->edges = [NSMutableArray new];
|
|
|
|
self->inBetweens = [NSMutableArray new];
|
|
|
|
}
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)onDestroy
|
|
|
|
{
|
|
|
|
gridChild *gc;
|
|
|
|
|
|
|
|
[self removeOurConstraints];
|
|
|
|
[self->edges release];
|
|
|
|
[self->inBetweens release];
|
|
|
|
|
|
|
|
for (gc in self->children) {
|
|
|
|
uiControlSetParent(gc.c, NULL);
|
|
|
|
uiDarwinControlSetSuperview(uiDarwinControl(gc.c), nil);
|
|
|
|
uiControlDestroy(gc.c);
|
|
|
|
}
|
|
|
|
[self->children release];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)removeOurConstraints
|
|
|
|
{
|
|
|
|
if ([self->edges count] != 0) {
|
|
|
|
[self removeConstraints:self->edges];
|
|
|
|
[self->edges removeAllObjects];
|
|
|
|
}
|
|
|
|
if ([self->inBetweens count] != 0) {
|
|
|
|
[self removeConstraints:self->inBetweens];
|
|
|
|
[self->inBetweens removeAllObjects];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)syncEnableStates:(int)enabled
|
|
|
|
{
|
|
|
|
gridChild *gc;
|
|
|
|
|
|
|
|
for (gc in self->children)
|
|
|
|
uiDarwinControlSyncEnableState(uiDarwinControl(gc.c), enabled);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (CGFloat)paddingAmount
|
|
|
|
{
|
|
|
|
if (!self->padded)
|
|
|
|
return 0.0;
|
|
|
|
return uiDarwinPaddingAmount(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)establishOurConstraints
|
|
|
|
{
|
|
|
|
gridChild *gc;
|
|
|
|
CGFloat padding;
|
|
|
|
intmax_t xmin, ymin;
|
|
|
|
intmax_t xmax, ymax;
|
|
|
|
intmax_t xcount, ycount;
|
|
|
|
BOOL first;
|
|
|
|
int **gg;
|
|
|
|
intmax_t x, y;
|
|
|
|
int i;
|
|
|
|
NSMutableSet *set;
|
|
|
|
NSNumber *number;
|
|
|
|
NSLayoutConstraint *c;
|
|
|
|
NSView **colviews, **rowviews;
|
2016-06-12 11:31:44 -05:00
|
|
|
NSView *firstView;
|
2016-06-11 22:09:53 -05:00
|
|
|
|
|
|
|
[self removeOurConstraints];
|
|
|
|
if ([self->children count] == 0)
|
|
|
|
return;
|
|
|
|
padding = [self paddingAmount];
|
|
|
|
|
|
|
|
// first, figure out the minimum and maximum row and column numbers
|
|
|
|
first = YES;
|
|
|
|
for (gc in self->children) {
|
|
|
|
if (first) {
|
|
|
|
xmin = gc.left;
|
|
|
|
ymin = gc.top;
|
|
|
|
xmax = gc.left + gc.xspan;
|
|
|
|
ymax = gc.top + gc.yspan;
|
|
|
|
first = NO;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (xmin > gc.left)
|
|
|
|
xmin = gc.left;
|
|
|
|
if (ymin > gc.top)
|
|
|
|
ymin = gc.top;
|
|
|
|
if (xmax < (gc.left + gc.xspan))
|
|
|
|
xmax = gc.left + gc.xspan;
|
|
|
|
if (ymax < (gc.top + gc.yspan))
|
|
|
|
ymax = gc.top + gc.yspan;
|
|
|
|
}
|
|
|
|
xcount = xmax - xmin;
|
|
|
|
ycount = ymax - ymin;
|
|
|
|
|
|
|
|
// now build a topological map of the grid gg[y][x]
|
|
|
|
gg = (int **) uiAlloc(ycount * sizeof (int *), "int[][]");
|
|
|
|
for (y = 0; y < ycount; y++) {
|
|
|
|
gg[y] = (int *) uiAlloc(xcount * sizeof (int), "int[]");
|
|
|
|
for (x = 0; x < xcount; x++)
|
|
|
|
gg[y][x] = -1; // empty
|
|
|
|
}
|
|
|
|
for (i = 0; i < [self->children count]; i++) {
|
|
|
|
gc = (gridChild *) [self->children objectAtIndex:i];
|
|
|
|
for (y = gc.top; y < gc.top + gc.yspan; y++)
|
|
|
|
for (x = gc.left; x < gc.left + gc.xspan; x++)
|
|
|
|
gg[y - ymin][x - xmin] = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
// now establish all the edge constraints
|
|
|
|
// leading edge
|
|
|
|
set = [NSMutableSet new];
|
|
|
|
for (y = 0; y < ycount; y++)
|
|
|
|
[set addObject:[NSNumber numberWithInt:gg[y][0]]];
|
|
|
|
for (number in set)
|
|
|
|
if ([number intValue] != -1) {
|
|
|
|
gc = (gridChild *) [self->children objectAtIndex:[number intValue]];
|
|
|
|
c = mkConstraint(self, NSLayoutAttributeLeading,
|
|
|
|
NSLayoutRelationEqual,
|
|
|
|
[gc view], NSLayoutAttributeLeading,
|
|
|
|
1, 0,
|
|
|
|
@"uiGrid leading edge constraint");
|
|
|
|
[self addConstraint:c];
|
|
|
|
[self->edges addObject:c];
|
|
|
|
}
|
|
|
|
// top
|
|
|
|
[set removeAllObjects];
|
|
|
|
for (x = 0; x < xcount; x++)
|
|
|
|
[set addObject:[NSNumber numberWithInt:gg[0][x]]];
|
|
|
|
for (number in set)
|
|
|
|
if ([number intValue] != -1) {
|
|
|
|
gc = (gridChild *) [self->children objectAtIndex:[number intValue]];
|
|
|
|
c = mkConstraint(self, NSLayoutAttributeTop,
|
|
|
|
NSLayoutRelationEqual,
|
|
|
|
[gc view], NSLayoutAttributeTop,
|
|
|
|
1, 0,
|
|
|
|
@"uiGrid top edge constraint");
|
|
|
|
[self addConstraint:c];
|
|
|
|
[self->edges addObject:c];
|
|
|
|
}
|
|
|
|
// trailing edge
|
|
|
|
[set removeAllObjects];
|
|
|
|
for (y = 0; y < ycount; y++)
|
|
|
|
[set addObject:[NSNumber numberWithInt:gg[y][xcount - 1]]];
|
|
|
|
for (number in set)
|
|
|
|
if ([number intValue] != -1) {
|
|
|
|
gc = (gridChild *) [self->children objectAtIndex:[number intValue]];
|
|
|
|
c = mkConstraint(self, NSLayoutAttributeTrailing,
|
|
|
|
NSLayoutRelationEqual,
|
|
|
|
[gc view], NSLayoutAttributeTrailing,
|
|
|
|
1, 0,
|
|
|
|
@"uiGrid trailing edge constraint");
|
|
|
|
[self addConstraint:c];
|
|
|
|
[self->edges addObject:c];
|
|
|
|
}
|
|
|
|
// bottom
|
|
|
|
[set removeAllObjects];
|
|
|
|
for (x = 0; x < xcount; x++)
|
|
|
|
[set addObject:[NSNumber numberWithInt:gg[ycount - 1][x]]];
|
|
|
|
for (number in set)
|
|
|
|
if ([number intValue] != -1) {
|
|
|
|
gc = (gridChild *) [self->children objectAtIndex:[number intValue]];
|
|
|
|
c = mkConstraint(self, NSLayoutAttributeBottom,
|
|
|
|
NSLayoutRelationEqual,
|
|
|
|
[gc view], NSLayoutAttributeBottom,
|
|
|
|
1, 0,
|
|
|
|
@"uiGrid bottom edge constraint");
|
|
|
|
[self addConstraint:c];
|
|
|
|
[self->edges addObject:c];
|
|
|
|
}
|
2016-06-12 11:31:44 -05:00
|
|
|
|
|
|
|
// now put all the views in the same row and column together
|
|
|
|
for (x = 0; x < xcount; x++) {
|
|
|
|
[set removeAllObjects];
|
|
|
|
for (y = 0; y < ycount; y++)
|
|
|
|
[set addObject:[NSNumber numberWithInt:gg[y][x]]];
|
|
|
|
first = YES;
|
|
|
|
for (number in set) {
|
|
|
|
if ([number intValue] == -1)
|
|
|
|
continue;
|
|
|
|
gc = (gridChild *) [self->children objectAtIndex:[number intValue]];
|
|
|
|
if (first) {
|
|
|
|
firstView = [gc view];
|
|
|
|
first = NO;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
c = mkConstraint([gc view], NSLayoutAttributeLeading,
|
|
|
|
NSLayoutRelationEqual,
|
|
|
|
firstView, NSLayoutAttributeLeading,
|
|
|
|
1, 0,
|
|
|
|
@"uiGrid column left edge constraint");
|
|
|
|
[self addConstraint:c];
|
|
|
|
[self->edges addObject:c];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (y = 0; y < ycount; y++) {
|
|
|
|
[set removeAllObjects];
|
|
|
|
for (x = 0; x < xcount; x++)
|
|
|
|
[set addObject:[NSNumber numberWithInt:gg[y][x]]];
|
|
|
|
first = YES;
|
|
|
|
for (number in set) {
|
|
|
|
if ([number intValue] == -1)
|
|
|
|
continue;
|
|
|
|
gc = (gridChild *) [self->children objectAtIndex:[number intValue]];
|
|
|
|
if (first) {
|
|
|
|
firstView = [gc view];
|
|
|
|
first = NO;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
c = mkConstraint([gc view], NSLayoutAttributeTop,
|
|
|
|
NSLayoutRelationEqual,
|
|
|
|
firstView, NSLayoutAttributeTop,
|
|
|
|
1, 0,
|
|
|
|
@"uiGrid row top edge constraint");
|
|
|
|
[self addConstraint:c];
|
|
|
|
[self->edges addObject:c];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO
|
|
|
|
return;
|
2016-06-11 22:09:53 -05:00
|
|
|
|
|
|
|
// now go through every row and column and extract SOME view from that row and column for the inner constraints
|
|
|
|
// if it turns out that a row or column is totally empty, duplicate the one to the left (this has the effect of collapsing empty rows)
|
|
|
|
// note that the edges cannot be empty because we built a smallest fitting rectangle way back in step 1
|
|
|
|
colviews = (NSView **) uiAlloc(xcount * sizeof (NSView *), "NSView *[]");
|
|
|
|
for (x = 0; x < xcount; x++) {
|
|
|
|
for (y = 0; y < ycount; y++)
|
|
|
|
if (gg[y][x] != -1) {
|
|
|
|
gc = (gridChild *) [self->children objectAtIndex:gg[y][x]];
|
|
|
|
colviews[x] = [gc view];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (colviews[x] == nil)
|
|
|
|
colviews[x] = colviews[x - 1];
|
|
|
|
}
|
|
|
|
rowviews = (NSView **) uiAlloc(ycount * sizeof (NSView *), "NSView *[]");
|
|
|
|
for (y = 0; y < ycount; y++) {
|
|
|
|
for (x = 0; x < xcount; x++)
|
|
|
|
if (gg[y][x] != -1) {
|
|
|
|
gc = (gridChild *) [self->children objectAtIndex:gg[y][x]];
|
|
|
|
rowviews[y] = [gc view];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (rowviews[y] == nil)
|
2016-06-11 22:42:58 -05:00
|
|
|
rowviews[y] = rowviews[y - 1];
|
2016-06-11 22:09:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// now string all the views together
|
|
|
|
for (gc in self->children) {
|
|
|
|
if (gc.left != xmin) {
|
|
|
|
c = mkConstraint([gc view], NSLayoutAttributeLeading,
|
|
|
|
NSLayoutRelationEqual,
|
|
|
|
colviews[(gc.left - 1) - xmin], NSLayoutAttributeTrailing,
|
|
|
|
1, padding,
|
|
|
|
@"uiGrid leading constraint");
|
|
|
|
[self addConstraint:c];
|
|
|
|
[self->inBetweens addObject:c];
|
|
|
|
}
|
|
|
|
if (gc.top != ymin) {
|
|
|
|
c = mkConstraint([gc view], NSLayoutAttributeTop,
|
|
|
|
NSLayoutRelationEqual,
|
|
|
|
rowviews[(gc.top - 1) - ymin], NSLayoutAttributeBottom,
|
|
|
|
1, padding,
|
|
|
|
@"uiGrid top constraint");
|
|
|
|
[self addConstraint:c];
|
|
|
|
[self->inBetweens addObject:c];
|
|
|
|
}
|
|
|
|
if ((gc.left + gc.xspan) != xmax) {
|
|
|
|
c = mkConstraint([gc view], NSLayoutAttributeTrailing,
|
|
|
|
NSLayoutRelationEqual,
|
|
|
|
colviews[(gc.left + gc.xspan) - xmin], NSLayoutAttributeLeading,
|
|
|
|
1, -padding,
|
|
|
|
@"uiGrid trailing constraint");
|
|
|
|
[self addConstraint:c];
|
|
|
|
[self->inBetweens addObject:c];
|
|
|
|
}
|
|
|
|
if ((gc.top + gc.yspan) != ymax) {
|
|
|
|
c = mkConstraint([gc view], NSLayoutAttributeBottom,
|
|
|
|
NSLayoutRelationEqual,
|
|
|
|
rowviews[(gc.top + gc.yspan) - ymin], NSLayoutAttributeTop,
|
|
|
|
1, -padding,
|
|
|
|
@"uiGrid bottom constraint");
|
|
|
|
[self addConstraint:c];
|
|
|
|
[self->inBetweens addObject:c];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO make all expanding rows/columns the same height/width
|
|
|
|
|
|
|
|
// and finally clean up
|
|
|
|
uiFree(colviews);
|
|
|
|
uiFree(rowviews);
|
2016-06-12 11:31:44 -05:00
|
|
|
[set release];
|
2016-06-11 22:09:53 -05:00
|
|
|
for (y = 0; y < ycount; y++)
|
|
|
|
uiFree(gg[y]);
|
|
|
|
uiFree(gg);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)append:(gridChild *)gc
|
|
|
|
{
|
|
|
|
NSLayoutPriority priority;
|
|
|
|
BOOL update;
|
|
|
|
intmax_t oldn;
|
|
|
|
|
|
|
|
uiControlSetParent(gc.c, uiControl(self->g));
|
|
|
|
uiDarwinControlSetSuperview(uiDarwinControl(gc.c), self);
|
|
|
|
uiDarwinControlSyncEnableState(uiDarwinControl(gc.c), uiControlEnabledToUser(uiControl(self->g)));
|
|
|
|
|
|
|
|
// if a control expands horizontally, it should not hug horizontally
|
|
|
|
// otherwise, it should *forcibly* hug
|
|
|
|
if (gc.hexpand)
|
|
|
|
priority = NSLayoutPriorityDefaultLow;
|
|
|
|
else
|
|
|
|
// LONGTERM will default high work?
|
|
|
|
priority = NSLayoutPriorityRequired;
|
|
|
|
uiDarwinControlSetHuggingPriority(uiDarwinControl(gc.c), priority, NSLayoutConstraintOrientationHorizontal);
|
|
|
|
// same for vertical direction
|
|
|
|
if (gc.vexpand)
|
|
|
|
priority = NSLayoutPriorityDefaultLow;
|
|
|
|
else
|
|
|
|
// LONGTERM will default high work?
|
|
|
|
priority = NSLayoutPriorityRequired;
|
|
|
|
uiDarwinControlSetHuggingPriority(uiDarwinControl(gc.c), priority, NSLayoutConstraintOrientationVertical);
|
|
|
|
|
|
|
|
[self->children addObject:gc];
|
|
|
|
|
|
|
|
[self establishOurConstraints];
|
|
|
|
update = NO;
|
2016-06-11 22:28:51 -05:00
|
|
|
if (gc.hexpand) {
|
2016-06-11 22:09:53 -05:00
|
|
|
oldn = self->nhexpand;
|
|
|
|
self->nhexpand++;
|
|
|
|
if (oldn == 0)
|
|
|
|
update = YES;
|
|
|
|
}
|
2016-06-11 22:28:51 -05:00
|
|
|
if (gc.vexpand) {
|
2016-06-11 22:09:53 -05:00
|
|
|
oldn = self->nvexpand;
|
|
|
|
self->nvexpand++;
|
|
|
|
if (oldn == 0)
|
|
|
|
update = YES;
|
|
|
|
}
|
|
|
|
if (update)
|
|
|
|
uiDarwinNotifyEdgeHuggingChanged(uiDarwinControl(self->g));
|
|
|
|
|
|
|
|
[gc release]; // we don't need the initial reference now
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)insert:(gridChild *)gc after:(uiControl *)c at:(uiAt)at
|
|
|
|
{
|
|
|
|
gridChild *other;
|
|
|
|
BOOL found;
|
|
|
|
|
|
|
|
found = NO;
|
|
|
|
for (other in self->children)
|
|
|
|
if (other.c == c) {
|
|
|
|
found = YES;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!found)
|
|
|
|
userbug("Existing control %p is not in grid %p; you cannot add other controls next to it", c, self->g);
|
|
|
|
|
|
|
|
switch (at) {
|
|
|
|
case uiAtLeading:
|
|
|
|
gc.left = other.left - gc.xspan;
|
|
|
|
gc.top = other.top;
|
|
|
|
break;
|
|
|
|
case uiAtTop:
|
|
|
|
gc.left = other.left;
|
|
|
|
gc.top = other.top - gc.yspan;
|
|
|
|
break;
|
|
|
|
case uiAtTrailing:
|
|
|
|
gc.left = other.left + other.xspan;
|
|
|
|
gc.top = other.top;
|
|
|
|
break;
|
|
|
|
case uiAtBottom:
|
|
|
|
gc.left = other.left;
|
|
|
|
gc.top = other.top + other.yspan;
|
|
|
|
break;
|
|
|
|
// TODO add error checks to ALL enums
|
|
|
|
}
|
|
|
|
|
|
|
|
[self append:gc];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (int)isPadded
|
|
|
|
{
|
|
|
|
return self->padded;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setPadded:(int)p
|
|
|
|
{
|
|
|
|
CGFloat padding;
|
|
|
|
NSLayoutConstraint *c;
|
|
|
|
|
2016-06-11 22:52:35 -05:00
|
|
|
dispatch_after(
|
|
|
|
dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC),
|
|
|
|
dispatch_get_main_queue(),
|
|
|
|
^{ [[self window] visualizeConstraints:[self constraints]]; }
|
|
|
|
);
|
2016-06-11 22:09:53 -05:00
|
|
|
self->padded = p;
|
|
|
|
padding = [self paddingAmount];
|
|
|
|
for (c in self->inBetweens)
|
|
|
|
switch ([c firstAttribute]) {
|
|
|
|
case NSLayoutAttributeLeading:
|
|
|
|
case NSLayoutAttributeTop:
|
|
|
|
[c setConstant:padding];
|
|
|
|
break;
|
|
|
|
case NSLayoutAttributeTrailing:
|
|
|
|
case NSLayoutAttributeBottom:
|
|
|
|
[c setConstant:-padding];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)hugsTrailing
|
|
|
|
{
|
|
|
|
// only hug if we have horizontally expanding
|
|
|
|
return self->nhexpand != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)hugsBottom
|
|
|
|
{
|
|
|
|
// only hug if we have vertically expanding
|
|
|
|
return self->nvexpand != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
static void uiGridDestroy(uiControl *c)
|
|
|
|
{
|
|
|
|
uiGrid *g = uiGrid(c);
|
|
|
|
|
|
|
|
[g->view onDestroy];
|
|
|
|
[g->view release];
|
|
|
|
uiFreeControl(uiControl(g));
|
|
|
|
}
|
|
|
|
|
|
|
|
uiDarwinControlDefaultHandle(uiGrid, view)
|
|
|
|
uiDarwinControlDefaultParent(uiGrid, view)
|
|
|
|
uiDarwinControlDefaultSetParent(uiGrid, view)
|
|
|
|
uiDarwinControlDefaultToplevel(uiGrid, view)
|
|
|
|
uiDarwinControlDefaultVisible(uiGrid, view)
|
|
|
|
uiDarwinControlDefaultShow(uiGrid, view)
|
|
|
|
uiDarwinControlDefaultHide(uiGrid, view)
|
|
|
|
uiDarwinControlDefaultEnabled(uiGrid, view)
|
|
|
|
uiDarwinControlDefaultEnable(uiGrid, view)
|
|
|
|
uiDarwinControlDefaultDisable(uiGrid, view)
|
|
|
|
|
|
|
|
static void uiGridSyncEnableState(uiDarwinControl *c, int enabled)
|
|
|
|
{
|
|
|
|
uiGrid *g = uiGrid(c);
|
|
|
|
|
|
|
|
if (uiDarwinShouldStopSyncEnableState(uiDarwinControl(g), enabled))
|
|
|
|
return;
|
|
|
|
[g->view syncEnableStates:enabled];
|
|
|
|
}
|
|
|
|
|
|
|
|
uiDarwinControlDefaultSetSuperview(uiGrid, view)
|
|
|
|
|
|
|
|
static BOOL uiGridHugsTrailingEdge(uiDarwinControl *c)
|
|
|
|
{
|
|
|
|
uiGrid *g = uiGrid(c);
|
|
|
|
|
|
|
|
return [g->view hugsTrailing];
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL uiGridHugsBottom(uiDarwinControl *c)
|
|
|
|
{
|
|
|
|
uiGrid *g = uiGrid(c);
|
|
|
|
|
|
|
|
return [g->view hugsBottom];
|
|
|
|
}
|
|
|
|
|
|
|
|
static void uiGridChildEdgeHuggingChanged(uiDarwinControl *c)
|
|
|
|
{
|
|
|
|
uiGrid *g = uiGrid(c);
|
|
|
|
|
|
|
|
[g->view establishOurConstraints];
|
|
|
|
}
|
|
|
|
|
|
|
|
uiDarwinControlDefaultHuggingPriority(uiGrid, view)
|
|
|
|
uiDarwinControlDefaultSetHuggingPriority(uiGrid, view)
|
|
|
|
|
|
|
|
static gridChild *toChild(uiControl *c, intmax_t xspan, intmax_t yspan, int hexpand, uiAlign halign, int vexpand, uiAlign valign)
|
|
|
|
{
|
|
|
|
gridChild *gc;
|
|
|
|
|
|
|
|
if (xspan < 0)
|
|
|
|
userbug("You cannot have a negative xspan in a uiGrid cell.");
|
|
|
|
if (yspan < 0)
|
|
|
|
userbug("You cannot have a negative yspan in a uiGrid cell.");
|
|
|
|
gc = [gridChild new];
|
|
|
|
gc.c = c;
|
|
|
|
gc.xspan = xspan;
|
|
|
|
gc.yspan = yspan;
|
|
|
|
gc.hexpand = hexpand;
|
|
|
|
gc.halign = halign;
|
|
|
|
gc.vexpand = vexpand;
|
|
|
|
gc.valign = valign;
|
|
|
|
gc.oldHorzHuggingPri = uiDarwinControlHuggingPriority(uiDarwinControl(gc.c), NSLayoutConstraintOrientationHorizontal);
|
|
|
|
gc.oldVertHuggingPri = uiDarwinControlHuggingPriority(uiDarwinControl(gc.c), NSLayoutConstraintOrientationVertical);
|
|
|
|
return gc;
|
|
|
|
}
|
|
|
|
|
|
|
|
void uiGridAppend(uiGrid *g, uiControl *c, intmax_t left, intmax_t top, intmax_t xspan, intmax_t yspan, int hexpand, uiAlign halign, int vexpand, uiAlign valign)
|
|
|
|
{
|
|
|
|
gridChild *gc;
|
|
|
|
|
|
|
|
// LONGTERM on other platforms
|
|
|
|
// or at leat allow this and implicitly turn it into a spacer
|
|
|
|
if (c == NULL)
|
|
|
|
userbug("You cannot add NULL to a uiGrid.");
|
|
|
|
gc = toChild(c, xspan, yspan, hexpand, halign, vexpand, valign);
|
|
|
|
gc.left = left;
|
|
|
|
gc.top = top;
|
|
|
|
[g->view append:gc];
|
|
|
|
}
|
|
|
|
|
|
|
|
void uiGridInsertAt(uiGrid *g, uiControl *c, uiControl *existing, uiAt at, intmax_t xspan, intmax_t yspan, int hexpand, uiAlign halign, int vexpand, uiAlign valign)
|
|
|
|
{
|
|
|
|
gridChild *gc;
|
|
|
|
|
|
|
|
gc = toChild(c, xspan, yspan, hexpand, halign, vexpand, valign);
|
|
|
|
[g->view insert:gc after:existing at:at];
|
|
|
|
}
|
|
|
|
|
|
|
|
int uiGridPadded(uiGrid *g)
|
|
|
|
{
|
|
|
|
return [g->view isPadded];
|
|
|
|
}
|
|
|
|
|
|
|
|
void uiGridSetPadded(uiGrid *g, int padded)
|
|
|
|
{
|
|
|
|
[g->view setPadded:padded];
|
|
|
|
}
|
|
|
|
|
2016-06-11 22:28:51 -05:00
|
|
|
uiGrid *uiNewGrid(void)
|
2016-06-11 22:09:53 -05:00
|
|
|
{
|
|
|
|
uiGrid *g;
|
|
|
|
|
|
|
|
uiDarwinNewControl(uiGrid, g);
|
|
|
|
|
|
|
|
g->view = [[gridView alloc] initWithG:g];
|
|
|
|
|
|
|
|
return g;
|
|
|
|
}
|