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/Window.cpp',
|
||||||
'./src/Widget.cpp',
|
'./src/Widget.cpp',
|
||||||
'./src/Button.cpp',
|
'./src/Button.cpp',
|
||||||
|
'./src/Layout.cpp',
|
||||||
'./src/Label.cpp',
|
'./src/Label.cpp',
|
||||||
'./src/main.cpp',
|
'./src/main.cpp',
|
||||||
dependencies : [cairomm_dep, xlib_dep, pangocairo_dep]
|
dependencies : [cairomm_dep, xlib_dep, pangocairo_dep]
|
||||||
|
|
|
@ -22,6 +22,8 @@ public:
|
||||||
|
|
||||||
std::function<void()> on_click { [](){} };
|
std::function<void()> on_click { [](){} };
|
||||||
protected:
|
protected:
|
||||||
|
WidgetType m_type { WidgetType::Button };
|
||||||
|
|
||||||
void on_paint();
|
void on_paint();
|
||||||
void on_init();
|
void on_init();
|
||||||
void on_focus_update(FocusUpdateEvent &event);
|
void on_focus_update(FocusUpdateEvent &event);
|
||||||
|
|
|
@ -5,6 +5,7 @@ namespace Raven {
|
||||||
class Painter;
|
class Painter;
|
||||||
class Point;
|
class Point;
|
||||||
class TopLevelStyles;
|
class TopLevelStyles;
|
||||||
|
class Layout;
|
||||||
class Widget;
|
class Widget;
|
||||||
class Window;
|
class Window;
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ public:
|
||||||
std::string &get_text() { return m_text; }
|
std::string &get_text() { return m_text; }
|
||||||
void set_text(std::string text) { m_text = text; wants_repaint(); }
|
void set_text(std::string text) { m_text = text; wants_repaint(); }
|
||||||
protected:
|
protected:
|
||||||
|
WidgetType m_type { WidgetType::Label };
|
||||||
|
|
||||||
void on_paint();
|
void on_paint();
|
||||||
void on_init();
|
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 {
|
class Point {
|
||||||
private:
|
private:
|
||||||
int m_x;
|
double m_x;
|
||||||
int m_y;
|
double m_y;
|
||||||
public:
|
public:
|
||||||
Point(int x, int y)
|
Point(double x, double y)
|
||||||
: m_x(x)
|
: m_x(x)
|
||||||
, m_y(y) {}
|
, m_y(y) {}
|
||||||
|
|
||||||
int get_x() { return m_x; }
|
double get_x() { return m_x; }
|
||||||
const int get_x() const { return m_x; }
|
const double get_x() const { return m_x; }
|
||||||
int get_y() { return m_y; }
|
double get_y() { return m_y; }
|
||||||
const int get_y() const { return m_y; }
|
const double get_y() const { return m_y; }
|
||||||
|
|
||||||
void set_x(int x) { m_x = x; }
|
void set_x(double x) { m_x = x; }
|
||||||
void set_y(int y) { m_y = y; }
|
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 "Widget.hpp"
|
||||||
#include "Events.hpp"
|
#include "Events.hpp"
|
||||||
#include "Window.hpp"
|
#include "Window.hpp"
|
||||||
|
#include "Layout.hpp"
|
||||||
|
|
||||||
namespace Raven {
|
namespace Raven {
|
||||||
|
|
||||||
|
void Widget::do_layout() {
|
||||||
|
if (m_layout) {
|
||||||
|
m_layout->run_on(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Widget::set_window(Window *window) {
|
void Widget::set_window(Window *window) {
|
||||||
m_window = window;
|
m_window = window;
|
||||||
m_styles = m_window->get_top_level_styles();
|
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
|
// children inherit the window from the parent
|
||||||
// TODO?: what happens when the parent changes its window?
|
// TODO?: what happens when the parent changes its window?
|
||||||
child->set_window(m_window);
|
child->set_window(m_window);
|
||||||
|
do_layout();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,6 +140,9 @@ void Widget::handle_mouse_button_event(MouseButtonEvent &event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::dispatch_event(Event &event) {
|
void Widget::dispatch_event(Event &event) {
|
||||||
|
if (!m_accepts_events)
|
||||||
|
return;
|
||||||
|
|
||||||
switch (event.get_type()) {
|
switch (event.get_type()) {
|
||||||
case EventType::MouseMove: {
|
case EventType::MouseMove: {
|
||||||
handle_mouse_move_event(reinterpret_cast<MouseMoveEvent&>(event));
|
handle_mouse_move_event(reinterpret_cast<MouseMoveEvent&>(event));
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "Box.hpp"
|
#include "Box.hpp"
|
||||||
#include "Events.hpp"
|
#include "Events.hpp"
|
||||||
#include "Forward.hpp"
|
#include "Forward.hpp"
|
||||||
#include "RGB.hpp"
|
#include "RGB.hpp"
|
||||||
|
@ -12,6 +12,18 @@
|
||||||
|
|
||||||
namespace Raven {
|
namespace Raven {
|
||||||
|
|
||||||
|
enum class WidgetType {
|
||||||
|
Widget = 0,
|
||||||
|
Button,
|
||||||
|
Label,
|
||||||
|
Control
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ControlWidgetType {
|
||||||
|
Widget = 0,
|
||||||
|
NewRow
|
||||||
|
};
|
||||||
|
|
||||||
class Widget {
|
class Widget {
|
||||||
|
|
||||||
DEF_WIDGET_STYLE_PROP(do_background_fill, bool, false)
|
DEF_WIDGET_STYLE_PROP(do_background_fill, bool, false)
|
||||||
|
@ -20,18 +32,28 @@ DEF_WIDGET_STYLE_PROP(background_border_radius, double, 0.0)
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Box m_current_geometry {};
|
Box m_current_geometry { 0, 0, 0, 0 };
|
||||||
std::vector<Widget*> m_children;
|
std::vector<Widget*> m_children;
|
||||||
Widget *m_parent { nullptr };
|
Widget *m_parent { nullptr };
|
||||||
Window *m_window { nullptr };
|
Window *m_window { nullptr };
|
||||||
std::shared_ptr<TopLevelStyles> m_styles = nullptr;
|
std::shared_ptr<TopLevelStyles> m_styles = nullptr;
|
||||||
|
Layout *m_layout { nullptr };
|
||||||
bool m_did_init { false };
|
bool m_did_init { false };
|
||||||
bool m_is_focused { false };
|
bool m_is_focused { false };
|
||||||
bool m_is_active { false };
|
bool m_is_active { false };
|
||||||
bool m_consumes_hits { false };
|
bool m_consumes_hits { false };
|
||||||
|
bool m_accepts_events { true };
|
||||||
|
ControlWidgetType m_control_type { ControlWidgetType::Widget };
|
||||||
public:
|
public:
|
||||||
Widget() {}
|
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; }
|
Box &get_current_geometry() { return m_current_geometry; }
|
||||||
void set_current_geometry(Box current_geometry) { m_current_geometry = current_geometry; wants_repaint(); }
|
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; }
|
bool get_consumes_hits() { return m_consumes_hits; }
|
||||||
void set_consumes_hits(bool consumes_hits) { m_consumes_hits = 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 dispatch_event(Event &event);
|
||||||
void wants_repaint();
|
void wants_repaint();
|
||||||
void wants_full_repaint();
|
void wants_full_repaint();
|
||||||
|
void do_layout();
|
||||||
|
|
||||||
virtual ~Widget() {};
|
virtual ~Widget() {};
|
||||||
protected:
|
protected:
|
||||||
|
WidgetType m_type { WidgetType::Widget };
|
||||||
|
|
||||||
virtual void on_init();
|
virtual void on_init();
|
||||||
virtual void on_mouse_button(MouseButtonEvent &event) {}
|
virtual void on_mouse_button(MouseButtonEvent &event) {}
|
||||||
virtual void on_mouse_move(MouseMoveEvent &event) {}
|
virtual void on_mouse_move(MouseMoveEvent &event) {}
|
||||||
|
|
13
src/main.cpp
13
src/main.cpp
|
@ -4,19 +4,26 @@
|
||||||
#include "Button.hpp"
|
#include "Button.hpp"
|
||||||
#include "Box.hpp"
|
#include "Box.hpp"
|
||||||
#include "Label.hpp"
|
#include "Label.hpp"
|
||||||
|
#include "Layout.hpp"
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
Raven::Layout main_layout {};
|
||||||
|
Raven::Widget new_row { Raven::ControlWidgetType::NewRow };
|
||||||
Raven::Window window {};
|
Raven::Window window {};
|
||||||
Raven::Widget main_widget {};
|
Raven::Widget main_widget {};
|
||||||
Raven::Button button {"click meeeeeeeeeeee"};
|
Raven::Button button {"click meeeeeeeeeeee"};
|
||||||
|
Raven::Button impostor_button {"other button"};
|
||||||
Raven::Label label {"click it!"};
|
Raven::Label label {"click it!"};
|
||||||
|
|
||||||
int times_clicked = 0;
|
int times_clicked = 0;
|
||||||
|
|
||||||
window.spawn_window();
|
window.spawn_window();
|
||||||
|
|
||||||
button.set_current_geometry(Raven::Box(10, 10, 100, 30));
|
button.set_current_geometry(Raven::Box(0, 0, 100, 30));
|
||||||
label.set_current_geometry(Raven::Box(10, 45, 100, 20));
|
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);
|
window.set_main_widget(&main_widget);
|
||||||
|
|
||||||
button.on_click = [&]() {
|
button.on_click = [&]() {
|
||||||
|
@ -26,6 +33,8 @@ int main() {
|
||||||
|
|
||||||
main_widget.add_child(&button);
|
main_widget.add_child(&button);
|
||||||
main_widget.add_child(&label);
|
main_widget.add_child(&label);
|
||||||
|
main_widget.add_child(&new_row);
|
||||||
|
main_widget.add_child(&impostor_button);
|
||||||
|
|
||||||
|
|
||||||
window.run(true);
|
window.run(true);
|
||||||
|
|
Loading…
Reference in a new issue