Compare commits
2 Commits
main
...
new-layout
Author | SHA1 | Date | |
---|---|---|---|
4087c7510e | |||
280b0c90af |
@ -23,6 +23,16 @@ struct Tile
|
|||||||
class GameWidget final : public ui::Widget
|
class GameWidget final : public ui::Widget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
GameWidget(ui::Window* window, ui::Widget* parent) : ui::Widget(window, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void show_tree(int indent) override
|
||||||
|
{
|
||||||
|
os::println("%*s- 2048 GameWidget (%d,%d,%d,%d)", indent, "", m_rect.pos.x, m_rect.pos.y, m_rect.width,
|
||||||
|
m_rect.height);
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr int MARGIN = 5;
|
static constexpr int MARGIN = 5;
|
||||||
|
|
||||||
Result<void> draw(ui::Canvas& canvas) override
|
Result<void> draw(ui::Canvas& canvas) override
|
||||||
@ -356,9 +366,8 @@ Result<int> luna_main(int, char**)
|
|||||||
window->set_background(ui::BLACK);
|
window->set_background(ui::BLACK);
|
||||||
window->set_title("2048");
|
window->set_title("2048");
|
||||||
|
|
||||||
GameWidget game;
|
auto* game = TRY(window->create_main_widget<GameWidget>());
|
||||||
window->set_main_widget(game);
|
game->reset();
|
||||||
game.reset();
|
|
||||||
|
|
||||||
return app.run();
|
return app.run();
|
||||||
}
|
}
|
||||||
|
@ -21,27 +21,26 @@ Result<int> luna_main(int, char**)
|
|||||||
utsname info;
|
utsname info;
|
||||||
uname(&info);
|
uname(&info);
|
||||||
|
|
||||||
ui::VerticalLayout main_layout;
|
auto* main_layout = TRY(window->create_main_widget<ui::VerticalLayout>());
|
||||||
window->set_main_widget(main_layout);
|
main_layout->set_layout_settings(ui::Margins { 0, 0, 20, 40 });
|
||||||
|
|
||||||
ui::Label title("About Luna");
|
auto* title = TRY(main_layout->add_child_widget<ui::Label>());
|
||||||
title.set_font(ui::Font::default_bold_font());
|
title->set_text("About Luna");
|
||||||
|
title->set_font(ui::Font::default_bold_font());
|
||||||
|
|
||||||
main_layout.add_widget(title);
|
auto* version_info = TRY(main_layout->add_child_widget<ui::VerticalLayout>());
|
||||||
|
version_info->set_layout_settings(ui::Margins { 0, 0, 10, 10 });
|
||||||
ui::VerticalLayout version_info;
|
|
||||||
main_layout.add_widget(version_info);
|
|
||||||
|
|
||||||
ui::Label license("Licensed under the BSD-2-Clause license.");
|
|
||||||
main_layout.add_widget(license);
|
|
||||||
|
|
||||||
|
auto* os_release = TRY(version_info->add_child_widget<ui::Label>());
|
||||||
String os_release_text = TRY(String::format("OS release: %s"_sv, info.release));
|
String os_release_text = TRY(String::format("OS release: %s"_sv, info.release));
|
||||||
ui::Label os_release(os_release_text.view());
|
os_release->set_text(os_release_text.view());
|
||||||
version_info.add_widget(os_release);
|
|
||||||
|
|
||||||
|
auto* kernel_version = TRY(version_info->add_child_widget<ui::Label>());
|
||||||
String kernel_version_text = TRY(String::format("Kernel version: %s"_sv, info.version));
|
String kernel_version_text = TRY(String::format("Kernel version: %s"_sv, info.version));
|
||||||
ui::Label kernel_version(kernel_version_text.view());
|
kernel_version->set_text(kernel_version_text.view());
|
||||||
version_info.add_widget(kernel_version);
|
|
||||||
|
auto* license = TRY(version_info->add_child_widget<ui::Label>());
|
||||||
|
license->set_text("Licensed under the BSD-2-Clause license.");
|
||||||
|
|
||||||
return app.run();
|
return app.run();
|
||||||
}
|
}
|
||||||
|
@ -29,12 +29,12 @@ Result<int> luna_main(int, char**)
|
|||||||
window->set_title("Clock");
|
window->set_title("Clock");
|
||||||
window->set_background(ui::GRAY);
|
window->set_background(ui::GRAY);
|
||||||
|
|
||||||
g_label = TRY(make<ui::Label>("00:00:00"));
|
g_label = TRY(window->create_main_widget<ui::Label>());
|
||||||
|
|
||||||
|
g_label->set_text("00:00:00");
|
||||||
g_label->set_font(ui::Font::default_bold_font());
|
g_label->set_font(ui::Font::default_bold_font());
|
||||||
g_label->set_color(ui::BLACK);
|
g_label->set_color(ui::BLACK);
|
||||||
|
|
||||||
window->set_main_widget(*g_label);
|
|
||||||
|
|
||||||
update_time();
|
update_time();
|
||||||
|
|
||||||
auto timer = TRY(os::Timer::create_repeating(1000, update_time));
|
auto timer = TRY(os::Timer::create_repeating(1000, update_time));
|
||||||
|
@ -30,24 +30,19 @@ void sighup_handler(int)
|
|||||||
os::Process::exec(args[0], { args, 1 });
|
os::Process::exec(args[0], { args, 1 });
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<void> create_widget_group_for_app(ui::HorizontalLayout& layout, StringView path, StringView icon)
|
Result<void> create_widget_group_for_app(ui::HorizontalLayout* layout, StringView path, StringView icon)
|
||||||
{
|
{
|
||||||
auto* button = TRY(make<ui::Button>(ui::Rect { 0, 0, 50, 50 }));
|
auto* button = TRY(layout->add_child_widget<ui::Button>());
|
||||||
layout.add_widget(*button);
|
|
||||||
|
|
||||||
auto* container = TRY(
|
auto* container = TRY(button->create_child_widget<ui::Container>());
|
||||||
make<ui::Container>(ui::Rect { 0, 0, 50, 50 }, ui::VerticalAlignment::Center, ui::HorizontalAlignment::Center));
|
|
||||||
button->set_widget(*container);
|
|
||||||
button->set_action([=] {
|
button->set_action([=] {
|
||||||
os::Launcher::LaunchDetachedRequest request;
|
os::Launcher::LaunchDetachedRequest request;
|
||||||
SET_IPC_STRING(request.command, path.chars());
|
SET_IPC_STRING(request.command, path.chars());
|
||||||
launcher_client->send_async(request);
|
launcher_client->send_async(request);
|
||||||
});
|
});
|
||||||
|
|
||||||
auto image = TRY(ui::ImageWidget::load(icon));
|
auto image = TRY(container->create_child_widget<ui::ImageWidget>());
|
||||||
container->set_widget(*image);
|
image->load(icon);
|
||||||
|
|
||||||
image.leak();
|
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -165,8 +160,8 @@ Result<int> luna_main(int, char**)
|
|||||||
window->set_background(TASKBAR_COLOR);
|
window->set_background(TASKBAR_COLOR);
|
||||||
window->set_special_attributes(ui::UNFOCUSEABLE);
|
window->set_special_attributes(ui::UNFOCUSEABLE);
|
||||||
|
|
||||||
ui::HorizontalLayout layout(ui::Margins { 0, 0, 0, 0 }, ui::AdjustHeight::Yes, ui::AdjustWidth::No);
|
auto* layout = TRY(window->create_main_widget<ui::HorizontalLayout>());
|
||||||
window->set_main_widget(layout);
|
layout->set_layout_settings(ui::Margins { 0, 0, 0, 0 }, ui::AdjustHeight::Yes, ui::AdjustWidth::No);
|
||||||
|
|
||||||
load_app_files_from_path("/usr/share/applications/");
|
load_app_files_from_path("/usr/share/applications/");
|
||||||
|
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
#include <os/FileSystem.h>
|
#include <os/FileSystem.h>
|
||||||
#include <ui/App.h>
|
#include <ui/App.h>
|
||||||
|
|
||||||
EditorWidget::EditorWidget(SharedPtr<ui::Font> font) : ui::TextInput(), m_font(font)
|
EditorWidget::EditorWidget(ui::Window* window, ui::Widget* parent)
|
||||||
|
: ui::TextInput(window, parent), m_font(ui::Font::default_font())
|
||||||
{
|
{
|
||||||
recalculate_lines();
|
recalculate_lines();
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
class EditorWidget : public ui::TextInput
|
class EditorWidget : public ui::TextInput
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EditorWidget(SharedPtr<ui::Font> font);
|
EditorWidget(ui::Window* window, ui::Widget* parent);
|
||||||
|
|
||||||
Result<void> load_file(const os::Path& path);
|
Result<void> load_file(const os::Path& path);
|
||||||
|
|
||||||
@ -31,6 +31,11 @@ class EditorWidget : public ui::TextInput
|
|||||||
return m_path;
|
return m_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_font(SharedPtr<ui::Font> font)
|
||||||
|
{
|
||||||
|
m_font = font;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SharedPtr<ui::Font> m_font;
|
SharedPtr<ui::Font> m_font;
|
||||||
|
|
||||||
|
@ -30,8 +30,7 @@ Result<int> luna_main(int argc, char** argv)
|
|||||||
window->set_title("Text Editor");
|
window->set_title("Text Editor");
|
||||||
app.set_main_window(window);
|
app.set_main_window(window);
|
||||||
|
|
||||||
auto* editor = TRY(make<EditorWidget>(ui::Font::default_font()));
|
auto* editor = TRY(window->create_main_widget<EditorWidget>());
|
||||||
window->set_main_widget(*editor);
|
|
||||||
if (!path.is_empty()) TRY(editor->load_file(path));
|
if (!path.is_empty()) TRY(editor->load_file(path));
|
||||||
|
|
||||||
TRY(window->add_keyboard_shortcut({ moon::K_CH26, ui::Mod_Ctrl }, true, [&](ui::Shortcut) {
|
TRY(window->add_keyboard_shortcut({ moon::K_CH26, ui::Mod_Ctrl }, true, [&](ui::Shortcut) {
|
||||||
@ -41,7 +40,5 @@ Result<int> luna_main(int argc, char** argv)
|
|||||||
os::println("editor: buffer saved to %s successfully", editor->path().name().chars());
|
os::println("editor: buffer saved to %s successfully", editor->path().name().chars());
|
||||||
}));
|
}));
|
||||||
|
|
||||||
window->draw();
|
|
||||||
|
|
||||||
return app.run();
|
return app.run();
|
||||||
}
|
}
|
||||||
|
@ -9,16 +9,25 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <os/Action.h>
|
#include <os/Action.h>
|
||||||
|
#include <os/File.h>
|
||||||
#include <ui/Widget.h>
|
#include <ui/Widget.h>
|
||||||
|
#include <ui/Window.h>
|
||||||
|
|
||||||
namespace ui
|
namespace ui
|
||||||
{
|
{
|
||||||
class Button : public Widget
|
class Button : public Widget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Button(Rect rect);
|
Button(ui::Window* window, ui::Widget* parent);
|
||||||
|
|
||||||
|
template <typename T> Result<T*> create_child_widget()
|
||||||
|
{
|
||||||
|
auto* widget = TRY(make<T>(window(), this));
|
||||||
|
m_child = widget;
|
||||||
|
window()->recalculate_layout();
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
|
||||||
void set_widget(Widget& widget);
|
|
||||||
void set_action(os::Action&& action);
|
void set_action(os::Action&& action);
|
||||||
|
|
||||||
Result<EventResult> handle_mouse_move(Point position) override;
|
Result<EventResult> handle_mouse_move(Point position) override;
|
||||||
@ -28,10 +37,20 @@ namespace ui
|
|||||||
Result<EventResult> handle_key_event(const ui::KeyEventRequest& request) override;
|
Result<EventResult> handle_key_event(const ui::KeyEventRequest& request) override;
|
||||||
Result<void> draw(Canvas& canvas) override;
|
Result<void> draw(Canvas& canvas) override;
|
||||||
|
|
||||||
|
void recalculate_true_rects() override;
|
||||||
|
void recalculate_pseudo_rects() override;
|
||||||
|
|
||||||
|
void show_tree(int indent) override
|
||||||
|
{
|
||||||
|
os::println("%*s- ui::Button (%d,%d,%d,%d)", indent, "", m_rect.pos.x, m_rect.pos.y, m_rect.width,
|
||||||
|
m_rect.height);
|
||||||
|
if (m_child) m_child->show_tree(indent + 1);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_hovered { false };
|
bool m_hovered { false };
|
||||||
bool m_clicked { false };
|
bool m_clicked { false };
|
||||||
Widget* m_child;
|
Widget* m_child { nullptr };
|
||||||
os::Action m_action;
|
os::Action m_action;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -8,17 +8,31 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <os/File.h>
|
||||||
#include <ui/Alignment.h>
|
#include <ui/Alignment.h>
|
||||||
#include <ui/Widget.h>
|
#include <ui/Widget.h>
|
||||||
|
#include <ui/Window.h>
|
||||||
|
|
||||||
namespace ui
|
namespace ui
|
||||||
{
|
{
|
||||||
class Container : public Widget
|
class Container : public Widget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Container(Rect rect, VerticalAlignment valign, HorizontalAlignment halign);
|
Container(ui::Window* window, ui::Widget* parent);
|
||||||
|
|
||||||
void set_widget(Widget& widget);
|
void set_container_settings(VerticalAlignment valign, HorizontalAlignment halign)
|
||||||
|
{
|
||||||
|
m_valign = valign;
|
||||||
|
m_halign = halign;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> Result<T*> create_child_widget()
|
||||||
|
{
|
||||||
|
auto* widget = TRY(make<T>(window(), this));
|
||||||
|
m_widget = widget;
|
||||||
|
window()->recalculate_layout();
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
|
||||||
Result<EventResult> handle_mouse_move(Point position) override;
|
Result<EventResult> handle_mouse_move(Point position) override;
|
||||||
Result<EventResult> handle_mouse_leave() override;
|
Result<EventResult> handle_mouse_leave() override;
|
||||||
@ -27,9 +41,19 @@ namespace ui
|
|||||||
Result<EventResult> handle_key_event(const ui::KeyEventRequest& request) override;
|
Result<EventResult> handle_key_event(const ui::KeyEventRequest& request) override;
|
||||||
Result<void> draw(Canvas& canvas) override;
|
Result<void> draw(Canvas& canvas) override;
|
||||||
|
|
||||||
|
void recalculate_true_rects() override;
|
||||||
|
void recalculate_pseudo_rects() override;
|
||||||
|
|
||||||
|
void show_tree(int indent) override
|
||||||
|
{
|
||||||
|
os::println("%*s- ui::Container (%d,%d,%d,%d)", indent, "", m_rect.pos.x, m_rect.pos.y, m_rect.width,
|
||||||
|
m_rect.height);
|
||||||
|
if (m_widget) m_widget->show_tree(indent + 1);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Widget* m_widget;
|
Widget* m_widget { nullptr };
|
||||||
VerticalAlignment m_valign;
|
VerticalAlignment m_valign = VerticalAlignment::Center;
|
||||||
HorizontalAlignment m_halign;
|
HorizontalAlignment m_halign = HorizontalAlignment::Center;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <luna/Buffer.h>
|
#include <luna/Buffer.h>
|
||||||
#include <luna/SharedPtr.h>
|
#include <luna/SharedPtr.h>
|
||||||
|
#include <os/File.h>
|
||||||
#include <os/Path.h>
|
#include <os/Path.h>
|
||||||
#include <ui/Widget.h>
|
#include <ui/Widget.h>
|
||||||
|
|
||||||
@ -82,10 +83,20 @@ namespace ui
|
|||||||
class ImageWidget final : public Widget
|
class ImageWidget final : public Widget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static Result<OwnedPtr<ImageWidget>> load(const os::Path& path);
|
ImageWidget(ui::Window* window, ui::Widget* parent);
|
||||||
|
|
||||||
|
Result<void> load(const os::Path& path);
|
||||||
|
|
||||||
Result<void> draw(Canvas& canvas) override;
|
Result<void> draw(Canvas& canvas) override;
|
||||||
|
|
||||||
|
void recalculate_pseudo_rects() override;
|
||||||
|
|
||||||
|
void show_tree(int indent) override
|
||||||
|
{
|
||||||
|
os::println("%*s- ui::Image %dx%d (%d,%d,%d,%d)", indent, "", m_image->width(), m_image->height(),
|
||||||
|
m_rect.pos.x, m_rect.pos.y, m_rect.width, m_rect.height);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SharedPtr<Image> m_image;
|
SharedPtr<Image> m_image;
|
||||||
};
|
};
|
||||||
|
@ -17,7 +17,12 @@ namespace ui
|
|||||||
class InputField : public ui::TextInput
|
class InputField : public ui::TextInput
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
InputField(SharedPtr<ui::Font> font);
|
InputField(Window* window, Widget* parent);
|
||||||
|
|
||||||
|
void set_font(SharedPtr<ui::Font> font)
|
||||||
|
{
|
||||||
|
m_font = font;
|
||||||
|
}
|
||||||
|
|
||||||
Result<ui::EventResult> handle_key_event(const ui::KeyEventRequest& request) override;
|
Result<ui::EventResult> handle_key_event(const ui::KeyEventRequest& request) override;
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <os/File.h>
|
||||||
#include <ui/Alignment.h>
|
#include <ui/Alignment.h>
|
||||||
#include <ui/Font.h>
|
#include <ui/Font.h>
|
||||||
#include <ui/Widget.h>
|
#include <ui/Widget.h>
|
||||||
@ -22,7 +23,7 @@ namespace ui
|
|||||||
class Label final : public Widget
|
class Label final : public Widget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Label(StringView text);
|
Label(Window* window, Widget* parent);
|
||||||
|
|
||||||
void set_alignment(VerticalAlignment valign, HorizontalAlignment halign)
|
void set_alignment(VerticalAlignment valign, HorizontalAlignment halign)
|
||||||
{
|
{
|
||||||
@ -47,6 +48,14 @@ namespace ui
|
|||||||
|
|
||||||
Result<void> draw(Canvas& canvas) override;
|
Result<void> draw(Canvas& canvas) override;
|
||||||
|
|
||||||
|
void recalculate_pseudo_rects() override;
|
||||||
|
|
||||||
|
void show_tree(int indent) override
|
||||||
|
{
|
||||||
|
os::println("%*s- ui::Label '%s' (%d,%d,%d,%d)", indent, "", m_text.chars(), m_rect.pos.x, m_rect.pos.y,
|
||||||
|
m_rect.width, m_rect.height);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StringView m_text;
|
StringView m_text;
|
||||||
VerticalAlignment m_valign = VerticalAlignment::Center;
|
VerticalAlignment m_valign = VerticalAlignment::Center;
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <luna/Vector.h>
|
#include <luna/Vector.h>
|
||||||
|
#include <os/File.h>
|
||||||
#include <ui/Widget.h>
|
#include <ui/Widget.h>
|
||||||
|
|
||||||
namespace ui
|
namespace ui
|
||||||
@ -36,8 +37,16 @@ namespace ui
|
|||||||
class HorizontalLayout final : public Widget
|
class HorizontalLayout final : public Widget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
HorizontalLayout(Margins margins = Margins { 0, 0, 0, 0 }, AdjustHeight adjust_height = AdjustHeight::Yes,
|
HorizontalLayout(ui::Window* window, ui::Widget* parent);
|
||||||
AdjustWidth adjust_width = AdjustWidth::Yes);
|
|
||||||
|
void set_layout_settings(Margins margins = Margins { 0, 0, 0, 0 },
|
||||||
|
AdjustHeight adjust_height = AdjustHeight::Yes,
|
||||||
|
AdjustWidth adjust_width = AdjustWidth::No)
|
||||||
|
{
|
||||||
|
m_margins = margins;
|
||||||
|
m_adjust_height = adjust_height;
|
||||||
|
m_adjust_width = adjust_width;
|
||||||
|
}
|
||||||
|
|
||||||
Result<EventResult> handle_mouse_move(Point position) override;
|
Result<EventResult> handle_mouse_move(Point position) override;
|
||||||
Result<EventResult> handle_mouse_leave() override;
|
Result<EventResult> handle_mouse_leave() override;
|
||||||
@ -47,21 +56,46 @@ namespace ui
|
|||||||
|
|
||||||
Result<void> draw(Canvas& canvas) override;
|
Result<void> draw(Canvas& canvas) override;
|
||||||
|
|
||||||
Result<void> add_widget(Widget& widget);
|
template <typename T> Result<T*> add_child_widget()
|
||||||
|
{
|
||||||
|
auto* widget = TRY(make<T>(window(), this));
|
||||||
|
add_widget(*widget);
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
void recalculate_pseudo_rects() override;
|
||||||
|
void recalculate_true_rects() override;
|
||||||
|
|
||||||
|
void show_tree(int indent) override
|
||||||
|
{
|
||||||
|
os::println("%*s- ui::HorizontalLayout [%zu widgets] (%d,%d,%d,%d)", indent, "", m_widgets.size(),
|
||||||
|
m_rect.pos.x, m_rect.pos.y, m_rect.width, m_rect.height);
|
||||||
|
for (auto* w : m_widgets) { w->show_tree(indent + 1); }
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector<Widget*> m_widgets;
|
Vector<Widget*> m_widgets;
|
||||||
Margins m_margins;
|
Margins m_margins { 0, 0, 0, 0 };
|
||||||
AdjustHeight m_adjust_height;
|
AdjustHeight m_adjust_height = AdjustHeight::Yes;
|
||||||
AdjustWidth m_adjust_width;
|
AdjustWidth m_adjust_width = AdjustWidth::No;
|
||||||
int m_used_width { 0 };
|
int m_used_width { 0 };
|
||||||
|
|
||||||
|
Result<void> add_widget(Widget& widget);
|
||||||
};
|
};
|
||||||
|
|
||||||
class VerticalLayout final : public Widget
|
class VerticalLayout final : public Widget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VerticalLayout(Margins margins = Margins { 0, 0, 0, 0 }, AdjustHeight adjust_height = AdjustHeight::Yes,
|
VerticalLayout(ui::Window* window, ui::Widget* parent);
|
||||||
AdjustWidth adjust_width = AdjustWidth::Yes);
|
|
||||||
|
void set_layout_settings(Margins margins = Margins { 0, 0, 0, 0 },
|
||||||
|
AdjustHeight adjust_height = AdjustHeight::No,
|
||||||
|
AdjustWidth adjust_width = AdjustWidth::Yes)
|
||||||
|
{
|
||||||
|
m_margins = margins;
|
||||||
|
m_adjust_height = adjust_height;
|
||||||
|
m_adjust_width = adjust_width;
|
||||||
|
}
|
||||||
|
|
||||||
Result<EventResult> handle_mouse_move(Point position) override;
|
Result<EventResult> handle_mouse_move(Point position) override;
|
||||||
Result<EventResult> handle_mouse_leave() override;
|
Result<EventResult> handle_mouse_leave() override;
|
||||||
@ -71,13 +105,30 @@ namespace ui
|
|||||||
|
|
||||||
Result<void> draw(Canvas& canvas) override;
|
Result<void> draw(Canvas& canvas) override;
|
||||||
|
|
||||||
Result<void> add_widget(Widget& widget);
|
template <typename T> Result<T*> add_child_widget()
|
||||||
|
{
|
||||||
|
auto* widget = TRY(make<T>(window(), this));
|
||||||
|
add_widget(*widget);
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
void recalculate_pseudo_rects() override;
|
||||||
|
void recalculate_true_rects() override;
|
||||||
|
|
||||||
|
void show_tree(int indent) override
|
||||||
|
{
|
||||||
|
os::println("%*s- ui::VerticalLayout [%zu widgets] (%d,%d,%d,%d)", indent, "", m_widgets.size(),
|
||||||
|
m_rect.pos.x, m_rect.pos.y, m_rect.width, m_rect.height);
|
||||||
|
for (auto* w : m_widgets) { w->show_tree(indent + 1); }
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector<Widget*> m_widgets;
|
Vector<Widget*> m_widgets;
|
||||||
Margins m_margins;
|
Margins m_margins { 0, 0, 0, 0 };
|
||||||
AdjustHeight m_adjust_height;
|
AdjustHeight m_adjust_height = AdjustHeight::No;
|
||||||
AdjustWidth m_adjust_width;
|
AdjustWidth m_adjust_width = AdjustWidth::Yes;
|
||||||
int m_used_height { 0 };
|
int m_used_height { 0 };
|
||||||
|
|
||||||
|
Result<void> add_widget(Widget& widget);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <luna/Buffer.h>
|
#include <luna/Buffer.h>
|
||||||
|
#include <os/File.h>
|
||||||
#include <os/Timer.h>
|
#include <os/Timer.h>
|
||||||
#include <ui/Widget.h>
|
#include <ui/Widget.h>
|
||||||
|
|
||||||
@ -17,12 +18,18 @@ namespace ui
|
|||||||
class TextInput : public Widget
|
class TextInput : public Widget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TextInput();
|
TextInput(Window* window, Widget* parent);
|
||||||
|
|
||||||
virtual Result<ui::EventResult> handle_key_event(const ui::KeyEventRequest& request) = 0;
|
virtual Result<ui::EventResult> handle_key_event(const ui::KeyEventRequest& request) = 0;
|
||||||
|
|
||||||
virtual Result<void> draw(ui::Canvas& canvas) = 0;
|
virtual Result<void> draw(ui::Canvas& canvas) = 0;
|
||||||
|
|
||||||
|
void show_tree(int indent) override
|
||||||
|
{
|
||||||
|
os::println("%*s- ui::TextInput (%d,%d,%d,%d)", indent, "", m_rect.pos.x, m_rect.pos.y, m_rect.width,
|
||||||
|
m_rect.height);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Buffer m_data;
|
Buffer m_data;
|
||||||
|
|
||||||
|
@ -28,6 +28,10 @@ namespace ui
|
|||||||
class Widget
|
class Widget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
Widget(Window* window, Widget* parent) : m_window(window), m_parent(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual Result<EventResult> handle_mouse_move(Point position)
|
virtual Result<EventResult> handle_mouse_move(Point position)
|
||||||
{
|
{
|
||||||
ignore(position);
|
ignore(position);
|
||||||
@ -59,16 +63,14 @@ namespace ui
|
|||||||
|
|
||||||
virtual Result<void> draw(Canvas& canvas);
|
virtual Result<void> draw(Canvas& canvas);
|
||||||
|
|
||||||
void set_window(Window* window, Rect rect, Badge<Window>)
|
void set_rect(Rect rect, Badge<Window>)
|
||||||
{
|
{
|
||||||
m_window = window;
|
|
||||||
m_rect = rect;
|
m_rect = rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_parent(Widget* parent)
|
void resize(Rect rect)
|
||||||
{
|
{
|
||||||
m_parent = parent;
|
m_preferred_rect = rect;
|
||||||
m_window = parent->m_window;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget* parent()
|
Widget* parent()
|
||||||
@ -86,9 +88,36 @@ namespace ui
|
|||||||
return m_rect;
|
return m_rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rect pseudo_rect()
|
||||||
|
{
|
||||||
|
return m_pseudo_rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect preferred_rect()
|
||||||
|
{
|
||||||
|
return m_preferred_rect.value_or({ 0, 0, 50, 50 });
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void recalculate_pseudo_rects()
|
||||||
|
{
|
||||||
|
m_pseudo_rect = preferred_rect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void recalculate_true_rects()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void show_tree(int indent) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Widget* m_parent { nullptr };
|
|
||||||
Window* m_window;
|
Window* m_window;
|
||||||
|
Widget* m_parent { nullptr };
|
||||||
|
|
||||||
|
Option<Rect> m_preferred_rect;
|
||||||
|
|
||||||
|
Rect m_pseudo_rect;
|
||||||
Rect m_rect { 0, 0, 50, 50 };
|
Rect m_rect { 0, 0, 50, 50 };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -8,9 +8,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <luna/Alloc.h>
|
||||||
|
#include <luna/HashMap.h>
|
||||||
#include <luna/OwnedPtr.h>
|
#include <luna/OwnedPtr.h>
|
||||||
#include <luna/String.h>
|
#include <luna/String.h>
|
||||||
#include <luna/StringView.h>
|
#include <luna/StringView.h>
|
||||||
|
#include <os/File.h>
|
||||||
#include <ui/Canvas.h>
|
#include <ui/Canvas.h>
|
||||||
#include <ui/Mouse.h>
|
#include <ui/Mouse.h>
|
||||||
#include <ui/Rect.h>
|
#include <ui/Rect.h>
|
||||||
@ -49,11 +52,13 @@ namespace ui
|
|||||||
m_background = color;
|
m_background = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_main_widget(Widget& widget)
|
template <typename T> Result<T*> create_main_widget()
|
||||||
{
|
{
|
||||||
check(!m_main_widget);
|
check(!m_main_widget);
|
||||||
widget.set_window(this, m_window_canvas.rect(), {});
|
auto* widget = TRY(make<T>(this, nullptr));
|
||||||
m_main_widget = &widget;
|
m_main_widget = widget;
|
||||||
|
widget->set_rect(m_window_canvas.rect(), {});
|
||||||
|
return widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
Canvas& canvas()
|
Canvas& canvas()
|
||||||
@ -75,11 +80,25 @@ namespace ui
|
|||||||
|
|
||||||
Result<void> add_keyboard_shortcut(ui::Shortcut shortcut, bool intercept, os::Function<ui::Shortcut>&& action);
|
Result<void> add_keyboard_shortcut(ui::Shortcut shortcut, bool intercept, os::Function<ui::Shortcut>&& action);
|
||||||
|
|
||||||
|
void recalculate_layout()
|
||||||
|
{
|
||||||
|
check(m_main_widget);
|
||||||
|
m_main_widget->recalculate_pseudo_rects();
|
||||||
|
m_main_widget->recalculate_true_rects();
|
||||||
|
}
|
||||||
|
|
||||||
int id() const
|
int id() const
|
||||||
{
|
{
|
||||||
return m_id;
|
return m_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void show_tree()
|
||||||
|
{
|
||||||
|
os::println("- ui::Window %d (%d,%d,%d,%d)", m_id, m_canvas.rect().pos.x, m_canvas.rect().pos.y,
|
||||||
|
m_canvas.rect().width, m_canvas.rect().height);
|
||||||
|
m_main_widget->show_tree(1);
|
||||||
|
}
|
||||||
|
|
||||||
~Window();
|
~Window();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -12,16 +12,26 @@
|
|||||||
|
|
||||||
namespace ui
|
namespace ui
|
||||||
{
|
{
|
||||||
Button::Button(Rect rect)
|
Button::Button(Window* window, Widget* parent) : ui::Widget(window, parent)
|
||||||
{
|
{
|
||||||
m_rect = rect;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Button::set_widget(Widget& widget)
|
void Button::recalculate_true_rects()
|
||||||
{
|
{
|
||||||
widget.rect() = m_rect;
|
if (!m_child) return;
|
||||||
m_child = &widget;
|
m_child->rect() = m_rect;
|
||||||
widget.set_parent(this);
|
m_child->recalculate_true_rects();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Button::recalculate_pseudo_rects()
|
||||||
|
{
|
||||||
|
if (m_child)
|
||||||
|
{
|
||||||
|
m_child->recalculate_pseudo_rects();
|
||||||
|
m_pseudo_rect = m_child->pseudo_rect();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_preferred_rect.has_value()) m_pseudo_rect = m_preferred_rect.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Button::set_action(os::Action&& action)
|
void Button::set_action(os::Action&& action)
|
||||||
|
@ -11,17 +11,22 @@
|
|||||||
|
|
||||||
namespace ui
|
namespace ui
|
||||||
{
|
{
|
||||||
Container::Container(Rect rect, VerticalAlignment valign, HorizontalAlignment halign)
|
Container::Container(Window* window, Widget* parent) : ui::Widget(window, parent)
|
||||||
: m_valign(valign), m_halign(halign)
|
|
||||||
{
|
{
|
||||||
m_rect = rect;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Container::set_widget(Widget& widget)
|
void Container::recalculate_true_rects()
|
||||||
{
|
{
|
||||||
m_widget = &widget;
|
if (!m_widget) return;
|
||||||
widget.rect() = ui::align(m_rect, widget.rect(), m_valign, m_halign);
|
m_widget->rect() = ui::align(m_rect, m_widget->pseudo_rect(), m_valign, m_halign);
|
||||||
widget.set_parent(this);
|
m_widget->recalculate_true_rects();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Container::recalculate_pseudo_rects()
|
||||||
|
{
|
||||||
|
if (m_widget) m_widget->recalculate_pseudo_rects();
|
||||||
|
|
||||||
|
m_pseudo_rect = preferred_rect();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<EventResult> Container::handle_mouse_move(Point position)
|
Result<EventResult> Container::handle_mouse_move(Point position)
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <os/File.h>
|
#include <os/File.h>
|
||||||
#include <ui/Alignment.h>
|
#include <ui/Alignment.h>
|
||||||
#include <ui/Image.h>
|
#include <ui/Image.h>
|
||||||
|
#include <ui/Window.h>
|
||||||
|
|
||||||
namespace ui
|
namespace ui
|
||||||
{
|
{
|
||||||
@ -32,17 +33,28 @@ namespace ui
|
|||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<OwnedPtr<ImageWidget>> ImageWidget::load(const os::Path& path)
|
ImageWidget::ImageWidget(Window* window, Widget* parent) : ui::Widget(window, parent)
|
||||||
{
|
{
|
||||||
auto widget = TRY(make_owned<ImageWidget>());
|
}
|
||||||
widget->m_image = TRY(Image::load(path));
|
|
||||||
widget->m_rect = { 0, 0, widget->m_image->width(), widget->m_image->height() };
|
Result<void> ImageWidget::load(const os::Path& path)
|
||||||
return widget;
|
{
|
||||||
|
m_image = TRY(Image::load(path));
|
||||||
|
window()->recalculate_layout();
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<void> ImageWidget::draw(Canvas& canvas)
|
Result<void> ImageWidget::draw(Canvas& canvas)
|
||||||
{
|
{
|
||||||
|
if (!m_image) return {};
|
||||||
canvas.subcanvas({ 0, 0, m_image->width(), m_image->height() }).fill(m_image->pixels(), m_image->width());
|
canvas.subcanvas({ 0, 0, m_image->width(), m_image->height() }).fill(m_image->pixels(), m_image->width());
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ImageWidget::recalculate_pseudo_rects()
|
||||||
|
{
|
||||||
|
if (m_preferred_rect.has_value()) m_pseudo_rect = m_preferred_rect.value();
|
||||||
|
|
||||||
|
if (m_image) m_pseudo_rect = ui::Rect { 0, 0, m_image->width(), m_image->height() };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
|
|
||||||
namespace ui
|
namespace ui
|
||||||
{
|
{
|
||||||
InputField::InputField(SharedPtr<ui::Font> font) : ui::TextInput(), m_font(font)
|
InputField::InputField(Window* window, Widget* parent)
|
||||||
|
: ui::TextInput(window, parent), m_font(ui::Font::default_font())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
namespace ui
|
namespace ui
|
||||||
{
|
{
|
||||||
Label::Label(StringView text) : m_text(text)
|
Label::Label(Window* window, Widget* parent) : Widget(window, parent), m_text()
|
||||||
{
|
{
|
||||||
m_font = ui::Font::default_font();
|
m_font = ui::Font::default_font();
|
||||||
}
|
}
|
||||||
@ -33,4 +33,14 @@ namespace ui
|
|||||||
m_font->render(buf, m_color, subcanvas);
|
m_font->render(buf, m_color, subcanvas);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Label::recalculate_pseudo_rects()
|
||||||
|
{
|
||||||
|
if (m_preferred_rect.has_value()) m_pseudo_rect = m_preferred_rect.value();
|
||||||
|
|
||||||
|
int height = m_font->height();
|
||||||
|
int width = m_font->width() * (int)m_text.length();
|
||||||
|
|
||||||
|
m_pseudo_rect = { 0, 0, width, height };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,11 +9,11 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <ui/Layout.h>
|
#include <ui/Layout.h>
|
||||||
|
#include <ui/Window.h>
|
||||||
|
|
||||||
namespace ui
|
namespace ui
|
||||||
{
|
{
|
||||||
HorizontalLayout::HorizontalLayout(Margins margins, AdjustHeight adjust_height, AdjustWidth adjust_width)
|
HorizontalLayout::HorizontalLayout(Window* window, Widget* parent) : ui::Widget(window, parent)
|
||||||
: m_margins(margins), m_adjust_height(adjust_height), m_adjust_width(adjust_width)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,38 +93,85 @@ namespace ui
|
|||||||
{
|
{
|
||||||
TRY(m_widgets.try_append(&widget));
|
TRY(m_widgets.try_append(&widget));
|
||||||
|
|
||||||
if (m_adjust_width == AdjustWidth::No)
|
window()->recalculate_layout();
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void HorizontalLayout::recalculate_pseudo_rects()
|
||||||
|
{
|
||||||
|
int min_height = 0;
|
||||||
|
int width = 0;
|
||||||
|
|
||||||
|
for (auto w : m_widgets)
|
||||||
{
|
{
|
||||||
widget.rect().pos.x = m_rect.pos.x + m_used_width + m_margins.left;
|
w->recalculate_pseudo_rects();
|
||||||
m_used_width += m_margins.left + widget.rect().width + m_margins.right;
|
if (w->pseudo_rect().height > min_height) min_height = w->pseudo_rect().height;
|
||||||
|
width += (m_margins.left + w->pseudo_rect().width + m_margins.right);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
min_height += (m_margins.top + m_margins.bottom);
|
||||||
|
|
||||||
|
m_pseudo_rect = { 0, 0, width, min_height };
|
||||||
|
|
||||||
|
if (m_preferred_rect.has_value()) m_pseudo_rect = m_preferred_rect.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HorizontalLayout::recalculate_true_rects()
|
||||||
|
{
|
||||||
|
if (m_adjust_width == AdjustWidth::Yes)
|
||||||
{
|
{
|
||||||
int used_width = 0;
|
int used_width = 0;
|
||||||
div_t result = div(m_rect.width, (int)m_widgets.size());
|
div_t result = div(m_rect.width, (int)m_widgets.size());
|
||||||
for (auto w : m_widgets)
|
for (auto w : m_widgets)
|
||||||
{
|
{
|
||||||
w->rect().pos.x = m_rect.pos.x + used_width + m_margins.left;
|
w->rect().pos.x = m_rect.pos.x + used_width + m_margins.left;
|
||||||
|
w->rect().pos.y = m_rect.pos.y + m_margins.top;
|
||||||
w->rect().width = result.quot - (m_margins.left + m_margins.right);
|
w->rect().width = result.quot - (m_margins.left + m_margins.right);
|
||||||
|
|
||||||
|
if (m_adjust_height == AdjustHeight::Yes)
|
||||||
|
{
|
||||||
|
w->rect().height = m_rect.height - (m_margins.top + m_margins.bottom);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
w->rect().height = w->pseudo_rect().height;
|
||||||
|
|
||||||
used_width += result.quot;
|
used_width += result.quot;
|
||||||
|
|
||||||
|
w->recalculate_true_rects();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.rem != 0 && m_widgets.size())
|
||||||
|
{
|
||||||
|
auto* last = m_widgets[m_widgets.size() - 1];
|
||||||
|
last->rect().width += result.rem;
|
||||||
|
last->recalculate_true_rects();
|
||||||
}
|
}
|
||||||
m_widgets[m_widgets.size() - 1]->rect().width += result.rem;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
widget.rect().pos.y = m_rect.pos.y + m_margins.top;
|
|
||||||
|
|
||||||
if (m_adjust_height == AdjustHeight::Yes)
|
|
||||||
{
|
{
|
||||||
widget.rect().height = m_rect.height - (m_margins.top + m_margins.bottom);
|
int used_width = 0;
|
||||||
|
for (auto w : m_widgets)
|
||||||
|
{
|
||||||
|
w->rect() = w->pseudo_rect();
|
||||||
|
w->rect().pos.x = m_rect.pos.x + used_width + m_margins.left;
|
||||||
|
w->rect().pos.y = m_rect.pos.y + m_margins.top;
|
||||||
|
|
||||||
|
if (m_adjust_height == AdjustHeight::Yes)
|
||||||
|
{
|
||||||
|
w->rect().height = m_rect.height - (m_margins.top + m_margins.bottom);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
w->rect().height = w->pseudo_rect().height;
|
||||||
|
|
||||||
|
used_width += (m_margins.left + m_margins.right + w->rect().width);
|
||||||
|
|
||||||
|
w->recalculate_true_rects();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
widget.set_parent(this);
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VerticalLayout::VerticalLayout(Margins margins, AdjustHeight adjust_height, AdjustWidth adjust_width)
|
VerticalLayout::VerticalLayout(Window* window, Widget* parent) : ui::Widget(window, parent)
|
||||||
: m_margins(margins), m_adjust_height(adjust_height), m_adjust_width(adjust_width)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,36 +247,84 @@ namespace ui
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<void> VerticalLayout::add_widget(Widget& widget)
|
void VerticalLayout::recalculate_pseudo_rects()
|
||||||
{
|
{
|
||||||
TRY(m_widgets.try_append(&widget));
|
int min_width = 0;
|
||||||
|
int height = 0;
|
||||||
|
|
||||||
if (m_adjust_height == AdjustHeight::No)
|
for (auto w : m_widgets)
|
||||||
{
|
{
|
||||||
widget.rect().pos.y = m_rect.pos.y + m_used_height + m_margins.top;
|
w->recalculate_pseudo_rects();
|
||||||
m_used_height += m_margins.top + widget.rect().height + m_margins.bottom;
|
if (w->pseudo_rect().width > min_width) min_width = w->pseudo_rect().width;
|
||||||
|
height += (m_margins.top + w->pseudo_rect().height + m_margins.bottom);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
min_width += (m_margins.left + m_margins.right);
|
||||||
|
|
||||||
|
m_pseudo_rect = { 0, 0, min_width, height };
|
||||||
|
|
||||||
|
if (m_preferred_rect.has_value()) m_pseudo_rect = m_preferred_rect.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerticalLayout::recalculate_true_rects()
|
||||||
|
{
|
||||||
|
if (m_adjust_height == AdjustHeight::Yes)
|
||||||
{
|
{
|
||||||
int used_height = 0;
|
int used_height = 0;
|
||||||
div_t result = div(m_rect.height, (int)m_widgets.size());
|
div_t result = div(m_rect.height, (int)m_widgets.size());
|
||||||
for (auto w : m_widgets)
|
for (auto w : m_widgets)
|
||||||
{
|
{
|
||||||
w->rect().pos.y = m_rect.pos.y + used_height + m_margins.top;
|
w->rect().pos.y = m_rect.pos.y + used_height + m_margins.top;
|
||||||
|
w->rect().pos.x = m_rect.pos.x + m_margins.left;
|
||||||
w->rect().height = result.quot - (m_margins.top + m_margins.bottom);
|
w->rect().height = result.quot - (m_margins.top + m_margins.bottom);
|
||||||
|
|
||||||
|
if (m_adjust_width == AdjustWidth::Yes)
|
||||||
|
{
|
||||||
|
w->rect().width = m_rect.width - (m_margins.left + m_margins.right);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
w->rect().width = w->pseudo_rect().width;
|
||||||
|
|
||||||
used_height += result.quot;
|
used_height += result.quot;
|
||||||
|
|
||||||
|
w->recalculate_true_rects();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.rem != 0 && m_widgets.size())
|
||||||
|
{
|
||||||
|
auto* last = m_widgets[m_widgets.size() - 1];
|
||||||
|
last->rect().height += result.rem;
|
||||||
|
last->recalculate_true_rects();
|
||||||
}
|
}
|
||||||
m_widgets[m_widgets.size() - 1]->rect().height += result.rem;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
widget.rect().pos.x = m_rect.pos.x + m_margins.left;
|
|
||||||
|
|
||||||
if (m_adjust_width == AdjustWidth::Yes)
|
|
||||||
{
|
{
|
||||||
widget.rect().width = m_rect.width - (m_margins.left + m_margins.right);
|
int used_height = 0;
|
||||||
}
|
for (auto w : m_widgets)
|
||||||
|
{
|
||||||
|
w->rect() = w->pseudo_rect();
|
||||||
|
w->rect().pos.y = m_rect.pos.y + used_height + m_margins.top;
|
||||||
|
w->rect().pos.x = m_rect.pos.x + m_margins.left;
|
||||||
|
|
||||||
widget.set_parent(this);
|
if (m_adjust_width == AdjustWidth::Yes)
|
||||||
|
{
|
||||||
|
w->rect().width = m_rect.width - (m_margins.left + m_margins.right);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
w->rect().width = w->pseudo_rect().width;
|
||||||
|
|
||||||
|
used_height += (m_margins.top + m_margins.bottom + w->rect().height);
|
||||||
|
|
||||||
|
w->recalculate_true_rects();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<void> VerticalLayout::add_widget(Widget& widget)
|
||||||
|
{
|
||||||
|
TRY(m_widgets.try_append(&widget));
|
||||||
|
|
||||||
|
window()->recalculate_layout();
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
namespace ui
|
namespace ui
|
||||||
{
|
{
|
||||||
TextInput::TextInput() : Widget()
|
TextInput::TextInput(Window* window, Widget* parent) : Widget(window, parent)
|
||||||
{
|
{
|
||||||
m_cursor_timer = os::Timer::create_repeating(500, [this]() { this->tick_cursor(); }).release_value();
|
m_cursor_timer = os::Timer::create_repeating(500, [this]() { this->tick_cursor(); }).release_value();
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,10 @@ static void sigchld_handler(int)
|
|||||||
ui::App::the().set_should_close(true);
|
ui::App::the().set_should_close(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TerminalWidget::TerminalWidget(ui::Window* window, ui::Widget* parent) : ui::Widget(window, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Result<void> TerminalWidget::init(char* const* args)
|
Result<void> TerminalWidget::init(char* const* args)
|
||||||
{
|
{
|
||||||
m_font = ui::Font::default_font();
|
m_font = ui::Font::default_font();
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include <luna/EscapeSequence.h>
|
#include <luna/EscapeSequence.h>
|
||||||
#include <luna/Utf8.h>
|
#include <luna/Utf8.h>
|
||||||
#include <luna/Vector.h>
|
#include <luna/Vector.h>
|
||||||
|
#include <os/File.h>
|
||||||
#include <os/Timer.h>
|
#include <os/Timer.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
@ -11,12 +12,20 @@
|
|||||||
class TerminalWidget : public ui::Widget
|
class TerminalWidget : public ui::Widget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
TerminalWidget(ui::Window* window, ui::Widget* parent);
|
||||||
|
|
||||||
Result<void> init(char* const* args);
|
Result<void> init(char* const* args);
|
||||||
|
|
||||||
Result<ui::EventResult> handle_key_event(const ui::KeyEventRequest& request) override;
|
Result<ui::EventResult> handle_key_event(const ui::KeyEventRequest& request) override;
|
||||||
|
|
||||||
Result<void> draw(ui::Canvas& canvas) override;
|
Result<void> draw(ui::Canvas& canvas) override;
|
||||||
|
|
||||||
|
void show_tree(int indent) override
|
||||||
|
{
|
||||||
|
os::println("%*s- TerminalWidget (%d,%d,%d,%d)", indent, "", m_rect.pos.x, m_rect.pos.y, m_rect.width,
|
||||||
|
m_rect.height);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ui::Canvas m_terminal_canvas;
|
ui::Canvas m_terminal_canvas;
|
||||||
Vector<u8> m_line_buffer;
|
Vector<u8> m_line_buffer;
|
||||||
|
@ -12,13 +12,10 @@ Result<int> luna_main(int, char**)
|
|||||||
app.set_main_window(window);
|
app.set_main_window(window);
|
||||||
window->set_title("Terminal");
|
window->set_title("Terminal");
|
||||||
|
|
||||||
TerminalWidget terminal;
|
auto* terminal = TRY(window->create_main_widget<TerminalWidget>());
|
||||||
window->set_main_widget(terminal);
|
|
||||||
|
|
||||||
char* args[] = { "/bin/sh", nullptr };
|
char* args[] = { "/bin/sh", nullptr };
|
||||||
TRY(terminal.init(args));
|
TRY(terminal->init(args));
|
||||||
|
|
||||||
window->draw();
|
|
||||||
|
|
||||||
return app.run();
|
return app.run();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user