glimmer-libui-cc-graphs_and_charts 0.1.4 → 0.1.6

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: fa1f107626b30af5f1158617ad578b5fcd82663700f60f36d581489026c7d5c8
4
- data.tar.gz: 3c38aab6b233810235a2ad87e2ce78a0bc58def745d9a72c1c9a27243b9be140
3
+ metadata.gz: bad5c6db427c320e3b452ee60e2b3af416604525c96e74c915b59c905d746b07
4
+ data.tar.gz: 3659c73cd8a91a9da31c5cf2cb896b04130a7e1a4c58d2f2e92f7b841726de58
5
5
  SHA512:
6
- metadata.gz: 131eddeb423e5b7c2194cddd21c7ce828b63dd6554f05c6377cf4960057bd30a5535ae705477e95d9b72782d7d355090e75ad08acad08f84bfa48ac5eeeafe17
7
- data.tar.gz: bbe9afaafbc760c80f73c59979f9354e9826129310b7122331e566dc24039ce5525b3968239c085ffc369b06a233a63d33ca0aa7f91a8c9f9560fa7f7783d248
6
+ metadata.gz: 9ff88818e482120a5492d7bb2a789afc89d1a40efed3411d355afcc5db7737ef5f5a5e206a3a2737ccdcaf11a8ba01592a398878b1cd005153d1d3ead08d2728
7
+ data.tar.gz: b487f6b49b979d6b3a72a2c174f8cd55c558037e2baf2997b6ddaf0a2b2e9ffa243d62ce48558966115a07bfaccf69802682a7d94b0af4043dad29da5e33e909
data/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.1.6
4
+
5
+ - Support passing line `values` as a `Hash` map of x-axis values to y-axis values instead of using the combination of `y_values`, `x_value_start`, and `x_interval_in_seconds`
6
+ - Rename `examples/graphs_and_charts/basic_line_graph.rb` to `examples/graphs_and_charts/basic_line_graph_relative.rb`
7
+ - New `examples/graphs_and_charts/basic_line_graph.rb` (replacing older example that got renamed to `basic_line_graph_relative.rb`)
8
+ - Add graph auto-scaling logic to both `examples/graphs_and_charts/basic_line_graph.rb` & `examples/graphs_and_charts/basic_line_graph_relative.rb`
9
+
10
+ ## 0.1.5
11
+
12
+ - Render circles for every point in addition to the lines connecting all the points
13
+ - Render a single point if there is only 1 value in `lines` `y_values` instead of rendering nothing until 2 values exist at least
14
+ - Support `graph_point_radius`, `graph_selected_point_radius`, and `graph_fill_selected_point` options for customizing the circle of every rendered point and selected point.
15
+ - Avoid rendering on top of the grid markers on the left side
16
+ - Optimize performance of rendering grid markers and showing mouse hover selection stats of a point
17
+
3
18
  ## 0.1.4
4
19
 
5
20
  - Fix issue with crashing at `lib/glimmer/view/line_graph.rb:243:in y_value_max_for_all_lines': undefined method max for nil:NilClass`
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Graphs and Charts 0.1.4 (Alpha)
1
+ # Graphs and Charts 0.1.6 (Alpha)
2
2
  ## [Glimmer DSL for LibUI](https://github.com/AndyObtiva/glimmer-dsl-libui) Custom Controls
3
3
  [![Gem Version](https://badge.fury.io/rb/glimmer-libui-cc-graphs_and_charts.svg)](http://badge.fury.io/rb/glimmer-libui-cc-graphs_and_charts)
4
4
  [![Join the chat at https://gitter.im/AndyObtiva/glimmer](https://badges.gitter.im/AndyObtiva/glimmer.svg)](https://gitter.im/AndyObtiva/glimmer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
@@ -12,7 +12,7 @@ Graphs and Charts (Custom Controls) for [Glimmer DSL for LibUI](https://github.c
12
12
  Add this line to Bundler `Gemfile`:
13
13
 
14
14
  ```ruby
15
- gem 'glimmer-libui-cc-graphs_and_charts', '~> 0.1.4'
15
+ gem 'glimmer-libui-cc-graphs_and_charts', '~> 0.1.6'
16
16
  ```
17
17
 
18
18
  Run:
@@ -47,7 +47,7 @@ line_graph(
47
47
  width: 900,
48
48
  height: 300,
49
49
  graph_point_distance: :width_divided_by_point_count,
50
- lines: [
50
+ series: [
51
51
  {
52
52
  name: 'Feature A',
53
53
  stroke: [163, 40, 39, thickness: 2],
@@ -71,6 +71,8 @@ line_graph(
71
71
 
72
72
  ![basic line graph](/screenshots/glimmer-libui-cc-graphs_and_charts-mac-basic-line-graph.png)
73
73
 
74
+ Look into [lib/glimmer/view/line_graph.rb](/lib/glimmer/view/line_graph.rb) to learn about all supported options.
75
+
74
76
  Basic Line Graph Example:
75
77
 
76
78
  [examples/graphs_and_charts/basic_line_graph.rb](/examples/graphs_and_charts/basic_line_graph.rb)
@@ -92,7 +94,7 @@ class BasicLineGraph
92
94
  width: 900,
93
95
  height: 300,
94
96
  graph_point_distance: :width_divided_by_point_count,
95
- lines: [
97
+ series: [
96
98
  {
97
99
  name: 'Feature A',
98
100
  stroke: [163, 40, 39, thickness: 2],
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.4
1
+ 0.1.6
@@ -7,36 +7,43 @@ require 'glimmer/view/line_graph'
7
7
  class BasicLineGraph
8
8
  include Glimmer::LibUI::Application
9
9
 
10
- before_body do
11
- @start_time = Time.now
12
- end
13
-
14
10
  body {
15
- window('Basic Line Graph', 900, 330) {
16
- line_graph(
11
+ window('Basic Line Graph', 900, 300) { |main_window|
12
+ @line_graph = line_graph(
17
13
  width: 900,
18
14
  height: 300,
19
- graph_point_distance: :width_divided_by_point_count,
20
15
  lines: [
21
16
  {
22
- name: 'Feature A',
17
+ name: 'Stock 1',
23
18
  stroke: [163, 40, 39, thickness: 2],
24
- x_value_start: @start_time,
25
- x_interval_in_seconds: 8,
19
+ values: {
20
+ Time.new(2030, 12, 1) => 80,
21
+ Time.new(2030, 12, 2) => 36,
22
+ Time.new(2030, 12, 4) => 10,
23
+ Time.new(2030, 12, 5) => 60,
24
+ Time.new(2030, 12, 6) => 20,
25
+ },
26
26
  x_value_format: -> (time) {time.strftime("%a %d %b %Y %T GMT")},
27
- y_values: [80, 36, 10, 60, 20, 110, 16, 5, 36, 1, 77, 15, 3, 34, 8, 63, 12, 17, 90, 28, 70]
28
27
  },
29
28
  {
30
- name: 'Feature B',
29
+ name: 'Stock 2',
31
30
  stroke: [47, 109, 104, thickness: 2],
32
- x_value_start: @start_time,
33
- x_interval_in_seconds: 8,
31
+ values: {
32
+ Time.new(2030, 12, 1) => 62,
33
+ Time.new(2030, 12, 2) => 0,
34
+ Time.new(2030, 12, 3) => 90,
35
+ Time.new(2030, 12, 5) => 0,
36
+ Time.new(2030, 12, 7) => 17,
37
+ },
34
38
  x_value_format: -> (time) {time.strftime("%a %d %b %Y %T GMT")},
35
- y_values: [62, 0, 90, 0, 0, 27, 0, 56, 0, 0, 24, 0, 60, 0, 30, 0, 47, 0, 38, 90, 0]
36
39
  },
37
40
  ],
38
- display_attributes_on_hover: true,
39
41
  )
42
+
43
+ on_content_size_changed do
44
+ @line_graph.width = main_window.content_size[0]
45
+ @line_graph.height = main_window.content_size[1]
46
+ end
40
47
  }
41
48
  }
42
49
  end
@@ -0,0 +1,49 @@
1
+ # This line is only needed when running the example from inside the project directory
2
+ $LOAD_PATH.prepend(File.expand_path(File.join(__dir__, '..', '..', 'lib'))) if File.exist?(File.join(__dir__, '..', '..', 'lib'))
3
+
4
+ require 'glimmer-dsl-libui'
5
+ require 'glimmer/view/line_graph'
6
+
7
+ class BasicLineGraph
8
+ include Glimmer::LibUI::Application
9
+
10
+ before_body do
11
+ @start_time = Time.now
12
+ end
13
+
14
+ body {
15
+ window('Basic Line Graph', 900, 330) { |main_window|
16
+ @line_graph = line_graph(
17
+ width: 900,
18
+ height: 300,
19
+ graph_point_distance: :width_divided_by_point_count,
20
+ lines: [
21
+ {
22
+ name: 'Feature A',
23
+ stroke: [163, 40, 39, thickness: 2],
24
+ x_value_start: @start_time,
25
+ x_interval_in_seconds: 8,
26
+ x_value_format: -> (time) {time.strftime("%a %d %b %Y %T GMT")},
27
+ y_values: [80, 36, 10, 60, 20, 110, 16, 5, 36, 1, 77, 15, 3, 34, 8, 63, 12, 17, 90, 28, 70]
28
+ },
29
+ {
30
+ name: 'Feature B',
31
+ stroke: [47, 109, 104, thickness: 2],
32
+ x_value_start: @start_time,
33
+ x_interval_in_seconds: 8,
34
+ x_value_format: -> (time) {time.strftime("%a %d %b %Y %T GMT")},
35
+ y_values: [62, 0, 90, 0, 0, 27, 0, 56, 0, 0, 24, 0, 60, 0, 30, 0, 47, 0, 38, 90, 0]
36
+ },
37
+ ],
38
+ display_attributes_on_hover: true,
39
+ )
40
+
41
+ on_content_size_changed do
42
+ @line_graph.width = main_window.content_size[0]
43
+ @line_graph.height = main_window.content_size[1] - 30
44
+ end
45
+ }
46
+ }
47
+ end
48
+
49
+ BasicLineGraph.launch
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: glimmer-libui-cc-graphs_and_charts 0.1.4 ruby lib
5
+ # stub: glimmer-libui-cc-graphs_and_charts 0.1.6 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "glimmer-libui-cc-graphs_and_charts".freeze
9
- s.version = "0.1.4".freeze
9
+ s.version = "0.1.6".freeze
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib".freeze]
13
13
  s.authors = ["Andy Maleh".freeze]
14
- s.date = "2023-12-19"
14
+ s.date = "2023-12-22"
15
15
  s.description = "Graphs and Charts (Custom Controls) for Glimmer DSL for LibUI, like Line Graph.".freeze
16
16
  s.email = "andy.am@gmail.com".freeze
17
17
  s.extra_rdoc_files = [
@@ -25,6 +25,7 @@ Gem::Specification.new do |s|
25
25
  "README.md",
26
26
  "VERSION",
27
27
  "examples/graphs_and_charts/basic_line_graph.rb",
28
+ "examples/graphs_and_charts/basic_line_graph_relative.rb",
28
29
  "glimmer-libui-cc-graphs_and_charts.gemspec",
29
30
  "lib/glimmer-libui-cc-graphs_and_charts.rb",
30
31
  "lib/glimmer/view/line_graph.rb"
@@ -4,12 +4,21 @@ module Glimmer
4
4
  module View
5
5
  # General-Purpose Line Graph Custom Control
6
6
  class LineGraph
7
+ class << self
8
+ def interpret_color(color_object)
9
+ @color_cache ||= {}
10
+ @color_cache[color_object] ||= Glimmer::LibUI.interpret_color(color_object)
11
+ end
12
+ end
13
+
7
14
  include Glimmer::LibUI::CustomControl
8
15
 
9
16
  DEFAULT_GRAPH_PADDING_WIDTH = 5.0
10
17
  DEFAULT_GRAPH_PADDING_HEIGHT = 5.0
11
- DEFAULT_GRAPH_GRID_MARKER_PADDING_WIDTH = 30.0
18
+ DEFAULT_GRAPH_GRID_MARKER_PADDING_WIDTH = 37.0
12
19
  DEFAULT_GRAPH_POINT_DISTANCE = 15.0
20
+ DEFAULT_GRAPH_POINT_RADIUS = 1.0
21
+ DEFAULT_GRAPH_SELECTED_POINT_RADIUS = 3.0
13
22
 
14
23
  DEFAULT_GRAPH_STROKE_GRID = [185, 184, 185]
15
24
  DEFAULT_GRAPH_STROKE_MARKER = [185, 184, 185]
@@ -17,6 +26,8 @@ module Glimmer
17
26
  DEFAULT_GRAPH_STROKE_PERIODIC_LINE = [121, 121, 121, thickness: 1, dashes: [1, 1]]
18
27
  DEFAULT_GRAPH_STROKE_HOVER_LINE = [133, 133, 133]
19
28
 
29
+ DEFAULT_GRAPH_FILL_SELECTED_POINT = :white
30
+
20
31
  DEFAULT_GRAPH_COLOR_MARKER_TEXT = [96, 96, 96]
21
32
  DEFAULT_GRAPH_COLOR_PERIOD_TEXT = [163, 40, 39]
22
33
 
@@ -44,6 +55,8 @@ module Glimmer
44
55
  option :graph_padding_height, default: DEFAULT_GRAPH_PADDING_HEIGHT
45
56
  option :graph_grid_marker_padding_width, default: DEFAULT_GRAPH_GRID_MARKER_PADDING_WIDTH
46
57
  option :graph_point_distance, default: DEFAULT_GRAPH_POINT_DISTANCE
58
+ option :graph_point_radius, default: DEFAULT_GRAPH_POINT_RADIUS
59
+ option :graph_selected_point_radius, default: DEFAULT_GRAPH_SELECTED_POINT_RADIUS
47
60
 
48
61
  option :graph_stroke_grid, default: DEFAULT_GRAPH_STROKE_GRID
49
62
  option :graph_stroke_marker, default: DEFAULT_GRAPH_STROKE_MARKER
@@ -51,6 +64,8 @@ module Glimmer
51
64
  option :graph_stroke_periodic_line, default: DEFAULT_GRAPH_STROKE_PERIODIC_LINE
52
65
  option :graph_stroke_hover_line, default: DEFAULT_GRAPH_STROKE_HOVER_LINE
53
66
 
67
+ option :graph_fill_selected_point, default: DEFAULT_GRAPH_FILL_SELECTED_POINT
68
+
54
69
  option :graph_color_marker_text, default: DEFAULT_GRAPH_COLOR_MARKER_TEXT
55
70
  option :graph_color_period_text, default: DEFAULT_GRAPH_COLOR_PERIOD_TEXT
56
71
 
@@ -93,7 +108,7 @@ module Glimmer
93
108
 
94
109
  if @hover_point && lines && lines[0] && @points && @points[lines[0]] && !@points[lines[0]].empty?
95
110
  x = @hover_point[:x]
96
- closest_point_index = @points[lines[0]].each_with_index.min_by { |point, index| (point[:x] - x).abs }[1]
111
+ closest_point_index = ((width - graph_padding_width - x) / graph_point_distance_for_line(lines[0])).round
97
112
  if closest_point_index != @closest_point_index
98
113
  @closest_point_index = closest_point_index
99
114
  graph_area.queue_redraw_all
@@ -116,8 +131,17 @@ module Glimmer
116
131
  def clear_drawing_cache
117
132
  @graph_point_distance_per_line = nil
118
133
  @y_value_max_for_all_lines = nil
134
+ @x_resolution = nil
135
+ @x_value_range_for_all_lines = nil
136
+ @x_value_min_for_all_lines = nil
137
+ @x_value_max_for_all_lines = nil
119
138
  @grid_marker_points = nil
120
139
  @points = nil
140
+ @grid_marker_number_values = nil
141
+ @grid_marker_numbers = nil
142
+ @graph_stroke_marker_values = nil
143
+ @mod_values = nil
144
+ @estimated_widths_of_text = nil
121
145
  end
122
146
 
123
147
  def calculate_dynamic_options
@@ -125,13 +149,19 @@ module Glimmer
125
149
  end
126
150
 
127
151
  def calculate_graph_point_distance_per_line
128
- return unless graph_point_distance == :width_divided_by_point_count
152
+ return unless lines[0]&.[](:y_values) && graph_point_distance == :width_divided_by_point_count
129
153
 
130
- @graph_point_distance_per_line = lines.inject({}) do |hash, line|
131
- hash.merge(line => (width - 2.0*graph_padding_width - graph_grid_marker_padding_width) / (line[:y_values].size - 1).to_f)
154
+ @graph_point_distance_per_line ||= lines.inject({}) do |hash, line|
155
+ value = (width - 2.0*graph_padding_width - graph_grid_marker_padding_width) / (line[:y_values].size - 1).to_f
156
+ value = [value, drawable_width].min
157
+ hash.merge(line => value)
132
158
  end
133
159
  end
134
160
 
161
+ def drawable_width
162
+ width - 2.0*graph_padding_width - graph_grid_marker_padding_width
163
+ end
164
+
135
165
  def graph_point_distance_for_line(line)
136
166
  @graph_point_distance_per_line&.[](line) || graph_point_distance
137
167
  end
@@ -149,12 +179,25 @@ module Glimmer
149
179
  line(graph_padding_width, height - graph_padding_height, width - graph_padding_width, height - graph_padding_height) {
150
180
  stroke graph_stroke_grid
151
181
  }
182
+ grid_marker_number_font = graph_font_marker_text.merge(size: 11)
183
+ @grid_marker_number_values ||= []
184
+ @grid_marker_numbers ||= []
185
+ @graph_stroke_marker_values ||= []
186
+ @mod_values ||= []
152
187
  grid_marker_points.each_with_index do |marker_point, index|
153
- grid_marker_number_value = (grid_marker_points.size - index).to_i
154
- grid_marker_number = (grid_marker_number_value >= 1000) ? "#{grid_marker_number_value / 1000}K" : grid_marker_number_value.to_s
155
- graph_stroke_marker_value = Glimmer::LibUI.interpret_color(graph_stroke_marker)
156
- graph_stroke_marker_value[:thickness] = (index != grid_marker_points.size - 1 ? 2 : 1) if graph_stroke_marker_value[:thickness].nil?
157
- mod_value = (2 * ((grid_marker_points.size / max_marker_count) + 1))
188
+ @grid_marker_number_values[index] ||= (grid_marker_points.size - index).to_i
189
+ grid_marker_number_value = @grid_marker_number_values[index]
190
+ @grid_marker_numbers[index] ||= (grid_marker_number_value >= 1000) ? "#{grid_marker_number_value / 1000}K" : grid_marker_number_value.to_s
191
+ grid_marker_number = @grid_marker_numbers[index]
192
+ @graph_stroke_marker_values[index] ||= LineGraph.interpret_color(graph_stroke_marker).tap do |color_hash|
193
+ color_hash[:thickness] = (index != grid_marker_points.size - 1 ? 2 : 1) if color_hash[:thickness].nil?
194
+ end
195
+ graph_stroke_marker_value = @graph_stroke_marker_values[index]
196
+ @mod_values[index] ||= begin
197
+ mod_value_multiplier = ((grid_marker_points.size / max_marker_count) + 1)
198
+ [((mod_value_multiplier <= 2 ? 2 : 5) * mod_value_multiplier), 1].max
199
+ end
200
+ mod_value = @mod_values[index]
158
201
  comparison_value = (mod_value > 2) ? 0 : 1
159
202
  if mod_value > 2
160
203
  if grid_marker_number_value % mod_value == comparison_value
@@ -173,7 +216,6 @@ module Glimmer
173
216
  }
174
217
  end
175
218
  if grid_marker_number_value % mod_value == comparison_value
176
- grid_marker_number_font = graph_font_marker_text.merge(size: 11)
177
219
  grid_marker_number_width = estimate_width_of_text(grid_marker_number, grid_marker_number_font)
178
220
  text(marker_point[:x] + 4 + 3, marker_point[:y] - 6, grid_marker_number_width) {
179
221
  string(grid_marker_number) {
@@ -210,17 +252,30 @@ module Glimmer
210
252
  def single_line_graph(graph_line)
211
253
  last_point = nil
212
254
  points = calculate_points(graph_line)
213
- points.each do |point|
255
+ points.to_a.each do |point|
214
256
  if last_point
215
257
  line(last_point[:x], last_point[:y], point[:x], point[:y]) {
216
258
  stroke graph_line[:stroke]
217
259
  }
218
260
  end
261
+ if last_point.nil? || graph_point_radius > 1
262
+ circle(point[:x], point[:y], graph_point_radius) {
263
+ fill graph_line[:stroke]
264
+ }
265
+ end
219
266
  last_point = point
220
267
  end
221
268
  end
222
269
 
223
270
  def calculate_points(graph_line)
271
+ if lines[0]&.[](:y_values)
272
+ calculate_points_relative(graph_line)
273
+ else
274
+ calculate_points_absolute(graph_line)
275
+ end
276
+ end
277
+
278
+ def calculate_points_relative(graph_line)
224
279
  @points ||= {}
225
280
  if @points[graph_line].nil?
226
281
  y_values = graph_line[:y_values] || []
@@ -236,9 +291,67 @@ module Glimmer
236
291
  @points[graph_line]
237
292
  end
238
293
 
294
+ def calculate_points_absolute(graph_line)
295
+ @points ||= {}
296
+ if @points[graph_line].nil?
297
+ values = graph_line[:values] || []
298
+ # all points are visible when :values is supplied because we stretch the graph to show them all
299
+ graph_y_max = [y_value_max_for_all_lines, 1].max
300
+ x_value_range_for_all_lines
301
+ points = values.each_with_index.map do |(x_value, y_value), index|
302
+ relative_x_value = x_value - x_value_min_for_all_lines
303
+ stretched_x_value = x_value_range_for_all_lines == 0 ? 0 : relative_x_value.to_f * x_resolution.to_f
304
+ x = width - graph_padding_width - stretched_x_value
305
+ y = ((height - graph_padding_height) - y_value * ((height - graph_padding_height * 2) / graph_y_max))
306
+ {x: x, y: y, index: index, x_value: x_value, y_value: y_value}
307
+ end
308
+ # Translation is not supported today
309
+ # TODO consider supporting in the future
310
+ # @points[graph_line] = translate_points(graph_line, points)
311
+ @points[graph_line] = points
312
+ end
313
+ @points[graph_line]
314
+ end
315
+
316
+ # this is the multiplier that we must multiply by the relative_x_value
317
+ def x_resolution
318
+ @x_resolution ||= drawable_width.to_f / x_value_range_for_all_lines.to_f
319
+ end
320
+
321
+ def x_value_range_for_all_lines
322
+ @x_value_range_for_all_lines ||= x_value_max_for_all_lines - x_value_min_for_all_lines
323
+ end
324
+
325
+ def x_value_min_for_all_lines
326
+ if @x_value_min_for_all_lines.nil?
327
+ line_visible_x_values = lines.map { |line| line[:values].to_h.keys }
328
+ all_visible_x_values = line_visible_x_values.reduce(:+) || []
329
+ # Right now, we assume Time objects
330
+ # TODO support String representations of Time (w/ some auto-detection of format)
331
+ @x_value_min_for_all_lines = all_visible_x_values.min
332
+ end
333
+ @x_value_min_for_all_lines
334
+ end
335
+
336
+ def x_value_max_for_all_lines
337
+ if @x_value_max_for_all_lines.nil?
338
+ line_visible_x_values = lines.map { |line| line[:values].to_h.keys }
339
+ all_visible_x_values = line_visible_x_values.reduce(:+) || []
340
+ # Right now, we assume Time objects
341
+ # TODO support String representations of Time (w/ some auto-detection of format)
342
+ @x_value_max_for_all_lines = all_visible_x_values.max
343
+ end
344
+ @x_value_max_for_all_lines
345
+ end
346
+
239
347
  def y_value_max_for_all_lines
240
348
  if @y_value_max_for_all_lines.nil?
241
- line_visible_y_values = lines.map { |line| line[:y_values][0, max_visible_point_count(line)] }
349
+ if lines[0]&.[](:y_values)
350
+ line_visible_y_values = lines.map { |line| line[:y_values][0, max_visible_point_count(line)] }
351
+ else
352
+ # When using :values , we always stretch the graph so that all points are visible
353
+ line_visible_y_values = lines.map { |line| line[:values].to_h.values }
354
+ end
242
355
  all_visible_y_values = line_visible_y_values.reduce(:+) || []
243
356
  @y_value_max_for_all_lines = all_visible_y_values.max.to_f
244
357
  end
@@ -257,14 +370,16 @@ module Glimmer
257
370
  points
258
371
  end
259
372
 
260
- def max_visible_point_count(graph_line) = (width / graph_point_distance_for_line(graph_line)).to_i + 1
373
+ def max_visible_point_count(graph_line) = ((width - graph_grid_marker_padding_width) / graph_point_distance_for_line(graph_line)).to_i + 1
261
374
 
262
375
  def periodic_lines
263
376
  return unless lines && lines[0] && lines[0][:x_interval_in_seconds] && lines[0][:x_interval_in_seconds] == DAY_IN_SECONDS
264
377
  day_count = lines[0][:y_values].size
265
378
  case day_count
266
379
  when ..7
267
- @points[lines[0]].each do |point|
380
+ @points[lines[0]].each_with_index do |point, index|
381
+ next if index == 0
382
+
268
383
  line(point[:x], graph_padding_height, point[:x], height - graph_padding_height) {
269
384
  stroke graph_stroke_periodic_line
270
385
  }
@@ -323,68 +438,64 @@ module Glimmer
323
438
  x = @hover_point[:x]
324
439
  closest_points = lines.map { |line| @points[line][@closest_point_index] }
325
440
  closest_x = closest_points[0]&.[](:x)
326
- closest_x_distance = PerfectShape::Point.point_distance(x.to_f, 0, closest_x.to_f, 0)
327
- # Today, we make the assumption that all lines have points along the same x-axis values
328
- # TODO In the future, we can support different x values along different lines
329
- if closest_x_distance < graph_point_distance_for_line(lines[0])
330
- line(closest_x, graph_padding_height, closest_x, height - graph_padding_height) {
331
- stroke graph_stroke_hover_line
441
+ line(closest_x, graph_padding_height, closest_x, height - graph_padding_height) {
442
+ stroke graph_stroke_hover_line
443
+ }
444
+ closest_points.each_with_index do |closest_point, index|
445
+ next unless closest_point && closest_point[:x] && closest_point[:y]
446
+
447
+ circle(closest_point[:x], closest_point[:y], graph_selected_point_radius) {
448
+ fill graph_fill_selected_point == :line_stroke ? lines[index][:stroke] : graph_fill_selected_point
449
+ stroke_value = lines[index][:stroke].dup
450
+ stroke_value << {} unless stroke_value.last.is_a?(Hash)
451
+ stroke_value.last[:thickness] = 2
452
+ stroke stroke_value
332
453
  }
333
- closest_points.each_with_index do |closest_point, index|
334
- next unless closest_point && closest_point[:x] && closest_point[:y]
335
-
336
- circle(closest_point[:x], closest_point[:y], 4) {
337
- fill lines[index][:stroke]
338
- }
339
- circle(closest_point[:x], closest_point[:y], 2) {
340
- fill :white
341
- }
342
- end
343
- text_label = formatted_x_value(@closest_point_index)
344
- text_label_width = estimate_width_of_text(text_label, DEFAULT_GRAPH_FONT_MARKER_TEXT)
345
- lines_with_closest_points = lines.each_with_index.map do |line, index|
346
- next if closest_points[index].nil?
347
-
348
- line
349
- end
350
- closest_point_texts = lines_with_closest_points.map { |line| "#{line[:name]}: #{line[:y_values][@closest_point_index]}" }
351
- closest_point_text_widths = closest_point_texts.map do |text|
352
- estimate_width_of_text(text, graph_font_marker_text)
353
- end
354
- square_size = 12.0
355
- square_to_label_padding = 10.0
356
- label_padding = 10.0
357
- text_label_x = width - graph_padding_width - text_label_width - label_padding -
358
- (lines_with_closest_points.size*(square_size + square_to_label_padding) + (lines_with_closest_points.size - 1)*label_padding + closest_point_text_widths.sum)
359
- text_label_y = height + graph_padding_height
454
+ end
455
+ text_label = formatted_x_value(@closest_point_index)
456
+ text_label_width = estimate_width_of_text(text_label, DEFAULT_GRAPH_FONT_MARKER_TEXT)
457
+ lines_with_closest_points = lines.each_with_index.map do |line, index|
458
+ next if closest_points[index].nil?
459
+
460
+ line
461
+ end.compact
462
+ closest_point_texts = lines_with_closest_points.map { |line| "#{line[:name]}: #{line[:y_values][@closest_point_index]}" }
463
+ closest_point_text_widths = closest_point_texts.map do |text|
464
+ estimate_width_of_text(text, graph_font_marker_text)
465
+ end
466
+ square_size = 12.0
467
+ square_to_label_padding = 10.0
468
+ label_padding = 10.0
469
+ text_label_x = width - graph_padding_width - text_label_width - label_padding -
470
+ (lines_with_closest_points.size*(square_size + square_to_label_padding) + (lines_with_closest_points.size - 1)*label_padding + closest_point_text_widths.sum)
471
+ text_label_y = height + graph_padding_height
360
472
 
361
- text(text_label_x, text_label_y, text_label_width) {
362
- string(text_label) {
363
- font DEFAULT_GRAPH_FONT_MARKER_TEXT
364
- color graph_color_marker_text
365
- }
473
+ text(text_label_x, text_label_y, text_label_width) {
474
+ string(text_label) {
475
+ font DEFAULT_GRAPH_FONT_MARKER_TEXT
476
+ color graph_color_marker_text
366
477
  }
478
+ }
367
479
 
368
- relative_x = text_label_x + text_label_width
369
- lines_with_closest_points.size.times do |index|
370
- square_x = relative_x + label_padding
480
+ relative_x = text_label_x + text_label_width
481
+ lines_with_closest_points.size.times do |index|
482
+ square_x = relative_x + label_padding
371
483
 
372
- square(square_x, text_label_y + 2, square_size) {
373
- fill lines_with_closest_points[index][:stroke]
374
- }
484
+ square(square_x, text_label_y + 2, square_size) {
485
+ fill lines_with_closest_points[index][:stroke]
486
+ }
375
487
 
376
- attribute_label_x = square_x + square_size + square_to_label_padding
377
- attribute_text = closest_point_texts[index]
378
- attribute_text_width = closest_point_text_widths[index]
379
- relative_x = attribute_label_x + attribute_text_width
488
+ attribute_label_x = square_x + square_size + square_to_label_padding
489
+ attribute_text = closest_point_texts[index]
490
+ attribute_text_width = closest_point_text_widths[index]
491
+ relative_x = attribute_label_x + attribute_text_width
380
492
 
381
- text(attribute_label_x, text_label_y, attribute_text_width) {
382
- string(attribute_text) {
383
- font graph_font_marker_text
384
- color graph_color_marker_text
385
- }
493
+ text(attribute_label_x, text_label_y, attribute_text_width) {
494
+ string(attribute_text) {
495
+ font graph_font_marker_text
496
+ color graph_color_marker_text
386
497
  }
387
- end
498
+ }
388
499
  end
389
500
  end
390
501
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glimmer-libui-cc-graphs_and_charts
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Maleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-19 00:00:00.000000000 Z
11
+ date: 2023-12-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: glimmer-dsl-libui
@@ -81,6 +81,7 @@ files:
81
81
  - README.md
82
82
  - VERSION
83
83
  - examples/graphs_and_charts/basic_line_graph.rb
84
+ - examples/graphs_and_charts/basic_line_graph_relative.rb
84
85
  - glimmer-libui-cc-graphs_and_charts.gemspec
85
86
  - lib/glimmer-libui-cc-graphs_and_charts.rb
86
87
  - lib/glimmer/view/line_graph.rb