glimmer-libui-cc-graphs_and_charts 0.1.4 → 0.1.6
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 +4 -4
- data/CHANGELOG.md +15 -0
- data/README.md +6 -4
- data/VERSION +1 -1
- data/examples/graphs_and_charts/basic_line_graph.rb +23 -16
- data/examples/graphs_and_charts/basic_line_graph_relative.rb +49 -0
- data/glimmer-libui-cc-graphs_and_charts.gemspec +4 -3
- data/lib/glimmer/view/line_graph.rb +180 -69
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bad5c6db427c320e3b452ee60e2b3af416604525c96e74c915b59c905d746b07
|
4
|
+
data.tar.gz: 3659c73cd8a91a9da31c5cf2cb896b04130a7e1a4c58d2f2e92f7b841726de58
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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
|
[](http://badge.fury.io/rb/glimmer-libui-cc-graphs_and_charts)
|
4
4
|
[](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.
|
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
|
-
|
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
|

|
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
|
-
|
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.
|
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,
|
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: '
|
17
|
+
name: 'Stock 1',
|
23
18
|
stroke: [163, 40, 39, thickness: 2],
|
24
|
-
|
25
|
-
|
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: '
|
29
|
+
name: 'Stock 2',
|
31
30
|
stroke: [47, 109, 104, thickness: 2],
|
32
|
-
|
33
|
-
|
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.
|
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.
|
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-
|
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 =
|
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 =
|
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
|
131
|
-
|
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
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
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
|
-
|
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]].
|
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
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
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
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
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
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
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
|
-
|
369
|
-
|
370
|
-
|
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
|
-
|
373
|
-
|
374
|
-
|
484
|
+
square(square_x, text_label_y + 2, square_size) {
|
485
|
+
fill lines_with_closest_points[index][:stroke]
|
486
|
+
}
|
375
487
|
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
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
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
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
|
-
|
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
|
+
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-
|
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
|