mirror of
https://github.com/NixOS/mobile-nixos.git
synced 2024-12-18 13:31:36 +03:00
171 lines
4.5 KiB
Ruby
171 lines
4.5 KiB
Ruby
|
module Kernel
|
||
|
alias_method :_exit, :exit
|
||
|
|
||
|
# mruby-at_exit seems to not be complete :/
|
||
|
# Let's instead hijack exit...
|
||
|
def exit(*args)
|
||
|
# Restore the console at exit.
|
||
|
VTConsole.map_console(1)
|
||
|
_exit(*args)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
class UI
|
||
|
attr_reader :screen
|
||
|
attr_reader :progress_bar
|
||
|
|
||
|
# As this is not using BaseWindow, LVGUI::init isn't handled for us.
|
||
|
LVGUI.init()
|
||
|
|
||
|
def initialize()
|
||
|
add_screen
|
||
|
# Biggest of horizontal or vertical; a percent.
|
||
|
@unit = ([@screen.get_width, @screen.get_height].max * 0.01).ceil
|
||
|
add_logo
|
||
|
add_progress_bar
|
||
|
add_label
|
||
|
add_cover # last
|
||
|
end
|
||
|
|
||
|
def add_label()
|
||
|
@label = LVGL::LVLabel.new(@screen)
|
||
|
@label.get_style(LVGL::LABEL_STYLE::MAIN).dup.tap do |style|
|
||
|
@label.set_style(LVGL::LABEL_STYLE::MAIN, style)
|
||
|
style.text_color = 0xFFFFFFFF
|
||
|
end
|
||
|
@label.set_long_mode(LVGL::LABEL_LONG::BREAK)
|
||
|
@label.set_align(LVGL::LABEL_ALIGN::CENTER)
|
||
|
|
||
|
@label.set_width(@screen.get_width * 0.9)
|
||
|
@label.set_pos(*center(@label, 0, 5*@unit))
|
||
|
@label.set_text("")
|
||
|
end
|
||
|
|
||
|
def add_logo()
|
||
|
# Try to find the logo, but don't fail if there isn't one.
|
||
|
file = nil
|
||
|
file = "/etc/logo.svg" if File.exist?("/etc/logo.svg")
|
||
|
file = "./logo.svg" if File.exist?("./logo.svg")
|
||
|
return unless file
|
||
|
|
||
|
if @screen.get_height > @screen.get_width
|
||
|
# 80% of the width
|
||
|
LVGL::Hacks::LVNanoSVG.resize_next_width((@screen.get_width * 0.8).to_i)
|
||
|
else
|
||
|
# 15% of the height
|
||
|
LVGL::Hacks::LVNanoSVG.resize_next_height((@screen.get_height * 0.15).to_i)
|
||
|
end
|
||
|
|
||
|
@logo = LVGL::LVImage.new(@screen)
|
||
|
@logo.set_src(file)
|
||
|
|
||
|
# Position the logo
|
||
|
@logo.set_pos(*center(@logo, 0, -@logo.get_height))
|
||
|
end
|
||
|
|
||
|
def add_progress_bar()
|
||
|
@progress_bar = ProgressBar.new(@screen)
|
||
|
@progress_bar.set_height(3 * @unit)
|
||
|
@progress_bar.set_width(@screen.get_width * 0.7)
|
||
|
@progress_bar.set_pos(*center(@progress_bar))
|
||
|
end
|
||
|
|
||
|
def add_screen()
|
||
|
@screen = LVGL::LVContainer.new()
|
||
|
@screen.get_style(LVGL::CONT_STYLE::MAIN).dup.tap do |style|
|
||
|
@screen.set_style(LVGL::CONT_STYLE::MAIN, style)
|
||
|
|
||
|
# Background for the splash, assumed black.
|
||
|
style.body_main_color = 0xFF000000
|
||
|
style.body_grad_color = 0xFF000000
|
||
|
end
|
||
|
end
|
||
|
|
||
|
# Used to handle fade-in/fade-out
|
||
|
# This is because opacity handles multiple overlaid objects wrong.
|
||
|
def add_cover()
|
||
|
@cover = LVGL::LVObject.new(@screen)
|
||
|
# Make it so we can use the opacity to fade in/out
|
||
|
@cover.set_opa_scale_enable(1)
|
||
|
@cover.set_width(@screen.get_width())
|
||
|
@cover.set_height(@screen.get_height())
|
||
|
|
||
|
@cover.get_style().dup.tap do |style|
|
||
|
@cover.set_style(style)
|
||
|
|
||
|
# Background for the splash, assumed black.
|
||
|
style.body_main_color = 0xFF000000
|
||
|
style.body_grad_color = 0xFF000000
|
||
|
# Some themes will add a border to LVObject.
|
||
|
style.body_border_width = 0
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def set_progress(amount)
|
||
|
progress_bar.progress = amount
|
||
|
end
|
||
|
|
||
|
def set_label(text)
|
||
|
@label.set_text(text)
|
||
|
end
|
||
|
|
||
|
# Fade-in animation
|
||
|
# Note that this looks like inverted logic because it is!
|
||
|
# We're actually fading-out the cover!
|
||
|
def fade_in()
|
||
|
LVGL::LVAnim.new().tap do |anim|
|
||
|
anim.set_exec_cb(@cover, :lv_obj_set_opa_scale)
|
||
|
anim.set_time(FADE_LENGTH, 0)
|
||
|
anim.set_values(255, 0)
|
||
|
anim.set_path_cb(LVGL::LVAnim::Path::EASE_OUT)
|
||
|
|
||
|
# Launch the animation
|
||
|
anim.create()
|
||
|
end
|
||
|
end
|
||
|
|
||
|
# Fade-out animation
|
||
|
# Note that this looks like inverted logic because it is!
|
||
|
# We're actually fading-in the cover!
|
||
|
def fade_out()
|
||
|
LVGL::LVAnim.new().tap do |anim|
|
||
|
anim.set_exec_cb(@cover, :lv_obj_set_opa_scale)
|
||
|
anim.set_time(FADE_LENGTH, PROGRESS_UPDATE_LENGTH)
|
||
|
anim.set_values(0, 255)
|
||
|
anim.set_path_cb(LVGL::LVAnim::Path::EASE_IN)
|
||
|
|
||
|
# Launch the animation
|
||
|
anim.create()
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def quit!()
|
||
|
fade_out()
|
||
|
set_progress(100)
|
||
|
|
||
|
# TODO: Callback on a timer or on the fade_out animation end.
|
||
|
# Though we **do** want to stop processing from the queue.
|
||
|
# This is not a callback yet because we don't have an ergonomic way to
|
||
|
# produce those callbacks for LVGL yet.
|
||
|
exit_timestamp = Time.now + FADE_LENGTH/1000.0 + PROGRESS_UPDATE_LENGTH/1000.0 + 0.1
|
||
|
LVGUI.main_loop do
|
||
|
if Time.now > exit_timestamp
|
||
|
sleep(2) if LVGL::Introspection.simulator?
|
||
|
exit(0)
|
||
|
end
|
||
|
end
|
||
|
# (end TODO)
|
||
|
end
|
||
|
|
||
|
private
|
||
|
|
||
|
def center(el, x = 0, y = 0)
|
||
|
[
|
||
|
@screen.get_width / 2 - el.get_width / 2 + x,
|
||
|
@screen.get_height / 2 - el.get_height / 2 + y,
|
||
|
]
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|