ui/winui/table.cpp

branch
newapi
changeset 218
d06e7e8e53e1
parent 216
391c2c723029
child 221
a82d9beaa94a
--- 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);
+}

mercurial