Serenity Operating System
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}