# frozen_string_literal: true module Gruff module Mini # A module to handle the small legend. # @private module Legend attr_accessor :hide_mini_legend, :legend_position def initialize(*) @hide_mini_legend = false @legend_position = nil super end ## # The canvas needs to be bigger so we can put the legend beneath it. def expand_canvas_for_vertical_legend return if @hide_mini_legend @legend_labels = store.data.map(&:label) legend_height = scale((store.length * calculate_line_height) + @top_margin + @bottom_margin) @original_rows = @raw_rows @original_columns = @raw_columns case @legend_position when :right @rows = [@rows, legend_height].max @columns += calculate_legend_width + @left_margin else font = @legend_font.dup font.size = scale(font.size) @rows += store.length * calculate_caps_height(font) * 1.7 end @renderer = Gruff::Renderer.new(@columns, @rows, @scale, @theme_options) end def calculate_line_height calculate_caps_height(@legend_font) * 1.7 end def calculate_legend_width width = @legend_labels.map { |label| calculate_width(@legend_font, label) }.max scale(width + (40 * 1.7)) end ## # Draw the legend beneath the existing graph. def draw_vertical_legend return if @hide_mini_legend legend_square_width = 40.0 # small square with color of this item @legend_left_margin = 100.0 legend_top_margin = 40.0 case @legend_position when :right current_x_offset = @original_columns + @left_margin current_y_offset = @top_margin + legend_top_margin else current_x_offset = @legend_left_margin current_y_offset = @original_rows + legend_top_margin end @legend_labels.each_with_index do |legend_label, index| # Draw label x_offset = current_x_offset + (legend_square_width * 1.7) label = truncate_legend_label(legend_label, x_offset) text_renderer = Gruff::Renderer::Text.new(renderer, label, font: @legend_font) text_renderer.add_to_render_queue(@raw_columns, 1.0, x_offset, current_y_offset, Magick::WestGravity) # Now draw box with color of this dataset rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: store.data[index].color) rect_renderer.render(current_x_offset, current_y_offset - (legend_square_width / 2.0), current_x_offset + legend_square_width, current_y_offset + (legend_square_width / 2.0)) current_y_offset += calculate_line_height end end ## # Shorten long labels so they will fit on the canvas. # # Department of Hu... def truncate_legend_label(label, x_offset) truncated_label = label.to_s font = @legend_font.dup font.size = scale(font.size) max_width = @columns - scale(x_offset) - @right_margin while calculate_width(font, "#{truncated_label}...") > max_width && truncated_label.length > 1 truncated_label = truncated_label[0..truncated_label.length - 2] end truncated_label + (truncated_label.length < label.to_s.length ? '...' : '') end def scale(value) value * @scale end end end end