Closed rubyFeedback closed 2 years ago
You can simply implement a spinner
with area
vector graphics using Glimmer::LibUI::timer
.
I added a section to the README called Area Animation that documents how to do it.
Spinner example that has a fully customizable method-based custom control called spinner
, which is destroyed if you click on it (you may copy/paste in girb
):
require 'glimmer-dsl-libui'
class SpinnerExample
include Glimmer
SIZE = 120
def initialize
create_gui
end
def launch
@main_window.show
end
def create_gui
@main_window = window {
title 'Spinner'
content_size SIZE*2, SIZE*2
horizontal_box {
padded false
vertical_box {
padded false
spinner(size: SIZE)
spinner(size: SIZE, fill_color: [42, 153, 214])
}
vertical_box {
padded false
spinner(size: SIZE/2.0, fill_color: :orange)
spinner(size: SIZE/2.0, fill_color: {x0: 0, y0: 0, x1: SIZE/2.0, y1: SIZE/2.0, stops: [{pos: 0.25, r: 204, g: 102, b: 204}, {pos: 1, r: 2, g: 2, b: 254}]})
spinner(size: SIZE/2.0, fill_color: :green, unfilled_color: :yellow)
spinner(size: SIZE/2.0, fill_color: :white, unfilled_color: :gray, background_color: :black)
}
}
}
end
def spinner(size: 40.0, fill_color: :gray, background_color: :white, unfilled_color: {r: 243, g: 243, b: 243}, donut_percentage: 0.25)
arc1 = arc2 = nil
area { |the_area|
rectangle(0, 0, size, size) {
fill background_color
}
circle(size/2.0, size/2.0, size/2.0) {
fill fill_color
}
arc1 = arc(size/2.0, size/2.0, size/2.0, 0, 180) {
fill unfilled_color
}
arc2 = arc(size/2.0, size/2.0, size/2.0, 90, 180) {
fill unfilled_color
}
circle(size/2.0, size/2.0, (size/2.0)*(1.0 - donut_percentage)) {
fill background_color
}
on_mouse_up do
the_area.destroy
end
}.tap do
Glimmer::LibUI.timer(0.05) do
delta = 10
arc1.start_angle += delta
arc2.start_angle += delta
end
end
end
end
SpinnerExample.new.launch
As you can see, the spinner
custom control is fully customizable with options like size
(you can set to 20
if you like) and fill_color
(which can even be a gradient).
If you click on any of the spinners, they are destroyed. This is how you can remove them in your application once there is no more work to do that needs a spinner, by calling the #destroy
method on the area
object.
To add them, you simply call code like this (assuming you declared a some_box
variable as vertical_box
or horizontal_box
):
some_box.content { spinner(size: 20) }
BTW, it works on Windows too:
Also, it works on Linux:
If there is anything that is not clear enough or you have any further questions, feel free to ask me by replying to this issue (even if closed) or opening a new one if needed.
Cheers!
Hey there Andy,
I already wrote a proposal for libui-ng in regards to spinner-widgets.
In ruby-gtk3 the spinner widget can be used to indicate an activity is ongoing.
See here as an example for the spinner in gtk:
https://docs.gtk.org/gtk4/class.Spinner.html
I use this, for example, to a GUI where the user can modify meta-data of a .mp4 file, via ffmpeg. That part works fine.
Now I was thinking to make this available on windows too. ffmpeg.exe works on windows, I already know that.
So my idea was to use glimmer-dsl-libui for that. But as far as I am aware there is no spinner functionality in upstream libui. Would it be possible to simulate or fake such a spinner widget, in glimmer-dsl-libui?
I don't have a good way to propose this, but two ideas I have on the top of my head are:
or alternatively:
Does not have to look pretty. The main idea behind the spinner is to indicate to the user that the application is still working, so the user does not get bored and knows that things are still happening as-is.
I don't know how easy it would be for glimmer-dsl-libui to support it or whether you think it is useful. The above two points in regards how to implement it are just examples; perhaps there are more ways to think about this.