WizardDialog.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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<DialogButton>("< Back");
  41. m_back_button->on_click = [&](auto) {
  42. pop_page();
  43. };
  44. m_next_button = nav_container_widget.add<DialogButton>("Next >");
  45. m_next_button->on_click = [&](auto) {
  46. VERIFY(has_pages());
  47. if (!current_page().can_go_next())
  48. return done(ExecResult::OK);
  49. auto next_page = current_page().next_page();
  50. if (!next_page)
  51. return done(ExecResult::OK);
  52. push_page(*next_page);
  53. };
  54. auto& button_spacer = nav_container_widget.add<Widget>();
  55. button_spacer.set_fixed_width(10);
  56. m_cancel_button = nav_container_widget.add<DialogButton>("Cancel");
  57. m_cancel_button->on_click = [&](auto) {
  58. handle_cancel();
  59. };
  60. update_navigation();
  61. }
  62. void WizardDialog::push_page(AbstractWizardPage& page)
  63. {
  64. if (!m_page_stack.is_empty())
  65. m_page_stack.last().page_leave();
  66. m_page_stack.append(page);
  67. m_page_container_widget->remove_all_children();
  68. m_page_container_widget->add_child(page);
  69. update_navigation();
  70. page.page_enter();
  71. }
  72. void WizardDialog::replace_page(AbstractWizardPage& page)
  73. {
  74. if (!m_page_stack.is_empty())
  75. m_page_stack.take_last()->page_leave();
  76. m_page_stack.append(page);
  77. m_page_container_widget->remove_all_children();
  78. m_page_container_widget->add_child(page);
  79. update_navigation();
  80. page.page_enter();
  81. }
  82. void WizardDialog::pop_page()
  83. {
  84. if (m_page_stack.size() <= 1)
  85. return;
  86. auto page = m_page_stack.take_last();
  87. page->page_leave();
  88. m_page_container_widget->remove_all_children();
  89. m_page_container_widget->add_child(m_page_stack.last());
  90. update_navigation();
  91. m_page_stack.last().page_enter();
  92. }
  93. void WizardDialog::update_navigation()
  94. {
  95. m_back_button->set_enabled(m_page_stack.size() > 1);
  96. if (has_pages()) {
  97. m_next_button->set_enabled(current_page().is_final_page() || current_page().can_go_next());
  98. m_next_button->set_text(current_page().is_final_page() ? "Finish" : "Next >");
  99. } else {
  100. m_next_button->set_text("Next >");
  101. m_next_button->set_enabled(false);
  102. }
  103. }
  104. AbstractWizardPage& WizardDialog::current_page()
  105. {
  106. VERIFY(has_pages());
  107. return m_page_stack.last();
  108. }
  109. void WizardDialog::handle_cancel()
  110. {
  111. if (on_cancel)
  112. return on_cancel();
  113. done(ExecResult::Cancel);
  114. }
  115. }