UNIXworkcode

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 "pch.h" 30 31 #include "container.h" 32 33 #include "../common/context.h" 34 #include "../common/object.h" 35 36 #include "util.h" 37 #include "../ui/widget.h" 38 39 40 void ui_container_begin_close(UiObject* obj) { 41 UiContainer* ct = uic_get_current_container(obj); 42 ct->close = 1; 43 } 44 45 int ui_container_finish(UiObject* obj) { 46 UiContainer* ct = uic_get_current_container(obj); 47 if (ct->close) { 48 ui_end(obj); 49 return 0; 50 } 51 return 1; 52 } 53 54 55 UIWIDGET ui_customwidget_create(UiObject *obj, ui_createwidget_func create_widget, void *userdata, UiWidgetArgs *args) { 56 UiObject* current = uic_current_obj(obj); 57 58 UIWIDGET widget = create_widget(obj, args, userdata); 59 FrameworkElement w = widget->uielement.as<FrameworkElement>(); 60 61 UI_APPLY_LAYOUT2(current, args); 62 63 current->container->Add(w, false); 64 65 return widget; 66 } 67 68 // --------------------- UiBoxContainer --------------------- 69 70 static UIWIDGET ui_box(UiObject* obj, UiContainerArgs *args, UiBoxContainerType type) { 71 UiObject* current = uic_current_obj(obj); 72 UI_APPLY_LAYOUT2(current, args); 73 74 Grid grid = Grid(); 75 current->container->Add(grid, true); 76 77 UIElement elm = grid; 78 UiWidget* widget = new UiWidget(elm); 79 ui_context_add_widget_destructor(current->ctx, widget); 80 81 UiObject* newobj = uic_object_new(obj, widget); 82 newobj->container = new UiBoxContainer(grid, type, args->margin, args->spacing); 83 ui_context_add_container_destructor(current->ctx, newobj->container); 84 uic_obj_add(obj, newobj); 85 86 return widget; 87 } 88 89 UIWIDGET ui_vbox_create(UiObject* obj, UiContainerArgs *args) { 90 return ui_box(obj, args, UI_BOX_CONTAINER_VBOX); 91 } 92 93 UIWIDGET ui_hbox_create(UiObject* obj, UiContainerArgs *args) { 94 return ui_box(obj, args, UI_BOX_CONTAINER_HBOX); 95 } 96 97 UiBoxContainer::UiBoxContainer(Grid grid, enum UiBoxContainerType type, int margin, int spacing) { 98 this->grid = grid; 99 this->type = type; 100 101 Thickness t = { (double)margin, (double)margin, (double)margin, (double)margin }; 102 grid.Margin(t); 103 grid.ColumnSpacing((double)spacing); 104 grid.RowSpacing((double)spacing); 105 106 GridLength gl; 107 gl.Value = 1; 108 gl.GridUnitType = GridUnitType::Star; 109 110 // hbox needs one row def, vbox needs one col def 111 // all other col/row defs are created when elements are added 112 if (type == UI_BOX_CONTAINER_HBOX) { 113 boxRowDef = RowDefinition(); 114 boxRowDef.Height(gl); 115 grid.RowDefinitions().Append(boxRowDef); 116 } else { 117 boxColDef = ColumnDefinition(); 118 boxColDef.Width(gl); 119 grid.ColumnDefinitions().Append(boxColDef); 120 } 121 122 ui_reset_layout(layout); 123 } 124 125 void UiBoxContainer::Add(FrameworkElement control, UiBool fill) { 126 if (this->layout.fill != UI_LAYOUT_UNDEFINED) { 127 fill = ui_lb2bool(this->layout.fill); 128 } 129 130 GridLength gl; 131 if (fill) { 132 gl.Value = 1; 133 gl.GridUnitType = GridUnitType::Star; 134 } 135 else { 136 gl.Value = 0; 137 gl.GridUnitType = GridUnitType::Auto; 138 } 139 140 control.HorizontalAlignment(HorizontalAlignment::Stretch); 141 control.VerticalAlignment(VerticalAlignment::Stretch); 142 143 if (type == UI_CONTAINER_HBOX) { 144 ColumnDefinition coldef = ColumnDefinition(); 145 coldef.Width(gl); 146 grid.ColumnDefinitions().Append(coldef); 147 grid.SetColumn(control, grid.Children().Size()); 148 grid.SetRow(control, 0); 149 } else { 150 RowDefinition rowdef = RowDefinition(); 151 rowdef.Height(gl); 152 grid.RowDefinitions().Append(rowdef); 153 grid.SetRow(control, grid.Children().Size()); 154 grid.SetColumn(control, 0); 155 } 156 157 grid.Children().Append(control); 158 159 ui_reset_layout(layout); 160 } 161 162 163 // --------------------- UiGridContainer --------------------- 164 165 UIWIDGET ui_grid_create(UiObject* obj, UiContainerArgs *args) { 166 UiObject* current = uic_current_obj(obj); 167 UI_APPLY_LAYOUT2(current, args); 168 169 Grid grid = Grid(); 170 current->container->Add(grid, true); 171 172 UIElement elm = grid; 173 UiWidget* widget = new UiWidget(elm); 174 ui_context_add_widget_destructor(current->ctx, widget); 175 176 UiObject* newobj = uic_object_new(obj, widget); 177 newobj->container = new UiGridContainer(grid, args->margin, args->columnspacing, args->rowspacing); 178 ui_context_add_container_destructor(current->ctx, newobj->container); 179 uic_obj_add(obj, newobj); 180 181 return widget; 182 } 183 184 UiGridContainer::UiGridContainer(Grid grid, int margin, int columnspacing, int rowspacing) { 185 this->grid = grid; 186 Thickness t = { (double)margin, (double)margin, (double)margin, (double)margin }; 187 grid.Margin(t); 188 grid.ColumnSpacing((double)columnspacing); 189 grid.RowSpacing((double)rowspacing); 190 ui_reset_layout(layout); 191 } 192 193 void UiGridContainer::Add(FrameworkElement control, UiBool fill) { 194 GridLength gl; 195 196 bool hexpand = false; 197 bool vexpand = false; 198 bool hfill = false; 199 bool vfill = false; 200 if(layout.fill != UI_LAYOUT_UNDEFINED) { 201 fill = ui_lb2bool(layout.fill); 202 } 203 if (layout.hexpand != UI_LAYOUT_UNDEFINED) { 204 hexpand = layout.hexpand; 205 hfill = true; 206 } 207 if (layout.vexpand != UI_LAYOUT_UNDEFINED) { 208 vexpand = layout.vexpand; 209 vfill = true; 210 } 211 if (fill) { 212 hfill = true; 213 vfill = true; 214 } 215 216 // create new RowDefinition for the new line 217 if (layout.newline || y == -1) { 218 x = 0; 219 y++; 220 RowDefinition rowdef = RowDefinition(); 221 if (vexpand) { 222 gl.GridUnitType = GridUnitType::Star; 223 gl.Value = 1; 224 } 225 else { 226 gl.GridUnitType = GridUnitType::Auto; 227 gl.Value = 0; 228 } 229 rowdef.Height(gl); 230 grid.RowDefinitions().Append(rowdef); 231 } else if (vexpand) { 232 // adjust row 233 gl.GridUnitType = GridUnitType::Star; 234 gl.Value = 1; 235 grid.RowDefinitions().GetAt(y).Height(gl); 236 } 237 238 // create new columndefinition, if a new column is added 239 if (x == cols) { 240 if (hexpand) { 241 gl.GridUnitType = GridUnitType::Star; 242 gl.Value = 1; 243 } 244 else { 245 gl.GridUnitType = GridUnitType::Auto; 246 gl.Value = 0; 247 } 248 ColumnDefinition coldef = ColumnDefinition(); 249 coldef.Width(gl); 250 grid.ColumnDefinitions().Append(coldef); 251 cols++; 252 } else if(hexpand) { 253 // adjust column 254 if (layout.colspan == 0) { 255 gl.GridUnitType = GridUnitType::Star; 256 gl.Value = 1; 257 grid.ColumnDefinitions().GetAt(x).Width(gl); 258 } else { 259 int adjust_col = x; 260 bool adjust = true; 261 for (int i = 0; i < layout.colspan; i++) { 262 if (grid.ColumnDefinitions().Size() == x + i) { 263 break; 264 } 265 adjust_col = x + i; 266 GridLength w = grid.ColumnDefinitions().GetAt(adjust_col).Width(); 267 if (w.GridUnitType == GridUnitType::Star) { 268 adjust = false; 269 break; 270 } 271 } 272 273 if (adjust) { 274 gl.GridUnitType = GridUnitType::Star; 275 gl.Value = 1; 276 grid.ColumnDefinitions().GetAt(adjust_col).Width(gl); 277 } 278 } 279 } 280 281 // add control 282 if (hfill) { 283 control.HorizontalAlignment(HorizontalAlignment::Stretch); 284 } 285 if (vfill) { 286 control.VerticalAlignment(VerticalAlignment::Stretch); 287 } 288 289 if (layout.colspan > 0) { 290 grid.SetColumnSpan(control, layout.colspan); 291 } 292 if (layout.rowspan > 0) { 293 grid.SetRowSpan(control, layout.rowspan); 294 } 295 296 grid.SetRow(control, y); 297 grid.SetColumn(control, x); 298 grid.Children().Append(control); 299 300 x++; 301 302 ui_reset_layout(layout); 303 } 304 305 // --------------------- UI Frame --------------------- 306 307 UIWIDGET ui_frame_create(UiObject* obj, UiFrameArgs *args) { 308 // create a grid for the frame, that contains the label and a sub-frame 309 Grid frame = Grid(); 310 311 GridLength gl; 312 gl.GridUnitType = GridUnitType::Star; 313 gl.Value = 1; 314 315 ColumnDefinition coldef = ColumnDefinition(); 316 coldef.Width(gl); 317 frame.ColumnDefinitions().Append(coldef); 318 319 RowDefinition rowdefFrame = RowDefinition(); 320 rowdefFrame.Height(gl); 321 322 // label 323 int row = 0; 324 if (args->label) { 325 RowDefinition rowdefLabel = RowDefinition(); 326 gl.GridUnitType = GridUnitType::Auto; 327 gl.Value = 0; 328 rowdefLabel.Height(gl); 329 frame.RowDefinitions().Append(rowdefLabel); 330 331 TextBlock label = TextBlock(); 332 wchar_t* wlabel = str2wstr(args->label, nullptr); 333 winrt::hstring hstr(wlabel); 334 label.Text(hstr); 335 free(wlabel); 336 337 frame.SetRow(label, row++); 338 frame.SetColumn(label, 0); 339 frame.Children().Append(label); 340 } 341 342 // workarea frame 343 frame.RowDefinitions().Append(rowdefFrame); 344 345 Grid workarea = Grid(); 346 frame.SetRow(workarea, row); 347 frame.SetColumn(workarea, 0); 348 frame.Children().Append(workarea); 349 350 // some styling for the workarea 351 winrt::Microsoft::UI::Xaml::Media::SolidColorBrush brush{ winrt::Microsoft::UI::ColorHelper::FromArgb(150, 150, 150, 150) }; 352 workarea.BorderBrush(brush); 353 CornerRadius radius{ 8, 8, 8, 8 }; 354 Thickness t = { 1, 1, 1, 1 }; 355 workarea.CornerRadius(radius); 356 workarea.BorderThickness(t); 357 358 Thickness padding = { 10, 10, 10, 10 }; 359 workarea.Padding(padding); 360 361 // add frame to the parent container 362 UiObject* current = uic_current_obj(obj); 363 UI_APPLY_LAYOUT2(current, args); 364 current->container->Add(frame, true); 365 366 UIElement elm = frame; 367 UiWidget* widget = new UiWidget(elm); 368 ui_context_add_widget_destructor(current->ctx, widget); 369 370 // sub container 371 UiContainer* ctn = nullptr; 372 switch (args->subcontainer) { 373 default: 374 case UI_CONTAINER_VBOX: { 375 ctn = new UiBoxContainer(workarea, UI_BOX_CONTAINER_VBOX, args->margin, args->spacing); 376 break; 377 } 378 case UI_CONTAINER_HBOX: { 379 ctn = new UiBoxContainer(workarea, UI_BOX_CONTAINER_HBOX, args->margin, args->spacing); 380 break; 381 } 382 case UI_CONTAINER_GRID: { 383 ctn = new UiGridContainer(workarea, args->margin, args->columnspacing, args->rowspacing); 384 break; 385 } 386 } 387 ui_context_add_container_destructor(current->ctx, ctn); 388 389 UiObject* newobj = uic_object_new(obj, widget); 390 newobj->container = ctn; 391 uic_obj_add(obj, newobj); 392 393 return widget; 394 } 395 396 // --------------------- UI Expander --------------------- 397 398 UIWIDGET ui_expander_create(UiObject* obj, UiFrameArgs *args) { 399 Expander expander = Expander(); 400 if (args->label) { 401 wchar_t* wlabel = str2wstr(args->label, nullptr); 402 expander.Header(box_value(wlabel)); 403 free(wlabel); 404 } 405 expander.IsExpanded(args->isexpanded); 406 407 // add frame to the parent container 408 UiObject* current = uic_current_obj(obj); 409 UI_APPLY_LAYOUT2(current, args); 410 current->container->Add(expander, true); 411 412 UIElement elm = expander; 413 UiWidget* widget = new UiWidget(elm); 414 ui_context_add_widget_destructor(current->ctx, widget); 415 416 Grid content = Grid(); 417 expander.Content(content); 418 419 UiContainer* ctn = nullptr; 420 switch (args->subcontainer) { 421 default: 422 case UI_CONTAINER_VBOX: { 423 ctn = new UiBoxContainer(content, UI_BOX_CONTAINER_VBOX, args->margin, args->spacing); 424 break; 425 } 426 case UI_CONTAINER_HBOX: { 427 ctn = new UiBoxContainer(content, UI_BOX_CONTAINER_HBOX, args->margin, args->spacing); 428 break; 429 } 430 case UI_CONTAINER_GRID: { 431 ctn = new UiGridContainer(content, args->margin, args->columnspacing, args->rowspacing); 432 break; 433 } 434 } 435 ui_context_add_container_destructor(current->ctx, ctn); 436 437 UiObject* newobj = uic_object_new(obj, widget); 438 newobj->container = ctn; 439 uic_obj_add(obj, newobj); 440 441 return widget; 442 } 443 444 // --------------------- UI ScrolledWindow --------------------- 445 446 UIWIDGET ui_scrolledwindow_create(UiObject* obj, UiFrameArgs *args) { 447 ScrollViewer scrollW = ScrollViewer(); 448 449 // add frame to the parent container 450 UiObject* current = uic_current_obj(obj); 451 UI_APPLY_LAYOUT2(current, args); 452 current->container->Add(scrollW, true); 453 454 UIElement elm = scrollW; 455 UiWidget* widget = new UiWidget(elm); 456 ui_context_add_widget_destructor(current->ctx, widget); 457 458 // create child container 459 Grid content = Grid(); 460 scrollW.Content(content); 461 462 UiContainer* ctn = nullptr; 463 switch (args->subcontainer) { 464 default: 465 case UI_CONTAINER_VBOX: { 466 ctn = new UiBoxContainer(content, UI_BOX_CONTAINER_VBOX, args->margin, args->spacing); 467 break; 468 } 469 case UI_CONTAINER_HBOX: { 470 ctn = new UiBoxContainer(content, UI_BOX_CONTAINER_HBOX, args->margin, args->spacing); 471 break; 472 } 473 case UI_CONTAINER_GRID: { 474 ctn = new UiGridContainer(content, args->margin, args->columnspacing, args->rowspacing); 475 break; 476 } 477 } 478 ui_context_add_container_destructor(current->ctx, ctn); 479 480 UiObject* newobj = uic_object_new(obj, widget); 481 newobj->container = ctn; 482 uic_obj_add(obj, newobj); 483 484 return widget; 485 } 486 487 // --------------------- UI TabView --------------------- 488 489 UiTabViewContainer::UiTabViewContainer(UiTabView* tabview) { 490 this->tabview = tabview; 491 } 492 493 void UiTabViewContainer::Add(FrameworkElement control, UiBool fill) { 494 // noop 495 } 496 497 static UiObject* create_subcontainer_obj(UiObject* current, Grid subcontainer, UiSubContainerType type, int margin, int spacing, int columnspacing, int rowspacing) { 498 UiContainer* ctn = nullptr; 499 switch (type) { 500 default: 501 case UI_CONTAINER_VBOX: { 502 ctn = new UiBoxContainer(subcontainer, UI_BOX_CONTAINER_VBOX, margin, spacing); 503 break; 504 } 505 case UI_CONTAINER_HBOX: { 506 ctn = new UiBoxContainer(subcontainer, UI_BOX_CONTAINER_HBOX, margin, spacing); 507 break; 508 } 509 case UI_CONTAINER_GRID: { 510 ctn = new UiGridContainer(subcontainer, margin, columnspacing, rowspacing); 511 break; 512 } 513 } 514 ui_context_add_container_destructor(current->ctx, ctn); 515 516 UIElement elm = subcontainer; 517 UiWidget* widget = new UiWidget(elm); 518 ui_context_add_widget_destructor(current->ctx, widget); 519 UiObject* newobj = uic_object_new(current, widget); 520 newobj->container = ctn; 521 return newobj; 522 } 523 524 static UiTabView* tabview_pivot_create(UiObject* obj, UiTabViewArgs *args) { 525 Pivot pivot = Pivot(); 526 UiPivotTabView* tabview = new UiPivotTabView(obj, pivot, args); 527 528 return tabview; 529 } 530 531 UiPivotTabView::UiPivotTabView(UiObject* obj, Pivot pivot, UiTabViewArgs *args) { 532 this->current = obj; 533 this->pivot = pivot; 534 this->subcontainer = args->subcontainer; 535 this->margin = args->margin; 536 this->spacing = args->spacing; 537 this->columnspacing = args->columnspacing; 538 this->rowspacing = args->rowspacing; 539 } 540 541 UiObject* UiPivotTabView::AddTab(const char* label, int index) { 542 TextBlock text = TextBlock(); 543 wchar_t* wlabel = str2wstr(label, nullptr); 544 winrt::hstring hstr(wlabel); 545 text.Text(hstr); 546 free(wlabel); 547 548 PivotItem item = PivotItem(); 549 item.Header(text); 550 551 // sub container 552 Grid subcontainer = Grid(); 553 item.Content(subcontainer); 554 pivot.Items().Append(item); 555 556 return create_subcontainer_obj(current, subcontainer, this->subcontainer, margin, spacing, columnspacing, rowspacing); 557 } 558 559 void UiPivotTabView::Remove(int index) { 560 pivot.Items().RemoveAt(index); 561 } 562 563 void UiPivotTabView::Select(int index) { 564 565 } 566 567 FrameworkElement UiPivotTabView::GetFrameworkElement() { 568 return pivot; 569 } 570 571 572 static UiTabView* tabview_invisible_create(UiObject *obj, UiTabViewArgs *args) { 573 Grid container = Grid(); 574 container.HorizontalAlignment(HorizontalAlignment::Stretch); 575 container.VerticalAlignment(VerticalAlignment::Stretch); 576 UiInvisibleTabView *tabview = new UiInvisibleTabView(obj, container, args); 577 return tabview; 578 } 579 580 UiInvisibleTabView::UiInvisibleTabView(UiObject* obj, Grid container, UiTabViewArgs *args) { 581 this->current = obj; 582 this->container = container; 583 this->subcontainer = args->subcontainer; 584 this->margin = args->margin; 585 this->spacing = args->spacing; 586 this->columnspacing = args->columnspacing; 587 this->rowspacing = args->rowspacing; 588 this->currentIndex = -1; 589 590 GridLength gl; 591 gl.GridUnitType = GridUnitType::Star; 592 gl.Value = 1; 593 594 ColumnDefinition coldef = ColumnDefinition(); 595 coldef.Width(gl); 596 container.ColumnDefinitions().Append(coldef); 597 598 RowDefinition rowdef = RowDefinition(); 599 rowdef.Height(gl); 600 container.RowDefinitions().Append(rowdef); 601 } 602 603 UiObject* UiInvisibleTabView::AddTab(const char* label, int index) { 604 Grid subcontainer = Grid(); 605 subcontainer.HorizontalAlignment(HorizontalAlignment::Stretch); 606 subcontainer.VerticalAlignment(VerticalAlignment::Stretch); 607 608 if (pages.size() == 0) { 609 container.Children().Append(subcontainer); 610 currentIndex = 0; 611 } 612 613 if (index < 0) { 614 pages.push_back(subcontainer); 615 } else { 616 pages.insert(pages.begin() + index, subcontainer); 617 } 618 619 // sub container 620 return create_subcontainer_obj(current, subcontainer, this->subcontainer, margin, spacing, columnspacing, rowspacing); 621 } 622 623 void UiInvisibleTabView::Remove(int index) { 624 625 } 626 627 void UiInvisibleTabView::Select(int index) { 628 if (index >= 0 && index < pages.size()) { 629 if (currentIndex != -1) { 630 container.Children().RemoveAt(0); 631 } 632 633 container.Children().Append(pages.at(index)); 634 } 635 } 636 637 FrameworkElement UiInvisibleTabView::GetFrameworkElement() { 638 return container; 639 } 640 641 642 static UiTabView* tabview_main_create(UiObject* obj, UiTabViewArgs *args) { 643 TabView tabview = TabView(); 644 tabview.IsAddTabButtonVisible(false); 645 //tabview.CanDragTabs(false); 646 //tabview.CanReorderTabs(false); 647 UiMainTabView* uitabview = new UiMainTabView(obj, tabview, args); 648 649 return uitabview; 650 } 651 652 UiMainTabView::UiMainTabView(UiObject* obj, TabView tabview, UiTabViewArgs *args) { 653 this->current = obj; 654 this->tabview = tabview; 655 this->subcontainer = args->subcontainer; 656 this->margin = args->margin; 657 this->spacing = args->spacing; 658 this->columnspacing = args->columnspacing; 659 this->rowspacing = args->rowspacing; 660 } 661 662 UiObject* UiMainTabView::AddTab(const char* label, int index) { 663 TextBlock text = TextBlock(); 664 wchar_t* wlabel = str2wstr(label, nullptr); 665 winrt::hstring hstr(wlabel); 666 text.Text(hstr); 667 free(wlabel); 668 669 TabViewItem item = TabViewItem(); 670 item.Header(text); 671 item.CanDrag(false); 672 item.IsClosable(false); 673 674 // sub container 675 Grid subcontainer = Grid(); 676 item.Content(subcontainer); 677 tabview.TabItems().Append(item); 678 679 return create_subcontainer_obj(current, subcontainer, this->subcontainer, margin, spacing, columnspacing, rowspacing); 680 } 681 682 void UiMainTabView::Remove(int index) { 683 this->tabview.TabItems().RemoveAt(index); 684 } 685 686 void UiMainTabView::Select(int index) { 687 688 } 689 690 FrameworkElement UiMainTabView::GetFrameworkElement() { 691 return tabview; 692 } 693 694 695 static UiTabView* tabview_navigationview_create(UiObject* obj, UiTabViewArgs *args, UiTabViewType type) { 696 NavigationView navigationview = NavigationView(); 697 UiNavigationTabView* tabview = new UiNavigationTabView(obj, navigationview, args, type); 698 navigationview.IsBackButtonVisible(NavigationViewBackButtonVisible::Collapsed); 699 navigationview.IsSettingsVisible(false); 700 701 return tabview; 702 } 703 704 UiNavigationTabView::UiNavigationTabView(UiObject* obj, NavigationView navigationview, UiTabViewArgs *args, UiTabViewType type) { 705 this->current = obj; 706 this->navigationview = navigationview; 707 this->type = type; 708 this->margin = args->margin; 709 this->spacing = args->spacing; 710 this->columnspacing = args->columnspacing; 711 this->rowspacing = args->rowspacing; 712 713 if (type == UI_TABVIEW_NAVIGATION_TOP) { 714 navigationview.PaneDisplayMode(NavigationViewPaneDisplayMode::Top); 715 } 716 717 navigationview.SelectionChanged({ this, &UiNavigationTabView::SelectionChanged }); 718 } 719 720 UiObject* UiNavigationTabView::AddTab(const char* label, int index1) { 721 TextBlock text = TextBlock(); 722 wchar_t* wlabel = str2wstr(label, nullptr); 723 winrt::hstring hstr(wlabel); 724 text.Text(hstr); 725 free(wlabel); 726 727 NavigationViewItem item = NavigationViewItem(); 728 item.Content(text); 729 730 // sub container 731 Grid subcontainer = Grid(); 732 if (pages.size() == 0) { 733 navigationview.Content(subcontainer); 734 navigationview.SelectedItem(item); 735 } 736 737 navigationview.MenuItems().Append(item); 738 auto page = std::tuple<NavigationViewItem, FrameworkElement>{ item, subcontainer }; 739 pages.push_back(page); 740 741 return create_subcontainer_obj(current, subcontainer, this->subcontainer, margin, spacing, columnspacing, rowspacing); 742 } 743 744 void UiNavigationTabView::Remove(int index) { 745 navigationview.MenuItems().RemoveAt(index); 746 pages.erase(pages.begin() + index); 747 } 748 749 void UiNavigationTabView::Select(int index) { 750 751 } 752 753 FrameworkElement UiNavigationTabView::GetFrameworkElement() { 754 return navigationview; 755 } 756 757 void UiNavigationTabView::SelectionChanged(NavigationView const& sender, NavigationViewSelectionChangedEventArgs const& args) { 758 for (auto page : pages) { 759 NavigationViewItem item = std::get<0>(page); 760 FrameworkElement elm = std::get<1>(page); 761 if (item == navigationview.SelectedItem()) { 762 navigationview.Content(elm); 763 break; 764 } 765 } 766 } 767 768 static int64_t ui_tabview_get(UiInteger *i) { 769 return 0; 770 } 771 772 static void ui_tabview_set(UiInteger *i, int64_t value) { 773 UiTabView *tabview = (UiTabView*)i->obj; 774 tabview->Select(value); 775 } 776 777 UIWIDGET ui_tabview_create(UiObject* obj, UiTabViewArgs *args) { 778 UiTabViewType type = args->tabview == UI_TABVIEW_DEFAULT ? UI_TABVIEW_NAVIGATION_TOP2 : args->tabview; 779 UiTabView* tabview = nullptr; 780 switch (type) { 781 default: { 782 tabview = tabview_pivot_create(obj, args); 783 break; 784 } 785 case UI_TABVIEW_DOC: { 786 tabview = tabview_main_create(obj, args); 787 break; 788 } 789 case UI_TABVIEW_NAVIGATION_SIDE: { 790 tabview = tabview_navigationview_create(obj, args, type); 791 break; 792 } 793 case UI_TABVIEW_NAVIGATION_TOP: { 794 tabview = tabview_navigationview_create(obj, args, type); 795 break; 796 } 797 case UI_TABVIEW_NAVIGATION_TOP2: { 798 tabview = tabview_pivot_create(obj, args); 799 break; 800 } 801 case UI_TABVIEW_INVISIBLE: { 802 tabview = tabview_invisible_create(obj, args); 803 break; 804 } 805 } 806 UiTabViewContainer* ctn = new UiTabViewContainer(tabview); 807 808 // add frame to the parent container 809 UiObject* current = uic_current_obj(obj); 810 UI_APPLY_LAYOUT2(current, args); 811 current->container->Add(tabview->GetFrameworkElement(), true); 812 813 UIElement elm = tabview->GetFrameworkElement(); 814 UiWidget* widget = new UiWidget(elm); 815 ui_context_add_widget_destructor(current->ctx, widget); 816 widget->data1 = tabview; 817 818 // TODO: add tabview destructor 819 820 // bind variable 821 UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_INTEGER); 822 if (var) { 823 UiInteger *i = (UiInteger*)var->value; 824 i->obj = tabview; 825 i->get = ui_tabview_get; 826 i->set = ui_tabview_set; 827 } 828 829 UiObject* newobj = uic_object_new(obj, widget); 830 newobj->container = ctn; 831 uic_obj_add(obj, newobj); 832 833 return widget; 834 } 835 836 void ui_tab_create(UiObject* obj, const char* title) { 837 UiObject* current = uic_current_obj(obj); 838 UiTabView* tabview = (UiTabView*)current->widget->data1; 839 UiObject* newobj = tabview->AddTab(title); 840 uic_obj_add(current, newobj); 841 } 842 843 UIEXPORT void ui_tabview_select(UIWIDGET tabview, int tab) { 844 UiTabView* t = (UiTabView*)tabview->data1; 845 t->Select(tab); 846 } 847 848 UIEXPORT void ui_tabview_remove(UIWIDGET tabview, int tab) { 849 UiTabView* t = (UiTabView*)tabview->data1; 850 t->Remove(tab); 851 } 852 853 UIEXPORT UiObject* ui_tabview_add(UIWIDGET tabview, const char *name, int tab_index) { 854 UiTabView* t = (UiTabView*)tabview->data1; 855 UiObject* newobj = t->AddTab(name, tab_index); 856 return newobj; 857 } 858 859 860 861 // --------------------- UI Headerbar --------------------- 862 863 // TODO: replace placeholder implementation 864 865 UIEXPORT UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs *args) { 866 UiContainerArgs boxargs = { }; 867 boxargs.fill = UI_OFF; 868 return ui_hbox_create(obj, &boxargs); 869 } 870 871 UIEXPORT void ui_headerbar_start_create(UiObject *obj) { 872 UiContainerArgs boxargs = { }; 873 boxargs.fill = UI_OFF; 874 ui_hbox_create(obj, &boxargs); 875 } 876 877 UIEXPORT void ui_headerbar_center_create(UiObject *obj) { 878 UiContainerArgs boxargs = { }; 879 boxargs.fill = UI_OFF; 880 ui_hbox_create(obj, &boxargs); 881 } 882 883 UIEXPORT void ui_headerbar_end_create(UiObject *obj) { 884 UiContainerArgs boxargs = { }; 885 boxargs.fill = UI_OFF; 886 ui_hbox_create(obj, &boxargs); 887 } 888 889 890 891 /* 892 * -------------------- Layout Functions -------------------- 893 * 894 * functions for setting layout attributes for the current container 895 * 896 */ 897 898 void ui_layout_fill(UiObject* obj, UiBool fill) { 899 UiContainer* ct = uic_get_current_container(obj); 900 ct->layout.fill = ui_bool2lb(fill); 901 } 902 903 void ui_layout_hexpand(UiObject* obj, UiBool expand) { 904 UiContainer* ct = uic_get_current_container(obj); 905 ct->layout.hexpand = expand; 906 } 907 908 void ui_layout_vexpand(UiObject* obj, UiBool expand) { 909 UiContainer* ct = uic_get_current_container(obj); 910 ct->layout.vexpand = expand; 911 } 912 913 void ui_layout_hfill(UiObject* obj, UiBool fill) { 914 UiContainer* ct = uic_get_current_container(obj); 915 ct->layout.hfill = fill; 916 } 917 918 void ui_layout_vfill(UiObject* obj, UiBool fill) { 919 UiContainer* ct = uic_get_current_container(obj); 920 ct->layout.vfill = fill; 921 } 922 923 void ui_layout_override_defaults(UiObject* obj, UiBool def) { 924 UiContainer* ct = uic_get_current_container(obj); 925 ct->layout.override_defaults = def; 926 } 927 928 void ui_layout_width(UiObject* obj, int width) { 929 UiContainer* ct = uic_get_current_container(obj); 930 ct->layout.width = width; 931 } 932 933 void ui_layout_height(UiObject* obj, int height) { 934 UiContainer* ct = uic_get_current_container(obj); 935 ct->layout.height = height; 936 } 937 938 void ui_layout_colspan(UiObject* obj, int cols) { 939 UiContainer* ct = uic_get_current_container(obj); 940 ct->layout.colspan = cols; 941 } 942 943 void ui_layout_rowspan(UiObject* obj, int rows) { 944 UiContainer* ct = uic_get_current_container(obj); 945 ct->layout.rowspan = rows; 946 } 947 948 void ui_newline(UiObject* obj) { 949 UiContainer* ct = uic_get_current_container(obj); 950 ct->layout.newline = TRUE; 951 } 952 953