Files
Renderive/Core/plottable/Hover_Tooltip.h
T
2026-08-02 18:58:35 +08:00

185 lines
6.5 KiB
C++

#pragma once
#include <functional>
#include <string>
#include <utility>
#include <vector>
#include "../Axis/export.h"
#include "../architecture/Render_Data.h"
#include "../base/Color.h"
#include "../base/Geometry.h"
#include "../base/Style.h"
#include "../base/Text.h"
#include "../render/Canvas.h"
namespace renderive {
struct Render_Frame_Snapshot;
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, const Render_Frame_Snapshot* snapshot = nullptr);
bool can_show_hover(Renderable* able) const;
};
struct LIB_DECL Hover_Tooltip_Provider {
struct Hover_Read_Guard {
Hover_Read_Guard() = default;
Hover_Read_Guard(Hover_Tooltip_State* state, Render_State_Read_Guard guard)
: state(state), guard(std::move(guard)) {}
Hover_Read_Guard(const Hover_Read_Guard&) = delete;
Hover_Read_Guard& operator=(const Hover_Read_Guard&) = delete;
Hover_Read_Guard(Hover_Read_Guard&&) noexcept = default;
Hover_Read_Guard& operator=(Hover_Read_Guard&&) noexcept = default;
~Hover_Read_Guard() = default;
Hover_Tooltip_State* operator->() const {
return state;
}
explicit operator bool() const {
return state && guard;
}
Hover_Tooltip_State* state{};
Render_State_Read_Guard guard;
};
struct Hover_Edit_Guard {
Hover_Edit_Guard() = default;
Hover_Edit_Guard(Hover_Tooltip_State* state, Render_State_Write_Guard guard)
: state(state), guard(std::move(guard)) {}
Hover_Edit_Guard(const Hover_Edit_Guard&) = delete;
Hover_Edit_Guard& operator=(const Hover_Edit_Guard&) = delete;
Hover_Edit_Guard(Hover_Edit_Guard&&) noexcept = default;
Hover_Edit_Guard& operator=(Hover_Edit_Guard&&) noexcept = default;
~Hover_Edit_Guard() = default;
Hover_Tooltip_State* operator->() const {
return state;
}
explicit operator bool() const {
return state && guard;
}
Hover_Tooltip_State* state{};
Render_State_Write_Guard guard;
};
virtual std::vector<std::string> build_hover_lines(Abs_Axis* h, Abs_Axis* v, Point pos, const Render_Frame_Snapshot* snapshot = nullptr);
virtual ~Hover_Tooltip_Provider() = default;
virtual void draw_hover_tooltip(Canvas* canvas, Abs_Axis* h, Abs_Axis* v) {
auto state = begin_hover_read();
if (state)
state->draw_hover_tooltip(canvas, h, v, this);
}
virtual bool hover_ok(Renderable* able) {
auto state = begin_hover_read();
return state && state->can_show_hover(able);
}
virtual bool hit_test_hover(Point pos) {
(void)pos;
return true;
}
bool hover_tooltip_enabled() {
auto state = begin_hover_read();
return state && state->use_hover_tooltip;
}
void set_use_hover_info(bool use) {
auto edit = begin_hover_edit();
if (!edit)
return;
edit->use_hover_tooltip = use;
}
void set_hover_tooltip_font(const Font& font) {
auto edit = begin_hover_edit();
if (!edit)
return;
edit->hover_info_font = font;
}
Font hover_tooltip_font() {
auto state = begin_hover_read();
return state ? state->hover_info_font : Font{};
}
Brush hover_info_background_brush() {
auto state = begin_hover_read();
return state ? state->tooltip_background_brush : Brush{};
}
void set_hover_tooltip_background_brush(const Brush& brush) {
auto edit = begin_hover_edit();
if (!edit)
return;
edit->tooltip_background_brush = brush.color.a != 0 ? brush : Brush{};
}
Pen tooltip_text_pen() {
auto state = begin_hover_read();
return state ? state->tooltip_text_pen : Pen{.style = Line_Style::None};
}
void set_tooltip_text_pen(const Pen& pen) {
auto edit = begin_hover_edit();
if (!edit)
return;
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 = begin_hover_read();
if (!s) {
left = top = right = bottom = 0;
return;
}
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();
if (!edit)
return;
edit->hover_info_left = left;
edit->hover_info_top = top;
edit->hover_info_right = right;
edit->hover_info_bottom = bottom;
}
Hover_Edit_Guard begin_hover_edit() {
return begin_hover_edit_impl();
}
Hover_Read_Guard begin_hover_read() {
return begin_hover_read_impl();
}
private:
virtual Hover_Read_Guard begin_hover_read_impl() = 0;
virtual Hover_Edit_Guard 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_Read_Guard begin_hover_read_impl() override {
auto t = that();
auto guard = t->d_ptr->acquire_state_read(Renderable_State_Role::Edit);
auto* state = dynamic_cast<Hover_Tooltip_State*>(guard.state);
if (!state)
return {};
return Hover_Read_Guard(state, std::move(guard));
}
Hover_Edit_Guard begin_hover_edit_impl() override {
auto t = that();
auto guard = t->d_ptr->acquire_edit_state();
auto* state = dynamic_cast<Hover_Tooltip_State*>(guard.state);
if (!state)
return {};
return Hover_Edit_Guard(state, std::move(guard));
}
};
} // namespace renderive