# HG changeset patch # User Olaf Wintermann # Date 1756562572 -7200 # Node ID 0dbf92544d4f6960dbdb94ff273d29813a5e0546 # Parent ac7f0869e8ae10f54bccce90dc0b499d9e4bb6ef add stylefunc for table/listview for row and cell styling options (GTK) diff -r ac7f0869e8ae -r 0dbf92544d4f application/main.c --- a/application/main.c Sat Aug 30 10:18:09 2025 +0200 +++ b/application/main.c Sat Aug 30 16:02:52 2025 +0200 @@ -460,6 +460,17 @@ return NULL; } +UiBool table_getstyle(UiList *list, void *elm, int row, int col, void *userdata, UiTextStyle *style) { + if(row < 2 && col != -1) { + style->text_style = UI_TEXT_STYLE_BOLD; + style->fg.blue = col == 0 ? 255 : 0; + style->fg.green = col == 1 ? 255 : 0; + style->fg.red = col == 4 ? 255 : 0; + return TRUE; + } + return FALSE; +} + void sourcelist_getvalue(UiList *list, void *sublistdata, void *rowdata, int index, UiSubListItem *item, void *userdata) { item->label = strdup(rowdata); item->eventdata = sublistdata; @@ -628,7 +639,7 @@ UiModel *model = ui_model(obj->ctx, UI_STRING, "col1", UI_INTEGER, "col2", UI_ICON, "col3", UI_ICON_TEXT, "col4", UI_INTEGER, "col5", -1); model->columnsize[0] = -1; ui_table(obj, .model = model, .list = doc->list2, .colspan = 2, .fill = TRUE, .contextmenu = menubuilder, .multiselection = TRUE, .fill = TRUE, - .getvalue = table_getvalue, + .getvalue = table_getvalue, .getstyle = table_getstyle, .onactivate = action_table_activate, .onactivatedata = "activate", .onselection = action_table_activate, .onselectiondata = "selection"); ui_hbox(obj, .fill = FALSE) { diff -r ac7f0869e8ae -r 0dbf92544d4f ui/gtk/list.c --- a/ui/gtk/list.c Sat Aug 30 10:18:09 2025 +0200 +++ b/ui/gtk/list.c Sat Aug 30 16:02:52 2025 +0200 @@ -92,6 +92,12 @@ tableview->ondropdata = args->ondropdata; tableview->selection.count = 0; tableview->selection.rows = NULL; + tableview->current_row = -1; + tableview->getstyle = args->getstyle; + tableview->getstyledata = args->getstyledata; +#if GTK_CHECK_VERSION(4, 10, 0) + tableview->default_attributes = pango_attr_list_new(); +#endif if(args->getvalue2) { tableview->getvalue = args->getvalue2; @@ -102,7 +108,7 @@ } else { tableview->getvalue = null_getvalue; } - + return tableview; } @@ -163,6 +169,28 @@ } } +PangoAttrList* textstyle2pangoattributes(UiTextStyle style) { + PangoAttrList *attr = pango_attr_list_new(); + + if(style.text_style & UI_TEXT_STYLE_BOLD) { + pango_attr_list_insert(attr, pango_attr_weight_new(PANGO_WEIGHT_BOLD)); + } + if(style.text_style & UI_TEXT_STYLE_ITALIC) { + pango_attr_list_insert(attr, pango_attr_style_new(PANGO_STYLE_ITALIC)); + } + if(style.text_style & UI_TEXT_STYLE_UNDERLINE) { + pango_attr_list_insert(attr, pango_attr_underline_new(PANGO_UNDERLINE_SINGLE)); + } + + // foreground color, convert from 8bit to 16bit + guint16 r = (guint16)style.fg.red * 257; + guint16 g = (guint16)style.fg.green * 257; + guint16 b = (guint16)style.fg.blue * 257; + pango_attr_list_insert(attr, pango_attr_foreground_new(r, g, b)); + + return attr; +} + static void column_factory_bind(GtkListItemFactory *factory, GtkListItem *item, gpointer userdata) { UiColData *col = userdata; UiList *list = col->listview->var ? col->listview->var->value : NULL; @@ -176,6 +204,34 @@ void *data = listview->getvalue(list, obj->data, obj->i, col->data_column, listview->getvaluedata, &freevalue); GtkWidget *child = gtk_list_item_get_child(item); + PangoAttrList *attributes = NULL; + UiTextStyle style = { 0, 0 }; + if(listview->getstyle) { + // query current row style, if it wasn't already queried + if(obj->i != listview->current_row) { + listview->current_row = obj->i; + listview->row_style = (UiTextStyle){ 0, 0 }; + listview->apply_row_style = listview->getstyle(list, obj->data, obj->i, -1, listview->getstyledata, &listview->row_style); + style = listview->row_style; + if(listview->apply_row_style) { + pango_attr_list_unref(listview->current_row_attributes); + listview->current_row_attributes = textstyle2pangoattributes(style); + } + } + + int style_col = col->data_column; + if(type == UI_ICON_TEXT || type == UI_ICON_TEXT_FREE) { + style_col++; // col->data_column is the icon, we need the next col for the label + } + + // get the column style + if(listview->getstyle(list, obj->data, obj->i, style_col, listview->getstyledata, &style)) { + attributes = textstyle2pangoattributes(style); + } else if(listview->apply_row_style) { + attributes = listview->current_row_attributes; + } + } + switch(type) { case UI_STRING_FREE: { freevalue = TRUE; @@ -185,6 +241,7 @@ if(freevalue) { free(data); } + gtk_label_set_attributes(GTK_LABEL(child), attributes); break; } case UI_INTEGER: { @@ -192,6 +249,7 @@ char buf[32]; snprintf(buf, 32, "%d", (int)intvalue); gtk_label_set_label(GTK_LABEL(child), buf); + gtk_label_set_attributes(GTK_LABEL(child), attributes); break; } case UI_ICON: { @@ -217,6 +275,7 @@ } if(data2 && label) { gtk_label_set_label(GTK_LABEL(label), data2); + gtk_label_set_attributes(GTK_LABEL(label), attributes); } if(freevalue) { free(data2); @@ -224,6 +283,10 @@ break; } } + + if(attributes != listview->current_row_attributes) { + pango_attr_list_unref(attributes); + } } static GtkSelectionModel* create_selection_model(UiListView *listview, GListStore *liststore, bool multiselection) { @@ -1676,6 +1739,8 @@ } #if GTK_CHECK_VERSION(4, 10, 0) free(v->columns); + pango_attr_list_unref(v->default_attributes); + pango_attr_list_unref(v->current_row_attributes); #endif free(v->selection.rows); free(v); diff -r ac7f0869e8ae -r 0dbf92544d4f ui/gtk/list.h --- a/ui/gtk/list.h Sat Aug 30 10:18:09 2025 +0200 +++ b/ui/gtk/list.h Sat Aug 30 16:02:52 2025 +0200 @@ -47,12 +47,19 @@ UiModel *model; ui_getvaluefunc2 getvalue; void *getvaluedata; + ui_stylefunc getstyle; + void *getstyledata; char **elements; size_t nelm; + int current_row; + UiTextStyle row_style; + UiBool apply_row_style; #if GTK_CHECK_VERSION(4, 10, 0) GListStore *liststore; GtkSelectionModel *selectionmodel; UiColData *columns; + PangoAttrList *default_attributes; // TODO: remove + PangoAttrList *current_row_attributes; #endif ui_callback onactivate; void *onactivatedata; diff -r ac7f0869e8ae -r 0dbf92544d4f ui/ui/toolkit.h --- a/ui/ui/toolkit.h Sat Aug 30 10:18:09 2025 +0200 +++ b/ui/ui/toolkit.h Sat Aug 30 16:02:52 2025 +0200 @@ -200,6 +200,9 @@ typedef struct UiListSelection UiListSelection; +typedef struct UiTextStyle UiTextStyle; +typedef struct UiColor UiColor; + /* begin opaque types */ typedef struct UiContext UiContext; typedef struct UiContainer UiContainer; @@ -251,6 +254,7 @@ typedef void*(*ui_getvaluefunc)(void *elm, int col); typedef void*(*ui_getvaluefunc2)(UiList *list, void *elm, int row, int col, void *userdata, UiBool *freeResult); +typedef UiBool(*ui_stylefunc)(UiList *list, void *elm, int row, int col, void *userdata, UiTextStyle *style); typedef int(*ui_threadfunc)(void*); @@ -502,6 +506,22 @@ UI_EVENT_DATA_FILE_LIST }; +#define UI_COLOR(r, g, b) (UiColor){r, g, b} +struct UiColor { + uint8_t red; + uint8_t green; + uint8_t blue; +}; + +#define UI_TEXT_STYLE_BOLD 1 +#define UI_TEXT_STYLE_ITALIC 2 +#define UI_TEXT_STYLE_UNDERLINE 4 + +struct UiTextStyle { + uint32_t text_style; + UiColor fg; +}; + UIEXPORT void ui_init(const char *appname, int argc, char **argv); UIEXPORT const char* ui_appname(); diff -r ac7f0869e8ae -r 0dbf92544d4f ui/ui/tree.h --- a/ui/ui/tree.h Sat Aug 30 10:18:09 2025 +0200 +++ b/ui/ui/tree.h Sat Aug 30 16:02:52 2025 +0200 @@ -120,6 +120,8 @@ ui_getvaluefunc getvalue; ui_getvaluefunc2 getvalue2; void *getvalue2data; + ui_stylefunc getstyle; + void *getstyledata; ui_callback onactivate; void* onactivatedata; ui_callback onselection;