A ton of edits.. I don't even know
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.18..3.27)
|
||||
project(JUI
|
||||
VERSION 1.1
|
||||
VERSION 4.0
|
||||
LANGUAGES CXX)
|
||||
|
||||
if (PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR)
|
||||
|
@@ -11,6 +11,16 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
/// Ideal refactor:
|
||||
/// * Completely separate Component for a given behavior / area of concern
|
||||
/// * XYZStyler class, stored as a pointer in the widget.
|
||||
/// * Smart pointers
|
||||
/// * Intelligent layout.
|
||||
/// *
|
||||
|
||||
|
||||
|
||||
#include <Event.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -31,17 +41,37 @@ namespace JUI {
|
||||
using namespace J3ML::Math;
|
||||
using namespace J3ML::LinearAlgebra;
|
||||
|
||||
struct EventArgs {
|
||||
|
||||
};
|
||||
|
||||
struct FocusedArgs {};
|
||||
struct UnfocusedEventArgs {};
|
||||
struct ChildAddedEventArgs {};
|
||||
struct ChildRemovedEventArgs {};
|
||||
|
||||
/// TODO: Refactor the member functions providing the parent-child hierarchy into the Node mixin.
|
||||
template <class TNode>
|
||||
class Node {
|
||||
public:
|
||||
|
||||
protected:
|
||||
std::vector<TNode*> children;
|
||||
TNode* parent;
|
||||
};
|
||||
|
||||
|
||||
/// Widget is the base class for all JUI elements and represents any object that can be in the tree hierarchy.
|
||||
/// Some widgets are expressly used for layout, and therefore do not strictly speaking 'Appear' on screen.
|
||||
/// Some widgets are expressly used for layout, and therefore do not strictly-speaking 'Appear' on screen.
|
||||
/// Widgets exist in a tree hierarchy where each object has one parent, and an arbitrary number of children. No circular references are allowed.
|
||||
class Widget {
|
||||
public:
|
||||
/// The default constructor for Widget. Generally, JUI widgets will initialize member data,
|
||||
/// and apply a default style in this constructor. Be aware of this, as this is not "idiomatic C++".
|
||||
Widget();
|
||||
/// Construct a new widget by specifying it's parent,
|
||||
/// Construct a new widget by specifying its parent,
|
||||
explicit Widget(Widget* parent);
|
||||
virtual ~Widget() {}
|
||||
virtual ~Widget() = default;
|
||||
public:
|
||||
#pragma region Events
|
||||
/// An event that triggers when the widget is in-focus, generally when the mouse is hovering it.
|
||||
@@ -111,6 +141,8 @@ namespace JUI {
|
||||
/// In a well-formed JUI menu, this **should** always be a Scene.
|
||||
Widget* GetFamilyTreeRoot() const;
|
||||
|
||||
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Layout
|
||||
@@ -391,6 +423,8 @@ namespace JUI {
|
||||
int layout_order = 0;
|
||||
Vector2 viewport_size{0,0};
|
||||
|
||||
bool is_mouse_inside = false;
|
||||
|
||||
/// Returns the amount of pixels this widget will be padded by from the top-left.
|
||||
/// Generally, the widget will be shrunk and moved over by this amount, relative to the parent.
|
||||
Vector2 GetAbsolutePaddingTopLeft() const;
|
||||
@@ -401,5 +435,8 @@ namespace JUI {
|
||||
Vector2 GetAbsoluteMarginTopLeft();
|
||||
Vector2 GetAbsoluteMarginBottomRight();
|
||||
void UpdateTweens(float elapsed);
|
||||
|
||||
/// Calculate if mouse is inside this element at the start of it's update frame.
|
||||
bool ComputeIsMouseInside() const;
|
||||
};
|
||||
}
|
||||
|
@@ -14,10 +14,27 @@
|
||||
#include <J3ML/LinearAlgebra/Vector2.hpp>
|
||||
#include <JUI/Base/Widget.hpp>
|
||||
|
||||
#include "Hoverable.hpp"
|
||||
|
||||
namespace JUI {
|
||||
|
||||
|
||||
struct ClickEventArgs {
|
||||
public:
|
||||
protected:
|
||||
private:
|
||||
};
|
||||
struct ReleaseEventArgs {
|
||||
public:
|
||||
protected:
|
||||
private:
|
||||
};
|
||||
|
||||
/// A mixin helper class that provides behavior and events for clickable widgets.
|
||||
class Clickable {
|
||||
public:
|
||||
Event<std::optional<ClickEventArgs>> Clicked;
|
||||
Event<ReleaseEventArgs> Released;
|
||||
|
||||
Event<Vector2, MouseButton> OnClickEvent;
|
||||
Event<Vector2, MouseButton, bool> OnReleaseEvent;
|
||||
|
@@ -18,6 +18,14 @@
|
||||
|
||||
namespace JUI
|
||||
{
|
||||
|
||||
/// Interface for anything that can report mouse presence.
|
||||
class IMouseAware {
|
||||
public:
|
||||
virtual ~IMouseAware() = default;
|
||||
virtual bool IsMouseAware() const = 0;
|
||||
};
|
||||
|
||||
/// A mixin helper class that provides behavior for hoverable objects.
|
||||
/// A hoverable object pays attention to when the mouse enters and leaves it's bounds.
|
||||
class Hoverable {
|
||||
@@ -39,7 +47,10 @@ namespace JUI
|
||||
virtual void OnExitChildren(const Vector2& mouse);
|
||||
virtual void OnExitDescendants(const Vector2& mouse);
|
||||
|
||||
void Update(const Vector2& m_pos, float delta);
|
||||
void Update(bool mouse_inside, float delta);
|
||||
|
||||
/// @note This member function **must** be implemented for classes that implement Hoverable.
|
||||
//[[nodiscard]] virtual bool IsMouseInside() const = 0;
|
||||
//virtual void SetTooltip(const std::string& content, float delay) {}
|
||||
protected:
|
||||
//Tooltip* tooltip = nullptr;
|
||||
|
@@ -164,4 +164,11 @@ namespace JUI {
|
||||
private:
|
||||
};
|
||||
|
||||
class ColorPickerDialog : public Window {
|
||||
public:
|
||||
protected:
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -124,6 +124,5 @@ namespace JUI {
|
||||
protected:
|
||||
FpsGraph* data_graph;
|
||||
private:
|
||||
|
||||
};
|
||||
}
|
@@ -17,6 +17,8 @@
|
||||
|
||||
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 };
|
||||
|
||||
@@ -24,8 +26,8 @@ namespace JUI {
|
||||
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.
|
||||
Event<> Clicked;
|
||||
Link() : Text(), Clickable(), Hoverable() {}
|
||||
explicit Link(const std::string& content) : Link() {
|
||||
this->Content(content);
|
||||
@@ -54,7 +56,7 @@ namespace JUI {
|
||||
TextColor(Colors::White);
|
||||
|
||||
if (!fire_on_release) {
|
||||
Clicked.Invoke();
|
||||
Clicked.Invoke(std::nullopt);
|
||||
already_clicked = true;
|
||||
}
|
||||
}
|
||||
@@ -69,7 +71,7 @@ namespace JUI {
|
||||
|
||||
TextColor(Colors::Black);
|
||||
if (fire_on_release) {
|
||||
Clicked.Invoke();
|
||||
Clicked.Invoke(std::nullopt);
|
||||
already_clicked = true;
|
||||
}
|
||||
}
|
||||
@@ -80,9 +82,8 @@ namespace JUI {
|
||||
Text::Update(delta);
|
||||
|
||||
// TODO: Why does hovered not handle this?
|
||||
hovered = IsMouseInside();
|
||||
|
||||
Hoverable::Update(last_known_mouse_pos, delta);
|
||||
Hoverable::Update(IsMouseInside(), delta);
|
||||
|
||||
// TODO: This is duplicated between here and Window.cpp
|
||||
// Will be abstracted away into Clickable shortly.
|
||||
|
10
include/JUI/Widgets/ToggleButton.hpp
Normal file
10
include/JUI/Widgets/ToggleButton.hpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include "Button.hpp"
|
||||
|
||||
|
||||
namespace JUI {
|
||||
/// The
|
||||
class ToggleButton : public Button {
|
||||
|
||||
};
|
||||
}
|
18
main.cpp
18
main.cpp
@@ -331,13 +331,21 @@ JUI::Rect* CreateWidgetList(JUI::Widget* root) {
|
||||
auto* radio_c_btn = new Checkbox(radio_btn_set_layout);
|
||||
radio_c_btn->Size({20_px, 20_px});
|
||||
|
||||
auto* linkbox = new Rect(collapsible->ContentBox());
|
||||
linkbox->Size({100_percent, 30_px});
|
||||
linkbox->Position({0_px, 20_px});
|
||||
auto* link_container = new Rect(collapsible->ContentBox());
|
||||
{
|
||||
link_container->Size({100_percent, 30_px});
|
||||
link_container->Position({0_px, 20_px});
|
||||
|
||||
auto* link = new JUI::Link(link_container);
|
||||
link->Content("Clickable Link");
|
||||
link->Clicked += [](auto event) {
|
||||
std::cout << "Link Released" << std::endl;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
auto* link = new JUI::Link(linkbox);
|
||||
link->Content("This Dick");
|
||||
// What the FUCK?
|
||||
|
||||
/*auto* radio_c_label = new TextRect(radio_btn_set_layout);
|
||||
|
@@ -281,6 +281,9 @@ void Widget::UpdateTweens(float elapsed) {
|
||||
}
|
||||
|
||||
void Widget::Update(float delta) {
|
||||
|
||||
is_mouse_inside = ComputeIsMouseInside();
|
||||
|
||||
UpdateChildWidgets(delta);
|
||||
UpdateTweens(delta);
|
||||
}
|
||||
@@ -313,7 +316,8 @@ Widget* Widget::GetFamilyTreeRoot() const {
|
||||
return parent->GetFamilyTreeRoot();
|
||||
}
|
||||
|
||||
bool Widget::IsMouseInside() const {
|
||||
|
||||
bool Widget::ComputeIsMouseInside() const {
|
||||
float x = last_known_mouse_pos.x;
|
||||
float y = last_known_mouse_pos.y;
|
||||
auto pos = GetAbsolutePosition();
|
||||
@@ -325,6 +329,20 @@ bool Widget::IsMouseInside() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Widget::IsMouseInside() const {
|
||||
return is_mouse_inside;
|
||||
|
||||
/*float x = last_known_mouse_pos.x;
|
||||
float y = last_known_mouse_pos.y;
|
||||
auto pos = GetAbsolutePosition();
|
||||
auto size = GetAbsoluteSize();
|
||||
|
||||
if (x > pos.x && y > pos.y && x < pos.x + size.x && y < pos.y + size.y)
|
||||
return true;
|
||||
|
||||
return false;*/
|
||||
}
|
||||
|
||||
bool Widget::IsMouseInsideChildren(bool include_this) const {
|
||||
if (include_this)
|
||||
if (IsMouseInside())
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#include <JUI/Mixins/Clickable.hpp>
|
||||
|
||||
void JUI::Clickable::Update(const Vector2 &mpos, const JUI::MouseButton &btn, bool hovering) {
|
||||
|
||||
//Hoverable::Update(mpos, delta);
|
||||
}
|
||||
|
||||
void JUI::Clickable::OnRelease(const Vector2 &MousePos, const JUI::MouseButton &MouseButton, bool MouseStillOver) {
|
||||
|
@@ -27,8 +27,9 @@ void JUI::Hoverable::OnExitDescendants(const Vector2& mouse) {
|
||||
// TODO: Implement
|
||||
}
|
||||
|
||||
void JUI::Hoverable::Update(const Vector2 &m_pos, float delta) {
|
||||
void JUI::Hoverable::Update(bool mouse_inside, float delta) {
|
||||
|
||||
hovered = mouse_inside;
|
||||
/*if (tooltip != nullptr)
|
||||
{
|
||||
if (IsHovered()) {
|
||||
@@ -41,12 +42,12 @@ void JUI::Hoverable::Update(const Vector2 &m_pos, float delta) {
|
||||
|
||||
|
||||
if (IsHovered() && !hover_debounce) {
|
||||
OnHover(m_pos);
|
||||
OnHover({0,0});
|
||||
hover_debounce = true;
|
||||
}
|
||||
|
||||
if (!IsHovered() && hover_debounce) {
|
||||
OnExit(m_pos);
|
||||
OnExit({0,0});
|
||||
hover_debounce = false;
|
||||
}
|
||||
}
|
||||
|
@@ -46,9 +46,8 @@ namespace JUI {
|
||||
}
|
||||
|
||||
void Button::Update(float delta) {
|
||||
hovered = IsMouseInside();
|
||||
|
||||
Hoverable::Update(last_known_mouse_pos, delta);
|
||||
Hoverable::Update(IsMouseInside(), delta);
|
||||
|
||||
// TODO: This is duplicated between here and Window.cpp
|
||||
// Will be abstracted away into Clickable shortly.
|
||||
|
@@ -28,12 +28,8 @@ namespace JUI
|
||||
}
|
||||
|
||||
void Slider::Update(float delta) {
|
||||
bool selected = Rect::IsMouseInside();
|
||||
|
||||
|
||||
hovered = IsMouseInside();
|
||||
|
||||
Hoverable::Update(last_known_mouse_pos, delta);
|
||||
Hoverable::Update(Rect::IsMouseInside(), delta);
|
||||
|
||||
// TODO: This is duplicated between here and Window.cpp
|
||||
// Will be abstracted away into Clickable shortly.
|
||||
|
@@ -215,9 +215,8 @@ namespace JUI {
|
||||
}
|
||||
|
||||
Widget::Update(delta);
|
||||
hovered = IsMouseInside();
|
||||
|
||||
Hoverable::Update(last_known_mouse_pos, delta);
|
||||
Hoverable::Update(IsMouseInside(), delta);
|
||||
|
||||
// TODO: This is duplicated between here and Window.cpp
|
||||
// Will be abstracted away into Clickable shortly.
|
||||
@@ -226,7 +225,6 @@ namespace JUI {
|
||||
OnClick(last_known_mouse_pos, mbtn);
|
||||
}
|
||||
|
||||
|
||||
if (prev_mb_state && !mb_state)
|
||||
{
|
||||
OnRelease(last_known_mouse_pos, mbtn, IsHovered());
|
||||
|
Reference in New Issue
Block a user