add very basic layout system

This commit is contained in:
hippoz 2022-03-30 14:49:31 +03:00
parent 9efac54ffa
commit 4401b7b5b2
No known key found for this signature in database
GPG key ID: 7C52899193467641
10 changed files with 118 additions and 13 deletions

View file

@ -11,6 +11,7 @@ executable(
'./src/Window.cpp',
'./src/Widget.cpp',
'./src/Button.cpp',
'./src/Layout.cpp',
'./src/Label.cpp',
'./src/main.cpp',
dependencies : [cairomm_dep, xlib_dep, pangocairo_dep]

View file

@ -22,6 +22,8 @@ public:
std::function<void()> on_click { [](){} };
protected:
WidgetType m_type { WidgetType::Button };
void on_paint();
void on_init();
void on_focus_update(FocusUpdateEvent &event);

View file

@ -5,6 +5,7 @@ namespace Raven {
class Painter;
class Point;
class TopLevelStyles;
class Layout;
class Widget;
class Window;

View file

@ -18,6 +18,8 @@ public:
std::string &get_text() { return m_text; }
void set_text(std::string text) { m_text = text; wants_repaint(); }
protected:
WidgetType m_type { WidgetType::Label };
void on_paint();
void on_init();
};

29
src/Layout.cpp Normal file
View file

@ -0,0 +1,29 @@
#include <iostream>
#include "Layout.hpp"
#include "Point.hpp"
#include "Box.hpp"
#include "Widget.hpp"
namespace Raven {
void Layout::run_on(Widget *target) {
Point point { target->get_current_geometry().get_x(), target->get_current_geometry().get_y() };
double row_largest_height = 0.0;
auto children = target->get_children();
for (auto& c : children) {
if (c->get_control_type() == ControlWidgetType::NewRow && row_largest_height) {
point.add(0, row_largest_height);
row_largest_height = 0.0;
point.set_x(0);
}
if (c->get_current_geometry().get_height() > row_largest_height) {
row_largest_height = c->get_current_geometry().get_height();
}
auto new_geometry = Box{ point.get_x(), point.get_y(), c->get_current_geometry().get_width(), c->get_current_geometry().get_height() };
c->set_current_geometry(std::move(new_geometry));
point.add(c->get_current_geometry().get_width(), 0);
}
}
}

14
src/Layout.hpp Normal file
View file

@ -0,0 +1,14 @@
#pragma once
#include "Forward.hpp"
namespace Raven {
class Layout {
public:
Layout() {}
void run_on(Widget *target);
};
}

View file

@ -4,20 +4,23 @@ namespace Raven {
class Point {
private:
int m_x;
int m_y;
double m_x;
double m_y;
public:
Point(int x, int y)
Point(double x, double y)
: m_x(x)
, m_y(y) {}
int get_x() { return m_x; }
const int get_x() const { return m_x; }
int get_y() { return m_y; }
const int get_y() const { return m_y; }
double get_x() { return m_x; }
const double get_x() const { return m_x; }
double get_y() { return m_y; }
const double get_y() const { return m_y; }
void set_x(int x) { m_x = x; }
void set_y(int y) { m_y = y; }
void set_x(double x) { m_x = x; }
void set_y(double y) { m_y = y; }
void add(double x, double y) { m_x += x; m_y += y; }
void add(Point const& other) { m_x += other.get_x(); m_y += other.get_y(); }
};
}

View file

@ -3,9 +3,16 @@
#include "Widget.hpp"
#include "Events.hpp"
#include "Window.hpp"
#include "Layout.hpp"
namespace Raven {
void Widget::do_layout() {
if (m_layout) {
m_layout->run_on(this);
}
}
void Widget::set_window(Window *window) {
m_window = window;
m_styles = m_window->get_top_level_styles();
@ -22,6 +29,7 @@ bool Widget::add_child(Widget *child) {
// children inherit the window from the parent
// TODO?: what happens when the parent changes its window?
child->set_window(m_window);
do_layout();
return true;
}
@ -132,6 +140,9 @@ void Widget::handle_mouse_button_event(MouseButtonEvent &event) {
}
void Widget::dispatch_event(Event &event) {
if (!m_accepts_events)
return;
switch (event.get_type()) {
case EventType::MouseMove: {
handle_mouse_move_event(reinterpret_cast<MouseMoveEvent&>(event));

View file

@ -12,6 +12,18 @@
namespace Raven {
enum class WidgetType {
Widget = 0,
Button,
Label,
Control
};
enum class ControlWidgetType {
Widget = 0,
NewRow
};
class Widget {
DEF_WIDGET_STYLE_PROP(do_background_fill, bool, false)
@ -20,18 +32,28 @@ DEF_WIDGET_STYLE_PROP(background_border_radius, double, 0.0)
private:
Box m_current_geometry {};
Box m_current_geometry { 0, 0, 0, 0 };
std::vector<Widget*> m_children;
Widget *m_parent { nullptr };
Window *m_window { nullptr };
std::shared_ptr<TopLevelStyles> m_styles = nullptr;
Layout *m_layout { nullptr };
bool m_did_init { false };
bool m_is_focused { false };
bool m_is_active { false };
bool m_consumes_hits { false };
bool m_accepts_events { true };
ControlWidgetType m_control_type { ControlWidgetType::Widget };
public:
Widget() {}
Widget(ControlWidgetType type)
: m_control_type(type) {
m_type = WidgetType::Control;
m_control_type = type;
m_accepts_events = false;
}
Box &get_current_geometry() { return m_current_geometry; }
void set_current_geometry(Box current_geometry) { m_current_geometry = current_geometry; wants_repaint(); }
@ -58,13 +80,24 @@ public:
bool get_consumes_hits() { return m_consumes_hits; }
void set_consumes_hits(bool consumes_hits) { m_consumes_hits = consumes_hits; }
bool get_accepts_events() { return m_accepts_events; }
void set_accepts_events(bool accepts_events) { m_accepts_events = accepts_events; }
void set_layout(Layout *layout) { m_layout = layout; }
Layout *get_layout() { return m_layout; }
WidgetType get_type() { return m_type; }
ControlWidgetType get_control_type() { return m_control_type; }
void dispatch_event(Event &event);
void wants_repaint();
void wants_full_repaint();
void do_layout();
virtual ~Widget() {};
protected:
WidgetType m_type { WidgetType::Widget };
virtual void on_init();
virtual void on_mouse_button(MouseButtonEvent &event) {}
virtual void on_mouse_move(MouseMoveEvent &event) {}

View file

@ -4,19 +4,26 @@
#include "Button.hpp"
#include "Box.hpp"
#include "Label.hpp"
#include "Layout.hpp"
int main() {
Raven::Layout main_layout {};
Raven::Widget new_row { Raven::ControlWidgetType::NewRow };
Raven::Window window {};
Raven::Widget main_widget {};
Raven::Button button {"click meeeeeeeeeeee"};
Raven::Button impostor_button {"other button"};
Raven::Label label {"click it!"};
int times_clicked = 0;
window.spawn_window();
button.set_current_geometry(Raven::Box(10, 10, 100, 30));
label.set_current_geometry(Raven::Box(10, 45, 100, 20));
button.set_current_geometry(Raven::Box(0, 0, 100, 30));
impostor_button.set_current_geometry(Raven::Box(0, 0, 100, 30));
label.set_current_geometry(Raven::Box(0, 0, 100, 20));
main_widget.set_layout(&main_layout);
window.set_main_widget(&main_widget);
button.on_click = [&]() {
@ -26,6 +33,8 @@ int main() {
main_widget.add_child(&button);
main_widget.add_child(&label);
main_widget.add_child(&new_row);
main_widget.add_child(&impostor_button);
window.run(true);