ratatui_ruby 0.3.1 → 0.4.0
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/.builds/ruby-3.2.yml +14 -12
- data/.builds/ruby-3.3.yml +14 -12
- data/.builds/ruby-3.4.yml +14 -12
- data/.builds/ruby-4.0.0.yml +14 -12
- data/AGENTS.md +54 -13
- data/CHANGELOG.md +186 -1
- data/README.md +17 -15
- data/doc/application_architecture.md +116 -0
- data/doc/application_testing.md +12 -7
- data/doc/contributors/better_dx.md +543 -0
- data/doc/contributors/design/ruby_frontend.md +1 -1
- data/doc/contributors/developing_examples.md +203 -0
- data/doc/contributors/documentation_style.md +97 -0
- data/doc/contributors/dwim_dx.md +366 -0
- data/doc/contributors/example_analysis.md +82 -0
- data/doc/custom.css +14 -0
- data/doc/event_handling.md +119 -0
- data/doc/images/all_events.png +0 -0
- data/doc/images/analytics.png +0 -0
- data/doc/images/block_padding.png +0 -0
- data/doc/images/block_titles.png +0 -0
- data/doc/images/box_demo.png +0 -0
- data/doc/images/calendar_demo.png +0 -0
- data/doc/images/cell_demo.png +0 -0
- data/doc/images/chart_demo.png +0 -0
- data/doc/images/custom_widget.png +0 -0
- data/doc/images/flex_layout.png +0 -0
- data/doc/images/gauge_demo.png +0 -0
- data/doc/images/hit_test.png +0 -0
- data/doc/images/line_gauge_demo.png +0 -0
- data/doc/images/list_demo.png +0 -0
- data/doc/images/list_styles.png +0 -0
- data/doc/images/login_form.png +0 -0
- data/doc/images/map_demo.png +0 -0
- data/doc/images/mouse_events.png +0 -0
- data/doc/images/popup_demo.png +0 -0
- data/doc/images/quickstart_dsl.png +0 -0
- data/doc/images/quickstart_lifecycle.png +0 -0
- data/doc/images/ratatui_logo_demo.png +0 -0
- data/doc/images/readme_usage.png +0 -0
- data/doc/images/rich_text.png +0 -0
- data/doc/images/scroll_text.png +0 -0
- data/doc/images/scrollbar_demo.png +0 -0
- data/doc/images/sparkline_demo.png +0 -0
- data/doc/images/table_flex.png +0 -0
- data/doc/images/table_select.png +0 -0
- data/doc/images/widget_style_colors.png +0 -0
- data/doc/index.md +1 -0
- data/doc/interactive_design.md +121 -0
- data/doc/quickstart.md +147 -72
- data/examples/all_events/app.rb +169 -0
- data/examples/all_events/app.rbs +7 -0
- data/examples/all_events/test_app.rb +139 -0
- data/examples/analytics/app.rb +258 -0
- data/examples/analytics/app.rbs +7 -0
- data/examples/analytics/test_app.rb +132 -0
- data/examples/block_padding/app.rb +63 -0
- data/examples/block_padding/app.rbs +7 -0
- data/examples/block_padding/test_app.rb +31 -0
- data/examples/block_titles/app.rb +61 -0
- data/examples/block_titles/app.rbs +7 -0
- data/examples/block_titles/test_app.rb +34 -0
- data/examples/box_demo/app.rb +216 -0
- data/examples/box_demo/app.rbs +7 -0
- data/examples/box_demo/test_app.rb +88 -0
- data/examples/calendar_demo/app.rb +101 -0
- data/examples/calendar_demo/app.rbs +7 -0
- data/examples/calendar_demo/test_app.rb +108 -0
- data/examples/cell_demo/app.rb +108 -0
- data/examples/cell_demo/app.rbs +7 -0
- data/examples/cell_demo/test_app.rb +36 -0
- data/examples/chart_demo/app.rb +203 -0
- data/examples/chart_demo/app.rbs +7 -0
- data/examples/chart_demo/test_app.rb +102 -0
- data/examples/custom_widget/app.rb +51 -0
- data/examples/custom_widget/app.rbs +7 -0
- data/examples/custom_widget/test_app.rb +30 -0
- data/examples/flex_layout/app.rb +156 -0
- data/examples/flex_layout/app.rbs +7 -0
- data/examples/flex_layout/test_app.rb +65 -0
- data/examples/gauge_demo/app.rb +182 -0
- data/examples/gauge_demo/app.rbs +7 -0
- data/examples/gauge_demo/test_app.rb +120 -0
- data/examples/hit_test/app.rb +175 -0
- data/examples/hit_test/app.rbs +7 -0
- data/examples/hit_test/test_app.rb +102 -0
- data/examples/line_gauge_demo/app.rb +190 -0
- data/examples/line_gauge_demo/app.rbs +7 -0
- data/examples/line_gauge_demo/test_app.rb +129 -0
- data/examples/list_demo/app.rb +253 -0
- data/examples/list_demo/app.rbs +12 -0
- data/examples/list_demo/test_app.rb +237 -0
- data/examples/list_styles/app.rb +140 -0
- data/examples/list_styles/app.rbs +7 -0
- data/examples/list_styles/test_app.rb +157 -0
- data/examples/{login_form.rb → login_form/app.rb} +12 -16
- data/examples/login_form/app.rbs +7 -0
- data/examples/login_form/test_app.rb +51 -0
- data/examples/map_demo/app.rb +90 -0
- data/examples/map_demo/app.rbs +7 -0
- data/examples/map_demo/test_app.rb +149 -0
- data/examples/{mouse_events.rb → mouse_events/app.rb} +29 -27
- data/examples/mouse_events/app.rbs +7 -0
- data/examples/mouse_events/test_app.rb +53 -0
- data/examples/{popup_demo.rb → popup_demo/app.rb} +15 -17
- data/examples/popup_demo/app.rbs +7 -0
- data/examples/{test_popup_demo.rb → popup_demo/test_app.rb} +18 -26
- data/examples/quickstart_dsl/app.rb +36 -0
- data/examples/quickstart_dsl/app.rbs +7 -0
- data/examples/quickstart_dsl/test_app.rb +29 -0
- data/examples/quickstart_lifecycle/app.rb +39 -0
- data/examples/quickstart_lifecycle/app.rbs +7 -0
- data/examples/quickstart_lifecycle/test_app.rb +29 -0
- data/examples/ratatui_logo_demo/app.rb +79 -0
- data/examples/ratatui_logo_demo/app.rbs +7 -0
- data/examples/ratatui_logo_demo/test_app.rb +51 -0
- data/examples/ratatui_mascot_demo/app.rb +84 -0
- data/examples/ratatui_mascot_demo/app.rbs +7 -0
- data/examples/ratatui_mascot_demo/test_app.rb +47 -0
- data/examples/readme_usage/app.rb +29 -0
- data/examples/readme_usage/app.rbs +7 -0
- data/examples/readme_usage/test_app.rb +29 -0
- data/examples/rich_text/app.rb +141 -0
- data/examples/rich_text/app.rbs +7 -0
- data/examples/rich_text/test_app.rb +166 -0
- data/examples/scroll_text/app.rb +103 -0
- data/examples/scroll_text/app.rbs +7 -0
- data/examples/scroll_text/test_app.rb +110 -0
- data/examples/scrollbar_demo/app.rb +143 -0
- data/examples/scrollbar_demo/app.rbs +7 -0
- data/examples/scrollbar_demo/test_app.rb +77 -0
- data/examples/sparkline_demo/app.rb +240 -0
- data/examples/sparkline_demo/app.rbs +10 -0
- data/examples/sparkline_demo/test_app.rb +107 -0
- data/examples/table_flex/app.rb +65 -0
- data/examples/table_flex/app.rbs +7 -0
- data/examples/table_flex/test_app.rb +36 -0
- data/examples/table_select/app.rb +198 -0
- data/examples/table_select/app.rbs +7 -0
- data/examples/table_select/test_app.rb +180 -0
- data/examples/widget_style_colors/app.rb +104 -0
- data/examples/widget_style_colors/app.rbs +14 -0
- data/examples/widget_style_colors/test_app.rb +48 -0
- data/ext/ratatui_ruby/Cargo.lock +889 -115
- data/ext/ratatui_ruby/Cargo.toml +4 -3
- data/ext/ratatui_ruby/clippy.toml +7 -0
- data/ext/ratatui_ruby/extconf.rb +7 -0
- data/ext/ratatui_ruby/src/events.rs +218 -229
- data/ext/ratatui_ruby/src/lib.rs +38 -10
- data/ext/ratatui_ruby/src/rendering.rs +90 -10
- data/ext/ratatui_ruby/src/style.rs +281 -98
- data/ext/ratatui_ruby/src/terminal.rs +119 -25
- data/ext/ratatui_ruby/src/text.rs +171 -0
- data/ext/ratatui_ruby/src/widgets/barchart.rs +97 -24
- data/ext/ratatui_ruby/src/widgets/block.rs +31 -3
- data/ext/ratatui_ruby/src/widgets/calendar.rs +45 -44
- data/ext/ratatui_ruby/src/widgets/canvas.rs +46 -29
- data/ext/ratatui_ruby/src/widgets/chart.rs +69 -27
- data/ext/ratatui_ruby/src/widgets/clear.rs +3 -1
- data/ext/ratatui_ruby/src/widgets/gauge.rs +11 -4
- data/ext/ratatui_ruby/src/widgets/layout.rs +218 -15
- data/ext/ratatui_ruby/src/widgets/line_gauge.rs +92 -0
- data/ext/ratatui_ruby/src/widgets/list.rs +91 -11
- data/ext/ratatui_ruby/src/widgets/mod.rs +3 -0
- data/ext/ratatui_ruby/src/widgets/overlay.rs +3 -2
- data/ext/ratatui_ruby/src/widgets/paragraph.rs +35 -13
- data/ext/ratatui_ruby/src/widgets/ratatui_logo.rs +29 -0
- data/ext/ratatui_ruby/src/widgets/ratatui_mascot.rs +44 -0
- data/ext/ratatui_ruby/src/widgets/scrollbar.rs +59 -7
- data/ext/ratatui_ruby/src/widgets/sparkline.rs +70 -6
- data/ext/ratatui_ruby/src/widgets/table.rs +173 -64
- data/ext/ratatui_ruby/src/widgets/tabs.rs +105 -5
- data/lib/ratatui_ruby/cell.rb +166 -0
- data/lib/ratatui_ruby/event/focus_gained.rb +49 -0
- data/lib/ratatui_ruby/event/focus_lost.rb +50 -0
- data/lib/ratatui_ruby/event/key.rb +211 -0
- data/lib/ratatui_ruby/event/mouse.rb +124 -0
- data/lib/ratatui_ruby/event/paste.rb +71 -0
- data/lib/ratatui_ruby/event/resize.rb +80 -0
- data/lib/ratatui_ruby/event.rb +79 -0
- data/lib/ratatui_ruby/schema/bar_chart/bar.rb +45 -0
- data/lib/ratatui_ruby/schema/bar_chart/bar_group.rb +27 -0
- data/lib/ratatui_ruby/schema/bar_chart.rb +228 -19
- data/lib/ratatui_ruby/schema/block.rb +186 -14
- data/lib/ratatui_ruby/schema/calendar.rb +74 -17
- data/lib/ratatui_ruby/schema/canvas.rb +215 -48
- data/lib/ratatui_ruby/schema/center.rb +49 -11
- data/lib/ratatui_ruby/schema/chart.rb +151 -41
- data/lib/ratatui_ruby/schema/clear.rb +41 -72
- data/lib/ratatui_ruby/schema/constraint.rb +82 -22
- data/lib/ratatui_ruby/schema/cursor.rb +27 -9
- data/lib/ratatui_ruby/schema/draw.rb +53 -0
- data/lib/ratatui_ruby/schema/gauge.rb +59 -15
- data/lib/ratatui_ruby/schema/layout.rb +95 -13
- data/lib/ratatui_ruby/schema/line_gauge.rb +78 -0
- data/lib/ratatui_ruby/schema/list.rb +93 -19
- data/lib/ratatui_ruby/schema/overlay.rb +34 -8
- data/lib/ratatui_ruby/schema/paragraph.rb +87 -30
- data/lib/ratatui_ruby/schema/ratatui_logo.rb +25 -0
- data/lib/ratatui_ruby/schema/ratatui_mascot.rb +29 -0
- data/lib/ratatui_ruby/schema/rect.rb +64 -15
- data/lib/ratatui_ruby/schema/scrollbar.rb +132 -24
- data/lib/ratatui_ruby/schema/shape/label.rb +66 -0
- data/lib/ratatui_ruby/schema/sparkline.rb +122 -15
- data/lib/ratatui_ruby/schema/style.rb +49 -21
- data/lib/ratatui_ruby/schema/table.rb +119 -21
- data/lib/ratatui_ruby/schema/tabs.rb +75 -13
- data/lib/ratatui_ruby/schema/text.rb +90 -0
- data/lib/ratatui_ruby/session.rb +146 -0
- data/lib/ratatui_ruby/test_helper.rb +156 -13
- data/lib/ratatui_ruby/version.rb +1 -1
- data/lib/ratatui_ruby.rb +143 -23
- data/sig/ratatui_ruby/event.rbs +69 -0
- data/sig/ratatui_ruby/ratatui_ruby.rbs +2 -1
- data/sig/ratatui_ruby/schema/bar_chart/bar.rbs +16 -0
- data/sig/ratatui_ruby/schema/bar_chart/bar_group.rbs +13 -0
- data/sig/ratatui_ruby/schema/bar_chart.rbs +20 -2
- data/sig/ratatui_ruby/schema/block.rbs +5 -4
- data/sig/ratatui_ruby/schema/calendar.rbs +6 -2
- data/sig/ratatui_ruby/schema/canvas.rbs +52 -39
- data/sig/ratatui_ruby/schema/center.rbs +3 -3
- data/sig/ratatui_ruby/schema/chart.rbs +8 -5
- data/sig/ratatui_ruby/schema/constraint.rbs +8 -5
- data/sig/ratatui_ruby/schema/cursor.rbs +1 -1
- data/sig/ratatui_ruby/schema/draw.rbs +23 -0
- data/sig/ratatui_ruby/schema/gauge.rbs +4 -2
- data/sig/ratatui_ruby/schema/layout.rbs +11 -1
- data/sig/ratatui_ruby/schema/line_gauge.rbs +16 -0
- data/sig/ratatui_ruby/schema/list.rbs +5 -1
- data/sig/ratatui_ruby/schema/paragraph.rbs +4 -1
- data/{lib/ratatui_ruby/output.rb → sig/ratatui_ruby/schema/ratatui_logo.rbs} +3 -2
- data/sig/ratatui_ruby/{buffer.rbs → schema/ratatui_mascot.rbs} +4 -3
- data/sig/ratatui_ruby/schema/rect.rbs +2 -1
- data/sig/ratatui_ruby/schema/scrollbar.rbs +18 -2
- data/sig/ratatui_ruby/schema/sparkline.rbs +6 -2
- data/sig/ratatui_ruby/schema/table.rbs +8 -1
- data/sig/ratatui_ruby/schema/tabs.rbs +5 -1
- data/sig/ratatui_ruby/schema/text.rbs +22 -0
- data/tasks/resources/build.yml.erb +13 -11
- data/tasks/terminal_preview/app_screenshot.rb +35 -0
- data/tasks/terminal_preview/crash_report.rb +54 -0
- data/tasks/terminal_preview/example_app.rb +25 -0
- data/tasks/terminal_preview/launcher_script.rb +48 -0
- data/tasks/terminal_preview/preview_collection.rb +60 -0
- data/tasks/terminal_preview/preview_timing.rb +22 -0
- data/tasks/terminal_preview/safety_confirmation.rb +58 -0
- data/tasks/terminal_preview/saved_screenshot.rb +55 -0
- data/tasks/terminal_preview/system_appearance.rb +11 -0
- data/tasks/terminal_preview/terminal_window.rb +138 -0
- data/tasks/terminal_preview/window_id.rb +14 -0
- data/tasks/terminal_preview.rake +28 -0
- data/tasks/test.rake +1 -1
- metadata +174 -53
- data/doc/images/examples-analytics.rb.png +0 -0
- data/doc/images/examples-box_demo.rb.png +0 -0
- data/doc/images/examples-calendar_demo.rb.png +0 -0
- data/doc/images/examples-chart_demo.rb.png +0 -0
- data/doc/images/examples-custom_widget.rb.png +0 -0
- data/doc/images/examples-dashboard.rb.png +0 -0
- data/doc/images/examples-list_styles.rb.png +0 -0
- data/doc/images/examples-login_form.rb.png +0 -0
- data/doc/images/examples-map_demo.rb.png +0 -0
- data/doc/images/examples-mouse_events.rb.png +0 -0
- data/doc/images/examples-popup_demo.rb.gif +0 -0
- data/doc/images/examples-quickstart_lifecycle.rb.png +0 -0
- data/doc/images/examples-scroll_text.rb.png +0 -0
- data/doc/images/examples-scrollbar_demo.rb.png +0 -0
- data/doc/images/examples-stock_ticker.rb.png +0 -0
- data/doc/images/examples-system_monitor.rb.png +0 -0
- data/doc/images/examples-table_select.rb.png +0 -0
- data/examples/analytics.rb +0 -88
- data/examples/box_demo.rb +0 -71
- data/examples/calendar_demo.rb +0 -55
- data/examples/chart_demo.rb +0 -84
- data/examples/custom_widget.rb +0 -43
- data/examples/dashboard.rb +0 -72
- data/examples/list_styles.rb +0 -66
- data/examples/map_demo.rb +0 -58
- data/examples/quickstart_dsl.rb +0 -30
- data/examples/quickstart_lifecycle.rb +0 -40
- data/examples/readme_usage.rb +0 -21
- data/examples/scroll_text.rb +0 -74
- data/examples/scrollbar_demo.rb +0 -75
- data/examples/stock_ticker.rb +0 -93
- data/examples/system_monitor.rb +0 -94
- data/examples/table_select.rb +0 -70
- data/examples/test_analytics.rb +0 -65
- data/examples/test_box_demo.rb +0 -38
- data/examples/test_calendar_demo.rb +0 -66
- data/examples/test_dashboard.rb +0 -38
- data/examples/test_list_styles.rb +0 -61
- data/examples/test_login_form.rb +0 -63
- data/examples/test_map_demo.rb +0 -100
- data/examples/test_scroll_text.rb +0 -130
- data/examples/test_stock_ticker.rb +0 -39
- data/examples/test_system_monitor.rb +0 -40
- data/examples/test_table_select.rb +0 -37
- data/ext/ratatui_ruby/src/buffer.rs +0 -54
- data/lib/ratatui_ruby/dsl.rb +0 -64
|
@@ -4,19 +4,101 @@
|
|
|
4
4
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
5
|
|
|
6
6
|
module RatatuiRuby
|
|
7
|
-
|
|
8
|
-
#
|
|
9
|
-
# [direction] The direction of the layout (:vertical or :horizontal).
|
|
10
|
-
# [constraints] An array of Constraint objects defining the size of each section.
|
|
11
|
-
# [children] An array of widgets to render within each section.
|
|
12
|
-
class Layout < Data.define(:direction, :constraints, :children)
|
|
13
|
-
# Creates a new Layout.
|
|
7
|
+
# Divides an area into smaller chunks.
|
|
14
8
|
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
|
|
19
|
-
|
|
9
|
+
# Terminal screens vary in size. Hardcoded positions break when the window resizes. You need a way to organize space dynamically.
|
|
10
|
+
#
|
|
11
|
+
# This class manages geometry. It splits a given area into multiple sections based on a list of constraints.
|
|
12
|
+
#
|
|
13
|
+
# Use layouts to build responsive grids. Stack sections vertically for a sidebar-main structure. Partition them horizontally for headers and footers. Let the layout engine do the math.
|
|
14
|
+
#
|
|
15
|
+
# === Examples
|
|
16
|
+
#
|
|
17
|
+
# # A simple vertical split (Sidebar / Main)
|
|
18
|
+
# Layout.new(
|
|
19
|
+
# direction: :horizontal,
|
|
20
|
+
# constraints: [
|
|
21
|
+
# Constraint.length(20), # Sidebar
|
|
22
|
+
# Constraint.min(0) # Main content
|
|
23
|
+
# ]
|
|
24
|
+
# )
|
|
25
|
+
#
|
|
26
|
+
# # Flex layout (Centering a block)
|
|
27
|
+
# Layout.new(
|
|
28
|
+
# direction: :vertical,
|
|
29
|
+
# flex: :center,
|
|
30
|
+
# constraints: [Constraint.length(10)], # A 10-row block centered vertically
|
|
31
|
+
# children: [modal_block]
|
|
32
|
+
# )
|
|
33
|
+
class Layout < Data.define(:direction, :constraints, :children, :flex)
|
|
34
|
+
##
|
|
35
|
+
# :attr_reader: direction
|
|
36
|
+
# Direction of the split.
|
|
37
|
+
#
|
|
38
|
+
# Either <tt>:vertical</tt> (top to bottom) or <tt>:horizontal</tt> (left to right).
|
|
39
|
+
#
|
|
40
|
+
# layout.direction # => :vertical
|
|
41
|
+
|
|
42
|
+
##
|
|
43
|
+
# :attr_reader: constraints
|
|
44
|
+
# Array of rules defining section sizes.
|
|
45
|
+
#
|
|
46
|
+
# See RatatuiRuby::Constraint.
|
|
47
|
+
|
|
48
|
+
##
|
|
49
|
+
# :attr_reader: children
|
|
50
|
+
# Widgets to render in each section (optional).
|
|
51
|
+
#
|
|
52
|
+
# If provided, `children[i]` is rendered into the area defined by `constraints[i]`.
|
|
53
|
+
|
|
54
|
+
##
|
|
55
|
+
# :attr_reader: flex
|
|
56
|
+
# Strategy for distributing extra space.
|
|
57
|
+
#
|
|
58
|
+
# One of <tt>:legacy</tt>, <tt>:start</tt>, <tt>:center</tt>, <tt>:end</tt>, <tt>:space_between</tt>, <tt>:space_around</tt>.
|
|
59
|
+
|
|
60
|
+
# :nodoc:
|
|
61
|
+
FLEX_MODES = %i[legacy start center end space_between space_around space_evenly].freeze
|
|
62
|
+
|
|
63
|
+
# Creates a new Layout.
|
|
64
|
+
#
|
|
65
|
+
# [direction]
|
|
66
|
+
# <tt>:vertical</tt> or <tt>:horizontal</tt> (default: <tt>:vertical</tt>).
|
|
67
|
+
# [constraints]
|
|
68
|
+
# list of Constraint objects.
|
|
69
|
+
# [children]
|
|
70
|
+
# List of widgets to render (optional).
|
|
71
|
+
# [flex]
|
|
72
|
+
# Flex mode for spacing (default: <tt>:legacy</tt>).
|
|
73
|
+
def initialize(direction: :vertical, constraints: [], children: [], flex: :legacy)
|
|
74
|
+
super
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Splits an area into multiple rectangles.
|
|
78
|
+
#
|
|
79
|
+
# This is a pure calculation helper for hit testing. It computes where
|
|
80
|
+
# widgets *would* be placed without actually rendering them.
|
|
81
|
+
#
|
|
82
|
+
# rects = Layout.split(
|
|
83
|
+
# area,
|
|
84
|
+
# direction: :horizontal,
|
|
85
|
+
# constraints: [Constraint.percentage(50), Constraint.percentage(50)]
|
|
86
|
+
# )
|
|
87
|
+
# left, right = rects
|
|
88
|
+
#
|
|
89
|
+
# [area]
|
|
90
|
+
# The area to split (a Rect or any object responding to x, y, width, height).
|
|
91
|
+
# [direction]
|
|
92
|
+
# <tt>:vertical</tt> or <tt>:horizontal</tt> (default: <tt>:vertical</tt>).
|
|
93
|
+
# [constraints]
|
|
94
|
+
# Array of Constraint objects defining section sizes.
|
|
95
|
+
# [flex]
|
|
96
|
+
# Flex mode for spacing (default: <tt>:legacy</tt>).
|
|
97
|
+
#
|
|
98
|
+
# Returns an Array of Rect objects.
|
|
99
|
+
def self.split(area, direction: :vertical, constraints:, flex: :legacy)
|
|
100
|
+
raw_rects = _split(area, direction, constraints, flex)
|
|
101
|
+
raw_rects.map { |r| Rect.new(x: r[:x], y: r[:y], width: r[:width], height: r[:height]) }
|
|
102
|
+
end
|
|
20
103
|
end
|
|
21
|
-
end
|
|
22
104
|
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
|
|
6
|
+
module RatatuiRuby
|
|
7
|
+
# Displays a compact, single-line progress bar.
|
|
8
|
+
#
|
|
9
|
+
# Screen space is precious. Standard block gauges are bulky and consume multiple rows.
|
|
10
|
+
#
|
|
11
|
+
# This widget compresses the feedback. It draws a progress bar using line characters, fitting perfectly into tight layouts or lists.
|
|
12
|
+
#
|
|
13
|
+
# Use it when you need to show status without stealing focus or space.
|
|
14
|
+
#
|
|
15
|
+
# === Examples
|
|
16
|
+
#
|
|
17
|
+
# LineGauge.new(
|
|
18
|
+
# ratio: 0.4,
|
|
19
|
+
# filled_style: Style.new(fg: :blue),
|
|
20
|
+
# unfilled_symbol: "-"
|
|
21
|
+
# )
|
|
22
|
+
class LineGauge < Data.define(:ratio, :label, :style, :filled_style, :unfilled_style, :block, :filled_symbol, :unfilled_symbol)
|
|
23
|
+
##
|
|
24
|
+
# :attr_reader: ratio
|
|
25
|
+
# Progress ratio from 0.0 to 1.0.
|
|
26
|
+
|
|
27
|
+
##
|
|
28
|
+
# :attr_reader: label
|
|
29
|
+
# Optional label.
|
|
30
|
+
|
|
31
|
+
##
|
|
32
|
+
# :attr_reader: style
|
|
33
|
+
# Base style applied to the entire gauge.
|
|
34
|
+
|
|
35
|
+
##
|
|
36
|
+
# :attr_reader: filled_style
|
|
37
|
+
# Style for the completed portion.
|
|
38
|
+
|
|
39
|
+
##
|
|
40
|
+
# :attr_reader: unfilled_style
|
|
41
|
+
# Style for the remainder.
|
|
42
|
+
|
|
43
|
+
##
|
|
44
|
+
# :attr_reader: block
|
|
45
|
+
# Optional wrapping block.
|
|
46
|
+
|
|
47
|
+
##
|
|
48
|
+
# :attr_reader: filled_symbol
|
|
49
|
+
# Character for filled segments.
|
|
50
|
+
|
|
51
|
+
##
|
|
52
|
+
# :attr_reader: unfilled_symbol
|
|
53
|
+
# Character for empty segments.
|
|
54
|
+
|
|
55
|
+
# Creates a new LineGauge.
|
|
56
|
+
#
|
|
57
|
+
# [ratio] Float (0.0 - 1.0).
|
|
58
|
+
# [label] String (optional).
|
|
59
|
+
# [style] Style (optional, base style for the gauge).
|
|
60
|
+
# [filled_style] Style.
|
|
61
|
+
# [unfilled_style] Style.
|
|
62
|
+
# [block] Block.
|
|
63
|
+
# [filled_symbol] String (default: <tt>"█"</tt>).
|
|
64
|
+
# [unfilled_symbol] String (default: <tt>"░"</tt>).
|
|
65
|
+
def initialize(ratio: 0.0, label: nil, style: nil, filled_style: nil, unfilled_style: nil, block: nil, filled_symbol: "█", unfilled_symbol: "░")
|
|
66
|
+
super(
|
|
67
|
+
ratio: Float(ratio),
|
|
68
|
+
label: label,
|
|
69
|
+
style: style,
|
|
70
|
+
filled_style: filled_style,
|
|
71
|
+
unfilled_style: unfilled_style,
|
|
72
|
+
block: block,
|
|
73
|
+
filled_symbol: filled_symbol,
|
|
74
|
+
unfilled_symbol: unfilled_symbol
|
|
75
|
+
)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -4,25 +4,99 @@
|
|
|
4
4
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
5
|
|
|
6
6
|
module RatatuiRuby
|
|
7
|
-
|
|
8
|
-
#
|
|
9
|
-
# [items] An array of strings to display in the list.
|
|
10
|
-
# [selected_index] The index of the currently selected item, or nil if none.
|
|
11
|
-
# [style] The base style for all items.
|
|
12
|
-
# [highlight_style] The style for the selected item.
|
|
13
|
-
# [highlight_symbol] The symbol to display in front of the selected item.
|
|
14
|
-
# [block] An optional Block widget to wrap the list.
|
|
15
|
-
class List < Data.define(:items, :selected_index, :style, :highlight_style, :highlight_symbol, :block)
|
|
16
|
-
# Creates a new List.
|
|
7
|
+
# Displays a selectable list of items.
|
|
17
8
|
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
|
|
25
|
-
|
|
9
|
+
# Users need to choose from options. Menus, file explorers, and selectors are everywhere.
|
|
10
|
+
# Implementing navigation, highlighting, and scrolling state from scratch is tedious.
|
|
11
|
+
#
|
|
12
|
+
# This widget manages the list. It renders the items. It highlights the selection. It handles the scrolling window.
|
|
13
|
+
#
|
|
14
|
+
# Use it to build main menus, navigation sidebars, or logs.
|
|
15
|
+
#
|
|
16
|
+
# === Examples
|
|
17
|
+
#
|
|
18
|
+
# # Basic List
|
|
19
|
+
# List.new(items: ["Item 1", "Item 2"])
|
|
20
|
+
#
|
|
21
|
+
# # Navigation Menu
|
|
22
|
+
# List.new(
|
|
23
|
+
# items: ["New Game", "Load Game", "Options", "Quit"],
|
|
24
|
+
# selected_index: 0,
|
|
25
|
+
# highlight_style: Style.new(bg: :blue),
|
|
26
|
+
# highlight_symbol: ">> "
|
|
27
|
+
# )
|
|
28
|
+
class List < Data.define(:items, :selected_index, :style, :highlight_style, :highlight_symbol, :repeat_highlight_symbol, :highlight_spacing, :direction, :scroll_padding, :block)
|
|
29
|
+
##
|
|
30
|
+
# :attr_reader: items
|
|
31
|
+
# The items to display (Array of Strings).
|
|
32
|
+
|
|
33
|
+
##
|
|
34
|
+
# :attr_reader: selected_index
|
|
35
|
+
# Index of the active selection (Integer or nil).
|
|
36
|
+
|
|
37
|
+
##
|
|
38
|
+
# :attr_reader: style
|
|
39
|
+
# Base style for unselected items.
|
|
40
|
+
|
|
41
|
+
##
|
|
42
|
+
# :attr_reader: highlight_style
|
|
43
|
+
# Style for the selected item.
|
|
44
|
+
|
|
45
|
+
##
|
|
46
|
+
# :attr_reader: highlight_symbol
|
|
47
|
+
# Symbol drawn before the selected item.
|
|
48
|
+
|
|
49
|
+
##
|
|
50
|
+
# :attr_reader: repeat_highlight_symbol
|
|
51
|
+
# Whether to repeat the highlight symbol for each line of the selected item.
|
|
52
|
+
|
|
53
|
+
##
|
|
54
|
+
# :attr_reader: highlight_spacing
|
|
55
|
+
# When to show the highlight symbol column.
|
|
56
|
+
#
|
|
57
|
+
# <tt>:always</tt>, <tt>:when_selected</tt>, or <tt>:never</tt>.
|
|
58
|
+
|
|
59
|
+
##
|
|
60
|
+
# :attr_reader: direction
|
|
61
|
+
# Render direction.
|
|
62
|
+
#
|
|
63
|
+
# <tt>:top_to_bottom</tt> or <tt>:bottom_to_top</tt>.
|
|
64
|
+
|
|
65
|
+
##
|
|
66
|
+
# :attr_reader: scroll_padding
|
|
67
|
+
# Number of items to keep visible above/below the selected item when scrolling (Integer or nil).
|
|
68
|
+
|
|
69
|
+
##
|
|
70
|
+
# :attr_reader: block
|
|
71
|
+
# Optional wrapping block.
|
|
72
|
+
|
|
73
|
+
# Creates a new List.
|
|
74
|
+
#
|
|
75
|
+
# Integer parameters accept any object responding to +to_int+ or +to_i+ (duck-typed).
|
|
76
|
+
#
|
|
77
|
+
# [items] Array of Strings.
|
|
78
|
+
# [selected_index] Numeric (nullable, coerced to Integer).
|
|
79
|
+
# [style] Style object.
|
|
80
|
+
# [highlight_style] Style object.
|
|
81
|
+
# [highlight_symbol] String (default: <tt>"> "</tt>).
|
|
82
|
+
# [repeat_highlight_symbol] Boolean (default: <tt>false</tt>).
|
|
83
|
+
# [highlight_spacing] Symbol (default: <tt>:when_selected</tt>).
|
|
84
|
+
# [direction] Symbol (default: <tt>:top_to_bottom</tt>).
|
|
85
|
+
# [scroll_padding] Numeric (nullable, coerced to Integer, default: <tt>nil</tt>).
|
|
86
|
+
# [block] Block (optional).
|
|
87
|
+
def initialize(items: [], selected_index: nil, style: nil, highlight_style: nil, highlight_symbol: "> ", repeat_highlight_symbol: false, highlight_spacing: :when_selected, direction: :top_to_bottom, scroll_padding: nil, block: nil)
|
|
88
|
+
super(
|
|
89
|
+
items: items,
|
|
90
|
+
selected_index: selected_index.nil? ? nil : Integer(selected_index),
|
|
91
|
+
style: style,
|
|
92
|
+
highlight_style: highlight_style,
|
|
93
|
+
highlight_symbol: highlight_symbol,
|
|
94
|
+
repeat_highlight_symbol: repeat_highlight_symbol,
|
|
95
|
+
highlight_spacing: highlight_spacing,
|
|
96
|
+
direction: direction,
|
|
97
|
+
scroll_padding: scroll_padding.nil? ? nil : Integer(scroll_padding),
|
|
98
|
+
block: block
|
|
99
|
+
)
|
|
100
|
+
end
|
|
26
101
|
end
|
|
27
|
-
end
|
|
28
102
|
end
|
|
@@ -4,12 +4,38 @@
|
|
|
4
4
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
5
|
|
|
6
6
|
module RatatuiRuby
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
|
|
7
|
+
# Stacks widgets on top of each other.
|
|
8
|
+
#
|
|
9
|
+
# Terminal interfaces are 2D grids, but complex UIs require depth. You need to float modals over text,
|
|
10
|
+
# or place a status bar on top of a map.
|
|
11
|
+
#
|
|
12
|
+
# This widget manages the Z-axis. It renders a list of widgets sequentially into the same area.
|
|
13
|
+
# Later widgets draw over earlier ones (Painter's Algorithm).
|
|
14
|
+
#
|
|
15
|
+
# Use overlays to compose complex scenes. Combine backgrounds, main content, and floating elements.
|
|
16
|
+
#
|
|
17
|
+
# === Examples
|
|
18
|
+
#
|
|
19
|
+
# Overlay.new(
|
|
20
|
+
# layers: [
|
|
21
|
+
# BackgroundMap.new,
|
|
22
|
+
# StatusBar.new, # Draws over map
|
|
23
|
+
# ModalDialog.new # Draws over everything
|
|
24
|
+
# ]
|
|
25
|
+
# )
|
|
26
|
+
class Overlay < Data.define(:layers)
|
|
27
|
+
##
|
|
28
|
+
# :attr_reader: layers
|
|
29
|
+
# The stack of widgets to render.
|
|
30
|
+
#
|
|
31
|
+
# Rendered from index 0 to N. Index N is the top-most layer.
|
|
32
|
+
|
|
33
|
+
# Creates a new Overlay.
|
|
34
|
+
#
|
|
35
|
+
# [layers]
|
|
36
|
+
# Array of widgets.
|
|
37
|
+
def initialize(layers: [])
|
|
38
|
+
super
|
|
39
|
+
end
|
|
40
|
+
end
|
|
15
41
|
end
|
|
@@ -4,37 +4,94 @@
|
|
|
4
4
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
5
|
|
|
6
6
|
module RatatuiRuby
|
|
7
|
-
|
|
8
|
-
#
|
|
9
|
-
# [text] the text to display.
|
|
10
|
-
# [style] the style to apply (Style object).
|
|
11
|
-
# [block] an optional Block widget to wrap the paragraph.
|
|
12
|
-
# [scroll] scroll offset as (y, x) array matching ratatui convention.
|
|
13
|
-
class Paragraph < Data.define(:text, :style, :block, :wrap, :align, :scroll)
|
|
14
|
-
# Creates a new Paragraph.
|
|
7
|
+
# Displays a block of text.
|
|
15
8
|
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
9
|
+
# Raw strings are insufficient for UIs. They overflow constraints. They don't respect alignment (left, center, right).
|
|
10
|
+
#
|
|
11
|
+
# This widget creates a smart text container. It wraps content to fit the area. It aligns text as requested. It supports scrolling.
|
|
12
|
+
#
|
|
13
|
+
# Use it for everything from simple labels to complex, multi-paragraph documents.
|
|
14
|
+
#
|
|
15
|
+
# === Examples
|
|
16
|
+
#
|
|
17
|
+
# # Basic Text
|
|
18
|
+
# Paragraph.new(text: "Hello, World!")
|
|
19
|
+
#
|
|
20
|
+
# # Styled container with wrapping
|
|
21
|
+
# Paragraph.new(
|
|
22
|
+
# text: "This is a long line that will wrap automatically.",
|
|
23
|
+
# style: Style.new(fg: :green),
|
|
24
|
+
# wrap: true,
|
|
25
|
+
# block: Block.new(title: "Output", borders: [:all])
|
|
26
|
+
# )
|
|
27
|
+
#
|
|
28
|
+
# # Scrolling mechanism
|
|
29
|
+
# Paragraph.new(text: large_text, scroll: [scroll_y, 0])
|
|
30
|
+
class Paragraph < Data.define(:text, :style, :block, :wrap, :alignment, :scroll)
|
|
31
|
+
##
|
|
32
|
+
# :attr_reader: text
|
|
33
|
+
# The content to display.
|
|
34
|
+
|
|
35
|
+
##
|
|
36
|
+
# :attr_reader: style
|
|
37
|
+
# Base style for the text.
|
|
38
|
+
|
|
39
|
+
##
|
|
40
|
+
# :attr_reader: block
|
|
41
|
+
# Optional wrapping block.
|
|
42
|
+
|
|
43
|
+
##
|
|
44
|
+
# :attr_reader: wrap
|
|
45
|
+
# Whether to wrap text at the edge of the container (Boolean).
|
|
46
|
+
|
|
47
|
+
##
|
|
48
|
+
# :attr_reader: alignment
|
|
49
|
+
# Text alignment.
|
|
50
|
+
#
|
|
51
|
+
# <tt>:left</tt>, <tt>:center</tt>, or <tt>:right</tt>.
|
|
52
|
+
|
|
53
|
+
##
|
|
54
|
+
# :attr_reader: scroll
|
|
55
|
+
# Scroll offset [y, x].
|
|
56
|
+
|
|
57
|
+
# Creates a new Paragraph.
|
|
58
|
+
#
|
|
59
|
+
# [text] String or Text::Line array.
|
|
60
|
+
# [style] Style object.
|
|
61
|
+
# [block] Block object.
|
|
62
|
+
# [wrap] Boolean (default: false).
|
|
63
|
+
# [alignment] Symbol (default: <tt>:left</tt>).
|
|
64
|
+
# [scroll] Array of [y, x] integers (duck-typed via +to_int+).
|
|
65
|
+
def initialize(text:, style: Style.default, block: nil, wrap: false, alignment: :left, scroll: [0, 0])
|
|
66
|
+
super(
|
|
67
|
+
text: text,
|
|
68
|
+
style: style,
|
|
69
|
+
block: block,
|
|
70
|
+
wrap: wrap,
|
|
71
|
+
alignment: alignment,
|
|
72
|
+
scroll: [Integer(scroll[0]), Integer(scroll[1])]
|
|
73
|
+
)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Legacy constructor support.
|
|
77
|
+
def self.new(text:, style: nil, fg: nil, bg: nil, block: nil, wrap: false, alignment: :left, scroll: [0, 0])
|
|
78
|
+
style ||= Style.new(fg:, bg:)
|
|
79
|
+
coerced_scroll = [Integer(scroll[0]), Integer(scroll[1])]
|
|
80
|
+
super(text:, style:, block:, wrap:, alignment:, scroll: coerced_scroll)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Returns the number of lines the paragraph would take up if rendered with the given width.
|
|
84
|
+
#
|
|
85
|
+
# [width] Integer (max width).
|
|
86
|
+
def line_count(width)
|
|
87
|
+
RatatuiRuby.warn_experimental_feature("Paragraph#line_count")
|
|
88
|
+
RatatuiRuby._paragraph_line_count(self, Integer(width))
|
|
89
|
+
end
|
|
25
90
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
# [block] the block to wrap the paragraph.
|
|
32
|
-
# [wrap] whether to wrap text at width.
|
|
33
|
-
# [align] alignment (:left, :center, :right).
|
|
34
|
-
# [scroll] scroll offset as (y, x) array (default: [0, 0]).
|
|
35
|
-
def self.new(text:, style: nil, fg: nil, bg: nil, block: nil, wrap: false, align: :left, scroll: [0, 0])
|
|
36
|
-
style ||= Style.new(fg:, bg:)
|
|
37
|
-
super(text:, style:, block:, wrap:, align:, scroll:)
|
|
91
|
+
# Returns the minimum width needed to not wrap any text.
|
|
92
|
+
def line_width
|
|
93
|
+
RatatuiRuby.warn_experimental_feature("Paragraph#line_width")
|
|
94
|
+
RatatuiRuby._paragraph_line_width(self)
|
|
95
|
+
end
|
|
38
96
|
end
|
|
39
|
-
end
|
|
40
97
|
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
|
|
6
|
+
module RatatuiRuby
|
|
7
|
+
# Displays the Ratatui logo.
|
|
8
|
+
#
|
|
9
|
+
# A simple widget that renders the Ratatui logo. Useful for demos and about screens.
|
|
10
|
+
#
|
|
11
|
+
# === Examples
|
|
12
|
+
#
|
|
13
|
+
# RatatuiLogo.new
|
|
14
|
+
#
|
|
15
|
+
class RatatuiLogo < Data.define
|
|
16
|
+
##
|
|
17
|
+
# :method: new
|
|
18
|
+
# :call-seq: new -> RatatuiLogo
|
|
19
|
+
#
|
|
20
|
+
# Creates a new RatatuiLogo.
|
|
21
|
+
def initialize
|
|
22
|
+
super
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
|
|
6
|
+
module RatatuiRuby
|
|
7
|
+
# Displays the Ratatui mascot.
|
|
8
|
+
#
|
|
9
|
+
# A widget that renders the Ratatui mascot (a rat).
|
|
10
|
+
#
|
|
11
|
+
# === Examples
|
|
12
|
+
#
|
|
13
|
+
# RatatuiMascot.new(
|
|
14
|
+
# block: Block.new(title: "Mascot")
|
|
15
|
+
# )
|
|
16
|
+
#
|
|
17
|
+
class RatatuiMascot < Data.define(:block)
|
|
18
|
+
##
|
|
19
|
+
# :method: new
|
|
20
|
+
# :call-seq: new(block: nil) -> RatatuiMascot
|
|
21
|
+
#
|
|
22
|
+
# Creates a new RatatuiMascot.
|
|
23
|
+
#
|
|
24
|
+
# @param block [Block, nil] A block to wrap the widget in.
|
|
25
|
+
def initialize(block: nil)
|
|
26
|
+
super
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -4,21 +4,70 @@
|
|
|
4
4
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
5
|
|
|
6
6
|
module RatatuiRuby
|
|
7
|
-
|
|
8
|
-
#
|
|
9
|
-
# [x] The x-coordinate of the top-left corner.
|
|
10
|
-
# [y] The y-coordinate of the top-left corner.
|
|
11
|
-
# [width] The width of the rectangle.
|
|
12
|
-
# [height] The height of the rectangle.
|
|
13
|
-
class Rect < Data.define(:x, :y, :width, :height)
|
|
14
|
-
# Creates a new Rect.
|
|
7
|
+
# Defines a rectangular area in the terminal grid.
|
|
15
8
|
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
|
|
21
|
-
|
|
9
|
+
# Geometry management involves passing groups of four integers (`x, y, width, height`) repeatedly.
|
|
10
|
+
# This is verbose and prone to parameter mismatch errors.
|
|
11
|
+
#
|
|
12
|
+
# This class encapsulates the geometry. It provides a standard primitive for passing area definitions
|
|
13
|
+
# between layout engines and rendering functions.
|
|
14
|
+
#
|
|
15
|
+
# Use it when manual positioning is required or when querying layout results.
|
|
16
|
+
#
|
|
17
|
+
# === Examples
|
|
18
|
+
#
|
|
19
|
+
# area = Rect.new(x: 0, y: 0, width: 80, height: 24)
|
|
20
|
+
# puts area.width # => 80
|
|
21
|
+
class Rect < Data.define(:x, :y, :width, :height)
|
|
22
|
+
##
|
|
23
|
+
# :attr_reader: x
|
|
24
|
+
# X coordinate (column) of the top-left corner (Integer, coerced via +to_int+ or +to_i+).
|
|
25
|
+
|
|
26
|
+
##
|
|
27
|
+
# :attr_reader: y
|
|
28
|
+
# Y coordinate (row) of the top-left corner (Integer, coerced via +to_int+ or +to_i+).
|
|
29
|
+
|
|
30
|
+
##
|
|
31
|
+
# :attr_reader: width
|
|
32
|
+
# Width in characters (Integer, coerced via +to_int+ or +to_i+).
|
|
33
|
+
|
|
34
|
+
##
|
|
35
|
+
# :attr_reader: height
|
|
36
|
+
# Height in characters (Integer, coerced via +to_int+ or +to_i+).
|
|
37
|
+
|
|
38
|
+
# Creates a new Rect.
|
|
39
|
+
#
|
|
40
|
+
# All parameters accept any object responding to +to_int+ or +to_i+ (duck-typed).
|
|
41
|
+
#
|
|
42
|
+
# [x] Column index (Numeric).
|
|
43
|
+
# [y] Row index (Numeric).
|
|
44
|
+
# [width] Width in columns (Numeric).
|
|
45
|
+
# [height] Height in rows (Numeric).
|
|
46
|
+
def initialize(x: 0, y: 0, width: 0, height: 0)
|
|
47
|
+
super(
|
|
48
|
+
x: Integer(x),
|
|
49
|
+
y: Integer(y),
|
|
50
|
+
width: Integer(width),
|
|
51
|
+
height: Integer(height)
|
|
52
|
+
)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Tests whether a point is inside this rectangle.
|
|
56
|
+
#
|
|
57
|
+
# Essential for hit testing mouse clicks against layout regions.
|
|
58
|
+
#
|
|
59
|
+
# area = Rect.new(x: 10, y: 5, width: 20, height: 10)
|
|
60
|
+
# area.contains?(15, 8) # => true
|
|
61
|
+
# area.contains?(5, 8) # => false
|
|
62
|
+
#
|
|
63
|
+
# [px]
|
|
64
|
+
# X coordinate to test (column).
|
|
65
|
+
# [py]
|
|
66
|
+
# Y coordinate to test (row).
|
|
67
|
+
#
|
|
68
|
+
# Returns true if the point (px, py) is within the rectangle bounds.
|
|
69
|
+
def contains?(px, py)
|
|
70
|
+
px >= x && px < x + width && py >= y && py < y + height
|
|
71
|
+
end
|
|
22
72
|
end
|
|
23
|
-
end
|
|
24
73
|
end
|