ui/winui/table.cpp

branch
newapi
changeset 218
d06e7e8e53e1
parent 216
391c2c723029
child 221
a82d9beaa94a
equal deleted inserted replaced
217:b9798109c7d2 218:d06e7e8e53e1
49 using namespace winrt::Windows::Foundation; 49 using namespace winrt::Windows::Foundation;
50 using namespace winrt::Microsoft::UI::Xaml::Controls::Primitives; 50 using namespace winrt::Microsoft::UI::Xaml::Controls::Primitives;
51 using namespace winrt::Microsoft::UI::Xaml::Media; 51 using namespace winrt::Microsoft::UI::Xaml::Media;
52 using namespace winrt::Windows::UI::Xaml::Input; 52 using namespace winrt::Windows::UI::Xaml::Input;
53 53
54 static UINT ui_double_click_time = GetDoubleClickTime();
55
54 extern "C" void reg_table_destructor(UiContext * ctx, UiTable * table) { 56 extern "C" void reg_table_destructor(UiContext * ctx, UiTable * table) {
55 // TODO: 57 // TODO:
56 } 58 }
57 59
58 UIEXPORT UIWIDGET ui_table_create(UiObject* obj, UiListArgs args) { 60 UIEXPORT UIWIDGET ui_table_create(UiObject* obj, UiListArgs args) {
64 66
65 // create widgets and wrapper obj 67 // create widgets and wrapper obj
66 ScrollViewer scrollW = ScrollViewer(); 68 ScrollViewer scrollW = ScrollViewer();
67 Grid grid = Grid(); 69 Grid grid = Grid();
68 scrollW.Content(grid); 70 scrollW.Content(grid);
69 UiTable* uitable = new UiTable(scrollW, grid); 71 UiTable* uitable = new UiTable(obj, scrollW, grid);
70 reg_table_destructor(current->ctx, uitable); 72 reg_table_destructor(current->ctx, uitable);
71
72 73
73 uitable->getvalue = args.model->getvalue ? args.model->getvalue : args.getvalue; 74 uitable->getvalue = args.model->getvalue ? args.model->getvalue : args.getvalue;
75 uitable->onselection = args.onselection;
76 uitable->onselectiondata = args.onselectiondata;
77 uitable->onactivate = args.onactivate;
78 uitable->onactivatedata = args.onactivatedata;
74 79
75 // grid styling 80 // grid styling
76 winrt::Windows::UI::Color bg = { 255, 255, 255, 255 }; // test color 81 winrt::Windows::UI::Color bg = { 255, 255, 255, 255 }; // test color
77 SolidColorBrush brush = SolidColorBrush(bg); 82 SolidColorBrush brush = SolidColorBrush(bg);
78 grid.Background(brush); 83 grid.Background(brush);
106 UiTable* table = (UiTable*)list->obj; 111 UiTable* table = (UiTable*)list->obj;
107 table->clear(); 112 table->clear();
108 table->update(list, i); 113 table->update(list, i);
109 } 114 }
110 115
111 UiTable::UiTable(winrt::Microsoft::UI::Xaml::Controls::ScrollViewer scrollW, winrt::Microsoft::UI::Xaml::Controls::Grid grid) { 116 UiTable::UiTable(UiObject *obj, winrt::Microsoft::UI::Xaml::Controls::ScrollViewer scrollW, winrt::Microsoft::UI::Xaml::Controls::Grid grid) {
117 this->obj = obj;
118
112 this->scrollw = scrollw; 119 this->scrollw = scrollw;
113 this->grid = grid; 120 this->grid = grid;
114 121
115 winrt::Windows::UI::Color highlightBg = { 255, 234, 234, 234 }; 122 winrt::Windows::UI::Color highlightBg = { 255, 234, 234, 234 };
116 highlightBrush = SolidColorBrush(highlightBg); 123 highlightBrush = SolidColorBrush(highlightBg);
194 wchar_t buf[16]; 201 wchar_t buf[16];
195 swprintf(buf, 16, L"%d", i); 202 swprintf(buf, 16, L"%d", i);
196 t.Text(winrt::hstring(buf)); 203 t.Text(winrt::hstring(buf));
197 } 204 }
198 205
206 static ULONG64 getsystime() {
207 SYSTEMTIME st;
208 GetSystemTime(&st);
209 return st.wYear * 10000000000000 +
210 st.wMonth * 100000000000 +
211 st.wDay * 1000000000 +
212 st.wHour * 10000000 +
213 st.wMinute * 100000 +
214 st.wSecond * 1000 +
215 st.wMilliseconds;
216 }
217
199 void UiTable::update(UiList* list, int i) { 218 void UiTable::update(UiList* list, int i) {
200 if (getvalue == nullptr) { 219 if (getvalue == nullptr) {
201 return; 220 return;
202 } 221 }
203 222
207 226
208 GridLength gl; 227 GridLength gl;
209 gl.Value = 0; 228 gl.Value = 0;
210 gl.GridUnitType = GridUnitType::Auto; 229 gl.GridUnitType = GridUnitType::Auto;
211 230
231 // iterate model
212 int row = 1; 232 int row = 1;
213 void* elm = list->first(list); 233 void* elm = list->first(list);
214 while (elm) { 234 while (elm) {
215 if (row >= maxrows) { 235 if (row >= maxrows) {
216 auto rowdef = RowDefinition(); 236 auto rowdef = RowDefinition();
219 maxrows = row; 239 maxrows = row;
220 } 240 }
221 241
222 Thickness cellpadding = { 10,0,4,0 }; 242 Thickness cellpadding = { 10,0,4,0 };
223 243
244 // model column, usually the same as col, however UI_ICON_TEXT uses two columns in the model
224 int model_col = 0; 245 int model_col = 0;
225 for (int col = 0; col < header.size(); col++, model_col++) { 246 for (int col = 0; col < header.size(); col++, model_col++) {
226 // create ui elements with the correct cell border 247 // create ui elements with the correct cell border
227 // dependeing on the column 248 // dependeing on the column
228 Border cellBorder = Border(); 249 Border cellBorder = Border();
229 cellBorder.Background(defaultBrush); 250 cellBorder.Background(defaultBrush);
251 cellBorder.BorderBrush(defaultBrush);
252 if (col == 0) {
253 cellBorder.BorderThickness(b1);
254 }
255 else if (col + 1 == header.size()) {
256 cellBorder.BorderThickness(b3);
257 }
258 else {
259 cellBorder.BorderThickness(b2);
260 }
230 261
231 // set the cell value 262 // set the cell value
263 // depending on the type, we create different cell controls
232 UiModelType type = model->types[col]; 264 UiModelType type = model->types[col];
233 switch (type) { 265 switch (type) {
234 case UI_STRING: { 266 case UI_STRING: {
235 TextBlock cell = TextBlock(); 267 TextBlock cell = TextBlock();
236 cell.Padding(cellpadding); 268 cell.Padding(cellpadding);
276 cellPanel.Children().Append(cell); 308 cellPanel.Children().Append(cell);
277 cellBorder.Child(cellPanel); 309 cellBorder.Child(cellPanel);
278 break; 310 break;
279 } 311 }
280 } 312 }
281
282 cellBorder.BorderBrush(defaultBrush);
283 if (col == 0) {
284 cellBorder.BorderThickness(b1);
285 }
286 else if (col + 1 == header.size()) {
287 cellBorder.BorderThickness(b3);
288 }
289 else {
290 cellBorder.BorderThickness(b2);
291 }
292 313
293 // event handler 314 // event handler
294 cellBorder.PointerPressed( 315 cellBorder.PointerPressed(
295 winrt::Microsoft::UI::Xaml::Input::PointerEventHandler( 316 winrt::Microsoft::UI::Xaml::Input::PointerEventHandler(
296 [=](IInspectable const& sender, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const& args) { 317 [=](IInspectable const& sender, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const& args) {
297 winrt::Windows::System::VirtualKeyModifiers modifiers = args.KeyModifiers(); 318 winrt::Windows::System::VirtualKeyModifiers modifiers = args.KeyModifiers();
319 bool update_selection = true;
298 320
299 if (modifiers == winrt::Windows::System::VirtualKeyModifiers::Control) { 321 if (modifiers == winrt::Windows::System::VirtualKeyModifiers::Control) {
300 // add/remove current row 322 // add/remove current row
301 if (!is_row_selected(row)) { 323 if (!is_row_selected(row)) {
302 row_background(row, selectedBrush, selectedBorderBrush); 324 row_background(row, selectedBrush, selectedBorderBrush);
313 change_rows_bg(selection, defaultBrush, defaultBrush); 335 change_rows_bg(selection, defaultBrush, defaultBrush);
314 } 336 }
315 337
316 row_background(row, selectedBrush, selectedBorderBrush); 338 row_background(row, selectedBrush, selectedBorderBrush);
317 selection = { row }; 339 selection = { row };
340 if (modifiers == winrt::Windows::System::VirtualKeyModifiers::None) {
341 SYSTEMTIME st;
342 GetSystemTime(&st);
343
344 ULONG64 now = getsystime();
345 ULONG64 tdiff = now - lastPointerPress;
346 if (tdiff < ui_double_click_time && onactivate != nullptr) {
347 // two pointer presse events in short time and we have an onactivate handler
348 update_selection = false; // we don't want an additional selection event
349 lastPointerPress = 0; // reset double-click
350
351 int selectedrow = row - 1; // subtract header row
352
353 UiListSelection selection;
354 selection.count = 1;
355 selection.rows = &selectedrow;
356
357 UiEvent evt;
358 evt.obj = obj;
359 evt.window = obj->window;
360 evt.document = obj->ctx->document;
361 evt.eventdata = &selection;
362 evt.intval = selectedrow;
363 onactivate(&evt, onactivatedata);
364 }
365 else {
366 lastPointerPress = now;
367 }
368 }
318 } 369 }
319 else if (modifiers == winrt::Windows::System::VirtualKeyModifiers::Shift) { 370 else if (modifiers == winrt::Windows::System::VirtualKeyModifiers::Shift) {
320 // select everything between the first selection and the current row 371 // select everything between the first selection and the current row
321 std::sort(selection.begin(), selection.end()); 372 std::sort(selection.begin(), selection.end());
322 int first = selection.front(); 373 int first = selection.front();
335 newselection.push_back(s); 386 newselection.push_back(s);
336 } 387 }
337 selection = newselection; 388 selection = newselection;
338 change_rows_bg(selection, selectedBrush, selectedBorderBrush); 389 change_rows_bg(selection, selectedBrush, selectedBorderBrush);
339 } 390 }
391
392 if (update_selection) {
393 call_handler(onselection, onselectiondata);
394 }
340 }) 395 })
341 ); 396 );
342 cellBorder.PointerReleased( 397 cellBorder.PointerReleased(
343 winrt::Microsoft::UI::Xaml::Input::PointerEventHandler( 398 winrt::Microsoft::UI::Xaml::Input::PointerEventHandler(
344 [=](IInspectable const& sender, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const& args) { 399 [=](IInspectable const& sender, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const& args) {
378 int child_row = grid.GetRow(elm); 433 int child_row = grid.GetRow(elm);
379 if (child_row > 0) { 434 if (child_row > 0) {
380 grid.Children().RemoveAt(i); 435 grid.Children().RemoveAt(i);
381 } 436 }
382 } 437 }
438
439 // TODO: should we clean row definitions?
383 } 440 }
384 441
385 void UiTable::row_background(int row, winrt::Microsoft::UI::Xaml::Media::Brush brush, winrt::Microsoft::UI::Xaml::Media::Brush borderBrush) { 442 void UiTable::row_background(int row, winrt::Microsoft::UI::Xaml::Media::Brush brush, winrt::Microsoft::UI::Xaml::Media::Brush borderBrush) {
386 Thickness b1 = { 1, 1, 0, 1 }; // first col 443 Thickness b1 = { 1, 1, 0, 1 }; // first col
387 Thickness b2 = { 0, 1, 0, 1 }; // middle 444 Thickness b2 = { 0, 1, 0, 1 }; // middle
408 465
409 void UiTable::remove_from_selection(int row) { 466 void UiTable::remove_from_selection(int row) {
410 selection.erase(std::remove(selection.begin(), selection.end(), row), selection.end()); 467 selection.erase(std::remove(selection.begin(), selection.end(), row), selection.end());
411 selection.shrink_to_fit(); 468 selection.shrink_to_fit();
412 } 469 }
470
471 void UiTable::call_handler(ui_callback cb, void* cbdata) {
472 if (!cb) {
473 return;
474 }
475
476 std::sort(selection.begin(), selection.end());
477
478 UiListSelection selobj;
479 selobj.count = selection.size();
480 selobj.rows = nullptr;
481 if (selobj.count > 0) {
482 selobj.rows = (int*)calloc(selobj.count, sizeof(int));
483 memcpy(selobj.rows, selection.data(), selobj.count * sizeof(int));
484 for (int i = 0; i < selobj.count; i++) {
485 selobj.rows[i]--;
486 }
487 }
488
489 UiEvent evt;
490 evt.obj = obj;
491 evt.window = obj->window;
492 evt.document = obj->ctx->document;
493 evt.eventdata = &selobj;
494 evt.intval = 0;
495 cb(&evt, cbdata);
496 }

mercurial