--- a/ui/winui/table.cpp Sat Oct 14 10:01:22 2023 +0200 +++ b/ui/winui/table.cpp Sat Oct 14 10:55:11 2023 +0200 @@ -51,6 +51,8 @@ using namespace winrt::Microsoft::UI::Xaml::Media; using namespace winrt::Windows::UI::Xaml::Input; +static UINT ui_double_click_time = GetDoubleClickTime(); + extern "C" void reg_table_destructor(UiContext * ctx, UiTable * table) { // TODO: } @@ -66,11 +68,14 @@ ScrollViewer scrollW = ScrollViewer(); Grid grid = Grid(); scrollW.Content(grid); - UiTable* uitable = new UiTable(scrollW, grid); + UiTable* uitable = new UiTable(obj, scrollW, grid); reg_table_destructor(current->ctx, uitable); - uitable->getvalue = args.model->getvalue ? args.model->getvalue : args.getvalue; + uitable->onselection = args.onselection; + uitable->onselectiondata = args.onselectiondata; + uitable->onactivate = args.onactivate; + uitable->onactivatedata = args.onactivatedata; // grid styling winrt::Windows::UI::Color bg = { 255, 255, 255, 255 }; // test color @@ -108,7 +113,9 @@ table->update(list, i); } -UiTable::UiTable(winrt::Microsoft::UI::Xaml::Controls::ScrollViewer scrollW, winrt::Microsoft::UI::Xaml::Controls::Grid grid) { +UiTable::UiTable(UiObject *obj, winrt::Microsoft::UI::Xaml::Controls::ScrollViewer scrollW, winrt::Microsoft::UI::Xaml::Controls::Grid grid) { + this->obj = obj; + this->scrollw = scrollw; this->grid = grid; @@ -196,6 +203,18 @@ t.Text(winrt::hstring(buf)); } +static ULONG64 getsystime() { + SYSTEMTIME st; + GetSystemTime(&st); + return st.wYear * 10000000000000 + + st.wMonth * 100000000000 + + st.wDay * 1000000000 + + st.wHour * 10000000 + + st.wMinute * 100000 + + st.wSecond * 1000 + + st.wMilliseconds; +} + void UiTable::update(UiList* list, int i) { if (getvalue == nullptr) { return; @@ -209,6 +228,7 @@ gl.Value = 0; gl.GridUnitType = GridUnitType::Auto; + // iterate model int row = 1; void* elm = list->first(list); while (elm) { @@ -221,14 +241,26 @@ Thickness cellpadding = { 10,0,4,0 }; + // model column, usually the same as col, however UI_ICON_TEXT uses two columns in the model 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); + cellBorder.BorderBrush(defaultBrush); + if (col == 0) { + cellBorder.BorderThickness(b1); + } + else if (col + 1 == header.size()) { + cellBorder.BorderThickness(b3); + } + else { + cellBorder.BorderThickness(b2); + } // set the cell value + // depending on the type, we create different cell controls UiModelType type = model->types[col]; switch (type) { case UI_STRING: { @@ -278,23 +310,13 @@ break; } } - - cellBorder.BorderBrush(defaultBrush); - if (col == 0) { - cellBorder.BorderThickness(b1); - } - else if (col + 1 == header.size()) { - cellBorder.BorderThickness(b3); - } - else { - cellBorder.BorderThickness(b2); - } // event handler cellBorder.PointerPressed( winrt::Microsoft::UI::Xaml::Input::PointerEventHandler( [=](IInspectable const& sender, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const& args) { winrt::Windows::System::VirtualKeyModifiers modifiers = args.KeyModifiers(); + bool update_selection = true; if (modifiers == winrt::Windows::System::VirtualKeyModifiers::Control) { // add/remove current row @@ -315,6 +337,35 @@ row_background(row, selectedBrush, selectedBorderBrush); selection = { row }; + if (modifiers == winrt::Windows::System::VirtualKeyModifiers::None) { + SYSTEMTIME st; + GetSystemTime(&st); + + ULONG64 now = getsystime(); + ULONG64 tdiff = now - lastPointerPress; + if (tdiff < ui_double_click_time && onactivate != nullptr) { + // two pointer presse events in short time and we have an onactivate handler + update_selection = false; // we don't want an additional selection event + lastPointerPress = 0; // reset double-click + + int selectedrow = row - 1; // subtract header row + + UiListSelection selection; + selection.count = 1; + selection.rows = &selectedrow; + + UiEvent evt; + evt.obj = obj; + evt.window = obj->window; + evt.document = obj->ctx->document; + evt.eventdata = &selection; + evt.intval = selectedrow; + onactivate(&evt, onactivatedata); + } + else { + lastPointerPress = now; + } + } } else if (modifiers == winrt::Windows::System::VirtualKeyModifiers::Shift) { // select everything between the first selection and the current row @@ -337,6 +388,10 @@ selection = newselection; change_rows_bg(selection, selectedBrush, selectedBorderBrush); } + + if (update_selection) { + call_handler(onselection, onselectiondata); + } }) ); cellBorder.PointerReleased( @@ -380,6 +435,8 @@ grid.Children().RemoveAt(i); } } + + // TODO: should we clean row definitions? } void UiTable::row_background(int row, winrt::Microsoft::UI::Xaml::Media::Brush brush, winrt::Microsoft::UI::Xaml::Media::Brush borderBrush) { @@ -410,3 +467,30 @@ selection.erase(std::remove(selection.begin(), selection.end(), row), selection.end()); selection.shrink_to_fit(); } + +void UiTable::call_handler(ui_callback cb, void* cbdata) { + if (!cb) { + return; + } + + std::sort(selection.begin(), selection.end()); + + UiListSelection selobj; + selobj.count = selection.size(); + selobj.rows = nullptr; + if (selobj.count > 0) { + selobj.rows = (int*)calloc(selobj.count, sizeof(int)); + memcpy(selobj.rows, selection.data(), selobj.count * sizeof(int)); + for (int i = 0; i < selobj.count; i++) { + selobj.rows[i]--; + } + } + + UiEvent evt; + evt.obj = obj; + evt.window = obj->window; + evt.document = obj->ctx->document; + evt.eventdata = &selobj; + evt.intval = 0; + cb(&evt, cbdata); +}