I received a GitHub issue request the other day asking how to implement a progress spinner in Glimmer DSL for LibUI. I did a quick implementation of it using `area` vector graphics, and documented it under the newly added Area Animation section in the README.
The solution is as simple as drawing a donut shape with multiple overlapping circles, and then adding an arc that covers part of the donut shape in order to show a filled area rotating around as a progress spinner. The rotation is repeated regularly using the `Glimmer::LibUI::timer` method.
Of course, it was encapsulated into a fully customizable custom control (aka custom widget) called `spinner` by using a combination of the method-based custom keyword and area-based custom control approaches.
Code:
# From: https://github.com/AndyObtiva/glimmer-dsl-libui#area-animation | |
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 |
Happy Glimmering!
No comments:
Post a Comment