diff --git a/CMakeLists.txt b/CMakeLists.txt index e9f0852..acd06ea 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,6 +86,7 @@ list(APPEND OGFX_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/WidgetManager.cpp ${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/ContextMenu.cpp ${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/MenuBar.cpp + ${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/ToolBar.cpp # gui/widgets ${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/widgets/Widget.cpp diff --git a/extra/DefaultTheme.oss b/extra/DefaultTheme.oss index 02cc12b..1f479ed 100644 --- a/extra/DefaultTheme.oss +++ b/extra/DefaultTheme.oss @@ -308,3 +308,7 @@ const $accentColorDark = #6B0A1DFF borderColor = #400000FF } % ===================== +(@tool_button button) { + fontSize = 18 + padding = rect(10, 0, 10, 0) +} diff --git a/other/TODO.txt b/other/TODO.txt index b0e15aa..8591493 100644 --- a/other/TODO.txt +++ b/other/TODO.txt @@ -35,6 +35,8 @@ FIX: Optimize ListView FIX: Padding for ListView items Add icons to ListView FIX: Limit FPS even when continuous events happen +Add gradient to listbox selection +Add gradient to menubar background and selection diff --git a/src/ogfx/gui/MenuBar.cpp b/src/ogfx/gui/MenuBar.cpp index b47f503..d8504e5 100644 --- a/src/ogfx/gui/MenuBar.cpp +++ b/src/ogfx/gui/MenuBar.cpp @@ -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 . +*/ + #include "MenuBar.hpp" #include "../render/BasicRenderer.hpp" #include "Window.hpp" diff --git a/src/ogfx/gui/MenuBar.hpp b/src/ogfx/gui/MenuBar.hpp index af093c3..34d8fef 100644 --- a/src/ogfx/gui/MenuBar.hpp +++ b/src/ogfx/gui/MenuBar.hpp @@ -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 . +*/ + #pragma once #include diff --git a/src/ogfx/gui/ToolBar.cpp b/src/ogfx/gui/ToolBar.cpp new file mode 100644 index 0000000..84b466f --- /dev/null +++ b/src/ogfx/gui/ToolBar.cpp @@ -0,0 +1,102 @@ +/* + 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 . +*/ + +#include "ToolBar.hpp" +#include "../render/BasicRenderer.hpp" +#include "Window.hpp" + +namespace ogfx +{ + namespace gui + { + ToolBar::ToolBar(Window& window) : Widget({ 0, 0, 0, 0 }, window) + { + create(); + } + + ToolBar& ToolBar::create(void) + { + setRootChild(); + setStylesheetCategoryName("toolbar"); + setTypeName("ogfx::gui::widgets::ToolBar"); + auto& win = cast(getWindow()); + setSize(win.getWindowWidth(), m_height); + if (win.isMenuBarVisible()) + setPosition(0, win.getMenuBar().getHeight()); + else + setPosition(0, 0); + return *this; + } + + void ToolBar::onWindowResized(const Event& event) + { + auto& win = cast(getWindow()); + setSize(win.getWindowWidth(), m_height); + f32 offset_y = 0; + if (win.getMenuBar().isVisible()) + offset_y += win.getMenuBar().geth(); + sety(offset_y); + } + + void ToolBar::applyTheme(const ostd::Stylesheet& theme) + { + auto& win = cast(getWindow()); + setHeight(theme.get("toolbar.height", getHeight(), {}, {})); + setItemPadding(theme.get("toolbar.itemPadding", getItemPadding(), {}, {})); + setFontSize(theme.get("toolbar.fontSize", getFontSize(), {}, {})); + setBackgroundColor(theme.get("toolbar.backgroundColor", getBackgroundColor(), {}, {})); + setTextColor(theme.get("toolbar.textColor", getTextColor(), {}, {})); + setBorderColor(theme.get("toolbar.borderColor", getBorderColor(), {}, {})); + setSize(win.getWindowWidth(), m_height); + } + + void ToolBar::onDraw(BasicRenderer2D& gfx) + { + if (!m_visible) return; + + gfx.fillRect(*this, m_backgroundColor); + + // Bottom border line + gfx.drawLine({ { getx(), gety() + m_height }, { getx() + getw(), gety() + m_height } }, m_borderColor); + } + + void ToolBar::onUpdate(void) + { + if (!m_visible) return; + } + + void ToolBar::onMousePressed(const Event& event) + { + if (!m_visible) return; + + Vec2 mousePos { event.mouse->position_x, event.mouse->position_y }; + + // event.handle(); + } + + void ToolBar::onMouseMoved(const Event& event) + { + if (!m_visible) return; + + Vec2 mousePos { event.mouse->position_x, event.mouse->position_y }; + + } + } +} diff --git a/src/ogfx/gui/ToolBar.hpp b/src/ogfx/gui/ToolBar.hpp new file mode 100644 index 0000000..634c255 --- /dev/null +++ b/src/ogfx/gui/ToolBar.hpp @@ -0,0 +1,64 @@ +/* + 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 . +*/ + +#pragma once + +#include + +namespace ogfx +{ + namespace gui + { + class Window; + class ToolBar : public Widget + { + public: + ToolBar(Window& window); + ToolBar& create(void); + void onWindowResized(const Event& event) override; + void applyTheme(const ostd::Stylesheet& theme) override; + void onDraw(BasicRenderer2D& gfx) override; + void onUpdate(void) override; + void onMousePressed(const Event& event) override; + void onMouseMoved(const Event& event) override; + + inline bool isVisible(void) const { return m_visible; } + inline void show(bool v = true) { m_visible = v; } + inline void hide(void) { show(false); } + + OSTD_PARAM_GETSET(f32, Height, m_height); + OSTD_PARAM_GETSET(Rectangle, ItemPadding, m_itemPadding); + OSTD_PARAM_GETSET(i32, FontSize, m_fontSize); + OSTD_PARAM_GETSET(Color, BackgroundColor, m_backgroundColor); + OSTD_PARAM_GETSET(Color, TextColor, m_textColor); + OSTD_PARAM_GETSET(Color, BorderColor, m_borderColor); + + private: + bool m_visible { true }; + + f32 m_height { 26 }; + Rectangle m_itemPadding { 0, 0, 0, 0 }; + i32 m_fontSize { 16 }; + Color m_backgroundColor { "#6B0A1DFF" }; + Color m_textColor { "#F16A85FF" }; + Color m_borderColor { "#400000FF" }; + }; + } +} diff --git a/src/ogfx/gui/Window.cpp b/src/ogfx/gui/Window.cpp index 5599689..1637bc6 100644 --- a/src/ogfx/gui/Window.cpp +++ b/src/ogfx/gui/Window.cpp @@ -829,8 +829,11 @@ namespace ogfx m_guiTheme = &theme; m_rootWidget.__applyTheme(theme, true); m_rootWidget.reloadTheme(true); + m_toolbar.__applyTheme(theme, true); + m_toolbar.reloadTheme(true); m_cmenu.applyTheme(theme); m_menubar.applyTheme(theme); + m_toolbar.applyTheme(theme); } void Window::__on_window_init(i32 width, i32 height, const String& title) @@ -874,6 +877,8 @@ namespace ogfx onRedraw(m_gfx); if (m_menubar.isVisible()) m_menubar.draw(m_gfx); + m_toolbar.__update(); + m_toolbar.__draw(m_gfx); if (m_cmenu.isVisible()) { stopTooltipTimer(); @@ -900,11 +905,13 @@ namespace ogfx { evt.__original_signal_id = ostd::BuiltinSignals::WindowClosed; m_rootWidget.__onWindowClosed(evt); + m_toolbar.__onWindowClosed(evt); } else if (signal.ID == ostd::BuiltinSignals::WindowFocused) { evt.__original_signal_id = ostd::BuiltinSignals::WindowFocused; m_rootWidget.__onWindowFocused(evt); + m_toolbar.__onWindowFocused(evt); } else if (signal.ID == ostd::BuiltinSignals::WindowLostFocus) { @@ -912,6 +919,7 @@ namespace ogfx m_cmenu.hide(); evt.__original_signal_id = ostd::BuiltinSignals::WindowLostFocus; m_rootWidget.__onWindowFocusLost(evt); + m_toolbar.__onWindowFocusLost(evt); } else if (signal.ID == ostd::BuiltinSignals::FileDragAndDropped) { @@ -939,6 +947,9 @@ namespace ogfx evt.__original_signal_id = ostd::BuiltinSignals::WindowResized; if (m_menubar.isVisible()) m_menubar.onWindowResized(evt); + if (m_toolbar.isVisible()) + m_toolbar.onWindowResized(evt); + m_toolbar.__onWindowResized(evt); m_rootWidget.__onWindowResized(evt); } else if (signal.ID == ostd::BuiltinSignals::MouseMoved) @@ -949,6 +960,9 @@ namespace ogfx m_menubar.onMouseMoved(evt); if (m_cmenu.isVisible()) m_cmenu.onMouseMoved(evt); + if (m_toolbar.isVisible()) + m_toolbar.onMouseMoved(evt); + m_toolbar.__onMouseMoved(evt); m_rootWidget.__onMouseMoved(evt); } else if (signal.ID == ostd::BuiltinSignals::MouseScrolled) @@ -957,6 +971,7 @@ namespace ogfx evt.__original_signal_id = ostd::BuiltinSignals::MouseScrolled; if (m_cmenu.isVisible()) m_cmenu.onMouseScrolled(evt); + m_toolbar.__onMouseScrolled(evt); m_rootWidget.__onMouseScrolled(evt); } else if (signal.ID == ostd::BuiltinSignals::MousePressed) @@ -967,6 +982,9 @@ namespace ogfx m_cmenu.onMousePressed(evt); if (m_menubar.isVisible()) m_menubar.onMousePressed(evt); + if (m_toolbar.isVisible()) + m_toolbar.onMousePressed(evt); + m_toolbar.__onMousePressed(evt); m_rootWidget.__onMousePressed(evt); } else if (signal.ID == ostd::BuiltinSignals::MouseReleased) @@ -975,18 +993,21 @@ namespace ogfx evt.__original_signal_id = ostd::BuiltinSignals::MouseReleased; if (m_cmenu.isVisible()) m_cmenu.onMouseReleased(evt); + m_toolbar.__onMouseReleased(evt); 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_toolbar.__onKeyPressed(evt); 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_toolbar.__onKeyReleased(evt); m_rootWidget.__onKeyReleased(evt); if (evt.keyboard->keyCode == KeyCode::Escape) close(); @@ -995,6 +1016,7 @@ namespace ogfx { evt.keyboard = &(ogfx::KeyEventData&)signal.userData; evt.__original_signal_id = ostd::BuiltinSignals::TextEntered; + m_toolbar.__onTextEntered(evt); m_rootWidget.__onTextEntered(evt); } onSignal(signal); diff --git a/src/ogfx/gui/Window.hpp b/src/ogfx/gui/Window.hpp index 5a7ecd9..d804a6d 100644 --- a/src/ogfx/gui/Window.hpp +++ b/src/ogfx/gui/Window.hpp @@ -31,6 +31,7 @@ #include #include #include +#include namespace ogfx { @@ -274,8 +275,10 @@ namespace ogfx inline void showContextMenu(const Vec2& pos) { m_cmenu.show(pos); } inline void setContextMenu(const ContextMenu::Instance& instance) { m_cmenu.setInstance(instance); } inline bool isContextMenuVisible(void) const { return m_cmenu.isVisible(); } + inline bool isMenuBarVisible(void) const { return m_menubar.isVisible(); } inline void hideContextMenu(void) { m_cmenu.hide(); } inline MenuBar& getMenuBar(void) { return m_menubar; } + inline ToolBar& getToolBar(void) { return m_toolbar; } inline virtual void onInitialize(void) { } inline virtual void onDestroy(void) { } @@ -302,6 +305,7 @@ namespace ogfx ostd::StepTimer::TimePoint m_lastFrameTime; ContextMenu m_cmenu { *this }; MenuBar m_menubar { *this }; + ToolBar m_toolbar { *this }; friend class widgets::RootWidget; }; diff --git a/src/ogfx/gui/widgets/Button.cpp b/src/ogfx/gui/widgets/Button.cpp index 76457dd..ee74388 100644 --- a/src/ogfx/gui/widgets/Button.cpp +++ b/src/ogfx/gui/widgets/Button.cpp @@ -73,6 +73,7 @@ namespace ogfx void Button::setText(const String& text) { m_text = text; + m_textChanged = true; __update_size(); } @@ -107,6 +108,11 @@ namespace ogfx void Button::__update_size(void) { m_realIconSize = getIconSize().propy(getGlobalContentBounds().getSize().y); + if (!isAutoSizeEnabled()) + { + m_textChanged = false; + return; + } auto size = getWindow().getGFX().getStringDimensions(getText(), getFontSize()); size.x += getPadding().left(); size.x += getPadding().right(); diff --git a/src/ogfx/gui/widgets/Button.hpp b/src/ogfx/gui/widgets/Button.hpp index bf2eac1..c1c6bcb 100644 --- a/src/ogfx/gui/widgets/Button.hpp +++ b/src/ogfx/gui/widgets/Button.hpp @@ -45,6 +45,7 @@ namespace ogfx inline String getText(void) const { return m_text; } inline Image& getIcon(void) { return m_icon; } OSTD_BOOL_PARAM_GETSET_E(Animated, m_animated); + OSTD_BOOL_PARAM_GETSET_E(AutoSize, m_autoSize); OSTD_BOOL_PARAM_GETSET_E(Icon, m_showIcon); OSTD_PARAM_GETSET(ostd::AnimationData, AnimationData, m_animData); OSTD_PARAM_GETSET(Vec2, IconSize, m_iconSize); @@ -57,6 +58,7 @@ namespace ogfx bool m_textChanged { true }; Image m_icon; Vec2 m_realIconSize { 0, 0 }; + bool m_autoSize { true }; bool m_showIcon { false }; ostd::AnimationData m_animData; diff --git a/src/ogfx/gui/widgets/RootWidget.cpp b/src/ogfx/gui/widgets/RootWidget.cpp index 254ae48..01aa130 100644 --- a/src/ogfx/gui/widgets/RootWidget.cpp +++ b/src/ogfx/gui/widgets/RootWidget.cpp @@ -42,6 +42,8 @@ namespace ogfx f32 offset_y = 0; if (win.m_menubar.isVisible()) offset_y += win.m_menubar.geth(); + if (win.m_toolbar.isVisible()) + offset_y += win.m_toolbar.geth(); sety(offset_y); setSize(cast(event.windowResized->new_width), cast(event.windowResized->new_height) - offset_y); } diff --git a/src/test/GuiTest.cpp b/src/test/GuiTest.cpp index 0460c83..c99ef01 100644 --- a/src/test/GuiTest.cpp +++ b/src/test/GuiTest.cpp @@ -163,7 +163,12 @@ class Window : public ogfx::gui::Window m_panel2.addWidget(m_label3); m_panel2.addWidget(m_panel1, { 400, 50 }); m_panel2.addWidget(m_label1, { 0, 500 }); - m_panel2.addWidget(m_btn1, { 0, 300 }); + // m_panel2.addWidget(m_btn1, { 0, 300 }); + m_btn1.addThemeID("tool_button"); + m_btn1.seth(26); + m_btn1.setText(" "); + m_btn1.disableAutoSize(); + getToolBar().addWidget(m_btn1, { 0, 0 }); m_panel2.addWidget(m_img, { 20, 50 }); addWidget(m_tabs, { 0, 0 });