Added caching for string dimensions in BasicRenderer2D
This commit is contained in:
parent
012f26f5f5
commit
424574a2e6
27 changed files with 143 additions and 61 deletions
|
|
@ -28,6 +28,7 @@
|
|||
***FIX: ToolBar::AddButton not consistent order
|
||||
***FIX: KeyPress crash on TreeView
|
||||
***FIX: Animated icons not working in TreeView
|
||||
***Check if possible, then change all WindowCore& refs to Window&
|
||||
Implement cursors in Stylesheet
|
||||
FIX: Window getting exponentially bigger when Desktop scale changes
|
||||
FIX: Refreshing scroll when content extent changes
|
||||
|
|
@ -55,7 +56,6 @@ FIX: ContextMenu rendering partly outside the screen when showing it close to th
|
|||
Add ToolBar::addButton overload that takes a ogfx::Icon wrapper
|
||||
Redesign theme overrides to be more robust
|
||||
Add modifiers to Event.keyboard path
|
||||
Check if possible, then change all WindowCore& refs to Window&
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -304,7 +304,7 @@ namespace ogfx
|
|||
push_panel(m_data.entries, pos, false);
|
||||
m_visible = true;
|
||||
m_animClock.startCount(ostd::eTimeUnits::Milliseconds);
|
||||
cast<Window&>(m_window).getFocusManager().clearFocus();
|
||||
m_window.getFocusManager().clearFocus();
|
||||
}
|
||||
|
||||
void ContextMenu::hide(void)
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ namespace ogfx
|
|||
f32 animProgress { 0 }; // 0.0 = collapsed, 1.0 = fully open
|
||||
};
|
||||
public:
|
||||
inline ContextMenu(WindowCore& window) : m_window(window) { create(); }
|
||||
inline ContextMenu(Window& window) : m_window(window) { create(); }
|
||||
ContextMenu& create(void);
|
||||
void applyTheme(const ostd::Stylesheet& theme);
|
||||
void draw(BasicRenderer2D& gfx);
|
||||
|
|
@ -155,7 +155,7 @@ namespace ogfx
|
|||
void relayout_panels(void);
|
||||
|
||||
private:
|
||||
WindowCore& m_window;
|
||||
Window& m_window;
|
||||
bool m_visible { false };
|
||||
Instance m_data;
|
||||
f32 m_entryHeight { 0 };
|
||||
|
|
|
|||
|
|
@ -138,17 +138,24 @@ namespace ogfx
|
|||
|
||||
void FocusManager::clearFocus(void)
|
||||
{
|
||||
if (m_focused)
|
||||
{
|
||||
m_focused->m_focused = false;
|
||||
m_focused = nullptr;
|
||||
}
|
||||
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();
|
||||
else if (event.keyboard->keyCode == KeyCode::Space || event.keyboard->keyCode == KeyCode::Return || event.keyboard->keyCode == KeyCode::Return2 || event.keyboard->keyCode == KeyCode::KpEnter)
|
||||
{
|
||||
if (!m_focused)
|
||||
return;
|
||||
if (m_focused->callback_onActionPerformed)
|
||||
m_focused->callback_onActionPerformed(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ namespace ogfx
|
|||
setRootChild();
|
||||
setStylesheetCategoryName("toolbar");
|
||||
setTypeName("ogfx::gui::ToolBar");
|
||||
auto& win = cast<Window&>(getWindow());
|
||||
auto& win = getWindow();
|
||||
w = win.getWindowWidth();
|
||||
h = m_height;
|
||||
disableBorder();
|
||||
|
|
@ -69,7 +69,7 @@ namespace ogfx
|
|||
|
||||
void ToolBar::onWindowResized(const Event& event)
|
||||
{
|
||||
auto& win = cast<Window&>(getWindow());
|
||||
auto& win = getWindow();
|
||||
w = win.getWindowWidth();
|
||||
h = m_height;
|
||||
f32 offset_y = 0;
|
||||
|
|
@ -82,7 +82,7 @@ namespace ogfx
|
|||
|
||||
void ToolBar::applyTheme(const ostd::Stylesheet& theme)
|
||||
{
|
||||
auto& win = cast<Window&>(getWindow());
|
||||
auto& win = getWindow();
|
||||
setHeight(getThemeValue<f32>(theme, "height", getHeight()));
|
||||
setSize(win.getWindowWidth(), m_height);
|
||||
enableBottomBorder(isBorderEnabled());
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ namespace ogfx
|
|||
{
|
||||
namespace gui
|
||||
{
|
||||
WidgetManager::WidgetManager(WindowCore& window, Widget& owner) : m_window(window), m_owner(owner)
|
||||
WidgetManager::WidgetManager(Window& window, Widget& owner) : m_window(window), m_owner(owner)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
|
@ -101,7 +101,7 @@ namespace ogfx
|
|||
if (!w->contains(event.mouse->position_x, event.mouse->position_y, true))
|
||||
continue;
|
||||
event.mouse->mousePressedOnWidget = w;
|
||||
cast<Window&>(m_window).getFocusManager().requestFocus(*w);
|
||||
m_window.getFocusManager().requestFocus(*w);
|
||||
w->__onMousePressed(event);
|
||||
m_mousePressedOnWidget = w;
|
||||
if (event.isHandled() || w->m_stopEvents)
|
||||
|
|
@ -219,14 +219,14 @@ namespace ogfx
|
|||
|
||||
void WidgetManager::onKeyPressed(const Event& event)
|
||||
{
|
||||
auto focused = cast<Window&>(m_window).getFocusManager().getFocused();
|
||||
auto focused = m_window.getFocusManager().getFocused();
|
||||
if (!focused || !focused->isVisible()) return;
|
||||
focused->__onKeyPressed(event);
|
||||
}
|
||||
|
||||
void WidgetManager::onKeyReleased(const Event& event)
|
||||
{
|
||||
auto focus = cast<Window&>(m_window).getFocusManager();
|
||||
auto focus = m_window.getFocusManager();
|
||||
auto focused = focus.getFocused();
|
||||
if (!focused || !focused->isVisible()) return;
|
||||
focused->__onKeyReleased(event);
|
||||
|
|
@ -234,7 +234,7 @@ namespace ogfx
|
|||
|
||||
void WidgetManager::onTextEntered(const Event& event)
|
||||
{
|
||||
auto focused = cast<Window&>(m_window).getFocusManager().getFocused();
|
||||
auto focused = m_window.getFocusManager().getFocused();
|
||||
if (!focused || !focused->isVisible()) return;
|
||||
focused->__onTextEntered(event);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,15 +29,15 @@ namespace ostd
|
|||
namespace ogfx
|
||||
{
|
||||
class BasicRenderer2D;
|
||||
class WindowCore;
|
||||
namespace gui
|
||||
{
|
||||
class Event;
|
||||
class Widget;
|
||||
class Window;
|
||||
class WidgetManager
|
||||
{
|
||||
public:
|
||||
WidgetManager(WindowCore& window, Widget& owner);
|
||||
WidgetManager(Window& window, Widget& owner);
|
||||
bool hasWidget(Widget& widget);
|
||||
bool addWidget(Widget& widget);
|
||||
bool removeWidget(Widget& widget);
|
||||
|
|
@ -59,14 +59,14 @@ namespace ogfx
|
|||
void onWindowFocusLost(const Event& event);
|
||||
|
||||
inline i32 widgetCount(void) const { return m_widgetList.size(); }
|
||||
inline WindowCore& getWindow(void) { return m_window; }
|
||||
inline Window& getWindow(void) { return m_window; }
|
||||
inline const stdvec<Widget*>& getWidgets(void) const { return m_widgetList; }
|
||||
|
||||
private:
|
||||
void processDragAndDrop(Widget* widget, const Event& event);
|
||||
|
||||
private:
|
||||
WindowCore& m_window;
|
||||
Window& m_window;
|
||||
Widget& m_owner;
|
||||
stdvec<Widget*> m_widgetList;
|
||||
Widget* m_mousePressedOnWidget { nullptr };
|
||||
|
|
|
|||
|
|
@ -56,8 +56,8 @@ namespace ogfx
|
|||
class Button : public Widget
|
||||
{
|
||||
public:
|
||||
inline Button(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(""); }
|
||||
inline Button(WindowCore& window, const String& text) : Widget({ 0, 0, 0, 0 }, window) { create(text); }
|
||||
inline Button(Window& window) : Widget({ 0, 0, 0, 0 }, window) { create(""); }
|
||||
inline Button(Window& window, const String& text) : Widget({ 0, 0, 0, 0 }, window) { create(text); }
|
||||
Button& create(const String& text);
|
||||
|
||||
void onDraw(ogfx::BasicRenderer2D& gfx) override;
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ namespace ogfx
|
|||
class CheckBox : public Widget
|
||||
{
|
||||
public:
|
||||
inline CheckBox(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(""); }
|
||||
inline CheckBox(WindowCore& window, const String& text) : Widget({ 0, 0, 0, 0 }, window) { create(text); }
|
||||
inline CheckBox(Window& window) : Widget({ 0, 0, 0, 0 }, window) { create(""); }
|
||||
inline CheckBox(Window& window, const String& text) : Widget({ 0, 0, 0, 0 }, window) { create(text); }
|
||||
CheckBox& create(const String& text);
|
||||
void applyTheme(const ostd::Stylesheet& theme) override;
|
||||
void onDraw(ogfx::BasicRenderer2D& gfx) override;
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ namespace ogfx
|
|||
setThemeQualifier("active", true);
|
||||
m_dropDownShown = true;
|
||||
Vec2 anchor = getGlobalPosition() + Vec2 { 0, geth() };
|
||||
cast<Window&>(getWindow()).showContextMenu(m_menu, anchor);
|
||||
getWindow().showContextMenu(m_menu, anchor);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ namespace ogfx
|
|||
class ComboBox : public Widget
|
||||
{
|
||||
public:
|
||||
inline ComboBox(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(); }
|
||||
inline ComboBox(Window& window) : Widget({ 0, 0, 0, 0 }, window) { create(); }
|
||||
ComboBox& create(void);
|
||||
i32 addMenuItem(const String& text);
|
||||
bool removeMenuItem(const String& text);
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ namespace ogfx
|
|||
m_titlebarHeight = getThemeValue<f32>(theme, "titlebarHeight", 30);
|
||||
m_titlebarBorderWidth = getThemeValue<i32>(theme, "titlebarBorderWidth", 1);
|
||||
m_titlebarFontSize = getThemeValue<i32>(theme, "titlebarFontSize", 26);
|
||||
m_titleTextAlign = getThemeValue<i32>(theme, "titlebarTextAlign", cast<i32>(WindowCore::eTextAlign::Left));
|
||||
m_titleTextAlign = getThemeValue<i32>(theme, "titlebarTextAlign", cast<i32>(Window::eTextAlign::Left));
|
||||
setTitlebarType(getThemeValue<String>(theme, "titlebarType", TitleBarTypes::None));
|
||||
}
|
||||
|
||||
|
|
@ -137,7 +137,7 @@ namespace ogfx
|
|||
{
|
||||
gfx.outlinedRoundRect(titleBarBounds, m_titlebarColor, m_titlebarColor, { cast<f32>(getBorderRadius()), cast<f32>(getBorderRadius()), 0, 0 }, getBorderWidth());
|
||||
gfx.drawLine({ getGlobalPosition() + Vec2 { 0, m_titlebarHeight - 2 }, getGlobalPosition() + Vec2 { getGlobalBounds().w, m_titlebarHeight - 2 } }, m_titlebarBorderColor, m_titlebarBorderWidth);
|
||||
if (m_titleTextAlign == cast<i32>(WindowCore::eTextAlign::Center))
|
||||
if (m_titleTextAlign == cast<i32>(Window::eTextAlign::Center))
|
||||
gfx.drawCenteredString(m_title, titleBarBounds, m_titleColor, m_titlebarFontSize);
|
||||
else
|
||||
gfx.drawString(m_title, titleBarBounds.getPosition() + Vec2 { 10, 5 }, m_titleColor, m_titlebarFontSize);
|
||||
|
|
@ -145,7 +145,7 @@ namespace ogfx
|
|||
}
|
||||
case TitleBarTypes::MinimalValue:
|
||||
{
|
||||
if (m_titleTextAlign == cast<i32>(WindowCore::eTextAlign::Center))
|
||||
if (m_titleTextAlign == cast<i32>(Window::eTextAlign::Center))
|
||||
gfx.drawCenteredString(m_title, titleBarBounds, m_titleColor, m_titlebarFontSize);
|
||||
else
|
||||
gfx.drawString(m_title, titleBarBounds.getPosition() + Vec2 { 10, 5 }, m_titleColor, m_titlebarFontSize);
|
||||
|
|
@ -268,6 +268,8 @@ namespace ogfx
|
|||
auto it = std::find_if(m_tabs.begin(), m_tabs.end(), [&](const std::unique_ptr<Panel>& p) { return p->getTitle() == title; });
|
||||
if (it == m_tabs.end())
|
||||
return false;
|
||||
if (m_currentTab == it->get())
|
||||
prepare_for_current_tab_removal();
|
||||
m_tabs.erase(it);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -289,6 +291,7 @@ namespace ogfx
|
|||
auto curr = m_tabs[index].get();
|
||||
if (!ignore_same_tab && curr == m_currentTab && m_currentTab != nullptr)
|
||||
return false;
|
||||
getWindow().getFocusManager().clearFocus();
|
||||
removeWidget(*m_currentTab);
|
||||
m_currentTabIndex = index;
|
||||
m_currentTab = curr;
|
||||
|
|
@ -320,6 +323,7 @@ namespace ogfx
|
|||
return;
|
||||
if (m_tabs.size() < 2)
|
||||
{
|
||||
getWindow().getFocusManager().clearFocus();
|
||||
m_currentTab = nullptr;
|
||||
return;
|
||||
}
|
||||
|
|
@ -328,6 +332,8 @@ namespace ogfx
|
|||
if (it == m_tabs.end())
|
||||
return; // shouldn't happen but defensive
|
||||
|
||||
getWindow().getFocusManager().clearFocus();
|
||||
|
||||
if (it != m_tabs.begin())
|
||||
m_currentTab = (it - 1)->get(); // tab to the left
|
||||
else
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ namespace ogfx
|
|||
inline static constexpr i32 MinimalValue = 2;
|
||||
};
|
||||
public:
|
||||
inline Panel(WindowCore& window) : ScrollableWidget(window) { create(); }
|
||||
inline Panel(Window& window) : ScrollableWidget(window) { create(); }
|
||||
Panel& create(void);
|
||||
void applyTheme(const ostd::Stylesheet& theme) override;
|
||||
void afterDraw(ogfx::BasicRenderer2D& gfx) override;
|
||||
|
|
@ -78,7 +78,7 @@ namespace ogfx
|
|||
class TabPanel : public Widget
|
||||
{
|
||||
public:
|
||||
inline TabPanel(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(); }
|
||||
inline TabPanel(Window& window) : Widget({ 0, 0, 0, 0 }, window) { create(); }
|
||||
TabPanel& create(void);
|
||||
void applyTheme(const ostd::Stylesheet& theme) override;
|
||||
void onMousePressed(const Event& event) override;
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ namespace ogfx
|
|||
class Label : public Widget
|
||||
{
|
||||
public:
|
||||
inline Label(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(""); }
|
||||
inline Label(WindowCore& window, const String& text) : Widget({ 0, 0, 0, 0 }, window) { create(text); }
|
||||
inline Label(Window& window) : Widget({ 0, 0, 0, 0 }, window) { create(""); }
|
||||
inline Label(Window& window, const String& text) : Widget({ 0, 0, 0, 0 }, window) { create(text); }
|
||||
Label& create(const String& text);
|
||||
|
||||
void onDraw(ogfx::BasicRenderer2D& gfx) override;
|
||||
|
|
@ -94,8 +94,8 @@ namespace ogfx
|
|||
class ImageLabel : public Widget
|
||||
{
|
||||
public:
|
||||
inline ImageLabel(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(""); }
|
||||
inline ImageLabel(WindowCore& window, const String& filePath) : Widget({ 0, 0, 0, 0 }, window) { create(filePath); }
|
||||
inline ImageLabel(Window& window) : Widget({ 0, 0, 0, 0 }, window) { create(""); }
|
||||
inline ImageLabel(Window& window, const String& filePath) : Widget({ 0, 0, 0, 0 }, window) { create(filePath); }
|
||||
ImageLabel& create(const String& filePath);
|
||||
|
||||
void applyTheme(const ostd::Stylesheet& theme) override;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ namespace ogfx
|
|||
class ProgressBar : public Widget
|
||||
{
|
||||
public:
|
||||
inline ProgressBar(WindowCore& window, f32 min = 0.0f, f32 max = 1.0f, f32 start = 0.0f) : Widget({ 0, 0, 0, 0 }, window), m_progress(std::clamp(start, min, max)), m_min(min), m_max(max) { create(); }
|
||||
inline ProgressBar(Window& window, f32 min = 0.0f, f32 max = 1.0f, f32 start = 0.0f) : Widget({ 0, 0, 0, 0 }, window), m_progress(std::clamp(start, min, max)), m_min(min), m_max(max) { create(); }
|
||||
ProgressBar& create(void);
|
||||
void applyTheme(const ostd::Stylesheet& theme) override;
|
||||
void onDraw(ogfx::BasicRenderer2D& gfx) override;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ namespace ogfx
|
|||
OSTD_PARAM_GETSET(Color, OuterCircleColor, m_outerCircleColor);
|
||||
|
||||
private:
|
||||
inline RadioButton(WindowCore& window, RadioButtonGroup& group, const String& text) : Widget({ 0, 0, 0, 0 }, window) { create(group, text); }
|
||||
inline RadioButton(Window& window, RadioButtonGroup& group, const String& text) : Widget({ 0, 0, 0, 0 }, window) { create(group, text); }
|
||||
RadioButton& create(RadioButtonGroup& group, const String& text);
|
||||
void __update_size(ogfx::BasicRenderer2D& gfx);
|
||||
void __set_selected(bool selected);
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ namespace ogfx
|
|||
{
|
||||
namespace gui
|
||||
{
|
||||
RootWidget::RootWidget(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window)
|
||||
RootWidget::RootWidget(Window& window) : Widget({ 0, 0, 0, 0 }, window)
|
||||
{
|
||||
setRootChild();
|
||||
disableFocus();
|
||||
|
|
@ -37,7 +37,7 @@ namespace ogfx
|
|||
|
||||
void RootWidget::onWindowResized(const Event& event)
|
||||
{
|
||||
Window& win = cast<Window&>(getWindow()); //TODO: Potentially unsage?
|
||||
Window& win = getWindow();
|
||||
f32 offset_y = 0;
|
||||
if (win.m_menubar.isVisible())
|
||||
offset_y += win.m_menubar.geth();
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ namespace ogfx
|
|||
class RootWidget : public Widget
|
||||
{
|
||||
public:
|
||||
RootWidget(WindowCore& window);
|
||||
RootWidget(Window& window);
|
||||
void onWindowResized(const Event& event) override;
|
||||
void applyTheme(const ostd::Stylesheet& theme) override;
|
||||
void onDraw(ogfx::BasicRenderer2D& gfx) override;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ namespace ogfx
|
|||
class VerticalScrollBar : public Widget
|
||||
{
|
||||
public:
|
||||
inline VerticalScrollBar(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(); }
|
||||
inline VerticalScrollBar(Window& window) : Widget({ 0, 0, 0, 0 }, window) { create(); }
|
||||
VerticalScrollBar& create(void);
|
||||
void applyTheme(const ostd::Stylesheet& theme) override;
|
||||
void afterDraw(ogfx::BasicRenderer2D& gfx) override;
|
||||
|
|
@ -68,7 +68,7 @@ namespace ogfx
|
|||
class HorizontalScrollbar : public Widget
|
||||
{
|
||||
public:
|
||||
inline HorizontalScrollbar(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(); }
|
||||
inline HorizontalScrollbar(Window& window) : Widget({ 0, 0, 0, 0 }, window) { create(); }
|
||||
HorizontalScrollbar& create(void);
|
||||
void applyTheme(const ostd::Stylesheet& theme) override;
|
||||
void afterDraw(ogfx::BasicRenderer2D& gfx) override;
|
||||
|
|
@ -106,7 +106,7 @@ namespace ogfx
|
|||
class ScrollableWidget : public Widget
|
||||
{
|
||||
public:
|
||||
inline ScrollableWidget(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(); }
|
||||
inline ScrollableWidget(Window& window) : Widget({ 0, 0, 0, 0 }, window) { create(); }
|
||||
ScrollableWidget& create(void);
|
||||
virtual void onUpdate(void) override;
|
||||
void drawScrollbars(ogfx::BasicRenderer2D& gfx);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ namespace ogfx
|
|||
class Slider : public Widget
|
||||
{
|
||||
public:
|
||||
inline Slider(WindowCore& window, bool vertical = false, f32 min = 0.0f, f32 max = 1.0f, f32 step = 0.1f) : Widget({ 0, 0, 0, 0 }, window) { create(vertical, min, max, step); }
|
||||
inline Slider(Window& window, bool vertical = false, f32 min = 0.0f, f32 max = 1.0f, f32 step = 0.1f) : Widget({ 0, 0, 0, 0 }, window) { create(vertical, min, max, step); }
|
||||
Slider& create(bool vertical, f32 min, f32 max, f32 step);
|
||||
void applyTheme(const ostd::Stylesheet& theme) override;
|
||||
void onMouseReleased(const Event& event) override;
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ namespace ogfx
|
|||
public:
|
||||
using ChevronDrawCallback = std::function<void(TreeView& sender, const Item& item, const Rectangle& bounds, BasicRenderer2D& gfx)>;
|
||||
|
||||
inline TreeView(WindowCore& window) : ScrollableWidget(window) { create(); }
|
||||
inline TreeView(Window& window) : ScrollableWidget(window) { create(); }
|
||||
TreeView& create(void);
|
||||
void applyTheme(const ostd::Stylesheet& theme) override;
|
||||
void onDraw(ogfx::BasicRenderer2D& gfx) override;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ namespace ogfx
|
|||
ostd::BaseObject* Widget::s_dragAndDropData { nullptr };
|
||||
bool Widget::s_hasDragAndDropData { false };
|
||||
|
||||
Widget::Widget(const Rectangle& bounds, WindowCore& window) : Rectangle(bounds), m_widgets(window, *this)
|
||||
Widget::Widget(const Rectangle& bounds, Window& window) : Rectangle(bounds), m_widgets(window, *this)
|
||||
{
|
||||
m_window = &window;
|
||||
}
|
||||
|
|
@ -39,8 +39,8 @@ namespace ogfx
|
|||
Widget::~Widget(void)
|
||||
{
|
||||
if (m_window && m_tabIndex >= 0)
|
||||
cast<Window&>(*m_window).getFocusManager().unregisterTabIndex(*this);
|
||||
auto& fm = cast<Window&>(*m_window).getFocusManager();
|
||||
m_window->getFocusManager().unregisterTabIndex(*this);
|
||||
auto& fm = m_window->getFocusManager();
|
||||
if (fm.getFocused() == this)
|
||||
fm.clearFocus(); // you'd add this method
|
||||
}
|
||||
|
|
@ -240,7 +240,7 @@ namespace ogfx
|
|||
|
||||
bool Widget::setTabIndex(i32 index)
|
||||
{
|
||||
if (cast<Window&>(getWindow()).getFocusManager().registerTabIndex(*this, index))
|
||||
if (getWindow().getFocusManager().registerTabIndex(*this, index))
|
||||
{
|
||||
m_tabIndex = index;
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ namespace ogfx
|
|||
{
|
||||
namespace gui
|
||||
{
|
||||
class Window;
|
||||
class Widget : public ostd::BaseObject, public Rectangle
|
||||
{
|
||||
private: struct ThemeOverride
|
||||
|
|
@ -65,7 +66,7 @@ namespace ogfx
|
|||
public: using EventCallback = std::function<void(const Event&)>;
|
||||
public:
|
||||
// ================================== MAIN =================================
|
||||
Widget(const Rectangle& bounds, WindowCore& window);
|
||||
Widget(const Rectangle& bounds, Window& window);
|
||||
Widget(Widget&&) = default;
|
||||
Widget& operator=(Widget&&) = delete;
|
||||
Widget(const Widget&) = delete;
|
||||
|
|
@ -161,7 +162,7 @@ namespace ogfx
|
|||
inline static void clearDragAndDropData(void) { s_dragAndDropData = nullptr; }
|
||||
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 Window& getWindow(void) { return *m_window; }
|
||||
inline Widget* getParent(void) { return m_parent; }
|
||||
inline const Widget* getParent(void) const { return m_parent; }
|
||||
inline ogfx::MouseEventData::eButton getPressedMouseButton(void) const { return m_pressedButton; }
|
||||
|
|
@ -235,7 +236,7 @@ namespace ogfx
|
|||
|
||||
private:
|
||||
// ======= CORE =======
|
||||
WindowCore* m_window { nullptr };
|
||||
Window* m_window { nullptr };
|
||||
Widget* m_parent { nullptr };
|
||||
WidgetManager m_widgets;
|
||||
std::unique_ptr<Layout> m_layout;
|
||||
|
|
|
|||
|
|
@ -232,28 +232,64 @@ namespace ogfx
|
|||
|
||||
Vec2 BasicRenderer2D::getStringDimensions(const String& message, i32 fontSize, TTF_Font* font)
|
||||
{
|
||||
if (!isValid()) return { 0, 0 };
|
||||
auto dimensions = getStringDimensionsPerCharacter(message, fontSize, font);
|
||||
if (dimensions.empty())
|
||||
return { 0, 0 };
|
||||
f32 totalWidth = 0;
|
||||
for (const auto& d : dimensions)
|
||||
totalWidth += d.x;
|
||||
return { totalWidth, dimensions[0].y };
|
||||
}
|
||||
|
||||
stdvec<Vec2> BasicRenderer2D::getStringDimensionsPerCharacter(const String& message, i32 fontSize, TTF_Font* font)
|
||||
{
|
||||
if (!isValid()) return { };
|
||||
if (fontSize <= 0) fontSize = m_fontSize;
|
||||
if (!font) font = m_font;
|
||||
|
||||
auto l_buildCacheKey = [&](void) -> String {
|
||||
return String("").add(message).add(fontSize).add(reinterpret_cast<uintptr_t>(font));
|
||||
};
|
||||
|
||||
String cacheKey = l_buildCacheKey();
|
||||
|
||||
auto it = m_strDimsCache.find(cacheKey);
|
||||
if (it != m_strDimsCache.end())
|
||||
{
|
||||
m_cacheHitCount++;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
i32 oldFontSize = getFontSize();
|
||||
setFontSize(fontSize);
|
||||
|
||||
auto glyphs = m_fontGlyphAtlas.processString(message, font, fontSize);
|
||||
if (glyphs.empty()) return { 0, 0 };
|
||||
if (glyphs.empty()) return { };
|
||||
|
||||
f32 totalWidth = 0;
|
||||
stdvec<Vec2> dimensions;
|
||||
dimensions.reserve(message.len());
|
||||
|
||||
f32 charWidth = 0;
|
||||
for (size_t i = 0; i < glyphs.size(); i++)
|
||||
{
|
||||
totalWidth += glyphs[i]->advance;
|
||||
charWidth += glyphs[i]->advance;
|
||||
if (i > 0)
|
||||
{
|
||||
i32 kern = 0;
|
||||
TTF_GetGlyphKerning(font, glyphs[i - 1]->codepoint, glyphs[i]->codepoint, &kern);
|
||||
totalWidth += kern;
|
||||
charWidth += kern;
|
||||
}
|
||||
dimensions.push_back({ charWidth, glyphs[0]->size.y });
|
||||
charWidth = 0;
|
||||
}
|
||||
setFontSize(oldFontSize);
|
||||
return { totalWidth, glyphs[0]->size.y };
|
||||
|
||||
if (m_strDimsCache.size() >= MaxStringDimsCacheSize)
|
||||
m_strDimsCache.pop_back();
|
||||
m_strDimsCache.insert(cacheKey, dimensions);
|
||||
|
||||
m_cacheMissCount++;
|
||||
return dimensions;
|
||||
}
|
||||
// ===================================================== UTILS =====================================================
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <ogfx/resources/Image.hpp>
|
||||
#include <ostd/io/IOHandlers.hpp>
|
||||
#include <ogfx/render/FontGlyphAtlas.hpp>
|
||||
#include <ostd/io/StaticHashMap.hpp>
|
||||
|
||||
namespace ogfx
|
||||
{
|
||||
|
|
@ -70,8 +71,11 @@ namespace ogfx
|
|||
i32 openFont(const ostd::UByte resource_data[], u32 data_size, i32 fontSize = 0);
|
||||
i32 setFontSize(i32 fontSize);
|
||||
Vec2 getStringDimensions(const String& message, i32 fontSize = 0, TTF_Font* font = nullptr);
|
||||
stdvec<Vec2> getStringDimensionsPerCharacter(const String& message, i32 fontSize = 0, TTF_Font* font = nullptr);
|
||||
|
||||
inline u32 getDrawCallCount(void) { return m_lastFrameDrawCallCount; }
|
||||
inline u32 getCacheHitCount(void) { return m_cacheHitCount; }
|
||||
inline u32 getCacheMissCount(void) { return m_cacheMissCount; }
|
||||
inline bool hasOpenFont(void) { return m_fontOpen; }
|
||||
inline TTF_Font* getSDLFont(void) { return m_font; }
|
||||
inline bool isValid(void) const { return m_initialized && m_fontOpen && (m_font != nullptr || m_fontFromMemory); }
|
||||
|
|
@ -164,6 +168,11 @@ namespace ogfx
|
|||
SDL_Texture* m_lastUsedGlyphAtlasTex { nullptr };
|
||||
SignalHandler m_sigHandler { *this };
|
||||
|
||||
ostd::StaticHashMap<String, stdvec<Vec2>> m_strDimsCache;
|
||||
i32 m_cacheHitCount { 0 };
|
||||
i32 m_cacheMissCount { 0 };
|
||||
|
||||
inline static constexpr i32 DefaultFontSize { 16 };
|
||||
inline static constexpr i32 MaxStringDimsCacheSize { 512 };
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -251,6 +251,17 @@ namespace ostd
|
|||
m_entries.pop_back();
|
||||
}
|
||||
|
||||
// Removes the first element
|
||||
void pop_front(void)
|
||||
{
|
||||
if (m_entries.empty()) return;
|
||||
m_index.erase(m_entries.front().first);
|
||||
m_entries.pop_front();
|
||||
// Rebuild all remaining indices (everything shifted by 1)
|
||||
for (i32 i = 0; i < size(); i++)
|
||||
m_index[m_entries[cast<u32>(i)].first] = i;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Removal
|
||||
// ============================================================
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
#include <ogfx/ogfx.hpp>
|
||||
#include <ostd/utils/Async.hpp>
|
||||
|
||||
ogfx::WindowCore::FileDialogFilterList filters = {
|
||||
ogfx::gui::Window::FileDialogFilterList filters = {
|
||||
{ "Image files", { "png", "jpg", "jpeg", "bmp" } },
|
||||
{ "All files", { "*" } }
|
||||
};
|
||||
|
|
@ -279,6 +279,14 @@ class TestWindow : public Window
|
|||
m_drawCallsLbl.addThemeOverride("@.label.padding", ostd::Rectangle { 10, 5, 0, 0 });
|
||||
getStatusBar().addWidget(m_drawCallsLbl, { 0, 0 });
|
||||
|
||||
m_cacheHitsLbl.addThemeOverride("@.label.fontSize", 20);
|
||||
m_cacheHitsLbl.addThemeOverride("@.label.padding", ostd::Rectangle { 10, 5, 0, 0 });
|
||||
getStatusBar().addWidget(m_cacheHitsLbl, { 200, 0 });
|
||||
|
||||
m_cacheMissesLbl.addThemeOverride("@.label.fontSize", 20);
|
||||
m_cacheMissesLbl.addThemeOverride("@.label.padding", ostd::Rectangle { 10, 5, 0, 0 });
|
||||
getStatusBar().addWidget(m_cacheMissesLbl, { 400, 0 });
|
||||
|
||||
m_progressJob.start([this] {
|
||||
while (true)
|
||||
{
|
||||
|
|
@ -352,6 +360,8 @@ class TestWindow : public Window
|
|||
{
|
||||
// gfx.fillRect(m_tabs.getGlobalPureContentBounds(), { 0, 255, 0, 100 });
|
||||
m_drawCallsLbl.setText(String("DrawCalls: ").add(gfx.getDrawCallCount()));
|
||||
m_cacheHitsLbl.setText(String("Cache Hits: ").add(gfx.getCacheHitCount()));
|
||||
m_cacheMissesLbl.setText(String("Cache Miss: ").add(gfx.getCacheMissCount()));
|
||||
}
|
||||
|
||||
void onFixedUpdate(void) override
|
||||
|
|
@ -377,6 +387,8 @@ class TestWindow : public Window
|
|||
Label m_slideLbl { *this };
|
||||
TreeView m_list { *this };
|
||||
Label m_drawCallsLbl { *this };
|
||||
Label m_cacheHitsLbl { *this };
|
||||
Label m_cacheMissesLbl { *this };
|
||||
ComboBox m_combo { *this };
|
||||
|
||||
enum MenuId : i32 { New = 1, Open, Save, SaveAs, Exit, CopyRaw, CopyFormatted };
|
||||
|
|
@ -501,7 +513,7 @@ i32 main(i32 argc, char** argv)
|
|||
window.initialize(1200, 900, "OmniaFramework - Test Window");
|
||||
window.setClearColor({ 0, 0, 0 });
|
||||
window.setPosition({ 50, 50 });
|
||||
// window.setWindowState(ogfx::WindowCore::eWindowState::Maximized);
|
||||
// window.setWindowState(ogfx::gui::Window::eWindowState::Maximized);
|
||||
window.mainLoop();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue