@@ -23,7 +23,7 @@ module Gruff
2323 # A common base class inherited from class of drawing a graph.
2424 class Base
2525 # Space around text elements. Mostly used for vertical spacing.
26- LEGEND_MARGIN = 20 .0
26+ LEGEND_MARGIN = 10 .0
2727 TITLE_MARGIN = 20.0
2828 LABEL_MARGIN = 15.0
2929 DEFAULT_MARGIN = 20.0
@@ -48,9 +48,6 @@ class Base
4848 # Blank space below the title. Default is +20+.
4949 attr_writer :title_margin #: Float | Integer
5050
51- # Blank space below the legend. Default is +20+.
52- attr_writer :legend_margin #: Float | Integer
53-
5451 # Truncates labels if longer than max specified.
5552 attr_writer :label_max_size #: Float | Integer
5653
@@ -115,13 +112,16 @@ class Base
115112 # first. This does not affect the legend. Default is +false+.
116113 attr_writer :sorted_drawing #: bool
117114
118- # Display the legend under the graph. Default is +false+.
119- attr_writer :legend_at_bottom #: bool
115+ # Blank space below the legend. Default is +20+.
116+ attr_writer :legend_margin #: Float | Integer
117+
118+ # Set the vertical spacing between individual legend items. Default is +5.0+.
119+ attr_writer :legend_spacing #: Float | Integer
120120
121- # Optionally set the size of the colored box by each item in the legend .
122- # Default is +20.0+.
123- #
124- # Will be scaled down if graph is smaller than 800px wide .
121+ # Set the inner padding between the legend frame and its contents. Default is +7.0+ .
122+ attr_writer :legend_padding #: Float | Integer
123+
124+ # Optionally set the size of the colored box by each item in the legend. Default is +20.0+ .
125125 attr_writer :legend_box_size #: Float | Integer
126126
127127 # If one numerical argument is given, the graph is drawn at 4/3 ratio
@@ -190,19 +190,21 @@ def initialize_attributes
190190
191191 @title_font = Gruff ::Font . new ( size : 36.0 , bold : true )
192192 @marker_font = Gruff ::Font . new ( size : 21.0 )
193- @legend_font = Gruff ::Font . new ( size : 20 .0)
193+ @legend_font = Gruff ::Font . new ( size : 12 .0)
194194 @no_data_font = Gruff ::Font . new ( size : 80.0 )
195195
196196 @label_margin = LABEL_MARGIN
197197 @top_margin = @bottom_margin = @left_margin = @right_margin = DEFAULT_MARGIN
198- @legend_margin = LEGEND_MARGIN
199198 @title_margin = TITLE_MARGIN
200199
201- @legend_box_size = 20.0
200+ @legend_margin = LEGEND_MARGIN
201+ @legend_spacing = 5.0
202+ @legend_padding = 7.0
203+ @legend_box_size = 10.0
202204
203205 @no_data_message = 'No Data'
204206
205- @hide_line_markers = @hide_legend = @hide_title = @hide_line_numbers = @legend_at_bottom = false
207+ @hide_line_markers = @hide_legend = @hide_title = @hide_line_numbers = false
206208 @label_max_size = 0
207209 @label_truncation_style = :absolute
208210 @label_rotation = 0
@@ -262,6 +264,13 @@ def label_stagger_height=(_value)
262264 warn '#label_stagger_height= is deprecated. It is no longer effective.'
263265 end
264266
267+ # Set the legend position to the bottom of the graph.
268+ # @deprecated
269+ # @rbs return: void
270+ def legend_at_bottom = ( _value )
271+ warn '#legend_at_bottom= is deprecated. It is no longer effective.'
272+ end
273+
265274 # Set the large title of the graph displayed at the top.
266275 # You can draw a multi-line title by putting a line break in the string
267276 # or by setting an array as argument.
@@ -629,11 +638,11 @@ def draw
629638
630639 setup_drawing
631640
632- draw_legend
633641 draw_line_markers
634642 draw_axis_labels
635643 draw_title
636644 draw_graph
645+ draw_legend
637646 end
638647
639648 protected
@@ -822,46 +831,42 @@ def center(size)
822831 def draw_legend
823832 return if @hide_legend
824833
825- legend_labels = store . data . map ( &:label )
826- legend_square_width = @legend_box_size # small square with color of this item
827- legend_label_lines = calculate_legend_label_widths_for_each_line ( legend_labels , legend_square_width )
828- line_height = [ legend_caps_height , legend_square_width ] . max + @legend_margin
834+ legend_labels = store . data . map ( &:label ) . reject ( &:empty? )
835+ return if legend_labels . empty?
829836
830- current_y_offset = begin
831- if @legend_at_bottom
832- @graph_bottom + @legend_margin + labels_caps_height + @label_margin + ( @x_axis_label ? ( @label_margin * 2 ) + marker_caps_height : 0 )
833- else
834- hide_title? ? @top_margin + @title_margin : @top_margin + @title_margin + title_caps_height
835- end
836- end
837+ line_height = [ legend_caps_height , @legend_box_size ] . max + @legend_spacing
837838
838- index = 0
839- legend_label_lines . each do |( legend_labels_width , legend_labels_line ) |
840- current_x_offset = center ( legend_labels_width )
841-
842- legend_labels_line . each do |legend_label |
843- unless legend_label . empty?
844- legend_label_width = calculate_width ( @legend_font , legend_label )
845-
846- # Draw label
847- text_renderer = Gruff ::Renderer ::Text . new ( renderer , legend_label , font : @legend_font )
848- text_renderer . add_to_render_queue ( legend_label_width ,
849- legend_square_width ,
850- current_x_offset + ( legend_square_width * 1.7 ) ,
851- current_y_offset ,
852- Magick ::CenterGravity )
853-
854- # Now draw box with color of this dataset
855- rect_renderer = Gruff ::Renderer ::Rectangle . new ( renderer , color : store . data [ index ] . color )
856- rect_renderer . render ( current_x_offset ,
857- current_y_offset ,
858- current_x_offset + legend_square_width ,
859- current_y_offset + legend_square_width )
860-
861- current_x_offset += legend_label_width + ( legend_square_width * 2.7 )
862- end
863- index += 1
864- end
839+ # Draw legend inside graph area, top-right corner, stacked vertically
840+ max_legend_label_width = legend_labels . map { |l | calculate_width ( @legend_font , l ) } . max || 0.0
841+ current_x_offset = @graph_right - @legend_margin - ( @legend_box_size * 1.5 ) - max_legend_label_width
842+ current_y_offset = @graph_top + @legend_margin + @legend_spacing
843+ last_item_y_offset = current_y_offset + ( line_height * ( legend_labels . size - 1 ) )
844+
845+ legend_items_end_x = @graph_right - @legend_margin
846+ legend_items_end_y = last_item_y_offset + @legend_box_size
847+
848+ # Draw legend frame around all items
849+ frame_renderer = Gruff ::Renderer ::Rectangle . new ( renderer , color : @marker_color , width : 1.1 , opacity : 0.2 , round : true )
850+ frame_renderer . render ( current_x_offset - @legend_padding ,
851+ current_y_offset - @legend_padding ,
852+ legend_items_end_x + @legend_padding ,
853+ legend_items_end_y + @legend_padding )
854+
855+ legend_labels . each_with_index do |legend_label , index |
856+ legend_label_width = calculate_width ( @legend_font , legend_label )
857+
858+ text_renderer = Gruff ::Renderer ::Text . new ( renderer , legend_label , font : @legend_font )
859+ text_renderer . add_to_render_queue ( legend_label_width ,
860+ @legend_box_size ,
861+ current_x_offset + ( @legend_box_size * 1.5 ) ,
862+ current_y_offset ,
863+ Magick ::CenterGravity )
864+
865+ rect_renderer = Gruff ::Renderer ::Rectangle . new ( renderer , color : store . data [ index ] . color )
866+ rect_renderer . render ( current_x_offset ,
867+ current_y_offset ,
868+ current_x_offset + @legend_box_size ,
869+ current_y_offset + @legend_box_size )
865870
866871 current_y_offset += line_height
867872 end
@@ -1123,14 +1128,12 @@ def setup_top_margin
11231128 # When @hide title, leave a title_margin space for aesthetics.
11241129 # Same with @hide_legend
11251130 @top_margin +
1126- ( hide_title? ? @title_margin : title_caps_height + @title_margin ) +
1127- ( @hide_legend || @legend_at_bottom ? @legend_margin : calculate_legend_height + @legend_margin )
1131+ ( hide_title? ? @title_margin : title_caps_height + @title_margin )
11281132 end
11291133
11301134 # @rbs return: Float
11311135 def setup_bottom_margin
11321136 graph_bottom_margin = hide_bottom_label_area? ? @bottom_margin : @bottom_margin + labels_caps_height + @label_margin
1133- graph_bottom_margin += ( calculate_legend_height + @legend_margin ) if @legend_at_bottom
11341137
11351138 x_axis_label_height = @x_axis_label . nil? ? 0.0 : marker_caps_height + ( @label_margin * 2 )
11361139 @raw_rows - graph_bottom_margin - x_axis_label_height
@@ -1211,42 +1214,6 @@ def y_axis_label(value, increment)
12111214 end
12121215 end
12131216
1214- # @rbs legend_labels: Array[String]
1215- # @rbs legend_square_width: Float | Integer
1216- # @rbs return: Array[Array[Float | Integer]]
1217- def calculate_legend_label_widths_for_each_line ( legend_labels , legend_square_width )
1218- label_widths = [ [ ] ]
1219- label_lines = [ [ ] ]
1220- legend_labels . each do |label |
1221- if label . empty?
1222- label_width = 0.0
1223- else
1224- width = calculate_width ( @legend_font , label )
1225- label_width = width + ( legend_square_width * 2.7 )
1226- end
1227- label_widths . last . push label_width
1228- label_lines . last . push label
1229-
1230- if label_widths . last . sum > ( @raw_columns * 0.9 )
1231- label_widths . push [ label_widths . last . pop ]
1232- label_lines . push [ label_lines . last . pop ]
1233- end
1234- end
1235-
1236- label_widths . map ( &:sum ) . zip ( label_lines )
1237- end
1238-
1239- # @rbs return: Float
1240- def calculate_legend_height
1241- return 0.0 if @hide_legend
1242-
1243- legend_labels = store . data . map ( &:label )
1244- legend_label_lines = calculate_legend_label_widths_for_each_line ( legend_labels , @legend_box_size )
1245- line_height = [ legend_caps_height , @legend_box_size ] . max
1246-
1247- ( line_height * legend_label_lines . count ) + ( @legend_margin * ( legend_label_lines . count - 1 ) )
1248- end
1249-
12501217 # Returns the height of the capital letter 'X' for the current font and
12511218 # size.
12521219 #
0 commit comments