# Copyright 2022 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 Stack def initialize(menu) @stack = []; @stack << menu; end def current_menu() = @stack[-1]; def push(menu) = @stack << menu; def pop() @stack.pop() if @stack.size > 1; end def draw() = @stack.each {_1.draw();} def size() = @stack.size; end 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