src/view.cpp in reflexion-0.1.38 vs src/view.cpp in reflexion-0.1.39
- old
+ new
@@ -1,8 +1,9 @@
#include "view.h"
+#include <limits.h>
#include <assert.h>
#include <memory>
#include <algorithm>
#include <rays/matrix.h>
#include "reflex/timer.h"
@@ -45,34 +46,39 @@
UPDATE_SHAPES = Xot::bit(4, FLAG_LAST),
UPDATE_LAYOUT = Xot::bit(5, FLAG_LAST),
- FIT_TO_CONTENT = Xot::bit(6, FLAG_LAST),
+ SORT_CHILDREN = Xot::bit(6, FLAG_LAST),
- HAS_VARIABLE_LENGTHS = Xot::bit(7, FLAG_LAST),
+ FIT_TO_CONTENT = Xot::bit(7, FLAG_LAST),
- NO_SHAPE = Xot::bit(8, FLAG_LAST),
+ HAS_VARIABLE_LENGTHS = Xot::bit(8, FLAG_LAST),
+ NO_SHAPE = Xot::bit(9, FLAG_LAST),
+
};// Flag
- Window* window = NULL;
+ Window* window = NULL;
- View* parent = NULL;
+ View* parent = NULL;
Bounds frame;
- float zoom = 1;
+ float zoom = 1;
- float angle = 0;
+ float angle = 0;
- ushort capture = CAPTURE_NONE;
+ ushort capture = CAPTURE_NONE;
- short hide_count = 0;
+ short hide_count = 0;
- uint flags = FLAG_CLIP | FLAG_RESIZE_TO_FIT | REDRAW | UPDATE_LAYOUT | UPDATE_STYLE;
+ ushort child_index = 0;
+ uint flags =
+ FLAG_CLIP | FLAG_RESIZE_TO_FIT | REDRAW | UPDATE_LAYOUT | UPDATE_STYLE;
+
std::unique_ptr<Point> ppivot;
std::unique_ptr<Point> pscroll;
SelectorPtr pselector;
@@ -97,10 +103,12 @@
std::unique_ptr<World> pchild_world;
std::unique_ptr<ChildList> pchildren;
+ std::unique_ptr<ChildList> pchildren_sorted;
+
Point& pivot ()
{
if (!ppivot) ppivot.reset(new Point);
return *ppivot;
}
@@ -241,13 +249,14 @@
void
get_body2view_matrix (Matrix* m)
{
assert(m && *m == 1 && ppivot && *ppivot != 0 && pbody);
+ Point pos = pbody->position();
Point pivot = *ppivot * frame.size();
float angle = pbody->angle();
- m->translate(pbody->position())
+ m->translate(pos.x, pos.y, frame.z)
.rotate(angle)
.translate( pivot)
.rotate(-angle)
.translate(-pivot);
}
@@ -302,16 +311,30 @@
for (auto& wall : view->find_children(WALL_NAME))
view->remove_child(wall.get());
}
- ChildList& children ()
+ ChildList* children (bool create = false, bool sort = false)
{
- if (!pchildren) pchildren.reset(new ChildList);
- return *pchildren;
+ if (!pchildren)
+ {
+ if (!create) return NULL;
+ pchildren.reset(new ChildList);
+ }
+
+ if (sort && check_and_remove_flag(SORT_CHILDREN))
+ do_sort_children();
+
+ return sort && pchildren_sorted ? pchildren_sorted.get() : pchildren.get();
}
+ void sort_children (bool order_only = false)
+ {
+ add_flag(SORT_CHILDREN);
+ if (!order_only && pchildren_sorted) pchildren_sorted.reset();
+ }
+
void add_flag (uint flag)
{
Xot::add_flag(&flags, flag);
}
@@ -328,10 +351,54 @@
bool check_and_remove_flag (uint flag)
{
return Xot::check_and_remove_flag(&flags, flag);
}
+ private:
+
+ void do_sort_children ()
+ {
+ assert(pchildren);
+
+ auto& children = *pchildren;
+
+ size_t size = children.size();
+ if (size >= USHRT_MAX)
+ invalid_state_error(__FILE__, __LINE__, "too many children");
+
+ ushort index = 0;
+ bool have_z = false;
+ for (auto& child : children)
+ {
+ child->self->child_index = index++;
+ have_z |= child->frame().z != 0;
+ }
+
+ if (!have_z)
+ {
+ pchildren_sorted.reset();
+ return;
+ }
+
+ if (!pchildren_sorted)
+ {
+ pchildren_sorted.reset(
+ new ChildList(children.begin(), children.end()));
+ }
+
+ std::sort(
+ pchildren_sorted->begin(), pchildren_sorted->end(),
+ [](const auto& a, const auto& b)
+ {
+ auto *aa = a->self.get(), *bb = b->self.get();
+ if (aa->frame.z != bb->frame.z)
+ return aa->frame.z < bb->frame.z;
+ else
+ return aa->child_index < bb->child_index;
+ });
+ }
+
};// View::Data
class LayoutContext
{
@@ -349,22 +416,22 @@
get_flow_sign(&flow_sub_h, &flow_sub_v, flow_sub);
}
void place_children ()
{
- View::ChildList* pchildren = parent->self->pchildren.get();
- if (!pchildren || pchildren->empty())
+ View::ChildList* children = parent->self->children();
+ if (!children || children->empty())
return;
bool leftward = flow_main_h < 0 || flow_sub_h < 0;
bool upward = flow_main_v < 0 || flow_sub_v < 0;
Point start_position(
leftward ? parent_frame.width : 0,
upward ? parent_frame.height : 0);
Point position = start_position;
- for (iterator begin = pchildren->begin(), end = pchildren->end(); true;)
+ for (iterator begin = children->begin(), end = children->end(); true;)
{
iterator line_end;
coord main_fill_size = 0;
coord sub_size_max = 0;
calc_line(&line_end, &main_fill_size, &sub_size_max, begin, end);
@@ -651,15 +718,15 @@
}
view->self->window = window;
view->self->update_body_and_shapes();
- View::ChildList* pchildren = view->self->pchildren.get();
- if (pchildren)
+ View::ChildList* children = view->self->children();
+ if (children)
{
- for (auto& pchild : *pchildren)
- View_set_window(pchild.get(), window);
+ for (auto& child : *children)
+ View_set_window(child.get(), window);
}
if (view->self->window)
{
Event e;
@@ -671,19 +738,19 @@
static void
apply_style_to_children_have_variable_lengths (View* parent)
{
assert(parent);
- View::ChildList* pchildren = parent->self->pchildren.get();
- if (!pchildren) return;
+ View::ChildList* children = parent->self->children();
+ if (!children) return;
- for (auto& pchild : *pchildren)
+ for (auto& child : *children)
{
- assert(pchild);
+ assert(child);
- if (pchild->self->has_flag(View::Data::HAS_VARIABLE_LENGTHS))
- pchild->self->add_flag(View::Data::APPLY_STYLE);
+ if (child->self->has_flag(View::Data::HAS_VARIABLE_LENGTHS))
+ child->self->add_flag(View::Data::APPLY_STYLE);
}
}
static void
update_view_layout (View* view, bool update_parent = false)
@@ -731,10 +798,13 @@
}
if (update_body && (moved || rotated) && self->pbody)
self->update_body_frame();
+ if (moved && event.dz() != 0 && self->parent)
+ self->parent->self->sort_children(true);
+
if ((moved || resized) && self->parent)
self->parent->self->add_flag(View::Data::FIT_TO_CONTENT);
view->redraw();
}
@@ -777,23 +847,23 @@
View::ChildList* result, const View* view, const Selector& selector,
bool recursive)
{
assert(result && view);
- View::ChildList* pchildren = view->self->pchildren.get();
- if (!pchildren) return;
+ View::ChildList* children = view->self->children();
+ if (!children) return;
- for (auto& pchild : *pchildren)
+ for (auto& child : *children)
{
- if (!pchild)
+ if (!child)
invalid_state_error(__FILE__, __LINE__);
- if (pchild->selector().contains(selector))
- result->push_back(pchild);
+ if (child->selector().contains(selector))
+ result->push_back(child);
if (recursive)
- find_all_children(result, pchild.get(), selector, true);
+ find_all_children(result, child.get(), selector, true);
}
}
static void
find_all_styles (
@@ -812,15 +882,15 @@
}
}
if (!recursive) return;
- View::ChildList* pchildren = view->self->pchildren.get();
- if (pchildren)
+ View::ChildList* children = view->self->children();
+ if (children)
{
- for (auto& pchild : *pchildren)
- find_all_styles(result, pchild.get(), selector, true);
+ for (auto& child : *children)
+ find_all_styles(result, child.get(), selector, true);
}
}
static void
fire_timers (View* view, double now)
@@ -864,11 +934,14 @@
Matrix m;
self->get_body2view_matrix(&m);
frame.set_position(m * Point(0));
}
else
- frame.set_position(body->position());
+ {
+ Point pos = body->position();
+ frame.set_position(pos.x, pos.y, frame.z);
+ }
update_view_frame(view, frame, view->zoom(), body->angle(), false);
}
static void
@@ -880,15 +953,15 @@
World* child_world = self->pchild_world.get();
if (!child_world) return;
child_world->on_update(dt);
- View::ChildList* pchildren = self->pchildren.get();
- if (pchildren)
+ View::ChildList* children = self->children();
+ if (children)
{
- for (auto& pchild : *pchildren)
- update_view_body(pchild.get());
+ for (auto& child : *children)
+ update_view_body(child.get());
}
}
static void
update_views_for_selectors (View* view)
@@ -908,12 +981,12 @@
if (view_sel && view_sel->contains(sel))
self->add_flag(View::Data::UPDATE_STYLE);
children.clear();
find_all_children(&children, view, sel, true);
- for (auto& pchild : children)
- pchild->self->add_flag(View::Data::UPDATE_STYLE);
+ for (auto& child : children)
+ child->self->add_flag(View::Data::UPDATE_STYLE);
}
sels->clear();
}
@@ -1008,15 +1081,15 @@
View::Data* self = view->self.get();
fire_timers(view, event.now());
- View::ChildList* pchildren = self->pchildren.get();
- if (pchildren)
+ View::ChildList* children = self->children();
+ if (children)
{
- for (auto& pchild : *pchildren)
- View_update_tree(pchild.get(), event);
+ for (auto& child : *children)
+ View_update_tree(child.get(), event);
}
update_view_shapes(view);
update_child_world(view, event.dt());
@@ -1146,17 +1219,17 @@
p->pop_state();
if (event->is_blocked()) return;
- View::ChildList* pchildren = self->pchildren.get();
- if (pchildren)
+ View::ChildList* children = self->children(false, true);
+ if (children)
{
- for (auto& pchild : *pchildren)
+ for (auto& child : *children)
{
- if (event->bounds() & pchild->self->frame)
- View_draw_tree(pchild.get(), event, offset, clip);
+ if (event->bounds() & child->self->frame)
+ View_draw_tree(child.get(), event, offset, clip);
}
}
World* child_world = self->pchild_world.get();
if (child_world)
@@ -1319,19 +1392,18 @@
default: break;
}
}
static void
- call_children (View* parent, std::function<bool(View*)> fun)
+ call_children (View* parent, std::function<bool(View*)> fun, bool sort = true)
{
assert(parent);
- auto* pchildren = parent->self->pchildren.get();
- if (!pchildren) return;
+ auto* children = parent->self->children(false, sort);
+ if (!children) return;
- auto end = pchildren->rend();
- for (auto it = pchildren->rbegin(); it != end; ++it)
+ for (auto it = children->rbegin(), end = children->rend(); it != end; ++it)
{
if (!fun(it->get()))
break;
}
}
@@ -1365,10 +1437,13 @@
case Pointer::UP: view->on_pointer_up(event); break;
case Pointer::MOVE: view->on_pointer_move(event); break;
case Pointer::CANCEL: view->on_pointer_cancel(event); break;
default: break;
}
+
+ if (!event->is_captured())
+ PointerEvent_increment_view_indices(event);
}
static void
register_captures (View* view, const PointerEvent& event)
{
@@ -1379,11 +1454,11 @@
invalid_state_error(__FILE__, __LINE__);
PointerEvent_each_pointer(&event, [&](const auto& pointer)
{
if (pointer.action() == Pointer::DOWN)
- Window_register_capture(win, view, pointer.id());
+ Window_register_capture(win, view, pointer.id(), pointer.view_index());
});
}
static void
unregister_captures (View* view, const PointerEvent& event)
@@ -1708,20 +1783,23 @@
static void
erase_child_from_children (View* parent, View* child)
{
assert(parent && child);
- View::ChildList* children = parent->self->pchildren.get();
+ View::ChildList* children = parent->self->children();
if (!children) return;
auto end = children->end();
auto it = std::find(children->begin(), end, child);
assert(it != end);
children->erase(it);
if (children->empty())
+ {
parent->self->pchildren.reset();
+ parent->self->pchildren_sorted.reset();
+ }
}
void
View::add_child (View* child)
{
@@ -1733,18 +1811,20 @@
if (found && belong)
return;
else if (found != belong)
invalid_state_error(__FILE__, __LINE__);
- self->children().push_back(child);
+ self->children(true)->push_back(child);
View* prev_parent = child->parent();
set_parent(child, this);
if (prev_parent)
erase_child_from_children(prev_parent, child);
+ self->sort_children();
+
update_view_layout(this);
}
void
View::remove_child (View* child)
@@ -1761,20 +1841,22 @@
set_parent(child, NULL);
erase_child_from_children(this, child);
+ self->sort_children();
+
update_view_layout(this);
}
void
View::clear_children ()
{
- if (!self->pchildren || self->pchildren->empty()) return;
+ auto* children = self->children();
+ if (!children || children->empty()) return;
- auto children = *self->pchildren;
- for (auto& child : children)
+ for (auto& child : *children)
remove_child(child);
}
View::ChildList
View::find_children (const Selector& selector, bool recursive) const
@@ -2262,12 +2344,12 @@
bool registered = old != CAPTURE_NONE;
bool capture = types != CAPTURE_NONE;
if (capture && !registered)
- Window_register_capture(w, this);
+ Window_register_capture(w, this, CAPTURE_ALL);
else if (!capture && registered)
- Window_unregister_capture(w, this);
+ Window_unregister_capture(w, this, CAPTURE_ALL);
CaptureEvent e(~old & types, old & ~types);
on_capture(&e);
}