From a01a9ac0f7e8e858139c00b41dc0896b777e48bf Mon Sep 17 00:00:00 2001 From: Samuel Dionne-Riel Date: Sat, 25 Sep 2021 15:45:42 -0400 Subject: [PATCH] lvgui: Improve keyboard --- boot/lib/lvgui/lvgui/base_window.rb | 26 ++++++++++++++++++++++++++ boot/lib/lvgui/lvgui/keyboard.rb | 26 ++++++++++++++++++++++++++ boot/lib/lvgui/lvgui/page.rb | 9 ++++++++- boot/lib/lvgui/lvgui/text_area.rb | 8 +++++--- boot/lib/lvgui/lvgui/windows.rb | 15 +++++++++++++++ 5 files changed, 80 insertions(+), 4 deletions(-) diff --git a/boot/lib/lvgui/lvgui/base_window.rb b/boot/lib/lvgui/lvgui/base_window.rb index ef371214..5e02b341 100644 --- a/boot/lib/lvgui/lvgui/base_window.rb +++ b/boot/lib/lvgui/lvgui/base_window.rb @@ -3,6 +3,9 @@ module LVGUI class BaseWindow include ::Singleton + attr_reader :keyboard + attr_reader :container + def self.inherited(superclass) superclass.class_eval do unless self.class_variable_defined?(:@@_after_initialize_callback) @@ -82,6 +85,8 @@ module LVGUI # Allow the window to do some work every time it is switched to. on_present + + refresh_keyboard() end # Hooking point for custom behaviour on present @@ -110,5 +115,26 @@ module LVGUI end end end + + def refresh_keyboard() + # Ensures keyboard is hidden and unlinked when it needs to be. + keyboard = LVGUI::Keyboard.instance + keyboard.set_ta(nil) + keyboard.hide() + + # Only do then next things if we linked the keyboard to this window (add_keyboard). + return unless @keyboard + # The keyboard is not added to the page; the page holds the elements that + # may move to ensure they're not covered by the keyboard. + @keyboard.set_parent(@screen) + @keyboard.set_protect(LVGL::PROTECT::POS) + @keyboard.container = @container + + # XXX : wrong on landscape + @keyboard.set_height(@screen.get_width * 0.55) + @keyboard.set_width(@screen.get_width_fit) + @container.keyboard = @keyboard + @container.refresh() + end end end diff --git a/boot/lib/lvgui/lvgui/keyboard.rb b/boot/lib/lvgui/lvgui/keyboard.rb index 32b20686..3a0f2518 100644 --- a/boot/lib/lvgui/lvgui/keyboard.rb +++ b/boot/lib/lvgui/lvgui/keyboard.rb @@ -4,6 +4,8 @@ class LVGUI::Keyboard < LVGUI::Widget include Singleton + attr_accessor :container + private def initialize() @@ -31,15 +33,39 @@ class LVGUI::Keyboard < LVGUI::Widget _set_position() end + def get_visible_height() + if @shown + # FIXME: "animated height" to collapse container accordingly + get_height() + else + 0 + end + end + def show() + raise "Parent not set" unless get_parent() + @shown = true _animate_y(get_parent.get_height() - get_height()) + if @container + @container.refresh() + LVGL::Hacks::LVTask.once(->() do + @container.focus( + self.get_ta(), + LVGL::ANIM::ON + ) + end, prio: LVGL::TASK_PRIO::LOWEST) + end end def hide() + raise "Parent not set" unless get_parent() + @shown = false _animate_y(get_parent.get_height) + @container.refresh() if @container end def _set_position() + raise "Parent not set" unless get_parent() if @shown _animate_y(get_parent.get_height() - get_height()) else diff --git a/boot/lib/lvgui/lvgui/page.rb b/boot/lib/lvgui/lvgui/page.rb index 1aafcfae..d67629e6 100644 --- a/boot/lib/lvgui/lvgui/page.rb +++ b/boot/lib/lvgui/lvgui/page.rb @@ -1,5 +1,7 @@ # Scrolling page. class LVGUI::Page < LVGUI::Widget + attr_accessor :keyboard + def initialize(parent) @parent = parent # A "holder" widget to work around idiosyncracies of pages. @@ -59,7 +61,12 @@ class LVGUI::Page < LVGUI::Widget def refresh() # Filling the parent that is at the root of the screen is apparently broken :/. @holder.set_height(@parent.get_height_fit - @holder.get_y) - set_height(@holder.get_height - get_y) + page_height = @holder.get_height - get_y + if @keyboard then + page_height = page_height - @keyboard.get_visible_height() + end + + set_height(page_height) end def inner_padding=(val) diff --git a/boot/lib/lvgui/lvgui/text_area.rb b/boot/lib/lvgui/lvgui/text_area.rb index f8b9b36a..0ffe5bd3 100644 --- a/boot/lib/lvgui/lvgui/text_area.rb +++ b/boot/lib/lvgui/lvgui/text_area.rb @@ -1,10 +1,13 @@ # Wraps a raw +lv_ta+ in minimal helpers class LVGUI::TextArea < LVGUI::Widget attr_reader :hidden + attr_reader :animation_length def initialize(parent) super(LVGL::LVTextArea.new(parent)) + @animation_length = 400 + @hidden = false set_text("") set_placeholder_text("") @@ -45,7 +48,6 @@ class LVGUI::TextArea < LVGUI::Widget # get_text() gives us a Fiddle::Pointer (leaky abstraction!!!) value = "#{get_text()}" @on_submit.call(value) if @on_submit - hide() end #else # puts "Unhandled event for #{self}: #{LVGL::EVENT.from_value(event)}" @@ -57,7 +59,7 @@ class LVGUI::TextArea < LVGUI::Widget @hidden = false LVGL::LVAnim.new().tap do |anim| anim.set_exec_cb(self, :lv_obj_set_opa_scale) - anim.set_time(FADE_LENGTH, 0) + anim.set_time(@animation_length, 0) anim.set_values(0, 255) anim.set_path_cb(LVGL::LVAnim::Path::EASE_OUT) @@ -75,7 +77,7 @@ class LVGUI::TextArea < LVGUI::Widget LVGL::LVAnim.new().tap do |anim| anim.set_exec_cb(self, :lv_obj_set_opa_scale) - anim.set_time(FADE_LENGTH, 0) + anim.set_time(@animation_length, 0) anim.set_values(255, 0) anim.set_path_cb(LVGL::LVAnim::Path::EASE_IN) diff --git a/boot/lib/lvgui/lvgui/windows.rb b/boot/lib/lvgui/lvgui/windows.rb index 468d5e68..85bc6d52 100644 --- a/boot/lib/lvgui/lvgui/windows.rb +++ b/boot/lib/lvgui/lvgui/windows.rb @@ -83,6 +83,21 @@ module LVGUI end end end + + def add_textarea() + add_keyboard + LVGUI::TextArea.new(@container).tap do |ta| + add_to_focus_group(ta) + ta.set_width(@container.get_width_fit) + end + end + + def add_keyboard() + unless @keyboard + @keyboard = LVGUI::Keyboard.instance() + refresh_keyboard() + end + end end module Window