Skip to content

Commit 4fd8710

Browse files
authored
Implement busy_bar (#397)
1 parent e00c4c8 commit 4fd8710

File tree

8 files changed

+281
-1
lines changed

8 files changed

+281
-1
lines changed

examples/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,4 @@ add_subdirectory(drop_file)
2727
add_subdirectory(range_slider)
2828
add_subdirectory(model)
2929
add_subdirectory(selection_list)
30+
add_subdirectory(status_bars)

examples/status_bars/CMakeLists.txt

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
cmake_minimum_required(VERSION 3.16.0)
2+
project(DynamicLists LANGUAGES C CXX VERSION "1.0.0")
3+
4+
if (NOT ELEMENTS_ROOT)
5+
message(FATAL_ERROR "ELEMENTS_ROOT is not set")
6+
endif()
7+
8+
# Make sure ELEMENTS_ROOT is an absolute path to add to the CMake module path
9+
get_filename_component(ELEMENTS_ROOT "${ELEMENTS_ROOT}" ABSOLUTE)
10+
set (CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${ELEMENTS_ROOT}/cmake")
11+
12+
# If we are building outside the project, you need to set ELEMENTS_ROOT:
13+
if (NOT ELEMENTS_BUILD_EXAMPLES)
14+
include(ElementsConfigCommon)
15+
set(ELEMENTS_BUILD_EXAMPLES OFF)
16+
add_subdirectory(${ELEMENTS_ROOT} elements)
17+
endif()
18+
19+
set(ELEMENTS_APP_PROJECT "StatusBars")
20+
set(ELEMENTS_APP_TITLE "Status Bars")
21+
set(ELEMENTS_APP_COPYRIGHT "Copyright (c) 2024 Flole")
22+
set(ELEMENTS_APP_ID "com.cycfi.status_bars")
23+
set(ELEMENTS_APP_VERSION "1.0")
24+
25+
set(ELEMENTS_APP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp)
26+
27+
# For your custom application icon on macOS or Windows see cmake/AppIcon.cmake module
28+
include(AppIcon)
29+
include(ElementsConfigApp)

examples/status_bars/main.cpp

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*=============================================================================
2+
Copyright (c) 2024 Flole
3+
4+
Distributed under the MIT License (https://opensource.org/licenses/MIT)
5+
=============================================================================*/
6+
#include <elements.hpp>
7+
8+
using namespace cycfi::elements;
9+
using cycfi::artist::rgba;
10+
namespace colors = cycfi::artist::colors;
11+
using namespace std::chrono_literals;
12+
13+
constexpr auto bred = colors::red.opacity(0.4);
14+
constexpr auto bgreen = colors::green.level(0.7).opacity(0.4);
15+
constexpr auto brblue = colors::royal_blue.opacity(0.4);
16+
constexpr auto pgold = colors::gold.opacity(0.8);
17+
18+
// Main window background color
19+
auto constexpr bkd_color = rgba(35, 35, 37, 255);
20+
auto background = box(bkd_color);
21+
22+
auto make_bars(view& view_)
23+
{
24+
auto prog_bar = share(progress_bar(rbox(colors::black), rbox(pgold)));
25+
auto bsy_bar = share(busy_bar(rbox(colors::black), rbox(brblue)));
26+
auto prog_advance = icon_button(icons::plus);
27+
auto busy_start = button("I", 1.0, bgreen);
28+
auto busy_stop = button("O", 1.0, bred);
29+
30+
prog_advance.on_click =
31+
[prog_bar, &view_](bool) mutable
32+
{
33+
auto val = prog_bar->value();
34+
if (val > 0.9)
35+
prog_bar->value(0.0);
36+
else
37+
prog_bar->value(val + 0.125);
38+
view_.refresh(*prog_bar);
39+
};
40+
41+
busy_stop.on_click =
42+
[bsy_bar, &view_](bool) mutable
43+
{
44+
bsy_bar->animate(view_, 0ms);
45+
};
46+
47+
busy_start.on_click =
48+
[bsy_bar, &view_](bool) mutable
49+
{
50+
bsy_bar->animate(view_, 50ms);
51+
};
52+
53+
return
54+
margin({20, 0, 20, 20},
55+
vtile(
56+
margin_top(20, htile(
57+
margin_right(3, valign(0.5, prog_advance)),
58+
vsize(27, hold(prog_bar))
59+
)),
60+
margin_top(20, vtile(
61+
margin_right(3, htile(
62+
busy_stop,
63+
busy_start
64+
)),
65+
vsize(27, hold(bsy_bar))
66+
))
67+
)
68+
);
69+
}
70+
71+
72+
int main(int argc, char* argv[])
73+
{
74+
app _app("Status Bars");
75+
window _win(_app.name());
76+
_win.on_close = [&_app]() { _app.stop(); };
77+
78+
view view_(_win);
79+
80+
view_.content(
81+
make_bars(view_),
82+
background
83+
);
84+
85+
_app.run();
86+
return 0;
87+
}

lib/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ add_subdirectory(artist)
2727

2828
set(ELEMENTS_SOURCES
2929
src/element/button.cpp
30+
src/element/busy_bar.cpp
3031
src/element/child_window.cpp
3132
src/element/composite.cpp
3233
src/element/dial.cpp
@@ -72,6 +73,7 @@ set(ELEMENTS_HEADERS
7273
include/elements.hpp
7374
include/elements/app.hpp
7475
include/elements/base_view.hpp
76+
include/elements/element/busy_bar.hpp
7577
include/elements/element.hpp
7678
include/elements/element/align.hpp
7779
include/elements/element/button.hpp

lib/include/elements/element.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include <elements/element/align.hpp>
1010
#include <elements/element/button.hpp>
11+
#include <elements/element/busy_bar.hpp>
1112
#include <elements/element/child_window.hpp>
1213
#include <elements/element/composite.hpp>
1314
#include <elements/element/dial.hpp>
+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*=============================================================================
2+
Copyright (c) 2024 Flole
3+
4+
Distributed under the MIT License [ https://opensource.org/licenses/MIT ]
5+
=============================================================================*/
6+
#if !defined(ELEMENTS_BUSY_BAR_JUNE_13_2024)
7+
#define ELEMENTS_BUSY_BAR_JUNE_13_2024
8+
9+
#include "elements/element/progress_bar.hpp"
10+
11+
namespace cycfi::elements
12+
{
13+
class busy_bar_base : public progress_bar_base
14+
{
15+
public:
16+
busy_bar_base(double init_value = 0.0, double start_value = 0.0)
17+
: progress_bar_base(init_value), _start(start_value), _status(-0.2)
18+
{}
19+
20+
void start(double val);
21+
double start() const { return _start; }
22+
void animate(view& view_, duration time);
23+
24+
rect foreground_bounds(context const& ctx) const override;
25+
26+
private:
27+
void animate(view& view_);
28+
29+
double _start; // Start position
30+
double _status;
31+
duration _time;
32+
};
33+
34+
class basic_busy_bar_base : public busy_bar_base
35+
{
36+
public:
37+
basic_busy_bar_base(double init_value, double start_value)
38+
: busy_bar_base(init_value, start_value)
39+
{}
40+
};
41+
42+
namespace concepts
43+
{
44+
template <typename T>
45+
concept BusyBar = std::is_base_of_v<busy_bar_base, std::decay_t<T>>;
46+
}
47+
48+
template <
49+
concepts::Element Background
50+
, concepts::Element Foreground
51+
, concepts::BusyBar Base = basic_busy_bar_base
52+
>
53+
class basic_busy_bar : public Base
54+
{
55+
public:
56+
57+
using background_type = std::decay_t<Background>;
58+
using foreground_type = std::decay_t<Foreground>;
59+
60+
basic_busy_bar(
61+
Background&& bg
62+
, Foreground&& fg
63+
, double init_value
64+
, double start_value
65+
)
66+
: Base(init_value, start_value)
67+
, _background(std::forward<Foreground>(bg))
68+
, _foreground(std::forward<Background>(fg))
69+
{}
70+
71+
basic_busy_bar(Background const& bg, Foreground const& fg, double init_value, double start_value)
72+
: Base(init_value, start_value)
73+
, _foreground(fg)
74+
, _background(bg)
75+
{}
76+
77+
element const& background() const override { return _background; }
78+
element& background() override { return _background; }
79+
element const& foreground() const override { return _foreground; }
80+
element& foreground() override { return _foreground; }
81+
82+
private:
83+
84+
background_type _background;
85+
foreground_type _foreground;
86+
};
87+
88+
template <concepts::Element Background, concepts::Element Foreground>
89+
basic_busy_bar<Background, Foreground, basic_busy_bar_base>
90+
busy_bar(Background&& bg, Foreground&& fg, double init_value = 0.0, double start_value = 0.0)
91+
{
92+
return {
93+
std::forward<Background>(bg),
94+
std::forward<Foreground>(fg),
95+
init_value,
96+
start_value
97+
};
98+
}
99+
}
100+
101+
#endif

lib/include/elements/element/progress_bar.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ namespace cycfi::elements
3030
void value(double val) override;
3131

3232
rect background_bounds(context const& ctx) const;
33-
rect foreground_bounds(context const& ctx) const;
33+
virtual rect foreground_bounds(context const& ctx) const;
3434

3535
virtual element const& background() const = 0;
3636
virtual element& background() = 0;

lib/src/element/busy_bar.cpp

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#include <elements/element/busy_bar.hpp>
2+
#include <elements/support/draw_utils.hpp>
3+
#include <elements/support/theme.hpp>
4+
#include <elements/view.hpp>
5+
6+
namespace cycfi::elements
7+
{
8+
// Implement the start method as per the patch
9+
void busy_bar_base::start(double val)
10+
{
11+
_start = clamp(val, 0.0, 1.0);
12+
}
13+
14+
// Implement foreground_bounds to include the start value
15+
rect busy_bar_base::foreground_bounds(context const& ctx) const
16+
{
17+
auto bounds = ctx.bounds;
18+
19+
if (bounds.width() > bounds.height())
20+
bounds.width(bounds.width() * value());
21+
else
22+
bounds.height(bounds.height() * (1.0 - value()));
23+
24+
// Adjust bounds based on the start value
25+
if (bounds.width() > bounds.height())
26+
bounds.left = bounds.left + (bounds.width() * start());
27+
else
28+
bounds.bottom = bounds.bottom + (bounds.height() * start());
29+
30+
return bounds;
31+
}
32+
33+
void busy_bar_base::animate(view& view_, duration time)
34+
{
35+
_time = time;
36+
animate(view_);
37+
}
38+
39+
void busy_bar_base::animate(view& view_)
40+
{
41+
if(_time == _time.zero()) {
42+
_status = -0.2;
43+
value(0.0);
44+
start(0.0);
45+
view_.refresh();
46+
return;
47+
}
48+
_status += 0.01;
49+
start(_status);
50+
value(_status + 0.2);
51+
if(_status >= 1.0) {
52+
_status = -0.2;
53+
}
54+
view_.refresh();
55+
view_.post(std::chrono::duration_cast<std::chrono::milliseconds>(_time), [&view_, this]() {
56+
animate(view_);
57+
});
58+
}
59+
}

0 commit comments

Comments
 (0)