diff options
Diffstat (limited to 'src/libui_sdl/libui/darwin/grid.m')
-rw-r--r-- | src/libui_sdl/libui/darwin/grid.m | 800 |
1 files changed, 800 insertions, 0 deletions
diff --git a/src/libui_sdl/libui/darwin/grid.m b/src/libui_sdl/libui/darwin/grid.m new file mode 100644 index 0000000..d5c5fb1 --- /dev/null +++ b/src/libui_sdl/libui/darwin/grid.m @@ -0,0 +1,800 @@ +// 11 june 2016 +#import "uipriv_darwin.h" + +// TODO the assorted test doesn't work right at all + +@interface gridChild : NSView +@property uiControl *c; +@property int left; +@property int top; +@property int xspan; +@property int yspan; +@property int hexpand; +@property uiAlign halign; +@property int vexpand; +@property uiAlign valign; + +@property (strong) NSLayoutConstraint *leadingc; +@property (strong) NSLayoutConstraint *topc; +@property (strong) NSLayoutConstraint *trailingc; +@property (strong) NSLayoutConstraint *bottomc; +@property (strong) NSLayoutConstraint *xcenterc; +@property (strong) NSLayoutConstraint *ycenterc; + +@property NSLayoutPriority oldHorzHuggingPri; +@property NSLayoutPriority oldVertHuggingPri; +- (void)setC:(uiControl *)c grid:(uiGrid *)g; +- (void)onDestroy; +- (NSView *)view; +@end + +@interface gridView : NSView { + uiGrid *g; + NSMutableArray *children; + int padded; + + NSMutableArray *edges; + NSMutableArray *inBetweens; + + NSMutableArray *emptyCellViews; +} +- (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; +- (int)nhexpand; +- (int)nvexpand; +@end + +struct uiGrid { + uiDarwinControl c; + gridView *view; +}; + +@implementation gridChild + +- (void)setC:(uiControl *)c grid:(uiGrid *)g +{ + self.c = c; + self.oldHorzHuggingPri = uiDarwinControlHuggingPriority(uiDarwinControl(self.c), NSLayoutConstraintOrientationHorizontal); + self.oldVertHuggingPri = uiDarwinControlHuggingPriority(uiDarwinControl(self.c), NSLayoutConstraintOrientationVertical); + + uiControlSetParent(self.c, uiControl(g)); + uiDarwinControlSetSuperview(uiDarwinControl(self.c), self); + uiDarwinControlSyncEnableState(uiDarwinControl(self.c), uiControlEnabledToUser(uiControl(g))); + + if (self.halign == uiAlignStart || self.halign == uiAlignFill) { + self.leadingc = mkConstraint(self, NSLayoutAttributeLeading, + NSLayoutRelationEqual, + [self view], NSLayoutAttributeLeading, + 1, 0, + @"uiGrid child horizontal alignment start constraint"); + [self addConstraint:self.leadingc]; + } + if (self.halign == uiAlignCenter) { + self.xcenterc = mkConstraint(self, NSLayoutAttributeCenterX, + NSLayoutRelationEqual, + [self view], NSLayoutAttributeCenterX, + 1, 0, + @"uiGrid child horizontal alignment center constraint"); + [self addConstraint:self.xcenterc]; + } + if (self.halign == uiAlignEnd || self.halign == uiAlignFill) { + self.trailingc = mkConstraint(self, NSLayoutAttributeTrailing, + NSLayoutRelationEqual, + [self view], NSLayoutAttributeTrailing, + 1, 0, + @"uiGrid child horizontal alignment end constraint"); + [self addConstraint:self.trailingc]; + } + + if (self.valign == uiAlignStart || self.valign == uiAlignFill) { + self.topc = mkConstraint(self, NSLayoutAttributeTop, + NSLayoutRelationEqual, + [self view], NSLayoutAttributeTop, + 1, 0, + @"uiGrid child vertical alignment start constraint"); + [self addConstraint:self.topc]; + } + if (self.valign == uiAlignCenter) { + self.ycenterc = mkConstraint(self, NSLayoutAttributeCenterY, + NSLayoutRelationEqual, + [self view], NSLayoutAttributeCenterY, + 1, 0, + @"uiGrid child vertical alignment center constraint"); + [self addConstraint:self.ycenterc]; + } + if (self.valign == uiAlignEnd || self.valign == uiAlignFill) { + self.bottomc = mkConstraint(self, NSLayoutAttributeBottom, + NSLayoutRelationEqual, + [self view], NSLayoutAttributeBottom, + 1, 0, + @"uiGrid child vertical alignment end constraint"); + [self addConstraint:self.bottomc]; + } +} + +- (void)onDestroy +{ + if (self.leadingc != nil) { + [self removeConstraint:self.leadingc]; + self.leadingc = nil; + } + if (self.topc != nil) { + [self removeConstraint:self.topc]; + self.topc = nil; + } + if (self.trailingc != nil) { + [self removeConstraint:self.trailingc]; + self.trailingc = nil; + } + if (self.bottomc != nil) { + [self removeConstraint:self.bottomc]; + self.bottomc = nil; + } + if (self.xcenterc != nil) { + [self removeConstraint:self.xcenterc]; + self.xcenterc = nil; + } + if (self.ycenterc != nil) { + [self removeConstraint:self.ycenterc]; + self.ycenterc = nil; + } + + uiControlSetParent(self.c, NULL); + uiDarwinControlSetSuperview(uiDarwinControl(self.c), nil); + uiDarwinControlSetHuggingPriority(uiDarwinControl(self.c), self.oldHorzHuggingPri, NSLayoutConstraintOrientationHorizontal); + uiDarwinControlSetHuggingPriority(uiDarwinControl(self.c), self.oldVertHuggingPri, NSLayoutConstraintOrientationVertical); +} + +- (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]; + + self->edges = [NSMutableArray new]; + self->inBetweens = [NSMutableArray new]; + + self->emptyCellViews = [NSMutableArray new]; + } + return self; +} + +- (void)onDestroy +{ + gridChild *gc; + + [self removeOurConstraints]; + [self->edges release]; + [self->inBetweens release]; + + [self->emptyCellViews release]; + + for (gc in self->children) { + [gc onDestroy]; + uiControlDestroy(gc.c); + [gc removeFromSuperview]; + } + [self->children release]; +} + +- (void)removeOurConstraints +{ + NSView *v; + + if ([self->edges count] != 0) { + [self removeConstraints:self->edges]; + [self->edges removeAllObjects]; + } + if ([self->inBetweens count] != 0) { + [self removeConstraints:self->inBetweens]; + [self->inBetweens removeAllObjects]; + } + + for (v in self->emptyCellViews) + [v removeFromSuperview]; + [self->emptyCellViews 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); +} + +// LONGTERM stop early if all controls are hidden +- (void)establishOurConstraints +{ + gridChild *gc; + CGFloat padding; + int xmin, ymin; + int xmax, ymax; + int xcount, ycount; + BOOL first; + int **gg; + NSView ***gv; + BOOL **gspan; + int x, y; + int i; + NSLayoutConstraint *c; + int firstx, firsty; + BOOL *hexpand, *vexpand; + BOOL doit; + BOOL onlyEmptyAndSpanning; + + [self removeOurConstraints]; + if ([self->children count] == 0) + return; + padding = [self paddingAmount]; + + // first, figure out the minimum and maximum row and column numbers + // ignore hidden controls + first = YES; + for (gc in self->children) { + // this bit is important: it ensures row ymin and column xmin have at least one cell to draw, so the onlyEmptyAndSpanning logic below will never run on those rows + if (!uiControlVisible(gc.c)) + continue; + 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; + } + if (first != NO) // the entire grid is hidden; do nothing + return; + xcount = xmax - xmin; + ycount = ymax - ymin; + + // now build a topological map of the grid gg[y][x] + // also figure out which cells contain spanned views so they can be ignored later + // treat hidden controls by keeping the indices -1 + gg = (int **) uiAlloc(ycount * sizeof (int *), "int[][]"); + gspan = (BOOL **) uiAlloc(ycount * sizeof (BOOL *), "BOOL[][]"); + for (y = 0; y < ycount; y++) { + gg[y] = (int *) uiAlloc(xcount * sizeof (int), "int[]"); + gspan[y] = (BOOL *) uiAlloc(xcount * sizeof (BOOL), "BOOL[]"); + 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]; + if (!uiControlVisible(gc.c)) + continue; + 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; + if (x != gc.left || y != gc.top) + gspan[y - ymin][x - xmin] = YES; + } + } + + // if a row or column only contains emptys and spanning cells of a opposite-direction spannings, remove it by duplicating the previous row or column + for (y = 0; y < ycount; y++) { + onlyEmptyAndSpanning = YES; + for (x = 0; x < xcount; x++) + if (gg[y][x] != -1) { + gc = (gridChild *) [self->children objectAtIndex:gg[y][x]]; + if (gc.yspan == 1 || gc.top - ymin == y) { + onlyEmptyAndSpanning = NO; + break; + } + } + if (onlyEmptyAndSpanning) + for (x = 0; x < xcount; x++) { + gg[y][x] = gg[y - 1][x]; + gspan[y][x] = YES; + } + } + for (x = 0; x < xcount; x++) { + onlyEmptyAndSpanning = YES; + for (y = 0; y < ycount; y++) + if (gg[y][x] != -1) { + gc = (gridChild *) [self->children objectAtIndex:gg[y][x]]; + if (gc.xspan == 1 || gc.left - xmin == x) { + onlyEmptyAndSpanning = NO; + break; + } + } + if (onlyEmptyAndSpanning) + for (y = 0; y < ycount; y++) { + gg[y][x] = gg[y][x - 1]; + gspan[y][x] = YES; + } + } + + // now build a topological map of the grid's views gv[y][x] + // for any empty cell, create a dummy view + gv = (NSView ***) uiAlloc(ycount * sizeof (NSView **), "NSView *[][]"); + for (y = 0; y < ycount; y++) { + gv[y] = (NSView **) uiAlloc(xcount * sizeof (NSView *), "NSView *[]"); + for (x = 0; x < xcount; x++) + if (gg[y][x] == -1) { + gv[y][x] = [[NSView alloc] initWithFrame:NSZeroRect]; + [gv[y][x] setTranslatesAutoresizingMaskIntoConstraints:NO]; + [self addSubview:gv[y][x]]; + [self->emptyCellViews addObject:gv[y][x]]; + } else { + gc = (gridChild *) [self->children objectAtIndex:gg[y][x]]; + gv[y][x] = gc; + } + } + + // now figure out which rows and columns really expand + hexpand = (BOOL *) uiAlloc(xcount * sizeof (BOOL), "BOOL[]"); + vexpand = (BOOL *) uiAlloc(ycount * sizeof (BOOL), "BOOL[]"); + // first, which don't span + for (gc in self->children) { + if (!uiControlVisible(gc.c)) + continue; + if (gc.hexpand && gc.xspan == 1) + hexpand[gc.left - xmin] = YES; + if (gc.vexpand && gc.yspan == 1) + vexpand[gc.top - ymin] = YES; + } + // second, which do span + // the way we handle this is simple: if none of the spanned rows/columns expand, make all rows/columns expand + for (gc in self->children) { + if (!uiControlVisible(gc.c)) + continue; + if (gc.hexpand && gc.xspan != 1) { + doit = YES; + for (x = gc.left; x < gc.left + gc.xspan; x++) + if (hexpand[x - xmin]) { + doit = NO; + break; + } + if (doit) + for (x = gc.left; x < gc.left + gc.xspan; x++) + hexpand[x - xmin] = YES; + } + if (gc.vexpand && gc.yspan != 1) { + doit = YES; + for (y = gc.top; y < gc.top + gc.yspan; y++) + if (vexpand[y - ymin]) { + doit = NO; + break; + } + if (doit) + for (y = gc.top; y < gc.top + gc.yspan; y++) + vexpand[y - ymin] = YES; + } + } + + // now establish all the edge constraints + // leading and trailing edges + for (y = 0; y < ycount; y++) { + c = mkConstraint(self, NSLayoutAttributeLeading, + NSLayoutRelationEqual, + gv[y][0], NSLayoutAttributeLeading, + 1, 0, + @"uiGrid leading edge constraint"); + [self addConstraint:c]; + [self->edges addObject:c]; + c = mkConstraint(self, NSLayoutAttributeTrailing, + NSLayoutRelationEqual, + gv[y][xcount - 1], NSLayoutAttributeTrailing, + 1, 0, + @"uiGrid trailing edge constraint"); + [self addConstraint:c]; + [self->edges addObject:c]; + } + // top and bottom edges + for (x = 0; x < xcount; x++) { + c = mkConstraint(self, NSLayoutAttributeTop, + NSLayoutRelationEqual, + gv[0][x], NSLayoutAttributeTop, + 1, 0, + @"uiGrid top edge constraint"); + [self addConstraint:c]; + [self->edges addObject:c]; + c = mkConstraint(self, NSLayoutAttributeBottom, + NSLayoutRelationEqual, + gv[ycount - 1][x], NSLayoutAttributeBottom, + 1, 0, + @"uiGrid bottom edge constraint"); + [self addConstraint:c]; + [self->edges addObject:c]; + } + + // now align leading and top edges + // do NOT align spanning cells! + for (x = 0; x < xcount; x++) { + for (y = 0; y < ycount; y++) + if (!gspan[y][x]) + break; + firsty = y; + for (y++; y < ycount; y++) { + if (gspan[y][x]) + continue; + c = mkConstraint(gv[firsty][x], NSLayoutAttributeLeading, + NSLayoutRelationEqual, + gv[y][x], NSLayoutAttributeLeading, + 1, 0, + @"uiGrid column leading constraint"); + [self addConstraint:c]; + [self->edges addObject:c]; + } + } + for (y = 0; y < ycount; y++) { + for (x = 0; x < xcount; x++) + if (!gspan[y][x]) + break; + firstx = x; + for (x++; x < xcount; x++) { + if (gspan[y][x]) + continue; + c = mkConstraint(gv[y][firstx], NSLayoutAttributeTop, + NSLayoutRelationEqual, + gv[y][x], NSLayoutAttributeTop, + 1, 0, + @"uiGrid row top constraint"); + [self addConstraint:c]; + [self->edges addObject:c]; + } + } + + // now string adjacent views together + for (y = 0; y < ycount; y++) + for (x = 1; x < xcount; x++) + if (gv[y][x - 1] != gv[y][x]) { + c = mkConstraint(gv[y][x - 1], NSLayoutAttributeTrailing, + NSLayoutRelationEqual, + gv[y][x], NSLayoutAttributeLeading, + 1, -padding, + @"uiGrid internal horizontal constraint"); + [self addConstraint:c]; + [self->inBetweens addObject:c]; + } + for (x = 0; x < xcount; x++) + for (y = 1; y < ycount; y++) + if (gv[y - 1][x] != gv[y][x]) { + c = mkConstraint(gv[y - 1][x], NSLayoutAttributeBottom, + NSLayoutRelationEqual, + gv[y][x], NSLayoutAttributeTop, + 1, -padding, + @"uiGrid internal vertical constraint"); + [self addConstraint:c]; + [self->inBetweens addObject:c]; + } + + // now set priorities for all widgets that expand or not + // if a cell is in an expanding row, OR If it spans, then it must be willing to stretch + // otherwise, it tries not to + // note we don't use NSLayoutPriorityRequired as that will cause things to squish when they shouldn't + for (gc in self->children) { + NSLayoutPriority priority; + + if (!uiControlVisible(gc.c)) + continue; + if (hexpand[gc.left - xmin] || gc.xspan != 1) + priority = NSLayoutPriorityDefaultLow; + else + priority = NSLayoutPriorityDefaultHigh; + uiDarwinControlSetHuggingPriority(uiDarwinControl(gc.c), priority, NSLayoutConstraintOrientationHorizontal); + // same for vertical direction + if (vexpand[gc.top - ymin] || gc.yspan != 1) + priority = NSLayoutPriorityDefaultLow; + else + priority = NSLayoutPriorityDefaultHigh; + uiDarwinControlSetHuggingPriority(uiDarwinControl(gc.c), priority, NSLayoutConstraintOrientationVertical); + } + + // TODO make all expanding rows/columns the same height/width + + // and finally clean up + uiFree(hexpand); + uiFree(vexpand); + for (y = 0; y < ycount; y++) { + uiFree(gg[y]); + uiFree(gv[y]); + uiFree(gspan[y]); + } + uiFree(gg); + uiFree(gv); + uiFree(gspan); +} + +- (void)append:(gridChild *)gc +{ + BOOL update; + int oldnh, oldnv; + + [gc setTranslatesAutoresizingMaskIntoConstraints:NO]; + [self addSubview:gc]; + + // no need to set priority here; that's done in establishOurConstraints + + oldnh = [self nhexpand]; + oldnv = [self nvexpand]; + [self->children addObject:gc]; + + [self establishOurConstraints]; + update = NO; + if (gc.hexpand) + if (oldnh == 0) + update = YES; + if (gc.vexpand) + if (oldnv == 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; + +#if 0 /* TODO */ +dispatch_after( +dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC), +dispatch_get_main_queue(), +^{ [[self window] visualizeConstraints:[self constraints]]; } +); +#endif + 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; +} + +- (int)nhexpand +{ + gridChild *gc; + int n; + + n = 0; + for (gc in self->children) { + if (!uiControlVisible(gc.c)) + continue; + if (gc.hexpand) + n++; + } + return n; +} + +- (int)nvexpand +{ + gridChild *gc; + int n; + + n = 0; + for (gc in self->children) { + if (!uiControlVisible(gc.c)) + continue; + if (gc.vexpand) + n++; + } + return n; +} + +@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 void uiGridChildVisibilityChanged(uiDarwinControl *c) +{ + uiGrid *g = uiGrid(c); + + [g->view establishOurConstraints]; +} + +static gridChild *toChild(uiControl *c, int xspan, int yspan, int hexpand, uiAlign halign, int vexpand, uiAlign valign, uiGrid *g) +{ + 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.xspan = xspan; + gc.yspan = yspan; + gc.hexpand = hexpand; + gc.halign = halign; + gc.vexpand = vexpand; + gc.valign = valign; + [gc setC:c grid:g]; + return gc; +} + +void uiGridAppend(uiGrid *g, uiControl *c, int left, int top, int xspan, int 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, g); + gc.left = left; + gc.top = top; + [g->view append:gc]; +} + +void uiGridInsertAt(uiGrid *g, uiControl *c, uiControl *existing, uiAt at, int xspan, int yspan, int hexpand, uiAlign halign, int vexpand, uiAlign valign) +{ + gridChild *gc; + + gc = toChild(c, xspan, yspan, hexpand, halign, vexpand, valign, g); + [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]; +} + +uiGrid *uiNewGrid(void) +{ + uiGrid *g; + + uiDarwinNewControl(uiGrid, g); + + g->view = [[gridView alloc] initWithG:g]; + + return g; +} |