diff options
author | Andreas Kling <kling@serenityos.org> | 2021-01-12 12:05:23 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-01-12 12:05:23 +0100 |
commit | dc28c07fa526841e05e16161c74a6c23984f1dd5 (patch) | |
tree | d68796bc7708eba33fbf7247e1a92188ac5acf6f /Userland/Applications/Welcome | |
parent | aa939c4b4b8a7eb1d22b166ebb5fb737d6e66714 (diff) | |
download | serenity-dc28c07fa526841e05e16161c74a6c23984f1dd5.zip |
Applications: Move to Userland/Applications/
Diffstat (limited to 'Userland/Applications/Welcome')
-rw-r--r-- | Userland/Applications/Welcome/BackgroundWidget.cpp | 52 | ||||
-rw-r--r-- | Userland/Applications/Welcome/BackgroundWidget.h | 41 | ||||
-rw-r--r-- | Userland/Applications/Welcome/CMakeLists.txt | 9 | ||||
-rw-r--r-- | Userland/Applications/Welcome/TextWidget.cpp | 140 | ||||
-rw-r--r-- | Userland/Applications/Welcome/TextWidget.h | 65 | ||||
-rw-r--r-- | Userland/Applications/Welcome/UnuncheckableButton.cpp | 35 | ||||
-rw-r--r-- | Userland/Applications/Welcome/UnuncheckableButton.h | 40 | ||||
-rw-r--r-- | Userland/Applications/Welcome/main.cpp | 234 |
8 files changed, 616 insertions, 0 deletions
diff --git a/Userland/Applications/Welcome/BackgroundWidget.cpp b/Userland/Applications/Welcome/BackgroundWidget.cpp new file mode 100644 index 0000000000..c64f2fc93b --- /dev/null +++ b/Userland/Applications/Welcome/BackgroundWidget.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020, the SerenityOS developers. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "BackgroundWidget.h" +#include <LibGUI/Painter.h> +#include <LibGfx/Color.h> +#include <LibGfx/Palette.h> + +BackgroundWidget::BackgroundWidget() +{ +} + +BackgroundWidget::~BackgroundWidget() +{ +} + +void BackgroundWidget::paint_event(GUI::PaintEvent& event) +{ + GUI::Frame::paint_event(event); + + GUI::Painter painter(*this); + painter.add_clip_rect(event.rect()); + painter.fill_rect_with_gradient(event.rect(), Color::from_rgb(0xccdddd), Color::from_rgb(0xdcdcde)); +} + +void BackgroundWidget::resize_event(GUI::ResizeEvent& event) +{ + GUI::Widget::resize_event(event); +} diff --git a/Userland/Applications/Welcome/BackgroundWidget.h b/Userland/Applications/Welcome/BackgroundWidget.h new file mode 100644 index 0000000000..fea3871edc --- /dev/null +++ b/Userland/Applications/Welcome/BackgroundWidget.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2020, the SerenityOS developers. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include <LibGUI/Frame.h> + +class BackgroundWidget : public GUI::Frame { + C_OBJECT(BackgroundWidget) +public: + virtual ~BackgroundWidget() override; + +private: + BackgroundWidget(); + + virtual void paint_event(GUI::PaintEvent&) override; + virtual void resize_event(GUI::ResizeEvent&) override; +}; diff --git a/Userland/Applications/Welcome/CMakeLists.txt b/Userland/Applications/Welcome/CMakeLists.txt new file mode 100644 index 0000000000..e9d1ef3380 --- /dev/null +++ b/Userland/Applications/Welcome/CMakeLists.txt @@ -0,0 +1,9 @@ +set(SOURCES + BackgroundWidget.cpp + main.cpp + TextWidget.cpp + UnuncheckableButton.cpp +) + +serenity_bin(Welcome) +target_link_libraries(Welcome LibGUI) diff --git a/Userland/Applications/Welcome/TextWidget.cpp b/Userland/Applications/Welcome/TextWidget.cpp new file mode 100644 index 0000000000..263d4514f8 --- /dev/null +++ b/Userland/Applications/Welcome/TextWidget.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "TextWidget.h" +#include <AK/Optional.h> +#include <AK/String.h> +#include <AK/StringBuilder.h> +#include <AK/Vector.h> +#include <LibGUI/Painter.h> +#include <LibGfx/Font.h> +#include <LibGfx/Palette.h> + +TextWidget::TextWidget(const StringView& text) + : m_text(text) +{ + set_frame_thickness(0); + set_frame_shadow(Gfx::FrameShadow::Plain); + set_frame_shape(Gfx::FrameShape::NoFrame); +} + +TextWidget::~TextWidget() +{ +} + +void TextWidget::set_text(const StringView& text) +{ + if (text == m_text) + return; + m_text = text; + wrap_and_set_height(); + update(); +} + +void TextWidget::paint_event(GUI::PaintEvent& event) +{ + GUI::Frame::paint_event(event); + + GUI::Painter painter(*this); + painter.add_clip_rect(event.rect()); + + int indent = 0; + if (frame_thickness() > 0) + indent = font().glyph_width('x') / 2; + + for (size_t i = 0; i < m_lines.size(); i++) { + auto& line = m_lines[i]; + + auto text_rect = frame_inner_rect(); + text_rect.move_by(indent, i * m_line_height); + if (!line.is_empty()) + text_rect.set_width(text_rect.width() - indent * 2); + + if (is_enabled()) { + painter.draw_text(text_rect, line, m_text_alignment, palette().color(foreground_role()), Gfx::TextElision::None); + } else { + painter.draw_text(text_rect.translated(1, 1), line, font(), text_alignment(), Color::White, Gfx::TextElision::Right); + painter.draw_text(text_rect, line, font(), text_alignment(), Color::from_rgb(0x808080), Gfx::TextElision::Right); + } + } +} + +void TextWidget::resize_event(GUI::ResizeEvent& event) +{ + wrap_and_set_height(); + GUI::Widget::resize_event(event); +} + +void TextWidget::wrap_and_set_height() +{ + Vector<String> words; + Optional<size_t> start; + for (size_t i = 0; i < m_text.length(); i++) { + auto ch = m_text[i]; + + if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') { + if (start.has_value()) + words.append(m_text.substring(start.value(), i - start.value())); + start.clear(); + } else if (!start.has_value()) { + start = i; + } + } + if (start.has_value()) + words.append(m_text.substring(start.value(), m_text.length() - start.value())); + + auto rect = frame_inner_rect(); + if (frame_thickness() > 0) + rect.set_width(rect.width() - font().glyph_width('x')); + + StringBuilder builder; + Vector<String> lines; + int line_width = 0; + for (auto& word : words) { + int word_width = font().width(word); + if (line_width != 0) + word_width += font().glyph_width('x'); + + if (line_width + word_width > rect.width()) { + lines.append(builder.to_string()); + builder.clear(); + line_width = 0; + } + + if (line_width != 0) + builder.append(' '); + builder.append(word); + line_width += word_width; + } + auto last_line = builder.to_string(); + if (!last_line.is_empty()) { + lines.append(last_line); + } + + m_lines = lines; + + set_fixed_height(m_lines.size() * m_line_height + frame_thickness() * 2); +} diff --git a/Userland/Applications/Welcome/TextWidget.h b/Userland/Applications/Welcome/TextWidget.h new file mode 100644 index 0000000000..c4353096ff --- /dev/null +++ b/Userland/Applications/Welcome/TextWidget.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include <AK/String.h> +#include <AK/Vector.h> +#include <LibGUI/Frame.h> +#include <LibGfx/TextAlignment.h> + +class TextWidget : public GUI::Frame { + C_OBJECT(TextWidget); + +public: + virtual ~TextWidget() override; + + String text() const { return m_text; } + void set_text(const StringView&); + + Gfx::TextAlignment text_alignment() const { return m_text_alignment; } + void set_text_alignment(Gfx::TextAlignment text_alignment) { m_text_alignment = text_alignment; } + + bool should_wrap() const { return m_should_wrap; } + void set_should_wrap(bool should_wrap) { m_should_wrap = should_wrap; } + + int line_height() const { return m_line_height; } + void set_line_height(int line_height) { m_line_height = line_height; } + + void wrap_and_set_height(); + +private: + explicit TextWidget(const StringView& text = {}); + + virtual void paint_event(GUI::PaintEvent&) override; + virtual void resize_event(GUI::ResizeEvent&) override; + + String m_text; + Vector<String> m_lines; + Gfx::TextAlignment m_text_alignment { Gfx::TextAlignment::Center }; + bool m_should_wrap { false }; + int m_line_height { 0 }; +}; diff --git a/Userland/Applications/Welcome/UnuncheckableButton.cpp b/Userland/Applications/Welcome/UnuncheckableButton.cpp new file mode 100644 index 0000000000..29194fff81 --- /dev/null +++ b/Userland/Applications/Welcome/UnuncheckableButton.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2020, the SerenityOS developers. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "UnuncheckableButton.h" + +UnuncheckableButton::UnuncheckableButton() +{ +} + +UnuncheckableButton::~UnuncheckableButton() +{ +} diff --git a/Userland/Applications/Welcome/UnuncheckableButton.h b/Userland/Applications/Welcome/UnuncheckableButton.h new file mode 100644 index 0000000000..b91a41ef9c --- /dev/null +++ b/Userland/Applications/Welcome/UnuncheckableButton.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020, the SerenityOS developers. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include <LibGUI/Button.h> + +class UnuncheckableButton : public GUI::Button { + C_OBJECT(UnuncheckableButton) +public: + virtual ~UnuncheckableButton() override; + + virtual bool is_uncheckable() const override { return false; } + +private: + UnuncheckableButton(); +}; diff --git a/Userland/Applications/Welcome/main.cpp b/Userland/Applications/Welcome/main.cpp new file mode 100644 index 0000000000..101b35fd97 --- /dev/null +++ b/Userland/Applications/Welcome/main.cpp @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "BackgroundWidget.h" +#include "TextWidget.h" +#include "UnuncheckableButton.h" +#include <AK/ByteBuffer.h> +#include <AK/Optional.h> +#include <AK/String.h> +#include <AK/StringBuilder.h> +#include <AK/Vector.h> +#include <LibCore/File.h> +#include <LibGUI/Application.h> +#include <LibGUI/BoxLayout.h> +#include <LibGUI/Button.h> +#include <LibGUI/ImageWidget.h> +#include <LibGUI/Label.h> +#include <LibGUI/MessageBox.h> +#include <LibGUI/StackWidget.h> +#include <LibGUI/Window.h> +#include <LibGfx/Bitmap.h> +#include <LibGfx/Font.h> +#include <LibGfx/FontDatabase.h> +#include <stdio.h> +#include <unistd.h> + +struct ContentPage { + String menu_name; + String title; + String icon = String::empty(); + Vector<String> content; +}; + +static Optional<Vector<ContentPage>> parse_welcome_file(const String& path) +{ + auto file = Core::File::construct(path); + if (!file->open(Core::IODevice::ReadOnly)) + return {}; + + Vector<ContentPage> pages; + StringBuilder current_output_line; + bool started = false; + ContentPage current; + while (file->can_read_line()) { + auto line = file->read_line(); + if (line.is_empty()) { + if (!current_output_line.to_string().is_empty()) + current.content.append(current_output_line.to_string()); + current_output_line.clear(); + continue; + } + switch (line[0]) { + case '*': + dbgln("menu_item line:\t{}", line); + if (started) + pages.append(current); + else + started = true; + + current = {}; + current.menu_name = line.substring(2, line.length() - 2); + break; + case '$': + dbgln("icon line: \t{}", line); + current.icon = line.substring(2, line.length() - 2); + break; + case '>': + dbgln("title line:\t{}", line); + current.title = line.substring(2, line.length() - 2); + break; + case '#': + dbgln("comment line:\t{}", line); + break; + default: + dbgln("content line:\t", line); + if (current_output_line.length() != 0) + current_output_line.append(' '); + current_output_line.append(line); + break; + } + } + + if (started) { + current.content.append(current_output_line.to_string()); + pages.append(current); + } + + return pages; +} + +int main(int argc, char** argv) +{ + if (pledge("stdio shared_buffer rpath unix cpath fattr", nullptr) < 0) { + perror("pledge"); + return 1; + } + + auto app = GUI::Application::construct(argc, argv); + + if (pledge("stdio shared_buffer rpath", nullptr) < 0) { + perror("pledge"); + return 1; + } + + if (unveil("/res", "r") < 0) { + perror("unveil"); + return 1; + } + + unveil(nullptr, nullptr); + + Optional<Vector<ContentPage>> _pages = parse_welcome_file("/res/welcome.txt"); + if (!_pages.has_value()) { + GUI::MessageBox::show(nullptr, "Could not open Welcome file.", "Welcome", GUI::MessageBox::Type::Error); + return 1; + } + auto pages = _pages.value(); + + auto window = GUI::Window::construct(); + window->set_title("Welcome"); + window->resize(640, 360); + window->center_on_screen(); + + auto& background = window->set_main_widget<BackgroundWidget>(); + background.set_fill_with_background_color(false); + background.set_layout<GUI::VerticalBoxLayout>(); + background.layout()->set_margins({ 16, 8, 16, 8 }); + background.layout()->set_spacing(8); + + // + // header + // + + auto& header = background.add<GUI::Label>(); + header.set_font(Gfx::Font::load_from_file("/res/fonts/PebbletonBold14.font")); + header.set_text("Welcome to SerenityOS!"); + header.set_text_alignment(Gfx::TextAlignment::CenterLeft); + header.set_fixed_height(30); + + // + // main section + // + + auto& main_section = background.add<GUI::Widget>(); + main_section.set_layout<GUI::HorizontalBoxLayout>(); + main_section.layout()->set_margins({ 0, 0, 0, 0 }); + main_section.layout()->set_spacing(8); + + auto& menu = main_section.add<GUI::Widget>(); + menu.set_layout<GUI::VerticalBoxLayout>(); + menu.layout()->set_margins({ 0, 0, 0, 0 }); + menu.layout()->set_spacing(4); + menu.set_fixed_width(100); + + auto& stack = main_section.add<GUI::StackWidget>(); + + bool first = true; + for (auto& page : pages) { + auto& content = stack.add<GUI::Widget>(); + content.set_layout<GUI::VerticalBoxLayout>(); + content.layout()->set_margins({ 0, 0, 0, 0 }); + content.layout()->set_spacing(8); + + auto& title_box = content.add<GUI::Widget>(); + title_box.set_layout<GUI::HorizontalBoxLayout>(); + title_box.layout()->set_spacing(4); + title_box.set_fixed_height(16); + + if (!page.icon.is_empty()) { + auto& icon = title_box.add<GUI::ImageWidget>(); + icon.set_fixed_size(16, 16); + icon.load_from_file(page.icon); + } + + auto& content_title = title_box.add<GUI::Label>(); + content_title.set_font(Gfx::FontDatabase::default_bold_font()); + content_title.set_text(page.title); + content_title.set_text_alignment(Gfx::TextAlignment::CenterLeft); + content_title.set_fixed_height(10); + + for (auto& paragraph : page.content) { + auto& content_text = content.add<TextWidget>(); + content_text.set_font(Gfx::FontDatabase::default_font()); + content_text.set_text(paragraph); + content_text.set_text_alignment(Gfx::TextAlignment::TopLeft); + content_text.set_line_height(12); + content_text.wrap_and_set_height(); + } + + auto& menu_option = menu.add<UnuncheckableButton>(); + menu_option.set_font(Gfx::FontDatabase::default_font()); + menu_option.set_text(page.menu_name); + menu_option.set_text_alignment(Gfx::TextAlignment::CenterLeft); + menu_option.set_fixed_height(20); + menu_option.set_checkable(true); + menu_option.set_exclusive(true); + + if (first) + menu_option.set_checked(true); + + menu_option.on_click = [content = &content, &stack](auto) { + stack.set_active_widget(content); + content->invalidate_layout(); + }; + + first = false; + } + + window->show(); + return app->exec(); +} |