diff --git a/lib/cyberarm_engine.rb b/lib/cyberarm_engine.rb index 07b4f5b..e04f64c 100644 --- a/lib/cyberarm_engine.rb +++ b/lib/cyberarm_engine.rb @@ -24,6 +24,8 @@ require_relative "cyberarm_engine/background" require_relative "cyberarm_engine/text" require_relative "cyberarm_engine/timer" +require_relative "cyberarm_engine/ui/dsl" + require_relative "cyberarm_engine/ui/theme" require_relative "cyberarm_engine/ui/event" require_relative "cyberarm_engine/ui/style" @@ -40,7 +42,5 @@ require_relative "cyberarm_engine/ui/elements/stack" require_relative "cyberarm_engine/ui/elements/check_box" require_relative "cyberarm_engine/ui/elements/progress" -require_relative "cyberarm_engine/ui/dsl" - require_relative "cyberarm_engine/game_state" require_relative "cyberarm_engine/ui/gui_state" diff --git a/lib/cyberarm_engine/ui/dsl.rb b/lib/cyberarm_engine/ui/dsl.rb index f68dc04..579a236 100644 --- a/lib/cyberarm_engine/ui/dsl.rb +++ b/lib/cyberarm_engine/ui/dsl.rb @@ -25,66 +25,52 @@ module CyberarmEngine end def label(text, options = {}, &block) - options[:parent] = @containers.last + options[:parent] = element_parent options[:theme] = current_theme - _element = Element::Label.new(text, options, block) - @containers.last.add(_element) - return _element + add_element( Element::Label.new(text, options, block) ) end def button(text, options = {}, &block) - options[:parent] = @containers.last + options[:parent] = element_parent options[:theme] = current_theme - _element = Element::Button.new(text, options, block) { if block.is_a?(Proc); block.call; end } - @containers.last.add(_element) - return _element + add_element( Element::Button.new(text, options, block) { if block.is_a?(Proc); block.call; end } ) end def edit_line(text, options = {}, &block) - options[:parent] = @containers.last + options[:parent] = element_parent options[:theme] = current_theme - _element = Element::EditLine.new(text, options, block) - @containers.last.add(_element) - return _element + add_element( Element::EditLine.new(text, options, block) ) end def toggle_button(options = {}, &block) - options[:parent] = @containers.last + options[:parent] = element_parent options[:theme] = current_theme - _element = Element::ToggleButton.new(options, block) - @containers.last.add(_element) - return _element + add_element( Element::ToggleButton.new(options, block) ) end def check_box(text, options = {}, &block) - options[:parent] = @containers.last + options[:parent] = element_parent options[:theme] = current_theme - _element = Element::CheckBox.new(text, options, block) - @containers.last.add(_element) - return _element + add_element( Element::CheckBox.new(text, options, block) ) end def image(path, options = {}, &block) - options[:parent] = @containers.last + options[:parent] = element_parent options[:theme] = current_theme - _element = Element::Image.new(path, options, block) - @containers.last.add(_element) - return _element + add_element( Element::Image.new(path, options, block) ) end def progress(options = {}, &block) - options[:parent] = @containers.last + options[:parent] = element_parent options[:theme] = current_theme - _element = Element::Progress.new(options, block) - @containers.last.add(_element) - return _element + element_parent( Element::Progress.new(options, block) ) end def background(color = Gosu::Color::NONE) @@ -92,11 +78,23 @@ module CyberarmEngine end def theme(theme) - @containers.last.options[:theme] = theme + self.is_a?(CyberarmEngine::Element::Container) ? self : @containers.last + + element_parent.options[:theme] = theme end def current_theme - @containers.last.options[:theme] + element_parent.options[:theme] + end + + private def add_element(element) + element_parent.add(element) + + return element + end + + private def element_parent + self.is_a?(CyberarmEngine::Element::Container) ? self : @containers.last end end end \ No newline at end of file diff --git a/lib/cyberarm_engine/ui/elements/container.rb b/lib/cyberarm_engine/ui/elements/container.rb index edc022e..24a50fa 100644 --- a/lib/cyberarm_engine/ui/elements/container.rb +++ b/lib/cyberarm_engine/ui/elements/container.rb @@ -2,6 +2,7 @@ module CyberarmEngine class Element class Container < Element include Common + include CyberarmEngine::DSL attr_accessor :stroke_color, :fill_color attr_reader :children, :gui_state @@ -31,6 +32,12 @@ module CyberarmEngine recalculate end + def clear(&block) + @children.clear + + block.call(self) if block + end + def render Gosu.clip_to(@x, @y, width, height) do @children.each(&:draw) diff --git a/lib/cyberarm_engine/ui/elements/edit_line.rb b/lib/cyberarm_engine/ui/elements/edit_line.rb index 271bb7a..62c66a1 100644 --- a/lib/cyberarm_engine/ui/elements/edit_line.rb +++ b/lib/cyberarm_engine/ui/elements/edit_line.rb @@ -16,16 +16,31 @@ module CyberarmEngine @text_input = Gosu::TextInput.new @text_input.text = text + @offset_x = 0 + return self end def render Gosu.clip_to(@text.x, @text.y, @style.width, @text.height) do - draw_text - Gosu.draw_rect(caret_position, @text.y, @caret_width, @caret_height, @caret_color, @z + 40) if @focus && @show_caret + Gosu.translate(-@offset_x, 0) do + draw_selection + draw_caret if @focus && @show_caret + draw_text + end end end + def draw_caret + Gosu.draw_rect(caret_position, @text.y, @caret_width, @caret_height, @caret_color, @z) + end + + def draw_selection + selection_width = caret_position - selection_start_position + + Gosu.draw_rect(selection_start_position, @text.y, selection_width, @text.height, default(:selection_color), @z) + end + def update if @type == :password @text.text = default(:password_character) * @text_input.text.length @@ -38,6 +53,51 @@ module CyberarmEngine @show_caret = !@show_caret end + + keep_caret_visible + end + + def move_caret_to_mouse(mouse_x) + 1.upto(@text.text.length) do |i| + if mouse_x < @text.x + @text.textobject.text_width(@text.text[0...i]) + @text_input.caret_pos = @text_input.selection_start = i - 1; + return + end + end + + @text_input.caret_pos = @text_input.selection_start = @text_input.text.length + end + + def keep_caret_visible + caret_pos = (caret_position - @text.x) + @caret_width + + @last_text ||= "/\\" + @last_pos ||= -1 + + puts "caret pos: #{caret_pos}, width: #{@width}, offset: #{@offset_x}" if (@last_text != @text.text) || (@last_pos != caret_pos) + + @last_text = @text.text + @last_pos = caret_pos + + + if caret_pos.between?(@offset_x, @width + @offset_x) + # Do nothing + + elsif caret_pos < @offset_x + if caret_pos > @width + @offset_x = caret_pos + @width + else + @offset_x = 0 + end + + elsif caret_pos > @width + @offset_x = caret_pos - @width + puts "triggered" + + else + # Reset to Zero + @offset_x = 0 + end end def left_mouse_button(sender, x, y) @@ -47,6 +107,8 @@ module CyberarmEngine @caret_last_interval = Gosu.milliseconds @show_caret = true + move_caret_to_mouse(x) + return :handled end @@ -79,12 +141,19 @@ module CyberarmEngine return :handled end - # TODO: Fix caret rendering in wrong position unless caret_pos is at end of text def caret_position + text_input_position_for(:caret_pos) + end + + def selection_start_position + text_input_position_for(:selection_start) + end + + def text_input_position_for(method) if @type == :password - @text.x + @text.textobject.text_width(default(:password_character) * @text_input.text[0..@text_input.caret_pos-1].length) + @text.x + @text.textobject.text_width(default(:password_character) * @text_input.text[0..@text_input.send(method)].length) else - @text.x + @text.textobject.text_width(@text_input.text[0..@text_input.caret_pos-1]) + @text.x + @text.textobject.text_width(@text_input.text[0..@text_input.send(method)]) end end diff --git a/lib/cyberarm_engine/ui/theme.rb b/lib/cyberarm_engine/ui/theme.rb index 0fda161..76728df 100644 --- a/lib/cyberarm_engine/ui/theme.rb +++ b/lib/cyberarm_engine/ui/theme.rb @@ -88,6 +88,7 @@ module CyberarmEngine caret_width: 2, caret_color: Gosu::Color::WHITE, caret_interval: 500, + selection_color: Gosu::Color::GREEN, }, Image: { # < Element