Started work on gui Widget system
This commit is contained in:
parent
f0f644102b
commit
924da0dba6
15 changed files with 1082 additions and 75 deletions
|
|
@ -89,7 +89,7 @@ list(APPEND OGFX_SOURCE_FILES
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/RawTextInput.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/RawTextInput.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/Window.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/Window.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/WindowOutputHandler.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/WindowOutputHandler.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/Widget.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/Widgets.cpp
|
||||||
|
|
||||||
# render
|
# render
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/render/BasicRenderer.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/render/BasicRenderer.cpp
|
||||||
|
|
|
||||||
|
|
@ -1 +1,5 @@
|
||||||
Add Color constants to ostd::Color
|
***Add Color constants to ostd::Color
|
||||||
|
Add MouseEntered/MouseExited callbacks
|
||||||
|
Fix mouse detection currently using local coordinates
|
||||||
|
implement JSON theme loading
|
||||||
|
Implemenmt MouseDragged callback
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,10 @@
|
||||||
namespace ogfx
|
namespace ogfx
|
||||||
{
|
{
|
||||||
class WindowCore;
|
class WindowCore;
|
||||||
|
namespace gui
|
||||||
|
{
|
||||||
|
class Widget;
|
||||||
|
}
|
||||||
class WindowResizedData : public ostd::BaseObject
|
class WindowResizedData : public ostd::BaseObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -55,6 +59,7 @@ namespace ogfx
|
||||||
float position_x;
|
float position_x;
|
||||||
float position_y;
|
float position_y;
|
||||||
eButton button;
|
eButton button;
|
||||||
|
gui::Widget* mousePressedOnWidget { nullptr };
|
||||||
WindowCore& parentWindow;
|
WindowCore& parentWindow;
|
||||||
};
|
};
|
||||||
class KeyEventData : public ostd::BaseObject
|
class KeyEventData : public ostd::BaseObject
|
||||||
|
|
@ -73,4 +78,23 @@ namespace ogfx
|
||||||
eKeyEvent eventType;
|
eKeyEvent eventType;
|
||||||
WindowCore& parentWindow;
|
WindowCore& parentWindow;
|
||||||
};
|
};
|
||||||
|
namespace gui
|
||||||
|
{
|
||||||
|
class Event
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline Event(WindowCore& _window) : window(_window) { }
|
||||||
|
inline void handle(void) { m_handled = true; }
|
||||||
|
inline bool isHandled(void) const { return m_handled; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
WindowCore& window;
|
||||||
|
WindowResizedData* windowResized { nullptr };
|
||||||
|
MouseEventData* mouse { nullptr };
|
||||||
|
KeyEventData* keyboard { nullptr };
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_handled { false };
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
90
src/ogfx/gui/Themes.hpp
Normal file
90
src/ogfx/gui/Themes.hpp
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
OmniaFramework - A collection of useful functionality
|
||||||
|
Copyright (C) 2025 OmniaX-Dev
|
||||||
|
|
||||||
|
This file is part of OmniaFramework.
|
||||||
|
|
||||||
|
OmniaFramework is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OmniaFramework is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OmniaFramework. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ostd/data/Color.hpp>
|
||||||
|
#include <ostd/math/Geometry.hpp>
|
||||||
|
#include <variant>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace ogfx
|
||||||
|
{
|
||||||
|
namespace gui
|
||||||
|
{
|
||||||
|
struct Theme
|
||||||
|
{
|
||||||
|
public: using ThemeValue = std::variant<int, float, bool, ostd::String, ostd::Color, ostd::Rectangle, ostd::Vec2>;
|
||||||
|
public:
|
||||||
|
inline Theme(bool blank = false)
|
||||||
|
{
|
||||||
|
if (blank) return;
|
||||||
|
|
||||||
|
set("window.backgroundColor", ostd::Colors::Black);
|
||||||
|
|
||||||
|
set("label.textColor", ostd::Colors::White);
|
||||||
|
set("label.backgroundColor", ostd::Colors::Transparent);
|
||||||
|
set("label.borderColor", ostd::Colors::White);
|
||||||
|
set("label.fontSize", 20);
|
||||||
|
set("label.borderRadius", 20);
|
||||||
|
set("label.borderWidth", 2);
|
||||||
|
set("label.showBackground", false);
|
||||||
|
set("label.showBorder", false);
|
||||||
|
set("label.padding", ostd::Rectangle { 5, 5, 5, 5 });
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Theme& blank(void)
|
||||||
|
{
|
||||||
|
m_values.clear();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Theme& loadFromJsonFile(const ostd::String& jsonFilePath)
|
||||||
|
{
|
||||||
|
return *this; //TODO: Implement
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void set(const std::string& key, ThemeValue value)
|
||||||
|
{
|
||||||
|
m_values[key] = std::move(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const ThemeValue* __get(const ostd::String& key) const
|
||||||
|
{
|
||||||
|
auto it = m_values.find(key);
|
||||||
|
return it != m_values.end() ? &it->second : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline T get(const ostd::String& key, const T& fallback) const
|
||||||
|
{
|
||||||
|
if (auto v = __get(key))
|
||||||
|
{
|
||||||
|
if (auto p = std::get_if<T>(v))
|
||||||
|
return *p;
|
||||||
|
}
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<ostd::String, ThemeValue> m_values;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
/*
|
|
||||||
OmniaFramework - A collection of useful functionality
|
|
||||||
Copyright (C) 2025 OmniaX-Dev
|
|
||||||
|
|
||||||
This file is part of OmniaFramework.
|
|
||||||
|
|
||||||
OmniaFramework is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
OmniaFramework is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OmniaFramework. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "Widget.hpp"
|
|
||||||
|
|
||||||
namespace ogfx
|
|
||||||
{
|
|
||||||
namespace gui
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
/*
|
|
||||||
OmniaFramework - A collection of useful functionality
|
|
||||||
Copyright (C) 2025 OmniaX-Dev
|
|
||||||
|
|
||||||
This file is part of OmniaFramework.
|
|
||||||
|
|
||||||
OmniaFramework is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
OmniaFramework is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OmniaFramework. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ostd/data/BaseObject.hpp>
|
|
||||||
#include <ostd/math/Geometry.hpp>
|
|
||||||
|
|
||||||
namespace ogfx
|
|
||||||
{
|
|
||||||
namespace gui
|
|
||||||
{
|
|
||||||
class Widget : public ostd::BaseObject, public ostd::Rectangle
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
private:
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
526
src/ogfx/gui/Widgets.cpp
Normal file
526
src/ogfx/gui/Widgets.cpp
Normal file
|
|
@ -0,0 +1,526 @@
|
||||||
|
/*
|
||||||
|
OmniaFramework - A collection of useful functionality
|
||||||
|
Copyright (C) 2025 OmniaX-Dev
|
||||||
|
|
||||||
|
This file is part of OmniaFramework.
|
||||||
|
|
||||||
|
OmniaFramework is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OmniaFramework is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OmniaFramework. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Widgets.hpp"
|
||||||
|
#include <ogfx/render/BasicRenderer.hpp>
|
||||||
|
#include <ogfx/gui/Window.hpp>
|
||||||
|
|
||||||
|
namespace ogfx
|
||||||
|
{
|
||||||
|
namespace gui
|
||||||
|
{
|
||||||
|
WidgetManager::WidgetManager(WindowCore& window, Widget& owner) : m_window(window), m_owner(owner)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WidgetManager::hasWidget(Widget& widget)
|
||||||
|
{
|
||||||
|
bool found = std::ranges::find(m_widgetList, &widget) != m_widgetList.end();
|
||||||
|
return found && widget.isValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WidgetManager::requestFocus(Widget& widget)
|
||||||
|
{
|
||||||
|
if (!hasWidget(widget)) return false;
|
||||||
|
if (&widget == m_focused) return true;
|
||||||
|
for (auto& w : m_widgetList)
|
||||||
|
{
|
||||||
|
if (w == nullptr) continue;
|
||||||
|
if (w->isInvalid()) continue;
|
||||||
|
if (w->m_focused)
|
||||||
|
{
|
||||||
|
w->m_focused = false;
|
||||||
|
w->onFocusLost(Event(m_window));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
w->m_focused = false;
|
||||||
|
}
|
||||||
|
widget.m_focused = true;
|
||||||
|
widget.onFocusGained(Event(m_window));
|
||||||
|
m_focused = &widget;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WidgetManager::addWidget(Widget& widget)
|
||||||
|
{
|
||||||
|
if (hasWidget(widget)) return false;
|
||||||
|
widget.m_parent = &m_owner;
|
||||||
|
m_widgetList.push_back(&widget);
|
||||||
|
std::ranges::sort(m_widgetList, {}, [](Widget* w) {
|
||||||
|
return w->m_zIndex;
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget* WidgetManager::focusNext(void)
|
||||||
|
{
|
||||||
|
if (m_widgetList.empty())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
Widget* next = nullptr;
|
||||||
|
Widget* smallest = nullptr;
|
||||||
|
|
||||||
|
int32_t currentTabIndex = (m_focused != nullptr ? m_focused->m_tabIndex : std::numeric_limits<int32_t>::max());
|
||||||
|
for (Widget* w : m_widgetList)
|
||||||
|
{
|
||||||
|
int tab_i = w->m_tabIndex;
|
||||||
|
if (tab_i < 0) continue;
|
||||||
|
if (!smallest || tab_i < smallest->m_tabIndex)
|
||||||
|
smallest = w;
|
||||||
|
if (tab_i > currentTabIndex)
|
||||||
|
{
|
||||||
|
if (!next || tab_i < next->m_tabIndex)
|
||||||
|
next = w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Widget* w = next ? next : smallest;
|
||||||
|
requestFocus(*w);
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WidgetManager::draw(ogfx::BasicRenderer2D& gfx)
|
||||||
|
{
|
||||||
|
for (auto& w : m_widgetList)
|
||||||
|
{
|
||||||
|
if (w == nullptr) continue;
|
||||||
|
if (w->isInvalid()) continue;
|
||||||
|
w->__draw(gfx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WidgetManager::update(void)
|
||||||
|
{
|
||||||
|
for (auto& w : m_widgetList)
|
||||||
|
{
|
||||||
|
if (w == nullptr) continue;
|
||||||
|
if (w->isInvalid()) continue;
|
||||||
|
w->__update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WidgetManager::onThemeApplied(const Theme& theme)
|
||||||
|
{
|
||||||
|
for (auto& w : m_widgetList)
|
||||||
|
{
|
||||||
|
if (w == nullptr) continue;
|
||||||
|
if (w->isInvalid()) continue;
|
||||||
|
w->__applyTheme(theme, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WidgetManager::onMousePressed(const Event& event)
|
||||||
|
{
|
||||||
|
for (int32_t i = m_widgetList.size() - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
Widget* w = m_widgetList[i];
|
||||||
|
if (w == nullptr) continue;
|
||||||
|
if (w->isInvalid()) continue;
|
||||||
|
if (!w->contains(event.mouse->position_x, event.mouse->position_y, true))
|
||||||
|
continue;
|
||||||
|
w->__onMousePressed(event);
|
||||||
|
m_mousePressedOnWidget = w;
|
||||||
|
if (event.isHandled())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WidgetManager::onMouseReleased(const Event& event)
|
||||||
|
{
|
||||||
|
for (int32_t i = m_widgetList.size() - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
Widget* w = m_widgetList[i];
|
||||||
|
if (w == nullptr) continue;
|
||||||
|
if (w->isInvalid()) continue;
|
||||||
|
event.mouse->mousePressedOnWidget = m_mousePressedOnWidget;
|
||||||
|
w->__onMouseReleased(event);
|
||||||
|
requestFocus(*w);
|
||||||
|
m_mousePressedOnWidget = nullptr;
|
||||||
|
if (event.isHandled())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WidgetManager::onMouseMoved(const Event& event)
|
||||||
|
{
|
||||||
|
for (int32_t i = m_widgetList.size() - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
Widget* w = m_widgetList[i];
|
||||||
|
if (w == nullptr) continue;
|
||||||
|
if (w->isInvalid()) continue;
|
||||||
|
if (!w->contains(event.mouse->position_x, event.mouse->position_y, true))
|
||||||
|
continue;
|
||||||
|
w->__onMouseMoved(event);
|
||||||
|
if (event.isHandled())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WidgetManager::onMouseDragged(const Event& event)
|
||||||
|
{
|
||||||
|
for (int32_t i = m_widgetList.size() - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
Widget* w = m_widgetList[i];
|
||||||
|
if (w == nullptr) continue;
|
||||||
|
if (w->isInvalid()) continue;
|
||||||
|
if (!w->contains(event.mouse->position_x, event.mouse->position_y, true))
|
||||||
|
continue;
|
||||||
|
w->__onMouseDragged(event);
|
||||||
|
if (event.isHandled())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WidgetManager::onKeyPressed(const Event& event)
|
||||||
|
{
|
||||||
|
if (!m_focused) return;
|
||||||
|
m_focused->__onKeyPressed(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WidgetManager::onKeyReleased(const Event& event)
|
||||||
|
{
|
||||||
|
if (!m_focused) return;
|
||||||
|
m_focused->__onKeyReleased(event);
|
||||||
|
if (m_tabNavigationEnabled && event.keyboard->keyCode == SDLK_TAB)
|
||||||
|
focusNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WidgetManager::onTextEntered(const Event& event)
|
||||||
|
{
|
||||||
|
if (!m_focused) return;
|
||||||
|
m_focused->__onTextEntered(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WidgetManager::onWindowClosed(const Event& event)
|
||||||
|
{
|
||||||
|
for (auto& w : m_widgetList)
|
||||||
|
{
|
||||||
|
if (w == nullptr) continue;
|
||||||
|
if (w->isInvalid()) continue;
|
||||||
|
w->__onWindowClosed(event);
|
||||||
|
if (event.isHandled())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WidgetManager::onWindowResized(const Event& event)
|
||||||
|
{
|
||||||
|
for (auto& w : m_widgetList)
|
||||||
|
{
|
||||||
|
if (w == nullptr) continue;
|
||||||
|
if (w->isInvalid()) continue;
|
||||||
|
w->__onWindowResized(event);
|
||||||
|
if (event.isHandled())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WidgetManager::onWindowFocused(const Event& event)
|
||||||
|
{
|
||||||
|
for (auto& w : m_widgetList)
|
||||||
|
{
|
||||||
|
if (w == nullptr) continue;
|
||||||
|
if (w->isInvalid()) continue;
|
||||||
|
w->__onWIndowFocused(event);
|
||||||
|
if (event.isHandled())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WidgetManager::onWindowFocusLost(const Event& event)
|
||||||
|
{
|
||||||
|
for (auto& w : m_widgetList)
|
||||||
|
{
|
||||||
|
if (w == nullptr) continue;
|
||||||
|
if (w->isInvalid()) continue;
|
||||||
|
w->__onWindowFocusLost(event);
|
||||||
|
if (event.isHandled())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Widget::Widget(const ostd::Rectangle& bounds, WindowCore& window) : Rectangle(bounds), m_widgets(window, *this)
|
||||||
|
{
|
||||||
|
m_window = &window;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Widget::addChild(Widget& child)
|
||||||
|
{
|
||||||
|
if (!m_allowChildren)
|
||||||
|
return false;
|
||||||
|
return m_widgets.addWidget(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
ostd::Vec2 Widget::getGlobalPosition(void) const
|
||||||
|
{
|
||||||
|
ostd::Vec2 glob = getPosition();
|
||||||
|
if (!m_rootChild && m_parent != nullptr)
|
||||||
|
glob += m_parent->getGlobalPosition();
|
||||||
|
return glob;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::applyThemeValue(Theme& theme, const ostd::String& key, Theme::ThemeValue value, bool propagate)
|
||||||
|
{
|
||||||
|
auto currentValue = theme.__get(key);
|
||||||
|
if (currentValue == nullptr) return;
|
||||||
|
theme.set(key, value);
|
||||||
|
__applyTheme(theme, propagate);
|
||||||
|
theme.set(key, *currentValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::__draw(ogfx::BasicRenderer2D& gfx)
|
||||||
|
{
|
||||||
|
if (isDrawBoxEnabled())
|
||||||
|
gfx.fillRect({ getGlobalPosition(), getSize() }, getDrawBoxColor());
|
||||||
|
onDraw(gfx);
|
||||||
|
if (hasChildren())
|
||||||
|
m_widgets.draw(gfx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::__update(void)
|
||||||
|
{
|
||||||
|
onUpdate();
|
||||||
|
if (hasChildren())
|
||||||
|
m_widgets.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::__onMousePressed(const Event& event)
|
||||||
|
{
|
||||||
|
if (hasChildren())
|
||||||
|
m_widgets.onMousePressed(event);
|
||||||
|
if (!event.isHandled())
|
||||||
|
{
|
||||||
|
if (callback_onMousePressed)
|
||||||
|
callback_onMousePressed(event);
|
||||||
|
onMousePressed(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::__onMouseReleased(const Event& event)
|
||||||
|
{
|
||||||
|
if (hasChildren())
|
||||||
|
m_widgets.onMouseReleased(event);
|
||||||
|
if (!event.isHandled())
|
||||||
|
{
|
||||||
|
if (callback_onMouseReleased)
|
||||||
|
callback_onMouseReleased(event);
|
||||||
|
onMouseReleased(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::__onMouseMoved(const Event& event)
|
||||||
|
{
|
||||||
|
if (hasChildren())
|
||||||
|
m_widgets.onMouseMoved(event);
|
||||||
|
if (!event.isHandled())
|
||||||
|
{
|
||||||
|
if (callback_onMouseMoved)
|
||||||
|
callback_onMouseMoved(event);
|
||||||
|
onMouseMoved(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::__onMouseDragged(const Event& event)
|
||||||
|
{
|
||||||
|
if (hasChildren())
|
||||||
|
m_widgets.onMouseDragged(event);
|
||||||
|
if (!event.isHandled())
|
||||||
|
{
|
||||||
|
if (callback_onMouseDragged)
|
||||||
|
callback_onMouseDragged(event);
|
||||||
|
onMouseDragged(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::__onKeyPressed(const Event& event)
|
||||||
|
{
|
||||||
|
if (hasChildren())
|
||||||
|
m_widgets.onKeyPressed(event);
|
||||||
|
if (!event.isHandled())
|
||||||
|
{
|
||||||
|
if (callback_onKeyPressed)
|
||||||
|
callback_onKeyPressed(event);
|
||||||
|
onKeyPressed(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::__onKeyReleased(const Event& event)
|
||||||
|
{
|
||||||
|
if (hasChildren())
|
||||||
|
m_widgets.onKeyReleased(event);
|
||||||
|
if (!event.isHandled())
|
||||||
|
{
|
||||||
|
if (callback_onKeyReleased)
|
||||||
|
callback_onKeyReleased(event);
|
||||||
|
onKeyReleased(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::__onTextEntered(const Event& event)
|
||||||
|
{
|
||||||
|
if (hasChildren())
|
||||||
|
m_widgets.onTextEntered(event);
|
||||||
|
if (!event.isHandled())
|
||||||
|
{
|
||||||
|
if (callback_onTextEntered)
|
||||||
|
callback_onTextEntered(event);
|
||||||
|
onTextEntered(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::__onWindowClosed(const Event& event)
|
||||||
|
{
|
||||||
|
if (hasChildren())
|
||||||
|
m_widgets.onWindowClosed(event);
|
||||||
|
if (!event.isHandled())
|
||||||
|
{
|
||||||
|
if (callback_onWindowClosed)
|
||||||
|
callback_onWindowClosed(event);
|
||||||
|
onWindowClosed(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::__onWindowResized(const Event& event)
|
||||||
|
{
|
||||||
|
if (hasChildren())
|
||||||
|
m_widgets.onWindowResized(event);
|
||||||
|
if (!event.isHandled())
|
||||||
|
{
|
||||||
|
if (callback_onWindowResized)
|
||||||
|
callback_onWindowResized(event);
|
||||||
|
onWindowResized(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::__onWIndowFocused(const Event& event)
|
||||||
|
{
|
||||||
|
if (hasChildren())
|
||||||
|
m_widgets.onWindowFocused(event);
|
||||||
|
if (!event.isHandled())
|
||||||
|
{
|
||||||
|
if (callback_onWindowFocused)
|
||||||
|
callback_onWindowFocused(event);
|
||||||
|
onWindowFocused(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::__onWindowFocusLost(const Event& event)
|
||||||
|
{
|
||||||
|
if (hasChildren())
|
||||||
|
m_widgets.onWindowFocusLost(event);
|
||||||
|
if (!event.isHandled())
|
||||||
|
{
|
||||||
|
if (callback_onWindowFocusLost)
|
||||||
|
callback_onWindowFocusLost(event);
|
||||||
|
onWindowFocusLost(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::__applyTheme(const Theme& theme, bool propagate)
|
||||||
|
{
|
||||||
|
if (propagate && hasChildren())
|
||||||
|
m_widgets.onThemeApplied(theme);
|
||||||
|
applyTheme(theme);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace widgets
|
||||||
|
{
|
||||||
|
RootWidget::RootWidget(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window)
|
||||||
|
{
|
||||||
|
m_rootChild = true;
|
||||||
|
setSize(static_cast<float>(window.getWindowWidth()), static_cast<float>(window.getWindowHeight()));
|
||||||
|
enableDrawBox();
|
||||||
|
setDrawBoxColor(window.getClearColor());
|
||||||
|
setTypeName("ogfx::gui::widgets::RootWidget");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RootWidget::onWindowResized(const Event& event)
|
||||||
|
{
|
||||||
|
setSize(static_cast<float>(event.windowResized->new_width), static_cast<float>(event.windowResized->new_height));
|
||||||
|
}
|
||||||
|
|
||||||
|
void RootWidget::applyTheme(const Theme& theme)
|
||||||
|
{
|
||||||
|
setDrawBoxColor(theme.get<ostd::Color>("window.backgroundColor", getWindow().getClearColor()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Label& Label::create(const ostd::String& text)
|
||||||
|
{
|
||||||
|
setText(text);
|
||||||
|
setPadding({ 5, 5, 5, 5 });
|
||||||
|
setTypeName("ogfx::gui::widgets::Label");
|
||||||
|
disableDrawBox();
|
||||||
|
enableBackground(false);
|
||||||
|
validate();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Label::applyTheme(const Theme& theme)
|
||||||
|
{
|
||||||
|
setColor(theme.get<ostd::Color>("label.textColor", ostd::Colors::White));
|
||||||
|
setBackGroundColor(theme.get<ostd::Color>("label.backgroundColor", ostd::Colors::Transparent));
|
||||||
|
setFontSize(theme.get<int32_t>("label.fontSize", 20));
|
||||||
|
m_borderRadius = theme.get<int32_t>("label.borderRadius", 10);
|
||||||
|
m_borderWidth = theme.get<int32_t>("label.borderWidth", 2);
|
||||||
|
m_showBorder = theme.get<bool>("label.showBorder", false);
|
||||||
|
m_borderColor = theme.get<ostd::Color>("label.borderColor", ostd::Colors::White);
|
||||||
|
enableBackground(theme.get<bool>("label.showBackground", false));
|
||||||
|
setPadding(theme.get<ostd::Rectangle>("label.padding", { 5, 5, 5, 5 }));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Label::onDraw(ogfx::BasicRenderer2D& gfx)
|
||||||
|
{
|
||||||
|
if (m_textChanged)
|
||||||
|
__update_size(gfx);
|
||||||
|
if (m_showBackground)
|
||||||
|
gfx.fillRoundRect({ getGlobalPosition(), getSize() }, m_backgroundColor, m_borderRadius);
|
||||||
|
if (m_showBorder)
|
||||||
|
gfx.drawRoundRect({ getGlobalPosition(), getSize() }, m_borderColor, m_borderRadius, m_borderWidth);
|
||||||
|
gfx.drawString(getText(), getGlobalPosition() + ostd::Vec2 { getPadding().left(), getPadding().top() }, getColor());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Label::setText(const ostd::String& text)
|
||||||
|
{
|
||||||
|
m_text = text;
|
||||||
|
m_textChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Label::__update_size(ogfx::BasicRenderer2D& gfx)
|
||||||
|
{
|
||||||
|
auto size = gfx.getStringSize(getText(), getFontSize());
|
||||||
|
size.x += getPadding().left();
|
||||||
|
size.x += getPadding().right();
|
||||||
|
size.y += getPadding().top();
|
||||||
|
size.y += getPadding().bottom();
|
||||||
|
setSize({ static_cast<float>(size.x), static_cast<float>(size.y) });
|
||||||
|
m_textChanged = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
226
src/ogfx/gui/Widgets.hpp
Normal file
226
src/ogfx/gui/Widgets.hpp
Normal file
|
|
@ -0,0 +1,226 @@
|
||||||
|
/*
|
||||||
|
OmniaFramework - A collection of useful functionality
|
||||||
|
Copyright (C) 2025 OmniaX-Dev
|
||||||
|
|
||||||
|
This file is part of OmniaFramework.
|
||||||
|
|
||||||
|
OmniaFramework is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OmniaFramework is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OmniaFramework. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ostd/data/BaseObject.hpp>
|
||||||
|
#include <ostd/math/Geometry.hpp>
|
||||||
|
#include <ostd/data/Color.hpp>
|
||||||
|
#include <ogfx/gui/Themes.hpp>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
namespace ogfx
|
||||||
|
{
|
||||||
|
class BasicRenderer2D;
|
||||||
|
class WindowCore;
|
||||||
|
namespace gui
|
||||||
|
{
|
||||||
|
class Event;
|
||||||
|
class Widget;
|
||||||
|
class WidgetManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WidgetManager(WindowCore& window, Widget& owner);
|
||||||
|
bool hasWidget(Widget& widget);
|
||||||
|
bool requestFocus(Widget& widget);
|
||||||
|
bool addWidget(Widget& widget);
|
||||||
|
Widget* focusNext(void);
|
||||||
|
|
||||||
|
void draw(ogfx::BasicRenderer2D& gfx);
|
||||||
|
void update(void);
|
||||||
|
void onThemeApplied(const Theme& theme);
|
||||||
|
void onMousePressed(const Event& event);
|
||||||
|
void onMouseReleased(const Event& event);
|
||||||
|
void onMouseMoved(const Event& event);
|
||||||
|
void onMouseDragged(const Event& event);
|
||||||
|
void onKeyPressed(const Event& event);
|
||||||
|
void onKeyReleased(const Event& event);
|
||||||
|
void onTextEntered(const Event& event);
|
||||||
|
void onWindowClosed(const Event& event);
|
||||||
|
void onWindowResized(const Event& event);
|
||||||
|
void onWindowFocused(const Event& event);
|
||||||
|
void onWindowFocusLost(const Event& event);
|
||||||
|
|
||||||
|
inline int32_t widgetCount(void) const { return m_widgetList.size(); }
|
||||||
|
inline WindowCore& getWindow(void) { return m_window; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
WindowCore& m_window;
|
||||||
|
Widget& m_owner;
|
||||||
|
std::vector<Widget*> m_widgetList;
|
||||||
|
Widget* m_focused { nullptr };
|
||||||
|
bool m_tabNavigationEnabled { true };
|
||||||
|
Widget* m_mousePressedOnWidget { nullptr };
|
||||||
|
};
|
||||||
|
class Widget : public ostd::BaseObject, public ostd::Rectangle
|
||||||
|
{
|
||||||
|
public: using EventCallback = std::function<void(const Event&)>;
|
||||||
|
public:
|
||||||
|
Widget(const ostd::Rectangle& bounds, WindowCore& window);
|
||||||
|
bool addChild(Widget& child);
|
||||||
|
ostd::Vec2 getGlobalPosition(void) const;
|
||||||
|
virtual void applyTheme(const Theme& theme) = 0;
|
||||||
|
void applyThemeValue(Theme& theme, const ostd::String& key, Theme::ThemeValue value, bool propagate);
|
||||||
|
|
||||||
|
inline virtual void onDraw(ogfx::BasicRenderer2D& gfx) { }
|
||||||
|
inline virtual void onUpdate(void) { }
|
||||||
|
|
||||||
|
inline virtual void onMousePressed(const Event& event) { }
|
||||||
|
inline virtual void onMouseReleased(const Event& event) { }
|
||||||
|
inline virtual void onMouseMoved(const Event& event) { }
|
||||||
|
inline virtual void onMouseDragged(const Event& event) { }
|
||||||
|
inline virtual void onKeyPressed(const Event& event) { }
|
||||||
|
inline virtual void onKeyReleased(const Event& event) { }
|
||||||
|
inline virtual void onTextEntered(const Event& event) { }
|
||||||
|
inline virtual void onFocusGained(const Event& event) { }
|
||||||
|
inline virtual void onFocusLost(const Event& event) { }
|
||||||
|
inline virtual void onWindowClosed(const Event& event) { }
|
||||||
|
inline virtual void onWindowResized(const Event& event) { }
|
||||||
|
inline virtual void onWindowFocused(const Event& event) { }
|
||||||
|
inline virtual void onWindowFocusLost(const Event& event) { }
|
||||||
|
|
||||||
|
void __draw(ogfx::BasicRenderer2D& gfx);
|
||||||
|
void __update(void);
|
||||||
|
void __onMousePressed(const Event& event);
|
||||||
|
void __onMouseReleased(const Event& event);
|
||||||
|
void __onMouseMoved(const Event& event);
|
||||||
|
void __onMouseDragged(const Event& event);
|
||||||
|
void __onKeyPressed(const Event& event);
|
||||||
|
void __onKeyReleased(const Event& event);
|
||||||
|
void __onTextEntered(const Event& event);
|
||||||
|
void __onWindowClosed(const Event& event);
|
||||||
|
void __onWindowResized(const Event& event);
|
||||||
|
void __onWIndowFocused(const Event& event);
|
||||||
|
void __onWindowFocusLost(const Event& event);
|
||||||
|
void __applyTheme(const Theme& theme, bool propagate);
|
||||||
|
|
||||||
|
inline virtual void setMousePressedCallback(EventCallback callback) { callback_onMousePressed = callback; }
|
||||||
|
inline virtual void setMouseReleasedCallback(EventCallback callback) { callback_onMouseReleased = callback; }
|
||||||
|
inline virtual void setMouseMovedCallback(EventCallback callback) { callback_onMouseMoved = callback; }
|
||||||
|
inline virtual void setMouseDraggedCallback(EventCallback callback) { callback_onMouseDragged = callback; }
|
||||||
|
inline virtual void setKeyPressedCallback(EventCallback callback) { callback_onKeyPressed = callback; }
|
||||||
|
inline virtual void setKeyReleasedCallback(EventCallback callback) { callback_onKeyReleased = callback; }
|
||||||
|
inline virtual void setTextEnteredCallback(EventCallback callback) { callback_onTextEntered = callback; }
|
||||||
|
inline virtual void setWindowClosedCallback(EventCallback callback) { callback_onWindowClosed = callback; }
|
||||||
|
inline virtual void setWindowResizedCallback(EventCallback callback) { callback_onWindowResized = callback; }
|
||||||
|
inline virtual void setWIndowFocusedCallback(EventCallback callback) { callback_onWindowFocused = callback; }
|
||||||
|
inline virtual void setWindowFocusLostCallback(EventCallback callback) { callback_onWindowFocusLost = callback; }
|
||||||
|
|
||||||
|
inline bool hasChildren(void) const { return m_allowChildren && m_widgets.widgetCount() > 0; }
|
||||||
|
inline virtual bool isInvalid(void) const override { return ostd::BaseObject::isInvalid() || (m_parent == nullptr && !m_rootChild); }
|
||||||
|
inline void setTabIndex(int32_t tabIndex) { m_tabIndex = tabIndex; }
|
||||||
|
inline int32_t getTabIndex(void) const { return m_tabIndex; }
|
||||||
|
inline bool isFocused(void) const { return m_focused; }
|
||||||
|
inline WindowCore& getWindow(void) { return *m_window; }
|
||||||
|
inline Widget* getParent(void) { return m_parent; }
|
||||||
|
inline int32_t getZIndex(void) const { return m_zIndex; }
|
||||||
|
inline bool isChildrenEnabled(void) const { return m_allowChildren; }
|
||||||
|
inline void setPadding(const ostd::Rectangle& pad) { m_padding = pad; }
|
||||||
|
inline Rectangle getPadding(void) { return m_padding; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
inline void disableChildren(void) { m_allowChildren = false; }
|
||||||
|
inline void disableDrawBox(void) { m_drawBox = false; }
|
||||||
|
inline void enableDrawBox(void) { m_drawBox = true; }
|
||||||
|
inline bool isDrawBoxEnabled(void) const { return m_drawBox; }
|
||||||
|
inline void setDrawBoxColor(const ostd::Color& color) { m_drawBoxColor = color; }
|
||||||
|
inline ostd::Color getDrawBoxColor(void) { return m_drawBoxColor; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool m_rootChild { false };
|
||||||
|
|
||||||
|
EventCallback callback_onMousePressed { nullptr };
|
||||||
|
EventCallback callback_onMouseReleased { nullptr };
|
||||||
|
EventCallback callback_onMouseMoved { nullptr };
|
||||||
|
EventCallback callback_onMouseDragged { nullptr };
|
||||||
|
EventCallback callback_onKeyPressed { nullptr };
|
||||||
|
EventCallback callback_onKeyReleased { nullptr };
|
||||||
|
EventCallback callback_onTextEntered { nullptr };
|
||||||
|
EventCallback callback_onWindowClosed { nullptr };
|
||||||
|
EventCallback callback_onWindowResized { nullptr };
|
||||||
|
EventCallback callback_onWindowFocused { nullptr };
|
||||||
|
EventCallback callback_onWindowFocusLost { nullptr };
|
||||||
|
|
||||||
|
private:
|
||||||
|
WindowCore* m_window { nullptr };
|
||||||
|
Widget* m_parent { nullptr };
|
||||||
|
bool m_focused { false };
|
||||||
|
int32_t m_tabIndex { -1 };
|
||||||
|
int32_t m_zIndex { -1 };
|
||||||
|
WidgetManager m_widgets;
|
||||||
|
bool m_allowChildren { true };
|
||||||
|
|
||||||
|
bool m_drawBox { true };
|
||||||
|
ostd::Color m_drawBoxColor { 255, 0, 0 };
|
||||||
|
|
||||||
|
ostd::Rectangle m_padding { 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
friend class WidgetManager;
|
||||||
|
};
|
||||||
|
namespace widgets
|
||||||
|
{
|
||||||
|
class RootWidget : public Widget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RootWidget(WindowCore& window);
|
||||||
|
void onWindowResized(const Event& event) override;
|
||||||
|
void applyTheme(const Theme& theme) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
class Label : public Widget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline Label(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(""); }
|
||||||
|
inline Label(WindowCore& window, const ostd::String& text) : Widget({ 0, 0, 0, 0 }, window) { create(text); }
|
||||||
|
Label& create(const ostd::String& text);
|
||||||
|
void applyTheme(const Theme& theme) override;
|
||||||
|
void onDraw(ogfx::BasicRenderer2D& gfx) override;
|
||||||
|
void setText(const ostd::String& text);
|
||||||
|
inline ostd::String getText(void) const { return m_text; }
|
||||||
|
inline ostd::Color getColor(void) const { return m_color; }
|
||||||
|
inline void setColor(const ostd::Color& color) { m_color = color; }
|
||||||
|
inline int32_t getFontSize(void) const { return m_fontSize; }
|
||||||
|
inline void setFontSize(int32_t fontSize) { m_fontSize = fontSize; }
|
||||||
|
inline void setBackGroundColor(const ostd::Color& color) { m_backgroundColor = color; }
|
||||||
|
inline ostd::Color getBackgroundColor(const ostd::Color& color) { return m_backgroundColor; }
|
||||||
|
inline void enableBackground(bool enable = true) { m_showBackground = enable; }
|
||||||
|
inline bool isBackgoundEnabled(void) const { return m_showBackground; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void __update_size(ogfx::BasicRenderer2D& gfx);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ostd::String m_text { "" };
|
||||||
|
bool m_textChanged { false };
|
||||||
|
int32_t m_fontSize { 20 };
|
||||||
|
ostd::Color m_color { 255, 255, 255 };
|
||||||
|
int32_t m_borderRadius { 10 };
|
||||||
|
int32_t m_borderWidth { 2 };
|
||||||
|
bool m_showBorder { false };
|
||||||
|
bool m_showBackground { false };
|
||||||
|
ostd::Color m_backgroundColor { ostd::Colors::Transparent };
|
||||||
|
ostd::Color m_borderColor { 255, 255, 255 };
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include "Window.hpp"
|
#include "Window.hpp"
|
||||||
#include "../../ostd/utils/Time.hpp"
|
#include "../../ostd/utils/Time.hpp"
|
||||||
|
#include <SDL3/SDL_events.h>
|
||||||
|
|
||||||
namespace ogfx
|
namespace ogfx
|
||||||
{
|
{
|
||||||
|
|
@ -74,9 +75,12 @@ namespace ogfx
|
||||||
connectSignal(ostd::tBuiltinSignals::MousePressed);
|
connectSignal(ostd::tBuiltinSignals::MousePressed);
|
||||||
connectSignal(ostd::tBuiltinSignals::MouseReleased);
|
connectSignal(ostd::tBuiltinSignals::MouseReleased);
|
||||||
connectSignal(ostd::tBuiltinSignals::MouseMoved);
|
connectSignal(ostd::tBuiltinSignals::MouseMoved);
|
||||||
|
connectSignal(ostd::tBuiltinSignals::MouseMoved);
|
||||||
connectSignal(ostd::tBuiltinSignals::OnGuiEvent);
|
connectSignal(ostd::tBuiltinSignals::OnGuiEvent);
|
||||||
connectSignal(ostd::tBuiltinSignals::WindowClosed);
|
connectSignal(ostd::tBuiltinSignals::WindowClosed);
|
||||||
connectSignal(ostd::tBuiltinSignals::WindowResized);
|
connectSignal(ostd::tBuiltinSignals::WindowResized);
|
||||||
|
connectSignal(ostd::tBuiltinSignals::WindowFocused);
|
||||||
|
connectSignal(ostd::tBuiltinSignals::WindowLostFocus);
|
||||||
|
|
||||||
__on_window_init(width, height, title);
|
__on_window_init(width, height, title);
|
||||||
}
|
}
|
||||||
|
|
@ -160,6 +164,11 @@ namespace ogfx
|
||||||
SDL_PushEvent(&e);
|
SDL_PushEvent(&e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WindowCore::handleSignal(ostd::tSignal& signal)
|
||||||
|
{
|
||||||
|
__on_signal(signal);
|
||||||
|
}
|
||||||
|
|
||||||
MouseEventData WindowCore::get_mouse_state(void)
|
MouseEventData WindowCore::get_mouse_state(void)
|
||||||
{
|
{
|
||||||
float mx = 0, my = 0;
|
float mx = 0, my = 0;
|
||||||
|
|
@ -216,6 +225,14 @@ namespace ogfx
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
else if (event.type == SDL_EVENT_WINDOW_FOCUS_GAINED)
|
||||||
|
{
|
||||||
|
ostd::SignalHandler::emitSignal(ostd::tBuiltinSignals::WindowFocused, ostd::tSignalPriority::RealTime, *this);
|
||||||
|
}
|
||||||
|
else if (event.type == SDL_EVENT_WINDOW_FOCUS_LOST)
|
||||||
|
{
|
||||||
|
ostd::SignalHandler::emitSignal(ostd::tBuiltinSignals::WindowLostFocus, ostd::tSignalPriority::RealTime, *this);
|
||||||
|
}
|
||||||
else if (event.type == SDL_EVENT_WINDOW_RESIZED)
|
else if (event.type == SDL_EVENT_WINDOW_RESIZED)
|
||||||
{
|
{
|
||||||
WindowResizedData wrd(*this, m_windowWidth, m_windowHeight, 0, 0);
|
WindowResizedData wrd(*this, m_windowWidth, m_windowHeight, 0, 0);
|
||||||
|
|
@ -267,6 +284,7 @@ namespace ogfx
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void GraphicsWindow::__on_window_init(int32_t width, int32_t height, const ostd::String& title)
|
void GraphicsWindow::__on_window_init(int32_t width, int32_t height, const ostd::String& title)
|
||||||
{
|
{
|
||||||
SDL_SetWindowResizable(m_window, false);
|
SDL_SetWindowResizable(m_window, false);
|
||||||
|
|
@ -305,6 +323,11 @@ namespace ogfx
|
||||||
m_fpsUpdateTimer.update();
|
m_fpsUpdateTimer.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GraphicsWindow::__on_signal(ostd::tSignal& signal)
|
||||||
|
{
|
||||||
|
onSignal(signal);
|
||||||
|
}
|
||||||
|
|
||||||
void GraphicsWindow::__on_event(SDL_Event& event)
|
void GraphicsWindow::__on_event(SDL_Event& event)
|
||||||
{
|
{
|
||||||
onSDLEvent(event);
|
onSDLEvent(event);
|
||||||
|
|
@ -320,11 +343,24 @@ namespace ogfx
|
||||||
|
|
||||||
namespace gui
|
namespace gui
|
||||||
{
|
{
|
||||||
|
void Window::addWidget(Widget& widget)
|
||||||
|
{
|
||||||
|
m_rootWidget.addChild(widget);
|
||||||
|
setTheme(*m_guiTheme);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::setTheme(const gui::Theme& theme)
|
||||||
|
{
|
||||||
|
m_guiTheme = &theme;
|
||||||
|
m_rootWidget.__applyTheme(theme, true);
|
||||||
|
}
|
||||||
|
|
||||||
void Window::__on_window_init(int32_t width, int32_t height, const ostd::String& title)
|
void Window::__on_window_init(int32_t width, int32_t height, const ostd::String& title)
|
||||||
{
|
{
|
||||||
enableBlockingEvents();
|
enableBlockingEvents();
|
||||||
setTypeName("ogfx::gui::Window");
|
setTypeName("ogfx::gui::Window");
|
||||||
m_gfx.init(*this);
|
m_gfx.init(*this);
|
||||||
|
loadDefaultTHeme();
|
||||||
onInitialize();
|
onInitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -339,19 +375,70 @@ namespace ogfx
|
||||||
{
|
{
|
||||||
handle_events();
|
handle_events();
|
||||||
before_render();
|
before_render();
|
||||||
|
m_rootWidget.__update();
|
||||||
|
m_rootWidget.__draw(m_gfx);
|
||||||
onRedraw(m_gfx);
|
onRedraw(m_gfx);
|
||||||
m_gfx.drawString("Hello World", { 100, 100 }, { 255, 0, 0 });
|
|
||||||
after_render();
|
after_render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::__on_event(SDL_Event& event)
|
void Window::__on_signal(ostd::tSignal& signal)
|
||||||
{
|
{
|
||||||
if (event.type == SDL_EVENT_KEY_UP)
|
Event evt(*this);
|
||||||
|
if (signal.ID == ostd::tBuiltinSignals::WindowClosed)
|
||||||
{
|
{
|
||||||
if (event.key.key == SDLK_ESCAPE)
|
m_rootWidget.__onWindowClosed(evt);
|
||||||
|
}
|
||||||
|
else if (signal.ID == ostd::tBuiltinSignals::WindowFocused)
|
||||||
|
{
|
||||||
|
m_rootWidget.__onWIndowFocused(evt);
|
||||||
|
}
|
||||||
|
else if (signal.ID == ostd::tBuiltinSignals::WindowLostFocus)
|
||||||
|
{
|
||||||
|
m_rootWidget.__onWindowFocusLost(evt);
|
||||||
|
}
|
||||||
|
else if (signal.ID == ostd::tBuiltinSignals::WindowResized)
|
||||||
|
{
|
||||||
|
evt.windowResized = &(ogfx::WindowResizedData&)signal.userData;
|
||||||
|
m_rootWidget.__onWindowResized(evt);
|
||||||
|
}
|
||||||
|
else if (signal.ID == ostd::tBuiltinSignals::MouseMoved)
|
||||||
|
{
|
||||||
|
evt.mouse = &(ogfx::MouseEventData&)signal.userData;
|
||||||
|
m_rootWidget.__onMouseMoved(evt);
|
||||||
|
}
|
||||||
|
else if (signal.ID == ostd::tBuiltinSignals::MousePressed)
|
||||||
|
{
|
||||||
|
evt.mouse = &(ogfx::MouseEventData&)signal.userData;
|
||||||
|
m_rootWidget.__onMousePressed(evt);
|
||||||
|
}
|
||||||
|
else if (signal.ID == ostd::tBuiltinSignals::MouseReleased)
|
||||||
|
{
|
||||||
|
evt.mouse = &(ogfx::MouseEventData&)signal.userData;
|
||||||
|
m_rootWidget.__onMouseReleased(evt);
|
||||||
|
}
|
||||||
|
else if (signal.ID == ostd::tBuiltinSignals::KeyPressed)
|
||||||
|
{
|
||||||
|
evt.keyboard = &(ogfx::KeyEventData&)signal.userData;
|
||||||
|
m_rootWidget.__onKeyPressed(evt);
|
||||||
|
}
|
||||||
|
else if (signal.ID == ostd::tBuiltinSignals::KeyReleased)
|
||||||
|
{
|
||||||
|
evt.keyboard = &(ogfx::KeyEventData&)signal.userData;
|
||||||
|
m_rootWidget.__onKeyReleased(evt);
|
||||||
|
if (evt.keyboard->keyCode == SDLK_ESCAPE)
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
else if (signal.ID == ostd::tBuiltinSignals::TextEntered)
|
||||||
|
{
|
||||||
|
evt.keyboard = &(ogfx::KeyEventData&)signal.userData;
|
||||||
|
m_rootWidget.__onTextEntered(evt);
|
||||||
|
}
|
||||||
|
onSignal(signal);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::__on_event(SDL_Event& event)
|
||||||
|
{
|
||||||
onSDLEvent(event);
|
onSDLEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,10 @@
|
||||||
#include <ostd/utils/Time.hpp>
|
#include <ostd/utils/Time.hpp>
|
||||||
#include <ostd/io/IOHandlers.hpp>
|
#include <ostd/io/IOHandlers.hpp>
|
||||||
#include <ogfx/gui/Events.hpp>
|
#include <ogfx/gui/Events.hpp>
|
||||||
|
#include <ogfx/gui/Widgets.hpp>
|
||||||
#include <ogfx/render/BasicRenderer.hpp>
|
#include <ogfx/render/BasicRenderer.hpp>
|
||||||
#include <ogfx/gui/WindowOutputHandler.hpp>
|
#include <ogfx/gui/WindowOutputHandler.hpp>
|
||||||
|
#include <ogfx/gui/Themes.hpp>
|
||||||
|
|
||||||
namespace ogfx
|
namespace ogfx
|
||||||
{
|
{
|
||||||
|
|
@ -47,6 +49,7 @@ namespace ogfx
|
||||||
void setIcon(const ostd::String& iconFilePath);
|
void setIcon(const ostd::String& iconFilePath);
|
||||||
void setBlockingEventsRefreshFPS(uint32_t fps);
|
void setBlockingEventsRefreshFPS(uint32_t fps);
|
||||||
void requestRedraw(void);
|
void requestRedraw(void);
|
||||||
|
void handleSignal(ostd::tSignal& signal) override;
|
||||||
|
|
||||||
inline bool isInitialized(void) const { return m_initialized; }
|
inline bool isInitialized(void) const { return m_initialized; }
|
||||||
inline bool isRunning(void) const { return m_running; }
|
inline bool isRunning(void) const { return m_running; }
|
||||||
|
|
@ -74,6 +77,7 @@ namespace ogfx
|
||||||
inline virtual void __on_window_init(int32_t width, int32_t height, const ostd::String& title) { }
|
inline virtual void __on_window_init(int32_t width, int32_t height, const ostd::String& title) { }
|
||||||
inline virtual void __on_window_destroy(void) { }
|
inline virtual void __on_window_destroy(void) { }
|
||||||
inline virtual void __on_window_close(void) { }
|
inline virtual void __on_window_close(void) { }
|
||||||
|
inline virtual void __on_signal(ostd::tSignal& signal) { }
|
||||||
inline virtual void __main_loop(void) = 0;
|
inline virtual void __main_loop(void) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -106,6 +110,7 @@ namespace ogfx
|
||||||
public:
|
public:
|
||||||
inline static constexpr int32_t MaxBlockingEventsFPS { 240 };
|
inline static constexpr int32_t MaxBlockingEventsFPS { 240 };
|
||||||
inline static constexpr int32_t DefaultBlockingEventsFPS { 30 };
|
inline static constexpr int32_t DefaultBlockingEventsFPS { 30 };
|
||||||
|
inline static const gui::Theme DefaultTheme;
|
||||||
};
|
};
|
||||||
class GraphicsWindow : public WindowCore
|
class GraphicsWindow : public WindowCore
|
||||||
{
|
{
|
||||||
|
|
@ -121,6 +126,7 @@ namespace ogfx
|
||||||
inline virtual void onDestroy(void) { }
|
inline virtual void onDestroy(void) { }
|
||||||
inline virtual void onClose(void) { }
|
inline virtual void onClose(void) { }
|
||||||
inline virtual void onSDLEvent(SDL_Event& event) { }
|
inline virtual void onSDLEvent(SDL_Event& event) { }
|
||||||
|
inline virtual void onSignal(ostd::tSignal& signal) { }
|
||||||
|
|
||||||
inline int32_t getFPS(void) const { return m_fps; }
|
inline int32_t getFPS(void) const { return m_fps; }
|
||||||
|
|
||||||
|
|
@ -130,6 +136,7 @@ namespace ogfx
|
||||||
void __on_window_destroy(void) override;
|
void __on_window_destroy(void) override;
|
||||||
void __on_window_close(void) override;
|
void __on_window_close(void) override;
|
||||||
void __main_loop(void) override;
|
void __main_loop(void) override;
|
||||||
|
void __on_signal(ostd::tSignal& signal) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int32_t m_fps { 0 };
|
int32_t m_fps { 0 };
|
||||||
|
|
@ -147,12 +154,18 @@ namespace ogfx
|
||||||
public:
|
public:
|
||||||
inline Window(void) { }
|
inline Window(void) { }
|
||||||
inline Window(int32_t width, int32_t height, const ostd::String& title) { initialize(width, height, title); }
|
inline Window(int32_t width, int32_t height, const ostd::String& title) { initialize(width, height, title); }
|
||||||
|
void addWidget(Widget& widget);
|
||||||
|
|
||||||
inline virtual void onInitialize(void) { }
|
inline virtual void onInitialize(void) { }
|
||||||
inline virtual void onDestroy(void) { }
|
inline virtual void onDestroy(void) { }
|
||||||
inline virtual void onClose(void) { }
|
inline virtual void onClose(void) { }
|
||||||
inline virtual void onSDLEvent(SDL_Event& event) { }
|
inline virtual void onSDLEvent(SDL_Event& event) { }
|
||||||
inline virtual void onRedraw(BasicRenderer2D& gfx) { }
|
inline virtual void onRedraw(BasicRenderer2D& gfx) { }
|
||||||
|
inline virtual void onSignal(ostd::tSignal& signal) { }
|
||||||
|
|
||||||
|
inline const gui::Theme& theme(void) const { return *m_guiTheme; }
|
||||||
|
void setTheme(const gui::Theme& theme);
|
||||||
|
inline void loadDefaultTHeme(void) { setTheme(DefaultTheme); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void __on_window_init(int32_t width, int32_t height, const ostd::String& title) override;
|
void __on_window_init(int32_t width, int32_t height, const ostd::String& title) override;
|
||||||
|
|
@ -160,9 +173,14 @@ namespace ogfx
|
||||||
void __on_window_destroy(void) override;
|
void __on_window_destroy(void) override;
|
||||||
void __on_window_close(void) override;
|
void __on_window_close(void) override;
|
||||||
void __main_loop(void) override;
|
void __main_loop(void) override;
|
||||||
|
void __on_signal(ostd::tSignal& signal) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BasicRenderer2D m_gfx;
|
BasicRenderer2D m_gfx;
|
||||||
|
widgets::RootWidget m_rootWidget { *this };
|
||||||
|
const gui::Theme* m_guiTheme { nullptr };
|
||||||
|
|
||||||
|
inline static const gui::Theme DefaultTheme;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,5 +78,62 @@ namespace ostd
|
||||||
uint8_t g;
|
uint8_t g;
|
||||||
uint8_t b;
|
uint8_t b;
|
||||||
uint8_t a;
|
uint8_t a;
|
||||||
|
|
||||||
|
public:
|
||||||
|
};
|
||||||
|
struct Colors
|
||||||
|
{
|
||||||
|
inline static const Color Transparent { 0, 0, 0, 0 };
|
||||||
|
inline static const Color Black { 0, 0, 0, 255 };
|
||||||
|
inline static const Color White { 255, 255, 255, 255 };
|
||||||
|
inline static const Color Gray { 128, 128, 128, 255 };
|
||||||
|
inline static const Color LightGray { 192, 192, 192, 255 };
|
||||||
|
inline static const Color DarkGray { 64, 64, 64, 255 };
|
||||||
|
|
||||||
|
inline static const Color Red { 255, 0, 0, 255 };
|
||||||
|
inline static const Color Green { 0, 255, 0, 255 };
|
||||||
|
inline static const Color Blue { 0, 0, 255, 255 };
|
||||||
|
|
||||||
|
inline static const Color Yellow { 255, 255, 0, 255 };
|
||||||
|
inline static const Color Cyan { 0, 255, 255, 255 };
|
||||||
|
inline static const Color Magenta { 255, 0, 255, 255 };
|
||||||
|
|
||||||
|
inline static const Color Orange { 255, 165, 0, 255 };
|
||||||
|
inline static const Color Purple { 128, 0, 128, 255 };
|
||||||
|
inline static const Color Brown { 139, 69, 19, 255 };
|
||||||
|
inline static const Color Pink { 255, 192, 203, 255 };
|
||||||
|
inline static const Color Lime { 50, 205, 50, 255 };
|
||||||
|
inline static const Color Olive { 128, 128, 0, 255 };
|
||||||
|
inline static const Color Teal { 0, 128, 128, 255 };
|
||||||
|
inline static const Color Navy { 0, 0, 128, 255 };
|
||||||
|
inline static const Color Maroon { 128, 0, 0, 255 };
|
||||||
|
inline static const Color Indigo { 75, 0, 130, 255 };
|
||||||
|
inline static const Color Gold { 255, 215, 0, 255 };
|
||||||
|
inline static const Color Silver { 192, 192, 192, 255 };
|
||||||
|
inline static const Color Beige { 245, 245, 220, 255 };
|
||||||
|
inline static const Color Coral { 255, 127, 80, 255 };
|
||||||
|
inline static const Color Salmon { 250, 128, 114, 255 };
|
||||||
|
inline static const Color Chocolate { 210, 105, 30, 255 };
|
||||||
|
inline static const Color Khaki { 240, 230, 140, 255 };
|
||||||
|
inline static const Color Lavender { 230, 230, 250, 255 };
|
||||||
|
inline static const Color Mint { 189, 252, 201, 255 };
|
||||||
|
inline static const Color SkyBlue { 135, 206, 235, 255 };
|
||||||
|
inline static const Color RoyalBlue { 65, 105, 225, 255 };
|
||||||
|
inline static const Color DeepSkyBlue { 0, 191, 255, 255 };
|
||||||
|
inline static const Color Turquoise { 64, 224, 208, 255 };
|
||||||
|
inline static const Color Aquamarine { 127, 255, 212, 255 };
|
||||||
|
inline static const Color ForestGreen { 34, 139, 34, 255 };
|
||||||
|
inline static const Color SeaGreen { 46, 139, 87, 255 };
|
||||||
|
inline static const Color SpringGreen { 0, 255, 127, 255 };
|
||||||
|
inline static const Color Firebrick { 178, 34, 34, 255 };
|
||||||
|
inline static const Color Crimson { 220, 20, 60, 255 };
|
||||||
|
inline static const Color Tomato { 255, 99, 71, 255 };
|
||||||
|
inline static const Color DarkOrange { 255, 140, 0, 255 };
|
||||||
|
inline static const Color DarkRed { 139, 0, 0, 255 };
|
||||||
|
inline static const Color DarkBlue { 0, 0, 139, 255 };
|
||||||
|
inline static const Color DarkGreen { 0, 100, 0, 255 };
|
||||||
|
inline static const Color DarkCyan { 0, 139, 139, 255 };
|
||||||
|
inline static const Color DarkMagenta { 139, 0, 139, 255 };
|
||||||
|
inline static const Color DarkYellow { 204, 204, 0, 255 };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -345,6 +345,11 @@ namespace ostd
|
||||||
inline virtual Vec2 bottomLeft(void) const { return Vec2(getx(), gety() + geth()); }
|
inline virtual Vec2 bottomLeft(void) const { return Vec2(getx(), gety() + geth()); }
|
||||||
inline virtual Vec2 bottomRight(void) const { return Vec2(getx() + getw(), gety() + geth()); }
|
inline virtual Vec2 bottomRight(void) const { return Vec2(getx() + getw(), gety() + geth()); }
|
||||||
|
|
||||||
|
inline virtual float left(void) const { return getx(); }
|
||||||
|
inline virtual float right(void) const { return getw(); }
|
||||||
|
inline virtual float top(void) const { return gety(); }
|
||||||
|
inline virtual float bottom(void) const { return geth(); }
|
||||||
|
|
||||||
inline virtual bool intersects(Rectangle rect, bool includeBounds = true) const
|
inline virtual bool intersects(Rectangle rect, bool includeBounds = true) const
|
||||||
{
|
{
|
||||||
if (includeBounds)
|
if (includeBounds)
|
||||||
|
|
@ -376,9 +381,9 @@ namespace ostd
|
||||||
inline virtual bool contains(Vec2 p, bool includeBounds = false) const
|
inline virtual bool contains(Vec2 p, bool includeBounds = false) const
|
||||||
{
|
{
|
||||||
if (includeBounds)
|
if (includeBounds)
|
||||||
return p.x >= x && p.y >= y & p.x <= x + w && p.y <= y + h;
|
return p.x >= x && p.y >= y && p.x <= x + w && p.y <= y + h;
|
||||||
else
|
else
|
||||||
return p.x > x && p.y > y & p.x < x + w && p.y < y + h;
|
return p.x > x && p.y > y && p.x < x + w && p.y < y + h;
|
||||||
}
|
}
|
||||||
inline virtual bool contains(float xx, float yy, bool includeBounds = false) const { return contains({ xx, yy }); }
|
inline virtual bool contains(float xx, float yy, bool includeBounds = false) const { return contains({ xx, yy }); }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,10 @@ namespace ostd
|
||||||
SignalHandler::m_windowResizedRecievers.reserve(SignalHandler::__SIGNAL_BUFFER_START_SIZE);
|
SignalHandler::m_windowResizedRecievers.reserve(SignalHandler::__SIGNAL_BUFFER_START_SIZE);
|
||||||
SignalHandler::m_windowClosedRecievers.clear();
|
SignalHandler::m_windowClosedRecievers.clear();
|
||||||
SignalHandler::m_windowClosedRecievers.reserve(SignalHandler::__SIGNAL_BUFFER_START_SIZE);
|
SignalHandler::m_windowClosedRecievers.reserve(SignalHandler::__SIGNAL_BUFFER_START_SIZE);
|
||||||
|
SignalHandler::m_windowFocusedRecievers.clear();
|
||||||
|
SignalHandler::m_windowFocusedRecievers.reserve(SignalHandler::__SIGNAL_BUFFER_START_SIZE);
|
||||||
|
SignalHandler::m_windowLostFocusRecievers.clear();
|
||||||
|
SignalHandler::m_windowLostFocusRecievers.reserve(SignalHandler::__SIGNAL_BUFFER_START_SIZE);
|
||||||
SignalHandler::m_delegatedSignals.clear();
|
SignalHandler::m_delegatedSignals.clear();
|
||||||
SignalHandler::m_delegatedSignals.reserve(SignalHandler::__DELEGATED_SIGNALS_BUFFER_START_SIZE);
|
SignalHandler::m_delegatedSignals.reserve(SignalHandler::__DELEGATED_SIGNALS_BUFFER_START_SIZE);
|
||||||
SignalHandler::m_onGuiEventRecievers.clear();
|
SignalHandler::m_onGuiEventRecievers.clear();
|
||||||
|
|
@ -71,6 +75,10 @@ namespace ostd
|
||||||
sig_list = &m_windowResizedRecievers;
|
sig_list = &m_windowResizedRecievers;
|
||||||
else if (signal_id == tBuiltinSignals::WindowClosed)
|
else if (signal_id == tBuiltinSignals::WindowClosed)
|
||||||
sig_list = &m_windowClosedRecievers;
|
sig_list = &m_windowClosedRecievers;
|
||||||
|
else if (signal_id == tBuiltinSignals::WindowLostFocus)
|
||||||
|
sig_list = &m_windowLostFocusRecievers;
|
||||||
|
else if (signal_id == tBuiltinSignals::WindowFocused)
|
||||||
|
sig_list = &m_windowFocusedRecievers;
|
||||||
else if (signal_id == tBuiltinSignals::OnGuiEvent)
|
else if (signal_id == tBuiltinSignals::OnGuiEvent)
|
||||||
sig_list = &m_onGuiEventRecievers;
|
sig_list = &m_onGuiEventRecievers;
|
||||||
else if (signal_id == tBuiltinSignals::BeforeSDLShutdown)
|
else if (signal_id == tBuiltinSignals::BeforeSDLShutdown)
|
||||||
|
|
@ -112,6 +120,10 @@ namespace ostd
|
||||||
m_windowResizedRecievers.push_back({ &object, signal_id });
|
m_windowResizedRecievers.push_back({ &object, signal_id });
|
||||||
else if (signal_id == tBuiltinSignals::WindowClosed)
|
else if (signal_id == tBuiltinSignals::WindowClosed)
|
||||||
m_windowClosedRecievers.push_back({ &object, signal_id });
|
m_windowClosedRecievers.push_back({ &object, signal_id });
|
||||||
|
else if (signal_id == tBuiltinSignals::WindowLostFocus)
|
||||||
|
m_windowLostFocusRecievers.push_back({ &object, signal_id });
|
||||||
|
else if (signal_id == tBuiltinSignals::WindowFocused)
|
||||||
|
m_windowFocusedRecievers.push_back({ &object, signal_id });
|
||||||
else if (signal_id == tBuiltinSignals::OnGuiEvent)
|
else if (signal_id == tBuiltinSignals::OnGuiEvent)
|
||||||
m_onGuiEventRecievers.push_back({ &object, signal_id });
|
m_onGuiEventRecievers.push_back({ &object, signal_id });
|
||||||
else if (signal_id == tBuiltinSignals::BeforeSDLShutdown)
|
else if (signal_id == tBuiltinSignals::BeforeSDLShutdown)
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,8 @@ namespace ostd
|
||||||
|
|
||||||
inline static constexpr uint32_t WindowResized = 0x1001;
|
inline static constexpr uint32_t WindowResized = 0x1001;
|
||||||
inline static constexpr uint32_t WindowClosed = 0x1002;
|
inline static constexpr uint32_t WindowClosed = 0x1002;
|
||||||
|
inline static constexpr uint32_t WindowFocused = 0x1003;
|
||||||
|
inline static constexpr uint32_t WindowLostFocus = 0x1004;
|
||||||
/*********************/
|
/*********************/
|
||||||
|
|
||||||
inline static constexpr uint32_t CustomSignalBase = 0xFF0000;
|
inline static constexpr uint32_t CustomSignalBase = 0xFF0000;
|
||||||
|
|
@ -107,6 +109,8 @@ namespace ostd
|
||||||
inline static std::vector<tSignalObjPair> m_textEnteredRecievers;
|
inline static std::vector<tSignalObjPair> m_textEnteredRecievers;
|
||||||
inline static std::vector<tSignalObjPair> m_windowResizedRecievers;
|
inline static std::vector<tSignalObjPair> m_windowResizedRecievers;
|
||||||
inline static std::vector<tSignalObjPair> m_windowClosedRecievers;
|
inline static std::vector<tSignalObjPair> m_windowClosedRecievers;
|
||||||
|
inline static std::vector<tSignalObjPair> m_windowFocusedRecievers;
|
||||||
|
inline static std::vector<tSignalObjPair> m_windowLostFocusRecievers;
|
||||||
inline static std::vector<tSignalObjPair> m_onGuiEventRecievers;
|
inline static std::vector<tSignalObjPair> m_onGuiEventRecievers;
|
||||||
inline static std::vector<tSignalObjPair> m_beforeSDLShutdownRecievers;
|
inline static std::vector<tSignalObjPair> m_beforeSDLShutdownRecievers;
|
||||||
/************************************/
|
/************************************/
|
||||||
|
|
|
||||||
|
|
@ -48,9 +48,25 @@ class Window : public ogfx::gui::Window
|
||||||
inline Window(void) { }
|
inline Window(void) { }
|
||||||
inline void onInitialize(void) override
|
inline void onInitialize(void) override
|
||||||
{
|
{
|
||||||
|
m_label1.setPosition(100, 200);
|
||||||
|
m_label1.setText("Hello World!");
|
||||||
|
m_label1.setMouseMovedCallback([&](const ogfx::gui::Event& event) -> void {
|
||||||
|
m_label1.applyThemeValue(m_theme, "label.backgroundColor", ostd::Colors::DarkBlue, false);
|
||||||
|
});
|
||||||
|
addWidget(m_label1);
|
||||||
|
|
||||||
|
m_label2.setPosition(100, 400);
|
||||||
|
m_label2.setText("Ciccia Bella!");
|
||||||
|
addWidget(m_label2);
|
||||||
|
|
||||||
|
m_theme.set("label.textColor", ostd::Colors::White);
|
||||||
|
m_theme.set("label.backgroundColor", ostd::Colors::DarkRed);
|
||||||
|
m_theme.set("label.showBackground", true);
|
||||||
|
m_theme.set("label.borderRadius", 0);
|
||||||
|
setTheme(m_theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void handleSignal(ostd::tSignal& signal) override
|
inline void onSignal(ostd::tSignal& signal) override
|
||||||
{
|
{
|
||||||
if (signal.ID == ostd::tBuiltinSignals::KeyReleased)
|
if (signal.ID == ostd::tBuiltinSignals::KeyReleased)
|
||||||
{
|
{
|
||||||
|
|
@ -62,10 +78,13 @@ class Window : public ogfx::gui::Window
|
||||||
|
|
||||||
void onRedraw(ogfx::BasicRenderer2D& gfx) override
|
void onRedraw(ogfx::BasicRenderer2D& gfx) override
|
||||||
{
|
{
|
||||||
wout().fg(ostd::Color { 255, 0, 0 }).p("Hello ").fg(ostd::Color { 0, 0, 255 }).p("World");
|
// wout().fg(ostd::Color { 255, 0, 0 }).p("Hello ").fg(ostd::Color { 0, 0, 255 }).p("World");
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
ogfx::gui::widgets::Label m_label1 { *this };
|
||||||
|
ogfx::gui::widgets::Label m_label2 { *this };
|
||||||
|
ogfx::gui::Theme m_theme = ogfx::gui::Theme();
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue