Serenity Operating System
at master 146 lines 4.1 kB view raw
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 8#include <LibGUI/BoxLayout.h> 9#include <LibGUI/Button.h> 10#include <LibGUI/SeparatorWidget.h> 11#include <LibGUI/Widget.h> 12#include <LibGUI/Wizards/AbstractWizardPage.h> 13#include <LibGUI/Wizards/WizardDialog.h> 14#include <LibGfx/Orientation.h> 15#include <LibGfx/SystemTheme.h> 16 17namespace GUI { 18 19WizardDialog::WizardDialog(Window* parent_window) 20 : Dialog(parent_window) 21 , m_page_stack() 22{ 23 resize(500, 360); 24 set_title(DeprecatedString::formatted("Sample wizard")); 25 set_resizable(false); 26 27 if (parent_window) 28 set_icon(parent_window->icon()); 29 30 auto main_widget = set_main_widget<Widget>().release_value_but_fixme_should_propagate_errors(); 31 main_widget->set_fill_with_background_color(true); 32 main_widget->set_layout<VerticalBoxLayout>(GUI::Margins {}, 0); 33 34 m_page_container_widget = main_widget->add<Widget>(); 35 m_page_container_widget->set_fixed_size(500, 315); 36 m_page_container_widget->set_layout<VerticalBoxLayout>(); 37 38 auto& separator = main_widget->add<SeparatorWidget>(Gfx::Orientation::Horizontal); 39 separator.set_fixed_height(2); 40 41 auto& nav_container_widget = main_widget->add<Widget>(); 42 nav_container_widget.set_layout<HorizontalBoxLayout>(GUI::Margins { 0, 10 }, 0); 43 nav_container_widget.set_fixed_height(42); 44 nav_container_widget.add_spacer().release_value_but_fixme_should_propagate_errors(); 45 46 m_back_button = nav_container_widget.add<DialogButton>("< Back"_short_string); 47 m_back_button->on_click = [&](auto) { 48 pop_page(); 49 }; 50 51 m_next_button = nav_container_widget.add<DialogButton>("Next >"_short_string); 52 m_next_button->on_click = [&](auto) { 53 VERIFY(has_pages()); 54 55 if (!current_page().can_go_next()) 56 return done(ExecResult::OK); 57 58 auto next_page = current_page().next_page(); 59 if (!next_page) 60 return done(ExecResult::OK); 61 62 push_page(*next_page); 63 }; 64 65 auto& button_spacer = nav_container_widget.add<Widget>(); 66 button_spacer.set_fixed_width(10); 67 68 m_cancel_button = nav_container_widget.add<DialogButton>("Cancel"_short_string); 69 m_cancel_button->on_click = [&](auto) { 70 handle_cancel(); 71 }; 72 73 update_navigation(); 74} 75 76void WizardDialog::push_page(AbstractWizardPage& page) 77{ 78 if (!m_page_stack.is_empty()) 79 m_page_stack.last()->page_leave(); 80 81 m_page_stack.append(page); 82 m_page_container_widget->remove_all_children(); 83 m_page_container_widget->add_child(page); 84 85 update_navigation(); 86 page.page_enter(); 87} 88 89void WizardDialog::replace_page(AbstractWizardPage& page) 90{ 91 if (!m_page_stack.is_empty()) 92 m_page_stack.take_last()->page_leave(); 93 94 m_page_stack.append(page); 95 m_page_container_widget->remove_all_children(); 96 m_page_container_widget->add_child(page); 97 98 update_navigation(); 99 page.page_enter(); 100} 101 102void WizardDialog::pop_page() 103{ 104 if (m_page_stack.size() <= 1) 105 return; 106 107 auto page = m_page_stack.take_last(); 108 page->page_leave(); 109 110 m_page_container_widget->remove_all_children(); 111 m_page_container_widget->add_child(m_page_stack.last()); 112 113 update_navigation(); 114 m_page_stack.last()->page_enter(); 115} 116 117void WizardDialog::update_navigation() 118{ 119 m_back_button->set_enabled(m_page_stack.size() > 1); 120 if (has_pages()) { 121 m_next_button->set_enabled(current_page().is_final_page() || current_page().can_go_next()); 122 if (current_page().is_final_page()) 123 m_next_button->set_text("Finish"_short_string); 124 else 125 m_next_button->set_text("Next >"_short_string); 126 } else { 127 m_next_button->set_text("Next >"_short_string); 128 m_next_button->set_enabled(false); 129 } 130} 131 132AbstractWizardPage& WizardDialog::current_page() 133{ 134 VERIFY(has_pages()); 135 return m_page_stack.last(); 136} 137 138void WizardDialog::handle_cancel() 139{ 140 if (on_cancel) 141 return on_cancel(); 142 143 done(ExecResult::Cancel); 144} 145 146}