diff -r 000000000000 -r 2483f517c562 ui/cocoa/tree.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/cocoa/tree.m Sun Jan 21 16:30:18 2024 +0100 @@ -0,0 +1,246 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2012 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#import +#import + +#import "tree.h" +#import "container.h" +#import "window.h" +#import "../common/context.h" +#import + +@implementation UiTableDataSource + +- (id)initWithData:(UiList*)list modelInfo:(UiModelInfo*)modelinfo { + data = list; + info = modelinfo; + lastSelection = NULL; + return self; +} + +- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableview { + return data->count(data); +} + +- (id)tableView: (NSTableView*)tableview + objectValueForTableColumn:(NSTableColumn*)column + row:(NSInteger)row +{ + int column_index = [[column identifier]intValue]; + + void *row_data = data->get(data, row); + void *cell_data = info->getvalue(row_data, column_index); + + BOOL f = false; + char *str = ui_type_to_string(info->types[column_index], cell_data, &f); + NSString *s = [[NSString alloc]initWithUTF8String:str]; + return s; +} + +- (void)tableView:(NSTableView *)tableview + setObjectValue:(id)object + forTableColumn:(NSTableColumn *)column + row:(NSInteger)row +{ + int column_index = [[column identifier]intValue]; + + // TODO +} + +- (void)tableViewSelectionDidChange:(NSNotification *)notification { + NSTableView *tableview = (NSTableView*)notification.object; + + // create selection object + UiListSelection *selection = malloc(sizeof(UiListSelection)); + selection->count = [tableview numberOfSelectedRows]; + + selection->rows = calloc(selection->count, sizeof(int)); + NSIndexSet *indices = [tableview selectedRowIndexes]; + NSUInteger index = [indices firstIndex]; + int i=0; + while (index!=NSNotFound) { + selection->rows[i] = index; + index = [indices indexGreaterThanIndex:index]; + i++; + } + + // create event object + UiEvent event; + NSWindow *activeWindow = [NSApp keyWindow]; + if([activeWindow class] == [UiCocoaWindow class]) { + event.obj = [(UiCocoaWindow*)activeWindow object]; + event.window = event.obj->window; + event.document = event.obj->ctx->document; + } else { + event.window = NULL; + event.document = NULL; + } + event.eventdata = selection; + event.intval = selection->count == 0 ? -1 : selection->rows[0]; + + // callback + info->selection(&event, info->userdata); + + // cleanup + if(lastSelection) { + free(lastSelection->rows); + free(lastSelection); + } + lastSelection = selection; +} + +- (void)handleDoubleAction:(id)sender { + // create event object + UiEvent event; + NSWindow *activeWindow = [NSApp keyWindow]; + if([activeWindow class] == [UiCocoaWindow class]) { + event.obj = [(UiCocoaWindow*)activeWindow object]; + event.window = event.obj->window; + event.document = event.obj->ctx->document; + } else { + event.window = NULL; + event.document = NULL; + } + event.eventdata = lastSelection; + event.intval = lastSelection->count == 0 ? -1 : lastSelection->rows[0]; + + info->activate(&event, info->userdata); +} + +- (BOOL)tableView:(NSTableView *)tableview isGroupRow:(NSInteger)row { + return NO; +} + +@end + + +UIWIDGET ui_table(UiObject *obj, UiList *model, UiModelInfo *modelinfo) { + UiContainer *ct = uic_get_current_container(obj); + NSRect frame = ct->getframe(ct); + + NSScrollView *scrollview = [[NSScrollView alloc] initWithFrame:frame]; + [scrollview setHasVerticalScroller:YES]; + //[scrollvew setHasHorizontalScroller:YES]; + [scrollview setBorderType:NSNoBorder]; + //[scrollview setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; + + NSTableView *tableview = [[NSTableView alloc]initWithFrame:frame]; + [scrollview setDocumentView:tableview]; + [tableview setAllowsMultipleSelection: YES]; + //[tableview setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleSourceList]; + + // add columns + for(int i=0;icolumns;i++) { + NSString *cid = [[NSString alloc]initWithFormat: @"%d", i]; + NSTableColumn *column = [[NSTableColumn alloc]initWithIdentifier:cid]; + + NSString *title = [[NSString alloc]initWithUTF8String: modelinfo->titles[i]]; + [[column headerCell] setStringValue:title]; + + [tableview addTableColumn:column]; + } + + UiTableDataSource *source = [[UiTableDataSource alloc]initWithData:model modelInfo:modelinfo]; + [tableview setDataSource:source]; + [tableview setDelegate:source]; + + [tableview setDoubleAction:@selector(handleDoubleAction:)]; + [tableview setTarget:source]; + + + ct->add(ct, scrollview); + return scrollview; +} + + +UIWIDGET ui_listview_var(UiObject *obj, UiListPtr *list, ui_model_getvalue_f getvalue, ui_callback f, void *udata) { + UiContainer *ct = uic_get_current_container(obj); + NSRect frame = ct->getframe(ct); + + NSScrollView *scrollview = [[NSScrollView alloc] initWithFrame:frame]; + [scrollview setHasVerticalScroller:YES]; + + [scrollview setBorderType:NSNoBorder]; + + NSTableView *tableview = [[NSTableView alloc]initWithFrame:frame]; + [scrollview setDocumentView:tableview]; + [tableview setAllowsMultipleSelection: NO]; + + // add single column + NSTableColumn *column = [[NSTableColumn alloc]initWithIdentifier:@"c"]; + [tableview addTableColumn:column]; + + // create model info + UiModelInfo *modelinfo = ui_model_info(obj->ctx, UI_STRING, -1); + + // add source + UiTableDataSource *source = [[UiTableDataSource alloc]initWithData:list->list modelInfo:modelinfo]; + + [tableview setDataSource:source]; + [tableview setDelegate:source]; + + [tableview setDoubleAction:@selector(handleDoubleAction:)]; + [tableview setTarget:source]; + + ct->add(ct, scrollview); + return scrollview; +} + +UIWIDGET ui_listview(UiObject *obj, UiList *list, ui_model_getvalue_f getvalue, ui_callback f, void *udata) { + UiListPtr *listptr = ucx_mempool_malloc(obj->ctx->mempool, sizeof(UiListPtr)); + listptr->list = list; + return ui_listview_var(obj, listptr, getvalue, f, udata); +} + +UIWIDGET ui_listview_nv(UiObject *obj, char *varname, ui_model_getvalue_f getvalue, ui_callback f, void *udata) { + UiVar *var = uic_connect_var(obj->ctx, varname, UI_VAR_LIST); + if(var) { + UiListVar *value = var->value; + return ui_listview_var(obj, value->listptr, getvalue, f, udata); + } else { + // TODO: error + } + return NULL; +} + + +// TODO: motif code duplicate +char* ui_type_to_string(UiModelType type, void *data, BOOL *free) { + switch(type) { + case UI_STRING: *free = FALSE; return data; + case UI_INTEGER: { + *free = TRUE; + int *val = data; + sstr_t str = ucx_asprintf(ucx_default_allocator(), "%d", *val); + return str.ptr; + } + } + *free = FALSE; + return NULL; +}