Compare commits
3 commits
94c0be051b
...
9ee4acfba5
Author | SHA1 | Date | |
---|---|---|---|
|
9ee4acfba5 | ||
|
305279c0f7 | ||
|
bfe126ab3c |
20 changed files with 193 additions and 188 deletions
|
@ -7,6 +7,7 @@ xlib_dep = dependency('x11')
|
||||||
executable(
|
executable(
|
||||||
'ravenapp',
|
'ravenapp',
|
||||||
'./src/Box.cpp',
|
'./src/Box.cpp',
|
||||||
|
'./src/Styles.cpp',
|
||||||
'./src/Painter.cpp',
|
'./src/Painter.cpp',
|
||||||
'./src/Window.cpp',
|
'./src/Window.cpp',
|
||||||
'./src/Widget.cpp',
|
'./src/Widget.cpp',
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "Box.hpp"
|
#include "Box.hpp"
|
||||||
#include "Window.hpp"
|
#include "Window.hpp"
|
||||||
#include "Painter.hpp"
|
#include "Painter.hpp"
|
||||||
|
#include "Styles.hpp"
|
||||||
#include "pango/pango-layout.h"
|
#include "pango/pango-layout.h"
|
||||||
#include <pango/pangocairo.h>
|
#include <pango/pangocairo.h>
|
||||||
|
|
||||||
|
@ -17,40 +18,21 @@ void Button::set_text(std::string text) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Button::on_init() {
|
void Button::on_init() {
|
||||||
set_background_border_radius(styles()->button_border_radius());
|
set_style(&default_button_style);
|
||||||
set_background_fill_color(styles()->button_normal_color());
|
|
||||||
set_do_background_fill(true);
|
|
||||||
fit_text(m_text);
|
fit_text(m_text);
|
||||||
|
|
||||||
set_did_init(true);
|
set_did_init(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Button::update_color() {
|
|
||||||
if (is_active()) {
|
|
||||||
set_background_fill_color(styles()->button_active_color());
|
|
||||||
} else if (is_focused()) {
|
|
||||||
set_background_fill_color(styles()->button_focused_color());
|
|
||||||
} else {
|
|
||||||
set_background_fill_color(styles()->button_normal_color());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Button::on_paint() {
|
void Button::on_paint() {
|
||||||
auto painter = window()->painter();
|
auto painter = window()->painter();
|
||||||
auto text_color = styles()->button_text_color();
|
|
||||||
|
|
||||||
painter.source_rgb(text_color);
|
painter.source_rgb(style()->foreground());
|
||||||
painter.set_pango_font_description(styles()->controls_font_description());
|
painter.set_pango_font_description(style()->font_description());
|
||||||
painter.text(current_geometry(), m_text, PaintTextAlign::Center, PANGO_ELLIPSIZE_END, true);
|
painter.text(rect(), m_text, PaintTextAlign::Center, PANGO_ELLIPSIZE_END, true);
|
||||||
painter.fill();
|
painter.fill();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Button::on_focus_update(FocusUpdateEvent &event) {
|
|
||||||
update_color();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Button::on_activation_update(ActivationUpdateEvent &event) {
|
void Button::on_activation_update(ActivationUpdateEvent &event) {
|
||||||
update_color();
|
|
||||||
if (event.activation_status() == false) {
|
if (event.activation_status() == false) {
|
||||||
on_click();
|
on_click();
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@ public:
|
||||||
protected:
|
protected:
|
||||||
void on_paint();
|
void on_paint();
|
||||||
void on_init();
|
void on_init();
|
||||||
void on_focus_update(FocusUpdateEvent &event);
|
|
||||||
void on_activation_update(ActivationUpdateEvent &event);
|
void on_activation_update(ActivationUpdateEvent &event);
|
||||||
private:
|
private:
|
||||||
void update_color();
|
void update_color();
|
||||||
|
|
|
@ -17,21 +17,21 @@ void DocumentLayout::run() {
|
||||||
if (child->absolute())
|
if (child->absolute())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (child->current_geometry().height() > largest_height_so_far) {
|
if (child->rect().height() > largest_height_so_far) {
|
||||||
largest_height_so_far = child->current_geometry().height();
|
largest_height_so_far = child->rect().height();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool new_row_because_of_control_widget = (child->control_type() == ControlWidgetType::NewRow && largest_height_so_far);
|
bool new_row_because_of_control_widget = (child->control_type() == ControlWidgetType::NewRow && largest_height_so_far);
|
||||||
bool new_row_because_of_justification = (current_position.x() + child->current_geometry().width() + m_margin) >= m_target->current_geometry().width();
|
bool new_row_because_of_justification = (current_position.x() + child->rect().width() + m_margin) >= m_target->rect().width();
|
||||||
bool should_do_new_row = new_row_because_of_control_widget || new_row_because_of_justification;
|
bool should_do_new_row = new_row_because_of_control_widget || new_row_because_of_justification;
|
||||||
if (should_do_new_row) {
|
if (should_do_new_row) {
|
||||||
current_position.add(0, largest_height_so_far + m_margin);
|
current_position.add(0, largest_height_so_far + m_margin);
|
||||||
current_position.set_x(m_margin);
|
current_position.set_x(m_margin);
|
||||||
}
|
}
|
||||||
|
|
||||||
child->current_geometry().set_x(current_position.x());
|
child->rect().set_x(current_position.x());
|
||||||
child->current_geometry().set_y(current_position.y());
|
child->rect().set_y(current_position.y());
|
||||||
current_position.add(child->current_geometry().width() + m_margin, 0);
|
current_position.add(child->rect().width() + m_margin, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
namespace Raven {
|
namespace Raven {
|
||||||
|
class GenericStyle;
|
||||||
class Box;
|
class Box;
|
||||||
class Button;
|
class Button;
|
||||||
class Events;
|
class Events;
|
||||||
class Painter;
|
class Painter;
|
||||||
class Point;
|
class Point;
|
||||||
class TopLevelStyles;
|
|
||||||
class Layout;
|
class Layout;
|
||||||
class Widget;
|
class Widget;
|
||||||
class Window;
|
class Window;
|
||||||
|
|
49
src/GenericStyle.hpp
Normal file
49
src/GenericStyle.hpp
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "pango/pango-font.h"
|
||||||
|
#include "RGB.hpp"
|
||||||
|
|
||||||
|
#define __RAVEN_STYLE_PROP(name, type, ...) \
|
||||||
|
private: \
|
||||||
|
type m_##name {__VA_ARGS__}; \
|
||||||
|
public: \
|
||||||
|
void set_##name(type new_prop_value) { m_##name = new_prop_value; style_prop_updated(); } \
|
||||||
|
type name() { return m_##name; } \
|
||||||
|
private:
|
||||||
|
|
||||||
|
namespace Raven {
|
||||||
|
|
||||||
|
class GenericStyle {
|
||||||
|
__RAVEN_STYLE_PROP(font_description, PangoFontDescription*, nullptr)
|
||||||
|
__RAVEN_STYLE_PROP(foreground, RGB, 0.00000, 0.00000, 0.00000)
|
||||||
|
__RAVEN_STYLE_PROP(background_norm, RGB, 1.00000, 1.00000, 1.00000)
|
||||||
|
__RAVEN_STYLE_PROP(background_focused, RGB, 1.00000, 1.00000, 1.00000)
|
||||||
|
__RAVEN_STYLE_PROP(background_active, RGB, 1.00000, 1.00000, 1.00000)
|
||||||
|
__RAVEN_STYLE_PROP(border_radius, double, 0.0)
|
||||||
|
__RAVEN_STYLE_PROP(fill_background, bool, true)
|
||||||
|
__RAVEN_STYLE_PROP(update_background, bool, false)
|
||||||
|
|
||||||
|
private:
|
||||||
|
void style_prop_updated() { }
|
||||||
|
public:
|
||||||
|
GenericStyle(
|
||||||
|
PangoFontDescription* font_description,
|
||||||
|
RGB foreground,
|
||||||
|
RGB background_norm,
|
||||||
|
RGB background_focused,
|
||||||
|
RGB background_active,
|
||||||
|
double border_radius,
|
||||||
|
bool fill_background,
|
||||||
|
bool update_background
|
||||||
|
)
|
||||||
|
: m_font_description(font_description)
|
||||||
|
, m_foreground(foreground)
|
||||||
|
, m_background_norm(background_norm)
|
||||||
|
, m_background_focused(background_focused)
|
||||||
|
, m_background_active(background_active)
|
||||||
|
, m_border_radius(border_radius)
|
||||||
|
, m_fill_background(fill_background)
|
||||||
|
, m_update_background(update_background) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
#include "Label.hpp"
|
#include "Label.hpp"
|
||||||
#include "Window.hpp"
|
#include "Window.hpp"
|
||||||
#include "pango/pango-layout.h"
|
#include "pango/pango-layout.h"
|
||||||
|
#include "Styles.hpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
namespace Raven {
|
namespace Raven {
|
||||||
|
@ -13,19 +14,17 @@ void Label::set_text(std::string text) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Label::on_init() {
|
void Label::on_init() {
|
||||||
|
set_style(&default_label_style);
|
||||||
fit_text(m_text);
|
fit_text(m_text);
|
||||||
|
|
||||||
set_did_init(true);
|
set_did_init(true);
|
||||||
set_do_background_fill(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Label::on_paint() {
|
void Label::on_paint() {
|
||||||
auto painter = window()->painter();
|
auto painter = window()->painter();
|
||||||
auto text_color = styles()->label_text_color();
|
|
||||||
|
|
||||||
painter.source_rgb(text_color);
|
painter.source_rgb(style()->foreground());
|
||||||
painter.set_pango_font_description(styles()->controls_font_description());
|
painter.set_pango_font_description(style()->font_description());
|
||||||
painter.text(current_geometry(), m_text, PaintTextAlign::Left, PANGO_ELLIPSIZE_NONE, true);
|
painter.text(rect(), m_text, PaintTextAlign::Left, PANGO_ELLIPSIZE_NONE, true);
|
||||||
painter.fill();
|
painter.fill();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Widget.hpp"
|
#include "Widget.hpp"
|
||||||
#include "PropMacros.hpp"
|
|
||||||
|
|
||||||
namespace Raven {
|
namespace Raven {
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,7 @@ Point Painter::text(Box &geometry, std::string &text, PaintTextAlign align, Pang
|
||||||
return {pango_units_to_double(pango_width), pango_units_to_double(pango_height)};
|
return {pango_units_to_double(pango_width), pango_units_to_double(pango_height)};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Painter::source_rgb(RGB &source_rgb) {
|
void Painter::source_rgb(RGB source_rgb) {
|
||||||
m_cairo->set_source_rgb(source_rgb.r(), source_rgb.g(), source_rgb.b());
|
m_cairo->set_source_rgb(source_rgb.r(), source_rgb.g(), source_rgb.b());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ public:
|
||||||
|
|
||||||
bool can_paint() { if (m_cairo) return true; else return false; }
|
bool can_paint() { if (m_cairo) return true; else return false; }
|
||||||
|
|
||||||
void source_rgb(RGB &source_rgb);
|
void source_rgb(RGB source_rgb);
|
||||||
void fill();
|
void fill();
|
||||||
|
|
||||||
void begin_paint_group();
|
void begin_paint_group();
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#define DEF_WIDGET_STYLE_PROP(name, type, ...) \
|
|
||||||
private: \
|
|
||||||
type m_##name {__VA_ARGS__}; \
|
|
||||||
public: \
|
|
||||||
void set_##name(type new_prop_value) { m_##name = new_prop_value; repaint(); } \
|
|
||||||
type name() { return m_##name; } \
|
|
||||||
private:
|
|
41
src/Styles.cpp
Normal file
41
src/Styles.cpp
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#include "Styles.hpp"
|
||||||
|
|
||||||
|
#include "pango/pango-font.h"
|
||||||
|
#include "RGB.hpp"
|
||||||
|
|
||||||
|
namespace Raven {
|
||||||
|
|
||||||
|
GenericStyle default_widget_style {
|
||||||
|
pango_font_description_from_string("sans-serif"),
|
||||||
|
RGB(0.00000, 0.00000, 0.00000),
|
||||||
|
RGB(1.00000, 1.00000, 1.00000),
|
||||||
|
RGB(1.00000, 1.00000, 1.00000),
|
||||||
|
RGB(1.00000, 1.00000, 1.00000),
|
||||||
|
0.0,
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
GenericStyle default_button_style {
|
||||||
|
pango_font_description_from_string("sans-serif"),
|
||||||
|
RGB(0.00000, 0.00000, 0.00000),
|
||||||
|
RGB(0.73333, 0.40392, 0.89412),
|
||||||
|
RGB(0.63922, 0.27843, 0.81961),
|
||||||
|
RGB(0.54118, 0.18039, 0.72157),
|
||||||
|
6.0,
|
||||||
|
true,
|
||||||
|
true
|
||||||
|
};
|
||||||
|
|
||||||
|
GenericStyle default_label_style {
|
||||||
|
pango_font_description_from_string("sans-serif"),
|
||||||
|
RGB(0.00000, 0.00000, 0.00000),
|
||||||
|
RGB(0.00000, 0.00000, 0.00000),
|
||||||
|
RGB(0.00000, 0.00000, 0.00000),
|
||||||
|
RGB(0.00000, 0.00000, 0.00000),
|
||||||
|
0.0,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
11
src/Styles.hpp
Normal file
11
src/Styles.hpp
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "GenericStyle.hpp"
|
||||||
|
|
||||||
|
namespace Raven {
|
||||||
|
|
||||||
|
extern GenericStyle default_widget_style;
|
||||||
|
extern GenericStyle default_button_style;
|
||||||
|
extern GenericStyle default_label_style;
|
||||||
|
|
||||||
|
}
|
|
@ -1,12 +0,0 @@
|
||||||
#include "TopLevelStyles.hpp"
|
|
||||||
#include "Window.hpp"
|
|
||||||
|
|
||||||
namespace Raven {
|
|
||||||
|
|
||||||
void TopLevelStyles::wants_repaint() {
|
|
||||||
// when one of the styles here changes, we will dispatch
|
|
||||||
// a full repaint to the entire window :^)
|
|
||||||
m_window->dispatch_full_repaint();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Forward.hpp"
|
|
||||||
#include "pango/pango-font.h"
|
|
||||||
#include "PropMacros.hpp"
|
|
||||||
#include "RGB.hpp"
|
|
||||||
|
|
||||||
namespace Raven {
|
|
||||||
|
|
||||||
class TopLevelStyles {
|
|
||||||
DEF_WIDGET_STYLE_PROP(controls_font_description, PangoFontDescription*, nullptr)
|
|
||||||
|
|
||||||
/* FIXME: */
|
|
||||||
/* right now, these colors are gruvbox */
|
|
||||||
/* however the `accent_color_darkest` is a darkened version of `accent_color_darker` */
|
|
||||||
DEF_WIDGET_STYLE_PROP(text_color, RGB, 0.0, 0.0, 0.0)
|
|
||||||
DEF_WIDGET_STYLE_PROP(accent_color, RGB, 0.6941, 0.3843, 0.5254)
|
|
||||||
DEF_WIDGET_STYLE_PROP(accent_color_darker, RGB, 0.5607, 0.2470, 0.4431)
|
|
||||||
DEF_WIDGET_STYLE_PROP(accent_color_darkest, RGB, 0.48069, 0.1669, 0.3631)
|
|
||||||
DEF_WIDGET_STYLE_PROP(background_color, RGB, 0.9764, 0.9607, 0.8431)
|
|
||||||
|
|
||||||
DEF_WIDGET_STYLE_PROP(button_text_color, RGB, m_text_color)
|
|
||||||
DEF_WIDGET_STYLE_PROP(button_normal_color, RGB, m_accent_color)
|
|
||||||
DEF_WIDGET_STYLE_PROP(button_focused_color, RGB, m_accent_color_darker)
|
|
||||||
DEF_WIDGET_STYLE_PROP(button_active_color, RGB, m_accent_color_darkest)
|
|
||||||
DEF_WIDGET_STYLE_PROP(button_border_radius, double, 6.0)
|
|
||||||
|
|
||||||
DEF_WIDGET_STYLE_PROP(label_text_color, RGB, m_text_color)
|
|
||||||
|
|
||||||
private:
|
|
||||||
Window *m_window;
|
|
||||||
public:
|
|
||||||
TopLevelStyles(Window *window)
|
|
||||||
: m_window(window)
|
|
||||||
{
|
|
||||||
PangoFontDescription *font_description = pango_font_description_new();
|
|
||||||
|
|
||||||
pango_font_description_set_family(font_description, "sans-serif");
|
|
||||||
pango_font_description_set_weight(font_description, PANGO_WEIGHT_NORMAL);
|
|
||||||
pango_font_description_set_absolute_size(font_description, 16 * PANGO_SCALE);
|
|
||||||
|
|
||||||
m_controls_font_description = font_description;
|
|
||||||
}
|
|
||||||
|
|
||||||
~TopLevelStyles() {
|
|
||||||
if (m_controls_font_description) {
|
|
||||||
pango_font_description_free(m_controls_font_description);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Window *window() { return m_window; }
|
|
||||||
void set_window(Window *window) { m_window = window; }
|
|
||||||
|
|
||||||
void repaint();
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -12,7 +12,7 @@ namespace Raven {
|
||||||
Point Widget::window_relative() {
|
Point Widget::window_relative() {
|
||||||
Point point = { 0, 0 };
|
Point point = { 0, 0 };
|
||||||
for (Widget* parent = m_parent; parent; parent = parent->parent()) {
|
for (Widget* parent = m_parent; parent; parent = parent->parent()) {
|
||||||
point.add(parent->current_geometry().x(), parent->current_geometry().y());
|
point.add(parent->rect().x(), parent->rect().y());
|
||||||
}
|
}
|
||||||
return point;
|
return point;
|
||||||
}
|
}
|
||||||
|
@ -21,32 +21,32 @@ void Widget::fit_text(std::string &text) {
|
||||||
if (!window())
|
if (!window())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
window()->painter().set_pango_font_description(styles()->controls_font_description());
|
window()->painter().set_pango_font_description(m_style->font_description());
|
||||||
auto size = window()->painter().compute_text_size(current_geometry(), text);
|
auto size = window()->painter().compute_text_size(rect(), text);
|
||||||
if (!resize(size)) {
|
if (!resize(size)) {
|
||||||
reflow();
|
reflow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Widget::resize(double width, double height) {
|
bool Widget::resize(double width, double height) {
|
||||||
if (m_current_geometry.width() == width && m_current_geometry.height() == height)
|
if (m_rect.width() == width && m_rect.height() == height)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (width < 0 || height < 0)
|
if (width < 0 || height < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_current_geometry.set_width(width);
|
m_rect.set_width(width);
|
||||||
m_current_geometry.set_height(height);
|
m_rect.set_height(height);
|
||||||
reflow();
|
reflow();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::move_to(double x, double y) {
|
void Widget::move_to(double x, double y) {
|
||||||
if (m_current_geometry.x() == x && m_current_geometry.y() == y)
|
if (m_rect.x() == x && m_rect.y() == y)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_current_geometry.set_x(x);
|
m_rect.set_x(x);
|
||||||
m_current_geometry.set_y(y);
|
m_rect.set_y(y);
|
||||||
reflow();
|
reflow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,6 @@ void Widget::set_window(Window *window) {
|
||||||
throw std::logic_error{"null window value for set_window"};
|
throw std::logic_error{"null window value for set_window"};
|
||||||
|
|
||||||
m_window = window;
|
m_window = window;
|
||||||
m_styles = m_window->top_level_styles();
|
|
||||||
|
|
||||||
on_init();
|
on_init();
|
||||||
}
|
}
|
||||||
|
@ -107,7 +106,7 @@ void Widget::handle_repaint_rect(RepaintRectEvent &event) {
|
||||||
if (!m_did_init || !painter.can_paint())
|
if (!m_did_init || !painter.can_paint())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!event.box().contains_box(current_geometry()))
|
if (!event.box().contains_box(m_rect))
|
||||||
return; // widgets contain their children, thus we don't need to recurse further
|
return; // widgets contain their children, thus we don't need to recurse further
|
||||||
|
|
||||||
// using a "group" in cairo reduces flickering
|
// using a "group" in cairo reduces flickering
|
||||||
|
@ -121,27 +120,37 @@ void Widget::handle_repaint_rect(RepaintRectEvent &event) {
|
||||||
|
|
||||||
cr->save();
|
cr->save();
|
||||||
|
|
||||||
// clip this widget. this ensuers that the background fill or children won't overflow the bounds of it
|
// clip this widget. this ensures that the background fill or children won't overflow the bounds of it
|
||||||
painter.rounded_rectangle(m_current_geometry, m_background_border_radius);
|
painter.rounded_rectangle(m_rect, m_style->border_radius());
|
||||||
cr->clip();
|
cr->clip();
|
||||||
|
|
||||||
// paint the background fill
|
// paint the background fill
|
||||||
// note that we're using the bounds of the paint event as the rectangle, this ensures that we dont draw over other widgets which won't be repainted.
|
// note that we're using the bounds of the paint event as the rectangle, this ensures that we dont draw over other widgets which won't be repainted.
|
||||||
if (m_do_background_fill) {
|
if (m_style->fill_background()) {
|
||||||
painter.source_rgb(m_background_fill_color);
|
if (m_style->update_background()) {
|
||||||
painter.rounded_rectangle(event.box(), m_background_border_radius);
|
if (m_is_focused) {
|
||||||
|
painter.source_rgb(m_style->background_focused());
|
||||||
|
} else if (m_is_active) {
|
||||||
|
painter.source_rgb(m_style->background_active());
|
||||||
|
} else {
|
||||||
|
painter.source_rgb(m_style->background_norm());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
painter.source_rgb(m_style->background_norm());
|
||||||
|
}
|
||||||
|
painter.rounded_rectangle(event.box(), m_style->border_radius());
|
||||||
cr->fill();
|
cr->fill();
|
||||||
}
|
}
|
||||||
|
|
||||||
// translate to the widget's position
|
// translate to the widget's position
|
||||||
// the origin of the painter is now the widget's origin
|
// the origin of the painter is now the widget's origin
|
||||||
// this is because the position of children is relative to the origin of their parent
|
// this is because the position of children is relative to the origin of their parent
|
||||||
cr->translate(current_geometry().x(), current_geometry().y());
|
cr->translate(rect().x(), rect().y());
|
||||||
|
|
||||||
on_paint();
|
on_paint();
|
||||||
|
|
||||||
// convert the paint event's origin to our coordinate space because all positions of children are relative to the origin of their parent
|
// convert the paint event's origin to our coordinate space because all positions of children are relative to the origin of their parent
|
||||||
auto local_box = event.box().offset(-m_current_geometry.x(), -m_current_geometry.y());
|
auto local_box = event.box().offset(-m_rect.x(), -m_rect.y());
|
||||||
auto local_event = RepaintRectEvent(false, local_box);
|
auto local_event = RepaintRectEvent(false, local_box);
|
||||||
for (auto child : m_children) {
|
for (auto child : m_children) {
|
||||||
child->dispatch_event(local_event);
|
child->dispatch_event(local_event);
|
||||||
|
@ -162,7 +171,7 @@ void Widget::handle_mouse_move_event(MouseMoveEvent &event) {
|
||||||
event.accept(); // we will do our own propagation logic
|
event.accept(); // we will do our own propagation logic
|
||||||
|
|
||||||
bool update_focus_to = true;
|
bool update_focus_to = true;
|
||||||
if (!m_current_geometry.contains_point(event.point())) {
|
if (!m_rect.contains_point(event.point())) {
|
||||||
// we just became unfocused
|
// we just became unfocused
|
||||||
update_focus_to = false;
|
update_focus_to = false;
|
||||||
}
|
}
|
||||||
|
@ -176,13 +185,17 @@ void Widget::handle_mouse_move_event(MouseMoveEvent &event) {
|
||||||
|
|
||||||
auto focus_update_event = FocusUpdateEvent(update_focus_to);
|
auto focus_update_event = FocusUpdateEvent(update_focus_to);
|
||||||
on_focus_update(focus_update_event);
|
on_focus_update(focus_update_event);
|
||||||
|
|
||||||
|
if (m_style->update_background()) {
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_consumes_hits) {
|
if (!m_consumes_hits) {
|
||||||
// translate the event's point to our coordinate space because the position of all children is relative to the origin of their parent
|
// translate the event's point to our coordinate space because the position of all children is relative to the origin of their parent
|
||||||
auto local_event = MouseMoveEvent(Point(
|
auto local_event = MouseMoveEvent(Point(
|
||||||
event.point().x() - m_current_geometry.x(),
|
event.point().x() - m_rect.x(),
|
||||||
event.point().y() - m_current_geometry.y()
|
event.point().y() - m_rect.y()
|
||||||
));
|
));
|
||||||
for (auto child : m_children) {
|
for (auto child : m_children) {
|
||||||
child->dispatch_event(local_event);
|
child->dispatch_event(local_event);
|
||||||
|
@ -195,7 +208,7 @@ void Widget::handle_mouse_button_event(MouseButtonEvent &event) {
|
||||||
|
|
||||||
bool update_activation_to = event.was_left_button_pressed();
|
bool update_activation_to = event.was_left_button_pressed();
|
||||||
|
|
||||||
if (!m_current_geometry.contains_point(event.point())) {
|
if (!m_rect.contains_point(event.point())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,13 +221,17 @@ void Widget::handle_mouse_button_event(MouseButtonEvent &event) {
|
||||||
|
|
||||||
auto activation_update_event = ActivationUpdateEvent(update_activation_to);
|
auto activation_update_event = ActivationUpdateEvent(update_activation_to);
|
||||||
on_activation_update(activation_update_event);
|
on_activation_update(activation_update_event);
|
||||||
|
|
||||||
|
if (m_style->update_background()) {
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_consumes_hits) {
|
if (!m_consumes_hits) {
|
||||||
// translate the event's point to our coordinate space because the position of all children is relative to the origin of their parent
|
// translate the event's point to our coordinate space because the position of all children is relative to the origin of their parent
|
||||||
auto local_event = MouseButtonEvent(event.was_left_button_pressed(), event.was_right_button_pressed(), Point(
|
auto local_event = MouseButtonEvent(event.was_left_button_pressed(), event.was_right_button_pressed(), Point(
|
||||||
event.point().x() - m_current_geometry.x(),
|
event.point().x() - m_rect.x(),
|
||||||
event.point().y() - m_current_geometry.y()
|
event.point().y() - m_rect.y()
|
||||||
));
|
));
|
||||||
for (auto child : m_children) {
|
for (auto child : m_children) {
|
||||||
child->dispatch_event(local_event);
|
child->dispatch_event(local_event);
|
||||||
|
@ -260,9 +277,4 @@ void Widget::dispatch_event(Event &event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::on_init() {
|
|
||||||
set_background_fill_color(styles()->background_color());
|
|
||||||
set_did_init(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
#include "Events.hpp"
|
#include "Events.hpp"
|
||||||
#include "Forward.hpp"
|
#include "Forward.hpp"
|
||||||
#include "RGB.hpp"
|
#include "RGB.hpp"
|
||||||
#include "TopLevelStyles.hpp"
|
#include "GenericStyle.hpp"
|
||||||
#include "PropMacros.hpp"
|
#include "Styles.hpp"
|
||||||
|
|
||||||
namespace Raven {
|
namespace Raven {
|
||||||
|
|
||||||
|
@ -27,10 +27,6 @@ enum class ControlWidgetType {
|
||||||
};
|
};
|
||||||
|
|
||||||
class Widget {
|
class Widget {
|
||||||
DEF_WIDGET_STYLE_PROP(do_background_fill, bool, true)
|
|
||||||
DEF_WIDGET_STYLE_PROP(background_fill_color, RGB, 0, 0, 0)
|
|
||||||
DEF_WIDGET_STYLE_PROP(background_border_radius, double, 0.0)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Widget() {}
|
Widget() {}
|
||||||
|
|
||||||
|
@ -58,9 +54,9 @@ public:
|
||||||
bool add_child(std::shared_ptr<Widget> child);
|
bool add_child(std::shared_ptr<Widget> child);
|
||||||
void remove_child(std::shared_ptr<Widget> child);
|
void remove_child(std::shared_ptr<Widget> child);
|
||||||
|
|
||||||
Box ¤t_geometry() { return m_current_geometry; }
|
Box &rect() { return m_rect; }
|
||||||
void set_current_geometry(Box current_geometry) { m_current_geometry = current_geometry; reflow(); }
|
void set_rect(Box rect) { m_rect = rect; reflow(); }
|
||||||
void set_current_geometry(Box current_geometry, bool is_pure) { m_current_geometry = current_geometry; if (!is_pure) { reflow(); } }
|
void set_rect(Box rect, bool is_pure) { m_rect = rect; if (!is_pure) { reflow(); } }
|
||||||
|
|
||||||
Point window_relative();
|
Point window_relative();
|
||||||
|
|
||||||
|
@ -73,14 +69,11 @@ public:
|
||||||
Window *window() { return m_window; }
|
Window *window() { return m_window; }
|
||||||
void set_window(Window *window);
|
void set_window(Window *window);
|
||||||
|
|
||||||
std::shared_ptr<TopLevelStyles> styles() { return m_styles; }
|
GenericStyle *style() { return m_style; }
|
||||||
void set_styles(std::shared_ptr<TopLevelStyles> styles) { m_styles = styles; wants_relayout(); }
|
void set_style(GenericStyle *style) { m_style = style; reflow(); }
|
||||||
|
|
||||||
void set_did_init(bool did_init) { m_did_init = did_init; }
|
|
||||||
bool did_init() { return m_did_init; }
|
bool did_init() { return m_did_init; }
|
||||||
|
|
||||||
bool is_focused() { return m_is_focused; }
|
bool is_focused() { return m_is_focused; }
|
||||||
|
|
||||||
bool is_active() { return m_is_active; }
|
bool is_active() { return m_is_active; }
|
||||||
|
|
||||||
bool consumes_hits() { return m_consumes_hits; }
|
bool consumes_hits() { return m_consumes_hits; }
|
||||||
|
@ -96,8 +89,6 @@ public:
|
||||||
std::shared_ptr<Layout> layout() { return m_layout; }
|
std::shared_ptr<Layout> layout() { return m_layout; }
|
||||||
|
|
||||||
void dispatch_event(Event &event);
|
void dispatch_event(Event &event);
|
||||||
void wants_repaint();
|
|
||||||
void wants_relayout();
|
|
||||||
|
|
||||||
template<typename T, class... Args>
|
template<typename T, class... Args>
|
||||||
std::shared_ptr<T> set_layout(Args&&... args) {
|
std::shared_ptr<T> set_layout(Args&&... args) {
|
||||||
|
@ -115,13 +106,15 @@ public:
|
||||||
protected:
|
protected:
|
||||||
WidgetType m_type { WidgetType::Widget };
|
WidgetType m_type { WidgetType::Widget };
|
||||||
|
|
||||||
virtual void on_init();
|
virtual void on_init() { set_did_init(true); }
|
||||||
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) {}
|
||||||
virtual void on_focus_update(FocusUpdateEvent &event) {}
|
virtual void on_focus_update(FocusUpdateEvent &event) {}
|
||||||
virtual void on_activation_update(ActivationUpdateEvent &event) {}
|
virtual void on_activation_update(ActivationUpdateEvent &event) {}
|
||||||
virtual void on_paint() {}
|
virtual void on_paint() {}
|
||||||
|
|
||||||
|
void set_did_init(bool did_init) { m_did_init = did_init; }
|
||||||
|
|
||||||
void repaint();
|
void repaint();
|
||||||
void reflow();
|
void reflow();
|
||||||
private:
|
private:
|
||||||
|
@ -131,11 +124,11 @@ private:
|
||||||
void handle_mouse_move_event(MouseMoveEvent &event);
|
void handle_mouse_move_event(MouseMoveEvent &event);
|
||||||
void handle_mouse_button_event(MouseButtonEvent &event);
|
void handle_mouse_button_event(MouseButtonEvent &event);
|
||||||
|
|
||||||
Box m_current_geometry { 0, 0, 0, 0 };
|
Box m_rect { 0, 0, 0, 0 };
|
||||||
std::vector<std::shared_ptr<Widget>> m_children;
|
std::vector<std::shared_ptr<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 };
|
GenericStyle *m_style { &default_widget_style };
|
||||||
std::shared_ptr<Layout> m_layout { nullptr };
|
std::shared_ptr<Layout> m_layout { nullptr };
|
||||||
bool m_did_init { false };
|
bool m_did_init { false };
|
||||||
bool m_is_focused { false };
|
bool m_is_focused { false };
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace Raven {
|
||||||
void Window::set_main_widget(std::shared_ptr<Widget> main_widget) {
|
void Window::set_main_widget(std::shared_ptr<Widget> main_widget) {
|
||||||
m_main_widget = main_widget;
|
m_main_widget = main_widget;
|
||||||
m_main_widget->set_window(this);
|
m_main_widget->set_window(this);
|
||||||
m_main_widget->set_current_geometry(m_current_geometry);
|
m_main_widget->set_rect(m_rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Window::spawn_window() {
|
bool Window::spawn_window() {
|
||||||
|
@ -33,8 +33,8 @@ bool Window::spawn_window() {
|
||||||
DefaultRootWindow(dsp),
|
DefaultRootWindow(dsp),
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
m_current_geometry.width(),
|
m_rect.width(),
|
||||||
m_current_geometry.height(),
|
m_rect.height(),
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
CopyFromParent,
|
CopyFromParent,
|
||||||
|
@ -50,8 +50,8 @@ bool Window::spawn_window() {
|
||||||
dsp,
|
dsp,
|
||||||
da,
|
da,
|
||||||
DefaultVisual(dsp, screen),
|
DefaultVisual(dsp, screen),
|
||||||
current_geometry().width(),
|
rect().width(),
|
||||||
current_geometry().height()
|
rect().height()
|
||||||
);
|
);
|
||||||
auto cairo_context = Cairo::Context::create(m_xlib_surface);
|
auto cairo_context = Cairo::Context::create(m_xlib_surface);
|
||||||
|
|
||||||
|
@ -82,12 +82,11 @@ void Window::repaint(Box geometry) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::repaint(Widget *target) {
|
void Window::repaint(Widget *target) {
|
||||||
std::cout << target->window_relative().x() << ", " << target->window_relative().y() << std::endl;
|
repaint(target->rect().offset(target->window_relative().x(), target->window_relative().y()));
|
||||||
repaint(target->current_geometry().offset(target->window_relative().x(), target->window_relative().y()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::repaint() {
|
void Window::repaint() {
|
||||||
repaint(m_current_geometry);
|
repaint(m_rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::relayout(Widget *target) {
|
void Window::relayout(Widget *target) {
|
||||||
|
@ -149,14 +148,14 @@ void Window::run(bool block) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ConfigureNotify: {
|
case ConfigureNotify: {
|
||||||
if (e.xconfigure.width != m_current_geometry.width() || e.xconfigure.height != m_current_geometry.height()) {
|
if (e.xconfigure.width != m_rect.width() || e.xconfigure.height != m_rect.height()) {
|
||||||
m_xlib_surface->set_size(e.xconfigure.width, e.xconfigure.height);
|
m_xlib_surface->set_size(e.xconfigure.width, e.xconfigure.height);
|
||||||
m_current_geometry.set_width(e.xconfigure.width);
|
m_rect.set_width(e.xconfigure.width);
|
||||||
m_current_geometry.set_height(e.xconfigure.height);
|
m_rect.set_height(e.xconfigure.height);
|
||||||
// if we have a main widget, we are going to have to resize it as well
|
// if we have a main widget, we are going to have to resize it as well
|
||||||
if (m_main_widget) {
|
if (m_main_widget) {
|
||||||
m_main_widget->current_geometry().set_width(m_current_geometry.width());
|
m_main_widget->rect().set_width(m_rect.width());
|
||||||
m_main_widget->current_geometry().set_height(m_current_geometry.height());
|
m_main_widget->rect().set_height(m_rect.height());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include "Widget.hpp"
|
#include "Widget.hpp"
|
||||||
#include "Painter.hpp"
|
#include "Painter.hpp"
|
||||||
#include "src/Events.hpp"
|
#include "Events.hpp"
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <cairomm/xlib_surface.h>
|
#include <cairomm/xlib_surface.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
@ -34,8 +34,6 @@ public:
|
||||||
std::shared_ptr<Widget> main_widget() { return m_main_widget; }
|
std::shared_ptr<Widget> main_widget() { return m_main_widget; }
|
||||||
void set_main_widget(std::shared_ptr<Widget> main_widget);
|
void set_main_widget(std::shared_ptr<Widget> main_widget);
|
||||||
|
|
||||||
std::shared_ptr<TopLevelStyles> top_level_styles() { return m_top_level_styles; }
|
|
||||||
|
|
||||||
void repaint();
|
void repaint();
|
||||||
void repaint(Box geometry);
|
void repaint(Box geometry);
|
||||||
void repaint(Widget *target);
|
void repaint(Widget *target);
|
||||||
|
@ -43,7 +41,7 @@ public:
|
||||||
void relayout();
|
void relayout();
|
||||||
void reflow();
|
void reflow();
|
||||||
|
|
||||||
Box ¤t_geometry() { return m_current_geometry; }
|
Box &rect() { return m_rect; }
|
||||||
|
|
||||||
template<typename T, class... Args>
|
template<typename T, class... Args>
|
||||||
std::shared_ptr<T> set_main_widget(Args&&... args) {
|
std::shared_ptr<T> set_main_widget(Args&&... args) {
|
||||||
|
@ -55,9 +53,8 @@ private:
|
||||||
Widget *m_focused_widget { nullptr };
|
Widget *m_focused_widget { nullptr };
|
||||||
Widget *m_active_widget { nullptr };
|
Widget *m_active_widget { nullptr };
|
||||||
std::shared_ptr<Widget> m_main_widget { nullptr };
|
std::shared_ptr<Widget> m_main_widget { nullptr };
|
||||||
Box m_current_geometry { 0, 0, 800, 600 };
|
Box m_rect { 0, 0, 800, 600 };
|
||||||
Painter m_painter {};
|
Painter m_painter {};
|
||||||
std::shared_ptr<TopLevelStyles> m_top_level_styles = std::make_shared<TopLevelStyles>(this);
|
|
||||||
Cairo::RefPtr<Cairo::XlibSurface> m_xlib_surface { nullptr };
|
Cairo::RefPtr<Cairo::XlibSurface> m_xlib_surface { nullptr };
|
||||||
bool m_is_batching { true };
|
bool m_is_batching { true };
|
||||||
bool m_did_relayout_during_batch { true };
|
bool m_did_relayout_during_batch { true };
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
#include "Label.hpp"
|
#include "Label.hpp"
|
||||||
#include "Layout.hpp"
|
#include "Layout.hpp"
|
||||||
#include "RGB.hpp"
|
#include "RGB.hpp"
|
||||||
#include "src/DocumentLayout.hpp"
|
#include "DocumentLayout.hpp"
|
||||||
#include "src/Events.hpp"
|
#include "Events.hpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -17,9 +17,10 @@ int main() {
|
||||||
window.spawn_window();
|
window.spawn_window();
|
||||||
|
|
||||||
auto main_widget = window.set_main_widget<Raven::Widget>();
|
auto main_widget = window.set_main_widget<Raven::Widget>();
|
||||||
|
main_widget->set_layout<Raven::DocumentLayout>(10.0);
|
||||||
|
|
||||||
auto second_widget = main_widget->add<Raven::Widget>();
|
auto second_widget = main_widget->add<Raven::Widget>();
|
||||||
second_widget->set_layout<Raven::DocumentLayout>(16.0);
|
second_widget->set_layout<Raven::DocumentLayout>(20.0);
|
||||||
second_widget->resize(800, 800);
|
second_widget->resize(800, 800);
|
||||||
|
|
||||||
auto inner_widget = second_widget->add<Raven::Widget>();
|
auto inner_widget = second_widget->add<Raven::Widget>();
|
||||||
|
|
Loading…
Reference in a new issue