Skip to content

Commit fbcc873

Browse files
committed
feat: Implement indefinite progress bar animation using KeyframeAnimation and add Window.try_lock for safe animation registration.
1 parent 08d6e66 commit fbcc873

File tree

5 files changed

+76
-10
lines changed

5 files changed

+76
-10
lines changed

animation.v

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ mut:
3232
// The animation's start time is set to the current time and will be processed
3333
// in the animation loop.
3434
pub fn (mut window Window) animation_add(mut animation Animation) {
35-
window.lock()
36-
defer { window.unlock() }
35+
if window.try_lock() {
36+
defer { window.unlock() }
37+
}
3738
animation.start = time.now()
3839
window.animations[animation.id] = animation
3940
}

examples/progress_bars.v

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ fn main_view(window &gui.Window) gui.View {
5959
percent: 0.80
6060
text_show: false
6161
),
62+
gui.progress_bar(
63+
id: 'pbar_indefinite'
64+
height: 20
65+
sizing: gui.fill_fixed
66+
indefinite: true
67+
),
6268
gui.row(
6369
spacing: 40
6470
sizing: gui.fit_fill

view_progress_bar.v

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module gui
22

33
import math
4+
import time
45

56
// ProgressBarCfg configures a [progress_bar](#progress_bar)
67
@[minify]
@@ -25,7 +26,7 @@ pub:
2526
text_show bool = gui_theme.progress_bar_style.text_show
2627
disabled bool
2728
invisible bool
28-
indefinite bool // TODO: not implemented
29+
indefinite bool // indicates indeterminate progress state
2930
vertical bool // orientation
3031
}
3132

@@ -38,7 +39,7 @@ pub fn progress_bar(cfg ProgressBarCfg) View {
3839
radius: cfg.radius
3940
color: cfg.color_bar
4041
)
41-
if cfg.text_show {
42+
if cfg.text_show && !cfg.indefinite {
4243
mut percent := f64_min(f64_max(cfg.percent, f64(0)), f64(1))
4344
percent = math.round(percent * 100)
4445
content << row(
@@ -53,6 +54,8 @@ pub fn progress_bar(cfg ProgressBarCfg) View {
5354
bar_percent := cfg.percent
5455
text_show := cfg.text_show
5556
vertical := cfg.vertical
57+
indefinite := cfg.indefinite
58+
id := cfg.id
5659

5760
size := f32(gui_theme.progress_bar_style.size)
5861
container_cfg := ContainerCfg{
@@ -72,17 +75,66 @@ pub fn progress_bar(cfg ProgressBarCfg) View {
7275
padding: padding_none
7376
h_align: .center
7477
v_align: .middle
75-
amend_layout: fn [bar_percent, text_show, vertical] (mut layout Layout, mut w Window) {
78+
amend_layout: fn [bar_percent, text_show, vertical, indefinite, id] (mut layout Layout, mut w Window) {
7679
if layout.children.len >= 0 {
77-
percent := f32_clamp(bar_percent, 0, 1)
80+
mut percent := f32_clamp(bar_percent, 0, 1)
81+
mut offset := f32(0)
82+
83+
if indefinite {
84+
// 30% width bar for indefinite mode
85+
percent = 0.3
86+
87+
// Register animation if missing
88+
anim_id := '${id}_indefinite'
89+
if anim_id !in w.animations {
90+
mut anim := KeyframeAnimation{
91+
id: anim_id
92+
repeat: true
93+
duration: 1500 * time.millisecond
94+
keyframes: [
95+
Keyframe{
96+
at: 0.0
97+
value: 0.0
98+
},
99+
Keyframe{
100+
at: 0.5
101+
value: 1.0
102+
easing: ease_in_out_quad
103+
},
104+
Keyframe{
105+
at: 1.0
106+
value: 0.0
107+
easing: ease_in_out_quad
108+
},
109+
]
110+
on_value: fn [id] (v f32, mut w Window) {
111+
if w.view_state.progress_state.contains(id) {
112+
w.view_state.progress_state.set(id, v)
113+
} else {
114+
// ensure entry exists
115+
w.view_state.progress_state.set(id, v)
116+
}
117+
}
118+
}
119+
anim.start = time.now()
120+
w.animation_add(mut anim)
121+
}
122+
123+
// Read current animation progress
124+
if progress := w.view_state.progress_state.get(id) {
125+
// Calculate offset based on available space (1.0 - bar_width_percent) * progress
126+
offset = (1.0 - percent) * progress
127+
}
128+
}
129+
78130
if vertical {
79131
height := f32_min(layout.shape.height * percent, layout.shape.height)
80132
layout.children[0].shape.x = layout.shape.x
81-
layout.children[0].shape.y = layout.shape.y
133+
layout.children[0].shape.y = layout.shape.y + (layout.shape.height * offset)
82134
layout.children[0].shape.height = height
83135
layout.children[0].shape.width = layout.shape.width
84136
// center label on bar. Label is row containing text
85-
if text_show {
137+
if text_show && !indefinite {
86138
center := layout.shape.x + layout.shape.width / 2
87139
half_width := layout.children[1].shape.width / 2
88140
old_x := layout.children[1].shape.x
@@ -97,12 +149,12 @@ pub fn progress_bar(cfg ProgressBarCfg) View {
97149
}
98150
} else {
99151
width := f32_min(layout.shape.width * percent, layout.shape.width)
100-
layout.children[0].shape.x = layout.shape.x
152+
layout.children[0].shape.x = layout.shape.x + (layout.shape.width * offset)
101153
layout.children[0].shape.y = layout.shape.y
102154
layout.children[0].shape.width = width
103155
layout.children[0].shape.height = layout.shape.height
104156
// center label on bar. Label is row containing text
105-
if text_show {
157+
if text_show && !indefinite {
106158
middle := layout.shape.y + layout.shape.height / 2
107159
half_height := layout.children[1].shape.height / 2
108160
old_y := layout.children[1].shape.y

view_state.v

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ mut:
7474
diagram_cache BoundedDiagramCache = BoundedDiagramCache{
7575
max_size: 50
7676
}
77+
progress_state BoundedMap[string, f32] = BoundedMap[string, f32]{
78+
max_size: 50
79+
}
7780
}
7881

7982
// TableColCache stores cached column widths and hash for invalidation

xtra_window.v

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@ pub fn (mut window Window) @lock() {
152152
window.mutex.lock()
153153
}
154154

155+
pub fn (mut window Window) try_lock() bool {
156+
return window.mutex.try_lock()
157+
}
158+
155159
// unlock unlocks the locked mutex. Same precautions apply as with [lock](#lock)
156160
pub fn (mut window Window) unlock() {
157161
window.mutex.unlock()

0 commit comments

Comments
 (0)