WizardDialog.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /*
  2. * Copyright (c) 2021, Nick Vella <nick@nxk.io>
  3. * Copyright (c) 2022, the SerenityOS developers.
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <LibGUI/BoxLayout.h>
  8. #include <LibGUI/Button.h>
  9. #include <LibGUI/SeparatorWidget.h>
  10. #include <LibGUI/Widget.h>
  11. #include <LibGUI/Wizards/AbstractWizardPage.h>
  12. #include <LibGUI/Wizards/WizardDialog.h>
  13. #include <LibGfx/Orientation.h>
  14. #include <LibGfx/SystemTheme.h>
  15. namespace GUI {
  16. WizardDialog::WizardDialog(Window* parent_window)
  17. : Dialog(parent_window)
  18. , m_page_stack()
  19. {
  20. resize(500, 360);
  21. set_title(String::formatted("Sample wizard"));
  22. set_resizable(false);
  23. if (parent_window)
  24. set_icon(parent_window->icon());
  25. auto& main_widget = set_main_widget<Widget>();
  26. main_widget.set_fill_with_background_color(true);
  27. main_widget.set_layout<VerticalBoxLayout>();
  28. main_widget.layout()->set_spacing(0);
  29. m_page_container_widget = main_widget.add<Widget>();
  30. m_page_container_widget->set_fixed_size(500, 315);
  31. m_page_container_widget->set_layout<VerticalBoxLayout>();
  32. auto& separator = main_widget.add<SeparatorWidget>(Gfx::Orientation::Horizontal);
  33. separator.set_fixed_height(2);
  34. auto& nav_container_widget = main_widget.add<Widget>();
  35. nav_container_widget.set_layout<HorizontalBoxLayout>();
  36. nav_container_widget.set_fixed_height(42);
  37. nav_container_widget.layout()->set_margins({ 0, 10 });
  38. nav_container_widget.layout()->set_spacing(0);
  39. nav_container_widget.layout()->add_spacer();
  40. m_back_button = nav_container_widget.add<Button>("< Back");
  41. m_back_button->set_fixed_width(75);
  42. m_back_button->on_click = [&](auto) {
  43. pop_page();
  44. };
  45. m_next_button = nav_container_widget.add<Button>("Next >");
  46. m_next_button->set_fixed_width(75);
  47. m_next_button->on_click = [&](auto) {
  48. VERIFY(has_pages());
  49. if (!current_page().can_go_next())
  50. return done(ExecResult::OK);
  51. auto next_page = current_page().next_page();
  52. if (!next_page)
  53. return done(ExecResult::OK);
  54. push_page(*next_page);
  55. };
  56. auto& button_spacer = nav_container_widget.add<Widget>();
  57. button_spacer.set_fixed_width(10);
  58. m_cancel_button = nav_container_widget.add<Button>("Cancel");
  59. m_cancel_button->set_fixed_width(75);
  60. m_cancel_button->on_click = [&](auto) {
  61. handle_cancel();
  62. };
  63. update_navigation();
  64. }
  65. void WizardDialog::push_page(AbstractWizardPage& page)
  66. {
  67. if (!m_page_stack.is_empty())
  68. m_page_stack.last().page_leave();
  69. m_page_stack.append(page);
  70. m_page_container_widget->remove_all_children();
  71. m_page_container_widget->add_child(page);
  72. update_navigation();
  73. page.page_enter();
  74. }
  75. void WizardDialog::replace_page(AbstractWizardPage& page)
  76. {
  77. if (!m_page_stack.is_empty())
  78. m_page_stack.take_last()->page_leave();
  79. m_page_stack.append(page);
  80. m_page_container_widget->remove_all_children();
  81. m_page_container_widget->add_child(page);
  82. update_navigation();
  83. page.page_enter();
  84. }
  85. void WizardDialog::pop_page()
  86. {
  87. if (m_page_stack.size() <= 1)
  88. return;
  89. auto page = m_page_stack.take_last();
  90. page->page_leave();
  91. m_page_container_widget->remove_all_children();
  92. m_page_container_widget->add_child(m_page_stack.last());
  93. update_navigation();
  94. m_page_stack.last().page_enter();
  95. }
  96. void WizardDialog::update_navigation()
  97. {
  98. m_back_button->set_enabled(m_page_stack.size() > 1);
  99. if (has_pages()) {
  100. m_next_button->set_enabled(current_page().is_final_page() || current_page().can_go_next());
  101. m_next_button->set_text(current_page().is_final_page() ? "Finish" : "Next >");
  102. } else {
  103. m_next_button->set_text("Next >");
  104. m_next_button->set_enabled(false);
  105. }
  106. }
  107. AbstractWizardPage& WizardDialog::current_page()
  108. {
  109. VERIFY(has_pages());
  110. return m_page_stack.last();
  111. }
  112. void WizardDialog::handle_cancel()
  113. {
  114. if (on_cancel)
  115. return on_cancel();
  116. done(ExecResult::Cancel);
  117. }
  118. }