Added drag and drop functionality for Widgets
This commit is contained in:
parent
260c7054bc
commit
d4b4df1e51
17 changed files with 630 additions and 369 deletions
1
.clangd
1
.clangd
|
|
@ -1,3 +1,2 @@
|
|||
CompileFlags:
|
||||
CompilationDatabase: bin
|
||||
Add: ["--target=x86_64-w64-mingw32"]
|
||||
|
|
@ -89,11 +89,13 @@ list(APPEND OGFX_SOURCE_FILES
|
|||
${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/WindowOutputHandler.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/WidgetManager.cpp
|
||||
|
||||
# gui/widgets
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/widgets/Widget.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/widgets/Containers.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/widgets/Label.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/widgets/RootWidget.cpp
|
||||
|
||||
# render
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/render/BasicRenderer.cpp
|
||||
|
|
|
|||
|
|
@ -42,11 +42,6 @@ window.backgroundColor = Color(rgba(120, 120, 120, 255))
|
|||
borderColor = Color(#208080FF)
|
||||
}
|
||||
|
||||
|
||||
% (@testLabel2 label:pressed [mouseButton=left or mouseButton=right]) {
|
||||
% ...
|
||||
|
||||
|
||||
(@testLabel2 label:pressed) {
|
||||
showBackground = true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ Add theme caching
|
|||
Implement mouse scroll callback
|
||||
Implement a way to determine on what widget (in the hierarchy chain) and event must stop
|
||||
Implement margin for widgets
|
||||
Implement conditional statements for stylesheet rules
|
||||
|
||||
|
||||
Implement following widgets:
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
2049
|
||||
2050
|
||||
|
|
|
|||
|
|
@ -78,12 +78,28 @@ namespace ogfx
|
|||
eKeyEvent eventType;
|
||||
WindowCore& parentWindow;
|
||||
};
|
||||
class DropEventData : public ostd::BaseObject
|
||||
{
|
||||
public: enum class eDropType { None = 0, File, Text, InApp };
|
||||
public:
|
||||
inline DropEventData(WindowCore& parent, eDropType type) : parentWindow(parent), dropType(type)
|
||||
{
|
||||
setTypeName("ogfx::DropEventData");
|
||||
validate();
|
||||
}
|
||||
|
||||
public:
|
||||
eDropType dropType;
|
||||
WindowCore& parentWindow;
|
||||
ostd::String textOrFilePath { "" };
|
||||
ostd::BaseObject* userObject { nullptr };
|
||||
};
|
||||
namespace gui
|
||||
{
|
||||
class Event
|
||||
{
|
||||
public:
|
||||
inline Event(WindowCore& _window) : window(_window) { }
|
||||
inline Event(WindowCore& _window) : window(_window), drop(window, DropEventData::eDropType::None) { }
|
||||
inline void handle(void) { m_handled = true; }
|
||||
inline bool isHandled(void) const { return m_handled; }
|
||||
|
||||
|
|
@ -92,6 +108,8 @@ namespace ogfx
|
|||
WindowResizedData* windowResized { nullptr };
|
||||
MouseEventData* mouse { nullptr };
|
||||
KeyEventData* keyboard { nullptr };
|
||||
DropEventData drop;
|
||||
uint32_t __original_signal_id { 0 };
|
||||
|
||||
private:
|
||||
bool m_handled { false };
|
||||
|
|
|
|||
317
src/ogfx/gui/WidgetManager.cpp
Normal file
317
src/ogfx/gui/WidgetManager.cpp
Normal file
|
|
@ -0,0 +1,317 @@
|
|||
/*
|
||||
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 "WidgetManager.hpp"
|
||||
#include "widgets/Widget.hpp"
|
||||
#include "../render/BasicRenderer.hpp"
|
||||
#include "../utils/Keycodes.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));
|
||||
w->setThemeQualifier("focused", false);
|
||||
}
|
||||
else
|
||||
w->m_focused = false;
|
||||
}
|
||||
widget.m_focused = true;
|
||||
widget.onFocusGained(Event(m_window));
|
||||
widget.setThemeQualifier("focused", true);
|
||||
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;
|
||||
gfx.pushClippingRect({ w->getGlobalPosition(), w->getSize() }, true);
|
||||
w->__draw(gfx);
|
||||
gfx.popClippingRect();
|
||||
}
|
||||
}
|
||||
|
||||
void WidgetManager::update(void)
|
||||
{
|
||||
for (auto& w : m_widgetList)
|
||||
{
|
||||
if (w == nullptr) continue;
|
||||
if (w->isInvalid()) continue;
|
||||
w->__update();
|
||||
}
|
||||
}
|
||||
|
||||
void WidgetManager::onThemeApplied(const ostd::Stylesheet& 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() || w->m_stopEvents)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void WidgetManager::onMouseReleased(const Event& event)
|
||||
{
|
||||
if (m_mousePressedOnWidget != nullptr)
|
||||
{
|
||||
event.mouse->mousePressedOnWidget = m_mousePressedOnWidget;
|
||||
m_mousePressedOnWidget->__onMouseReleased(event);
|
||||
// processDragAndDrop(m_mousePressedOnWidget, 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 == m_mousePressedOnWidget) continue;
|
||||
event.mouse->mousePressedOnWidget = m_mousePressedOnWidget;
|
||||
w->__onMouseReleased(event);
|
||||
processDragAndDrop(w, event);
|
||||
// requestFocus(*w);
|
||||
if (w->isMouseInside() && w->m_stopEvents)
|
||||
break;
|
||||
}
|
||||
m_mousePressedOnWidget = nullptr;
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
if (w->m_mouseInside)
|
||||
{
|
||||
w->m_mouseInside = false;
|
||||
w->__onMouseExited(event);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!w->m_mouseInside)
|
||||
{
|
||||
w->m_mouseInside = true;
|
||||
w->__onMouseEntered(event);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (w->m_pressedButton != ogfx::MouseEventData::eButton::None)
|
||||
w->__onMouseDragged(event);
|
||||
else
|
||||
w->__onMouseMoved(event);
|
||||
}
|
||||
if (event.isHandled() || w->m_stopEvents)
|
||||
{
|
||||
bool mouseOut = false;
|
||||
for (int32_t j = i - 1; j >= 0; j--)
|
||||
{
|
||||
Widget* ww = m_widgetList[j];
|
||||
if (ww->m_mouseInside)
|
||||
{
|
||||
ww->m_mouseInside = false;
|
||||
ww->__onMouseExited(event);
|
||||
}
|
||||
}
|
||||
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 == KeyCode::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;
|
||||
}
|
||||
}
|
||||
|
||||
void WidgetManager::processDragAndDrop(Widget* widget, const Event& event)
|
||||
{
|
||||
if (widget == nullptr) return;
|
||||
if (!widget->isDragAndDropEnabled()) return;
|
||||
if (!widget->isMouseInside()) return;
|
||||
if (Widget::s_dragAndDropData != nullptr)
|
||||
{
|
||||
widget->__onDragAndDrop(event);
|
||||
Widget::clearDragAndDropData();
|
||||
}
|
||||
|
||||
auto& const_cast_event = const_cast<Event&>(event);
|
||||
// if (event.__original_signal_id == ostd::BuiltinSignals::TextDragAndDropped)
|
||||
}
|
||||
}
|
||||
}
|
||||
76
src/ogfx/gui/WidgetManager.hpp
Normal file
76
src/ogfx/gui/WidgetManager.hpp
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
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/string/String.hpp>
|
||||
|
||||
namespace ostd
|
||||
{
|
||||
class Stylesheet;
|
||||
}
|
||||
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 ostd::Stylesheet& 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:
|
||||
void processDragAndDrop(Widget* widget, const Event& event);
|
||||
|
||||
private:
|
||||
WindowCore& m_window;
|
||||
Widget& m_owner;
|
||||
std::vector<Widget*> m_widgetList;
|
||||
Widget* m_focused { nullptr };
|
||||
bool m_tabNavigationEnabled { true };
|
||||
Widget* m_mousePressedOnWidget { nullptr };
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@
|
|||
#include "Window.hpp"
|
||||
#include "../../ostd/utils/Time.hpp"
|
||||
#include "utils/Keycodes.hpp"
|
||||
#include <SDL3/SDL_events.h>
|
||||
|
||||
namespace ogfx
|
||||
{
|
||||
|
|
@ -336,6 +337,18 @@ namespace ogfx
|
|||
{
|
||||
close();
|
||||
}
|
||||
else if (event.type == SDL_EVENT_DROP_FILE)
|
||||
{
|
||||
DropEventData ded(*this, DropEventData::eDropType::File);
|
||||
ded.textOrFilePath = event.drop.data;
|
||||
ostd::SignalHandler::emitSignal(ostd::BuiltinSignals::FileDragAndDropped, ostd::Signal::Priority::RealTime, ded);
|
||||
}
|
||||
else if (event.type == SDL_EVENT_DROP_TEXT)
|
||||
{
|
||||
DropEventData ded(*this, DropEventData::eDropType::Text);
|
||||
ded.textOrFilePath = event.drop.data;
|
||||
ostd::SignalHandler::emitSignal(ostd::BuiltinSignals::FileDragAndDropped, ostd::Signal::Priority::RealTime, ded);
|
||||
}
|
||||
else if (event.type == SDL_EVENT_WINDOW_FOCUS_GAINED)
|
||||
{
|
||||
ostd::SignalHandler::emitSignal(ostd::BuiltinSignals::WindowFocused, ostd::Signal::Priority::RealTime, *this);
|
||||
|
|
@ -497,46 +510,74 @@ namespace ogfx
|
|||
void Window::__on_signal(ostd::Signal& signal)
|
||||
{
|
||||
Event evt(*this);
|
||||
evt.__original_signal_id = ostd::BuiltinSignals::NoSignal;
|
||||
if (signal.ID == ostd::BuiltinSignals::WindowClosed)
|
||||
{
|
||||
evt.__original_signal_id = ostd::BuiltinSignals::WindowClosed;
|
||||
m_rootWidget.__onWindowClosed(evt);
|
||||
}
|
||||
else if (signal.ID == ostd::BuiltinSignals::WindowFocused)
|
||||
{
|
||||
m_rootWidget.__onWIndowFocused(evt);
|
||||
evt.__original_signal_id = ostd::BuiltinSignals::WindowFocused;
|
||||
m_rootWidget.__onWindowFocused(evt);
|
||||
}
|
||||
else if (signal.ID == ostd::BuiltinSignals::WindowLostFocus)
|
||||
{
|
||||
evt.__original_signal_id = ostd::BuiltinSignals::WindowLostFocus;
|
||||
m_rootWidget.__onWindowFocusLost(evt);
|
||||
}
|
||||
else if (signal.ID == ostd::BuiltinSignals::FileDragAndDropped)
|
||||
{
|
||||
auto& ud = (ogfx::DropEventData&)signal.userData;
|
||||
evt.drop.dropType = ud.dropType;
|
||||
evt.drop.userObject = ud.userObject;
|
||||
evt.drop.textOrFilePath = ud.textOrFilePath;
|
||||
evt.__original_signal_id = ostd::BuiltinSignals::FileDragAndDropped;
|
||||
m_rootWidget.__onDragAndDrop(evt);
|
||||
}
|
||||
else if (signal.ID == ostd::BuiltinSignals::TextDragAndDropped)
|
||||
{
|
||||
auto& ud = (ogfx::DropEventData&)signal.userData;
|
||||
evt.drop.dropType = ud.dropType;
|
||||
evt.drop.userObject = ud.userObject;
|
||||
evt.drop.textOrFilePath = ud.textOrFilePath;
|
||||
evt.__original_signal_id = ostd::BuiltinSignals::TextDragAndDropped;
|
||||
m_rootWidget.__onDragAndDrop(evt);
|
||||
}
|
||||
else if (signal.ID == ostd::BuiltinSignals::WindowResized)
|
||||
{
|
||||
evt.windowResized = &(ogfx::WindowResizedData&)signal.userData;
|
||||
evt.__original_signal_id = ostd::BuiltinSignals::WindowResized;
|
||||
m_rootWidget.__onWindowResized(evt);
|
||||
}
|
||||
else if (signal.ID == ostd::BuiltinSignals::MouseMoved)
|
||||
{
|
||||
evt.mouse = &(ogfx::MouseEventData&)signal.userData;
|
||||
evt.__original_signal_id = ostd::BuiltinSignals::MouseMoved;
|
||||
m_rootWidget.__onMouseMoved(evt);
|
||||
}
|
||||
else if (signal.ID == ostd::BuiltinSignals::MousePressed)
|
||||
{
|
||||
evt.mouse = &(ogfx::MouseEventData&)signal.userData;
|
||||
evt.__original_signal_id = ostd::BuiltinSignals::MousePressed;
|
||||
m_rootWidget.__onMousePressed(evt);
|
||||
}
|
||||
else if (signal.ID == ostd::BuiltinSignals::MouseReleased)
|
||||
{
|
||||
evt.mouse = &(ogfx::MouseEventData&)signal.userData;
|
||||
evt.__original_signal_id = ostd::BuiltinSignals::MouseReleased;
|
||||
m_rootWidget.__onMouseReleased(evt);
|
||||
}
|
||||
else if (signal.ID == ostd::BuiltinSignals::KeyPressed)
|
||||
{
|
||||
evt.keyboard = &(ogfx::KeyEventData&)signal.userData;
|
||||
evt.__original_signal_id = ostd::BuiltinSignals::KeyPressed;
|
||||
m_rootWidget.__onKeyPressed(evt);
|
||||
}
|
||||
else if (signal.ID == ostd::BuiltinSignals::KeyReleased)
|
||||
{
|
||||
evt.keyboard = &(ogfx::KeyEventData&)signal.userData;
|
||||
evt.__original_signal_id = ostd::BuiltinSignals::KeyReleased;
|
||||
m_rootWidget.__onKeyReleased(evt);
|
||||
if (evt.keyboard->keyCode == KeyCode::Escape)
|
||||
close();
|
||||
|
|
@ -544,6 +585,7 @@ namespace ogfx
|
|||
else if (signal.ID == ostd::BuiltinSignals::TextEntered)
|
||||
{
|
||||
evt.keyboard = &(ogfx::KeyEventData&)signal.userData;
|
||||
evt.__original_signal_id = ostd::BuiltinSignals::TextEntered;
|
||||
m_rootWidget.__onTextEntered(evt);
|
||||
}
|
||||
onSignal(signal);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <ostd/io/IOHandlers.hpp>
|
||||
#include <ogfx/gui/Events.hpp>
|
||||
#include <ogfx/gui/widgets/Widget.hpp>
|
||||
#include <ogfx/gui/widgets/RootWidget.hpp>
|
||||
#include <ogfx/render/BasicRenderer.hpp>
|
||||
#include <ogfx/gui/WindowOutputHandler.hpp>
|
||||
|
||||
|
|
|
|||
55
src/ogfx/gui/widgets/RootWidget.cpp
Normal file
55
src/ogfx/gui/widgets/RootWidget.cpp
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
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 "RootWidget.hpp"
|
||||
#include "../../render/BasicRenderer.hpp"
|
||||
#include "../Window.hpp"
|
||||
|
||||
namespace ogfx
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace widgets
|
||||
{
|
||||
RootWidget::RootWidget(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window)
|
||||
{
|
||||
disableDrawBox();
|
||||
m_rootChild = true;
|
||||
setSize(static_cast<float>(window.getWindowWidth()), static_cast<float>(window.getWindowHeight()));
|
||||
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 ostd::Stylesheet& theme)
|
||||
{
|
||||
m_color = getThemeValue<ostd::Color>(theme, "window.backgroundColor", getWindow().getClearColor());
|
||||
}
|
||||
|
||||
void RootWidget::onDraw(ogfx::BasicRenderer2D& gfx)
|
||||
{
|
||||
gfx.fillRect({ 0, 0, static_cast<float>(getWindow().getWindowWidth()), static_cast<float>(getWindow().getWindowHeight()) }, m_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
44
src/ogfx/gui/widgets/RootWidget.hpp
Normal file
44
src/ogfx/gui/widgets/RootWidget.hpp
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
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 <ogfx/gui/widgets/Widget.hpp>
|
||||
|
||||
namespace ogfx
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace widgets
|
||||
{
|
||||
class RootWidget : public Widget
|
||||
{
|
||||
public:
|
||||
RootWidget(WindowCore& window);
|
||||
void onWindowResized(const Event& event) override;
|
||||
void applyTheme(const ostd::Stylesheet& theme) override;
|
||||
void onDraw(ogfx::BasicRenderer2D& gfx) override;
|
||||
|
||||
private:
|
||||
ostd::Color m_color { ostd::Colors::Transparent };
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +21,6 @@
|
|||
#include "Widget.hpp"
|
||||
#include "gui/Events.hpp"
|
||||
#include "io/Memory.hpp"
|
||||
#include "utils/Keycodes.hpp"
|
||||
#include "../..//render/BasicRenderer.hpp"
|
||||
#include "../Window.hpp"
|
||||
|
||||
|
|
@ -29,273 +28,6 @@ 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));
|
||||
w->setThemeQualifier("focused", true);
|
||||
}
|
||||
else
|
||||
w->m_focused = false;
|
||||
}
|
||||
widget.m_focused = true;
|
||||
widget.onFocusGained(Event(m_window));
|
||||
widget.setThemeQualifier("focused", true);
|
||||
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;
|
||||
gfx.pushClippingRect({ w->getGlobalPosition(), w->getSize() }, true);
|
||||
w->__draw(gfx);
|
||||
gfx.popClippingRect();
|
||||
}
|
||||
}
|
||||
|
||||
void WidgetManager::update(void)
|
||||
{
|
||||
for (auto& w : m_widgetList)
|
||||
{
|
||||
if (w == nullptr) continue;
|
||||
if (w->isInvalid()) continue;
|
||||
w->__update();
|
||||
}
|
||||
}
|
||||
|
||||
void WidgetManager::onThemeApplied(const ostd::Stylesheet& 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() || w->m_stopEvents)
|
||||
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))
|
||||
{
|
||||
if (w->m_mouseInside)
|
||||
{
|
||||
w->m_mouseInside = false;
|
||||
w->__onMouseExited(event);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!w->m_mouseInside)
|
||||
{
|
||||
w->m_mouseInside = true;
|
||||
w->__onMouseEntered(event);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (w->m_pressedButton != ogfx::MouseEventData::eButton::None)
|
||||
w->__onMouseDragged(event);
|
||||
else
|
||||
w->__onMouseMoved(event);
|
||||
}
|
||||
if (event.isHandled() || w->m_stopEvents)
|
||||
{
|
||||
bool mouseOut = false;
|
||||
for (int32_t j = i - 1; j >= 0; j--)
|
||||
{
|
||||
Widget* ww = m_widgetList[j];
|
||||
if (ww->m_mouseInside)
|
||||
{
|
||||
ww->m_mouseInside = false;
|
||||
ww->__onMouseExited(event);
|
||||
}
|
||||
}
|
||||
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 == KeyCode::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;
|
||||
|
|
@ -403,7 +135,7 @@ namespace ogfx
|
|||
}
|
||||
}
|
||||
|
||||
bool Widget::getThemeQualifier(const ostd::String& qualifier)
|
||||
bool Widget::getThemeQualifier(const ostd::String& qualifier) const
|
||||
{
|
||||
for (auto& [name, state] : m_qualifierList)
|
||||
{
|
||||
|
|
@ -473,6 +205,18 @@ namespace ogfx
|
|||
}
|
||||
}
|
||||
|
||||
void Widget::__onDragAndDrop(const Event& event)
|
||||
{
|
||||
// if (hasChildren())
|
||||
// m_widgets.onMouseReleased(event);
|
||||
if (!event.isHandled())
|
||||
{
|
||||
if (callback_onDragAndDrop)
|
||||
callback_onDragAndDrop(event);
|
||||
onDragAndDrop(event);
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::__onMouseMoved(const Event& event)
|
||||
{
|
||||
if (hasChildren())
|
||||
|
|
@ -574,7 +318,7 @@ namespace ogfx
|
|||
}
|
||||
}
|
||||
|
||||
void Widget::__onWIndowFocused(const Event& event)
|
||||
void Widget::__onWindowFocused(const Event& event)
|
||||
{
|
||||
if (hasChildren())
|
||||
m_widgets.onWindowFocused(event);
|
||||
|
|
@ -604,33 +348,5 @@ namespace ogfx
|
|||
m_widgets.onThemeApplied(theme);
|
||||
applyTheme(theme);
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace widgets
|
||||
{
|
||||
RootWidget::RootWidget(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window)
|
||||
{
|
||||
disableDrawBox();
|
||||
m_rootChild = true;
|
||||
setSize(static_cast<float>(window.getWindowWidth()), static_cast<float>(window.getWindowHeight()));
|
||||
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 ostd::Stylesheet& theme)
|
||||
{
|
||||
m_color = getThemeValue<ostd::Color>(theme, "window.backgroundColor", getWindow().getClearColor());
|
||||
}
|
||||
|
||||
void RootWidget::onDraw(ogfx::BasicRenderer2D& gfx)
|
||||
{
|
||||
gfx.fillRect({ 0, 0, static_cast<float>(getWindow().getWindowWidth()), static_cast<float>(getWindow().getWindowHeight()) }, m_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,56 +21,16 @@
|
|||
#pragma once
|
||||
|
||||
#include <ogfx/gui/Events.hpp>
|
||||
#include <ogfx/gui/WidgetManager.hpp>
|
||||
#include <ostd/data/BaseObject.hpp>
|
||||
#include <ostd/math/Geometry.hpp>
|
||||
#include <ostd/data/Color.hpp>
|
||||
#include <ostd/io/Stylesheet.hpp>
|
||||
#include <ostd/utils/Time.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 ostd::Stylesheet& 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
|
||||
{
|
||||
private: struct ThemeOverride
|
||||
|
|
@ -95,7 +55,7 @@ namespace ogfx
|
|||
void addThemeOverride(const ostd::String& fullKey, ostd::Stylesheet::TypeVariant value, bool propagate = true);
|
||||
void reloadTheme(void);
|
||||
void setThemeQualifier(const ostd::String& qualifier, bool value = true);
|
||||
bool getThemeQualifier(const ostd::String& qualifier);
|
||||
bool getThemeQualifier(const ostd::String& qualifier) const;
|
||||
bool addThemeID(const ostd::String& id);
|
||||
bool removeThemeID(const ostd::String& id);
|
||||
inline const ostd::Stylesheet::QualifierList& getThemeQualifierList(void) const { return m_qualifierList; }
|
||||
|
|
@ -106,6 +66,7 @@ namespace ogfx
|
|||
inline virtual void onMousePressed(const Event& event) { }
|
||||
inline virtual void onMouseReleased(const Event& event) { }
|
||||
inline virtual void onMouseMoved(const Event& event) { }
|
||||
inline virtual void onDragAndDrop(const Event& event) { }
|
||||
inline virtual void onMouseEntered(const Event& event) { }
|
||||
inline virtual void onMouseExited(const Event& event) { }
|
||||
inline virtual void onMouseDragged(const Event& event) { }
|
||||
|
|
@ -123,6 +84,7 @@ namespace ogfx
|
|||
void __update(void);
|
||||
void __onMousePressed(const Event& event);
|
||||
void __onMouseReleased(const Event& event);
|
||||
void __onDragAndDrop(const Event& event);
|
||||
void __onMouseMoved(const Event& event);
|
||||
void __onMouseEntered(const Event& event);
|
||||
void __onMouseExited(const Event& event);
|
||||
|
|
@ -132,13 +94,14 @@ namespace ogfx
|
|||
void __onTextEntered(const Event& event);
|
||||
void __onWindowClosed(const Event& event);
|
||||
void __onWindowResized(const Event& event);
|
||||
void __onWIndowFocused(const Event& event);
|
||||
void __onWindowFocused(const Event& event);
|
||||
void __onWindowFocusLost(const Event& event);
|
||||
void __applyTheme(const ostd::Stylesheet& 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 setDragAndDropCallback(EventCallback callback) { callback_onDragAndDrop = callback; }
|
||||
inline virtual void setMouseEnteredCallback(EventCallback callback) { callback_onMouseEntered = callback; }
|
||||
inline virtual void setMouseExitedCallback(EventCallback callback) { callback_onMouseExited = callback; }
|
||||
inline virtual void setMouseDraggedCallback(EventCallback callback) { callback_onMouseDragged = callback; }
|
||||
|
|
@ -147,7 +110,7 @@ namespace ogfx
|
|||
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 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; }
|
||||
|
|
@ -168,8 +131,11 @@ namespace ogfx
|
|||
inline bool isFocusEnabled(void) const { return m_allowFocus; }
|
||||
inline void enableFocus(bool enable = true) { m_allowFocus = enable; }
|
||||
inline void disableFocus(void) { enableFocus(false); }
|
||||
inline void disabble(void) { enable(false); }
|
||||
inline void disable(void) { enable(false); }
|
||||
inline void enableStopEvents(bool enable = true) { m_stopEvents = enable; }
|
||||
inline bool isDragAndDropEnabled(void) const { return m_acceptDragAndDrop; }
|
||||
inline void enableDragAndDrop(bool enable = true) { m_acceptDragAndDrop = enable; }
|
||||
inline void disableDragAndDrop(void) { enableDragAndDrop(false); }
|
||||
|
||||
template<typename T>
|
||||
inline T getThemeValue(const ostd::Stylesheet &theme, const ostd::String& key, const T& fallback)
|
||||
|
|
@ -177,6 +143,10 @@ namespace ogfx
|
|||
return theme.get<T>(key, fallback, getThemeIDList(), getThemeQualifierList());
|
||||
}
|
||||
|
||||
inline static void setDragAndDropData(ostd::BaseObject& data) { s_dragAndDropData = &data; }
|
||||
inline static void clearDragAndDropData(void) { s_dragAndDropData = nullptr; }
|
||||
inline static ostd::BaseObject* getDragAndDropData(void) { return s_dragAndDropData; }
|
||||
|
||||
protected:
|
||||
inline void disableChildren(void) { m_allowChildren = false; }
|
||||
inline void disableDrawBox(void) { m_drawBox = false; }
|
||||
|
|
@ -194,6 +164,7 @@ namespace ogfx
|
|||
|
||||
EventCallback callback_onMousePressed { nullptr };
|
||||
EventCallback callback_onMouseReleased { nullptr };
|
||||
EventCallback callback_onDragAndDrop { nullptr };
|
||||
EventCallback callback_onMouseMoved { nullptr };
|
||||
EventCallback callback_onMouseEntered { nullptr };
|
||||
EventCallback callback_onMouseExited { nullptr };
|
||||
|
|
@ -219,6 +190,7 @@ namespace ogfx
|
|||
bool m_enabled { true };
|
||||
bool m_stopEvents { true };
|
||||
bool m_clipContents { true };
|
||||
bool m_acceptDragAndDrop { false };
|
||||
MouseEventData::eButton m_pressedButton { MouseEventData::eButton::None };
|
||||
|
||||
std::vector<ostd::String> m_themeIDList;
|
||||
|
|
@ -236,21 +208,9 @@ namespace ogfx
|
|||
|
||||
ostd::Rectangle m_padding { 0, 0, 0, 0 };
|
||||
|
||||
inline static ostd::BaseObject* s_dragAndDropData { nullptr };
|
||||
|
||||
friend class WidgetManager;
|
||||
};
|
||||
namespace widgets
|
||||
{
|
||||
class RootWidget : public Widget
|
||||
{
|
||||
public:
|
||||
RootWidget(WindowCore& window);
|
||||
void onWindowResized(const Event& event) override;
|
||||
void applyTheme(const ostd::Stylesheet& theme) override;
|
||||
void onDraw(ogfx::BasicRenderer2D& gfx) override;
|
||||
|
||||
private:
|
||||
ostd::Color m_color { ostd::Colors::Transparent };
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,23 @@
|
|||
/*
|
||||
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 "Logic.hpp"
|
||||
#include "../string/String.hpp"
|
||||
#ifndef __APPLE__
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ namespace ostd
|
|||
inline static constexpr uint32_t TextEntered = 0x0007;
|
||||
|
||||
inline static constexpr uint32_t OnGuiEvent = 0x2001;
|
||||
inline static constexpr uint32_t FileDragAndDropped = 0x2002;
|
||||
inline static constexpr uint32_t TextDragAndDropped = 0x2003;
|
||||
|
||||
inline static constexpr uint32_t BeforeSDLShutdown = 0x3001;
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ class Window : public ogfx::gui::Window
|
|||
inline void onInitialize(void) override
|
||||
{
|
||||
m_panel1.setSize(300, 140);
|
||||
m_panel1.setPosition(200, 150);
|
||||
m_panel1.setPosition(350, 50);
|
||||
m_panel1.setMousePressedCallback([&](const ogfx::gui::Event& event) -> void {
|
||||
pos = { event.mouse->position_x, event.mouse->position_y };
|
||||
});
|
||||
|
|
@ -43,6 +43,13 @@ class Window : public ogfx::gui::Window
|
|||
|
||||
m_panel2.setSize(300, 140);
|
||||
m_panel2.setPosition(130, 200);
|
||||
m_panel2.setMousePressedCallback([&](const ogfx::gui::Event& event) -> void {
|
||||
ogfx::gui::Widget::setDragAndDropData(m_label3);
|
||||
setCursor(eCursor::Move);
|
||||
});
|
||||
m_panel2.setMouseReleasedCallback([&](const ogfx::gui::Event& event) -> void {
|
||||
setCursor(eCursor::Default);
|
||||
});
|
||||
|
||||
m_label1.setPosition(100, 200);
|
||||
m_label1.setText("Hello World!");
|
||||
|
|
@ -57,6 +64,14 @@ class Window : public ogfx::gui::Window
|
|||
m_label2.setText("Ciccia Bella!");
|
||||
m_label2.addThemeID("testLabel");
|
||||
m_label2.addThemeID("testLabel2");
|
||||
m_label2.enableDragAndDrop();
|
||||
m_label2.setDragAndDropCallback([&](const ogfx::gui::Event& event) -> void {
|
||||
std::cout << "DROP\n";
|
||||
if (auto data = ogfx::gui::Widget::getDragAndDropData())
|
||||
{
|
||||
std::cout << static_cast<ogfx::gui::widgets::Label&>(*data).getText() << "!\n";
|
||||
}
|
||||
});
|
||||
m_panel1.addChild(m_label2);
|
||||
|
||||
m_label1.addThemeOverride("@:pressed.label.textColor", ostd::Colors::Crimson);
|
||||
|
|
|
|||
Loading…
Reference in a new issue