whirled_peas 0.9.0 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +0 -2
- data/CHANGELOG.md +21 -0
- data/README.md +9 -1053
- data/doc/application.md +92 -0
- data/doc/cli.md +115 -0
- data/doc/components.md +51 -0
- data/doc/easing.md +257 -0
- data/doc/elements.md +69 -0
- data/doc/screen_test.md +23 -0
- data/doc/settings.md +466 -0
- data/doc/template_factory.md +53 -0
- data/doc/themes.md +50 -0
- data/examples/components.rb +33 -0
- data/examples/graph.rb +1 -1
- data/examples/scrolling.rb +8 -19
- data/lib/data/themes.yaml +17 -0
- data/lib/whirled_peas.rb +31 -9
- data/lib/whirled_peas/animator/debug_consumer.rb +2 -2
- data/lib/whirled_peas/animator/easing.rb +57 -0
- data/lib/whirled_peas/animator/frameset.rb +13 -8
- data/lib/whirled_peas/animator/producer.rb +7 -8
- data/lib/whirled_peas/animator/renderer_consumer.rb +7 -5
- data/lib/whirled_peas/command/config_command.rb +3 -3
- data/lib/whirled_peas/command/frames.rb +1 -3
- data/lib/whirled_peas/command/play.rb +9 -7
- data/lib/whirled_peas/command/record.rb +1 -3
- data/lib/whirled_peas/command/still.rb +6 -2
- data/lib/whirled_peas/command/themes.rb +78 -0
- data/lib/whirled_peas/command_line.rb +3 -1
- data/lib/whirled_peas/component.rb +35 -0
- data/lib/whirled_peas/component/list_with_active.rb +88 -0
- data/lib/whirled_peas/config.rb +1 -8
- data/lib/whirled_peas/device/null_device.rb +1 -1
- data/lib/whirled_peas/device/output_file.rb +2 -2
- data/lib/whirled_peas/device/rendered_frame.rb +12 -0
- data/lib/whirled_peas/device/screen.rb +12 -8
- data/lib/whirled_peas/graphics/box_painter.rb +4 -4
- data/lib/whirled_peas/graphics/composer.rb +9 -2
- data/lib/whirled_peas/graphics/container_coords.rb +23 -25
- data/lib/whirled_peas/graphics/container_dimensions.rb +24 -0
- data/lib/whirled_peas/graphics/container_painter.rb +27 -139
- data/lib/whirled_peas/graphics/debugger.rb +2 -7
- data/lib/whirled_peas/graphics/graph_painter.rb +31 -22
- data/lib/whirled_peas/graphics/pixel_grid.rb +44 -0
- data/lib/whirled_peas/graphics/renderer.rb +4 -5
- data/lib/whirled_peas/graphics/scrollbar_helper.rb +126 -0
- data/lib/whirled_peas/null_logger.rb +0 -1
- data/lib/whirled_peas/settings/bg_color.rb +5 -1
- data/lib/whirled_peas/settings/border.rb +25 -4
- data/lib/whirled_peas/settings/color.rb +8 -4
- data/lib/whirled_peas/settings/container_settings.rb +14 -7
- data/lib/whirled_peas/settings/debugger.rb +3 -1
- data/lib/whirled_peas/settings/element_settings.rb +18 -6
- data/lib/whirled_peas/settings/graph_settings.rb +1 -1
- data/lib/whirled_peas/settings/position.rb +17 -5
- data/lib/whirled_peas/settings/text_color.rb +5 -0
- data/lib/whirled_peas/settings/text_settings.rb +1 -0
- data/lib/whirled_peas/settings/theme.rb +61 -0
- data/lib/whirled_peas/settings/theme_library.rb +69 -0
- data/lib/whirled_peas/utils/ansi.rb +4 -2
- data/lib/whirled_peas/utils/file_handler.rb +14 -9
- data/lib/whirled_peas/utils/formatted_string.rb +5 -3
- data/lib/whirled_peas/version.rb +1 -1
- data/screen_test/components/list_with_active/l2r_position_end.frame +1 -0
- data/screen_test/components/list_with_active/l2r_position_end.rb +16 -0
- data/screen_test/components/list_with_active/l2r_position_middle.frame +1 -0
- data/screen_test/components/list_with_active/l2r_position_middle.rb +16 -0
- data/screen_test/components/list_with_active/l2r_position_start.frame +1 -0
- data/screen_test/components/list_with_active/l2r_position_start.rb +16 -0
- data/screen_test/components/list_with_active/l2r_separator.frame +1 -0
- data/screen_test/components/list_with_active/l2r_separator.rb +17 -0
- data/screen_test/components/list_with_active/t2b_position_end.frame +1 -0
- data/screen_test/components/list_with_active/t2b_position_end.rb +17 -0
- data/screen_test/components/list_with_active/t2b_position_middle.frame +1 -0
- data/screen_test/components/list_with_active/t2b_position_middle.rb +17 -0
- data/screen_test/components/list_with_active/t2b_position_start.frame +1 -0
- data/screen_test/components/list_with_active/t2b_position_start.rb +17 -0
- data/screen_test/components/list_with_active/t2b_separator.frame +1 -0
- data/screen_test/components/list_with_active/t2b_separator.rb +18 -0
- data/screen_test/elements/box.frame +1 -1
- data/screen_test/elements/box.rb +1 -1
- data/screen_test/elements/graph_asc.frame +1 -0
- data/screen_test/elements/{graph.rb → graph_asc.rb} +1 -1
- data/screen_test/elements/graph_desc.frame +1 -0
- data/screen_test/elements/graph_desc.rb +12 -0
- data/screen_test/elements/graph_horiz.frame +1 -0
- data/screen_test/elements/graph_horiz.rb +12 -0
- data/screen_test/elements/graph_sin.frame +1 -0
- data/screen_test/elements/graph_sin.rb +12 -0
- data/screen_test/elements/grid.frame +1 -1
- data/screen_test/elements/grid.rb +1 -1
- data/screen_test/elements/screen_overflow_x.frame +1 -1
- data/screen_test/elements/screen_overflow_x.rb +1 -1
- data/screen_test/elements/screen_overflow_y.frame +1 -1
- data/screen_test/elements/screen_overflow_y.rb +1 -1
- data/screen_test/elements/text.frame +1 -1
- data/screen_test/elements/text.rb +1 -1
- data/screen_test/elements/text_multiline.frame +1 -1
- data/screen_test/elements/text_multiline.rb +1 -1
- data/screen_test/elements/theme.frame +1 -0
- data/screen_test/elements/theme.rb +26 -0
- data/screen_test/settings/align/box_around.frame +1 -1
- data/screen_test/settings/align/box_around.rb +1 -1
- data/screen_test/settings/align/box_between.frame +1 -1
- data/screen_test/settings/align/box_between.rb +1 -1
- data/screen_test/settings/align/box_center.frame +1 -1
- data/screen_test/settings/align/box_center.rb +1 -1
- data/screen_test/settings/align/box_default.frame +1 -1
- data/screen_test/settings/align/box_default.rb +1 -1
- data/screen_test/settings/align/box_evenly.frame +1 -1
- data/screen_test/settings/align/box_evenly.rb +1 -1
- data/screen_test/settings/align/box_left.frame +1 -1
- data/screen_test/settings/align/box_left.rb +1 -1
- data/screen_test/settings/align/box_right.frame +1 -1
- data/screen_test/settings/align/box_right.rb +1 -1
- data/screen_test/settings/align/children_center.frame +1 -1
- data/screen_test/settings/align/children_center.rb +1 -1
- data/screen_test/settings/align/children_left.frame +1 -1
- data/screen_test/settings/align/children_left.rb +1 -1
- data/screen_test/settings/align/children_right.frame +1 -1
- data/screen_test/settings/align/children_right.rb +1 -1
- data/screen_test/settings/align/grid_center.frame +1 -1
- data/screen_test/settings/align/grid_center.rb +1 -1
- data/screen_test/settings/align/grid_default.frame +1 -1
- data/screen_test/settings/align/grid_default.rb +1 -1
- data/screen_test/settings/align/grid_left.frame +1 -1
- data/screen_test/settings/align/grid_left.rb +1 -1
- data/screen_test/settings/align/grid_right.frame +1 -1
- data/screen_test/settings/align/grid_right.rb +1 -1
- data/screen_test/settings/ansi/bold.frame +1 -1
- data/screen_test/settings/ansi/bold.rb +1 -1
- data/screen_test/settings/ansi/color.frame +1 -1
- data/screen_test/settings/ansi/color.rb +1 -1
- data/screen_test/settings/ansi/underline.frame +1 -1
- data/screen_test/settings/ansi/underline.rb +1 -1
- data/screen_test/settings/border.frame +1 -1
- data/screen_test/settings/border.rb +1 -1
- data/screen_test/settings/content_start/box_bottom.frame +1 -0
- data/screen_test/settings/content_start/box_bottom.rb +17 -0
- data/screen_test/settings/content_start/box_left.frame +1 -0
- data/screen_test/settings/{position → content_start}/box_left.rb +2 -2
- data/screen_test/settings/content_start/box_left_negative.frame +1 -0
- data/screen_test/settings/{position → content_start}/box_left_negative.rb +2 -2
- data/screen_test/settings/content_start/box_right.frame +1 -0
- data/screen_test/settings/content_start/box_right.rb +17 -0
- data/screen_test/settings/content_start/box_top.frame +1 -0
- data/screen_test/settings/{position → content_start}/box_top.rb +2 -2
- data/screen_test/settings/content_start/box_top_negative.frame +1 -0
- data/screen_test/settings/{position → content_start}/box_top_negative.rb +2 -2
- data/screen_test/settings/content_start/grid_left.frame +1 -0
- data/screen_test/settings/{position → content_start}/grid_left.rb +2 -2
- data/screen_test/settings/content_start/grid_left_negative.frame +1 -0
- data/screen_test/settings/{position → content_start}/grid_left_negative.rb +2 -2
- data/screen_test/settings/content_start/grid_top.frame +1 -0
- data/screen_test/settings/{position → content_start}/grid_top.rb +2 -2
- data/screen_test/settings/content_start/grid_top_negative.frame +1 -0
- data/screen_test/settings/{position → content_start}/grid_top_negative.rb +2 -2
- data/screen_test/settings/flow/box_b2t.frame +1 -1
- data/screen_test/settings/flow/box_b2t.rb +1 -1
- data/screen_test/settings/flow/box_l2r.frame +1 -1
- data/screen_test/settings/flow/box_l2r.rb +1 -1
- data/screen_test/settings/flow/box_r2l.frame +1 -1
- data/screen_test/settings/flow/box_r2l.rb +1 -1
- data/screen_test/settings/flow/box_t2b.frame +1 -1
- data/screen_test/settings/flow/box_t2b.rb +1 -1
- data/screen_test/settings/flow/grid_b2t.frame +1 -1
- data/screen_test/settings/flow/grid_b2t.rb +1 -1
- data/screen_test/settings/flow/grid_l2r.frame +1 -1
- data/screen_test/settings/flow/grid_l2r.rb +1 -1
- data/screen_test/settings/flow/grid_r2l.frame +1 -1
- data/screen_test/settings/flow/grid_r2l.rb +1 -1
- data/screen_test/settings/flow/grid_t2b.frame +1 -1
- data/screen_test/settings/flow/grid_t2b.rb +1 -1
- data/screen_test/settings/height/box.frame +1 -1
- data/screen_test/settings/height/box.rb +1 -1
- data/screen_test/settings/height/box_border_sizing.frame +1 -1
- data/screen_test/settings/height/box_border_sizing.rb +1 -1
- data/screen_test/settings/height/grid.frame +1 -1
- data/screen_test/settings/height/grid.rb +1 -1
- data/screen_test/settings/height/overflow_box.frame +1 -1
- data/screen_test/settings/height/overflow_box.rb +1 -1
- data/screen_test/settings/height/overflow_box_l2r.frame +1 -1
- data/screen_test/settings/height/overflow_box_l2r.rb +1 -1
- data/screen_test/settings/height/overflow_box_t2b.frame +1 -1
- data/screen_test/settings/height/overflow_box_t2b.rb +1 -1
- data/screen_test/settings/height/overflow_grid.frame +1 -1
- data/screen_test/settings/height/overflow_grid.rb +1 -1
- data/screen_test/settings/margin.frame +1 -1
- data/screen_test/settings/margin.rb +1 -1
- data/screen_test/settings/padding.frame +1 -1
- data/screen_test/settings/padding.rb +1 -1
- data/screen_test/settings/scroll/horiz_box.frame +1 -1
- data/screen_test/settings/scroll/horiz_box.rb +3 -5
- data/screen_test/settings/scroll/horiz_box_align_center.rb +3 -5
- data/screen_test/settings/scroll/horiz_box_align_right.rb +3 -5
- data/screen_test/settings/scroll/vert_box.frame +1 -1
- data/screen_test/settings/scroll/vert_box.rb +6 -8
- data/screen_test/settings/title_font.frame +1 -1
- data/screen_test/settings/title_font.rb +1 -1
- data/screen_test/settings/valign/box_around.frame +1 -1
- data/screen_test/settings/valign/box_around.rb +1 -1
- data/screen_test/settings/valign/box_between.frame +1 -1
- data/screen_test/settings/valign/box_between.rb +1 -1
- data/screen_test/settings/valign/box_bottom.frame +1 -1
- data/screen_test/settings/valign/box_bottom.rb +1 -1
- data/screen_test/settings/valign/box_default.frame +1 -1
- data/screen_test/settings/valign/box_default.rb +1 -1
- data/screen_test/settings/valign/box_evenly.frame +1 -1
- data/screen_test/settings/valign/box_evenly.rb +1 -1
- data/screen_test/settings/valign/box_middle.frame +1 -1
- data/screen_test/settings/valign/box_middle.rb +1 -1
- data/screen_test/settings/valign/box_top.frame +1 -1
- data/screen_test/settings/valign/box_top.rb +1 -1
- data/screen_test/settings/valign/grid_bottom.frame +1 -1
- data/screen_test/settings/valign/grid_bottom.rb +1 -1
- data/screen_test/settings/valign/grid_default.frame +1 -1
- data/screen_test/settings/valign/grid_default.rb +1 -1
- data/screen_test/settings/valign/grid_middle.frame +1 -1
- data/screen_test/settings/valign/grid_middle.rb +1 -1
- data/screen_test/settings/valign/grid_top.frame +1 -1
- data/screen_test/settings/valign/grid_top.rb +1 -1
- data/screen_test/settings/width/box_border_sizing.frame +1 -1
- data/screen_test/settings/width/box_border_sizing.rb +1 -1
- data/screen_test/settings/width/box_content.frame +1 -1
- data/screen_test/settings/width/box_content.rb +1 -1
- data/screen_test/settings/width/box_default.frame +1 -1
- data/screen_test/settings/width/box_default.rb +1 -1
- data/screen_test/settings/width/grid.frame +1 -1
- data/screen_test/settings/width/grid.rb +1 -1
- data/screen_test/settings/width/overflow_align_center.frame +1 -1
- data/screen_test/settings/width/overflow_align_center.rb +1 -1
- data/screen_test/settings/width/overflow_align_right.frame +1 -1
- data/screen_test/settings/width/overflow_align_right.rb +1 -1
- data/screen_test/settings/width/overflow_box.frame +1 -1
- data/screen_test/settings/width/overflow_box.rb +1 -1
- data/screen_test/settings/width/overflow_box_l2r.frame +1 -1
- data/screen_test/settings/width/overflow_box_l2r.rb +1 -1
- data/screen_test/settings/width/overflow_box_t2b.frame +1 -1
- data/screen_test/settings/width/overflow_box_t2b.rb +1 -1
- data/screen_test/settings/width/overflow_grid.frame +1 -1
- data/screen_test/settings/width/overflow_grid.rb +1 -1
- data/tools/whirled_peas/tools/screen_tester.rb +20 -3
- metadata +67 -22
- data/bin/easing +0 -33
- data/lib/whirled_peas/graphics/mock_screen.rb +0 -26
- data/screen_test/elements/graph.frame +0 -1
- data/screen_test/settings/position/box_left.frame +0 -1
- data/screen_test/settings/position/box_left_negative.frame +0 -1
- data/screen_test/settings/position/box_top.frame +0 -1
- data/screen_test/settings/position/box_top_negative.frame +0 -1
- data/screen_test/settings/position/grid_left.frame +0 -1
- data/screen_test/settings/position/grid_left_negative.frame +0 -1
- data/screen_test/settings/position/grid_top.frame +0 -1
- data/screen_test/settings/position/grid_top_negative.frame +0 -1
@@ -9,11 +9,11 @@ module WhirledPeas
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def left
|
12
|
-
start_left
|
12
|
+
start_left
|
13
13
|
end
|
14
14
|
|
15
15
|
def top
|
16
|
-
start_top
|
16
|
+
start_top
|
17
17
|
end
|
18
18
|
|
19
19
|
def border_left
|
@@ -33,35 +33,33 @@ module WhirledPeas
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def content_left(col_index=0)
|
36
|
-
padding_left + settings.padding.left + col_index * grid_width
|
36
|
+
padding_left + settings.padding.left + col_index * dimensions.grid_width
|
37
37
|
end
|
38
38
|
|
39
|
-
def
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
39
|
+
def offset_content_left(col_index=0)
|
40
|
+
if settings.content_start.left
|
41
|
+
content_left(col_index) + settings.content_start.left
|
42
|
+
elsif settings.content_start.right
|
43
|
+
left_offset = dimensions.content_width - dimensions.children_width
|
44
|
+
content_left(col_index) + left_offset - settings.content_start.right
|
45
|
+
else
|
46
|
+
content_left(col_index)
|
47
|
+
end
|
47
48
|
end
|
48
49
|
|
49
|
-
def
|
50
|
-
|
51
|
-
inner_grid_width +
|
52
|
-
(settings.scrollbar.vert? ? 1 : 0)
|
53
|
-
end
|
54
|
-
|
55
|
-
def inner_grid_height
|
56
|
-
settings.padding.top +
|
57
|
-
dimensions.content_height +
|
58
|
-
settings.padding.bottom
|
50
|
+
def content_top(row_index=0)
|
51
|
+
padding_top + settings.padding.top + row_index * dimensions.grid_height
|
59
52
|
end
|
60
53
|
|
61
|
-
def
|
62
|
-
|
63
|
-
|
64
|
-
|
54
|
+
def offset_content_top(row_index=0)
|
55
|
+
if settings.content_start.top
|
56
|
+
content_top(row_index) + settings.content_start.top
|
57
|
+
elsif settings.content_start.bottom
|
58
|
+
top_offset = dimensions.content_height - dimensions.children_height
|
59
|
+
content_top(row_index) + top_offset - settings.content_start.bottom
|
60
|
+
else
|
61
|
+
content_top(row_index)
|
62
|
+
end
|
65
63
|
end
|
66
64
|
|
67
65
|
private
|
@@ -31,6 +31,30 @@ module WhirledPeas
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
+
def inner_grid_width
|
35
|
+
settings.padding.left +
|
36
|
+
content_width +
|
37
|
+
settings.padding.right
|
38
|
+
end
|
39
|
+
|
40
|
+
def grid_width
|
41
|
+
(settings.border.inner_vert? ? 1 : 0) +
|
42
|
+
inner_grid_width +
|
43
|
+
(settings.scrollbar.vert? ? 1 : 0)
|
44
|
+
end
|
45
|
+
|
46
|
+
def inner_grid_height
|
47
|
+
settings.padding.top +
|
48
|
+
content_height +
|
49
|
+
settings.padding.bottom
|
50
|
+
end
|
51
|
+
|
52
|
+
def grid_height
|
53
|
+
(settings.border.inner_horiz? ? 1 : 0) +
|
54
|
+
inner_grid_height +
|
55
|
+
(settings.scrollbar.horiz? ? 1 : 0)
|
56
|
+
end
|
57
|
+
|
34
58
|
def outer_width
|
35
59
|
@outer_width ||= margin_width +
|
36
60
|
outer_border_width +
|
@@ -2,6 +2,7 @@ require 'whirled_peas/utils/formatted_string'
|
|
2
2
|
|
3
3
|
require_relative 'container_coords'
|
4
4
|
require_relative 'painter'
|
5
|
+
require_relative 'scrollbar_helper'
|
5
6
|
|
6
7
|
module WhirledPeas
|
7
8
|
module Graphics
|
@@ -34,11 +35,17 @@ module WhirledPeas
|
|
34
35
|
|
35
36
|
# Paint the top border if the settings call for it
|
36
37
|
if settings.border.top?
|
37
|
-
canvas.stroke(stroke_left, stroke_top, top_border_stroke
|
38
|
+
canvas.stroke(stroke_left, stroke_top, top_border_stroke, formatting, &block)
|
38
39
|
stroke_top += 1
|
39
40
|
end
|
40
41
|
# Precalculate the middle border container grids with more than 1 row
|
41
|
-
middle_border = dimensions.num_rows > 1 ? middle_border_stroke
|
42
|
+
middle_border = dimensions.num_rows > 1 ? middle_border_stroke : ''
|
43
|
+
|
44
|
+
vert_scrollbar = settings.scrollbar.vert? ? ScrollbarHelper.vert(
|
45
|
+
dimensions.children_height + dimensions.padding_height,
|
46
|
+
dimensions.inner_grid_height,
|
47
|
+
canvas_coords.content_top - canvas_coords.offset_content_top,
|
48
|
+
) : []
|
42
49
|
|
43
50
|
# Paint each grid row by row
|
44
51
|
dimensions.num_rows.times do |row_num|
|
@@ -52,8 +59,9 @@ module WhirledPeas
|
|
52
59
|
|
53
60
|
# Paint the interior of each row (horizontal borders, veritical scroll bar and
|
54
61
|
# background color for the padding and content area)
|
55
|
-
|
56
|
-
|
62
|
+
dimensions.inner_grid_height.times do |row_within_cell|
|
63
|
+
content_line = content_line_stroke(row_within_cell, vert_scrollbar)
|
64
|
+
canvas.stroke(stroke_left, stroke_top, content_line, formatting, &block)
|
57
65
|
stroke_top += 1
|
58
66
|
end
|
59
67
|
|
@@ -66,7 +74,7 @@ module WhirledPeas
|
|
66
74
|
|
67
75
|
# Paint the bottom border if the settings call for it
|
68
76
|
if settings.border.bottom?
|
69
|
-
canvas.stroke(stroke_left, stroke_top, bottom_border_stroke
|
77
|
+
canvas.stroke(stroke_left, stroke_top, bottom_border_stroke, formatting, &block)
|
70
78
|
stroke_top += 1
|
71
79
|
end
|
72
80
|
end
|
@@ -176,59 +184,49 @@ module WhirledPeas
|
|
176
184
|
end
|
177
185
|
|
178
186
|
# Return the stroke for the top border
|
179
|
-
def top_border_stroke
|
187
|
+
def top_border_stroke
|
180
188
|
line_stroke(
|
181
189
|
settings.border.style.top_left,
|
182
190
|
settings.border.style.top_junc,
|
183
191
|
settings.border.style.top_right
|
184
192
|
) do
|
185
|
-
settings.border.style.top_horiz * (
|
193
|
+
settings.border.style.top_horiz * (dimensions.inner_grid_width + (settings.scrollbar.vert? ? 1 : 0))
|
186
194
|
end
|
187
195
|
end
|
188
196
|
|
189
197
|
# Return the stroke for an inner horizontal border
|
190
|
-
def middle_border_stroke
|
198
|
+
def middle_border_stroke
|
191
199
|
line_stroke(
|
192
200
|
settings.border.style.left_junc,
|
193
201
|
settings.border.style.cross_junc,
|
194
202
|
settings.border.style.right_junc
|
195
203
|
) do
|
196
|
-
settings.border.style.middle_horiz * (
|
204
|
+
settings.border.style.middle_horiz * (dimensions.inner_grid_width + (settings.scrollbar.vert? ? 1 : 0))
|
197
205
|
end
|
198
206
|
end
|
199
207
|
|
200
208
|
# Return the stroke for the bottom border
|
201
|
-
def bottom_border_stroke
|
209
|
+
def bottom_border_stroke
|
202
210
|
line_stroke(
|
203
211
|
settings.border.style.bottom_left,
|
204
212
|
settings.border.style.bottom_junc,
|
205
213
|
settings.border.style.bottom_right
|
206
214
|
) do
|
207
|
-
settings.border.style.bottom_horiz * (
|
215
|
+
settings.border.style.bottom_horiz * (dimensions.inner_grid_width + (settings.scrollbar.vert? ? 1 : 0))
|
208
216
|
end
|
209
217
|
end
|
210
218
|
|
211
219
|
# Return the stroke for a grid row between any borders
|
212
|
-
def content_line_stroke(
|
220
|
+
def content_line_stroke(row_within_cell, vert_scrollbar)
|
213
221
|
line_stroke(
|
214
222
|
settings.border.style.left_vert,
|
215
223
|
settings.border.style.middle_vert,
|
216
224
|
settings.border.style.right_vert,
|
217
225
|
) do
|
218
226
|
if settings.scrollbar.vert?
|
219
|
-
|
220
|
-
scrollbar_char = GUTTER
|
221
|
-
else
|
222
|
-
scrollbar_char = vert_scroll_char(
|
223
|
-
dimensions.children_height + dimensions.padding_height,
|
224
|
-
canvas_coords.inner_grid_height,
|
225
|
-
-children.first.settings.position.top,
|
226
|
-
row_within_cell
|
227
|
-
)
|
228
|
-
end
|
229
|
-
PADDING * canvas_coords.inner_grid_width + scrollbar_char
|
227
|
+
PADDING * dimensions.inner_grid_width + vert_scrollbar[row_within_cell]
|
230
228
|
else
|
231
|
-
PADDING *
|
229
|
+
PADDING * dimensions.inner_grid_width
|
232
230
|
end
|
233
231
|
end
|
234
232
|
end
|
@@ -240,121 +238,11 @@ module WhirledPeas
|
|
240
238
|
settings.border.style.middle_vert,
|
241
239
|
settings.border.style.right_vert,
|
242
240
|
) do
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
col_within_cell
|
249
|
-
)
|
250
|
-
end.join
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
# Contants to paint scrollbars
|
255
|
-
GUTTER = ' '
|
256
|
-
HORIZONTAL = %w[▗ ▄ ▖]
|
257
|
-
VERTICAL = %w[
|
258
|
-
▗
|
259
|
-
▐
|
260
|
-
▝
|
261
|
-
]
|
262
|
-
|
263
|
-
# Determine the character to paint the horizontal scroll bar with for the given column
|
264
|
-
#
|
265
|
-
# @see #scroll_char for more details
|
266
|
-
def horiz_scroll_char(col_count, viewable_col_count, first_visible_col, curr_col)
|
267
|
-
scroll_char(col_count, viewable_col_count, first_visible_col, curr_col, HORIZONTAL)
|
268
|
-
end
|
269
|
-
|
270
|
-
# Determine the character to paint the vertical scroll bar with for the given row
|
271
|
-
#
|
272
|
-
# @see #scroll_char for more details
|
273
|
-
def vert_scroll_char(row_count, viewable_row_count, first_visible_row, curr_row)
|
274
|
-
scroll_char(row_count, viewable_row_count, first_visible_row, curr_row, VERTICAL)
|
275
|
-
end
|
276
|
-
|
277
|
-
private
|
278
|
-
|
279
|
-
# Determine which character to paint a for a scrollbar
|
280
|
-
#
|
281
|
-
# @param total_count [Integer] total number of rows/columns in the content
|
282
|
-
# @param viewable_count [Integer] number of rows/columns visible in the viewport
|
283
|
-
# @param first_visible [Integer] zero-based index of the first row/column that is visible
|
284
|
-
# in the viewport
|
285
|
-
# @param curr [Integer] zero-based index of the row/column (relative to the first visible
|
286
|
-
# row/column) that the painted character is being requested for
|
287
|
-
# @param chars [Array<String>] an array with three 1-character strings, the frist is the
|
288
|
-
# "second half" scrollbar character, the second is the "full" scrollbar character, and
|
289
|
-
# the third is the "first half" scrollbar character.
|
290
|
-
def scroll_char(total_count, viewable_count, first_visible, curr, chars)
|
291
|
-
return GUTTER unless total_count > 0 && viewable_count > 0
|
292
|
-
# The scroll handle has the exact same relative size and position in the scroll gutter
|
293
|
-
# that the viewable content has in the total content area. For example, a content area
|
294
|
-
# that is 50 columns wide with a view port that is 20 columns wide might look like
|
295
|
-
#
|
296
|
-
# +---------1-----****2*********3******---4---------+
|
297
|
-
# | * * |
|
298
|
-
# | hidden * viewable * hidden |
|
299
|
-
# | * * |
|
300
|
-
# +---------1-----****2*********3******---4---------+
|
301
|
-
#
|
302
|
-
# The scoll gutter, would look like
|
303
|
-
#
|
304
|
-
# |......********.....|
|
305
|
-
#
|
306
|
-
# Scrolling all the way to the right results in
|
307
|
-
#
|
308
|
-
# +---------1---------2---------3*********4*********+
|
309
|
-
# | * *
|
310
|
-
# | hidden * viewable *
|
311
|
-
# | * *
|
312
|
-
# +---------1---------2---------3*********4*********+
|
313
|
-
# |...........********|
|
314
|
-
#
|
315
|
-
# Returning to the first example, we can match up the arguments to this method to the
|
316
|
-
# diagram
|
317
|
-
#
|
318
|
-
# total_count = 50
|
319
|
-
# |<----------------------------------------------->|
|
320
|
-
# | |
|
321
|
-
# | veiwable_count = 20 |
|
322
|
-
# | |<----------------->| |
|
323
|
-
# ↓ ↓ ↓ ↓
|
324
|
-
# +---------1-----****2*********3******---4---------+
|
325
|
-
# | * * |
|
326
|
-
# | hidden * viewable * hidden |
|
327
|
-
# | * * |
|
328
|
-
# +---------1-----****2*********3******---4---------+
|
329
|
-
# |......****?***.....|
|
330
|
-
# ↑ ↑
|
331
|
-
# first_visible = 16 |
|
332
|
-
# curr = 11
|
333
|
-
|
334
|
-
# The first task of determining how much of the handle is visible in a row/column is to
|
335
|
-
# calculate the range (as a precentage of the total) of viewable items
|
336
|
-
viewable_start = first_visible.to_f / total_count
|
337
|
-
viewable_end = (first_visible + viewable_count).to_f / total_count
|
338
|
-
|
339
|
-
# Always use the same length for the scroll bar so it does not give an inchworm effect
|
340
|
-
# as it scrolls along.
|
341
|
-
#
|
342
|
-
# Also, double the value now to get granularity for half width
|
343
|
-
# scrollbar characters.
|
344
|
-
scrollbar_length = ((2 * viewable_count ** 2).to_f / total_count).ceil
|
345
|
-
scrollbar_start = ((2 * first_visible * viewable_count).to_f / total_count).floor
|
346
|
-
|
347
|
-
first_half = (scrollbar_start...scrollbar_start + scrollbar_length).include?(2 * curr)
|
348
|
-
second_half = (scrollbar_start...scrollbar_start + scrollbar_length).include?(2 * curr + 1)
|
349
|
-
|
350
|
-
if first_half && second_half
|
351
|
-
chars[1]
|
352
|
-
elsif first_half
|
353
|
-
chars[2]
|
354
|
-
elsif second_half
|
355
|
-
chars[0]
|
356
|
-
else
|
357
|
-
GUTTER
|
241
|
+
ScrollbarHelper.horiz(
|
242
|
+
dimensions.children_width + dimensions.padding_width,
|
243
|
+
dimensions.inner_grid_width,
|
244
|
+
canvas_coords.content_left - canvas_coords.offset_content_left
|
245
|
+
).join
|
358
246
|
end
|
359
247
|
end
|
360
248
|
end
|
@@ -15,16 +15,11 @@ module WhirledPeas
|
|
15
15
|
"#{indent}* #{painter.class}(#{painter.name})",
|
16
16
|
]
|
17
17
|
info << "#{indent + ' '}- Dimensions(#{dimensions})"
|
18
|
+
info << "#{indent + ' '}- Theme=#{painter.settings.theme.inspect}" if indent == ''
|
18
19
|
info << "#{indent + ' '}- Settings"
|
19
20
|
info << Settings::Debugger.new(painter.settings).debug(indent + ' ')
|
20
21
|
if painter.is_a?(TextPainter)
|
21
|
-
content =
|
22
|
-
'<multiline>'
|
23
|
-
elsif painter.content.first.length > 12
|
24
|
-
"#{painter.content.first[0..9]}...".inspect
|
25
|
-
else
|
26
|
-
painter.content.first.inspect
|
27
|
-
end
|
22
|
+
content = painter.content
|
28
23
|
info << "#{indent + ' '}- Content(value=#{content})"
|
29
24
|
elsif painter.is_a?(ContainerPainter)
|
30
25
|
info << "#{indent + ' '}- Children"
|
@@ -5,6 +5,10 @@ require_relative 'content_painter'
|
|
5
5
|
module WhirledPeas
|
6
6
|
module Graphics
|
7
7
|
class GraphPainter < ContentPainter
|
8
|
+
# The number of units along the Y-axis a single character can be divided into
|
9
|
+
Y_AXIS_SCALE = 2
|
10
|
+
private_constant :Y_AXIS_SCALE
|
11
|
+
|
8
12
|
def paint(canvas, left, top, &block)
|
9
13
|
axis_formatting = [*settings.axis_color, *settings.bg_color]
|
10
14
|
plot_formatting = [*settings.color, *settings.bg_color]
|
@@ -26,8 +30,8 @@ module WhirledPeas
|
|
26
30
|
min_y = 1.0 / 0
|
27
31
|
max_y = -1.0 / 0
|
28
32
|
if settings.width
|
29
|
-
interpolated = inner_width.times.map do |i|
|
30
|
-
x = (i * (content.length - 1).to_f / inner_width).floor
|
33
|
+
interpolated = (inner_width + 1).times.map do |i|
|
34
|
+
x = (i * (content.length - 1).to_f / (inner_width + 1)).floor
|
31
35
|
max_y = content[x] if content[x] > max_y
|
32
36
|
min_y = content[x] if content[x] < min_y
|
33
37
|
content[x]
|
@@ -39,29 +43,34 @@ module WhirledPeas
|
|
39
43
|
min_y = y if y < min_y
|
40
44
|
end
|
41
45
|
end
|
46
|
+
if min_y == max_y
|
47
|
+
min_y -= 1
|
48
|
+
max_y += 1
|
49
|
+
end
|
42
50
|
scaled = interpolated.map do |y|
|
43
|
-
|
51
|
+
inner_height * (y - min_y).to_f / (max_y - min_y)
|
44
52
|
end
|
53
|
+
|
45
54
|
@plot_lines = Array.new(inner_height) { '' }
|
46
|
-
scaled.each.with_index do |y, x_index|
|
55
|
+
scaled[0..-2].each.with_index do |y, x_index|
|
56
|
+
last = x_index == scaled.length - 2
|
57
|
+
|
58
|
+
prev_y = x_index == 0 ? y : scaled[x_index - 1]
|
59
|
+
next_y = scaled[x_index + 1]
|
60
|
+
|
61
|
+
min_y = [(prev_y + y) / 2, y, last ? next_y : (y + next_y) / 2].min
|
62
|
+
min_y = (Y_AXIS_SCALE * min_y).round.to_f / Y_AXIS_SCALE
|
63
|
+
|
64
|
+
max_y = [(prev_y + y) / 2, y, last ? next_y : (y + next_y) / 2].max
|
65
|
+
max_y = (Y_AXIS_SCALE * max_y).round.to_f / Y_AXIS_SCALE
|
66
|
+
|
47
67
|
@plot_lines.each.with_index do |row, row_index|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
else
|
55
|
-
scaled[x_index + 1] >= y
|
56
|
-
[true, scaled[x_index + 1]]
|
57
|
-
end
|
58
|
-
if asc
|
59
|
-
top_half = (y...next_y).include?(2 * y_index + 1)
|
60
|
-
bottom_half = (y...next_y).include?(2 * y_index)
|
61
|
-
else
|
62
|
-
top_half = (next_y...y).include?(2 * y_index + 1)
|
63
|
-
bottom_half = (next_y...y).include?(2 * y_index)
|
64
|
-
end
|
68
|
+
bottom_value = inner_height - row_index - 1
|
69
|
+
top_value = bottom_value + 1.0 / Y_AXIS_SCALE
|
70
|
+
|
71
|
+
top_half = min_y == top_value || (min_y <= top_value && top_value < max_y)
|
72
|
+
bottom_half = min_y == bottom_value || (min_y <= bottom_value && bottom_value < max_y)
|
73
|
+
|
65
74
|
row << if top_half && bottom_half
|
66
75
|
'█'
|
67
76
|
elsif top_half
|
@@ -81,7 +90,7 @@ module WhirledPeas
|
|
81
90
|
end
|
82
91
|
|
83
92
|
def inner_width
|
84
|
-
settings.width.nil? ? content.length : settings.width - 1
|
93
|
+
(settings.width.nil? ? content.length : settings.width) - 1
|
85
94
|
end
|
86
95
|
|
87
96
|
def axes_lines
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module WhirledPeas
|
2
|
+
module Graphics
|
3
|
+
class PixelGrid
|
4
|
+
Pixel = Struct.new(:char, :formatting)
|
5
|
+
|
6
|
+
def initialize(width, height)
|
7
|
+
@pixels = Array.new(height) { Array.new(width) { Pixel.new } }
|
8
|
+
end
|
9
|
+
|
10
|
+
def add_stroke(left, top, fstring)
|
11
|
+
fstring.each_char.with_index do |char, offset|
|
12
|
+
pixels[top][left + offset].char = char
|
13
|
+
pixels[top][left + offset].formatting = fstring.formatting
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_s
|
18
|
+
str = Utils::Ansi.cursor_pos(left: 0, top: 0) + Utils::Ansi.clear_down
|
19
|
+
formatting = nil
|
20
|
+
chars = ''
|
21
|
+
pixels.each.with_index do |row, row_offset|
|
22
|
+
str += Utils::Ansi.cursor_pos(left: 0, top: row_offset) if row_offset > 0
|
23
|
+
row.each do |pixel|
|
24
|
+
if pixel.formatting != formatting
|
25
|
+
str += Utils::FormattedString.new(chars, formatting).to_s if chars != ''
|
26
|
+
chars = ''
|
27
|
+
formatting = pixel.formatting
|
28
|
+
end
|
29
|
+
chars << pixel.char
|
30
|
+
end
|
31
|
+
if chars != ''
|
32
|
+
str += Utils::FormattedString.new(chars, formatting).to_s
|
33
|
+
chars = ''
|
34
|
+
end
|
35
|
+
end
|
36
|
+
str
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
attr_reader :pixels
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|