/// Josh's User Interface Library /// A C++20 Library for creating, styling, and rendering of a UI/UX widgets. /// Developed and Maintained by Josh O'Leary @ Redacted Software. /// Special Thanks to William Tomasine II and Maxine Hayes. /// (c) 2025 Redacted Software /// This work is dedicated to the public domain. /// @file Link.hpp /// @desc Special category of text-objects that model a clickable link in HTML. /// @edit 2025-06-11 #pragma once #include #include "JUI/Mixins/Clickable.hpp" namespace JUI { struct LinkInvokedEventArgs {}; /// Controls when Link widgets fire their Cicked callback. It can fire right when the widget is clicked, or when it is is released. enum class LinkClickMode { Press, Release }; /// The Link widget is a specialization of the Text widget that has the appearance and behavior of a clickable link, such as in HTML. class Link : public Text, public Clickable, public Hoverable { public: enum LinkClickMode ClickMode = LinkClickMode::Release; Event> Invoked; /// This event is fired when the user clicks/releases the link. Link() : Text(), Clickable(), Hoverable() {} explicit Link(const std::string& content) : Link() { this->Content(content); } explicit Link(Widget* parent) : Link() { this->Parent(parent); } void OnHover(const Vector2 &MousePos) override { TextColor(Colors::Blues::CornflowerBlue); } void OnExit(const Vector2 &MousePos) override { TextColor(Colors::Blues::DeepSkyBlue); } void OnClick(const Vector2& mouse_pos, const MouseButton& btn) override { if (disabled) return; Clickable::OnClick(mouse_pos, btn); TextColor(Colors::White); if (!fire_on_release) { Clicked.Invoke(std::nullopt); already_clicked = true; } } void OnRelease(const J3ML::LinearAlgebra::Vector2 &mouse_pos, const JUI::MouseButton &btn, bool still_hovering) override { if (disabled) return; Clickable::OnRelease(mouse_pos, btn, still_hovering); TextColor(Colors::Black); if (fire_on_release) { Clicked.Invoke(std::nullopt); already_clicked = true; } } void Update(float delta) override { Text::Update(delta); // TODO: Why does hovered not handle this? Hoverable::Update(IsMouseInside(), delta); // TODO: This is duplicated between here and Window.cpp // Will be abstracted away into Clickable shortly. // OMFG if (IsHovered() && mb_state && !prev_mb_state) { OnClick(last_known_mouse_pos, mbtn); } if (IsClicked() && !mb_state) { OnRelease(last_known_mouse_pos, mbtn, IsHovered()); } } protected: Color4 already_clicked_color; Color4 hovered_color; Color4 clicked_color; bool disabled = false; bool already_clicked = false; bool fire_on_release; private: }; }