Add a display server and graphical user interface #38

Merged
apio merged 103 commits from display-server into main 2023-09-20 18:49:21 +00:00
8 changed files with 183 additions and 0 deletions
Showing only changes of commit 35c7011997 - Show all commits

View File

@ -1,4 +1,6 @@
#include <ui/App.h>
#include <ui/Container.h>
#include <ui/Image.h>
#include <ui/Layout.h>
Result<int> luna_main(int argc, char** argv)
@ -17,6 +19,12 @@ Result<int> luna_main(int argc, char** argv)
ui::HorizontalLayout layout(ui::AdjustHeight::Yes, ui::AdjustWidth::No);
window->set_main_widget(layout);
ui::Container container({ 0, 0, 50, 50 }, ui::VerticalAlignment::Center, ui::HorizontalAlignment::Center);
layout.add_widget(container);
auto image = TRY(ui::ImageWidget::load("/usr/share/icons/32x32/start-icon.tga"));
container.set_widget(*image);
window->draw();
return app.run();

View File

@ -13,6 +13,8 @@ set(SOURCES
src/App.cpp
src/Window.cpp
src/Layout.cpp
src/Alignment.cpp
src/Container.cpp
)
add_library(ui ${SOURCES})

View File

@ -0,0 +1,30 @@
/**
* @file Alignment.h
* @author apio (cloudapio.eu)
* @brief UI component alignment.
*
* @copyright Copyright (c) 2023, the Luna authors.
*
*/
#pragma once
#include <ui/Rect.h>
namespace ui
{
enum class VerticalAlignment
{
Top,
Center,
Bottom
};
enum class HorizontalAlignment
{
Left,
Center,
Right
};
Rect align(Rect container, Rect contained, VerticalAlignment valign, HorizontalAlignment halign);
}

View File

@ -0,0 +1,31 @@
/**
* @file Container.h
* @author apio (cloudapio.eu)
* @brief A container widget to pad and align objects inside it.
*
* @copyright Copyright (c) 2023, the Luna authors.
*
*/
#pragma once
#include <ui/Alignment.h>
#include <ui/Widget.h>
namespace ui
{
class Container : public Widget
{
public:
Container(Rect rect, VerticalAlignment valign, HorizontalAlignment halign);
void set_widget(Widget& widget);
Result<EventResult> handle_mousemove(Point position) override;
Result<void> draw(Canvas& canvas) override;
private:
Widget* m_widget;
VerticalAlignment m_valign;
HorizontalAlignment m_halign;
};
}

View File

@ -11,6 +11,7 @@
#include <luna/Buffer.h>
#include <luna/SharedPtr.h>
#include <os/Path.h>
#include <ui/Widget.h>
namespace ui
{
@ -77,4 +78,16 @@ namespace ui
TGAHeader m_tga_header;
Buffer m_image_data;
};
class ImageWidget final : public Widget
{
public:
static Result<OwnedPtr<ImageWidget>> load(const os::Path& path);
Result<EventResult> handle_mousemove(Point position) override;
Result<void> draw(Canvas& canvas) override;
private:
SharedPtr<Image> m_image;
};
}

40
libui/src/Alignment.cpp Normal file
View File

@ -0,0 +1,40 @@
/**
* @file Alignment.cpp
* @author apio (cloudapio.eu)
* @brief UI component alignment.
*
* @copyright Copyright (c) 2023, the Luna authors.
*
*/
#include <ui/Alignment.h>
namespace ui
{
Rect align(Rect container, Rect contained, VerticalAlignment valign, HorizontalAlignment halign)
{
Rect result;
result.width = contained.width;
result.height = contained.height;
result.pos.y = container.pos.y;
result.pos.x = container.pos.x;
switch (valign)
{
case VerticalAlignment::Top: break;
case VerticalAlignment::Center: result.pos.y += (container.height - contained.height) / 2; break;
case VerticalAlignment::Bottom: result.pos.y += container.height - contained.height; break;
default: break;
}
switch (halign)
{
case HorizontalAlignment::Left: break;
case HorizontalAlignment::Center: result.pos.x += (container.width - contained.width) / 2; break;
case HorizontalAlignment::Right: result.pos.x += container.width - contained.width; break;
default: break;
}
return result;
}
}

39
libui/src/Container.cpp Normal file
View File

@ -0,0 +1,39 @@
/**
* @file Container.cpp
* @author apio (cloudapio.eu)
* @brief A container widget to pad and align objects inside it.
*
* @copyright Copyright (c) 2023, the Luna authors.
*
*/
#include <ui/Container.h>
namespace ui
{
Container::Container(Rect rect, VerticalAlignment valign, HorizontalAlignment halign)
: m_valign(valign), m_halign(halign)
{
m_rect = rect;
}
void Container::set_widget(Widget& widget)
{
m_widget = &widget;
widget.rect() = ui::align(m_rect, widget.rect(), m_valign, m_halign);
}
Result<EventResult> Container::handle_mousemove(Point position)
{
return m_widget->handle_mousemove(position);
}
Result<void> Container::draw(Canvas& canvas)
{
auto rect = ui::Rect { m_widget->rect().pos.x - m_rect.pos.x, m_widget->rect().pos.y - m_rect.pos.y,
m_widget->rect().width, m_widget->rect().height };
auto subcanvas = canvas.subcanvas(rect);
return m_widget->draw(subcanvas);
}
}

View File

@ -8,6 +8,7 @@
*/
#include <os/File.h>
#include <ui/Alignment.h>
#include <ui/Image.h>
namespace ui
@ -30,4 +31,23 @@ namespace ui
return image;
}
Result<OwnedPtr<ImageWidget>> ImageWidget::load(const os::Path& path)
{
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() };
return widget;
}
Result<EventResult> ImageWidget::handle_mousemove(Point)
{
return EventResult::DidNotHandle;
}
Result<void> ImageWidget::draw(Canvas& canvas)
{
canvas.subcanvas({ 0, 0, m_image->width(), m_image->height() }).fill(m_image->pixels(), m_image->width());
return {};
}
}