summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/menu.rb202
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