From a79b9cc20eb7fb9c201869331d05a4239119d3e9 Mon Sep 17 00:00:00 2001 From: Cyberarm Date: Mon, 20 Apr 2026 10:14:57 -0500 Subject: [PATCH] Added Widget, which acts like a Flow and a button. --- lib/cyberarm_engine.rb | 1 + lib/cyberarm_engine/ui/dsl.rb | 4 +++ lib/cyberarm_engine/ui/elements/text_block.rb | 3 ++ lib/cyberarm_engine/ui/elements/widget.rb | 36 +++++++++++++++++++ lib/cyberarm_engine/ui/gui_state.rb | 2 +- 5 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 lib/cyberarm_engine/ui/elements/widget.rb diff --git a/lib/cyberarm_engine.rb b/lib/cyberarm_engine.rb index 4a94d96..44c8339 100644 --- a/lib/cyberarm_engine.rb +++ b/lib/cyberarm_engine.rb @@ -58,6 +58,7 @@ require_relative "cyberarm_engine/ui/elements/image" require_relative "cyberarm_engine/ui/elements/container" require_relative "cyberarm_engine/ui/elements/flow" require_relative "cyberarm_engine/ui/elements/stack" +require_relative "cyberarm_engine/ui/elements/widget" require_relative "cyberarm_engine/ui/elements/check_box" require_relative "cyberarm_engine/ui/elements/radio" require_relative "cyberarm_engine/ui/elements/progress" diff --git a/lib/cyberarm_engine/ui/dsl.rb b/lib/cyberarm_engine/ui/dsl.rb index 4733c17..ca73a51 100644 --- a/lib/cyberarm_engine/ui/dsl.rb +++ b/lib/cyberarm_engine/ui/dsl.rb @@ -20,6 +20,10 @@ module CyberarmEngine container(CyberarmEngine::Element::Stack, options, &block) end + def widget(options = {}, &block) + container(CyberarmEngine::Element::Widget, options, &block) + end + def menu(options = {}, &block) container(CyberarmEngine::Element::Menu, options, &block) end diff --git a/lib/cyberarm_engine/ui/elements/text_block.rb b/lib/cyberarm_engine/ui/elements/text_block.rb index aa7d77f..d0d8ff3 100644 --- a/lib/cyberarm_engine/ui/elements/text_block.rb +++ b/lib/cyberarm_engine/ui/elements/text_block.rb @@ -214,6 +214,9 @@ module CyberarmEngine end class ToolTip < TextBlock + def needs_repaint? + @needs_repaint || !value.to_s.empty? + end end class Link < TextBlock diff --git a/lib/cyberarm_engine/ui/elements/widget.rb b/lib/cyberarm_engine/ui/elements/widget.rb new file mode 100644 index 0000000..ad8b8b7 --- /dev/null +++ b/lib/cyberarm_engine/ui/elements/widget.rb @@ -0,0 +1,36 @@ +module CyberarmEngine + class Element + # Special container that has a layout like a Flow + # and makes all its children mirror its styling (i.e. hover, active, disabled...) + class Widget < Flow + def update_styles(style = :default) + super + + @children.each do |child| + recursive_styles(style, self) + end + end + + # Make child elements mirror the widgets styling + # disabled elements will not have their styling overridden + def recursive_styles(style, container) + container.children.each do |child| + child.update_styles(style) + + recursive_styles(style, child) if child.is_a?(Container) + end + end + + # Enable child elements to display their tooltips + # but fall back to the Widget if no hit element has a tip + def tip + elements = hit_element?(window.mouse_x, window.mouse_y) + + return @tip unless elements + + elements.delete(self) # prevent infinite recursive loop (Widget#tip) + elements.reverse.find { |e| !e.tip.empty? }&.tip || @tip + end + end + end +end diff --git a/lib/cyberarm_engine/ui/gui_state.rb b/lib/cyberarm_engine/ui/gui_state.rb index 6002fce..f73a0f3 100644 --- a/lib/cyberarm_engine/ui/gui_state.rb +++ b/lib/cyberarm_engine/ui/gui_state.rb @@ -168,7 +168,7 @@ module CyberarmEngine # list of containers decending down to hit element new_hit_elements = (@menu || @root_container).hit_element?(window.mouse_x, window.mouse_y) # element the mouse is over, if any. - new_mouse_over = new_hit_elements&.last + new_mouse_over = new_hit_elements&.find { |c| c.is_a?(CyberarmEngine::Element::Widget) } || new_hit_elements&.last # is the currently hit element the same as last hit element? same_element = @mouse_over && new_mouse_over == @mouse_over