#pragma once #include #include namespace sixtyfps::internal { // Workaround https://github.com/eqrion/cbindgen/issues/43 struct ComponentVTable; struct ItemVTable; } #include "sixtyfps_internal.h" #include "sixtyfps_gl_internal.h" namespace sixtyfps { extern "C" { extern const internal::ItemVTable RectangleVTable; extern const internal::ItemVTable TextVTable; extern const internal::ItemVTable TouchAreaVTable; extern const internal::ItemVTable ImageVTable; } // Bring opaque structure in scope using internal::ComponentVTable; using internal::ItemTreeNode; using ComponentRef = VRef; using ItemVisitorRefMut = VRefMut; struct ComponentWindow { ComponentWindow() { internal::sixtyfps_component_window_gl_renderer_init(&inner); } ~ComponentWindow() { internal::sixtyfps_component_window_drop(&inner); } ComponentWindow(const ComponentWindow &) = delete; ComponentWindow(ComponentWindow &&) = delete; ComponentWindow &operator=(const ComponentWindow &) = delete; template void run(Component *c) { sixtyfps_component_window_run(&inner, VRefMut { &Component::component_type, c }); } private: internal::ComponentWindowOpaque inner; }; using internal::EvaluationContext; using internal::Image; using internal::Rectangle; using internal::Text; using internal::TouchArea; // the component has static lifetime so it does not need to be destroyed // FIXME: we probably need some kind of way to dinstinguish static component and // these on the heap inline void dummy_destory(ComponentRef) { } constexpr inline ItemTreeNode make_item_node(std::uintptr_t offset, const internal::ItemVTable *vtable, uint32_t child_count, uint32_t child_index) { return ItemTreeNode { ItemTreeNode::Item_Body { ItemTreeNode::Tag::Item, {vtable, offset}, child_count, child_index } }; } constexpr inline ItemTreeNode make_dyn_node(std::uintptr_t offset) { return ItemTreeNode { ItemTreeNode::DynamicTree_Body { ItemTreeNode::Tag::DynamicTree, offset } }; } using internal::sixtyfps_visit_item_tree; // layouts: using internal::Slice; using internal::solve_grid_layout; using internal::GridLayoutCellData; using internal::GridLayoutData; using internal::Constraint; // models struct Model { virtual ~Model() = default; Model() = default; Model(const Model &) = delete; Model &operator=(const Model &) = delete; virtual int count() const = 0; virtual const void *get(int i) const = 0; }; template struct ArrayModel : Model { std::array data; template ArrayModel(A &&... a) : data { std::forward(a)... } { } ArrayModel(int x) { } int count() const override { return Count; } const void *get(int i) const override { return &data[i]; } }; struct IntModel : Model { IntModel(int d) : data(d) { } int data; int count() const override { return data; } const void *get(int) const override { return &data; } }; template struct Repeater { std::vector> data; void update_model(Model *model) { data.clear(); auto count = model->count(); for (auto i = 0; i < count; ++i) { auto x = std::make_unique(); x->update_data(i, model->get(i)); data.push_back(std::move(x)); } } void visit(ItemVisitorRefMut visitor) const { for (const auto &x : data) { VRef ref{&C::component_type, x.get()}; ref.vtable->visit_children_item(ref, -1, visitor); } } }; } // namespace sixtyfps