// 3 june 2018 #import "uipriv_darwin.h" #import "table.h" // TODO is the initial scroll position still wrong? @interface uiprivTableModel : NSObject { uiTableModel *m; } - (id)initWithModel:(uiTableModel *)model; @end // TODO we really need to clean up the sharing of the table and model variables... @interface uiprivTableView : NSTableView { uiTable *uiprivT; uiTableModel *uiprivM; } - (id)initWithFrame:(NSRect)r uiprivT:(uiTable *)t uiprivM:(uiTableModel *)m; @end @implementation uiprivTableView - (id)initWithFrame:(NSRect)r uiprivT:(uiTable *)t uiprivM:(uiTableModel *)m { self = [super initWithFrame:r]; if (self) { self->uiprivT = t; self->uiprivM = m; } return self; } // TODO is this correct for overflow scrolling? static void setBackgroundColor(uiprivTableView *t, NSTableRowView *rv, NSInteger row) { NSColor *color; double r, g, b, a; if (t->uiprivT->backgroundColumn == -1) return; // let Cocoa do its default thing if (uiprivTableModelColorIfProvided(t->uiprivM, row, t->uiprivT->backgroundColumn, &r, &g, &b, &a)) color = [NSColor colorWithSRGBRed:r green:g blue:b alpha:a]; else { NSArray *colors; NSInteger index; // this usage is primarily a guess; hopefully it is correct for the non-two color case... (TODO) // it does seem to be correct for the two-color case, judging from comparing against the value of backgroundColor before changing it (and no, nil does not work; it just sets to white) colors = [NSColor controlAlternatingRowBackgroundColors]; index = row % [colors count]; color = (NSColor *) [colors objectAtIndex:index]; } [rv setBackgroundColor:color]; // color is autoreleased in all cases } @end @implementation uiprivTableModel - (id)initWithModel:(uiTableModel *)model { self = [super init]; if (self) self->m = model; return self; } - (NSInteger)numberOfRowsInTableView:(NSTableView *)tv { return uiprivTableModelNumRows(self->m); } - (NSView *)tableView:(NSTableView *)tv viewForTableColumn:(NSTableColumn *)cc row:(NSInteger)row { uiprivTableColumn *c = (uiprivTableColumn *) cc; uiprivTableCellView *cv; cv = (uiprivTableCellView *) [tv makeViewWithIdentifier:[c identifier] owner:self]; if (cv == nil) cv = [c uiprivMakeCellView]; [cv uiprivUpdate:row]; return cv; } - (void)tableView:(NSTableView *)tv didAddRowView:(NSTableRowView *)rv forRow:(NSInteger)row { setBackgroundColor((uiprivTableView *) tv, rv, row); } @end uiTableModel *uiNewTableModel(uiTableModelHandler *mh) { uiTableModel *m; m = uiprivNew(uiTableModel); m->mh = mh; m->m = [[uiprivTableModel alloc] initWithModel:m]; m->tables = [NSMutableArray new]; return m; } void uiFreeTableModel(uiTableModel *m) { if ([m->tables count] != 0) uiprivUserBug("You cannot free a uiTableModel while uiTables are using it."); [m->tables release]; [m->m release]; uiprivFree(m); } void uiTableModelRowInserted(uiTableModel *m, int newIndex) { NSTableView *tv; NSIndexSet *set; set = [NSIndexSet indexSetWithIndex:newIndex]; for (tv in m->tables) [tv insertRowsAtIndexes:set withAnimation:NSTableViewAnimationEffectNone]; // set is autoreleased } void uiTableModelRowChanged(uiTableModel *m, int index) { uiprivTableView *tv; NSTableRowView *rv; NSUInteger i, n; uiprivTableCellView *cv; for (tv in m->tables) { rv = [tv rowViewAtRow:index makeIfNecessary:NO]; if (rv != nil) setBackgroundColor(tv, rv, index); n = [[tv tableColumns] count]; for (i = 0; i < n; i++) { cv = (uiprivTableCellView *) [tv viewAtColumn:i row:index makeIfNecessary:NO]; if (cv != nil) [cv uiprivUpdate:index]; } } } void uiTableModelRowDeleted(uiTableModel *m, int oldIndex) { NSTableView *tv; NSIndexSet *set; set = [NSIndexSet indexSetWithIndex:oldIndex]; for (tv in m->tables) [tv removeRowsAtIndexes:set withAnimation:NSTableViewAnimationEffectNone]; // set is autoreleased } uiTableModelHandler *uiprivTableModelHandler(uiTableModel *m) { return m->mh; } uiDarwinControlAllDefaultsExceptDestroy(uiTable, sv) static void uiTableDestroy(uiControl *c) { uiTable *t = uiTable(c); [t->m->tables removeObject:t->tv]; uiprivScrollViewFreeData(t->sv, t->d); [t->tv release]; [t->sv release]; uiFreeControl(uiControl(t)); } uiTable *uiNewTable(uiTableParams *p) { uiTable *t; uiprivScrollViewCreateParams sp; uiDarwinNewControl(uiTable, t); t->m = p->Model; t->backgroundColumn = p->RowBackgroundColorModelColumn; t->tv = [[uiprivTableView alloc] initWithFrame:NSZeroRect uiprivT:t uiprivM:t->m]; [t->tv setDataSource:t->m->m]; [t->tv setDelegate:t->m->m]; [t->tv reloadData]; [t->m->tables addObject:t->tv]; // TODO is this sufficient? [t->tv setAllowsColumnReordering:NO]; [t->tv setAllowsColumnResizing:YES]; [t->tv setAllowsMultipleSelection:NO]; [t->tv setAllowsEmptySelection:YES]; [t->tv setAllowsColumnSelection:NO]; [t->tv setUsesAlternatingRowBackgroundColors:YES]; [t->tv setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleRegular]; [t->tv setGridStyleMask:NSTableViewGridNone]; [t->tv setAllowsTypeSelect:YES]; // TODO floatsGroupRows — do we even allow group rows? memset(&sp, 0, sizeof (uiprivScrollViewCreateParams)); sp.DocumentView = t->tv; // this is what Interface Builder sets it to // TODO verify sp.BackgroundColor = [NSColor colorWithCalibratedWhite:1.0 alpha:1.0]; sp.DrawsBackground = YES; sp.Bordered = YES; sp.HScroll = YES; sp.VScroll = YES; t->sv = uiprivMkScrollView(&sp, &(t->d)); // TODO WHY DOES THIS REMOVE ALL GRAPHICAL GLITCHES? // I got the idea from http://jwilling.com/blog/optimized-nstableview-scrolling/ but that was on an unrelated problem I didn't seem to have (although I have small-ish tables to start with) // I don't get layer-backing... am I supposed to layer-back EVERYTHING manually? I need to check Interface Builder again... [t->sv setWantsLayer:YES]; return t; }