Thu, 22 Feb 2024 22:25:53 +0100
implement listview (GTK)
/* * 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 <stdio.h> #import <stdlib.h> #import "tree.h" #import "container.h" #import "window.h" #import "../common/context.h" #import <ucx/utils.h> @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;i<modelinfo->columns;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; }