# HG changeset patch # User Olaf Wintermann # Date 1697203254 -7200 # Node ID 1bd5534c395da647e3824ba917d5073dd686edc7 # Parent 279c0c81d3b12dcf230dfff268e3a0e1c5052b98 add support for icons in the table widget (WinUI3) diff -r 279c0c81d3b1 -r 1bd5534c395d make/vs/testapp/main.c --- a/make/vs/testapp/main.c Fri Oct 13 11:26:47 2023 +0200 +++ b/make/vs/testapp/main.c Fri Oct 13 15:20:54 2023 +0200 @@ -48,6 +48,8 @@ UiList* list3; } WindowData; +static UiIcon* folder_icon; + void action1(UiEvent* event, void* data) { char* action = data; @@ -105,9 +107,10 @@ void* table_getvalue(void* data, int i) { TableData* t = data; switch (i) { - case 0: return t->col1; - case 1: return t->col2; - case 2: return t->col3; + case 0: return folder_icon; + case 1: return t->col1; + case 2: return t->col2; + case 3: return t->col3; } return NULL; } @@ -160,6 +163,7 @@ ui_list_append(wdata->list3, "test"); ui_list_append(wdata->list3, "dir"); + folder_icon = ui_icon("Folder", 32); TableData* td1 = malloc(sizeof(TableData)); TableData* td2 = malloc(sizeof(TableData)); @@ -263,7 +267,7 @@ ui_newline(obj); - UiModel* model = ui_model(obj->ctx, UI_STRING, "Col 1", UI_STRING, "Col 2", UI_STRING, "Col 3", -1); + UiModel* model = ui_model(obj->ctx, UI_ICON_TEXT, "Col 1", UI_STRING, "Col 2", UI_STRING, "Col 3", -1); model->getvalue = table_getvalue; ui_table(obj, .colspan = 3, .model = model, .list = wdata->list2); ui_model_free(obj->ctx, model); diff -r 279c0c81d3b1 -r 1bd5534c395d ui/common/types.c --- a/ui/common/types.c Fri Oct 13 11:26:47 2023 +0200 +++ b/ui/common/types.c Fri Oct 13 15:20:54 2023 +0200 @@ -204,10 +204,28 @@ return info; } +UiModel* ui_model_copy(UiContext *ctx, UiModel* model) { + const CxAllocator* a = ctx ? ctx->allocator : cxDefaultAllocator; + + UiModel* newmodel = cxMalloc(a, sizeof(UiModel)); + *newmodel = *model; + + newmodel->types = cxCalloc(a, model->columns, sizeof(UiModelType)); + memcpy(newmodel->types, model->types, model->columns); + + newmodel->titles = cxCalloc(a, model->columns, sizeof(char*)); + for (int i = 0; i < model->columns; i++) { + newmodel->titles[i] = model->titles[i] ? cx_strdup_a(a, cx_str(model->titles[i])).ptr : NULL; + } + + return newmodel; +} + void ui_model_free(UiContext *ctx, UiModel *mi) { - cxFree(ctx->allocator, mi->types); - cxFree(ctx->allocator, mi->titles); - cxFree(ctx->allocator, mi); + const CxAllocator* a = ctx ? ctx->allocator : cxDefaultAllocator; + cxFree(a, mi->types); + cxFree(a, mi->titles); + cxFree(a, mi); } // types diff -r 279c0c81d3b1 -r 1bd5534c395d ui/common/types.h --- a/ui/common/types.h Fri Oct 13 11:26:47 2023 +0200 +++ b/ui/common/types.h Fri Oct 13 15:20:54 2023 +0200 @@ -55,7 +55,7 @@ void uic_text_unbind(UiText *t); void uic_range_unbind(UiRange *r); void uic_list_unbind(UiList *l); - + #ifdef __cplusplus } #endif diff -r 279c0c81d3b1 -r 1bd5534c395d ui/ui/image.h --- a/ui/ui/image.h Fri Oct 13 11:26:47 2023 +0200 +++ b/ui/ui/image.h Fri Oct 13 15:20:54 2023 +0200 @@ -35,6 +35,13 @@ extern "C" { #endif + /* +UIEXPORT UiIcon* ui_icon(const char* name, size_t size); +UIEXPORT UiIcon* ui_imageicon(const char* file); +UIEXPORT void ui_icon_free(UiIcon* icon); +*/ + +/* UiIcon* ui_icon(const char *name, int size); UiIcon* ui_icon_unscaled(const char *name, int size); void ui_free_icon(UiIcon *icon); @@ -44,6 +51,7 @@ UiImage* ui_named_image(const char *filename, const char *name); UiImage* ui_load_image_from_path(const char *path, const char *name); void ui_free_image(UiImage *img); +*/ #ifdef __cplusplus diff -r 279c0c81d3b1 -r 1bd5534c395d ui/ui/toolkit.h --- a/ui/ui/toolkit.h Fri Oct 13 11:26:47 2023 +0200 +++ b/ui/ui/toolkit.h Fri Oct 13 15:20:54 2023 +0200 @@ -433,6 +433,14 @@ UIEXPORT void ui_set_visible(UIWIDGET widget, int visible); + + + +UIEXPORT UiIcon* ui_icon(const char* name, size_t size); +UIEXPORT UiIcon* ui_imageicon(const char* file); +UIEXPORT void ui_icon_free(UiIcon* icon); + + #ifdef __cplusplus } #endif diff -r 279c0c81d3b1 -r 1bd5534c395d ui/ui/tree.h --- a/ui/ui/tree.h Fri Oct 13 11:26:47 2023 +0200 +++ b/ui/ui/tree.h Fri Oct 13 15:20:54 2023 +0200 @@ -129,6 +129,7 @@ }; UIEXPORT UiModel* ui_model(UiContext *ctx, ...); +UIEXPORT UiModel* ui_model_copy(UiContext *ctx, UiModel* model); UIEXPORT void ui_model_free(UiContext *ctx, UiModel *mi); #define ui_listview(obj, ...) ui_listview_create(obj, (UiListArgs) { __VA_ARGS__ } ) diff -r 279c0c81d3b1 -r 1bd5534c395d ui/winui/icons.cpp --- a/ui/winui/icons.cpp Fri Oct 13 11:26:47 2023 +0200 +++ b/ui/winui/icons.cpp Fri Oct 13 15:20:54 2023 +0200 @@ -33,6 +33,7 @@ #include #include +#include "util.h" using namespace winrt; using namespace Microsoft::UI::Xaml; @@ -252,3 +253,50 @@ SymbolIcon icon = SymbolIcon(symbol); return icon; } + + +// symbol icon implementation +UiSymbolIcon::UiSymbolIcon(winrt::Microsoft::UI::Xaml::Controls::Symbol sym) { + symbol = sym; +} + +UiSymbolIcon::~UiSymbolIcon() { + +} + +winrt::Microsoft::UI::Xaml::Controls::IconElement UiSymbolIcon::getIcon() { + return SymbolIcon(symbol); +} + +// image icon implementation +UiImageIcon::UiImageIcon(const char* uristr) { + wchar_t* wuri = str2wstr(uristr, nullptr); + Windows::Foundation::Uri uri{ wuri }; + this->uri = uri; + free(wuri); +} + +UiImageIcon::~UiImageIcon() { + +} + +winrt::Microsoft::UI::Xaml::Controls::IconElement UiImageIcon::getIcon() { + BitmapIcon icon = BitmapIcon(); + icon.UriSource(uri); + return icon; +} + +UIEXPORT UiIcon* ui_icon(const char* name, size_t size) { + Symbol symbol = ui_symbol_icons[name]; + UiSymbolIcon* icon = new UiSymbolIcon(symbol); + return icon; +} + + +UIEXPORT UiIcon* ui_imageicon(const char* file) { + return new UiImageIcon(file); +} + +UIEXPORT void ui_icon_free(UiIcon* icon) { + delete icon; +} diff -r 279c0c81d3b1 -r 1bd5534c395d ui/winui/icons.h --- a/ui/winui/icons.h Fri Oct 13 11:26:47 2023 +0200 +++ b/ui/winui/icons.h Fri Oct 13 15:20:54 2023 +0200 @@ -30,12 +30,33 @@ #include "../ui/toolkit.h" + + struct UiIcon { - winrt::Microsoft::UI::Xaml::Controls::IconElement icon; + //virtual ~UiIcon() = 0; + + virtual winrt::Microsoft::UI::Xaml::Controls::IconElement getIcon() = 0; }; -void ui_init_symbol_icons(); +struct UiSymbolIcon : UiIcon { + winrt::Microsoft::UI::Xaml::Controls::Symbol symbol; + + UiSymbolIcon(winrt::Microsoft::UI::Xaml::Controls::Symbol sym); + + ~UiSymbolIcon(); + + winrt::Microsoft::UI::Xaml::Controls::IconElement getIcon(); +}; -void ui_add_symbol_icon(std::string name, winrt::Microsoft::UI::Xaml::Controls::Symbol symbol); +struct UiImageIcon : UiIcon { + winrt::Windows::Foundation::Uri uri{ nullptr }; + + UiImageIcon(const char* uristr); + + ~UiImageIcon(); + + winrt::Microsoft::UI::Xaml::Controls::IconElement getIcon(); +}; + winrt::Microsoft::UI::Xaml::Controls::IconElement ui_get_icon(const char* name); diff -r 279c0c81d3b1 -r 1bd5534c395d ui/winui/table.cpp --- a/ui/winui/table.cpp Fri Oct 13 11:26:47 2023 +0200 +++ b/ui/winui/table.cpp Fri Oct 13 15:20:54 2023 +0200 @@ -31,9 +31,11 @@ #include "table.h" #include "container.h" #include "util.h" +#include "icons.h" #include "../common/context.h" #include "../common/object.h" +#include "../common/types.h" #include #include @@ -130,7 +132,13 @@ ); } +UiTable::~UiTable() { + ui_model_free(NULL, model); +} + void UiTable::add_header(UiModel* model) { + this->model = ui_model_copy(NULL, model); + GridLength gl; gl.Value = 0; gl.GridUnitType = GridUnitType::Auto; @@ -174,6 +182,20 @@ maxrows = 1; } +static void textblock_set_str(TextBlock &t, const char *str) { + if (str) { + wchar_t* wstr = str2wstr(str, nullptr); + t.Text(winrt::hstring(wstr)); + free(wstr); + } +} + +static void textblock_set_int(TextBlock& t, int i) { + wchar_t buf[16]; + swprintf(buf, 16, L"%d", i); + t.Text(winrt::hstring(buf)); +} + void UiTable::update(UiList* list, int i) { if (getvalue == nullptr) { return; @@ -197,13 +219,66 @@ maxrows = row; } - for (int col = 0; col < header.size(); col++) { + Thickness cellpadding = { 10,0,4,0 }; + + int model_col = 0; + for (int col = 0; col < header.size(); col++, model_col++) { // create ui elements with the correct cell border // dependeing on the column Border cellBorder = Border(); cellBorder.Background(defaultBrush); - TextBlock cell = TextBlock(); - cellBorder.Child(cell); + + // set the cell value + UiModelType type = model->types[col]; + switch (type) { + case UI_STRING: { + TextBlock cell = TextBlock(); + cell.Padding(cellpadding); + cell.VerticalAlignment(VerticalAlignment::Stretch); + textblock_set_str(cell, (char*)getvalue(elm, model_col)); + cellBorder.Child(cell); + break; + } + case UI_INTEGER: { + TextBlock cell = TextBlock(); + cell.Padding(cellpadding); + cell.VerticalAlignment(VerticalAlignment::Stretch); + int *value = (int*)getvalue(elm, model_col); + if (value) { + textblock_set_int(cell, *value); + } + cellBorder.Child(cell); + break; + } + case UI_ICON: { + UiIcon* iconConstr = (UiIcon*)getvalue(elm, model_col); + if (iconConstr) { + IconElement icon = iconConstr->getIcon(); + cellBorder.Child(icon); + } + break; + } + case UI_ICON_TEXT: { + StackPanel cellPanel = StackPanel(); + cellPanel.Spacing(2); + cellPanel.Padding(cellpadding); + cellPanel.VerticalAlignment(VerticalAlignment::Stretch); + + cellPanel.Orientation(Orientation::Horizontal); + UiIcon* iconConstr = (UiIcon*)getvalue(elm, model_col++); + char* str = (char*)getvalue(elm, model_col); + if (iconConstr) { + IconElement icon = iconConstr->getIcon(); + cellPanel.Children().Append(icon); + } + TextBlock cell = TextBlock(); + textblock_set_str(cell, str); + cellPanel.Children().Append(cell); + cellBorder.Child(cellPanel); + break; + } + } + cellBorder.BorderBrush(defaultBrush); if (col == 0) { cellBorder.BorderThickness(b1); @@ -214,17 +289,6 @@ else { cellBorder.BorderThickness(b2); } - Thickness padding = { 10,0,4,0 }; - cell.Padding(padding); - cell.VerticalAlignment(VerticalAlignment::Stretch); - - // set cell value - char* value = (char*)getvalue(elm, col); - if (value) { - wchar_t* wstr = str2wstr(value, nullptr); - cell.Text(winrt::hstring(wstr)); - free(wstr); - } // event handler cellBorder.PointerPressed( diff -r 279c0c81d3b1 -r 1bd5534c395d ui/winui/table.h --- a/ui/winui/table.h Fri Oct 13 11:26:47 2023 +0200 +++ b/ui/winui/table.h Fri Oct 13 15:20:54 2023 +0200 @@ -45,13 +45,16 @@ winrt::Microsoft::UI::Xaml::Media::SolidColorBrush highlightBrush; winrt::Microsoft::UI::Xaml::Media::SolidColorBrush selectedBrush; winrt::Microsoft::UI::Xaml::Media::SolidColorBrush selectedBorderBrush; + UiModel* model = nullptr; std::vector header; - ui_getvaluefunc getvalue; - int maxrows; - int lastSelection; + ui_getvaluefunc getvalue = nullptr; + int maxrows = 0; + int lastSelection = 0; std::vector selection; UiTable(winrt::Microsoft::UI::Xaml::Controls::ScrollViewer scrollW, winrt::Microsoft::UI::Xaml::Controls::Grid grid); + + ~UiTable(); void add_header(UiModel* model);