2020-03-31 01:55:39 +00:00
|
|
|
#include <Array.h>
|
2020-06-21 14:15:17 +00:00
|
|
|
#include "ruamoko/qwaq/ui/listener.h"
|
2021-09-24 17:14:26 +00:00
|
|
|
#include "ruamoko/qwaq/ui/scrollbar.h"
|
2020-06-21 14:15:17 +00:00
|
|
|
#include "ruamoko/qwaq/ui/tableview.h"
|
2020-03-31 01:55:39 +00:00
|
|
|
|
|
|
|
@implementation TableViewColumn
|
|
|
|
-initWithName:(string)name width:(int)width
|
|
|
|
{
|
|
|
|
if (!(self = [super init])) {
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
self.name = name;
|
|
|
|
self.width = width;
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
+(TableViewColumn *)named:(string)name
|
|
|
|
{
|
|
|
|
return [[[self alloc] initWithName:name width:-1] autorelease];
|
|
|
|
}
|
|
|
|
|
|
|
|
+(TableViewColumn *)named:(string)name width:(int)width
|
|
|
|
{
|
|
|
|
return [[[self alloc] initWithName:name width:width] autorelease];
|
|
|
|
}
|
|
|
|
|
2020-03-31 13:03:56 +00:00
|
|
|
-setGrowMode: (int) mode
|
|
|
|
{
|
|
|
|
growMode = mode;
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
-(int)growMode
|
|
|
|
{
|
|
|
|
return growMode;
|
|
|
|
}
|
|
|
|
|
2020-03-31 01:55:39 +00:00
|
|
|
-(string)name
|
|
|
|
{
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
-(int)width
|
|
|
|
{
|
|
|
|
return width;
|
|
|
|
}
|
|
|
|
|
|
|
|
-setWidth:(int)width
|
|
|
|
{
|
|
|
|
self.width = width;
|
|
|
|
return self;
|
|
|
|
}
|
2020-03-31 13:03:56 +00:00
|
|
|
|
|
|
|
-grow:(Extent)delta
|
|
|
|
{
|
|
|
|
if (growMode & gfGrowHiX) {
|
|
|
|
width += delta.width;
|
|
|
|
}
|
|
|
|
return self;
|
|
|
|
}
|
2020-03-31 01:55:39 +00:00
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation TableView
|
|
|
|
-initWithRect:(Rect)rect
|
|
|
|
{
|
|
|
|
if (!(self = [super initWithRect:rect])) {
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
options = ofCanFocus | ofRelativeEvents;
|
|
|
|
columns = [[Array array] retain];
|
|
|
|
buffer = [[DrawBuffer buffer:size] retain];
|
2020-03-31 11:48:38 +00:00
|
|
|
[buffer bkgd:' '];
|
2020-03-31 01:55:39 +00:00
|
|
|
[onViewScrolled addListener:self :@selector(onScroll:)];
|
2020-03-31 13:03:56 +00:00
|
|
|
growMode = gfGrowHi;
|
2020-03-31 01:55:39 +00:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
-(void)dealloc
|
|
|
|
{
|
|
|
|
[columns release];
|
|
|
|
[buffer release];
|
|
|
|
[dataSource release];
|
2020-03-31 11:48:38 +00:00
|
|
|
[super dealloc];
|
2020-03-31 01:55:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
+(TableView *)withRect:(Rect)rect
|
|
|
|
{
|
|
|
|
return [[[self alloc] initWithRect:rect] autorelease];
|
|
|
|
}
|
|
|
|
|
|
|
|
-addColumn:(TableViewColumn *)column
|
|
|
|
{
|
|
|
|
[columns addObject:column];
|
|
|
|
columns_dirty = 1;
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
-setDataSource:(id<TableViewDataSource>)dataSource
|
|
|
|
{
|
|
|
|
self.dataSource = [dataSource retain];
|
2021-09-24 17:14:26 +00:00
|
|
|
[[dataSource onRowCountChanged] addListener:self
|
|
|
|
:@selector(onRowCountChanged:)];
|
2021-09-25 04:27:55 +00:00
|
|
|
[vScrollBar setRange:[dataSource numberOfRows:self]];
|
2020-03-31 01:55:39 +00:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2021-09-24 17:14:26 +00:00
|
|
|
-(void)onRowCountChanged:(id)sender
|
|
|
|
{
|
|
|
|
[vScrollBar setRange:[sender numberOfRows:self]];
|
|
|
|
}
|
|
|
|
|
2020-03-31 01:55:39 +00:00
|
|
|
-resize:(Extent)delta
|
|
|
|
{
|
|
|
|
Extent size = self.size;
|
|
|
|
[super resize:delta];
|
|
|
|
[buffer resizeTo:self.size];
|
2020-03-31 13:03:56 +00:00
|
|
|
for (int i = [columns count]; i-- > 0; ) {
|
|
|
|
[[columns objectAtIndex: i] grow: delta];
|
|
|
|
}
|
2020-03-31 01:55:39 +00:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
-draw
|
|
|
|
{
|
|
|
|
View *cell;
|
|
|
|
TableViewColumn *col;
|
|
|
|
[super draw];
|
|
|
|
int numCols = [columns count];
|
|
|
|
int numRows = [dataSource numberOfRows:self];
|
|
|
|
[buffer clear];
|
|
|
|
for (int y = 0; y < ylen; y++) {
|
|
|
|
for (int i = 0, x = 0; i < numCols; i++) {
|
|
|
|
int row = base.y + y;
|
|
|
|
if (row >= numRows) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
col = [columns objectAtIndex:i];
|
|
|
|
cell = [dataSource tableView:self forColumn:col row:row];
|
2021-09-25 04:27:55 +00:00
|
|
|
[[[[cell setContext:buffer]
|
|
|
|
moveTo:{x, y}]
|
|
|
|
resizeTo:{[col width], 1}]
|
|
|
|
draw];
|
2020-03-31 01:55:39 +00:00
|
|
|
x += [col width];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
[textContext blitFromBuffer:buffer to:pos from:[buffer rect]];
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
-(void)onScroll:(id)sender
|
|
|
|
{
|
|
|
|
if (base.y != scroll.y) {
|
|
|
|
base.y = scroll.y;
|
|
|
|
[self redraw];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-24 17:14:26 +00:00
|
|
|
static int
|
|
|
|
handleEvent (TableView *self, qwaq_event_t *event)
|
|
|
|
{
|
|
|
|
if (event.what & qe_mouse) {
|
|
|
|
if (event.what == qe_mouseclick) {
|
|
|
|
if (event.mouse.buttons & (1 << 3)) {
|
|
|
|
[self.vScrollBar page:1 dir:0];
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (event.mouse.buttons & (1 << 4)) {
|
|
|
|
[self.vScrollBar page:1 dir:1];
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#if 0
|
|
|
|
if (event.mouse.buttons & (1 << 5)) {
|
|
|
|
[self scrollLeft: 1];
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (event.mouse.buttons & (1 << 6)) {
|
|
|
|
[self scrollRight: 1];
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
} else if (event.what == qe_keydown) {
|
|
|
|
#if 0
|
|
|
|
switch (event.key.code) {
|
|
|
|
case QFK_PAGEUP:
|
|
|
|
if (event.key.shift & qe_control) {
|
|
|
|
[self moveBOT];
|
|
|
|
} else {
|
|
|
|
[self pageUp];
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
case QFK_PAGEDOWN:
|
|
|
|
if (event.key.shift & qe_control) {
|
|
|
|
[self moveEOT];
|
|
|
|
} else {
|
|
|
|
[self pageDown];
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
case QFK_UP:
|
|
|
|
if (event.key.shift & qe_control) {
|
|
|
|
[self linesUp];
|
|
|
|
} else {
|
|
|
|
[self charUp];
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
case QFK_DOWN:
|
|
|
|
if (event.key.shift & qe_control) {
|
|
|
|
[self linesDown];
|
|
|
|
} else {
|
|
|
|
[self charDown];
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
case QFK_LEFT:
|
|
|
|
if (event.key.shift & qe_control) {
|
|
|
|
[self wordLeft];
|
|
|
|
} else {
|
|
|
|
[self charLeft];
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
case QFK_RIGHT:
|
|
|
|
if (event.key.shift & qe_control) {
|
|
|
|
[self wordRight];
|
|
|
|
} else {
|
|
|
|
[self charRight];
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
case QFK_HOME:
|
|
|
|
if (event.key.shift & qe_control) {
|
|
|
|
[self moveBOS];
|
|
|
|
} else {
|
|
|
|
[self moveBOL];
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
case QFK_END:
|
|
|
|
if (event.key.shift & qe_control) {
|
|
|
|
[self moveEOS];
|
|
|
|
} else {
|
|
|
|
[self moveEOL];
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
-handleEvent:(qwaq_event_t *) event
|
|
|
|
{
|
|
|
|
[super handleEvent: event];
|
|
|
|
|
|
|
|
if (handleEvent (self, event)) {
|
|
|
|
event.what = qe_none;
|
|
|
|
}
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2020-03-31 01:55:39 +00:00
|
|
|
@end
|