Compare commits

...

2 commits

Author SHA1 Message Date
hippoz
5e436b5463
replace the separate layout and repaint events with a single "reflow"
event
2022-05-12 17:05:16 +03:00
hippoz
e52bbce5e0
fix layouting when button text changes 2022-05-10 21:14:55 +03:00
8 changed files with 58 additions and 50 deletions

View file

@ -31,10 +31,11 @@ void Button::on_paint() {
auto painter = window()->painter(); auto painter = window()->painter();
auto text_color = styles()->button_text_color(); auto text_color = styles()->button_text_color();
auto max_geometry = current_geometry().max_geometry(); auto max_geometry = current_geometry().max_geometry();
bool set_size = current_geometry().max_width() != -1 && current_geometry().max_height() != -1;
painter.source_rgb(text_color); painter.source_rgb(text_color);
painter.set_pango_font_description(styles()->controls_font_description()); painter.set_pango_font_description(styles()->controls_font_description());
auto point = painter.text(max_geometry, m_text, PaintTextAlign::Center, PANGO_ELLIPSIZE_END); auto point = painter.text(max_geometry, m_text, PaintTextAlign::Center, PANGO_ELLIPSIZE_END, set_size);
resize(point); resize(point);
painter.fill(); painter.fill();
} }

View file

@ -11,10 +11,20 @@ enum class EventType {
MouseButton, MouseButton,
MouseMove, MouseMove,
WidgetRepaintRequested, Reflow,
FocusUpdate, FocusUpdate,
ActivationUpdate, ActivationUpdate,
WidgetRelayoutRequestedEvent };
enum class ReflowType {
RepaintSubtree,
RelayoutSubtree,
RepaintSelf
};
enum class ReflowGrouping {
Yes,
No
}; };
class Event { class Event {
@ -65,26 +75,23 @@ public:
Point &point() { return m_point; } Point &point() { return m_point; }
}; };
class WidgetRepaintRequestedEvent : public Event { class ReflowEvent: public Event {
private: private:
bool m_should_do_group { false }; ReflowType m_reflow_type;
ReflowGrouping m_reflow_grouping;
public: public:
WidgetRepaintRequestedEvent(bool should_do_group) ReflowEvent(ReflowType type, ReflowGrouping grouping)
: m_should_do_group(should_do_group) {} : m_reflow_type(type)
, m_reflow_grouping(grouping) {}
EventType type() { return EventType::WidgetRepaintRequested; } EventType type() { return EventType::Reflow; }
const char *name() { return "WidgetRepaintRequested"; } const char *name() { return "Reflow"; }
bool should_do_group() { return m_should_do_group; } ReflowType reflow_type() { return m_reflow_type; }
void set_should_do_group(bool should_do_group) { m_should_do_group = should_do_group; } ReflowGrouping reflow_grouping() { return m_reflow_grouping; }
};
class WidgetRelayoutRequestedEvent : public Event { void set_reflow_grouping(ReflowGrouping reflow_grouping) { m_reflow_grouping = reflow_grouping; }
public: void set_reflow_type(ReflowType reflow_type) { m_reflow_type = reflow_type; }
WidgetRelayoutRequestedEvent() {}
EventType type() { return EventType::WidgetRelayoutRequestedEvent; }
const char *name() { return "WidgetRelayoutRequestedEvent"; }
}; };
class FocusUpdateEvent : public Event { class FocusUpdateEvent : public Event {

View file

@ -20,10 +20,11 @@ void Label::on_paint() {
auto painter = window()->painter(); auto painter = window()->painter();
auto text_color = styles()->label_text_color(); auto text_color = styles()->label_text_color();
auto text_geometry = current_geometry().max_geometry(); auto text_geometry = current_geometry().max_geometry();
bool set_size = current_geometry().max_width() != -1 && current_geometry().max_height() != -1;
painter.source_rgb(text_color); painter.source_rgb(text_color);
painter.set_pango_font_description(styles()->controls_font_description()); painter.set_pango_font_description(styles()->controls_font_description());
auto point = painter.text(text_geometry, m_text, PaintTextAlign::Left, PANGO_ELLIPSIZE_NONE); auto point = painter.text(text_geometry, m_text, PaintTextAlign::Left, PANGO_ELLIPSIZE_NONE, set_size);
resize(point); resize(point);
painter.fill(); painter.fill();
} }

View file

@ -39,7 +39,7 @@ bool Painter::text(Point &where, std::string &text) {
return true; return true;
} }
Point Painter::text(Box &geometry, std::string &text, PaintTextAlign align, PangoEllipsizeMode ellipsize) { Point Painter::text(Box &geometry, std::string &text, PaintTextAlign align, PangoEllipsizeMode ellipsize, bool set_size) {
if (m_pango_font_description == nullptr) if (m_pango_font_description == nullptr)
return {-1,-1}; return {-1,-1};
@ -51,9 +51,9 @@ Point Painter::text(Box &geometry, std::string &text, PaintTextAlign align, Pang
int pango_height; int pango_height;
pango_layout_set_font_description(layout, m_pango_font_description); pango_layout_set_font_description(layout, m_pango_font_description);
if (geometry.width() > 0) if (geometry.width() > 0 && set_size)
pango_layout_set_width(layout, pango_units_from_double(geometry.width())); pango_layout_set_width(layout, pango_units_from_double(geometry.width()));
if (geometry.height() > 0) if (geometry.height() > 0 && set_size)
pango_layout_set_height(layout, pango_units_from_double(geometry.height())); pango_layout_set_height(layout, pango_units_from_double(geometry.height()));
pango_layout_set_ellipsize(layout, ellipsize); pango_layout_set_ellipsize(layout, ellipsize);
pango_layout_set_text(layout, text.c_str(), -1); pango_layout_set_text(layout, text.c_str(), -1);

View file

@ -29,7 +29,7 @@ public:
void rounded_rectangle(Box &geometry, double border_radius); void rounded_rectangle(Box &geometry, double border_radius);
bool text(Point &where, std::string &text); bool text(Point &where, std::string &text);
Point text(Box &geometry, std::string &text, PaintTextAlign align, PangoEllipsizeMode ellipsize); Point text(Box &geometry, std::string &text, PaintTextAlign align, PangoEllipsizeMode ellipsize, bool set_size);
bool can_paint() { if (m_cairo) return true; else return false; } bool can_paint() { if (m_cairo) return true; else return false; }

View file

@ -31,10 +31,8 @@ void Widget::move_to(double x, double y) {
} }
void Widget::do_layout() { void Widget::do_layout() {
if (m_layout) { if (m_layout)
m_layout->run(); m_layout->run();
wants_repaint(); // TODO: should relayout really repaint as well?
}
} }
void Widget::set_layout(std::shared_ptr<Layout> layout) { void Widget::set_layout(std::shared_ptr<Layout> layout) {
@ -114,7 +112,7 @@ void Widget::wants_full_relayout() {
m_window->dispatch_full_relayout(); m_window->dispatch_full_relayout();
} }
void Widget::handle_repaint(WidgetRepaintRequestedEvent &event) { void Widget::handle_reflow(ReflowEvent &event) {
// immediately accept the event - we will do our own propagation logic // immediately accept the event - we will do our own propagation logic
event.accept(); event.accept();
@ -122,29 +120,35 @@ void Widget::handle_repaint(WidgetRepaintRequestedEvent &event) {
return; return;
auto painter = m_window->painter(); auto painter = m_window->painter();
if (!painter.can_paint()) if (!painter.can_paint())
return; return;
auto cr = painter.cairo(); auto cr = painter.cairo();
auto event_should_do_group = event.should_do_group(); auto grouping = event.reflow_grouping();
auto type = event.reflow_type();
if (event_should_do_group) { if (grouping == ReflowGrouping::Yes) {
painter.begin_paint_group(); painter.begin_paint_group();
} }
if (type == ReflowType::RelayoutSubtree) {
do_layout();
}
cr->save(); cr->save();
on_paint(); on_paint();
cr->restore(); cr->restore();
// we will propagate this event to all of our children, except it will have if (type != ReflowType::RepaintSelf) {
// should_do_group set to false // we will propagate this event to all of our children, except it will have
event.set_should_do_group(false); // should_do_group set to false
for (auto& child : m_children) { event.set_reflow_grouping(ReflowGrouping::No);
child->dispatch_event(event); for (auto& child : m_children) {
child->dispatch_event(event);
}
} }
if (event_should_do_group) { if (grouping == ReflowGrouping::Yes) {
painter.end_paint_group(); painter.end_paint_group();
} }
} }
@ -207,12 +211,8 @@ void Widget::dispatch_event(Event &event) {
handle_mouse_button_event(reinterpret_cast<MouseButtonEvent&>(event)); handle_mouse_button_event(reinterpret_cast<MouseButtonEvent&>(event));
break; break;
} }
case EventType::WidgetRepaintRequested: { case EventType::Reflow: {
handle_repaint(reinterpret_cast<WidgetRepaintRequestedEvent&>(event)); handle_reflow(reinterpret_cast<ReflowEvent&>(event));
break;
}
case EventType::WidgetRelayoutRequestedEvent: {
do_layout();
break; break;
} }
/* these events aren't handled here, as they won't be dispatched to us from other places */ /* these events aren't handled here, as they won't be dispatched to us from other places */

View file

@ -132,7 +132,7 @@ private:
void wants_full_repaint(); void wants_full_repaint();
void wants_full_relayout(); void wants_full_relayout();
void do_layout(); void do_layout();
void handle_repaint(WidgetRepaintRequestedEvent& event); void handle_reflow(ReflowEvent& event);
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);
}; };

View file

@ -61,12 +61,12 @@ bool Window::spawn_window() {
} }
void Window::widget_repaint(Widget *target) { void Window::widget_repaint(Widget *target) {
auto event = WidgetRepaintRequestedEvent(true); auto event = ReflowEvent(ReflowType::RepaintSubtree, ReflowGrouping::Yes);
target->dispatch_event(event); target->dispatch_event(event);
} }
void Window::widget_relayout(Widget *target) { void Window::widget_relayout(Widget *target) {
auto event = WidgetRelayoutRequestedEvent(); auto event = ReflowEvent(ReflowType::RelayoutSubtree, ReflowGrouping::Yes);
target->dispatch_event(event); target->dispatch_event(event);
} }
@ -79,12 +79,12 @@ bool Window::dispatch_to_main_widget(Event &event) {
} }
bool Window::dispatch_full_repaint() { bool Window::dispatch_full_repaint() {
auto event = WidgetRepaintRequestedEvent(true); auto event = ReflowEvent(ReflowType::RepaintSubtree, ReflowGrouping::Yes);
return dispatch_to_main_widget(event); return dispatch_to_main_widget(event);
} }
bool Window::dispatch_full_relayout() { bool Window::dispatch_full_relayout() {
auto event = WidgetRelayoutRequestedEvent(); auto event = ReflowEvent(ReflowType::RelayoutSubtree, ReflowGrouping::Yes);
return dispatch_to_main_widget(event); return dispatch_to_main_widget(event);
} }
@ -118,7 +118,6 @@ void Window::run(bool block) {
} }
case Expose: { case Expose: {
if (e.xexpose.count == 0) { if (e.xexpose.count == 0) {
// TODO: hack
// might run into issues with other X implementations... :( // might run into issues with other X implementations... :(
dispatch_full_repaint(); dispatch_full_repaint();
} }