add very basic layout system
This commit is contained in:
parent
9efac54ffa
commit
4401b7b5b2
10 changed files with 118 additions and 13 deletions
|
@ -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]
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -5,6 +5,7 @@ namespace Raven {
|
|||
class Painter;
|
||||
class Point;
|
||||
class TopLevelStyles;
|
||||
class Layout;
|
||||
class Widget;
|
||||
class Window;
|
||||
|
||||
|
|
|
@ -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
29
src/Layout.cpp
Normal 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
14
src/Layout.hpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include "Forward.hpp"
|
||||
|
||||
namespace Raven {
|
||||
|
||||
class Layout {
|
||||
public:
|
||||
Layout() {}
|
||||
|
||||
void run_on(Widget *target);
|
||||
};
|
||||
|
||||
}
|
|
@ -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(); }
|
||||
};
|
||||
|
||||
}
|
|
@ -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));
|
||||
|
|
|
@ -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) {}
|
||||
|
|
13
src/main.cpp
13
src/main.cpp
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue