2014-07-29 09:32:49 -05:00
|
|
|
// 29 july 2014
|
|
|
|
|
|
|
|
#import "objc_darwin.h"
|
|
|
|
#import "_cgo_export.h"
|
|
|
|
#import <Cocoa/Cocoa.h>
|
|
|
|
|
|
|
|
#define toNSTableView(x) ((NSTableView *) (x))
|
|
|
|
|
2014-08-10 21:10:47 -05:00
|
|
|
// NSTableColumn provides no provision to store an integer data
|
|
|
|
// it does provide an identifier tag, but that's a NSString, and I'd rather not risk the conversion overhead
|
|
|
|
@interface goTableColumn : NSTableColumn {
|
|
|
|
@public
|
|
|
|
intptr_t gocolnum;
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation goTableColumn
|
|
|
|
@end
|
|
|
|
|
2014-08-20 20:43:28 -05:00
|
|
|
@interface goTableDataSource : NSObject <NSTableViewDataSource, NSTableViewDelegate> {
|
2014-07-29 09:32:49 -05:00
|
|
|
@public
|
|
|
|
void *gotable;
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation goTableDataSource
|
2014-07-29 09:54:52 -05:00
|
|
|
|
|
|
|
- (NSInteger)numberOfRowsInTableView:(NSTableView *)view
|
|
|
|
{
|
|
|
|
return (NSInteger) goTableDataSource_getRowCount(self->gotable);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id)tableView:(NSTableView *)view objectValueForTableColumn:(NSTableColumn *)col row:(NSInteger)row
|
|
|
|
{
|
2014-08-16 20:49:43 -05:00
|
|
|
void *ret;
|
2014-07-29 09:54:52 -05:00
|
|
|
NSString *s;
|
2014-08-10 21:10:47 -05:00
|
|
|
intptr_t colnum;
|
2014-08-16 20:49:43 -05:00
|
|
|
char *str;
|
2014-08-17 09:13:28 -05:00
|
|
|
int type = colTypeText;
|
2014-07-29 09:54:52 -05:00
|
|
|
|
2014-08-10 21:10:47 -05:00
|
|
|
colnum = ((goTableColumn *) col)->gocolnum;
|
2014-08-17 09:13:28 -05:00
|
|
|
ret = goTableDataSource_getValue(self->gotable, (intptr_t) row, colnum, &type);
|
|
|
|
switch (type) {
|
|
|
|
case colTypeImage:
|
2014-08-16 20:49:43 -05:00
|
|
|
return (id) ret;
|
2014-08-17 09:13:28 -05:00
|
|
|
case colTypeCheckbox:
|
|
|
|
if (ret == NULL)
|
|
|
|
return nil;
|
|
|
|
return (id) [NSNumber numberWithInt:1];
|
|
|
|
}
|
2014-08-16 20:49:43 -05:00
|
|
|
str = (char *) ret;
|
2014-07-29 09:54:52 -05:00
|
|
|
s = [NSString stringWithUTF8String:str];
|
|
|
|
free(str); // allocated with C.CString() on the Go side
|
2014-08-16 20:49:43 -05:00
|
|
|
return (id) s;
|
2014-07-29 09:54:52 -05:00
|
|
|
}
|
|
|
|
|
2014-08-17 09:13:28 -05:00
|
|
|
- (void)tableView:(NSTableView *)view setObjectValue:(id)value forTableColumn:(NSTableColumn *)col row:(NSInteger)row
|
|
|
|
{
|
|
|
|
intptr_t colnum;
|
|
|
|
|
|
|
|
colnum = ((goTableColumn *) col)->gocolnum;
|
|
|
|
// TODO verify type of value
|
|
|
|
goTableDataSource_toggled(self->gotable, (intptr_t) row, colnum, [value boolValue]);
|
|
|
|
}
|
|
|
|
|
2014-08-20 20:43:28 -05:00
|
|
|
- (void)tableViewSelectionDidChange:(NSNotification *)note
|
|
|
|
{
|
|
|
|
tableSelectionChanged(self->gotable);
|
|
|
|
}
|
|
|
|
|
2014-07-29 09:32:49 -05:00
|
|
|
@end
|
|
|
|
|
|
|
|
id newTable(void)
|
|
|
|
{
|
|
|
|
NSTableView *t;
|
|
|
|
|
2014-08-05 21:02:57 -05:00
|
|
|
t = [[NSTableView alloc] initWithFrame:NSZeroRect];
|
2014-07-29 09:32:49 -05:00
|
|
|
[t setAllowsColumnReordering:NO];
|
|
|
|
[t setAllowsColumnResizing:YES];
|
|
|
|
[t setAllowsMultipleSelection:NO];
|
|
|
|
[t setAllowsEmptySelection:YES];
|
|
|
|
[t setAllowsColumnSelection:NO];
|
|
|
|
return (id) t;
|
|
|
|
}
|
|
|
|
|
2014-08-17 09:13:28 -05:00
|
|
|
void tableAppendColumn(id t, intptr_t colnum, char *name, int type, BOOL editable)
|
2014-07-29 09:32:49 -05:00
|
|
|
{
|
2014-08-10 21:10:47 -05:00
|
|
|
goTableColumn *c;
|
2014-08-16 20:49:43 -05:00
|
|
|
NSImageCell *ic;
|
2014-08-17 09:13:28 -05:00
|
|
|
NSButtonCell *bc;
|
|
|
|
NSLineBreakMode lbm = NSLineBreakByTruncatingTail; // default for most types
|
2014-07-29 09:32:49 -05:00
|
|
|
|
2014-08-10 21:10:47 -05:00
|
|
|
c = [[goTableColumn alloc] initWithIdentifier:nil];
|
|
|
|
c->gocolnum = colnum;
|
2014-08-16 20:49:43 -05:00
|
|
|
switch (type) {
|
|
|
|
case colTypeImage:
|
|
|
|
ic = [[NSImageCell alloc] initImageCell:nil];
|
|
|
|
// this is the behavior we want, which differs from the Interface Builder default of proportionally down
|
|
|
|
[ic setImageScaling:NSImageScaleProportionallyUpOrDown];
|
|
|
|
// these two, however, ARE Interface Builder defaults
|
|
|
|
[ic setImageFrameStyle:NSImageFrameNone];
|
|
|
|
[ic setImageAlignment:NSImageAlignCenter];
|
|
|
|
[c setDataCell:ic];
|
|
|
|
break;
|
2014-08-17 09:13:28 -05:00
|
|
|
case colTypeCheckbox:
|
|
|
|
bc = [[NSButtonCell alloc] init];
|
|
|
|
[bc setBezelStyle:NSRegularSquareBezelStyle]; // not explicitly stated as such in Interface Builder; extracted with a test program
|
|
|
|
[bc setButtonType:NSSwitchButton];
|
|
|
|
[bc setBordered:NO];
|
|
|
|
[bc setTransparent:NO];
|
|
|
|
[bc setAllowsMixedState:NO];
|
|
|
|
[bc setTitle:@""]; // no label
|
|
|
|
lbm = NSLineBreakByWordWrapping; // Interface Builder sets this mode for this type
|
|
|
|
[c setDataCell:bc];
|
|
|
|
break;
|
2014-08-16 20:49:43 -05:00
|
|
|
}
|
|
|
|
// otherwise just use the current cell
|
2014-08-17 09:13:28 -05:00
|
|
|
[c setEditable:editable];
|
2014-07-29 09:32:49 -05:00
|
|
|
[[c headerCell] setStringValue:[NSString stringWithUTF8String:name]];
|
2014-07-30 12:10:19 -05:00
|
|
|
setSmallControlFont((id) [c headerCell]);
|
|
|
|
setStandardControlFont((id) [c dataCell]);
|
2014-08-10 22:54:56 -05:00
|
|
|
// the following are according to Interface Builder
|
2014-08-11 02:56:07 -05:00
|
|
|
// for the header cell, a stub program had to be written because Interface Builder doesn't support editing header cells directly
|
|
|
|
[[c headerCell] setScrollable:NO];
|
|
|
|
[[c headerCell] setWraps:NO];
|
|
|
|
[[c headerCell] setLineBreakMode:NSLineBreakByTruncatingTail];
|
|
|
|
[[c headerCell] setUsesSingleLineMode:NO];
|
|
|
|
[[c headerCell] setTruncatesLastVisibleLine:NO];
|
2014-08-10 22:54:56 -05:00
|
|
|
[[c dataCell] setScrollable:NO];
|
|
|
|
[[c dataCell] setWraps:NO];
|
2014-08-17 09:13:28 -05:00
|
|
|
[[c dataCell] setLineBreakMode:lbm];
|
2014-08-10 22:54:56 -05:00
|
|
|
[[c dataCell] setUsesSingleLineMode:NO];
|
|
|
|
[[c dataCell] setTruncatesLastVisibleLine:NO];
|
2014-07-29 09:32:49 -05:00
|
|
|
[toNSTableView(t) addTableColumn:c];
|
|
|
|
}
|
|
|
|
|
|
|
|
void tableUpdate(id t)
|
|
|
|
{
|
|
|
|
[toNSTableView(t) reloadData];
|
|
|
|
}
|
|
|
|
|
2014-08-20 20:43:28 -05:00
|
|
|
// also sets the delegate
|
2014-07-29 09:54:52 -05:00
|
|
|
void tableMakeDataSource(id table, void *gotable)
|
|
|
|
{
|
|
|
|
goTableDataSource *model;
|
|
|
|
|
|
|
|
model = [goTableDataSource new];
|
|
|
|
model->gotable = gotable;
|
|
|
|
[toNSTableView(table) setDataSource:model];
|
2014-08-20 20:43:28 -05:00
|
|
|
[toNSTableView(table) setDelegate:model];
|
2014-07-29 09:54:52 -05:00
|
|
|
}
|
2014-08-10 14:56:59 -05:00
|
|
|
|
|
|
|
// -[NSTableView sizeToFit] does not actually size to fit
|
|
|
|
// -[NSTableColumn sizeToFit] is just for the header
|
|
|
|
// -[NSTableColumn sizeToFit] can work for guessing but overrides user settings
|
|
|
|
// -[[NSTableColumn headerCell] cellSize] does NOT (despite being documented as returning the minimum needed size)
|
|
|
|
// Let's write our own to prefer:
|
|
|
|
// - width of the sum of all columns's current widths
|
|
|
|
// - height of 5 rows (arbitrary count; seems reasonable) + header view height
|
|
|
|
// Hopefully this is reasonable.
|
|
|
|
struct xsize tablePreferredSize(id control)
|
|
|
|
{
|
|
|
|
NSTableView *t;
|
|
|
|
NSArray *columns;
|
|
|
|
struct xsize s;
|
|
|
|
NSUInteger i, n;
|
|
|
|
NSTableColumn *c;
|
|
|
|
|
|
|
|
t = toNSTableView(control);
|
|
|
|
columns = [t tableColumns];
|
|
|
|
n = [columns count];
|
|
|
|
s.width = 0;
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
CGFloat width;
|
|
|
|
|
|
|
|
c = (NSTableColumn *) [columns objectAtIndex:i];
|
|
|
|
s.width += (intptr_t) [c width];
|
|
|
|
}
|
|
|
|
s.height = 5 * (intptr_t) [t rowHeight];
|
|
|
|
s.height += (intptr_t) [[t headerView] frame].size.height;
|
|
|
|
return s;
|
|
|
|
}
|
2014-08-18 09:41:58 -05:00
|
|
|
|
|
|
|
intptr_t tableSelected(id table)
|
|
|
|
{
|
|
|
|
return (intptr_t) [toNSTableView(table) selectedRow];
|
|
|
|
}
|
|
|
|
|
|
|
|
void tableSelect(id table, intptr_t row)
|
|
|
|
{
|
|
|
|
[toNSTableView(table) deselectAll:table];
|
|
|
|
if (row != -1)
|
|
|
|
[toNSTableView(table) selectRowIndexes:[NSIndexSet indexSetWithIndex:((NSUInteger) row)] byExtendingSelection:NO];
|
|
|
|
}
|