258 lines
No EOL
8.7 KiB
C++
258 lines
No EOL
8.7 KiB
C++
#pragma once
|
|
|
|
#include <ostd/BaseObject.hpp>
|
|
#include <ostd/Geometry.hpp>
|
|
#include <ostd/Color.hpp>
|
|
#include <ogfx/RTData.hpp>
|
|
#include <ostd/Signals.hpp>
|
|
|
|
#include <unordered_map>
|
|
|
|
namespace ogfx
|
|
{
|
|
class RenderCore;
|
|
class Event;
|
|
|
|
namespace oxgui
|
|
{
|
|
struct tWidgetState
|
|
{
|
|
inline static constexpr ostd::WidgetID DuplicatedWidget = 0x00000001;
|
|
inline static constexpr ostd::WidgetID WidgetHasParent = 0x00000002;
|
|
|
|
inline static constexpr ostd::WidgetID ValidWidgetBase = 0x00000400;
|
|
|
|
inline static bool check(ostd::WidgetID result) { return result >= ValidWidgetBase; }
|
|
};
|
|
|
|
class WidgetTheme
|
|
{
|
|
using Col = ostd::Color;
|
|
using Font = ostd::ResourceID;
|
|
public: struct tSubWindowTheme {
|
|
Col titleBarColor_focused;
|
|
Col titleBarColor_unfocused;
|
|
Col titleColor;
|
|
Col closeButtonColor;
|
|
Col closeButtonColor_hover;
|
|
Col closeButtonTextColor;
|
|
Col borderColor_focused;
|
|
Col borderColor_unfocused;
|
|
Col backgroundColor;
|
|
|
|
Font titleFont { 0 };
|
|
Font closeButtonFont { 0 };
|
|
Font font { 0 };
|
|
|
|
bool enableShadow { true };
|
|
};
|
|
|
|
public: struct tTabPanel {
|
|
Col backgroundColor;
|
|
Col tabBackground_focused;
|
|
Col tabBackground_unfocused;
|
|
Col focusedTabHighlight;
|
|
Col unfocusedTabHighlight;
|
|
Col tabBarBackground;
|
|
Col tabBackground_hover;
|
|
Col focusedTabNameColor;
|
|
Col unfocusedTabNameColor;
|
|
|
|
Font tabNameFont { 0 };
|
|
Font font { 0 };
|
|
|
|
float fixedTabWidth { 130 };
|
|
float tabBarHeight { 25 };
|
|
float tabHighlightHeight { 1 };
|
|
float tabNameFontSize { 20 };
|
|
};
|
|
|
|
public:
|
|
tSubWindowTheme subWindow;
|
|
tTabPanel tabPanel;
|
|
};
|
|
|
|
class Widget : public ostd::BaseObject, public ostd::Rectangle
|
|
{
|
|
public:
|
|
~Widget(void) = default;
|
|
void connectSignals(void);
|
|
void handleSignal(ostd::tSignal& signal) override;
|
|
|
|
inline void enableGlobalThemeOverride(bool enable = true) { m_overrideGlobalTheme = enable; }
|
|
inline bool isGlobalThemeOverrideEnabled(void) { return m_overrideGlobalTheme; }
|
|
inline void setTheme(WidgetTheme theme) { m_theme = theme; }
|
|
inline WidgetTheme& getTheme(void) { return m_theme; }
|
|
inline std::unordered_map<ostd::WidgetID, Widget*>& getChildren(void) { return m_widgets; }
|
|
inline void setSubWindowHandle(int32_t handle) { m_subWindowHandle = handle; }
|
|
inline int32_t getSubWindowHandle(void) { return m_subWindowHandle; }
|
|
|
|
void setx(float x) override;
|
|
void sety(float y) override;
|
|
|
|
ostd::WidgetID addWidget(Widget& widget);
|
|
|
|
inline void enable(bool enabled = true) { m_enabled = enabled; }
|
|
inline bool isEnabled(void) { return m_enabled; }
|
|
void focus(bool value = true);
|
|
inline bool isFocused(void) { return m_focused; }
|
|
|
|
inline virtual ostd::Vec2 getContentSize(void) { return getSize(); }
|
|
inline virtual ostd::Vec2 getContentOffset(void) { return { 0, 0 }; }
|
|
|
|
inline virtual void onSignal(ostd::tSignal& signal) { }
|
|
inline virtual void onKeyPressed(ogfx::Event& evt) { }
|
|
inline virtual void onKeyReleased(ogfx::Event& evt) { }
|
|
inline virtual void onMousePressed(ogfx::Event& evt) { }
|
|
inline virtual void onMouseReleased(ogfx::Event& evt) { }
|
|
inline virtual void onMouseMoved(ogfx::Event& evt) { }
|
|
inline virtual void onFocusGained(void) { }
|
|
inline virtual void onFocusLost(void) { }
|
|
|
|
inline virtual void renderFrame(ogfx::RenderCore& gfx) { }
|
|
inline virtual void renderContent(ogfx::RenderCore& gfx) { }
|
|
|
|
void render(ogfx::RenderCore& gfx);
|
|
|
|
private:
|
|
void __on_mouse_pressed(ogfx::Event& evt);
|
|
void __on_mouse_released(ogfx::Event& evt);
|
|
void __on_mouse_moved(ogfx::Event& evt);
|
|
void __on_key_pressed(ogfx::Event& evt);
|
|
void __on_key_released(ogfx::Event& evt);
|
|
|
|
void __recursize_handle_set(Widget& widget);
|
|
|
|
protected:
|
|
Widget(void);
|
|
void drawOutlinedQuad(ogfx::RenderCore& gfx, const ostd::Vec2& position, const ostd::Vec2& size, const ostd::Color& fill, const ostd::Color& border, float borderWidth = 2);
|
|
|
|
private:
|
|
bool m_enabled { false };
|
|
bool m_focused { false };
|
|
int32_t m_subWindowHandle { -1 };
|
|
|
|
std::unordered_map<ostd::WidgetID, Widget*> m_widgets;
|
|
|
|
inline static ostd::WidgetID s_nextWidgetID = tWidgetState::ValidWidgetBase;
|
|
|
|
protected:
|
|
inline static const uint32_t OnWidgetFocusGainedSignal = ostd::SignalHandler::newCustomSignal(1200);
|
|
WidgetTheme m_theme;
|
|
bool m_overrideGlobalTheme { false };
|
|
Widget* m_parent { nullptr };
|
|
bool m_disableAutoChildrenRender { false };
|
|
};
|
|
|
|
class WidgetManager : public ostd::BaseObject
|
|
{
|
|
public:
|
|
static void init(void);
|
|
static void addWidget(Widget& widget);
|
|
static void render(RenderCore& gfx);
|
|
static bool testForFocus(Widget& widget, const ostd::Vec2& mouseClick);
|
|
static Widget& getSubWindow(int32_t handle);
|
|
|
|
inline static void setGlobalTheme(WidgetTheme theme) { s_globalTheme = theme; }
|
|
inline static WidgetTheme& getGlobalTheme(void) { return s_globalTheme; }
|
|
|
|
private:
|
|
static void reorder_widgets(void);
|
|
static int32_t find_index(uint32_t index);
|
|
static void recursive_handle_set(Widget& widget, int32_t handle);
|
|
|
|
private:
|
|
inline static std::vector<Widget*> s_widgets;
|
|
inline static std::vector<uint32_t> s_widgetOrder;
|
|
inline static WidgetTheme s_globalTheme;
|
|
};
|
|
|
|
class SubWindow : public Widget
|
|
{
|
|
public:
|
|
inline SubWindow(void) : Widget() { invalidate(); }
|
|
inline SubWindow(const ostd::Vec2& position, const ostd::Vec2& size) : Widget() { create(position, size); }
|
|
virtual ~SubWindow(void) = default;
|
|
SubWindow& create(const ostd::Vec2& position, const ostd::Vec2& size);
|
|
inline ostd::String getTitle(void) { return m_title; }
|
|
inline void setTitle(const ostd::String& title) { m_title = title; }
|
|
inline ostd::Vec2 getContentSize(void) override { return getSize() - ostd::Vec2 { m_borderWidth * 2, m_titleBarHeight + (m_borderWidth * 2) }; }
|
|
inline ostd::Vec2 getContentOffset(void) override { return ostd::Vec2 { m_borderWidth, m_titleBarHeight + m_borderWidth }; }
|
|
|
|
virtual void renderFrame(ogfx::RenderCore& gfx) override;
|
|
|
|
void onMousePressed(ogfx::Event& evt) override;
|
|
void onMouseReleased(ogfx::Event& evt) override;
|
|
void onMouseMoved(ogfx::Event& evt) override;
|
|
|
|
void onSignal(ostd::tSignal& signal) override;
|
|
|
|
// inline virtual void onSignal(ostd::tSignal& signal) { }
|
|
// inline virtual void onFocusGained(void) { }
|
|
// inline virtual void onFocusLost(void) { }
|
|
// void onKeyPressed(ogfx::Event& evt) override;
|
|
// void onKeyReleased(ogfx::Event& evt) override;
|
|
|
|
private:
|
|
bool m_mousePressed { false };
|
|
ostd::Vec2 m_clickPos { 0, 0 };
|
|
float m_titleBarHeight { 20 };
|
|
float m_closeBtnWidth { 24 };
|
|
float m_borderWidth { 1 };
|
|
Rectangle m_closeBtnRect;
|
|
bool m_hoverCloseBtn { false };
|
|
ostd::String m_title { "" };
|
|
};
|
|
|
|
class TabPanel;
|
|
class TabWidget : public Widget
|
|
{
|
|
public:
|
|
inline TabWidget(void) : Widget() { invalidate(); }
|
|
inline TabWidget(TabPanel& parent, const ostd::String& text) { create(parent, text); }
|
|
TabWidget& create(TabPanel& parent, const ostd::String& text);
|
|
|
|
void onMousePressed(ogfx::Event& evt) override;
|
|
void onMouseReleased(ogfx::Event& evt) override;
|
|
|
|
inline ostd::Vec2 getContentOffset(void) override { return m_parent->getContentOffset(); }
|
|
inline ostd::Vec2 getContentSize(void) override { return getSize(); }
|
|
|
|
inline void setText(const ostd::String& text) { m_text = text; }
|
|
inline ostd::String getText(void) { return m_text; }
|
|
|
|
private:
|
|
ostd::String m_text { "" };
|
|
};
|
|
|
|
class TabPanel : public Widget
|
|
{
|
|
public:
|
|
inline TabPanel(void) : Widget() { invalidate(); }
|
|
inline TabPanel(Widget& parent, const ostd::Vec2& subPosition = { 0, 0 }, const ostd::Vec2& size = { 0, 0 }) { create(parent, subPosition, size); }
|
|
TabPanel& create(Widget& parent, const ostd::Vec2& subPosition = { 0, 0 }, const ostd::Vec2& size = { 0, 0 });
|
|
|
|
virtual void renderFrame(ogfx::RenderCore& gfx) override;
|
|
virtual void renderContent(ogfx::RenderCore& gfx) override;
|
|
|
|
ostd::Vec2 getContentSize(void) override;
|
|
ostd::Vec2 getContentOffset(void) override;
|
|
|
|
void onMousePressed(ogfx::Event& evt) override;
|
|
void onMouseReleased(ogfx::Event& evt) override;
|
|
void onMouseMoved(ogfx::Event& evt) override;
|
|
|
|
// TabWidget& newTab(const ostd::String& text);
|
|
void addTab(TabWidget& tab);
|
|
inline bool selectTab(uint32_t tabIndex) { if (tabIndex >= m_tabs.size()) return false; m_selectedTab = tabIndex; return true; }
|
|
inline int32_t getSelectedTab(void) { return m_selectedTab; }
|
|
|
|
private:
|
|
std::vector<TabWidget*> m_tabs;
|
|
int32_t m_selectedTab { -1 };
|
|
ostd::Vec2 m_mousePos { -10000, -10000 };
|
|
int32_t m_hoverTab { -1 };
|
|
bool m_enableTabBarColorBlend { false };
|
|
};
|
|
}
|
|
} |