gruff 0.18.0-java → 0.20.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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.