Added ProgressBar widget

This commit is contained in:
OmniaX-Dev 2026-04-22 18:34:47 +02:00
parent 1c9d0b5ab9
commit 327582c463
11 changed files with 215 additions and 5 deletions

View file

@ -94,6 +94,7 @@ list(APPEND OGFX_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/widgets/Scrollbar.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/widgets/Button.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/widgets/RadioButton.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/widgets/ProgressBar.cpp
# render
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/render/BasicRenderer.cpp
@ -152,7 +153,7 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_definitions(${OMNIA_STD_LIB} PUBLIC OX_DEBUG_BUILD)
target_compile_definitions(${OMNIA_GFX_LIB} PUBLIC OX_DEBUG_BUILD)
elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
add_compile_options(-MMD -MP -Wall)
add_compile_options(-MMD -MP -Wall -latomic)
target_compile_definitions(${OMNIA_STD_LIB} PUBLIC OX_RELEASE_BUILD)
target_compile_definitions(${OMNIA_GFX_LIB} PUBLIC OX_RELEASE_BUILD)
endif()

View file

@ -219,3 +219,19 @@ const $accentColorDark = #6B0A1DFF
(image) {
}
% ===================
% ====== Image ======
(progressbar) {
backgroundColor = #400000FF
progressColor = #AA0000FF
borderColor = $accentColor
showDecimal = false
showText = true
useBackgroundGradient = true
backgroundGradient = gradientV(#400A1DFF - $accentColorDark)
useProgressGradient = true
progressGradient = gradientV(#C21135FF - #820B23FF)
}
% ===================

View file

@ -24,7 +24,7 @@ Add theme caching
Implement cursors in Stylesheet
FIX: Window getting exponentially bigger when Desktop scale changes
FIX: Refreshing scroll when content extent changes
Add Dark Mode Default theme
Add Dark Mode Default theme, and see if I can query OS theme mode to saelect the right theme
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
Add buttons to scroll tabs in TabPanel
@ -46,7 +46,7 @@ Implement following widgets:
***Tooltips
***Radio Button
***Grouping
Progressbar
***Progressbar
Horizontal Slider
Vertical Slider
ListBox

View file

@ -26,3 +26,4 @@
#include <ogfx/gui/widgets/Scrollbar.hpp>
#include <ogfx/gui/widgets/Button.hpp>
#include <ogfx/gui/widgets/RadioButton.hpp>
#include <ogfx/gui/widgets/ProgressBar.hpp>

View file

@ -47,7 +47,7 @@ namespace ogfx
inline Color getCheckBoxColor(void) const { return m_checkBoxColor; }
inline void setCheckBoxColor(const Color& color) { m_checkBoxColor = color; }
inline bool isChecked(void) const { return m_checked; }
inline void setStateChangedCallback(std::function<void(CheckBox&, bool)> callback) { callback_onStateChanged = callback; }
inline void setStateChangedCallback(std::function<void(CheckBox&, bool)> callback) { callback_onStateChanged = std::move(callback); }
private:
void __update_size(ogfx::BasicRenderer2D& gfx);

View file

@ -0,0 +1,98 @@
/*
OmniaFramework - A collection of useful functionality
Copyright (C) 2025 OmniaX-Dev
This file is part of OmniaFramework.
OmniaFramework is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OmniaFramework is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OmniaFramework. If not, see <https://www.gnu.org/licenses/>.
*/
#include "ProgressBar.hpp"
#include "../../render/BasicRenderer.hpp"
namespace ogfx
{
namespace gui
{
namespace widgets
{
ProgressBar& ProgressBar::create(void)
{
setPadding({ 0, 0, 0, 0 });
setTypeName("ogfx::gui::widgets::ProgressBar");
disableChildren();
enableBackground();
enableBorder();
setStylesheetCategoryName("progressbar");
validate();
return *this;
}
void ProgressBar::applyTheme(const ostd::Stylesheet& theme)
{
setProgressColor(getThemeValue<Color>(theme, "progressColor", getProgressColor()));
enableShowDecimal(getThemeValue<bool>(theme, "showDecimal", isShowDecimalEnabled()));
enableShowText(getThemeValue<bool>(theme, "showText", isShowTextEnabled()));
enableProgressGradient(getThemeValue<bool>(theme, "useProgressGradient", isProgressGradientEnabled()));
setProgressGradient(getThemeValue<ColorGradient>(theme, "progressGradient", getProgressGradient()));
}
void ProgressBar::onDraw(ogfx::BasicRenderer2D& gfx)
{
f32 prog = getProgressNormalized();
f32 progressw = (prog * getw());
if (isProgressGradientEnabled())
gfx.fillGradientRect({ getGlobalPosition(), { progressw, geth() } }, m_progressGradient);
else
gfx.fillRect({ getGlobalPosition(), { progressw, geth() } }, getProgressColor());
if (isShowTextEnabled())
{
String text = "";
if (isShowDecimalEnabled())
text.add(prog * 100, 2).add("%");
else
text.add(cast<i32>(std::round(prog * 100))).add("%");
gfx.drawCenteredString(text, getGlobalBounds(), getTextColor(), getFontSize());
}
}
void ProgressBar::setProgressNormalized(f32 normalized_value)
{
f32 current = m_progress.load(std::memory_order_relaxed);
f32 next = current;
next = current + std::clamp(normalized_value, 0.0f, 1.0f) * (m_max - m_min);
m_progress.store(next, std::memory_order_relaxed);
}
void ProgressBar::setProgress(f32 value)
{
f32 current = m_progress.load(std::memory_order_relaxed);
f32 next = current;
next = std::clamp(value, m_min, m_max);
m_progress.store(next, std::memory_order_relaxed);
}
f32 ProgressBar::getProgress(void) const
{
return m_progress.load(std::memory_order_relaxed);
}
f32 ProgressBar::getProgressNormalized(void) const
{
f32 s = m_progress.load(std::memory_order_relaxed);
return (s - m_min) / (m_max - m_min);
}
}
}
}

View file

@ -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 <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <ogfx/gui/widgets/Widget.hpp>
#include <atomic>
namespace ogfx
{
namespace gui
{
namespace widgets
{
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(); }
ProgressBar& create(void);
void applyTheme(const ostd::Stylesheet& theme) override;
void onDraw(ogfx::BasicRenderer2D& gfx) override;
void setProgressNormalized(f32 normalized_value);
void setProgress(f32 value);
f32 getProgress(void) const;
f32 getProgressNormalized(void) const;
OSTD_PARAM_GETSET(Color, ProgressColor, m_progressColor);
OSTD_BOOL_PARAM_GETSET_E(ShowDecimal, m_showDecimal);
OSTD_BOOL_PARAM_GETSET_E(ShowText, m_showText);
OSTD_BOOL_PARAM_GETSET_E(ProgressGradient, m_useProgressGradient);
OSTD_PARAM_GETSET(ColorGradient, ProgressGradient, m_progressGradient);
private:
Color m_progressColor { 255, 255, 255 };
f32 m_min { 0.0f };
f32 m_max { 1.0f };
std::atomic<f32> m_progress;
bool m_showDecimal { false };
bool m_showText { true };
bool m_useProgressGradient { true };
ColorGradient m_progressGradient {
{ Colors::Crimson.darkened(0.1f), Colors::Crimson.darkened(0.35f) },
{ 1.0f }
};
};
}
}
}

View file

@ -117,9 +117,14 @@ namespace ogfx
{
if (is_button_present(sender))
{
if (m_selected != nullptr && m_selected == &sender)
return;
unselect_all();
auto previous = m_selected;
m_selected = &sender;
m_selected->__set_selected(true);
if (previous != nullptr && callback_onSelectionChanged != nullptr)
callback_onSelectionChanged(*previous, sender);
return;
}
}

View file

@ -66,6 +66,7 @@ namespace ogfx
public:
RadioButtonGroup(void);
RadioButton& addButton(Widget& parent, const String& text, const Vec2& position = { 0, 0 });
inline void setSelectionChangedCallback(std::function<void(RadioButton& previous, RadioButton& sender)> callback) { callback_onSelectionChanged = std::move(callback); }
private:
void set_selected(RadioButton& sender);
@ -75,6 +76,7 @@ namespace ogfx
private:
stdvec<std::unique_ptr<RadioButton>> m_buttons;
RadioButton* m_selected { nullptr };
std::function<void(RadioButton& previous, RadioButton& sender)> callback_onSelectionChanged { nullptr };
friend class RadioButton;
};

View file

@ -228,7 +228,7 @@ namespace ogfx
Rectangle m_padding { 0, 0, 0, 0 };
Rectangle m_margin { 0, 0, 0, 0 };
Vec2 m_contentOffset { 0, 0 };
i32 m_borderRadius { 10 };
i32 m_borderRadius { 0 };
i32 m_borderWidth { 2 };
Color m_borderColor { 255, 255, 255 };
bool m_showBorder { false };

View file

@ -22,6 +22,7 @@
#include <SDL3/SDL_rect.h>
#include <ogfx/utils/Keycodes.hpp>
#include <ogfx/ogfx.hpp>
#include <ostd/utils/Async.hpp>
ogfx::WindowCore::FileDialogFilterList filters = {
{ "Image files", { "png", "jpg", "jpeg", "bmp" } },
@ -103,6 +104,8 @@ class Window : public ogfx::gui::Window
m_panel2.enableTooltip();
m_panel2.setTooltipText("PANEL tooltip");
m_prog.setSize(300, 30);
m_tabs.setSize(900, 700);
auto& t1 = m_tabs.addTab("Tab1");
auto& t2 = m_tabs.addTab("Tab2 Test");
@ -115,6 +118,11 @@ class Window : public ogfx::gui::Window
m_radioGroup.addButton(t1, "Radio this out!", { 30, 80 });
m_radioGroup.addButton(t1, "Radio Opt. 2", { 30, 110 });
m_radioGroup.addButton(t1, "Radio 3", { 30, 140 });
m_radioGroup.setSelectionChangedCallback([&](RadioButton& previous, RadioButton& sender) -> void {
std::cout << previous.getText() << "\n";
std::cout << sender.getText() << "\n\n";
});
t1.addWidget(m_prog, { 30, 200 });
t2.addWidget(m_panel2, { 500, 100 });
m_panel3.addWidget(m_label4);
@ -133,6 +141,17 @@ class Window : public ogfx::gui::Window
m_theme.loadFromFile("./DefaultTheme.oss", true, getDefaultStylesheetVariableList());
setTheme(m_theme);
m_progressJob.start([this] {
f32 prog = 0.0f;
while (prog < 100)
{
prog += 0.6f;
ostd::Time::sleep(ostd::Random::getui32(10, 200));
this->m_prog.setProgress(prog);
}
return true;
});
}
inline void onSignal(ostd::Signal& signal) override
@ -168,6 +187,10 @@ class Window : public ogfx::gui::Window
ImageLabel m_img { *this };
TabPanel m_tabs { *this };
RadioButtonGroup m_radioGroup;
ProgressBar m_prog { *this, 0, 100 };
ostd::StepTimer m_timer;
ostd::AsyncJob<bool> m_progressJob;
ostd::Stylesheet m_theme;
};