diff options
author | Frederico Linhares <fred@linhares.blue> | 2022-03-29 11:51:11 -0300 |
---|---|---|
committer | Frederico Linhares <fred@linhares.blue> | 2022-04-06 16:41:51 -0300 |
commit | 418f45f78bbf743021c53030da2ad2158fa355d2 (patch) | |
tree | 1ce50685cdced80b06039f603d9600e4316c3a3c /lib |
Initial commit
Diffstat (limited to 'lib')
-rw-r--r-- | lib/menu.rb | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/lib/menu.rb b/lib/menu.rb new file mode 100644 index 0000000..a3f1533 --- /dev/null +++ b/lib/menu.rb @@ -0,0 +1,202 @@ +# Copyright 2021 Frederico de Oliveira Linhares +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +module CandyGear + class Menu + class BorderlessView + attr_reader(:texture, :font, :text_color, :bg_color, :sprites); + + def initialize( + texture, font, text_color, bg_color, sprite_width, sprite_height) + @texture = texture; + @font = font; + @text_color = text_color; + @bg_color = bg_color; + @sprite_width = sprite_width; + @sprite_height = sprite_height; + + @sprites = {}; + @sprites[:arrow_select] = Sprite.new( + @texture, 1 * @sprite_width, 1 * @sprite_height, + @sprite_width, @sprite_height); + end + + def draw(x, y, width, height) + # Nothing. + end + + def border_width() = 0; + def border_height() = 0; + end + + class BorderedView + attr_reader( + :texture, :font, :text_color, :bg_color, :sprites, :border_width, + :border_height); + + def initialize( + texture, font, text_color, bg_color, sprite_width, sprite_height) + @texture = texture; + @font = font; + @text_color = text_color; + @bg_color = bg_color; + @border_width = sprite_width; + @border_height = sprite_height; + + @sprites = {}; + @sprites[:arrow_select] = Sprite.new( + @texture, 1 * @border_width, 1 * @border_height, + @border_width, @border_height); + @sprites[:box_top_left] = Sprite.new( + @texture, 0, 0, @border_width, @border_height); + @sprites[:box_top] = Sprite.new( + @texture, 1 * @border_width, 0, + @border_width, @border_height); + @sprites[:box_top_right] = Sprite.new( + @texture, 2 * @border_height, 0, + @border_width, @border_height); + @sprites[:box_left] = Sprite.new( + @texture, 0, 1 * @border_height, + @border_width, @border_height); + @sprites[:box_right] = Sprite.new( + @texture, 2 * @border_width, 1 * @border_height, + @border_width, @border_height); + @sprites[:box_bottom_left] = Sprite.new( + @texture, 0, 2 * @border_height, + @border_width, @border_height); + @sprites[:box_bottom] = Sprite.new( + @texture, 1 * @border_width, 2 * @border_height, + @border_width, @border_height); + @sprites[:box_bottom_right] = Sprite.new( + @texture, 2 * @border_width, 2 * @border_height, + @border_width, @border_height); + end + + def draw(x, y, width, height) + num_horizontal_sprites = width / @border_width + 1; + num_horizontal_sprites += 1 if width % @border_width > 0; + num_vertical_sprites = height / @border_height; + num_vertical_sprites += 1 if height % @border_height > 0; + background = Rect.new( + x, y, + (num_horizontal_sprites + 2) * @border_width, + (num_vertical_sprites + 2) * @border_height); + + Graphic.set_color(@bg_color); + background.draw_fill(); + + # Draw the corners. + @sprites[:box_top_left].draw_xy(x, y); + @sprites[:box_top_right].draw_xy( + @border_width * (num_horizontal_sprites + 1) + x, y); + @sprites[:box_bottom_left].draw_xy( + x, @border_height * (num_vertical_sprites + 1) + y); + @sprites[:box_bottom_right].draw_xy( + @border_width * (num_horizontal_sprites + 1) + x, + @border_height * (num_vertical_sprites + 1) + y); + + # Draw the edges. + num_horizontal_sprites.times do |i| + # Top + @sprites[:box_top].draw_xy(@border_width * (i + 1) + x, y); + # Bottom + @sprites[:box_bottom].draw_xy( + @border_width * (i + 1) + x, + @border_height * (num_vertical_sprites + 1) + y); + end + num_vertical_sprites.times do |i| + # Left + @sprites[:box_left].draw_xy(x, @border_height * (i + 1) + y); + # Right + @sprites[:box_right].draw_xy( + @border_width * (num_horizontal_sprites + 1) + x, + @border_height * (i + 1) + y); + end + end + end + + class Option + attr_reader(:action, :text); + + def initialize(text, action); + @text = text; + @action = action; + end + end + + attr_reader(:width, :height); + + def initialize(view, pos_x, pos_y, options) + @view = view; + + @pos_x = pos_x; + @pos_y = pos_y; + + @options = options.map do |opt| + Option.new( + Texture.from_text( + opt[:text], view.font, view.text_color, view.bg_color), + opt[:action]); + end + @current_option = 0; + @option_max_width = 0; + @option_max_height = 0; + + @options.each do |i| + if @option_max_width < i.text.width then + @option_max_width = i.text.width; + end + if @option_max_height < i.text.height then + @option_max_height = i.text.height; + end + end + + @width = @option_max_width; + @height = @option_max_height * @options.size; + end + + def next_opt() + @current_option += 1; + @current_option = 0 if @current_option >= @options.size(); + end + + def pred_opt() + if @current_option <= 0 then + @current_option = @options.size - 1; + else + @current_option -= 1; + end + end + + def activate() + @options[@current_option].action.call(); + end + + def draw() + @view.draw(@pos_x, @pos_y, @width, @height); + + @options.each_with_index do |opt, i| + opt.text.draw_xy( + @pos_x + @view.border_width + @view.sprites[:arrow_select].width, + @pos_y + @view.border_height + + @option_max_height * i); + end + + @view.sprites[:arrow_select].draw_xy( + @pos_x + @view.border_width, + @pos_y + @view.border_height + + @option_max_height * @current_option); + end + end +end |