Spitball Redesigns

This commit is contained in:
2025-04-28 21:32:32 -05:00
parent c3e372ac29
commit 6f7388a27d
6 changed files with 267 additions and 91 deletions

View File

@@ -28,7 +28,9 @@ endif()
if (WIN32)
add_library(JUI STATIC ${JUI_SRC}
include/JUI/Mixins/DragAndDropReceiver.hpp
include/JUI/Widgets/RadioButtonSet.hpp)
include/JUI/Widgets/RadioButtonSet.hpp
src/JUI/Widgets/UtilityBar.cpp
include/JUI/Widgets/ContextMenu.hpp)
endif()
set_target_properties(JUI PROPERTIES LINKER_LANGUAGE CXX)

View File

@@ -0,0 +1,119 @@
/// 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) 2024 Redacted Software
/// This work is dedicated to the public domain.
/// @file Widget.hpp
/// @desc Base Widget Class - All JUI widgets extend their behavior from this class.
/// @edit 2024-10-11
#pragma once
#include <JUI/Widgets/TextButton.hpp>
#include "ListLayout.hpp"
namespace JUI {
/// TODO: Observe and design all the base interfaces for various style categories.
class TextStyleInterface {
public:
virtual ~TextStyleInterface() = default;
virtual JGL::Font Font() const = 0;
virtual int TextSize() const = 0;
virtual Color4 TextColor() const = 0;
virtual bool WordWrap() const = 0;
virtual void Font(const JGL::Font& value) = 0;
virtual void TextSize(int value) = 0;
virtual void TextColor(const Color4& color) = 0;
};
class RectStyleInterface {
public:
virtual Color4 BGColor() const = 0;
virtual Color4 BorderColor() const = 0;
virtual enum BorderMode BorderMode() const = 0;
virtual float BorderWidth() const = 0;
virtual float CornerRounding() const = 0;
virtual void BGColor(const Color4& color) = 0;
virtual void BorderColor(const Color4& color) = 0;
virtual void BorderMode(const enum BorderMode& borderMode) = 0;
};
class PaddingStyleInterface {
};
class MarginStyleInterface {
};
/// A vertically-descending list menu of button objects, which supports sub-menus much like class UtilityBar.
/// @see UtilityBar
class ContextMenu : public Rect, public TextStyleInterface {
public:
void PropogateTextSize(int value) {
for (auto* child : children) {
TextStyleInterface* textual = dynamic_cast<TextStyleInterface *>(child);
if (textual)
textual->TextSize(value);
}
}
/// Sets the TextSize property for the child elements of this widget.
void TextSize(int value) override {
// TODO: This works fine for the ContextMenu, where children are assuemed to only by submenus and buttons.
// Some widgets will need to be handled specially, because only some of their children are logically bound to it.
PropogateTextSize(value);
}
ContextMenu();
explicit ContextMenu(Widget* parent);
void SetFont(const JGL::Font& use_my_font);
TextButton* AddButton(const std::string &name);
TextButton* AddButton(const std::string& name, const std::function<void()> &callback) {
auto* btn = AddButton(name);
// TODO: Is this memory safe at all?
btn->OnClickEvent += [&] (auto a, auto b) mutable {
callback();
};
return btn;
}
std::pair<TextButton*, ContextMenu*> AddSubmenu(const std::string& name);
/// Sets whether the widget will automatically hide itself when the mouse leaves its bounding box.
void CloseOnHoverLoss(bool value);
/// @return Whether the widget will automatically hide itself when the mouse leaves its bounding box.
[[nodiscard]] bool CloseOnHoverLoss() const;
protected:
VerticalListLayout* layout;
JGL::Font font;
bool close_on_hover_loss = true;;
private:
};
}

View File

@@ -1,100 +1,37 @@
/// 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) 2024 Redacted Software
/// This work is dedicated to the public domain.
/// @file Widget.hpp
/// @desc Base Widget Class - All JUI widgets extend their behavior from this class.
/// @edit 2024-10-11
#pragma once
#include "ContextMenu.hpp"
namespace JUI
{
class UtilityBar;
class ContextMenu : public Rect {
public:
ContextMenu() : Rect() {
Name("ContextMenu");
this->BGColor(Colors::White);
this->Margin(2_px);
this->Size({200, 200, 0, 0});
layout = new VerticalListLayout(this);
MouseExit += [this] (Vector2 _)
{
this->Visible(false);
this->Parent(nullptr);
// TODO: Collect
};
}
explicit ContextMenu(Widget* parent) : ContextMenu()
{
this->Parent(parent);
}
void SetFont(const JGL::Font& use_my_font)
{
font = use_my_font;
}
TextButton* AddItem(const std::string &name)
{
auto* line_item = new TextButton(layout);
line_item->SetFont(font);
line_item->SetContent(name);
line_item->SetTextSize(16);
line_item->SetTextColor(Colors::Black);
line_item->Size({0, 20, 1, 0});
return line_item;
}
protected:
VerticalListLayout* layout;
JGL::Font font;
private:
};
/// A horizontal toolbar widget that is designed to be used at the top of windows, and subwindow widgets.
/// Convenience functions are provided for adding tool buttons and sub-menus.
/// @see class ContextMenu
class UtilityBar : public Rect
{
public:
UtilityBar() : Rect()
{
// TODO: Make a note that all JGL::Font members on widgets need to be initialized to JGL::Fonts::Jupiteroid inside the constructor.
font = JGL::Fonts::Jupiteroid;
UtilityBar();
this->Size({0, 20, 1, 0});
this->Position({0,0,0,0});
this->BGColor(Colors::White);
this->BorderColor(Colors::Blues::CornflowerBlue);
this->BorderWidth(2);
this->Margin(2_px);
this->BorderMode(BorderMode::Outline);
layout = new HorizontalListLayout(this);
//layout->PaddingLeft(2_px);
layout->PaddingRight(2_px);
//layout->PaddingRight(2_px);
}
explicit UtilityBar(Widget* parent);
explicit UtilityBar(Widget* parent) : UtilityBar() {
this->Parent(parent);
}
TextButton* AddSubmenu(const std::string& name)
{
auto btn = AddButton(name);
/// Adds a new 'Submenu', which consists of a labeled button, which opens a contextual-submenu
std::pair<TextButton*, ContextMenu*> AddSubmenu(const std::string& name);
return btn;
}
TextButton* AddButton(const std::string& name);
TextButton* AddButton(const std::string& name)
{
auto str_width = font.MeasureString(name, 14);
auto* btn = new TextButton(layout);
btn->SetFont(font);
btn->SetTextSize(14);
btn->SetTextColor(Colors::Black);
btn->Size({static_cast<int>(str_width.x)+16, 0, 0, 1});
btn->BorderWidth(0.f);
btn->SetContent(name);
return btn;
}
void SetFont(const JGL::Font& use_my_font)
{
font = use_my_font;
@@ -104,4 +41,4 @@ namespace JUI
JGL::Font font;
private:
};
}
}

View File

@@ -70,12 +70,21 @@ JUI::Scene* CreateScene() {
auto* topbar = new UtilityBar(root);
topbar->ZIndex(3);
auto* file = topbar->AddButton("Demos");
auto [demo_btn, demos] = topbar->AddSubmenu("Demos");
auto* file_tt = new JUI::Tooltip(file);
file_tt->SetContent("Tooltip");
demos->AddButton("9-Slice Widget Demo",
[&] mutable { nineslice_demo_window->Toggle(); });
file->OnClickEvent += [&, root, nineslice_demo_window] (Vector2 pos, JUI::MouseButton btn)
demos->AddButton("Scroll Widget Demo", [&] mutable {});
demos->AddButton("Command Line",
[&] mutable{ console->Toggle();});
//auto* file_tt = new JUI::Tooltip(file);
//file_tt->SetContent("Tooltip");
/*file->OnClickEvent += [&, root, nineslice_demo_window] (Vector2 pos, JUI::MouseButton btn)
{
auto* ctx_menu = new ContextMenu(root);
ctx_menu->Position(UDim2(0,20,0,0));
@@ -97,7 +106,7 @@ JUI::Scene* CreateScene() {
};
ctx_menu->ZIndex(3);
};
};*/
topbar->AddButton("Edit");
auto* view = topbar->AddButton("View");

View File

@@ -0,0 +1,49 @@
#include <JUI/Widgets/ContextMenu.hpp>
namespace JUI {
ContextMenu::ContextMenu(): Rect() {
Name("ContextMenu");
this->BGColor(Colors::White);
this->Margin(2_px);
this->Size({200, 200, 0, 0});
layout = new VerticalListLayout(this);
MouseExit += [this] (Vector2 _)
{
this->Visible(false);
this->Parent(nullptr);
// TODO: Collect
};
}
ContextMenu::ContextMenu(Widget *parent): ContextMenu() {
this->Parent(parent);
}
void ContextMenu::SetFont(const JGL::Font &use_my_font) {
font = use_my_font;
}
TextButton * ContextMenu::AddButton(const std::string &name) {
auto* line_item = new TextButton(layout);
line_item->SetFont(font);
line_item->SetContent(name);
line_item->SetTextSize(16);
line_item->SetTextColor(Colors::Black);
line_item->Size({0, 20, 1, 0});
return line_item;
}
std::pair<TextButton *, ContextMenu *> ContextMenu::AddSubmenu(const std::string &name) {
auto* btn = AddButton(name);
// TODO: Duplicated code with UtilityBar.cpp
auto* submenu = new JUI::ContextMenu(this);
submenu->AnchorPoint({1, 0});
}
void ContextMenu::CloseOnHoverLoss(bool value) { close_on_hover_loss = value;}
bool ContextMenu::CloseOnHoverLoss() const { return close_on_hover_loss; }
}

View File

@@ -0,0 +1,60 @@
#include <JUI/Widgets/UtilityBar.hpp>
namespace JUI {
UtilityBar::UtilityBar(): Rect() {
// TODO: Make a note that all JGL::Font members on widgets need to be initialized to JGL::Fonts::Jupiteroid inside the constructor.
font = JGL::Fonts::Jupiteroid;
this->Size({0, 20, 1, 0});
this->Position({0,0,0,0});
this->BGColor(Colors::White);
this->BorderColor(Colors::Blues::CornflowerBlue);
this->BorderWidth(2);
this->Margin(2_px);
this->BorderMode(BorderMode::Outline);
layout = new HorizontalListLayout(this);
//layout->PaddingLeft(2_px);
layout->PaddingRight(2_px);
//layout->PaddingRight(2_px);
}
UtilityBar::UtilityBar(Widget *parent): UtilityBar() {
this->Parent(parent);
}
std::pair<TextButton *, ContextMenu *> UtilityBar::AddSubmenu(const std::string &name) {
auto btn = AddButton(name);
auto* submenu = new JUI::ContextMenu(this);
submenu->AnchorPoint({1, 0});
submenu->Position({0_percent, 0_percent});
btn->OnClickEvent += [&] (auto a, auto b) mutable {
submenu->Visible(true);
};
// TODO: We seem to have duplicate events
// Hoverable::OnExitEvent
// RectBase::MouseExit
//submenu->MouseExit += [&] (auto) mutable {
// submenu->Visible(false);
//};
return {btn, submenu};
}
TextButton * UtilityBar::AddButton(const std::string &name) {
auto str_width = font.MeasureString(name, 14);
auto* btn = new TextButton(layout);
btn->SetFont(font);
btn->SetTextSize(14);
btn->SetTextColor(Colors::Black);
btn->Size({static_cast<int>(str_width.x)+16, 0, 0, 1});
btn->BorderWidth(0.f);
btn->SetContent(name);
return btn;
}
}