Added FocusManager
This commit is contained in:
parent
67a1dd605d
commit
203a305633
24 changed files with 373 additions and 164 deletions
|
|
@ -88,6 +88,7 @@ list(APPEND OGFX_SOURCE_FILES
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/MenuBar.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/MenuBar.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/ToolBar.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/ToolBar.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/Layout.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/Layout.cpp
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/FocusManager.cpp
|
||||||
|
|
||||||
# gui/widgets
|
# gui/widgets
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/widgets/Widget.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/widgets/Widget.cpp
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,8 @@
|
||||||
***FIX: Limit FPS even when continuous events happen
|
***FIX: Limit FPS even when continuous events happen
|
||||||
***FIX: Float values in stylesheet needing to have decimal point to be read as float
|
***FIX: Float values in stylesheet needing to have decimal point to be read as float
|
||||||
***Make parsing of vec2 and rect in stylesheet, consistent with other value functions like gradients and animations
|
***Make parsing of vec2 and rect in stylesheet, consistent with other value functions like gradients and animations
|
||||||
|
***FIX: ToolBar::AddButton not consistent order
|
||||||
|
***FIX: KeyPress crash on TreeView
|
||||||
Implement cursors in Stylesheet
|
Implement cursors in Stylesheet
|
||||||
FIX: Window getting exponentially bigger when Desktop scale changes
|
FIX: Window getting exponentially bigger when Desktop scale changes
|
||||||
FIX: Refreshing scroll when content extent changes
|
FIX: Refreshing scroll when content extent changes
|
||||||
|
|
@ -52,6 +54,8 @@ FIX: ContextMenu rendering partly outside the screen when showing it close to th
|
||||||
Update theme for visible TreeView lines
|
Update theme for visible TreeView lines
|
||||||
Add ToolBar::addButton overload that takes a ogfx::Icon wrapper
|
Add ToolBar::addButton overload that takes a ogfx::Icon wrapper
|
||||||
Redesign theme overrides to be more robust
|
Redesign theme overrides to be more robust
|
||||||
|
FIX: Animated icons not working in TreeView
|
||||||
|
Add modifiers to Event.keyboard path
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -160,14 +160,14 @@ namespace ogfx
|
||||||
Instance m_data;
|
Instance m_data;
|
||||||
f32 m_entryHeight { 0 };
|
f32 m_entryHeight { 0 };
|
||||||
Vec2 m_mousePos { 0, 0 };
|
Vec2 m_mousePos { 0, 0 };
|
||||||
ostd::Timer m_animClock;
|
ostd::Counter m_animClock;
|
||||||
|
|
||||||
stdvec<Panel> m_panels;
|
stdvec<Panel> m_panels;
|
||||||
|
|
||||||
i32 m_pendingOpenPanelDepth { -1 };
|
i32 m_pendingOpenPanelDepth { -1 };
|
||||||
i32 m_pendingOpenEntryIndex { -1 };
|
i32 m_pendingOpenEntryIndex { -1 };
|
||||||
ostd::Timer m_hoverOpenTimer;
|
ostd::Counter m_hoverOpenTimer;
|
||||||
ostd::Timer m_hoverCloseTimer;
|
ostd::Counter m_hoverCloseTimer;
|
||||||
bool m_hoverOpenTimerActive { false };
|
bool m_hoverOpenTimerActive { false };
|
||||||
bool m_hoverCloseTimerActive { false };
|
bool m_hoverCloseTimerActive { false };
|
||||||
|
|
||||||
|
|
|
||||||
154
src/ogfx/gui/FocusManager.cpp
Normal file
154
src/ogfx/gui/FocusManager.cpp
Normal file
|
|
@ -0,0 +1,154 @@
|
||||||
|
/*
|
||||||
|
OmniaFramework - A collection of useful functionality
|
||||||
|
Copyright (C) 2026 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 "FocusManager.hpp"
|
||||||
|
#include "Window.hpp"
|
||||||
|
#include "../utils/Keycodes.hpp"
|
||||||
|
|
||||||
|
namespace ogfx
|
||||||
|
{
|
||||||
|
namespace gui
|
||||||
|
{
|
||||||
|
FocusManager::FocusManager(Window& window) : m_window(window)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FocusManager::requestFocus(Widget& widget)
|
||||||
|
{
|
||||||
|
if (&widget == m_focused) return true;
|
||||||
|
if (!widget.isFocusEnabled()) return false;
|
||||||
|
if (m_window.getToolBar().isVisible())
|
||||||
|
{
|
||||||
|
if (requestFocus(widget, m_window.getToolBar()))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (m_window.getStatusBar().isVisible())
|
||||||
|
{
|
||||||
|
if (requestFocus(widget, m_window.getStatusBar()))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return requestFocus(widget, m_window.m_rootWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FocusManager::requestFocus(Widget& widget, Widget& root)
|
||||||
|
{
|
||||||
|
if (&widget == m_focused) return true;
|
||||||
|
if (!widget.isFocusEnabled()) return false;
|
||||||
|
if (widget.isInvalid()) return false;
|
||||||
|
if (!widget.isVisible()) return false;
|
||||||
|
if (!root.hasChildren() || !root.isChildrenEnabled())
|
||||||
|
return false;
|
||||||
|
if (!root.getChildren().hasWidget(widget))
|
||||||
|
{
|
||||||
|
for (auto& child : root.getChildren().m_widgetList)
|
||||||
|
{
|
||||||
|
if (child && requestFocus(widget, *child))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_focused)
|
||||||
|
{
|
||||||
|
m_focused->m_focused = false;
|
||||||
|
m_focused->onFocusLost(Event(m_window));
|
||||||
|
m_focused->setThemeQualifier("focused", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
widget.m_focused = true;
|
||||||
|
widget.onFocusGained(Event(m_window));
|
||||||
|
widget.setThemeQualifier("focused", true);
|
||||||
|
m_focused = &widget;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget* FocusManager::focusNext(void)
|
||||||
|
{
|
||||||
|
if (m_tabIndexMap.empty())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
i32 startIndex = -1, smallest = i32Range::max();
|
||||||
|
if (m_focused)
|
||||||
|
startIndex = m_focused->m_tabIndex;
|
||||||
|
i32 nextIndex = i32Range::max();
|
||||||
|
Widget* nextPtr = nullptr;
|
||||||
|
Widget* smallestPtr = nullptr;
|
||||||
|
|
||||||
|
for (auto&[wptr, index] : m_tabIndexMap)
|
||||||
|
{
|
||||||
|
if (index < smallest)
|
||||||
|
{
|
||||||
|
smallest = index;
|
||||||
|
smallestPtr = wptr;
|
||||||
|
}
|
||||||
|
if (index > startIndex && index < nextIndex)
|
||||||
|
{
|
||||||
|
nextIndex = index;
|
||||||
|
nextPtr = wptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget* w = nullptr;
|
||||||
|
if (!nextPtr)
|
||||||
|
{
|
||||||
|
if (!smallestPtr)
|
||||||
|
return nullptr;
|
||||||
|
w = smallestPtr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
w = nextPtr;
|
||||||
|
|
||||||
|
requestFocus(*w);
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FocusManager::registerTabIndex(Widget& widget, i32 index)
|
||||||
|
{
|
||||||
|
if (index >= 0)
|
||||||
|
{
|
||||||
|
m_tabIndexMap[&widget] = index;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FocusManager::unregisterTabIndex(Widget& widget)
|
||||||
|
{
|
||||||
|
if (m_tabIndexMap.count(&widget) > 0)
|
||||||
|
m_tabIndexMap.erase(m_tabIndexMap.find(&widget));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FocusManager::clearFocus(void)
|
||||||
|
{
|
||||||
|
if (m_focused)
|
||||||
|
{
|
||||||
|
m_focused->m_focused = false;
|
||||||
|
m_focused = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FocusManager::onKeyReleased(const Event& event)
|
||||||
|
{
|
||||||
|
if (isTabNavigationEnabled() && event.keyboard->keyCode == KeyCode::Tab)
|
||||||
|
focusNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
55
src/ogfx/gui/FocusManager.hpp
Normal file
55
src/ogfx/gui/FocusManager.hpp
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
OmniaFramework - A collection of useful functionality
|
||||||
|
Copyright (C) 2026 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
|
||||||
|
{
|
||||||
|
class Window;
|
||||||
|
class FocusManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FocusManager(Window& window);
|
||||||
|
bool requestFocus(Widget& widget, Widget& root);
|
||||||
|
bool requestFocus(Widget& widget);
|
||||||
|
Widget* focusNext(void);
|
||||||
|
|
||||||
|
bool registerTabIndex(Widget& widget, i32 index);
|
||||||
|
void unregisterTabIndex(Widget& widget);
|
||||||
|
|
||||||
|
void clearFocus(void);
|
||||||
|
|
||||||
|
void onKeyReleased(const Event& event);
|
||||||
|
|
||||||
|
inline Widget* getFocused(void) { return m_focused; }
|
||||||
|
OSTD_BOOL_PARAM_GETSET_E(TabNavigation, m_tabNavigationEnabled);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Window& m_window;
|
||||||
|
Widget* m_focused { nullptr };
|
||||||
|
bool m_tabNavigationEnabled { true };
|
||||||
|
stdumap<Widget*, i32> m_tabIndexMap;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,21 +1,21 @@
|
||||||
/*
|
/*
|
||||||
OmniaFramework - A collection of useful functionality
|
OmniaFramework - A collection of useful functionality
|
||||||
Copyright (C) 2026 OmniaX-Dev
|
Copyright (C) 2026 OmniaX-Dev
|
||||||
|
|
||||||
This file is part of OmniaFramework.
|
This file is part of OmniaFramework.
|
||||||
|
|
||||||
OmniaFramework is free software: you can redistribute it and/or modify
|
OmniaFramework is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
OmniaFramework is distributed in the hope that it will be useful,
|
OmniaFramework is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with OmniaFramework. If not, see <https://www.gnu.org/licenses/>.
|
along with OmniaFramework. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
@ -60,35 +60,35 @@ namespace ogfx
|
||||||
u8 extraPaddingLeft { 0 };
|
u8 extraPaddingLeft { 0 };
|
||||||
|
|
||||||
bool cursorBlink { true };
|
bool cursorBlink { true };
|
||||||
ostd::Counter cursorBlinkCounter { 30 };
|
ostd::BasicCounter cursorBlinkCounter { 30 };
|
||||||
};
|
};
|
||||||
public: struct tDefaultThemes
|
public: struct tDefaultThemes
|
||||||
{
|
{
|
||||||
inline static const Theme DebugTheme {
|
inline static const Theme DebugTheme {
|
||||||
{ 220, 220, 255 }, //Text Color
|
{ 220, 220, 255 }, //Text Color
|
||||||
{ 10, 20, 120 }, //Border Color
|
{ 10, 20, 120 }, //Border Color
|
||||||
{ 0, 0, 22 }, //Background Color
|
{ 0, 0, 22 }, //Background Color
|
||||||
{ 220, 10, 10 }, //Cursor Color
|
{ 220, 10, 10 }, //Cursor Color
|
||||||
|
|
||||||
2, //Cursor Width
|
2, //Cursor Width
|
||||||
0, //Extra Padding Top
|
0, //Extra Padding Top
|
||||||
0, //Extra Padding Left
|
0, //Extra Padding Left
|
||||||
|
|
||||||
true, //Cursor Blink
|
true, //Cursor Blink
|
||||||
{ 30 } //Cursor Blink Timer
|
{ 30 } //Cursor Blink Timer
|
||||||
};
|
};
|
||||||
inline static const Theme DefaultTheme {
|
inline static const Theme DefaultTheme {
|
||||||
{ 120, 120, 180 }, //Text Color
|
{ 120, 120, 180 }, //Text Color
|
||||||
{ 10, 20, 120 }, //Border Color
|
{ 10, 20, 120 }, //Border Color
|
||||||
{ 0, 2, 10 }, //Background Color
|
{ 0, 2, 10 }, //Background Color
|
||||||
{ 20, 100, 255 }, //Cursor Color
|
{ 20, 100, 255 }, //Cursor Color
|
||||||
|
|
||||||
2, //Cursor Width
|
2, //Cursor Width
|
||||||
0, //Extra Padding Top
|
0, //Extra Padding Top
|
||||||
0, //Extra Padding Left
|
0, //Extra Padding Left
|
||||||
|
|
||||||
true, //Cursor Blink
|
true, //Cursor Blink
|
||||||
{ 30 } //Cursor Blink Timer
|
{ 30 } //Cursor Blink Timer
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
public: enum eActionEventType { None = 0, Enter, Tab };
|
public: enum eActionEventType { None = 0, Enter, Tab };
|
||||||
|
|
@ -156,7 +156,7 @@ namespace ogfx
|
||||||
u16 m_cursorPosition { 0 };
|
u16 m_cursorPosition { 0 };
|
||||||
bool m_cursorState { true };
|
bool m_cursorState { true };
|
||||||
|
|
||||||
ostd::Counter m_keyRepeatCounter { 1 };
|
ostd::BasicCounter m_keyRepeatCounter { 1 };
|
||||||
char m_lastChar { 0 };
|
char m_lastChar { 0 };
|
||||||
i32 m_lastKeyCode { 0 };
|
i32 m_lastKeyCode { 0 };
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ namespace ogfx
|
||||||
setPosition(0, win.getMenuBar().getHeight());
|
setPosition(0, win.getMenuBar().getHeight());
|
||||||
else
|
else
|
||||||
setPosition(0, 0);
|
setPosition(0, 0);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "WidgetManager.hpp"
|
#include "WidgetManager.hpp"
|
||||||
|
#include "Window.hpp"
|
||||||
#include "widgets/Widget.hpp"
|
#include "widgets/Widget.hpp"
|
||||||
#include "../render/BasicRenderer.hpp"
|
#include "../render/BasicRenderer.hpp"
|
||||||
#include "../utils/Keycodes.hpp"
|
|
||||||
#include "../../ostd/io/Memory.hpp"
|
#include "../../ostd/io/Memory.hpp"
|
||||||
|
|
||||||
namespace ogfx
|
namespace ogfx
|
||||||
|
|
@ -39,41 +39,11 @@ namespace ogfx
|
||||||
return found && widget.isValid();
|
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->isVisible()) 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)
|
bool WidgetManager::addWidget(Widget& widget)
|
||||||
{
|
{
|
||||||
if (hasWidget(widget)) return false;
|
if (hasWidget(widget)) return false;
|
||||||
widget.m_parent = &m_owner;
|
widget.m_parent = &m_owner;
|
||||||
m_widgetList.push_back(&widget);
|
m_widgetList.push_back(&widget);
|
||||||
if (widget.m_topMost)
|
|
||||||
return true;
|
|
||||||
std::ranges::sort(m_widgetList, {}, [](Widget* w) {
|
|
||||||
return w->m_zIndex;
|
|
||||||
});
|
|
||||||
widget.refresh();
|
widget.refresh();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -84,32 +54,6 @@ namespace ogfx
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget* WidgetManager::focusNext(void)
|
|
||||||
{
|
|
||||||
if (m_widgetList.empty())
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
Widget* next = nullptr;
|
|
||||||
Widget* smallest = nullptr;
|
|
||||||
|
|
||||||
i32 currentTabIndex = (m_focused != nullptr ? m_focused->m_tabIndex : std::numeric_limits<i32>::max());
|
|
||||||
for (Widget* w : m_widgetList)
|
|
||||||
{
|
|
||||||
i32 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)
|
void WidgetManager::draw(ogfx::BasicRenderer2D& gfx)
|
||||||
{
|
{
|
||||||
for (auto& w : m_widgetList)
|
for (auto& w : m_widgetList)
|
||||||
|
|
@ -157,6 +101,7 @@ namespace ogfx
|
||||||
if (!w->contains(event.mouse->position_x, event.mouse->position_y, true))
|
if (!w->contains(event.mouse->position_x, event.mouse->position_y, true))
|
||||||
continue;
|
continue;
|
||||||
event.mouse->mousePressedOnWidget = w;
|
event.mouse->mousePressedOnWidget = w;
|
||||||
|
cast<Window&>(m_window).getFocusManager().requestFocus(*w);
|
||||||
w->__onMousePressed(event);
|
w->__onMousePressed(event);
|
||||||
m_mousePressedOnWidget = w;
|
m_mousePressedOnWidget = w;
|
||||||
if (event.isHandled() || w->m_stopEvents)
|
if (event.isHandled() || w->m_stopEvents)
|
||||||
|
|
@ -182,7 +127,6 @@ namespace ogfx
|
||||||
event.mouse->mousePressedOnWidget = m_mousePressedOnWidget;
|
event.mouse->mousePressedOnWidget = m_mousePressedOnWidget;
|
||||||
w->__onMouseReleased(event);
|
w->__onMouseReleased(event);
|
||||||
processDragAndDrop(w, event);
|
processDragAndDrop(w, event);
|
||||||
// requestFocus(*w);
|
|
||||||
if (w->isMouseInside() && w->m_stopEvents)
|
if (w->isMouseInside() && w->m_stopEvents)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -275,22 +219,24 @@ namespace ogfx
|
||||||
|
|
||||||
void WidgetManager::onKeyPressed(const Event& event)
|
void WidgetManager::onKeyPressed(const Event& event)
|
||||||
{
|
{
|
||||||
if (!m_focused || !m_focused->isVisible()) return;
|
auto focused = cast<Window&>(m_window).getFocusManager().getFocused();
|
||||||
m_focused->__onKeyPressed(event);
|
if (!focused || !focused->isVisible()) return;
|
||||||
|
focused->__onKeyPressed(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WidgetManager::onKeyReleased(const Event& event)
|
void WidgetManager::onKeyReleased(const Event& event)
|
||||||
{
|
{
|
||||||
if (!m_focused || !m_focused->isVisible()) return;
|
auto focus = cast<Window&>(m_window).getFocusManager();
|
||||||
m_focused->__onKeyReleased(event);
|
auto focused = focus.getFocused();
|
||||||
if (m_tabNavigationEnabled && event.keyboard->keyCode == KeyCode::Tab)
|
if (!focused || !focused->isVisible()) return;
|
||||||
focusNext();
|
focused->__onKeyReleased(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WidgetManager::onTextEntered(const Event& event)
|
void WidgetManager::onTextEntered(const Event& event)
|
||||||
{
|
{
|
||||||
if (!m_focused || !m_focused->isVisible()) return;
|
auto focused = cast<Window&>(m_window).getFocusManager().getFocused();
|
||||||
m_focused->__onTextEntered(event);
|
if (!focused || !focused->isVisible()) return;
|
||||||
|
focused->__onTextEntered(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WidgetManager::onWindowClosed(const Event& event)
|
void WidgetManager::onWindowClosed(const Event& event)
|
||||||
|
|
|
||||||
|
|
@ -39,10 +39,8 @@ namespace ogfx
|
||||||
public:
|
public:
|
||||||
WidgetManager(WindowCore& window, Widget& owner);
|
WidgetManager(WindowCore& window, Widget& owner);
|
||||||
bool hasWidget(Widget& widget);
|
bool hasWidget(Widget& widget);
|
||||||
bool requestFocus(Widget& widget);
|
|
||||||
bool addWidget(Widget& widget);
|
bool addWidget(Widget& widget);
|
||||||
bool removeWidget(Widget& widget);
|
bool removeWidget(Widget& widget);
|
||||||
Widget* focusNext(void);
|
|
||||||
|
|
||||||
void draw(ogfx::BasicRenderer2D& gfx);
|
void draw(ogfx::BasicRenderer2D& gfx);
|
||||||
void update(void);
|
void update(void);
|
||||||
|
|
@ -71,9 +69,9 @@ namespace ogfx
|
||||||
WindowCore& m_window;
|
WindowCore& m_window;
|
||||||
Widget& m_owner;
|
Widget& m_owner;
|
||||||
stdvec<Widget*> m_widgetList;
|
stdvec<Widget*> m_widgetList;
|
||||||
Widget* m_focused { nullptr };
|
|
||||||
bool m_tabNavigationEnabled { true };
|
|
||||||
Widget* m_mousePressedOnWidget { nullptr };
|
Widget* m_mousePressedOnWidget { nullptr };
|
||||||
|
|
||||||
|
friend class FocusManager;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1008,6 +1008,7 @@ namespace ogfx
|
||||||
{
|
{
|
||||||
evt.keyboard = &(ogfx::KeyEventData&)signal.userData;
|
evt.keyboard = &(ogfx::KeyEventData&)signal.userData;
|
||||||
evt.__original_signal_id = ostd::BuiltinSignals::KeyReleased;
|
evt.__original_signal_id = ostd::BuiltinSignals::KeyReleased;
|
||||||
|
m_focusManager.onKeyReleased(evt);
|
||||||
m_toolbar.__onKeyReleased(evt);
|
m_toolbar.__onKeyReleased(evt);
|
||||||
m_statusbar.__onKeyReleased(evt);
|
m_statusbar.__onKeyReleased(evt);
|
||||||
m_rootWidget.__onKeyReleased(evt);
|
m_rootWidget.__onKeyReleased(evt);
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
#include <ogfx/gui/ContextMenu.hpp>
|
#include <ogfx/gui/ContextMenu.hpp>
|
||||||
#include <ogfx/gui/MenuBar.hpp>
|
#include <ogfx/gui/MenuBar.hpp>
|
||||||
#include <ogfx/gui/ToolBar.hpp>
|
#include <ogfx/gui/ToolBar.hpp>
|
||||||
|
#include <ogfx/gui/FocusManager.hpp>
|
||||||
|
|
||||||
namespace ogfx
|
namespace ogfx
|
||||||
{
|
{
|
||||||
|
|
@ -181,7 +182,7 @@ namespace ogfx
|
||||||
String m_title { "" };
|
String m_title { "" };
|
||||||
i32 m_blockingEventsDelay { 33 };
|
i32 m_blockingEventsDelay { 33 };
|
||||||
Vec2 m_mousePosition { 0, 0 };
|
Vec2 m_mousePosition { 0, 0 };
|
||||||
ostd::Timer m_tooltipTimer;
|
ostd::Counter m_tooltipTimer;
|
||||||
String m_tooltipText { "" };
|
String m_tooltipText { "" };
|
||||||
|
|
||||||
bool m_running { false };
|
bool m_running { false };
|
||||||
|
|
@ -259,7 +260,7 @@ namespace ogfx
|
||||||
i32 m_fps { 0 };
|
i32 m_fps { 0 };
|
||||||
ostd::StepTimer m_fixedUpdateTImer;
|
ostd::StepTimer m_fixedUpdateTImer;
|
||||||
ostd::StepTimer m_fpsUpdateTimer;
|
ostd::StepTimer m_fpsUpdateTimer;
|
||||||
ostd::Timer m_fpsUpdateClock;
|
ostd::Counter m_fpsUpdateClock;
|
||||||
u64 m_frameTimeAcc { 0 };
|
u64 m_frameTimeAcc { 0 };
|
||||||
i32 m_frameCount { 0 };
|
i32 m_frameCount { 0 };
|
||||||
};
|
};
|
||||||
|
|
@ -284,6 +285,7 @@ namespace ogfx
|
||||||
inline void showMenuBar(bool show = true) { m_menubar.show(show); }
|
inline void showMenuBar(bool show = true) { m_menubar.show(show); }
|
||||||
inline void showToolBar(bool show = true) { m_toolbar.setVisible(show); }
|
inline void showToolBar(bool show = true) { m_toolbar.setVisible(show); }
|
||||||
inline void showStatusBar(bool show = true) { m_statusbar.setVisible(show); }
|
inline void showStatusBar(bool show = true) { m_statusbar.setVisible(show); }
|
||||||
|
inline FocusManager& getFocusManager(void) { return m_focusManager; }
|
||||||
|
|
||||||
inline virtual void onInitialize(void) { }
|
inline virtual void onInitialize(void) { }
|
||||||
inline virtual void onDestroy(void) { }
|
inline virtual void onDestroy(void) { }
|
||||||
|
|
@ -308,6 +310,7 @@ namespace ogfx
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
RootWidget m_rootWidget { *this };
|
RootWidget m_rootWidget { *this };
|
||||||
|
FocusManager m_focusManager { *this };
|
||||||
ostd::StepTimer m_fixedUpdateTimer;
|
ostd::StepTimer m_fixedUpdateTimer;
|
||||||
ostd::StepTimer::TimePoint m_lastFrameTime;
|
ostd::StepTimer::TimePoint m_lastFrameTime;
|
||||||
ostd::StepTimer m_mainLoopTimer;
|
ostd::StepTimer m_mainLoopTimer;
|
||||||
|
|
@ -317,6 +320,7 @@ namespace ogfx
|
||||||
ToolBar m_statusbar { *this, true };
|
ToolBar m_statusbar { *this, true };
|
||||||
|
|
||||||
friend class RootWidget;
|
friend class RootWidget;
|
||||||
|
friend class FocusManager;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ namespace ogfx
|
||||||
setPadding({ 5, 5, 5, 5 });
|
setPadding({ 5, 5, 5, 5 });
|
||||||
setTypeName("ogfx::gui::Label");
|
setTypeName("ogfx::gui::Label");
|
||||||
disableChildren();
|
disableChildren();
|
||||||
|
disableFocus();
|
||||||
enableBackground(false);
|
enableBackground(false);
|
||||||
setStylesheetCategoryName("label");
|
setStylesheetCategoryName("label");
|
||||||
validate();
|
validate();
|
||||||
|
|
@ -127,6 +128,7 @@ namespace ogfx
|
||||||
setPadding({ 0, 0, 0, 0 });
|
setPadding({ 0, 0, 0, 0 });
|
||||||
setTypeName("ogfx::gui::ImageLabel");
|
setTypeName("ogfx::gui::ImageLabel");
|
||||||
disableChildren();
|
disableChildren();
|
||||||
|
disableFocus();
|
||||||
disableBackground();
|
disableBackground();
|
||||||
disableBorder();
|
disableBorder();
|
||||||
setStylesheetCategoryName("image");
|
setStylesheetCategoryName("image");
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ namespace ogfx
|
||||||
setPadding({ 0, 0, 0, 0 });
|
setPadding({ 0, 0, 0, 0 });
|
||||||
setTypeName("ogfx::gui::ProgressBar");
|
setTypeName("ogfx::gui::ProgressBar");
|
||||||
disableChildren();
|
disableChildren();
|
||||||
|
disableFocus();
|
||||||
enableBackground();
|
enableBackground();
|
||||||
enableBorder();
|
enableBorder();
|
||||||
setStylesheetCategoryName("progressbar");
|
setStylesheetCategoryName("progressbar");
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ namespace ogfx
|
||||||
RootWidget::RootWidget(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window)
|
RootWidget::RootWidget(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window)
|
||||||
{
|
{
|
||||||
setRootChild();
|
setRootChild();
|
||||||
|
disableFocus();
|
||||||
setSize(cast<f32>(window.getWindowWidth()), cast<f32>(window.getWindowHeight()));
|
setSize(cast<f32>(window.getWindowWidth()), cast<f32>(window.getWindowHeight()));
|
||||||
setStylesheetCategoryName("window");
|
setStylesheetCategoryName("window");
|
||||||
setTypeName("ogfx::gui::RootWidget");
|
setTypeName("ogfx::gui::RootWidget");
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ namespace ogfx
|
||||||
setMargin({ 0, 0, 0, 0 });
|
setMargin({ 0, 0, 0, 0 });
|
||||||
setTypeName("ogfx::gui::Label");
|
setTypeName("ogfx::gui::Label");
|
||||||
disableChildren();
|
disableChildren();
|
||||||
|
disableFocus();
|
||||||
enableBackground(true);
|
enableBackground(true);
|
||||||
enableBorder(false);
|
enableBorder(false);
|
||||||
enableTopMost(true);
|
enableTopMost(true);
|
||||||
|
|
@ -154,6 +155,7 @@ namespace ogfx
|
||||||
setMargin({ 0, 0, 0, 0 });
|
setMargin({ 0, 0, 0, 0 });
|
||||||
setTypeName("ogfx::gui::Label");
|
setTypeName("ogfx::gui::Label");
|
||||||
disableChildren();
|
disableChildren();
|
||||||
|
disableFocus();
|
||||||
enableBackground(true);
|
enableBackground(true);
|
||||||
enableBorder(false);
|
enableBorder(false);
|
||||||
enableTopMost(true);
|
enableTopMost(true);
|
||||||
|
|
|
||||||
|
|
@ -277,11 +277,11 @@ namespace ogfx
|
||||||
auto& item = *m_list[i];
|
auto& item = *m_list[i];
|
||||||
if (!item.isValid()) continue;
|
if (!item.isValid()) continue;
|
||||||
if (!item.isVisible()) continue;
|
if (!item.isVisible()) continue;
|
||||||
if (!item.isIconEnabled()) continue;
|
f32 itemH = item.getDimensions().y;
|
||||||
if (y > visibleEnd) break;
|
if (y > visibleEnd) break;
|
||||||
if (item.getIcon().getFrameCount() != 1)
|
if (item.isIconEnabled())
|
||||||
std::cout << item.getIcon().getCurrentFrame() << "\n";
|
item.getIcon().update();
|
||||||
item.getIcon().update();
|
y += itemH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,15 @@ namespace ogfx
|
||||||
m_window = &window;
|
m_window = &window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget::~Widget(void)
|
||||||
|
{
|
||||||
|
if (m_window && m_tabIndex >= 0)
|
||||||
|
cast<Window&>(*m_window).getFocusManager().unregisterTabIndex(*this);
|
||||||
|
auto& fm = cast<Window&>(*m_window).getFocusManager();
|
||||||
|
if (fm.getFocused() == this)
|
||||||
|
fm.clearFocus(); // you'd add this method
|
||||||
|
}
|
||||||
|
|
||||||
bool Widget::addWidget(Widget& child, const Vec2& position, bool __skip_callback)
|
bool Widget::addWidget(Widget& child, const Vec2& position, bool __skip_callback)
|
||||||
{
|
{
|
||||||
if (!m_allowChildren)
|
if (!m_allowChildren)
|
||||||
|
|
@ -229,6 +238,16 @@ namespace ogfx
|
||||||
m_visible = v;
|
m_visible = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Widget::setTabIndex(i32 index)
|
||||||
|
{
|
||||||
|
if (cast<Window&>(getWindow()).getFocusManager().registerTabIndex(*this, index))
|
||||||
|
{
|
||||||
|
m_tabIndex = index;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void Widget::setLayout(std::unique_ptr<Layout> layout)
|
void Widget::setLayout(std::unique_ptr<Layout> layout)
|
||||||
{
|
{
|
||||||
m_layout = std::move(layout);
|
m_layout = std::move(layout);
|
||||||
|
|
@ -297,6 +316,9 @@ namespace ogfx
|
||||||
if (m_showBorder)
|
if (m_showBorder)
|
||||||
gfx.drawRoundRect({ getGlobalPosition(), getSize() }, m_borderColor, m_borderRadius, m_borderWidth);
|
gfx.drawRoundRect({ getGlobalPosition(), getSize() }, m_borderColor, m_borderRadius, m_borderWidth);
|
||||||
afterDraw(gfx);
|
afterDraw(gfx);
|
||||||
|
|
||||||
|
if (isFocused())
|
||||||
|
gfx.drawRoundRect({ getGlobalPosition(), getSize() }, Colors::Red, m_borderRadius, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::__update(void)
|
void Widget::__update(void)
|
||||||
|
|
@ -416,41 +438,26 @@ namespace ogfx
|
||||||
void Widget::__onKeyPressed(const Event& event)
|
void Widget::__onKeyPressed(const Event& event)
|
||||||
{
|
{
|
||||||
if (event.isHandled() || !isKeyPressedEventEnabled()) return;
|
if (event.isHandled() || !isKeyPressedEventEnabled()) return;
|
||||||
if (hasChildren())
|
if (callback_onKeyPressed)
|
||||||
m_widgets.onKeyPressed(event);
|
callback_onKeyPressed(event);
|
||||||
if (!event.isHandled())
|
onKeyPressed(event);
|
||||||
{
|
|
||||||
if (callback_onKeyPressed)
|
|
||||||
callback_onKeyPressed(event);
|
|
||||||
onKeyPressed(event);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::__onKeyReleased(const Event& event)
|
void Widget::__onKeyReleased(const Event& event)
|
||||||
{
|
{
|
||||||
if (event.isHandled() || !isKeyReleasedEventEnabled()) return;
|
if (event.isHandled() || !isKeyReleasedEventEnabled()) return;
|
||||||
m_pressedButton = ogfx::MouseEventData::eButton::None;
|
m_pressedButton = ogfx::MouseEventData::eButton::None;
|
||||||
if (hasChildren())
|
if (callback_onKeyReleased)
|
||||||
m_widgets.onKeyReleased(event);
|
callback_onKeyReleased(event);
|
||||||
if (!event.isHandled())
|
onKeyReleased(event);
|
||||||
{
|
|
||||||
if (callback_onKeyReleased)
|
|
||||||
callback_onKeyReleased(event);
|
|
||||||
onKeyReleased(event);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::__onTextEntered(const Event& event)
|
void Widget::__onTextEntered(const Event& event)
|
||||||
{
|
{
|
||||||
if (event.isHandled() || !isTextEnteredEventEnabled()) return;
|
if (event.isHandled() || !isTextEnteredEventEnabled()) return;
|
||||||
if (hasChildren())
|
if (callback_onTextEntered)
|
||||||
m_widgets.onTextEntered(event);
|
callback_onTextEntered(event);
|
||||||
if (!event.isHandled())
|
onTextEntered(event);
|
||||||
{
|
|
||||||
if (callback_onTextEntered)
|
|
||||||
callback_onTextEntered(event);
|
|
||||||
onTextEntered(event);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::__onWindowClosed(const Event& event)
|
void Widget::__onWindowClosed(const Event& event)
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,11 @@ namespace ogfx
|
||||||
public:
|
public:
|
||||||
// ================================== MAIN =================================
|
// ================================== MAIN =================================
|
||||||
Widget(const Rectangle& bounds, WindowCore& window);
|
Widget(const Rectangle& bounds, WindowCore& window);
|
||||||
|
Widget(Widget&&) = default;
|
||||||
|
Widget& operator=(Widget&&) = delete;
|
||||||
|
Widget(const Widget&) = delete;
|
||||||
|
Widget& operator=(const Widget&) = delete;
|
||||||
|
virtual ~Widget(void);
|
||||||
bool addWidget(Widget& child, const Vec2& position = { 0, 0 }, bool __skip_callback = false);
|
bool addWidget(Widget& child, const Vec2& position = { 0, 0 }, bool __skip_callback = false);
|
||||||
bool removeWidget(Widget& child);
|
bool removeWidget(Widget& child);
|
||||||
void enable(bool enable = true);
|
void enable(bool enable = true);
|
||||||
|
|
@ -76,6 +81,7 @@ namespace ogfx
|
||||||
bool addThemeID(const String& id);
|
bool addThemeID(const String& id);
|
||||||
bool removeThemeID(const String& id);
|
bool removeThemeID(const String& id);
|
||||||
void setVisible(bool v);
|
void setVisible(bool v);
|
||||||
|
bool setTabIndex(i32 index);
|
||||||
virtual void setCallback(eCallback type, EventCallback callback);
|
virtual void setCallback(eCallback type, EventCallback callback);
|
||||||
using Rectangle::contains; bool contains(Vec2 p, bool includeBounds = false) const override;
|
using Rectangle::contains; bool contains(Vec2 p, bool includeBounds = false) const override;
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
@ -154,10 +160,10 @@ namespace ogfx
|
||||||
inline static void setDragAndDropData(ostd::BaseObject& data) { s_dragAndDropData = &data; s_hasDragAndDropData = true; }
|
inline static void setDragAndDropData(ostd::BaseObject& data) { s_dragAndDropData = &data; s_hasDragAndDropData = true; }
|
||||||
inline static void clearDragAndDropData(void) { s_dragAndDropData = nullptr; }
|
inline static void clearDragAndDropData(void) { s_dragAndDropData = nullptr; }
|
||||||
inline static ostd::BaseObject* getDragAndDropData(void) { return s_dragAndDropData; }
|
inline static ostd::BaseObject* getDragAndDropData(void) { return s_dragAndDropData; }
|
||||||
|
inline i32 getTabIndex(void) const { return m_tabIndex; }
|
||||||
inline WindowCore& getWindow(void) { return *m_window; }
|
inline WindowCore& getWindow(void) { return *m_window; }
|
||||||
inline Widget* getParent(void) { return m_parent; }
|
inline Widget* getParent(void) { return m_parent; }
|
||||||
inline const Widget* getParent(void) const { return m_parent; }
|
inline const Widget* getParent(void) const { return m_parent; }
|
||||||
inline i32 getZIndex(void) const { return m_zIndex; }
|
|
||||||
inline ogfx::MouseEventData::eButton getPressedMouseButton(void) const { return m_pressedButton; }
|
inline ogfx::MouseEventData::eButton getPressedMouseButton(void) const { return m_pressedButton; }
|
||||||
inline const stdvec<String>& getThemeIDList(void) const { return m_themeIDList; }
|
inline const stdvec<String>& getThemeIDList(void) const { return m_themeIDList; }
|
||||||
inline const ostd::Stylesheet::QualifierList& getThemeQualifierList(void) const { return m_qualifierList; }
|
inline const ostd::Stylesheet::QualifierList& getThemeQualifierList(void) const { return m_qualifierList; }
|
||||||
|
|
@ -172,7 +178,6 @@ namespace ogfx
|
||||||
OSTD_PARAM_GETSET(ostd::ColorGradient, BackgroundGradient, m_backgroundGradient);
|
OSTD_PARAM_GETSET(ostd::ColorGradient, BackgroundGradient, m_backgroundGradient);
|
||||||
OSTD_PARAM_GETSET(Rectangle, Padding, m_padding);
|
OSTD_PARAM_GETSET(Rectangle, Padding, m_padding);
|
||||||
OSTD_PARAM_GETSET(Rectangle, Margin, m_margin);
|
OSTD_PARAM_GETSET(Rectangle, Margin, m_margin);
|
||||||
OSTD_PARAM_GETSET(i32, TabIndex, m_tabIndex);
|
|
||||||
OSTD_PARAM_GETSET(Vec2, ContentOffset, m_contentOffset);
|
OSTD_PARAM_GETSET(Vec2, ContentOffset, m_contentOffset);
|
||||||
OSTD_PARAM_GETSET(String, TooltipText, m_tooltipText);
|
OSTD_PARAM_GETSET(String, TooltipText, m_tooltipText);
|
||||||
|
|
||||||
|
|
@ -236,7 +241,6 @@ namespace ogfx
|
||||||
bool m_rootChild { false };
|
bool m_rootChild { false };
|
||||||
bool m_focused { false };
|
bool m_focused { false };
|
||||||
i32 m_tabIndex { -1 };
|
i32 m_tabIndex { -1 };
|
||||||
i32 m_zIndex { -1 };
|
|
||||||
String m_tooltipText { "" };
|
String m_tooltipText { "" };
|
||||||
MouseEventData::eButton m_pressedButton { MouseEventData::eButton::None };
|
MouseEventData::eButton m_pressedButton { MouseEventData::eButton::None };
|
||||||
// ====================
|
// ====================
|
||||||
|
|
@ -313,6 +317,7 @@ namespace ogfx
|
||||||
static ostd::BaseObject* s_dragAndDropData;
|
static ostd::BaseObject* s_dragAndDropData;
|
||||||
static bool s_hasDragAndDropData;
|
static bool s_hasDragAndDropData;
|
||||||
friend class WidgetManager;
|
friend class WidgetManager;
|
||||||
|
friend class FocusManager;
|
||||||
// ====================
|
// ====================
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,13 +27,21 @@ namespace ogfx
|
||||||
{
|
{
|
||||||
m_animData = ad;
|
m_animData = ad;
|
||||||
m_spriteSheet = &spriteSheet;
|
m_spriteSheet = &spriteSheet;
|
||||||
m_timer.create(m_animData.fps, [&](f64 dt) -> void {
|
m_timer.startCount(ostd::eTimeUnits::Milliseconds);
|
||||||
update_animation();
|
|
||||||
});
|
|
||||||
update_animation();
|
update_animation();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Animation::update(void)
|
||||||
|
{
|
||||||
|
f64 dtms = (1.0 / cast<f64>(m_animData.fps)) * 1000.0;
|
||||||
|
if (m_timer.read() >= dtms)
|
||||||
|
{
|
||||||
|
update_animation();
|
||||||
|
m_timer.restart(ostd::eTimeUnits::Milliseconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Animation::resetAnimation(void)
|
void Animation::resetAnimation(void)
|
||||||
{
|
{
|
||||||
m_currentFrame = 0;
|
m_currentFrame = 0;
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,9 @@ namespace ogfx
|
||||||
inline Animation(const AnimationData& ad) { create(ad); };
|
inline Animation(const AnimationData& ad) { create(ad); };
|
||||||
inline Animation(const AnimationData& ad, Image& spriteSheet) { create(ad, spriteSheet); };
|
inline Animation(const AnimationData& ad, Image& spriteSheet) { create(ad, spriteSheet); };
|
||||||
inline Animation& create(const AnimationData& ad) { return create(ad, InvalidImage); }
|
inline Animation& create(const AnimationData& ad) { return create(ad, InvalidImage); }
|
||||||
inline void update(void) { m_timer.update(); }
|
|
||||||
inline i32 getCurrentFrame(void) const { return m_currentFrame; }
|
inline i32 getCurrentFrame(void) const { return m_currentFrame; }
|
||||||
Animation& create(const AnimationData& ad, Image& spriteSheet);
|
Animation& create(const AnimationData& ad, Image& spriteSheet);
|
||||||
|
void update(void);
|
||||||
void resetAnimation(void);
|
void resetAnimation(void);
|
||||||
|
|
||||||
inline void setFrameCount(i32 n) { m_animData.frameCount = n; }
|
inline void setFrameCount(i32 n) { m_animData.frameCount = n; }
|
||||||
|
|
@ -88,7 +88,7 @@ namespace ogfx
|
||||||
private:
|
private:
|
||||||
inline static Image InvalidImage;
|
inline static Image InvalidImage;
|
||||||
AnimationData m_animData;
|
AnimationData m_animData;
|
||||||
ostd::StepTimer m_timer;
|
ostd::Counter m_timer;
|
||||||
Image* m_spriteSheet { nullptr };
|
Image* m_spriteSheet { nullptr };
|
||||||
i32 m_currentFrame { 0 };
|
i32 m_currentFrame { 0 };
|
||||||
bool m_back { false };
|
bool m_back { false };
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,19 @@ using stdvec = std::vector<T>;
|
||||||
template<typename Key, typename Value>
|
template<typename Key, typename Value>
|
||||||
using stdumap = std::unordered_map<Key, Value>;
|
using stdumap = std::unordered_map<Key, Value>;
|
||||||
|
|
||||||
|
using i8Range = std::numeric_limits<i8>;
|
||||||
|
using i16Range = std::numeric_limits<i16>;
|
||||||
|
using i32Range = std::numeric_limits<i32>;
|
||||||
|
using i64Range = std::numeric_limits<i64>;
|
||||||
|
|
||||||
|
using u8Range = std::numeric_limits<u8>;
|
||||||
|
using u16Range = std::numeric_limits<u16>;
|
||||||
|
using u32Range = std::numeric_limits<u32>;
|
||||||
|
using u64Range = std::numeric_limits<u64>;
|
||||||
|
|
||||||
|
using f32Range = std::numeric_limits<f32>;
|
||||||
|
using f64Range = std::numeric_limits<f64>;
|
||||||
|
|
||||||
#define cast static_cast
|
#define cast static_cast
|
||||||
|
|
||||||
namespace ostd
|
namespace ostd
|
||||||
|
|
|
||||||
|
|
@ -412,7 +412,7 @@ namespace ostd
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
u64 Timer::start(bool print, const String& name, eTimeUnits timeUnit, OutputHandlerBase* __destination)
|
u64 Counter::start(bool print, const String& name, eTimeUnits timeUnit, OutputHandlerBase* __destination)
|
||||||
{
|
{
|
||||||
m_timeUnit = timeUnit;
|
m_timeUnit = timeUnit;
|
||||||
m_started = true;
|
m_started = true;
|
||||||
|
|
@ -459,7 +459,7 @@ namespace ostd
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 Timer::startCount(eTimeUnits timeUnit)
|
u64 Counter::startCount(eTimeUnits timeUnit)
|
||||||
{
|
{
|
||||||
m_timeUnit = timeUnit;
|
m_timeUnit = timeUnit;
|
||||||
m_started = true;
|
m_started = true;
|
||||||
|
|
@ -483,7 +483,7 @@ namespace ostd
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 Timer::end(bool print)
|
u64 Counter::end(bool print)
|
||||||
{
|
{
|
||||||
if (!m_started) return 0;
|
if (!m_started) return 0;
|
||||||
m_started = false;
|
m_started = false;
|
||||||
|
|
@ -537,7 +537,7 @@ namespace ostd
|
||||||
return diff;
|
return diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 Timer::endCount(bool stop)
|
u64 Counter::endCount(bool stop)
|
||||||
{
|
{
|
||||||
if (!m_started) return 0;
|
if (!m_started) return 0;
|
||||||
m_started = !stop;
|
m_started = !stop;
|
||||||
|
|
@ -562,7 +562,7 @@ namespace ostd
|
||||||
return diff;
|
return diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 Timer::restart(eTimeUnits timeUnit)
|
u64 Counter::restart(eTimeUnits timeUnit)
|
||||||
{
|
{
|
||||||
if (!m_started)
|
if (!m_started)
|
||||||
{
|
{
|
||||||
|
|
@ -574,7 +574,7 @@ namespace ostd
|
||||||
return elapsed;
|
return elapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 Timer::getEpoch(eTimeUnits timeUnit)
|
u64 Counter::getEpoch(eTimeUnits timeUnit)
|
||||||
{
|
{
|
||||||
switch (timeUnit)
|
switch (timeUnit)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -59,11 +59,11 @@ namespace ostd
|
||||||
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
class _Counter
|
class _BasicCounter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline _Counter(void) { m_count = 200; m_current = 0; }
|
inline _BasicCounter(void) { m_count = 200; m_current = 0; }
|
||||||
inline _Counter(T count, T step = 1) { m_count = count; m_current = 0; m_step = step; }
|
inline _BasicCounter(T count, T step = 1) { m_count = count; m_current = 0; m_step = step; }
|
||||||
inline void setCount(T count) { m_count = count; m_counting = false; m_current = 0; }
|
inline void setCount(T count) { m_count = count; m_counting = false; m_current = 0; }
|
||||||
inline T getCount(void) { return m_count; }
|
inline T getCount(void) { return m_count; }
|
||||||
inline T getCurrent(void) { return m_current; };
|
inline T getCurrent(void) { return m_current; };
|
||||||
|
|
@ -87,15 +87,15 @@ namespace ostd
|
||||||
bool m_counting { false };
|
bool m_counting { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef _Counter<u64> Counter;
|
typedef _BasicCounter<u64> BasicCounter;
|
||||||
typedef _Counter<f32> FloatCounter;
|
typedef _BasicCounter<f32> BasicFloatCounter;
|
||||||
typedef _Counter<f64> DoubleCounter;
|
typedef _BasicCounter<f64> BasicDoubleCounter;
|
||||||
|
|
||||||
class OutputHandlerBase;
|
class OutputHandlerBase;
|
||||||
class Timer
|
class Counter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline Timer(void) { m_started = false; m_current = 0; m_timeUnit = eTimeUnits::Nanoseconds; m_dest = nullptr; }
|
inline Counter(void) { m_started = false; m_current = 0; m_timeUnit = eTimeUnits::Nanoseconds; m_dest = nullptr; }
|
||||||
u64 start(bool print = true, const String& name = "", eTimeUnits timeUnit = eTimeUnits::Nanoseconds, OutputHandlerBase* __destination = nullptr);
|
u64 start(bool print = true, const String& name = "", eTimeUnits timeUnit = eTimeUnits::Nanoseconds, OutputHandlerBase* __destination = nullptr);
|
||||||
u64 startCount(eTimeUnits timeUnit = eTimeUnits::Nanoseconds);
|
u64 startCount(eTimeUnits timeUnit = eTimeUnits::Nanoseconds);
|
||||||
u64 end(bool print = true);
|
u64 end(bool print = true);
|
||||||
|
|
@ -172,7 +172,7 @@ namespace ostd
|
||||||
u16 years;
|
u16 years;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Timer m_rtClock;
|
Counter m_rtClock;
|
||||||
f32 m_timeOfDay;
|
f32 m_timeOfDay;
|
||||||
f32 m_totalSeconds;
|
f32 m_totalSeconds;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -100,9 +100,11 @@ class TestWindow : public Window
|
||||||
m_btn1.setCallback(Widget::eCallback::ActionPerformed, [&](const Event& event) -> void {
|
m_btn1.setCallback(Widget::eCallback::ActionPerformed, [&](const Event& event) -> void {
|
||||||
std::cout << showOpenFileDialog(filters) << "\n";
|
std::cout << showOpenFileDialog(filters) << "\n";
|
||||||
});
|
});
|
||||||
|
m_btn1.setTabIndex(1);
|
||||||
|
|
||||||
m_check1.setText("Check this out!");
|
m_check1.setText("Check this out!");
|
||||||
m_check1.setChecked(true);
|
m_check1.setChecked(true);
|
||||||
|
m_check1.setTabIndex(2);
|
||||||
m_check1.setStateChangedCallback([&](CheckBox& sender, bool state) -> void {
|
m_check1.setStateChangedCallback([&](CheckBox& sender, bool state) -> void {
|
||||||
m_panel1.setVisible(state);
|
m_panel1.setVisible(state);
|
||||||
});
|
});
|
||||||
|
|
@ -195,12 +197,13 @@ class TestWindow : public Window
|
||||||
// });
|
// });
|
||||||
m_list.collapseAll();
|
m_list.collapseAll();
|
||||||
|
|
||||||
for (i32 i = 0; i < 20; i++)
|
for (i32 i = 0; i < 17; i++)
|
||||||
{
|
{
|
||||||
auto icon = l_randomIcon(iconsAD);
|
auto icon = l_randomIcon(iconsAD);
|
||||||
auto& btn = getToolBar().addButton("./icons.png");
|
auto& btn = getToolBar().addButton("./icons.png");
|
||||||
btn.enableAnimated();
|
btn.enableAnimated();
|
||||||
btn.setAnimationData(icon);
|
btn.setAnimationData(icon);
|
||||||
|
btn.setTabIndex(i + 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_tabs.setSize(900, 700);
|
m_tabs.setSize(900, 700);
|
||||||
|
|
@ -210,9 +213,12 @@ class TestWindow : public Window
|
||||||
auto& t3 = m_tabs.addTab("Long Tab Test");
|
auto& t3 = m_tabs.addTab("Long Tab Test");
|
||||||
|
|
||||||
t1.addWidget(m_check1, { 30, 30 });
|
t1.addWidget(m_check1, { 30, 30 });
|
||||||
m_radioGroup.addButton(t1, "Radio this out!", { 30, 80 });
|
auto& rb1 = m_radioGroup.addButton(t1, "Radio this out!", { 30, 80 });
|
||||||
m_radioGroup.addButton(t1, "Radio Opt. 2", { 30, 110 });
|
rb1.setTabIndex(3);
|
||||||
m_radioGroup.addButton(t1, "Radio 3", { 30, 140 });
|
auto& rb2 = m_radioGroup.addButton(t1, "Radio Opt. 2", { 30, 110 });
|
||||||
|
rb2.setTabIndex(4);
|
||||||
|
auto& rb3 = m_radioGroup.addButton(t1, "Radio 3", { 30, 140 });
|
||||||
|
rb3.setTabIndex(5);
|
||||||
m_radioGroup.setSelectionChangedCallback([&](RadioButton& previous, RadioButton& sender) -> void {
|
m_radioGroup.setSelectionChangedCallback([&](RadioButton& previous, RadioButton& sender) -> void {
|
||||||
std::cout << previous.getText() << "\n";
|
std::cout << previous.getText() << "\n";
|
||||||
std::cout << sender.getText() << "\n\n";
|
std::cout << sender.getText() << "\n\n";
|
||||||
|
|
@ -492,7 +498,7 @@ i32 main(i32 argc, char** argv)
|
||||||
ostd::Random::autoSeed();
|
ostd::Random::autoSeed();
|
||||||
ostd::initialize();
|
ostd::initialize();
|
||||||
TestWindow window;
|
TestWindow window;
|
||||||
window.initialize(1200, 1100, "OmniaFramework - Test Window");
|
window.initialize(1200, 900, "OmniaFramework - Test Window");
|
||||||
window.setClearColor({ 0, 0, 0 });
|
window.setClearColor({ 0, 0, 0 });
|
||||||
window.setPosition({ 50, 50 });
|
window.setPosition({ 50, 50 });
|
||||||
// window.setWindowState(ogfx::WindowCore::eWindowState::Maximized);
|
// window.setWindowState(ogfx::WindowCore::eWindowState::Maximized);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue