gruff 0.18.0-java → 0.20.0-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a00db2218eaaafaa261ece0433671849fae44f4eccbf7e53fdb28767f11022ea
4
- data.tar.gz: 904fe6ad5c4694308b20740e12adde7483b11f16eb7eea75061af57935a6c285
3
+ metadata.gz: 0470a845dea66723f512a991696cefcec76110bc625720c9de2e06b248968dfb
4
+ data.tar.gz: d6d93d5ac547d1b588e8b936b8faf1bdbdd86b1f6b05859c62569dcc2096ddf0
5
5
  SHA512:
6
- metadata.gz: 2e33b0cfbbe2f1c99d8bca06a9914ce0e53b060d3b01434f2a3c15a49795fc2ba2b8dc94964c99cd548a8d466de865d92430f39d863f040ffa6d68ab8aadb28c
7
- data.tar.gz: 7d6673cf33d50a250e9f1cde7d7caa23b2a0edcf9a780e0feb784f24dbac36eb768dee29409291e7968ca445a38ba06caea52c210678e50c429cfb1a39c635f4
6
+ metadata.gz: d57209f9c7dc7d3739feea9d1d1cfb41afd85db57d3723a768c17f37413f689becaabba7a119f33a97ed7e4fab7a4906c8a334a8d230cee537fa164d62cd3f01
7
+ data.tar.gz: 697e7f71c16e5c8d5351144b5cd9fff0bef80a7d9f2dee100dd5e6f90daf712ca041cf8acd581830de8763b697a9c8b66b7b3ddd51df7cd40ece16fac0bc37f7
@@ -0,0 +1,26 @@
1
+ // For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
2
+ // https://github.com/microsoft/vscode-dev-containers/tree/v0.245.0/containers/docker-existing-dockerfile
3
+ {
4
+ "name": "Existing Dockerfile",
5
+
6
+ // Sets the run context to one level up instead of the .devcontainer folder.
7
+ "context": "..",
8
+
9
+ // Update the 'dockerFile' property if you aren't using the standard 'Dockerfile' filename.
10
+ "dockerFile": "../Dockerfile"
11
+
12
+ // Use 'forwardPorts' to make a list of ports inside the container available locally.
13
+ // "forwardPorts": [],
14
+
15
+ // Uncomment the next line to run commands after the container is created - for example installing curl.
16
+ // "postCreateCommand": "apt-get update && apt-get install -y curl",
17
+
18
+ // Uncomment when using a ptrace-based debugger like C++, Go, and Rust
19
+ // "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ],
20
+
21
+ // Uncomment to use the Docker CLI from inside the container. See https://aka.ms/vscode-remote/samples/docker-from-docker.
22
+ // "mounts": [ "source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind" ],
23
+
24
+ // Uncomment to connect as a non-root user if you've added one. See https://aka.ms/vscode-remote/containers/non-root.
25
+ // "remoteUser": "vscode"
26
+ }
@@ -11,17 +11,17 @@ permissions:
11
11
 
12
12
  jobs:
13
13
  lint:
14
- runs-on: ubuntu-20.04
14
+ runs-on: ubuntu-22.04
15
15
  timeout-minutes: 20
16
16
  name: Lint
17
17
  steps:
18
18
  - uses: actions/checkout@v3
19
19
  with:
20
20
  ref: ${{ github.event.pull_request.head.sha }}
21
- - name: Set up Ruby 2.5
21
+ - name: Set up Ruby 2.6
22
22
  uses: ruby/setup-ruby@master
23
23
  with:
24
- ruby-version: '2.5'
24
+ ruby-version: '2.6'
25
25
  bundler-cache: true
26
26
  - name: Install dependencies
27
27
  run: bundle install --path=vendor/bundle --jobs 4 --retry 3
@@ -31,13 +31,13 @@ jobs:
31
31
  run: bundle exec rubocop
32
32
 
33
33
  test-ruby:
34
- runs-on: ubuntu-20.04
34
+ runs-on: ubuntu-22.04
35
35
  timeout-minutes: 20
36
36
  strategy:
37
37
  matrix:
38
- ruby-version: ['2.5', '2.6', '2.7', '3.0', '3.1']
38
+ ruby-version: ['2.6', '2.7', '3.0', '3.1', '3.2']
39
39
  imagemagick-version:
40
- - { full: 7.1.0-39, major-minor: '7.0' }
40
+ - { full: 7.1.0-55, major-minor: '7.1' }
41
41
  name: Ruby ${{ matrix.ruby-version }}
42
42
  steps:
43
43
  - uses: actions/checkout@v3
@@ -63,11 +63,11 @@ jobs:
63
63
  run: bundle exec rake
64
64
 
65
65
  test-jruby:
66
- runs-on: ubuntu-20.04
66
+ runs-on: ubuntu-22.04
67
67
  timeout-minutes: 20
68
68
  strategy:
69
69
  matrix:
70
- ruby-version: ['9.2.20.1', '9.3.4.0']
70
+ ruby-version: ['9.3.10.0', '9.4.2.0']
71
71
  name: JRuby ${{ matrix.ruby-version }}
72
72
  steps:
73
73
  - uses: actions/checkout@v3
data/.rubocop.yml CHANGED
@@ -1,10 +1,11 @@
1
1
  require:
2
+ - rubocop-minitest
2
3
  - rubocop-performance
3
4
  - rubocop-rake
4
5
 
5
6
  AllCops:
6
7
  EnabledByDefault: true
7
- TargetRubyVersion: 2.5
8
+ TargetRubyVersion: 2.6
8
9
  Exclude:
9
10
  - 'vendor/bundle/**/*'
10
11
  - 'rails_generators/gruff/**/*'
@@ -12,6 +13,12 @@ AllCops:
12
13
  Metrics:
13
14
  Enabled: false
14
15
 
16
+ Gemspec/DependencyVersion:
17
+ Enabled: false
18
+
19
+ Gemspec/DevelopmentDependencies:
20
+ Enabled: false
21
+
15
22
  Gemspec/OrderedDependencies:
16
23
  Enabled: false
17
24
 
@@ -21,6 +28,9 @@ Gemspec/RequiredRubyVersion:
21
28
  Layout/AccessModifierIndentation:
22
29
  EnforcedStyle: outdent
23
30
 
31
+ Layout/ClassStructure:
32
+ Enabled: false
33
+
24
34
  Layout/FirstMethodArgumentLineBreak:
25
35
  Enabled: false
26
36
 
@@ -111,11 +121,17 @@ Style/OptionHash:
111
121
  Style/RedundantBegin:
112
122
  Enabled: false
113
123
 
124
+ Style/RequireOrder:
125
+ Enabled: false
126
+
114
127
  Style/SingleLineBlockParams:
115
128
  Enabled: false
116
129
 
117
130
  Style/StructInheritance:
118
131
  Enabled: false
119
132
 
133
+ Style/YodaExpression:
134
+ Enabled: false
135
+
120
136
  Performance/ChainArrayAllocation:
121
137
  Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.20.0
4
+ - Fix legend position when blank labels present (#614)
5
+ - Fixed NoMethodError (undefined method `format=' for Gruff::Line (#612)
6
+ - Drop Ruby 2.5 support (#611)
7
+ - Fix deprecation warning for Base#to_blob (#610)
8
+
9
+ ## 0.19.0
10
+ - Draw the graph starting from zero point by default (#609)
11
+ - Improve joints in Gruff::Net using polyline method (#608)
12
+ - Improve joints in Gruff::Line using polyline method (#607)
13
+ - Adjust default font size in Gruff::Mini::{Bar, Pie}
14
+
3
15
  ## 0.18.0
4
16
  - Add Gruff::Bubble (#604)
5
17
  - Rename Gruff::BoxPlot to Gruff::Box (#603)
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Gruff Graphs
2
2
 
3
- [![Build Status](https://travis-ci.org/topfunky/gruff.svg?branch=master)](https://travis-ci.org/topfunky/gruff)
3
+ [![CI](https://github.com/topfunky/gruff/actions/workflows/ci.yml/badge.svg)](https://github.com/topfunky/gruff/actions/workflows/ci.yml)
4
4
  [![Gem Version](https://badge.fury.io/rb/gruff.svg)](https://badge.fury.io/rb/gruff)
5
5
 
6
6
  A library for making beautiful graphs.
data/gruff.gemspec CHANGED
@@ -17,19 +17,19 @@ Gem::Specification.new do |s|
17
17
  s.summary = 'Beautiful graphs for one or multiple datasets.'
18
18
  s.license = 'MIT'
19
19
  s.executables = s.files.grep(%r{^bin/}).map { |f| File.basename(f) }
20
- s.specification_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
21
20
 
22
21
  if defined? JRUBY_VERSION
23
22
  s.platform = 'java'
24
23
  s.add_dependency 'rmagick4j'
25
24
  else
26
25
  s.add_dependency 'rmagick', '>= 4.2'
27
- s.add_development_dependency 'rubocop', '~> 1.28.2'
28
- s.add_development_dependency 'rubocop-performance', '~> 1.13.3'
26
+ s.add_development_dependency 'rubocop', '~> 1.50.2'
27
+ s.add_development_dependency 'rubocop-minitest', '~> 0.30.0'
28
+ s.add_development_dependency 'rubocop-performance', '~> 1.17.1'
29
29
  s.add_development_dependency 'rubocop-rake', '~> 0.6.0'
30
30
  end
31
31
  s.add_dependency 'histogram'
32
- s.required_ruby_version = '>= 2.5.0'
32
+ s.required_ruby_version = '>= 2.6.0'
33
33
 
34
34
  s.add_development_dependency 'rake'
35
35
  s.add_development_dependency 'minitest-reporters'
data/lib/gruff/bar.rb CHANGED
@@ -48,7 +48,7 @@ class Gruff::Bar < Gruff::Base
48
48
  #
49
49
  # Default value is +0.9+.
50
50
  def spacing_factor=(space_percent)
51
- raise ArgumentError, 'spacing_factor must be between 0.00 and 1.00' unless (space_percent >= 0) && (space_percent <= 1)
51
+ raise ArgumentError, 'spacing_factor must be between 0.00 and 1.00' if (space_percent < 0) || (space_percent > 1)
52
52
 
53
53
  @spacing_factor = (1 - space_percent)
54
54
  end
data/lib/gruff/base.rb CHANGED
@@ -218,7 +218,7 @@ module Gruff
218
218
  # g.labels = ['2005', nil, nil, '2006', nil, nil, '2007', nil, nil, '2008'] # same labels for columns
219
219
  def labels=(labels)
220
220
  if labels.is_a?(Array)
221
- labels = labels.each_with_index.each_with_object({}) do |(label, index), hash|
221
+ labels = labels.each_with_index.with_object({}) do |(label, index), hash|
222
222
  hash[index] = label
223
223
  end
224
224
  end
@@ -469,7 +469,8 @@ module Gruff
469
469
  #
470
470
  # Set it after you have given all your data to the graph object.
471
471
  def minimum_value
472
- (@minimum_value || store.min).to_f
472
+ min = [0.0, store.min.to_f].min
473
+ (@minimum_value || min).to_f
473
474
  end
474
475
  attr_writer :minimum_value
475
476
 
@@ -521,9 +522,8 @@ module Gruff
521
522
  # @deprecated Please use +to_image.to_blob+ instead.
522
523
  def to_blob(image_format = 'PNG')
523
524
  warn '#to_blob is deprecated. Please use `to_image.to_blob` instead'
524
- to_image.to_blob do
525
- self.format = image_format
526
- end
525
+ to_image.format = image_format
526
+ to_image.to_blob
527
527
  end
528
528
 
529
529
  # Draw a graph.
@@ -821,7 +821,7 @@ module Gruff
821
821
  end
822
822
 
823
823
  def clip_value_if_greater_than(value, max_value)
824
- value > max_value ? max_value : value
824
+ [value, max_value].min
825
825
  end
826
826
 
827
827
  def significant(i)
@@ -907,7 +907,7 @@ module Gruff
907
907
  bottom_label_width = extra_left_room_for_long_label
908
908
 
909
909
  margin = line_number_width + y_axis_label_width
910
- @left_margin + (margin > bottom_label_width ? margin : bottom_label_width)
910
+ @left_margin + [margin, bottom_label_width].max
911
911
  end
912
912
 
913
913
  def setup_right_margin
@@ -1035,7 +1035,7 @@ module Gruff
1035
1035
  def calculate_legend_label_widths_for_each_line(legend_labels, legend_square_width)
1036
1036
  label_widths = [[]]
1037
1037
  label_lines = [[]]
1038
- legend_labels.each do |label|
1038
+ legend_labels.reject(&:empty?).each do |label|
1039
1039
  width = calculate_width(@legend_font, label)
1040
1040
  label_width = width + (legend_square_width * 2.7)
1041
1041
  label_widths.last.push label_width
@@ -1129,7 +1129,7 @@ module Gruff
1129
1129
  -(width / 2.0)
1130
1130
  end
1131
1131
  end
1132
- y_offset = (height / 2.0) > margin ? (height / 2.0) : margin
1132
+ y_offset = [(height / 2.0), margin].max
1133
1133
 
1134
1134
  [x_offset, y_offset]
1135
1135
  end
data/lib/gruff/bezier.rb CHANGED
@@ -24,6 +24,9 @@ private
24
24
  def draw_graph
25
25
  x_increment = (@graph_width / (column_count - 1)).to_f
26
26
 
27
+ renderer_class = RUBY_PLATFORM == 'java' ? Gruff::Renderer::Polyline : Gruff::Renderer::Bezier
28
+ stroke_width = clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 4.0), 5.0)
29
+
27
30
  store.norm_data.each do |data_row|
28
31
  next if data_row[1].empty?
29
32
 
@@ -45,13 +48,7 @@ private
45
48
  draw_label(new_x, index)
46
49
  end
47
50
 
48
- stroke_width = clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 4), 5.0)
49
-
50
- if RUBY_PLATFORM == 'java'
51
- Gruff::Renderer::Polyline.new(renderer, color: data_row.color, width: stroke_width).render(poly_points)
52
- else
53
- Gruff::Renderer::Bezier.new(renderer, color: data_row.color, width: stroke_width).render(poly_points)
54
- end
51
+ renderer_class.new(renderer, color: data_row.color, width: stroke_width).render(poly_points)
55
52
  end
56
53
  end
57
54
  end
data/lib/gruff/box.rb CHANGED
@@ -23,7 +23,7 @@ class Gruff::Box < Gruff::Base
23
23
  #
24
24
  # Default value is +0.8+.
25
25
  def spacing_factor=(space_percent)
26
- raise ArgumentError, 'spacing_factor must be between 0.00 and 1.00' unless (space_percent >= 0) && (space_percent <= 1)
26
+ raise ArgumentError, 'spacing_factor must be between 0.00 and 1.00' if (space_percent < 0) || (space_percent > 1)
27
27
 
28
28
  @spacing_factor = (1 - space_percent)
29
29
  end
@@ -134,7 +134,7 @@ private
134
134
  end
135
135
 
136
136
  def median
137
- if points.size.zero?
137
+ if points.empty?
138
138
  0
139
139
  elsif points.size.odd?
140
140
  points[points.size / 2]
@@ -144,7 +144,7 @@ private
144
144
  end
145
145
 
146
146
  def first_quartile
147
- if points.size.zero?
147
+ if points.empty?
148
148
  0
149
149
  elsif points.size.odd?
150
150
  points[points.size / 4]
@@ -154,7 +154,7 @@ private
154
154
  end
155
155
 
156
156
  def third_quartile
157
- if points.size.zero?
157
+ if points.empty?
158
158
  0
159
159
  elsif points.size.odd?
160
160
  points[(points.size * 3) / 4]
@@ -33,7 +33,7 @@ class Gruff::Candlestick < Gruff::Base
33
33
  #
34
34
  # Default value is +0.9+.
35
35
  def spacing_factor=(space_percent)
36
- raise ArgumentError, 'spacing_factor must be between 0.00 and 1.00' unless (space_percent >= 0) && (space_percent <= 1)
36
+ raise ArgumentError, 'spacing_factor must be between 0.00 and 1.00' if (space_percent < 0) || (space_percent > 1)
37
37
 
38
38
  @spacing_factor = (1 - space_percent)
39
39
  end
@@ -90,10 +90,10 @@ private
90
90
  Gruff::Renderer::Rectangle.new(renderer, color: color, opacity: @fill_opacity, width: @stroke_width).render(left_x, open_y, right_x, close_y)
91
91
 
92
92
  low_y, = conversion.get_top_bottom_scaled(candlestick.low)
93
- y = open_y < close_y ? close_y : open_y
93
+ y = [open_y, close_y].max
94
94
  Gruff::Renderer::Line.new(renderer, color: color, width: @stroke_width).render(center_x, low_y, center_x, y)
95
95
  high_y, = conversion.get_top_bottom_scaled(candlestick.high)
96
- y = open_y > close_y ? close_y : open_y
96
+ y = [open_y, close_y].min
97
97
  Gruff::Renderer::Line.new(renderer, color: color, width: @stroke_width).render(center_x, y, center_x, high_y)
98
98
  end
99
99
  end
data/lib/gruff/dot.rb CHANGED
@@ -29,7 +29,7 @@ private
29
29
 
30
30
  items_width = @graph_height / column_count
31
31
  item_width = items_width * spacing_factor / store.length
32
- padding = (items_width * (1 - spacing_factor)) / 2
32
+ padding = (items_width * (1 - spacing_factor)) / 2.0
33
33
 
34
34
  store.norm_data.each_with_index do |data_row, row_index|
35
35
  data_row.points.each_with_index do |data_point, point_index|
data/lib/gruff/line.rb CHANGED
@@ -208,12 +208,15 @@ private
208
208
  draw_vertical_reference_line(curr_reference_line) if curr_reference_line.key?(:index)
209
209
  end
210
210
 
211
- store.norm_data.each do |data_row|
212
- prev_x = prev_y = nil
211
+ stroke_width = @line_width || clip_value_if_greater_than(@columns / (store.norm_data.first.y_points.size * 4.0), 5.0)
212
+ circle_radius = @dot_radius || clip_value_if_greater_than(@columns / (store.norm_data.first.y_points.size * 2.5), 5.0)
213
213
 
214
- one_point = contains_one_point_only?(data_row)
214
+ store.norm_data.each do |data_row|
215
+ poly_points_group = [[]]
215
216
 
216
217
  data_row.coordinates.each_with_index do |(x_data, y_data), index|
218
+ poly_points = poly_points_group.last
219
+
217
220
  new_x = begin
218
221
  if x_data.nil?
219
222
  # use the old method: equally spaced points along the x-axis
@@ -224,28 +227,27 @@ private
224
227
  end
225
228
  draw_label_for_x_data(x_data, new_x, index)
226
229
 
227
- unless y_data # we can't draw a line for a null data point, we can still label the axis though
228
- prev_x = prev_y = nil
230
+ unless y_data
231
+ # we can't draw a line for a null data point, we can still label the axis though.
232
+ # Split the polygonal line into separate groups of points for polyline.
233
+ poly_points_group << []
229
234
  next
230
235
  end
231
236
 
232
237
  new_y = @graph_top + (@graph_height - (y_data * @graph_height))
233
238
 
234
- # Reset each time to avoid thin-line errors
235
- stroke_width = @line_width || clip_value_if_greater_than(@columns / (store.norm_data.first.y_points.size * 4), 5.0)
236
- circle_radius = @dot_radius || clip_value_if_greater_than(@columns / (store.norm_data.first.y_points.size * 2.5), 5.0)
239
+ poly_points << new_x
240
+ poly_points << new_y
237
241
 
238
- if !@hide_lines && prev_x && prev_y
239
- Gruff::Renderer::Line.new(renderer, color: data_row.color, width: stroke_width)
240
- .render(prev_x, prev_y, new_x, new_y)
241
- end
242
-
243
- if one_point || !@hide_dots
242
+ if contains_one_point_only?(data_row) || !@hide_dots
244
243
  Gruff::Renderer::Dot.new(renderer, @dot_style, color: data_row.color, width: stroke_width).render(new_x, new_y, circle_radius)
245
244
  end
245
+ end
246
246
 
247
- prev_x = new_x
248
- prev_y = new_y
247
+ unless @hide_lines
248
+ poly_points_group.each do |poly_points|
249
+ Gruff::Renderer::Polyline.new(renderer, color: data_row.color, width: stroke_width).render(poly_points) unless poly_points.empty?
250
+ end
249
251
  end
250
252
  end
251
253
  end
@@ -12,36 +12,31 @@
12
12
  # g.data :Science, [2, 15, 8, 11]
13
13
  # g.write('mini_bar.png')
14
14
  #
15
- module Gruff
16
- module Mini
17
- # A class for drawing a small bar graph.
18
- class Bar < Gruff::Bar
19
- private
15
+ class Gruff::Mini::Bar < Gruff::Bar
16
+ private
20
17
 
21
- include Gruff::Mini::Legend
18
+ include Gruff::Mini::Legend
22
19
 
23
- def initialize_attributes
24
- super
20
+ def initialize_attributes
21
+ super
25
22
 
26
- @hide_legend = true
27
- @hide_title = true
28
- @hide_line_numbers = true
23
+ @hide_legend = true
24
+ @hide_title = true
25
+ @hide_line_numbers = true
29
26
 
30
- @marker_font.size = 50.0
31
- @legend_font.size = 60.0
27
+ @marker_font.size = 50.0
28
+ @legend_font.size = 50.0
32
29
 
33
- @minimum_value = 0.0
34
- end
30
+ @minimum_value = 0.0
31
+ end
35
32
 
36
- def setup_data
37
- expand_canvas_for_vertical_legend
38
- super
39
- end
33
+ def setup_data
34
+ expand_canvas_for_vertical_legend
35
+ super
36
+ end
40
37
 
41
- def draw_graph
42
- super
43
- draw_vertical_legend
44
- end
45
- end
38
+ def draw_graph
39
+ super
40
+ draw_vertical_legend
46
41
  end
47
42
  end
@@ -1,110 +1,98 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Gruff
4
- module Mini
5
- # A module to handle the small legend.
6
- # @private
7
- module Legend
8
- attr_accessor :hide_mini_legend, :legend_position
9
-
10
- def initialize(*)
11
- @hide_mini_legend = false
12
- @legend_position = nil
13
- super
14
- end
15
-
16
- ##
17
- # The canvas needs to be bigger so we can put the legend beneath it.
18
-
19
- def expand_canvas_for_vertical_legend
20
- return if @hide_mini_legend
21
-
22
- @legend_labels = store.data.map(&:label)
23
-
24
- legend_height = scale((store.length * calculate_line_height) + @top_margin + @bottom_margin)
25
-
26
- @original_rows = @raw_rows
27
- @original_columns = @raw_columns
28
-
29
- case @legend_position
30
- when :right
31
- @rows = [@rows, legend_height].max
32
- @columns += calculate_legend_width + @left_margin
33
- else
34
- font = @legend_font.dup
35
- font.size = scale(font.size)
36
- @rows += store.length * calculate_caps_height(font) * 1.7
37
- end
38
-
39
- @renderer = Gruff::Renderer.new(@columns, @rows, @scale, @theme_options)
40
- end
41
-
42
- def calculate_line_height
43
- calculate_caps_height(@legend_font) * 1.7
44
- end
45
-
46
- def calculate_legend_width
47
- width = @legend_labels.map { |label| calculate_width(@legend_font, label) }.max
48
- scale(width + (40 * 1.7))
49
- end
50
-
51
- ##
52
- # Draw the legend beneath the existing graph.
53
-
54
- def draw_vertical_legend
55
- return if @hide_mini_legend
56
-
57
- legend_square_width = 40.0 # small square with color of this item
58
- @legend_left_margin = 100.0
59
- legend_top_margin = 40.0
60
-
61
- case @legend_position
62
- when :right
63
- current_x_offset = @original_columns + @left_margin
64
- current_y_offset = @top_margin + legend_top_margin
65
- else
66
- current_x_offset = @legend_left_margin
67
- current_y_offset = @original_rows + legend_top_margin
68
- end
69
-
70
- @legend_labels.each_with_index do |legend_label, index|
71
- # Draw label
72
- x_offset = current_x_offset + (legend_square_width * 1.7)
73
- label = truncate_legend_label(legend_label, x_offset)
74
- text_renderer = Gruff::Renderer::Text.new(renderer, label, font: @legend_font)
75
- text_renderer.add_to_render_queue(@raw_columns, 1.0, x_offset, current_y_offset, Magick::WestGravity)
76
-
77
- # Now draw box with color of this dataset
78
- rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: store.data[index].color)
79
- rect_renderer.render(current_x_offset,
80
- current_y_offset - (legend_square_width / 2.0),
81
- current_x_offset + legend_square_width,
82
- current_y_offset + (legend_square_width / 2.0))
83
-
84
- current_y_offset += calculate_line_height
85
- end
86
- end
87
-
88
- ##
89
- # Shorten long labels so they will fit on the canvas.
90
- #
91
- # Department of Hu...
92
-
93
- def truncate_legend_label(label, x_offset)
94
- truncated_label = label.to_s
95
-
96
- font = @legend_font.dup
97
- font.size = scale(font.size)
98
- max_width = @columns - scale(x_offset) - @right_margin
99
- while calculate_width(font, "#{truncated_label}...") > max_width && truncated_label.length > 1
100
- truncated_label = truncated_label[0..truncated_label.length - 2]
101
- end
102
- truncated_label + (truncated_label.length < label.to_s.length ? '...' : '')
103
- end
104
-
105
- def scale(value)
106
- value * @scale
107
- end
3
+ # A module to handle the small legend.
4
+ # @private
5
+ module Gruff::Mini::Legend
6
+ attr_accessor :hide_mini_legend, :legend_position
7
+
8
+ def initialize(*)
9
+ @hide_mini_legend = false
10
+ @legend_position = nil
11
+ super
12
+ end
13
+
14
+ # The canvas needs to be bigger so we can put the legend beneath it.
15
+ def expand_canvas_for_vertical_legend
16
+ return if @hide_mini_legend
17
+
18
+ @legend_labels = store.data.map(&:label)
19
+
20
+ legend_height = scale((store.length * calculate_line_height) + @top_margin + @bottom_margin)
21
+
22
+ @original_rows = @raw_rows
23
+ @original_columns = @raw_columns
24
+
25
+ case @legend_position
26
+ when :right
27
+ @rows = [@rows, legend_height].max
28
+ @columns += calculate_legend_width + @left_margin
29
+ else
30
+ font = @legend_font.dup
31
+ font.size = scale(font.size)
32
+ @rows += store.length * calculate_caps_height(font) * 1.7
33
+ end
34
+
35
+ @renderer = Gruff::Renderer.new(@columns, @rows, @scale, @theme_options)
36
+ end
37
+
38
+ def calculate_line_height
39
+ calculate_caps_height(@legend_font) * 1.7
40
+ end
41
+
42
+ def calculate_legend_width
43
+ width = @legend_labels.map { |label| calculate_width(@legend_font, label) }.max
44
+ scale(width + (40 * 1.7))
45
+ end
46
+
47
+ # Draw the legend beneath the existing graph.
48
+ def draw_vertical_legend
49
+ return if @hide_mini_legend
50
+
51
+ legend_square_width = 40.0 # small square with color of this item
52
+ @legend_left_margin = 100.0
53
+ legend_top_margin = 40.0
54
+
55
+ case @legend_position
56
+ when :right
57
+ current_x_offset = @original_columns + @left_margin
58
+ current_y_offset = @top_margin + legend_top_margin
59
+ else
60
+ current_x_offset = @legend_left_margin
61
+ current_y_offset = @original_rows + legend_top_margin
108
62
  end
63
+
64
+ @legend_labels.each_with_index do |legend_label, index|
65
+ # Draw label
66
+ x_offset = current_x_offset + (legend_square_width * 1.7)
67
+ label = truncate_legend_label(legend_label, x_offset)
68
+ text_renderer = Gruff::Renderer::Text.new(renderer, label, font: @legend_font)
69
+ text_renderer.add_to_render_queue(@raw_columns, 1.0, x_offset, current_y_offset, Magick::WestGravity)
70
+
71
+ # Now draw box with color of this dataset
72
+ rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: store.data[index].color)
73
+ rect_renderer.render(current_x_offset,
74
+ current_y_offset - (legend_square_width / 2.0),
75
+ current_x_offset + legend_square_width,
76
+ current_y_offset + (legend_square_width / 2.0))
77
+
78
+ current_y_offset += calculate_line_height
79
+ end
80
+ end
81
+
82
+ # Shorten long labels so they will fit on the canvas.
83
+ def truncate_legend_label(label, x_offset)
84
+ truncated_label = label.to_s
85
+
86
+ font = @legend_font.dup
87
+ font.size = scale(font.size)
88
+ max_width = @columns - scale(x_offset) - @right_margin
89
+ while calculate_width(font, "#{truncated_label}...") > max_width && truncated_label.length > 1
90
+ truncated_label = truncated_label[0..truncated_label.length - 2]
91
+ end
92
+ truncated_label + (truncated_label.length < label.to_s.length ? '...' : '')
93
+ end
94
+
95
+ def scale(value)
96
+ value * @scale
109
97
  end
110
98
  end
@@ -11,34 +11,29 @@
11
11
  # g.data 'Hamburgers', 50
12
12
  # g.write("mini_pie_keynote.png")
13
13
  #
14
- module Gruff
15
- module Mini
16
- # A class for drawing a small pie graph.
17
- class Pie < Gruff::Pie
18
- private
14
+ class Gruff::Mini::Pie < Gruff::Pie
15
+ private
19
16
 
20
- include Gruff::Mini::Legend
17
+ include Gruff::Mini::Legend
21
18
 
22
- def initialize_attributes
23
- super
19
+ def initialize_attributes
20
+ super
24
21
 
25
- @hide_legend = true
26
- @hide_title = true
27
- @hide_line_numbers = true
22
+ @hide_legend = true
23
+ @hide_title = true
24
+ @hide_line_numbers = true
28
25
 
29
- @marker_font.size = 60.0
30
- @legend_font.size = 60.0
31
- end
26
+ @marker_font.size = 50.0
27
+ @legend_font.size = 50.0
28
+ end
32
29
 
33
- def setup_data
34
- expand_canvas_for_vertical_legend
35
- super
36
- end
30
+ def setup_data
31
+ expand_canvas_for_vertical_legend
32
+ super
33
+ end
37
34
 
38
- def draw_graph
39
- super
40
- draw_vertical_legend
41
- end
42
- end
35
+ def draw_graph
36
+ super
37
+ draw_vertical_legend
43
38
  end
44
39
  end
@@ -19,33 +19,28 @@
19
19
  # g.data :Science, [2, 15, 8, 11]
20
20
  # g.write('mini_sidebar.png')
21
21
  #
22
- module Gruff
23
- module Mini
24
- # A class for drawing a small side bar graph.
25
- class SideBar < Gruff::SideBar
26
- private
22
+ class Gruff::Mini::SideBar < Gruff::SideBar
23
+ private
27
24
 
28
- include Gruff::Mini::Legend
25
+ include Gruff::Mini::Legend
29
26
 
30
- def initialize_attributes
31
- super
32
- @hide_legend = true
33
- @hide_title = true
34
- @hide_line_numbers = true
27
+ def initialize_attributes
28
+ super
29
+ @hide_legend = true
30
+ @hide_title = true
31
+ @hide_line_numbers = true
35
32
 
36
- @marker_font.size = 50.0
37
- @legend_font.size = 50.0
38
- end
33
+ @marker_font.size = 50.0
34
+ @legend_font.size = 50.0
35
+ end
39
36
 
40
- def setup_data
41
- expand_canvas_for_vertical_legend
42
- super
43
- end
37
+ def setup_data
38
+ expand_canvas_for_vertical_legend
39
+ super
40
+ end
44
41
 
45
- def draw_graph
46
- super
47
- draw_vertical_legend
48
- end
49
- end
42
+ def draw_graph
43
+ super
44
+ draw_vertical_legend
50
45
  end
51
46
  end
data/lib/gruff/net.rb CHANGED
@@ -60,6 +60,8 @@ private
60
60
 
61
61
  def draw_graph
62
62
  store.norm_data.each do |data_row|
63
+ poly_points = []
64
+
63
65
  data_row.points.each_with_index do |data_point, index|
64
66
  next if data_point.nil?
65
67
 
@@ -67,6 +69,10 @@ private
67
69
  point_distance = data_point * @radius
68
70
  start_x = @center_x + (Math.sin(rad_pos) * point_distance)
69
71
  start_y = @center_y - (Math.cos(rad_pos) * point_distance)
72
+ if poly_points.empty?
73
+ poly_points << start_x
74
+ poly_points << start_y
75
+ end
70
76
 
71
77
  next_index = index + 1 < data_row.points.length ? index + 1 : 0
72
78
 
@@ -74,14 +80,16 @@ private
74
80
  next_point_distance = data_row.points[next_index] * @radius
75
81
  end_x = @center_x + (Math.sin(next_rad_pos) * next_point_distance)
76
82
  end_y = @center_y - (Math.cos(next_rad_pos) * next_point_distance)
77
-
78
- Gruff::Renderer::Line.new(renderer, color: data_row.color, width: @stroke_width).render(start_x, start_y, end_x, end_y)
83
+ poly_points << end_x
84
+ poly_points << end_y
79
85
 
80
86
  unless @hide_dots
81
87
  circle_renderer = Gruff::Renderer::Circle.new(renderer, color: data_row.color, width: @stroke_width)
82
88
  circle_renderer.render(start_x, start_y, start_x - @circle_radius, start_y)
83
89
  end
84
90
  end
91
+
92
+ Gruff::Renderer::Polyline.new(renderer, color: data_row.color, width: @stroke_width).render(poly_points) unless poly_points.empty?
85
93
  end
86
94
  end
87
95
 
@@ -7,8 +7,8 @@ module Magick
7
7
  refine Draw do
8
8
  # Additional method to scale annotation text since Draw.scale doesn't.
9
9
  def annotate_scaled(img, width, height, x, y, text, scale)
10
- scaled_width = (width * scale) >= 1 ? (width * scale) : 1
11
- scaled_height = (height * scale) >= 1 ? (height * scale) : 1
10
+ scaled_width = [(width * scale), 1].max
11
+ scaled_height = [(height * scale), 1].max
12
12
 
13
13
  annotate(img,
14
14
  scaled_width, scaled_height,
@@ -11,8 +11,8 @@ module Gruff
11
11
 
12
12
  def render(points)
13
13
  @renderer.draw.push
14
- @renderer.draw.stroke(@color)
15
14
  @renderer.draw.stroke_width(@width)
15
+ @renderer.draw.stroke(@color)
16
16
  @renderer.draw.fill_opacity(0.0)
17
17
  @renderer.draw.bezier(*points)
18
18
  @renderer.draw.pop
@@ -12,10 +12,10 @@ module Gruff
12
12
 
13
13
  def render(origin_x, origin_y, perim_x, perim_y)
14
14
  @renderer.draw.push
15
- @renderer.draw.fill(@color)
16
- @renderer.draw.fill_opacity(@opacity)
17
- @renderer.draw.stroke(@color)
18
15
  @renderer.draw.stroke_width(@width)
16
+ @renderer.draw.stroke(@color)
17
+ @renderer.draw.fill_opacity(@opacity)
18
+ @renderer.draw.fill(@color)
19
19
  @renderer.draw.circle(origin_x, origin_y, perim_x, perim_y)
20
20
  @renderer.draw.pop
21
21
  end
@@ -13,9 +13,9 @@ module Gruff
13
13
  def render(start_x, start_y, end_x, end_y)
14
14
  @renderer.draw.push
15
15
  @renderer.draw.stroke_color(@color)
16
- @renderer.draw.fill_opacity(0.0)
17
16
  @renderer.draw.stroke_dasharray(*@dasharray)
18
17
  @renderer.draw.stroke_width(@width)
18
+ @renderer.draw.fill_opacity(0.0)
19
19
  @renderer.draw.line(start_x, start_y, end_x, end_y)
20
20
  @renderer.draw.pop
21
21
  end
@@ -15,8 +15,8 @@ module Gruff
15
15
  @renderer.draw.push
16
16
  @renderer.draw.stroke_width(@width)
17
17
  @renderer.draw.stroke(@color)
18
- @renderer.draw.fill(@color)
19
18
  @renderer.draw.fill_opacity(@opacity)
19
+ @renderer.draw.fill(@color)
20
20
  case @style.to_sym
21
21
  when :square
22
22
  square(new_x, new_y, radius)
@@ -30,9 +30,9 @@ module Gruff
30
30
  end
31
31
 
32
32
  @renderer.draw.push
33
+ @renderer.draw.stroke_width(@width) if @width
33
34
  @renderer.draw.stroke(color)
34
35
  @renderer.draw.fill(color)
35
- @renderer.draw.stroke_width(@width) if @width
36
36
  @renderer.draw.line(start_x, start_y, end_x, end_y)
37
37
  @renderer.draw.pop
38
38
  end
@@ -14,8 +14,8 @@ module Gruff
14
14
  @renderer.draw.push
15
15
  @renderer.draw.stroke_width(@width)
16
16
  @renderer.draw.stroke(@color)
17
- @renderer.draw.fill(@color)
18
17
  @renderer.draw.fill_opacity(@opacity)
18
+ @renderer.draw.fill(@color)
19
19
  @renderer.draw.polygon(*points)
20
20
  @renderer.draw.pop
21
21
  end
@@ -3,17 +3,19 @@
3
3
  module Gruff
4
4
  # @private
5
5
  class Renderer::Polyline
6
- def initialize(renderer, color:, width:)
6
+ def initialize(renderer, color:, width: 1.0, linejoin: 'bevel')
7
7
  @renderer = renderer
8
8
  @color = color
9
9
  @width = width
10
+ @linejoin = linejoin
10
11
  end
11
12
 
12
13
  def render(points)
13
14
  @renderer.draw.push
15
+ @renderer.draw.stroke_linejoin(@linejoin)
16
+ @renderer.draw.stroke_width(@width)
14
17
  @renderer.draw.stroke(@color)
15
18
  @renderer.draw.fill('transparent')
16
- @renderer.draw.stroke_width(@width)
17
19
  @renderer.draw.polyline(*points)
18
20
  @renderer.draw.pop
19
21
  end
data/lib/gruff/scatter.rb CHANGED
@@ -142,6 +142,9 @@ private
142
142
  end
143
143
 
144
144
  def draw_graph
145
+ stroke_width = @stroke_width || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 4.0), 5.0)
146
+ circle_radius = @circle_radius || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 2.5), 5.0)
147
+
145
148
  store.norm_data.each do |data_row|
146
149
  data_row.coordinates.each do |x_value, y_value|
147
150
  next if y_value.nil? || x_value.nil?
@@ -149,9 +152,6 @@ private
149
152
  new_x = @graph_left + (x_value * @graph_width)
150
153
  new_y = @graph_bottom - (y_value * @graph_height)
151
154
 
152
- # Reset each time to avoid thin-line errors
153
- stroke_width = @stroke_width || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 4.0), 5.0)
154
- circle_radius = @circle_radius || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 2.5), 5.0)
155
155
  Gruff::Renderer::Circle.new(renderer, color: data_row.color, width: stroke_width).render(new_x, new_y, new_x - circle_radius, new_y)
156
156
  end
157
157
  end
@@ -78,7 +78,7 @@ private
78
78
  #
79
79
  # Columns sit stacked.
80
80
  bar_width = @graph_width / column_count
81
- padding = (bar_width * (1 - @bar_spacing)) / 2
81
+ padding = (bar_width * (1 - @bar_spacing)) / 2.0
82
82
 
83
83
  # Setup the BarConversion Object
84
84
  conversion = Gruff::BarConversion.new(
data/lib/gruff/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Gruff
4
- VERSION = '0.18.0'
4
+ VERSION = '0.20.0'
5
5
  end
data/lib/gruff.rb CHANGED
@@ -45,6 +45,7 @@ module Gruff
45
45
  autoload :Layer, Gruff.libpath('scene')
46
46
  autoload :Themes, Gruff.libpath('themes')
47
47
 
48
+ # @private
48
49
  class Renderer
49
50
  autoload :Bezier, Gruff.libpath('renderer/bezier')
50
51
  autoload :Circle, Gruff.libpath('renderer/circle')
@@ -58,12 +59,14 @@ module Gruff
58
59
  autoload :Text, Gruff.libpath('renderer/text')
59
60
  end
60
61
 
62
+ # @private
61
63
  class Store
62
64
  autoload :BasicData, Gruff.libpath('store/basic_data')
63
65
  autoload :XYData, Gruff.libpath('store/xy_data')
64
66
  autoload :XYPointsizeData, Gruff.libpath('store/xy_pointsizes_data')
65
67
  end
66
68
 
69
+ # A module for small graphs
67
70
  module Mini
68
71
  autoload :Bar, Gruff.libpath('mini/bar')
69
72
  autoload :Legend, Gruff.libpath('mini/legend')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gruff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.18.0
4
+ version: 0.20.0
5
5
  platform: java
6
6
  authors:
7
7
  - Geoffrey Grosenbach
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-06-26 00:00:00.000000000 Z
12
+ date: 2023-06-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  requirement: !ruby/object:Gem::Requirement
@@ -102,6 +102,7 @@ executables: []
102
102
  extensions: []
103
103
  extra_rdoc_files: []
104
104
  files:
105
+ - ".devcontainer/devcontainer.json"
105
106
  - ".editorconfig"
106
107
  - ".github/ISSUE_TEMPLATE.md"
107
108
  - ".github/workflows/ci.yml"
@@ -182,14 +183,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
182
183
  requirements:
183
184
  - - ">="
184
185
  - !ruby/object:Gem::Version
185
- version: 2.5.0
186
+ version: 2.6.0
186
187
  required_rubygems_version: !ruby/object:Gem::Requirement
187
188
  requirements:
188
189
  - - ">="
189
190
  - !ruby/object:Gem::Version
190
191
  version: '0'
191
192
  requirements: []
192
- rubygems_version: 3.2.29
193
+ rubygems_version: 3.3.25
193
194
  signing_key:
194
195
  specification_version: 4
195
196
  summary: Beautiful graphs for one or multiple datasets.