#pragma once #include #include #include #include #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 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 struct LIB_DECL Hover_Tooltip_Mixin : Hover_Tooltip_Provider { private: That* that() { return static_cast(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(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(guard.state); if (!state) return {}; return Hover_Edit_Guard(state, std::move(guard)); } }; } // namespace renderive