ui/winui/table.cpp

branch
newapi
changeset 203
0e94be3d9722
child 205
b1ac0dd1d38b
equal deleted inserted replaced
202:9f309d1914a2 203:0e94be3d9722
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2023 Olaf Wintermann. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "table.h"
30 #include "container.h"
31 #include "util.h"
32
33 #include "../common/context.h"
34 #include "../common/object.h"
35
36 #include <winrt/Microsoft.UI.Xaml.Data.h>
37 #include <winrt/Microsoft.UI.Xaml.Media.h>
38 #include <winrt/Microsoft.UI.Xaml.Input.h>
39
40 using namespace winrt;
41 using namespace Microsoft::UI::Xaml;
42 using namespace Microsoft::UI::Xaml::Controls;
43 using namespace Windows::UI::Xaml::Interop;
44 using namespace winrt::Windows::Foundation;
45 using namespace winrt::Microsoft::UI::Xaml::Controls::Primitives;
46 using namespace winrt::Microsoft::UI::Xaml::Media;
47 using namespace winrt::Windows::UI::Xaml::Input;
48
49 extern "C" void reg_table_destructor(UiContext * ctx, UiTable * table) {
50 // TODO:
51 }
52
53 UIEXPORT UIWIDGET ui_table_create(UiObject* obj, UiListArgs args) {
54 if (!args.model) {
55 return nullptr;
56 }
57
58 UiObject* current = uic_current_obj(obj);
59
60 // create widgets and wrapper obj
61 ScrollViewer scrollW = ScrollViewer();
62 Grid grid = Grid();
63 scrollW.Content(grid);
64 UiTable* uitable = new UiTable(scrollW, grid);
65 reg_table_destructor(current->ctx, uitable);
66
67
68 uitable->getvalue = args.model->getvalue ? args.model->getvalue : args.getvalue;
69
70 // grid styling
71 winrt::Windows::UI::Color bg = { 233, 233, 255, 255 }; // test color
72 SolidColorBrush brush = SolidColorBrush(bg);
73 grid.Background(brush);
74
75 // add columns from args.model
76 uitable->add_header(args.model);
77
78 // bind var
79 UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.list, args.varname, UI_VAR_LIST);
80 if (var) {
81 UiList* list = (UiList*)var->value;
82 list->update = ui_table_update;
83 list->obj = uitable;
84 uitable->update(list, 0);
85 }
86
87 // create toolkit wrapper object and register destructor
88 UIElement elm = scrollW;
89 UiWidget* widget = new UiWidget(elm);
90 ui_context_add_widget_destructor(current->ctx, widget);
91
92 // add scrollW to current container
93 UI_APPLY_LAYOUT1(current, args);
94
95 current->container->Add(scrollW, false);
96
97 return widget;
98 }
99
100 extern "C" void ui_table_update(UiList * list, int i) {
101 UiTable* table = (UiTable*)list->obj;
102 table->clear();
103 table->update(list, i);
104 }
105
106 UiTable::UiTable(winrt::Microsoft::UI::Xaml::Controls::ScrollViewer scrollW, winrt::Microsoft::UI::Xaml::Controls::Grid grid) {
107 this->scrollw = scrollw;
108 this->grid = grid;
109
110 winrt::Windows::UI::Color highlightBg = { 120, 120, 255, 255 }; // test color
111 highlightBrush = SolidColorBrush(highlightBg);
112
113 winrt::Windows::UI::Color defaultBg = { 0, 0, 0, 0 }; // default
114 defaultBrush = SolidColorBrush(defaultBg);
115
116 winrt::Windows::UI::Color selectedBg = { 255, 120, 120, 255 }; // test color
117 selectedBrush = SolidColorBrush(selectedBg);
118
119 winrt::Windows::UI::Color selectedFg = { 255, 20, 20, 255 }; // test color
120 selectedBorderBrush = SolidColorBrush(selectedFg);
121 }
122
123 void UiTable::add_header(UiModel* model) {
124 GridLength gl;
125 gl.Value = 0;
126 gl.GridUnitType = GridUnitType::Auto;
127
128 // add header row definition
129 auto headerRowDef = RowDefinition();
130 headerRowDef.Height(gl);
131 grid.RowDefinitions().Append(headerRowDef);
132
133
134 for (int i = 0; i < model->columns;i++) {
135 char* title = model->titles[i];
136 UiModelType type = model->types[i];
137
138 // add grid column definition
139 auto colDef = ColumnDefinition();
140 colDef.Width(gl);
141 grid.ColumnDefinitions().Append(colDef);
142
143 // add button
144 auto button = Button();
145 wchar_t* wlabel = str2wstr(title, nullptr);
146 button.Content(box_value(wlabel));
147 free(wlabel);
148
149 // some styling for the button
150 Thickness border = { 0,0,1,0 };
151 CornerRadius corner = { 0,0,0,0 };
152 button.BorderThickness(border);
153 button.CornerRadius(corner);
154
155 grid.SetColumn(button, i);
156 grid.SetRow(button, 0);
157 grid.Children().Append(button);
158
159 UiTableColumn h;
160 h.header = button;
161 header.push_back(h);
162 }
163
164 maxrows = 1;
165 }
166
167 void UiTable::update(UiList* list, int i) {
168 if (getvalue == nullptr) {
169 return;
170 }
171
172 Thickness b1 = { 1, 1, 0, 1 }; // first col
173 Thickness b2 = { 0, 1, 0, 1 }; // middle
174 Thickness b3 = { 0, 1, 1, 1 }; // last col
175
176 GridLength gl;
177 gl.Value = 0;
178 gl.GridUnitType = GridUnitType::Auto;
179
180 int row = 1;
181 void* elm = list->first(list);
182 while (elm) {
183 if (row >= maxrows) {
184 auto rowdef = RowDefinition();
185 rowdef.Height(gl);
186 grid.RowDefinitions().Append(rowdef);
187 maxrows = row;
188 }
189
190 for (int col = 0; col < header.size(); col++) {
191 Border cellBorder = Border();
192 cellBorder.Background(defaultBrush);
193 TextBlock cell = TextBlock();
194 cellBorder.Child(cell);
195 cellBorder.BorderBrush(defaultBrush);
196 if (col == 0) {
197 cellBorder.BorderThickness(b1);
198 }
199 else if (col + 1 == header.size()) {
200 cellBorder.BorderThickness(b3);
201 }
202 else {
203 cellBorder.BorderThickness(b2);
204 }
205
206 char* value = (char*)getvalue(elm, col);
207 if (value) {
208 wchar_t* wstr = str2wstr(value, nullptr);
209 cell.Text(winrt::hstring(wstr));
210 free(wstr);
211 }
212 Thickness padding = { 10,0,4,0 };
213 cell.Padding(padding);
214 cell.VerticalAlignment(VerticalAlignment::Stretch);
215
216 // event handler
217 cellBorder.PointerPressed(
218 winrt::Microsoft::UI::Xaml::Input::PointerEventHandler(
219 [=](IInspectable const& sender, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const& args) {
220 if (selection > 0) {
221 row_background(selection, defaultBrush, defaultBrush);
222 }
223 row_background(row, selectedBrush, selectedBorderBrush);
224 selection = row;
225 })
226 );
227 cellBorder.PointerReleased(
228 winrt::Microsoft::UI::Xaml::Input::PointerEventHandler(
229 [=](IInspectable const& sender, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const& args) {
230
231 })
232 );
233 cellBorder.PointerEntered(
234 winrt::Microsoft::UI::Xaml::Input::PointerEventHandler(
235 [=](IInspectable const& sender, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const& args) {
236 if (selection != row) {
237 row_background(row, highlightBrush, highlightBrush);
238 }
239 })
240 );
241 cellBorder.PointerExited(
242 winrt::Microsoft::UI::Xaml::Input::PointerEventHandler(
243 [=](IInspectable const& sender, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const& args) {
244 if (selection != row) {
245 row_background(row, defaultBrush, defaultBrush);
246 }
247 })
248 );
249
250 grid.SetColumn(cellBorder, col);
251 grid.SetRow(cellBorder, row);
252 grid.Children().Append(cellBorder);
253 }
254
255 row++;
256 elm = list->next(list);
257 }
258 }
259
260 void UiTable::clear() {
261 for (int i = grid.Children().Size()-1; i >= 0; i--) {
262 FrameworkElement elm = grid.Children().GetAt(i).as<FrameworkElement>();
263 int child_row = grid.GetRow(elm);
264 if (child_row > 0) {
265 grid.Children().RemoveAt(i);
266 }
267 }
268 }
269
270 void UiTable::row_background(int row, winrt::Microsoft::UI::Xaml::Media::Brush brush, winrt::Microsoft::UI::Xaml::Media::Brush borderBrush) {
271 Thickness b1 = { 1, 1, 0, 1 }; // first col
272 Thickness b2 = { 0, 1, 0, 1 }; // middle
273 Thickness b3 = { 0, 1, 1, 1 }; // last col
274
275 for (auto child : grid.Children()) {
276 FrameworkElement elm = child.as<FrameworkElement>();
277 int child_row = grid.GetRow(elm);
278 if (child_row == row) {
279 Border b = elm.as<Border>();
280 b.Background(brush);
281 b.BorderBrush(borderBrush);
282 }
283 }
284 }

mercurial