Files
ReJUI/include/JUI/Widgets/Link.hpp

114 lines
3.3 KiB
C++

/// 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 <JUI/Widgets/Text.hpp>
#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<std::optional<LinkInvokedEventArgs>> 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:
};
}