diff --git a/darwin/CMakeLists.txt b/darwin/CMakeLists.txt index e7fe4507..c8d1f3be 100644 --- a/darwin/CMakeLists.txt +++ b/darwin/CMakeLists.txt @@ -34,6 +34,7 @@ list(APPEND _LIBUI_SOURCES darwin/spinbox.m darwin/stddialogs.m darwin/tab.m + darwin/table.m darwin/text.m darwin/util.m darwin/window.m diff --git a/darwin/table.m b/darwin/table.m new file mode 100644 index 00000000..9ae9e184 --- /dev/null +++ b/darwin/table.m @@ -0,0 +1,239 @@ +// 21 june 2016 +#import "uipriv_darwin.h" + +@interface tableModel : NSObject { + uiTableModel *libui_m; +} +- (id)initWithModel:(uiTableModel *)m; +@end + +enum { + partText, +}; + +@interface tablePart : NSObject +@property int type; +@property int mainColumn; +@property int expand; +- (NSView *)mkView:(uiTableModel *)m row:(int)row; +@end + +@interface tableColumn : NSTableColumn +@property uiTableColumn *libui_col; +@end + +struct uiTableModel { + uiTableModelHandler *mh; + tableModel *m; + NSMutableArray *tables; +}; + +// TODO better memory management for this +// note how expand is part of this +struct uiTableCellPart { + tablePart *part; +} + +struct uiTableColumn { + NSMutableArray *parts; +}; + +struct uiTable { + uiDarwinControl c; + NSScrollView *sv; + NSTableView *tv; +}; + +@implementation tableModel + +- (id)initWithModel:(uiTableModel *)m +{ + self = [super init]; + if (self) + self->libui_m = m; + return self; +} + +- (NSInteger)numberOfRowsInTableView:(NSTableView *)tv +{ + uiTableModelHandler *mh = self->libui_m->mh; + + return (*(mh->NumRows))(mh, m); +} + +// these are according to Interface Builder +#define xleft 2 +#define xmiddle 7 /* between images and text, anyway; let's just use it for everything to be simpler */ +#define xright 3 + + - (NSView *)tableView:(NSTableView *)tv viewForTableColumn:(NSTableColumn *)cc row:(NSInteger)row +{ + NSView *v; + tableColumn *c = (tableColumn *) cc; + tablePart *part; + NSMutableArray *views; + NSView *view, *prev; + + v = [[NSView alloc] initWithFrame:NSZeroRect]; + + views = [NSMutableArray new]; + for (part in c.libui_col->parts) + [views addObject:[part mkView:self->libui_m row:row]]; + if ([views count] == 0) // empty (TODO allow?) + goto done; + + // arrange horizontally + prev = nil; + for (view in views) { + if (prev == nil) { // first view + [v addConstraint:mkConstraint(v, NSLayoutAttributeLeading, + NSLayoutRelationEqual, + view, NSLayoutAttributeLeading, + 1, -xleft, + @"uiTableColumn first part horizontal constraint")]; + prev = view; + continue; + } + [v addConstraint:mkConstraint(prev, NSLayoutAttributeTrailing, + NSLayoutRelationEqual, + view, NSLayoutAttributeLeading, + 1, -xmiddle, + @"uiTableColumn middle horizontal constraint")]; + prev = view; + } + [v addConstraint:mkConstraint(prev, NSLayoutAttributeTrailing, + NSLayoutRelationEqual, + v, NSLayoutAttributeTrailing, + 1, -xright, + @"uiTableColumn last part horizontal constraint")]; + + // and vertically + for (view in views) + [v addConstraint:mkConstraint(view, NSLayoutAttributeCenterY, + NSLayoutRelationEqual, + v, NSLayoutAttributeCenterY, + 1, 0, + @"uiTableColumn part vertical constraint")]; + +done: + [views release]; + // TODO autorelease? + return v; +} + +@end + +@implementation tablePart + +- (NSView *)mkView:(uiTableModel *)m row:(int)row; +{ + void *data; + NSString *str; + NSView *view; + NSTextField *tf; + + data = (*(m->mh->CellValue))(m->mh, m, row, self.mainColumn); + switch (self.type) { + case partText: + str = toNSString((char *) data); + uiFree(data); + tf = newLabel(str); + // TODO set wrap and ellipsize modes + view = tf; + break; + } + + // if stretchy, don't hug, otherwise hug forcibly + if (self.expand) + [view setContentHuggingPriority:NSLayoutPriorityDefaultLow forOrientation:NSLayoutConstraintOrientationHorizontal]; + else + [view setContentHuggingPriority:NSLayoutPriorityRequired forOrientation:NSLayoutConstraintOrientationHorizontal]; + // TODO autorelease? + return view; +} + +@end + +@implementation tableColumn +@end + +void *uiTableModelStrdup(const char *str) +{ + // TODO don't we have this already? + char *dup; + + dup = (char *) uiAlloc((strlen(str) + 1) * sizeof (char), "char[]"); + strcpy(dup, str); + return dup; +} + +uiTableModel *uiNewTableModel(uITableModelHandler *mh) +{ + uiTableModel *m; + + m = uiNew(uiTableModel); + m->mh = mh; + m->m = [[tableModel alloc] initWithModel:m]; + m->tables = [NSMutableArray new]; + return m; +} + +void uiFreeTableModel(uiTableModel *m) +{ + if ([m->tables count] != 0) + userbug("You cannot free a uiTableModel while uiTables are using it."); + [m->tables release]; + [m->m release]; + uiFree(m); +} + +void uiTableModelRowInserted(uiTableModel *m, int newIndex) +{ + NSTableView *tv; + NSIndexSet *set; + + set = [NSIndexSet indexSetWithIndex:index]; + for (tv in m->tables) + [tv insertRowsAtIndexes:set withAnimation:NSTableViewAnimationEffectNone]; + // set is autoreleased +} + +void uiTableModelRowChanged(uiTableModel *m, int index) +{ + NSTableView *tv; + NSIndexSet *set, *cols; + + set = [NSIndexSet indexSetWithIndex:index]; + for (tv in m->tables) { + cols = [[NSIndexSet alloc] initWithIndexesInRange:NSMakeRange(0, [[tv tableColumns] count])]; + [tv reloadDataForRowIndexes:set columnIndexes:cols]; + [cols release]; + } + // set is autoreleased +} + +void uiTableModelRowDeleted(uiTableModel *m, int oldIndex) +{ + NSTableView *tv; + NSIndexSet *set; + + set = [NSIndexSet indexSetWithIndex:index]; + for (tv in m->tables) + [tv removeRowsAtIndexes:set withAnimation:NSTableViewAnimationEffectNone]; + // set is autoreleased +} + +void uiTableColumnAppend(uiTableColumn *c, uiTableCellPart *part, int expand) +{ + part->part.expand = expand; + [c->parts addObject:part->part]; +} + +_UI_EXTERN uiTableCellPart *uiNewTableTextPart(int modelColumn); +_UI_EXTERN void uiFreeTableCellPart(uiTableCellPart *p); + +typedef struct uiTable uiTable; +#define uiTable(this) ((uiTable *) (this)) +_UI_EXTERN uiTableColumn *uiTableAppendColumn(uiTable *t, const char *name); +_UI_EXTERN uiTableColumn *uiTableAppendTextColumn(uiTable *t, const char *name, int modelColumn); +_UI_EXTERN uiTable *uiNewTable(uiTableModel *model); diff --git a/test/page16.c b/test/page16.c index 0dd74421..129aeaf8 100644 --- a/test/page16.c +++ b/test/page16.c @@ -3,22 +3,22 @@ static uiTableModelHandler mh; -static nt modelNumColumns(uiTableModel *m) +static nt modelNumColumns(uiTableModelHandler *mh, uiTableModel *m) { return 3; } -static uiTableModelColumnType modelColumnType(uiTableModel *m, int column) +static uiTableModelColumnType modelColumnType(uiTableModelHandler *mh, uiTableModel *m, int column) { return uiTableModelColumnString; } -static int modelNumRows(uiTableModel *m) +static int modelNumRows(uiTableModelHandler *mh, uiTableModel *m) { return 15; } -static void *modelCellValue(uiTableModel *m, int row, int col) +static void *modelCellValue(uiTableModelHandler *mh, uiTableModel *m, int row, int col) { char buf[256]; @@ -34,7 +34,7 @@ static void *modelCellValue(uiTableModel *m, int row, int col) return uiTableModelStrdup(buf); } -static void modelSetCellValue(uiTableModel *m, int row, int col, void *val) +static void modelSetCellValue(uiTableModelHandler *mh, uiTableModel *m, int row, int col, void *val) { // not implemented yet } diff --git a/uitable.h b/uitable.h index ed5d96ec..4b7d5cf7 100644 --- a/uitable.h +++ b/uitable.h @@ -9,11 +9,11 @@ _UI_ENUM(uiTableModelColumnType) { }; struct uiTableModelHandler { - int (*NumColumns)(uiTableModel *); - uiTableModelColumnType (*ColumnType)(uiTableModel *, int); - int (*NumRows)(uiTableModel *); - void *(*CellValue)(uiTableModel *, int, int); - void (*SetCellValue)(uiTableModel *, int, int, void *); + int (*NumColumns)(uiTableModelHandler *, uiTableModel *); + uiTableModelColumnType (*ColumnType)(uiTableModelHandler *, uiTableModel *, int); + int (*NumRows)(uiTableModelHandler *, uiTableModel *); + void *(*CellValue)(uiTableModelHandler *, uiTableModel *, int, int); + void (*SetCellValue)(uiTableModelHandler *, uiTableModel *, int, int, void *); }; _UI_EXTERN void *uiTableModelStrdup(const char *str); @@ -23,6 +23,7 @@ _UI_EXTERN void uiFreeTableModel(uiTableModel *m); _UI_EXTERN void uiTableModelRowInserted(uiTableModel *m, int newIndex); _UI_EXTERN void uiTableModelRowChanged(uiTableModel *m, int index); _UI_EXTERN void uiTableModelRowDeleted(uiTableModel *m, int oldIndex); +// TODO reordering/moving typedef struct uiTableColumn uiTableColumn; typedef struct uiTableCellPart uiTableCellPart;