165 lines
4.6 KiB
C++
165 lines
4.6 KiB
C++
#pragma once
|
|
|
|
#include <psemek/ui/shape.hpp>
|
|
#include <psemek/ui/event.hpp>
|
|
#include <psemek/ui/painter.hpp>
|
|
#include <psemek/ui/style.hpp>
|
|
|
|
#include <psemek/async/event_loop.hpp>
|
|
|
|
#include <psemek/util/span.hpp>
|
|
#include <psemek/util/function.hpp>
|
|
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <any>
|
|
|
|
namespace psemek::ui
|
|
{
|
|
|
|
struct element
|
|
: std::enable_shared_from_this<element>
|
|
{
|
|
virtual element * parent() const { return parent_; }
|
|
virtual void set_parent(element * parent);
|
|
|
|
using children_range = util::span<element * const>;
|
|
|
|
virtual children_range children() const { return {}; }
|
|
|
|
virtual element * root();
|
|
virtual element const * root() const;
|
|
virtual async::event_loop * loop() const;
|
|
virtual void set_loop(async::event_loop * loop);
|
|
|
|
virtual geom::box<float, 2> events_bbox() const;
|
|
|
|
virtual bool on_event(mouse_move const &) { return false; }
|
|
virtual bool on_event(mouse_click const &) { return false; }
|
|
virtual bool on_event(mouse_wheel const &) { return false; }
|
|
virtual bool on_event(key_press const &) { return false; }
|
|
virtual bool on_event(text_input const &) { return false; }
|
|
|
|
virtual bool focused() const { return false; }
|
|
|
|
virtual struct shape const & shape() const = 0;
|
|
virtual void reshape(geom::box<float, 2> const & bbox) = 0;
|
|
virtual void reshape();
|
|
|
|
// Constraints on the element's width & height, assuming unlimited available space
|
|
virtual geom::box<float, 2> size_constraints() const;
|
|
|
|
// Constraints on the element's width, assuming fixed height
|
|
virtual geom::interval<float> width_constraints(float height) const;
|
|
|
|
// Constraints on the element's height, assuming fixed width
|
|
virtual geom::interval<float> height_constraints(float width) const;
|
|
|
|
virtual bool enabled() const { return enabled_; }
|
|
virtual void set_enabled(bool value) { enabled_ = value; }
|
|
virtual void enable() { set_enabled(true); }
|
|
virtual void disable() { set_enabled(false); }
|
|
|
|
virtual bool hidden() const { return hidden_; }
|
|
virtual void set_hidden(bool value) { hidden_ = value; }
|
|
virtual void hide() { set_hidden(true); }
|
|
virtual void show() { set_hidden(false); }
|
|
|
|
virtual bool transparent() const { return false; }
|
|
|
|
virtual std::shared_ptr<struct style> style() const { return style_; }
|
|
virtual std::shared_ptr<struct style> own_style() const { return own_style_; }
|
|
virtual std::shared_ptr<struct style> set_style(std::shared_ptr<struct style> st);
|
|
virtual std::shared_ptr<struct style> set_own_style(std::shared_ptr<struct style> st);
|
|
|
|
virtual void style_updated() const;
|
|
virtual void own_style_updated() const;
|
|
|
|
virtual std::optional<std::string> const & id() const { return id_; }
|
|
virtual std::optional<std::string> set_id(std::optional<std::string> id);
|
|
|
|
virtual std::optional<std::string> const & hint() const { return hint_; }
|
|
virtual std::optional<std::string> set_hint(std::optional<std::string> hint);
|
|
|
|
virtual std::any const & data() const { return data_; }
|
|
virtual std::any & data() { return data_; }
|
|
|
|
virtual void update(float /* dt */) {}
|
|
|
|
virtual void draw(painter & p) const = 0;
|
|
virtual void post_draw(painter & /* p */) const {}
|
|
|
|
virtual ~element();
|
|
|
|
virtual void post(util::function<void()> f) const;
|
|
virtual void post_reshape();
|
|
|
|
protected:
|
|
virtual void release_children();
|
|
|
|
virtual std::shared_ptr<struct style> merged_style() const;
|
|
virtual std::shared_ptr<struct style> merged_own_style() const;
|
|
|
|
static bool in_text_input();
|
|
static void start_text_input();
|
|
static void stop_text_input();
|
|
|
|
private:
|
|
element * parent_ = nullptr;
|
|
async::event_loop * loop_ = nullptr;
|
|
std::shared_ptr<struct style> style_;
|
|
std::shared_ptr<struct style> own_style_;
|
|
mutable std::shared_ptr<struct style> merged_style_;
|
|
mutable std::shared_ptr<struct style> merged_own_style_;
|
|
|
|
bool reshape_posted_ = false;
|
|
bool enabled_ = true;
|
|
bool hidden_ = false;
|
|
|
|
mutable std::vector<util::function<void()>> delayed_callbacks_;
|
|
|
|
std::optional<std::string> id_;
|
|
std::optional<std::string> hint_;
|
|
|
|
std::any data_;
|
|
|
|
void post_delayed_callbacks() const;
|
|
};
|
|
|
|
template <typename Type>
|
|
Type * find_first_parent_of_type(element * e)
|
|
{
|
|
while (true)
|
|
{
|
|
if (!e)
|
|
return nullptr;
|
|
|
|
if (auto p = dynamic_cast<Type *>(e))
|
|
return p;
|
|
|
|
e = e->parent();
|
|
}
|
|
}
|
|
|
|
template <typename Type>
|
|
Type * find_last_parent_of_type(element * e)
|
|
{
|
|
Type * r = nullptr;
|
|
while (true)
|
|
{
|
|
if (auto p = find_first_parent_of_type<Type>(e))
|
|
{
|
|
r = p;
|
|
e = p->parent();
|
|
}
|
|
else
|
|
return r;
|
|
}
|
|
}
|
|
|
|
element * find_element_by_id(element * root, std::string_view id);
|
|
|
|
void send_fake_mouse_move_event(element * e, bool mouseover);
|
|
|
|
}
|