167 lines
6.0 KiB
C++
167 lines
6.0 KiB
C++
#pragma once
|
|
#include <functional>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
#include "../Axis/export.h"
|
|
#include "../base/Color.h"
|
|
#include "../base/Geometry.h"
|
|
#include "../base/Style.h"
|
|
#include "../base/Text.h"
|
|
#include "../render/Canvas.h"
|
|
namespace renderive {
|
|
struct Hover_Tooltip_State;
|
|
struct Hover_Tooltip_Provider;
|
|
struct LIB_DECL Hover_Tooltip_State {
|
|
virtual ~Hover_Tooltip_State() = default;
|
|
Hover_Tooltip_State() {
|
|
tooltip_background_brush = Brush{Color::white(), Brush_Style::Solid};
|
|
tooltip_text_pen = Pen{Color::black()};
|
|
}
|
|
int hover_info_left = 4;
|
|
int hover_info_top = 4;
|
|
int hover_info_right = 4;
|
|
int hover_info_bottom = 4;
|
|
Brush tooltip_background_brush;
|
|
Font hover_info_font;
|
|
Pen tooltip_text_pen;
|
|
bool use_hover_tooltip = true;
|
|
bool hover_info_active = false;
|
|
Point hover_position;
|
|
void draw_hover_tooltip(Canvas* canvas, Abs_Axis* domain_axis, Abs_Axis* value_axis, Hover_Tooltip_Provider* renderable);
|
|
bool can_show_hover(Renderable* able) const;
|
|
};
|
|
struct LIB_DECL Hover_Tooltip_Provider {
|
|
struct Hover_State_Edit {
|
|
Hover_State_Edit() = default;
|
|
Hover_State_Edit(Hover_Tooltip_Provider* owner, Hover_Tooltip_State* state, std::function<void()> on_finish)
|
|
: owner(owner), state(state), on_finish(std::move(on_finish)) {}
|
|
Hover_State_Edit(const Hover_State_Edit&) = delete;
|
|
Hover_State_Edit& operator=(const Hover_State_Edit&) = delete;
|
|
Hover_State_Edit(Hover_State_Edit&& other) noexcept
|
|
: owner(std::exchange(other.owner, nullptr)),
|
|
state(std::exchange(other.state, nullptr)),
|
|
on_finish(std::move(other.on_finish)) {}
|
|
Hover_State_Edit& operator=(Hover_State_Edit&& other) noexcept {
|
|
if (this == &other)
|
|
return *this;
|
|
finish();
|
|
owner = std::exchange(other.owner, nullptr);
|
|
state = std::exchange(other.state, nullptr);
|
|
on_finish = std::move(other.on_finish);
|
|
return *this;
|
|
}
|
|
~Hover_State_Edit() {
|
|
finish();
|
|
}
|
|
Hover_Tooltip_State* operator->() const {
|
|
return state;
|
|
}
|
|
private:
|
|
void finish() {
|
|
if (!owner)
|
|
return;
|
|
if (on_finish)
|
|
on_finish();
|
|
on_finish = {};
|
|
owner = nullptr;
|
|
state = nullptr;
|
|
}
|
|
Hover_Tooltip_Provider* owner{};
|
|
Hover_Tooltip_State* state{};
|
|
std::function<void()> on_finish{};
|
|
};
|
|
virtual std::vector<std::string> build_hover_lines(Abs_Axis* h, Abs_Axis* v, Point pos);
|
|
virtual ~Hover_Tooltip_Provider() = default;
|
|
virtual void draw_hover_tooltip(Canvas* canvas, Abs_Axis* h, Abs_Axis* v) {
|
|
return hover_render_state()->draw_hover_tooltip(canvas, h, v, this);
|
|
}
|
|
virtual bool hover_ok(Renderable* able) {
|
|
return hover_render_state()->can_show_hover(able);
|
|
}
|
|
virtual bool hit_test_hover(Point pos) {
|
|
(void)pos;
|
|
return true;
|
|
}
|
|
bool hover_tooltip_enabled() {
|
|
return hover_edit_state()->use_hover_tooltip;
|
|
}
|
|
void set_use_hover_info(bool use) {
|
|
auto edit = begin_hover_edit();
|
|
edit->use_hover_tooltip = use;
|
|
}
|
|
void set_hover_tooltip_font(const Font& font) {
|
|
auto edit = begin_hover_edit();
|
|
edit->hover_info_font = font;
|
|
}
|
|
Font hover_tooltip_font() {
|
|
return hover_edit_state()->hover_info_font;
|
|
}
|
|
Brush hover_info_background_brush() {
|
|
return hover_edit_state()->tooltip_background_brush;
|
|
}
|
|
void set_hover_tooltip_background_brush(const Brush& brush) {
|
|
auto edit = begin_hover_edit();
|
|
edit->tooltip_background_brush = brush.color.a != 0 ? brush : Brush{};
|
|
}
|
|
Pen tooltip_text_pen() {
|
|
return hover_edit_state()->tooltip_text_pen;
|
|
}
|
|
void set_tooltip_text_pen(const Pen& pen) {
|
|
auto edit = begin_hover_edit();
|
|
edit->tooltip_text_pen = pen.color.a != 0 ? pen : Pen{.style = Line_Style::None};
|
|
}
|
|
void get_hover_tooltip_contents_margins(int& left, int& top, int& right, int& bottom) {
|
|
auto s = hover_edit_state();
|
|
left = s->hover_info_left;
|
|
top = s->hover_info_top;
|
|
right = s->hover_info_right;
|
|
bottom = s->hover_info_bottom;
|
|
}
|
|
void set_hover_tooltip_contents_margins(int left, int top, int right, int bottom) {
|
|
auto edit = begin_hover_edit();
|
|
edit->hover_info_left = left;
|
|
edit->hover_info_top = top;
|
|
edit->hover_info_right = right;
|
|
edit->hover_info_bottom = bottom;
|
|
}
|
|
Hover_State_Edit begin_hover_edit() {
|
|
return begin_hover_edit_impl();
|
|
}
|
|
private:
|
|
virtual Hover_Tooltip_State* hover_edit_state() = 0;
|
|
virtual Hover_Tooltip_State* hover_render_state() = 0;
|
|
virtual Hover_State_Edit begin_hover_edit_impl() = 0;
|
|
};
|
|
template <typename That>
|
|
struct LIB_DECL Hover_Tooltip_Mixin : Hover_Tooltip_Provider {
|
|
private:
|
|
That* that() {
|
|
return static_cast<That*>(this);
|
|
}
|
|
Hover_Tooltip_State* hover_edit_state() override {
|
|
auto t = that();
|
|
return dynamic_cast<Hover_Tooltip_State*>(t->d_ptr->state(State_Edit));
|
|
}
|
|
Hover_Tooltip_State* hover_render_state() override {
|
|
auto t = that();
|
|
return dynamic_cast<Hover_Tooltip_State*>(t->d_ptr->state(State_Render));
|
|
}
|
|
Hover_State_Edit begin_hover_edit_impl() override {
|
|
auto t = that();
|
|
auto record = t->d_ptr->state_control.try_acquire_role(State_Edit);
|
|
if (record.result != Triple_Buffer_Result::Success)
|
|
return {};
|
|
auto lease = record.lease;
|
|
auto* data = t->d_ptr;
|
|
auto* state = dynamic_cast<Hover_Tooltip_State*>(data->state_by_index(lease.index));
|
|
return Hover_State_Edit(this, state, [data, lease]() mutable {
|
|
++data->state_by_index(lease.index)->version;
|
|
if (data->q_ptr)
|
|
data->q_ptr->mark_render_dirty();
|
|
data->state_control.unmark_use(lease);
|
|
});
|
|
}
|
|
};
|
|
} // namespace renderive
|