ui/winui/container.cpp

changeset 76
641dcc79e0ef
parent 75
73c8a3780c72
--- a/ui/winui/container.cpp	Sun Nov 10 09:12:30 2024 +0100
+++ b/ui/winui/container.cpp	Sun Nov 10 15:30:46 2024 +0100
@@ -1,30 +1,30 @@
 /*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2023 Olaf Wintermann. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *   1. Redistributions of source code must retain the above copyright
- *      notice, this list of conditions and the following disclaimer.
- *
- *   2. Redistributions in binary form must reproduce the above copyright
- *      notice, this list of conditions and the following disclaimer in the
- *      documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+*
+* Copyright 2023 Olaf Wintermann. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+*   1. Redistributions of source code must retain the above copyright
+*      notice, this list of conditions and the following disclaimer.
+*
+*   2. Redistributions in binary form must reproduce the above copyright
+*      notice, this list of conditions and the following disclaimer in the
+*      documentation and/or other materials provided with the distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*/
 
 #include "pch.h"
 
@@ -122,7 +122,7 @@
 		gl.Value = 0;
 		gl.GridUnitType = GridUnitType::Auto;
 	}
-	
+
 	control.HorizontalAlignment(HorizontalAlignment::Stretch);
 	control.VerticalAlignment(VerticalAlignment::Stretch);
 
@@ -179,13 +179,24 @@
 void UiGridContainer::Add(FrameworkElement control, UiBool fill) {
 	GridLength gl;
 
-	int hexpand = FALSE;
-	int vexpand = FALSE;
+	bool hexpand = false;
+	bool vexpand = false;
+	bool hfill = false;
+	bool vfill = false;
+	if(layout.fill != UI_LAYOUT_UNDEFINED) {
+		fill = ui_lb2bool(layout.fill);
+	}
 	if (layout.hexpand != UI_LAYOUT_UNDEFINED) {
 		hexpand = layout.hexpand;
+		hfill = true;
 	}
 	if (layout.vexpand != UI_LAYOUT_UNDEFINED) {
 		vexpand = layout.vexpand;
+		vfill = true;
+	}
+	if (fill) {
+		hfill = true;
+		vfill = true;
 	}
 
 	// create new RowDefinition for the new line
@@ -203,6 +214,11 @@
 		}
 		rowdef.Height(gl);
 		grid.RowDefinitions().Append(rowdef);
+	} else if (vexpand) {
+		// adjust row
+		gl.GridUnitType = GridUnitType::Star;
+		gl.Value = 1;
+		grid.RowDefinitions().GetAt(y).Height(gl);
 	}
 
 	// create new columndefinition, if a new column is added
@@ -219,11 +235,42 @@
 		coldef.Width(gl);
 		grid.ColumnDefinitions().Append(coldef);
 		cols++;
+	} else if(hexpand) {
+		// adjust column
+		if (layout.colspan == 0) {
+			gl.GridUnitType = GridUnitType::Star;
+			gl.Value = 1;
+			grid.ColumnDefinitions().GetAt(x).Width(gl);
+		} else {
+			int adjust_col = x;
+			bool adjust = true;
+			for (int i = 0; i < layout.colspan; i++) {
+				if (grid.ColumnDefinitions().Size() == x + i) {
+					break;
+				}
+				adjust_col = x + i;
+				GridLength w = grid.ColumnDefinitions().GetAt(adjust_col).Width();
+				if (w.GridUnitType == GridUnitType::Star) {
+					adjust = false;
+					break;
+				}
+			}
+
+			if (adjust) {
+				gl.GridUnitType = GridUnitType::Star;
+				gl.Value = 1;
+				grid.ColumnDefinitions().GetAt(adjust_col).Width(gl);
+			}
+		}
 	}
 
 	// add control
-	control.HorizontalAlignment(HorizontalAlignment::Stretch);
-	control.VerticalAlignment(VerticalAlignment::Stretch);
+	if (hfill) {
+		control.HorizontalAlignment(HorizontalAlignment::Stretch);
+	}
+	if (vfill) {
+		control.VerticalAlignment(VerticalAlignment::Stretch);
+	}
 
 	if (layout.colspan > 0) {
 		grid.SetColumnSpan(control, layout.colspan);
@@ -277,7 +324,7 @@
 		frame.SetColumn(label, 0);
 		frame.Children().Append(label);
 	}
-	
+
 	// workarea frame
 	frame.RowDefinitions().Append(rowdefFrame);
 
@@ -460,16 +507,24 @@
 	return newobj;
 }
 
+static UiTabView* tabview_pivot_create(UiObject* obj, UiTabViewArgs args) {
+	Pivot pivot = Pivot();
+	UiPivotTabView* tabview = new UiPivotTabView(obj, pivot, args);
+
+	return tabview;
+}
+
 UiPivotTabView::UiPivotTabView(UiObject* obj, Pivot pivot, UiTabViewArgs args) {
 	this->current = obj;
 	this->pivot = pivot;
+	this->subcontainer = args.subcontainer;
 	this->margin = args.margin;
 	this->spacing = args.spacing;
 	this->columnspacing = args.columnspacing;
 	this->rowspacing = args.rowspacing;
 }
 
-UiObject* UiPivotTabView::AddTab(const char* label) {
+UiObject* UiPivotTabView::AddTab(const char* label, int index) {
 	TextBlock text = TextBlock();
 	wchar_t* wlabel = str2wstr(label, nullptr);
 	winrt::hstring hstr(wlabel);
@@ -487,27 +542,110 @@
 	return create_subcontainer_obj(current, subcontainer, this->subcontainer, margin, spacing, columnspacing, rowspacing);
 }
 
+void UiPivotTabView::Remove(int index) {
+	pivot.Items().RemoveAt(index);
+}
+
+void UiPivotTabView::Select(int index) {
+	
+}
+
 FrameworkElement UiPivotTabView::GetFrameworkElement() {
 	return pivot;
 }
 
-static UiTabView* tabview_pivot_create(UiObject* obj, UiTabViewArgs args) {
-	Pivot pivot = Pivot();
-	UiPivotTabView* tabview = new UiPivotTabView(obj, pivot, args);
+
+static UiTabView* tabview_invisible_create(UiObject *obj, UiTabViewArgs args) {
+	Grid container = Grid();
+	container.HorizontalAlignment(HorizontalAlignment::Stretch);
+	container.VerticalAlignment(VerticalAlignment::Stretch);
+	UiInvisibleTabView *tabview = new UiInvisibleTabView(obj, container, args);
+	return tabview;
+}
+
+UiInvisibleTabView::UiInvisibleTabView(UiObject* obj, Grid container, UiTabViewArgs args) {
+	this->current = obj;
+	this->container = container;
+	this->subcontainer = args.subcontainer;
+	this->margin = args.margin;
+	this->spacing = args.spacing;
+	this->columnspacing = args.columnspacing;
+	this->rowspacing = args.rowspacing;
+	this->currentIndex = -1;
+
+	GridLength gl;
+	gl.GridUnitType = GridUnitType::Star;
+	gl.Value = 1;
+
+	ColumnDefinition coldef = ColumnDefinition();
+	coldef.Width(gl);
+	container.ColumnDefinitions().Append(coldef);
+
+	RowDefinition rowdef = RowDefinition();
+	rowdef.Height(gl);
+	container.RowDefinitions().Append(rowdef);
+}
 
-	return tabview;
+UiObject* UiInvisibleTabView::AddTab(const char* label, int index) {
+	Grid subcontainer = Grid();
+	subcontainer.HorizontalAlignment(HorizontalAlignment::Stretch);
+	subcontainer.VerticalAlignment(VerticalAlignment::Stretch);
+	
+	if (pages.size() == 0) {
+		container.Children().Append(subcontainer);
+		currentIndex = 0;
+	}
+
+	if (index < 0) {
+		pages.push_back(subcontainer);
+	} else {
+		pages.insert(pages.begin() + index, subcontainer);
+	}
+
+	// sub container
+	return create_subcontainer_obj(current, subcontainer, this->subcontainer, margin, spacing, columnspacing, rowspacing);
+}
+
+void UiInvisibleTabView::Remove(int index) {
+	
+}
+
+void UiInvisibleTabView::Select(int index) {
+	if (index >= 0 && index < pages.size()) {
+		if (currentIndex != -1) {
+			container.Children().RemoveAt(0);
+		}
+		
+		container.Children().Append(pages.at(index));
+	}
+}
+
+FrameworkElement UiInvisibleTabView::GetFrameworkElement() {
+	return container;
+}
+
+
+static UiTabView* tabview_main_create(UiObject* obj, UiTabViewArgs args) {
+	TabView tabview = TabView();
+	tabview.IsAddTabButtonVisible(false);
+	//tabview.CanDragTabs(false);
+	//tabview.CanReorderTabs(false);
+	UiMainTabView* uitabview = new UiMainTabView(obj, tabview, args);
+
+	return uitabview;
 }
 
 UiMainTabView::UiMainTabView(UiObject* obj, TabView tabview, UiTabViewArgs args) {
 	this->current = obj;
 	this->tabview = tabview;
+	this->subcontainer = args.subcontainer;
 	this->margin = args.margin;
 	this->spacing = args.spacing;
 	this->columnspacing = args.columnspacing;
 	this->rowspacing = args.rowspacing;
 }
 
-UiObject* UiMainTabView::AddTab(const char* label) {
+UiObject* UiMainTabView::AddTab(const char* label, int index) {
 	TextBlock text = TextBlock();
 	wchar_t* wlabel = str2wstr(label, nullptr);
 	winrt::hstring hstr(wlabel);
@@ -527,18 +665,26 @@
 	return create_subcontainer_obj(current, subcontainer, this->subcontainer, margin, spacing, columnspacing, rowspacing);
 }
 
+void UiMainTabView::Remove(int index) {
+	this->tabview.TabItems().RemoveAt(index);
+}
+
+void UiMainTabView::Select(int index) {
+
+}
+
 FrameworkElement UiMainTabView::GetFrameworkElement() {
 	return tabview;
 }
 
-static UiTabView* tabview_main_create(UiObject* obj, UiTabViewArgs args) {
-	TabView tabview = TabView();
-	tabview.IsAddTabButtonVisible(false);
-	//tabview.CanDragTabs(false);
-	//tabview.CanReorderTabs(false);
-	UiMainTabView* uitabview = new UiMainTabView(obj, tabview, args);
 
-	return uitabview;
+static UiTabView* tabview_navigationview_create(UiObject* obj, UiTabViewArgs args, UiTabViewType type) {
+	NavigationView navigationview = NavigationView();
+	UiNavigationTabView* tabview = new UiNavigationTabView(obj, navigationview, args, type);
+	navigationview.IsBackButtonVisible(NavigationViewBackButtonVisible::Collapsed);
+	navigationview.IsSettingsVisible(false);
+
+	return tabview;
 }
 
 UiNavigationTabView::UiNavigationTabView(UiObject* obj, NavigationView navigationview, UiTabViewArgs args, UiTabViewType type) {
@@ -557,7 +703,7 @@
 	navigationview.SelectionChanged({ this, &UiNavigationTabView::SelectionChanged });
 }
 
-UiObject* UiNavigationTabView::AddTab(const char* label) {
+UiObject* UiNavigationTabView::AddTab(const char* label, int index1) {
 	TextBlock text = TextBlock();
 	wchar_t* wlabel = str2wstr(label, nullptr);
 	winrt::hstring hstr(wlabel);
@@ -581,6 +727,15 @@
 	return create_subcontainer_obj(current, subcontainer, this->subcontainer, margin, spacing, columnspacing, rowspacing);
 }
 
+void UiNavigationTabView::Remove(int index) {
+	navigationview.MenuItems().RemoveAt(index);
+	pages.erase(pages.begin() + index);
+}
+
+void UiNavigationTabView::Select(int index) {
+
+}
+
 FrameworkElement UiNavigationTabView::GetFrameworkElement() {
 	return navigationview;
 }
@@ -596,13 +751,13 @@
 	}
 }
 
-static UiTabView* tabview_navigationview_create(UiObject* obj, UiTabViewArgs args, UiTabViewType type) {
-	NavigationView navigationview = NavigationView();
-	UiNavigationTabView* tabview = new UiNavigationTabView(obj, navigationview, args, type);
-	navigationview.IsBackButtonVisible(NavigationViewBackButtonVisible::Collapsed);
-	navigationview.IsSettingsVisible(false);
+static int64_t ui_tabview_get(UiInteger *i) {
+	return 0;
+}
 
-	return tabview;
+static void ui_tabview_set(UiInteger *i, int64_t value) {
+	UiTabView *tabview = (UiTabView*)i->obj;
+	tabview->Select(value);
 }
 
 UIWIDGET ui_tabview_create(UiObject* obj, UiTabViewArgs args) {
@@ -629,6 +784,10 @@
 			tabview = tabview_pivot_create(obj, args);
 			break;
 		}
+		case UI_TABVIEW_INVISIBLE: {
+			tabview = tabview_invisible_create(obj, args);
+			break;
+		}
 	}
 	UiTabViewContainer* ctn = new UiTabViewContainer(tabview);
 
@@ -642,6 +801,17 @@
 	ui_context_add_widget_destructor(current->ctx, widget);
 	widget->data1 = tabview;
 
+	// TODO: add tabview destructor
+
+	// bind variable
+	UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_INTEGER);
+	if (var) {
+		UiInteger *i = (UiInteger*)var->value;
+		i->obj = tabview;
+		i->get = ui_tabview_get;
+		i->set = ui_tabview_set;
+	}
+
 	UiObject* newobj = uic_object_new(obj, widget);
 	newobj->container = ctn;
 	uic_obj_add(obj, newobj);
@@ -656,12 +826,59 @@
 	uic_obj_add(current, newobj);
 }
 
+UIEXPORT void ui_tabview_select(UIWIDGET tabview, int tab) {
+	UiTabView* t = (UiTabView*)tabview->data1;
+	t->Select(tab);
+}
+
+UIEXPORT void ui_tabview_remove(UIWIDGET tabview, int tab) {
+	UiTabView* t = (UiTabView*)tabview->data1;
+	t->Remove(tab);
+}
+
+UIEXPORT UiObject* ui_tabview_add(UIWIDGET tabview, const char *name, int tab_index) {
+	UiTabView* t = (UiTabView*)tabview->data1;
+	UiObject* newobj = t->AddTab(name, tab_index);
+	return newobj;
+}
+
+
+
+// --------------------- UI Headerbar ---------------------
+
+// TODO: replace placeholder implementation
+
+UIEXPORT UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs args) {
+	UiContainerArgs boxargs = { };
+	boxargs.fill = UI_OFF;
+	return ui_hbox_create(obj, boxargs);
+}
+
+UIEXPORT void ui_headerbar_start_create(UiObject *obj) {
+	UiContainerArgs boxargs = { };
+	boxargs.fill = UI_OFF;
+	ui_hbox_create(obj, boxargs);
+}
+
+UIEXPORT void ui_headerbar_center_create(UiObject *obj) {
+	UiContainerArgs boxargs = { };
+	boxargs.fill = UI_OFF;
+	ui_hbox_create(obj, boxargs);
+}
+
+UIEXPORT void ui_headerbar_end_create(UiObject *obj) {
+	UiContainerArgs boxargs = { };
+	boxargs.fill = UI_OFF;
+	ui_hbox_create(obj, boxargs);
+}
+
+
 /*
- * -------------------- Layout Functions --------------------
- *
- * functions for setting layout attributes for the current container
- *
- */
+* -------------------- Layout Functions --------------------
+*
+* functions for setting layout attributes for the current container
+*
+*/
 
 void ui_layout_fill(UiObject* obj, UiBool fill) {
 	UiContainer* ct = uic_get_current_container(obj);
@@ -678,14 +895,14 @@
 	ct->layout.vexpand = expand;
 }
 
-void ui_layout_hfill(UiObject *obj, UiBool fill) {
-    UiContainer *ct = uic_get_current_container(obj);
-    ct->layout.hfill = fill;
+void ui_layout_hfill(UiObject* obj, UiBool fill) {
+	UiContainer* ct = uic_get_current_container(obj);
+	ct->layout.hfill = fill;
 }
 
-void ui_layout_vfill(UiObject *obj, UiBool fill) {
-    UiContainer *ct = uic_get_current_container(obj);
-    ct->layout.vfill = fill;
+void ui_layout_vfill(UiObject* obj, UiBool fill) {
+	UiContainer* ct = uic_get_current_container(obj);
+	ct->layout.vfill = fill;
 }
 
 void ui_layout_width(UiObject* obj, int width) {

mercurial