ratatui_ruby 0.5.0 → 0.6.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 +1 -1
- data/.builds/ruby-3.3.yml +1 -1
- data/.builds/ruby-3.4.yml +1 -1
- data/.builds/ruby-4.0.0.yml +1 -1
- data/AGENTS.md +6 -0
- data/CHANGELOG.md +44 -7
- data/README.md +11 -4
- data/REUSE.toml +2 -7
- data/doc/application_architecture.md +84 -10
- data/doc/application_testing.md +75 -29
- data/doc/contributors/design/ruby_frontend.md +39 -3
- data/doc/contributors/design/rust_backend.md +1 -0
- data/doc/contributors/developing_examples.md +129 -44
- data/doc/contributors/examples_audit/p1_high.md +21 -0
- data/doc/contributors/examples_audit/p2_moderate.md +81 -0
- data/doc/contributors/examples_audit.md +41 -0
- data/doc/event_handling.md +11 -3
- data/doc/images/app_all_events.png +0 -0
- data/doc/images/app_color_picker.png +0 -0
- data/doc/images/app_login_form.png +0 -0
- data/doc/images/app_stateful_interaction.png +0 -0
- data/doc/images/verify_quickstart_dsl.png +0 -0
- data/doc/images/verify_quickstart_layout.png +0 -0
- data/doc/images/verify_quickstart_lifecycle.png +0 -0
- data/doc/images/verify_readme_usage.png +0 -0
- data/doc/images/widget_barchart_demo.png +0 -0
- data/doc/images/widget_block_demo.png +0 -0
- data/doc/images/widget_canvas_demo.png +0 -0
- data/doc/images/widget_cell_demo.png +0 -0
- data/doc/images/widget_center_demo.png +0 -0
- data/doc/images/widget_chart_demo.png +0 -0
- data/doc/images/widget_list_demo.png +0 -0
- data/doc/images/widget_overlay_demo.png +0 -0
- data/doc/images/widget_render.png +0 -0
- data/doc/images/widget_rich_text.png +0 -0
- data/doc/images/widget_scroll_text.png +0 -0
- data/doc/images/widget_sparkline_demo.png +0 -0
- data/doc/images/widget_table_demo.png +0 -0
- data/doc/images/widget_tabs_demo.png +0 -0
- data/doc/images/widget_text_width.png +0 -0
- data/doc/quickstart.md +69 -76
- data/doc/terminal_limitations.md +92 -0
- data/examples/app_all_events/README.md +45 -27
- data/examples/app_all_events/app.rb +38 -35
- data/examples/app_all_events/model/app_model.rb +157 -0
- data/examples/app_all_events/model/event_entry.rb +17 -0
- data/examples/app_all_events/model/msg.rb +37 -0
- data/examples/app_all_events/update.rb +73 -0
- data/examples/app_all_events/view/app_view.rb +8 -8
- data/examples/app_all_events/view/controls_view.rb +8 -6
- data/examples/app_all_events/view/counts_view.rb +12 -8
- data/examples/app_all_events/view/live_view.rb +8 -7
- data/examples/app_all_events/view/log_view.rb +10 -15
- data/examples/app_color_picker/README.md +84 -44
- data/examples/app_color_picker/app.rb +24 -62
- data/examples/app_color_picker/controls.rb +90 -0
- data/examples/app_color_picker/copy_dialog.rb +45 -49
- data/examples/app_color_picker/export_pane.rb +126 -0
- data/examples/app_color_picker/input.rb +99 -67
- data/examples/app_color_picker/main_container.rb +178 -0
- data/examples/app_color_picker/palette.rb +55 -26
- data/examples/app_login_form/README.md +47 -0
- data/examples/app_login_form/app.rb +2 -3
- data/examples/app_stateful_interaction/README.md +31 -0
- data/examples/app_stateful_interaction/app.rb +272 -0
- data/examples/timeout_demo.rb +43 -0
- data/examples/verify_quickstart_dsl/README.md +48 -0
- data/examples/verify_quickstart_dsl/app.rb +2 -0
- data/examples/verify_quickstart_layout/README.md +71 -0
- data/examples/verify_quickstart_layout/app.rb +2 -0
- data/examples/verify_quickstart_lifecycle/README.md +56 -0
- data/examples/verify_quickstart_lifecycle/app.rb +8 -2
- data/examples/verify_readme_usage/README.md +43 -0
- data/examples/verify_readme_usage/app.rb +8 -2
- data/examples/widget_barchart_demo/README.md +49 -0
- data/examples/widget_barchart_demo/app.rb +5 -5
- data/examples/widget_block_demo/README.md +34 -0
- data/examples/widget_block_demo/app.rb +256 -0
- data/examples/widget_box_demo/README.md +45 -0
- data/examples/widget_calendar_demo/README.md +39 -0
- data/examples/widget_canvas_demo/README.md +27 -0
- data/examples/widget_canvas_demo/app.rb +123 -0
- data/examples/widget_cell_demo/README.md +36 -0
- data/examples/widget_cell_demo/app.rb +31 -24
- data/examples/widget_center_demo/README.md +29 -0
- data/examples/widget_center_demo/app.rb +116 -0
- data/examples/widget_chart_demo/README.md +41 -0
- data/examples/widget_chart_demo/app.rb +7 -2
- data/examples/widget_gauge_demo/README.md +41 -0
- data/examples/widget_layout_split/README.md +44 -0
- data/examples/widget_line_gauge_demo/README.md +41 -0
- data/examples/widget_list_demo/README.md +49 -0
- data/examples/widget_list_demo/app.rb +91 -107
- data/examples/widget_map_demo/README.md +39 -0
- data/examples/{app_map_demo → widget_map_demo}/app.rb +2 -2
- data/examples/widget_overlay_demo/app.rb +248 -0
- data/examples/widget_popup_demo/README.md +36 -0
- data/examples/widget_ratatui_logo_demo/README.md +34 -0
- data/examples/widget_ratatui_mascot_demo/README.md +34 -0
- data/examples/widget_rect/README.md +38 -0
- data/examples/widget_render/README.md +37 -0
- data/examples/widget_rich_text/README.md +35 -0
- data/examples/widget_rich_text/app.rb +62 -33
- data/examples/widget_scroll_text/README.md +37 -0
- data/examples/widget_scroll_text/app.rb +0 -1
- data/examples/widget_scrollbar_demo/README.md +37 -0
- data/examples/widget_sparkline_demo/README.md +42 -0
- data/examples/widget_sparkline_demo/app.rb +4 -3
- data/examples/widget_style_colors/README.md +34 -0
- data/examples/widget_table_demo/README.md +48 -0
- data/examples/{app_table_select → widget_table_demo}/app.rb +46 -8
- data/examples/widget_tabs_demo/README.md +41 -0
- data/examples/widget_tabs_demo/app.rb +15 -1
- data/examples/widget_text_width/README.md +35 -0
- data/examples/widget_text_width/app.rb +106 -0
- data/exe/.gitkeep +0 -0
- data/ext/ratatui_ruby/Cargo.lock +11 -4
- data/ext/ratatui_ruby/Cargo.toml +2 -1
- data/ext/ratatui_ruby/src/events.rs +238 -26
- data/ext/ratatui_ruby/src/frame.rs +113 -1
- data/ext/ratatui_ruby/src/lib.rs +34 -4
- data/ext/ratatui_ruby/src/string_width.rs +101 -0
- data/ext/ratatui_ruby/src/terminal.rs +39 -15
- data/ext/ratatui_ruby/src/text.rs +1 -1
- data/ext/ratatui_ruby/src/widgets/barchart.rs +24 -6
- data/ext/ratatui_ruby/src/widgets/gauge.rs +9 -2
- data/ext/ratatui_ruby/src/widgets/line_gauge.rs +9 -2
- data/ext/ratatui_ruby/src/widgets/list.rs +179 -3
- data/ext/ratatui_ruby/src/widgets/list_state.rs +137 -0
- data/ext/ratatui_ruby/src/widgets/mod.rs +3 -0
- data/ext/ratatui_ruby/src/widgets/scrollbar.rs +93 -1
- data/ext/ratatui_ruby/src/widgets/scrollbar_state.rs +169 -0
- data/ext/ratatui_ruby/src/widgets/table.rs +113 -1
- data/ext/ratatui_ruby/src/widgets/table_state.rs +121 -0
- data/lib/ratatui_ruby/cell.rb +4 -4
- data/lib/ratatui_ruby/event/key/character.rb +35 -0
- data/lib/ratatui_ruby/event/key/media.rb +44 -0
- data/lib/ratatui_ruby/event/key/modifier.rb +95 -0
- data/lib/ratatui_ruby/event/key/navigation.rb +55 -0
- data/lib/ratatui_ruby/event/key/system.rb +45 -0
- data/lib/ratatui_ruby/event/key.rb +111 -51
- data/lib/ratatui_ruby/event/mouse.rb +3 -3
- data/lib/ratatui_ruby/event/paste.rb +1 -1
- data/lib/ratatui_ruby/frame.rb +96 -0
- data/lib/ratatui_ruby/list_state.rb +88 -0
- data/lib/ratatui_ruby/schema/bar_chart/bar.rb +2 -2
- data/lib/ratatui_ruby/schema/cursor.rb +5 -0
- data/lib/ratatui_ruby/schema/gauge.rb +3 -1
- data/lib/ratatui_ruby/schema/line_gauge.rb +2 -2
- data/lib/ratatui_ruby/schema/list.rb +25 -4
- data/lib/ratatui_ruby/schema/list_item.rb +41 -0
- data/lib/ratatui_ruby/schema/rect.rb +43 -0
- data/lib/ratatui_ruby/schema/style.rb +24 -4
- data/lib/ratatui_ruby/schema/table.rb +21 -3
- data/lib/ratatui_ruby/schema/text.rb +69 -1
- data/lib/ratatui_ruby/scrollbar_state.rb +112 -0
- data/lib/ratatui_ruby/session/autodoc.rb +65 -0
- data/lib/ratatui_ruby/session.rb +22 -7
- data/lib/ratatui_ruby/table_state.rb +90 -0
- data/lib/ratatui_ruby/test_helper/event_injection.rb +169 -0
- data/lib/ratatui_ruby/test_helper/snapshot.rb +390 -0
- data/lib/ratatui_ruby/test_helper/style_assertions.rb +351 -0
- data/lib/ratatui_ruby/test_helper/terminal.rb +127 -0
- data/lib/ratatui_ruby/test_helper/test_doubles.rb +68 -0
- data/lib/ratatui_ruby/test_helper.rb +65 -358
- data/lib/ratatui_ruby/version.rb +1 -1
- data/lib/ratatui_ruby.rb +42 -19
- data/sig/examples/app_stateful_interaction/app.rbs +33 -0
- data/sig/examples/widget_block_demo/app.rbs +32 -0
- data/sig/examples/{app_map_demo → widget_map_demo}/app.rbs +2 -2
- data/sig/examples/{app_table_select → widget_table_demo}/app.rbs +2 -2
- data/sig/examples/{widget_table_flex → widget_text_width}/app.rbs +2 -3
- data/sig/ratatui_ruby/event.rbs +11 -1
- data/sig/ratatui_ruby/frame.rbs +2 -0
- data/sig/ratatui_ruby/list_state.rbs +13 -0
- data/sig/ratatui_ruby/ratatui_ruby.rbs +2 -2
- data/sig/ratatui_ruby/schema/bar_chart/bar.rbs +3 -3
- data/sig/ratatui_ruby/schema/gauge.rbs +2 -2
- data/sig/ratatui_ruby/schema/line_gauge.rbs +2 -2
- data/sig/ratatui_ruby/schema/list.rbs +4 -2
- data/sig/ratatui_ruby/schema/list_item.rbs +10 -0
- data/sig/ratatui_ruby/schema/rect.rbs +3 -0
- data/sig/ratatui_ruby/schema/style.rbs +3 -3
- data/sig/ratatui_ruby/schema/table.rbs +3 -1
- data/sig/ratatui_ruby/schema/text.rbs +8 -6
- data/sig/ratatui_ruby/scrollbar_state.rbs +18 -0
- data/sig/ratatui_ruby/session.rbs +13 -0
- data/sig/ratatui_ruby/table_state.rbs +15 -0
- data/sig/ratatui_ruby/test_helper/event_injection.rbs +16 -0
- data/sig/ratatui_ruby/test_helper/snapshot.rbs +12 -0
- data/sig/ratatui_ruby/test_helper/style_assertions.rbs +64 -0
- data/sig/ratatui_ruby/test_helper/terminal.rbs +14 -0
- data/sig/ratatui_ruby/test_helper/test_doubles.rbs +22 -0
- data/sig/ratatui_ruby/test_helper.rbs +5 -4
- data/tasks/autodoc/examples.rb +79 -0
- data/tasks/autodoc/inventory.rb +9 -7
- data/tasks/autodoc.rake +11 -5
- data/tasks/bump/changelog.rb +3 -3
- data/tasks/bump/links.rb +67 -0
- data/tasks/sourcehut.rake +61 -21
- data/tasks/terminal_preview/app_screenshot.rb +13 -3
- data/tasks/terminal_preview/saved_screenshot.rb +4 -3
- metadata +111 -37
- data/doc/images/app_table_select.png +0 -0
- data/doc/images/widget_block_padding.png +0 -0
- data/doc/images/widget_block_titles.png +0 -0
- data/doc/images/widget_list_styles.png +0 -0
- data/examples/app_all_events/model/events.rb +0 -180
- data/examples/app_all_events/model/highlight.rb +0 -57
- data/examples/app_all_events/test/snapshots/after_focus_lost.txt +0 -24
- data/examples/app_all_events/test/snapshots/after_focus_regained.txt +0 -24
- data/examples/app_all_events/test/snapshots/after_horizontal_resize.txt +0 -24
- data/examples/app_all_events/test/snapshots/after_key_a.txt +0 -24
- data/examples/app_all_events/test/snapshots/after_key_ctrl_x.txt +0 -24
- data/examples/app_all_events/test/snapshots/after_mouse_click.txt +0 -24
- data/examples/app_all_events/test/snapshots/after_mouse_drag.txt +0 -24
- data/examples/app_all_events/test/snapshots/after_multiple_events.txt +0 -24
- data/examples/app_all_events/test/snapshots/after_paste.txt +0 -24
- data/examples/app_all_events/test/snapshots/after_resize.txt +0 -24
- data/examples/app_all_events/test/snapshots/after_right_click.txt +0 -24
- data/examples/app_all_events/test/snapshots/after_vertical_resize.txt +0 -24
- data/examples/app_all_events/test/snapshots/initial_state.txt +0 -24
- data/examples/app_all_events/view_state.rb +0 -42
- data/examples/app_color_picker/scene.rb +0 -201
- data/examples/widget_block_padding/app.rb +0 -67
- data/examples/widget_block_titles/app.rb +0 -69
- data/examples/widget_list_styles/app.rb +0 -141
- data/examples/widget_table_flex/app.rb +0 -95
- data/sig/examples/widget_block_padding/app.rbs +0 -11
- data/sig/examples/widget_block_titles/app.rbs +0 -11
- data/sig/examples/widget_list_styles/app.rbs +0 -11
- data/tasks/bump/comparison_links.rb +0 -41
- /data/doc/images/{app_map_demo.png → widget_map_demo.png} +0 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
3
|
+
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
+
-->
|
|
5
|
+
# Block Widget Demo
|
|
6
|
+
|
|
7
|
+
This example demonstrates the versatile `Block` widget, which provides the visual container, borders, and titles for almost every other widget in `ratatui_ruby`.
|
|
8
|
+
|
|
9
|
+
## Key Concepts
|
|
10
|
+
|
|
11
|
+
- **Borders:** Choose which sides to show and apply different border types (plain, rounded, double, thick, etc.).
|
|
12
|
+
- **Titles:** Add a main title with alignment or multiple titles at the top and bottom with independent styles and positions.
|
|
13
|
+
- **Padding:** Define inner spacing using uniform or directional (L/R/T/B) values.
|
|
14
|
+
- **Styling:** Individually style the block's content area, its borders, and its titles.
|
|
15
|
+
- **Custom Border Sets:** Create entirely custom border appearances by defining each character in the border set.
|
|
16
|
+
|
|
17
|
+
## Hotkeys
|
|
18
|
+
|
|
19
|
+
- `t`: Cycle **Title** (None, Main Title)
|
|
20
|
+
- `a`: Cycle **Title Alignment** (Left, Center, Right)
|
|
21
|
+
- `s`: Cycle **Title Style** (None, Cyan Bold, Yellow Italic)
|
|
22
|
+
- `e`: Cycle **Additional Titles** (None, Top+Bottom, Complex)
|
|
23
|
+
- `b`: Cycle **Borders** (All, Top/Bottom, Left/Right, None)
|
|
24
|
+
- `y`: Cycle **Border Type** (Rounded, Plain, Double, Thick, Quadrant, Custom)
|
|
25
|
+
- `c`: Cycle **Border Style** (Magenta Bold, None, Green, Blue on White)
|
|
26
|
+
- `p`: Cycle **Padding** (Uniform, None, Directional, Narrow)
|
|
27
|
+
- `f`: Cycle **Base Style** (Dark Gray, None, White on Black)
|
|
28
|
+
- `q`: **Quit**
|
|
29
|
+
|
|
30
|
+
## Usage
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
ruby examples/widget_block_demo/app.rb
|
|
34
|
+
```
|
|
@@ -0,0 +1,256 @@
|
|
|
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
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
|
|
7
|
+
require "ratatui_ruby"
|
|
8
|
+
|
|
9
|
+
# Demonstrates the Block widget with interactive attribute cycling.
|
|
10
|
+
#
|
|
11
|
+
# Blocks are the foundation of terminal layouts, providing structure, borders, and titles.
|
|
12
|
+
# This demo showcases all available parameters, including advanced title positioning,
|
|
13
|
+
# directional padding, and custom border sets.
|
|
14
|
+
#
|
|
15
|
+
# === Examples
|
|
16
|
+
#
|
|
17
|
+
# Run the demo from the terminal:
|
|
18
|
+
#
|
|
19
|
+
# ruby examples/widget_block_demo/app.rb
|
|
20
|
+
#
|
|
21
|
+
# rdoc-image:/doc/images/widget_block_demo.png
|
|
22
|
+
class WidgetBlockDemo
|
|
23
|
+
def initialize
|
|
24
|
+
@title_configs = [
|
|
25
|
+
{ name: "None", title: nil },
|
|
26
|
+
{ name: "Main Title", title: "Main Title" },
|
|
27
|
+
]
|
|
28
|
+
@title_index = 1
|
|
29
|
+
|
|
30
|
+
@titles_configs = [
|
|
31
|
+
{ name: "None", titles: [] },
|
|
32
|
+
{
|
|
33
|
+
name: "Top + Bottom",
|
|
34
|
+
titles: [
|
|
35
|
+
{ content: "Top Right", alignment: :right, position: :top },
|
|
36
|
+
{ content: "Bottom Left", alignment: :left, position: :bottom },
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: "Complex",
|
|
41
|
+
titles: [
|
|
42
|
+
{ content: "★ Left ★", alignment: :left, position: :top },
|
|
43
|
+
{ content: "Center", alignment: :center, position: :top },
|
|
44
|
+
{ content: "Right", alignment: :right, position: :top },
|
|
45
|
+
{ content: "Bottom Center", alignment: :center, position: :bottom },
|
|
46
|
+
],
|
|
47
|
+
},
|
|
48
|
+
]
|
|
49
|
+
@titles_index = 1
|
|
50
|
+
|
|
51
|
+
@alignment_configs = [
|
|
52
|
+
{ name: "Left", alignment: :left },
|
|
53
|
+
{ name: "Center", alignment: :center },
|
|
54
|
+
{ name: "Right", alignment: :right },
|
|
55
|
+
]
|
|
56
|
+
@alignment_index = 1 # Center
|
|
57
|
+
|
|
58
|
+
@border_configs = [
|
|
59
|
+
{ name: "All", borders: [:all] },
|
|
60
|
+
{ name: "Top/Bottom", borders: [:top, :bottom] },
|
|
61
|
+
{ name: "Left/Right", borders: [:left, :right] },
|
|
62
|
+
{ name: "None", borders: [] },
|
|
63
|
+
]
|
|
64
|
+
@border_index = 0
|
|
65
|
+
|
|
66
|
+
@border_type_configs = [
|
|
67
|
+
{ name: "Rounded", type: :rounded },
|
|
68
|
+
{ name: "Plain", type: :plain },
|
|
69
|
+
{ name: "Double", type: :double },
|
|
70
|
+
{ name: "Thick", type: :thick },
|
|
71
|
+
{ name: "Quadrant Inside", type: :quadrant_inside },
|
|
72
|
+
{ name: "Quadrant Outside", type: :quadrant_outside },
|
|
73
|
+
{
|
|
74
|
+
name: "Custom Set",
|
|
75
|
+
type: nil,
|
|
76
|
+
set: {
|
|
77
|
+
top_left: "1",
|
|
78
|
+
top_right: "2",
|
|
79
|
+
bottom_left: "3",
|
|
80
|
+
bottom_right: "4",
|
|
81
|
+
vertical_left: "5",
|
|
82
|
+
vertical_right: "6",
|
|
83
|
+
horizontal_top: "7",
|
|
84
|
+
horizontal_bottom: "8",
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
]
|
|
88
|
+
@border_type_index = 0
|
|
89
|
+
|
|
90
|
+
@padding_configs = [
|
|
91
|
+
{ name: "Uniform (2)", padding: 2 },
|
|
92
|
+
{ name: "None (0)", padding: 0 },
|
|
93
|
+
{ name: "Directional (L:4, T:2)", padding: [4, 0, 2, 0] },
|
|
94
|
+
{ name: "Narrow (H:1, V:0)", padding: [1, 1, 0, 0] },
|
|
95
|
+
]
|
|
96
|
+
@padding_index = 0
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def run
|
|
100
|
+
RatatuiRuby.run do |tui|
|
|
101
|
+
@tui = tui
|
|
102
|
+
|
|
103
|
+
@title_styles = [
|
|
104
|
+
{ name: "None", style: nil },
|
|
105
|
+
{ name: "Magenta Bold", style: @tui.style(fg: :magenta, modifiers: [:bold]) },
|
|
106
|
+
{ name: "Cyan Bold", style: @tui.style(fg: :cyan, modifiers: [:bold]) },
|
|
107
|
+
{ name: "Yellow Italic", style: @tui.style(fg: :yellow, modifiers: [:italic]) },
|
|
108
|
+
]
|
|
109
|
+
@title_style_index = 1 # Magenta Bold
|
|
110
|
+
|
|
111
|
+
@border_styles = [
|
|
112
|
+
{ name: "Cyan", style: @tui.style(fg: :cyan) },
|
|
113
|
+
{ name: "Magenta Bold", style: @tui.style(fg: :magenta, modifiers: [:bold]) },
|
|
114
|
+
{ name: "None", style: nil },
|
|
115
|
+
{ name: "Blue on White", style: @tui.style(fg: :blue, bg: :white) },
|
|
116
|
+
]
|
|
117
|
+
@border_style_index = 0
|
|
118
|
+
|
|
119
|
+
@base_styles = [
|
|
120
|
+
{ name: "Dark Gray", style: @tui.style(fg: :dark_gray) },
|
|
121
|
+
{ name: "None", style: nil },
|
|
122
|
+
{ name: "White on Black", style: @tui.style(fg: :white, bg: :black) },
|
|
123
|
+
]
|
|
124
|
+
@base_style_index = 1
|
|
125
|
+
|
|
126
|
+
@hotkey_style = @tui.style(modifiers: [:bold, :underlined])
|
|
127
|
+
|
|
128
|
+
loop do
|
|
129
|
+
render
|
|
130
|
+
break if handle_input == :quit
|
|
131
|
+
sleep 0.05
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
private def render
|
|
137
|
+
title_config = @title_configs[@title_index]
|
|
138
|
+
titles_config = @titles_configs[@titles_index]
|
|
139
|
+
alignment_config = @alignment_configs[@alignment_index]
|
|
140
|
+
title_style_config = @title_styles[@title_style_index]
|
|
141
|
+
border_config = @border_configs[@border_index]
|
|
142
|
+
border_type_config = @border_type_configs[@border_type_index]
|
|
143
|
+
border_style_config = @border_styles[@border_style_index]
|
|
144
|
+
base_style_config = @base_styles[@base_style_index]
|
|
145
|
+
padding_config = @padding_configs[@padding_index]
|
|
146
|
+
|
|
147
|
+
@tui.draw do |frame|
|
|
148
|
+
main_area, control_area = @tui.layout_split(
|
|
149
|
+
frame.area,
|
|
150
|
+
direction: :vertical,
|
|
151
|
+
constraints: [
|
|
152
|
+
@tui.constraint_fill(1),
|
|
153
|
+
@tui.constraint_length(10),
|
|
154
|
+
]
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
# Render the demo block
|
|
158
|
+
demo_block = @tui.block(
|
|
159
|
+
title: title_config[:title],
|
|
160
|
+
titles: titles_config[:titles],
|
|
161
|
+
title_alignment: alignment_config[:alignment],
|
|
162
|
+
title_style: title_style_config[:style],
|
|
163
|
+
borders: border_config[:borders],
|
|
164
|
+
border_type: border_type_config[:type],
|
|
165
|
+
border_set: border_type_config[:set],
|
|
166
|
+
border_style: border_style_config[:style],
|
|
167
|
+
style: base_style_config[:style],
|
|
168
|
+
padding: padding_config[:padding]
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
# Paragraph inside the block to show padding/content interaction
|
|
172
|
+
content = @tui.paragraph(
|
|
173
|
+
text: "This paragraph is rendered inside the Block widget.\n" \
|
|
174
|
+
"You can see how padding and base style affect this content.\n\n" \
|
|
175
|
+
"Current State:\n" \
|
|
176
|
+
"• Padding: #{padding_config[:name]}\n" \
|
|
177
|
+
"• Borders: #{border_config[:name]}\n" \
|
|
178
|
+
"• Type: #{border_type_config[:name]}",
|
|
179
|
+
block: demo_block
|
|
180
|
+
)
|
|
181
|
+
frame.render_widget(content, main_area)
|
|
182
|
+
|
|
183
|
+
# Render control panel
|
|
184
|
+
control_panel = @tui.block(
|
|
185
|
+
title: "Controls",
|
|
186
|
+
borders: [:all],
|
|
187
|
+
children: [
|
|
188
|
+
@tui.paragraph(
|
|
189
|
+
text: [
|
|
190
|
+
@tui.text_line(spans: [
|
|
191
|
+
@tui.text_span(content: "t", style: @hotkey_style),
|
|
192
|
+
@tui.text_span(content: ": Title (#{title_config[:name]}) "),
|
|
193
|
+
@tui.text_span(content: "a", style: @hotkey_style),
|
|
194
|
+
@tui.text_span(content: ": Alignment (#{alignment_config[:name]}) "),
|
|
195
|
+
@tui.text_span(content: "s", style: @hotkey_style),
|
|
196
|
+
@tui.text_span(content: ": Title Style (#{title_style_config[:name]})"),
|
|
197
|
+
]),
|
|
198
|
+
@tui.text_line(spans: [
|
|
199
|
+
@tui.text_span(content: "e", style: @hotkey_style),
|
|
200
|
+
@tui.text_span(content: ": Additional Titles (#{titles_config[:name]})"),
|
|
201
|
+
]),
|
|
202
|
+
@tui.text_line(spans: [
|
|
203
|
+
@tui.text_span(content: "b", style: @hotkey_style),
|
|
204
|
+
@tui.text_span(content: ": Borders (#{border_config[:name]}) "),
|
|
205
|
+
@tui.text_span(content: "y", style: @hotkey_style),
|
|
206
|
+
@tui.text_span(content: ": Border Type (#{border_type_config[:name]})"),
|
|
207
|
+
]),
|
|
208
|
+
@tui.text_line(spans: [
|
|
209
|
+
@tui.text_span(content: "c", style: @hotkey_style),
|
|
210
|
+
@tui.text_span(content: ": Border Style (#{border_style_config[:name]}) "),
|
|
211
|
+
@tui.text_span(content: "p", style: @hotkey_style),
|
|
212
|
+
@tui.text_span(content: ": Padding (#{padding_config[:name]})"),
|
|
213
|
+
]),
|
|
214
|
+
@tui.text_line(spans: [
|
|
215
|
+
@tui.text_span(content: "f", style: @hotkey_style),
|
|
216
|
+
@tui.text_span(content: ": Base Style (#{base_style_config[:name]}) "),
|
|
217
|
+
@tui.text_span(content: "q", style: @hotkey_style),
|
|
218
|
+
@tui.text_span(content: ": Quit"),
|
|
219
|
+
]),
|
|
220
|
+
]
|
|
221
|
+
),
|
|
222
|
+
]
|
|
223
|
+
)
|
|
224
|
+
frame.render_widget(control_panel, control_area)
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
private def handle_input
|
|
229
|
+
case @tui.poll_event
|
|
230
|
+
in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
|
|
231
|
+
:quit
|
|
232
|
+
in type: :key, code: "t"
|
|
233
|
+
@title_index = (@title_index + 1) % @title_configs.size
|
|
234
|
+
in type: :key, code: "e"
|
|
235
|
+
@titles_index = (@titles_index + 1) % @titles_configs.size
|
|
236
|
+
in type: :key, code: "a"
|
|
237
|
+
@alignment_index = (@alignment_index + 1) % @alignment_configs.size
|
|
238
|
+
in type: :key, code: "s"
|
|
239
|
+
@title_style_index = (@title_style_index + 1) % @title_styles.size
|
|
240
|
+
in type: :key, code: "b"
|
|
241
|
+
@border_index = (@border_index + 1) % @border_configs.size
|
|
242
|
+
in type: :key, code: "y"
|
|
243
|
+
@border_type_index = (@border_type_index + 1) % @border_type_configs.size
|
|
244
|
+
in type: :key, code: "c"
|
|
245
|
+
@border_style_index = (@border_style_index + 1) % @border_styles.size
|
|
246
|
+
in type: :key, code: "p"
|
|
247
|
+
@padding_index = (@padding_index + 1) % @padding_configs.size
|
|
248
|
+
in type: :key, code: "f"
|
|
249
|
+
@base_style_index = (@base_style_index + 1) % @base_styles.size
|
|
250
|
+
else
|
|
251
|
+
nil
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
WidgetBlockDemo.new.run if __FILE__ == $PROGRAM_NAME
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
+
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
# Box (Block) Widget Example
|
|
7
|
+
|
|
8
|
+
Demonstrates visual container attributes with interactive cycling.
|
|
9
|
+
|
|
10
|
+
Widgets often float in a void. Without boundaries, interfaces become a chaotic mess of text. `Block` (often called a Box) provides the structure and visual hierarchy needed to organize information.
|
|
11
|
+
|
|
12
|
+
## Features Demonstrated
|
|
13
|
+
|
|
14
|
+
- **Border Types**: Native styles like `:plain`, `:rounded`, `:double`, `:thick`.
|
|
15
|
+
- **Custom Borders**: defining completely custom character sets (e.g. using numbers or letters for borders).
|
|
16
|
+
- **Styling**: Independent control over border color, background style, and title style.
|
|
17
|
+
- **Positioning**: Placing titles on the `:top` or `:bottom` border (`position`).
|
|
18
|
+
- **Alignment**: Aligning titles to `:left`, `:center`, or `:right` (`alignment`).
|
|
19
|
+
|
|
20
|
+
## Hotkeys
|
|
21
|
+
|
|
22
|
+
- **Arrow Keys**: Change Border/Content Color
|
|
23
|
+
- **Space**: Cycle Border Type (`border_type`)
|
|
24
|
+
- **c**: Cycle Custom Border Set (`border_set`)
|
|
25
|
+
- **Enter**: Cycle Title Alignment (`title_alignment`)
|
|
26
|
+
- **s**: Cycle Content Style (`style`)
|
|
27
|
+
- **t**: Cycle Title Style (`title_style`)
|
|
28
|
+
- **b**: Cycle Border Style (`border_style`)
|
|
29
|
+
- **q**: Quit
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
ruby examples/widget_box_demo/app.rb
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Learning Outcomes
|
|
38
|
+
|
|
39
|
+
Use this example if you need to...
|
|
40
|
+
- Group related widgets together.
|
|
41
|
+
- Create distinct "panels" or "cards" in your UI.
|
|
42
|
+
- Style borders to indicate state (e.g., Red border for error state).
|
|
43
|
+
- Understand the difference between `style` (content) and `border_style` (frame).
|
|
44
|
+
|
|
45
|
+

|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
+
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
# Calendar Widget Example
|
|
7
|
+
|
|
8
|
+
Demonstrates a monthly calendar with customizable headers and event highlighting.
|
|
9
|
+
|
|
10
|
+
Rendering dates in a grid involves complex calculations for leap years and weekday offsets. This widget handles that logic, letting you focus on displaying dates.
|
|
11
|
+
|
|
12
|
+
## Features Demonstrated
|
|
13
|
+
|
|
14
|
+
- **Headers**: Toggling the Month name and Weekday labels.
|
|
15
|
+
- **Surrounding Days**: displaying (or hiding/dimming) days from the previous and next months to fill the grid.
|
|
16
|
+
- **Event Styling**: applying specific styles to individual `Time` or `Date` objects to highlight events.
|
|
17
|
+
|
|
18
|
+
## Hotkeys
|
|
19
|
+
|
|
20
|
+
- **h**: Toggle Month Header (`show_month_header`)
|
|
21
|
+
- **w**: Toggle Weekday Labels (`show_weekdays_header`)
|
|
22
|
+
- **s**: Toggle Surrounding Days (`show_surrounding`)
|
|
23
|
+
- **e**: Toggle Example Events (`events`)
|
|
24
|
+
- **q**: Quit
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
ruby examples/widget_calendar_demo/app.rb
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Learning Outcomes
|
|
33
|
+
|
|
34
|
+
Use this example if you need to...
|
|
35
|
+
- Display a date picker.
|
|
36
|
+
- Show a schedule or timeline view.
|
|
37
|
+
- Highlight specific dates (deadlines, holidays) on a calendar grid.
|
|
38
|
+
|
|
39
|
+

|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Canvas Widget Demo
|
|
2
|
+
<!--
|
|
3
|
+
SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
|
+
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
5
|
+
-->
|
|
6
|
+
|
|
7
|
+
This example demonstrates the `Canvas` widget, which provides a high-resolution drawing surface using Braille characters.
|
|
8
|
+
|
|
9
|
+
## Key Concepts
|
|
10
|
+
|
|
11
|
+
- **Shapes**: Supports `Point`, `Line`, `Rectangle`, `Circle`, and `Map`.
|
|
12
|
+
- **Coordinates**: Uses a float-based coordinate system independent of terminal cells.
|
|
13
|
+
- **Markers**: Can use Braille (high res) or block characters (lower res) for rendering.
|
|
14
|
+
|
|
15
|
+
## Controls
|
|
16
|
+
|
|
17
|
+
| Key | Action |
|
|
18
|
+
| --- | --- |
|
|
19
|
+
| `q` | Quit |
|
|
20
|
+
|
|
21
|
+
## Screenshot
|
|
22
|
+
|
|
23
|
+

|
|
24
|
+
|
|
25
|
+
## Source Code
|
|
26
|
+
|
|
27
|
+
- [app.rb](app.rb)
|
|
@@ -0,0 +1,123 @@
|
|
|
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
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
|
|
7
|
+
require "ratatui_ruby"
|
|
8
|
+
|
|
9
|
+
# Demo: Canvas Widget
|
|
10
|
+
# Demonstrates how to draw geometric shapes (Points, Lines, Rects, Circles)
|
|
11
|
+
# on a high-resolution canvas.
|
|
12
|
+
class WidgetCanvasDemo
|
|
13
|
+
def initialize
|
|
14
|
+
@x_offset = 0.0
|
|
15
|
+
@y_offset = 0.0
|
|
16
|
+
@time = 0.0
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def run
|
|
20
|
+
RatatuiRuby.run do |tui|
|
|
21
|
+
@tui = tui
|
|
22
|
+
loop do
|
|
23
|
+
# Animate
|
|
24
|
+
@time += 0.1
|
|
25
|
+
@x_offset = Math.sin(@time) * 20.0
|
|
26
|
+
@y_offset = Math.cos(@time) * 20.0
|
|
27
|
+
|
|
28
|
+
render
|
|
29
|
+
break if handle_input == :quit
|
|
30
|
+
|
|
31
|
+
sleep 0.05
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private def render
|
|
37
|
+
@tui.draw do |frame|
|
|
38
|
+
# Define shapes
|
|
39
|
+
shapes = []
|
|
40
|
+
|
|
41
|
+
# 1. Static Grid (Lines)
|
|
42
|
+
(-100..100).step(20) do |i|
|
|
43
|
+
shapes << @tui.shape_line(x1: i.to_f, y1: -100.0, x2: i.to_f, y2: 100.0, color: :gray)
|
|
44
|
+
shapes << @tui.shape_line(x1: -100.0, y1: i.to_f, x2: 100.0, y2: i.to_f, color: :gray)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# 2. Moving Circle (The "Player")
|
|
48
|
+
shapes << @tui.shape_circle(
|
|
49
|
+
x: @x_offset,
|
|
50
|
+
y: @y_offset,
|
|
51
|
+
radius: 10.0,
|
|
52
|
+
color: :green
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# 3. Static Rectangle (Target)
|
|
56
|
+
shapes << @tui.shape_rectangle(
|
|
57
|
+
x: 30.0,
|
|
58
|
+
y: 30.0,
|
|
59
|
+
width: 20.0,
|
|
60
|
+
height: 20.0,
|
|
61
|
+
color: :red
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
# 4. Points (Starfield)
|
|
65
|
+
# Deterministic "random" points
|
|
66
|
+
10.times do |i|
|
|
67
|
+
shapes << @tui.shape_point(
|
|
68
|
+
x: ((i * 37) % 200) - 100.0,
|
|
69
|
+
y: ((i * 19) % 200) - 100.0
|
|
70
|
+
)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# 5. Label
|
|
74
|
+
shapes << @tui.shape_line(x1: 0.0, y1: 0.0, x2: @x_offset, y2: @y_offset, color: :yellow)
|
|
75
|
+
|
|
76
|
+
canvas = @tui.canvas(
|
|
77
|
+
shapes:,
|
|
78
|
+
x_bounds: [-100.0, 100.0],
|
|
79
|
+
y_bounds: [-100.0, 100.0],
|
|
80
|
+
marker: :braille,
|
|
81
|
+
block: @tui.block(title: "Canvas Demo", borders: [:all])
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# Main area for canvas
|
|
85
|
+
layout = @tui.layout_split(
|
|
86
|
+
frame.area,
|
|
87
|
+
direction: :vertical,
|
|
88
|
+
constraints: [
|
|
89
|
+
@tui.constraint_fill(1),
|
|
90
|
+
@tui.constraint_length(3),
|
|
91
|
+
]
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
frame.render_widget(canvas, layout[0])
|
|
95
|
+
|
|
96
|
+
# Controls
|
|
97
|
+
controls = @tui.paragraph(
|
|
98
|
+
text: [
|
|
99
|
+
@tui.text_line(spans: [
|
|
100
|
+
@tui.text_span(content: "Canvas auto-animates.", style: @tui.style(fg: :yellow)),
|
|
101
|
+
]),
|
|
102
|
+
@tui.text_line(spans: [
|
|
103
|
+
@tui.text_span(content: "q", style: @tui.style(modifiers: [:bold, :underlined])),
|
|
104
|
+
@tui.text_span(content: ": Quit"),
|
|
105
|
+
]),
|
|
106
|
+
],
|
|
107
|
+
block: @tui.block(borders: [:top])
|
|
108
|
+
)
|
|
109
|
+
frame.render_widget(controls, layout[1])
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def handle_input
|
|
114
|
+
case @tui.poll_event
|
|
115
|
+
in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
|
|
116
|
+
:quit
|
|
117
|
+
else
|
|
118
|
+
# Ignore other events
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
WidgetCanvasDemo.new.run if __FILE__ == $0
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
+
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
# Cell Widget Example
|
|
7
|
+
|
|
8
|
+
Demonstrates using `Cell` objects for granular control over individual character grid units.
|
|
9
|
+
|
|
10
|
+
Sometimes you need to render specific characters with unique styles outside of standard widgets. The `Cell` primitive allows you to build custom widgets or inject styled content into Tables.
|
|
11
|
+
|
|
12
|
+
## Features Demonstrated
|
|
13
|
+
|
|
14
|
+
- **Custom Widgets**: A `CheckeredBackground` widget built by rendering `Cell`s in a loop.
|
|
15
|
+
- **Table Integration**: Mixing simple Strings and rich `Cell` objects in a Table row.
|
|
16
|
+
- **Overlays**: Using `RatatuiRuby::Overlay` to stack widgets on top of each other.
|
|
17
|
+
- **Modifiers**: Using `rapid_blink`, `bold`, and `dim` on individual cells.
|
|
18
|
+
|
|
19
|
+
## Hotkeys
|
|
20
|
+
|
|
21
|
+
- **q** / **Ctrl+c**: Quit
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
ruby examples/widget_cell_demo/app.rb
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Learning Outcomes
|
|
30
|
+
|
|
31
|
+
Use this example if you need to...
|
|
32
|
+
- Create a custom widget (like a game board or specialized graph).
|
|
33
|
+
- Style specific cells in a Table (e.g., Green "OK", Red "FAIL").
|
|
34
|
+
- Understand how to position content precisely with `Cell`.
|
|
35
|
+
|
|
36
|
+

|
|
@@ -9,15 +9,19 @@ require "ratatui_ruby"
|
|
|
9
9
|
|
|
10
10
|
# A custom widget that fills its area with a checkered pattern using Cell objects.
|
|
11
11
|
class CheckeredBackground
|
|
12
|
+
def initialize(tui)
|
|
13
|
+
@tui = tui
|
|
14
|
+
end
|
|
15
|
+
|
|
12
16
|
def render(area)
|
|
13
|
-
cell =
|
|
17
|
+
cell = @tui.cell(char: "░", fg: :dark_gray)
|
|
14
18
|
commands = []
|
|
15
19
|
area.height.times do |y|
|
|
16
20
|
area.width.times do |x|
|
|
17
21
|
# Checkerboard logic
|
|
18
22
|
if (x + y).even?
|
|
19
23
|
# Use a dim cell for the background pattern
|
|
20
|
-
commands <<
|
|
24
|
+
commands << @tui.draw_cell(area.x + x, area.y + y, cell)
|
|
21
25
|
end
|
|
22
26
|
end
|
|
23
27
|
end
|
|
@@ -26,12 +30,13 @@ class CheckeredBackground
|
|
|
26
30
|
end
|
|
27
31
|
|
|
28
32
|
class WidgetCellDemo
|
|
29
|
-
def
|
|
33
|
+
def run
|
|
30
34
|
RatatuiRuby.run do |tui|
|
|
35
|
+
@tui = tui
|
|
31
36
|
# Define some reusable cells for our table
|
|
32
|
-
ok_cell =
|
|
33
|
-
fail_cell =
|
|
34
|
-
pending_cell =
|
|
37
|
+
ok_cell = @tui.cell(char: "OK", fg: :green)
|
|
38
|
+
fail_cell = @tui.cell(char: "FAIL", fg: :red, modifiers: ["bold"])
|
|
39
|
+
pending_cell = @tui.cell(char: "...", fg: :yellow, modifiers: ["dim"])
|
|
35
40
|
|
|
36
41
|
# A mix of Strings and Cells in rows
|
|
37
42
|
rows = [
|
|
@@ -39,47 +44,47 @@ class WidgetCellDemo
|
|
|
39
44
|
["Cache", ok_cell],
|
|
40
45
|
["Worker", fail_cell],
|
|
41
46
|
["Analytics", pending_cell],
|
|
42
|
-
["Web Server",
|
|
47
|
+
["Web Server", @tui.cell(char: "RESTARTING", fg: :blue, modifiers: ["rapid_blink"])],
|
|
43
48
|
]
|
|
44
49
|
|
|
45
|
-
table =
|
|
46
|
-
header: ["Service",
|
|
50
|
+
table = @tui.table(
|
|
51
|
+
header: ["Service", @tui.cell(char: "Status", modifiers: ["underlined"])],
|
|
47
52
|
rows:,
|
|
48
53
|
widths: [
|
|
49
|
-
|
|
50
|
-
|
|
54
|
+
@tui.constraint_percentage(70),
|
|
55
|
+
@tui.constraint_percentage(30),
|
|
51
56
|
],
|
|
52
|
-
block:
|
|
57
|
+
block: @tui.block(title: "System Status", borders: :all),
|
|
53
58
|
column_spacing: 1
|
|
54
59
|
)
|
|
55
60
|
|
|
56
61
|
# Main loop
|
|
57
62
|
loop do
|
|
58
|
-
tui.draw do |frame|
|
|
63
|
+
@tui.draw do |frame|
|
|
59
64
|
# Create a layout that holds both widgets
|
|
60
65
|
# We use a vertical layout:
|
|
61
66
|
# Top: Custom CheckeredBackground with specific height
|
|
62
67
|
# Bottom: Table using remaining space
|
|
63
|
-
top_area, bottom_area =
|
|
68
|
+
top_area, bottom_area = @tui.layout_split(
|
|
64
69
|
frame.area,
|
|
65
70
|
direction: :vertical,
|
|
66
71
|
constraints: [
|
|
67
|
-
|
|
68
|
-
|
|
72
|
+
@tui.constraint_length(10), # Top section
|
|
73
|
+
@tui.constraint_min(0), # Bottom section
|
|
69
74
|
]
|
|
70
75
|
)
|
|
71
76
|
|
|
72
77
|
# Top Child: An Overlay of Paragraph on top of CheckeredBackground
|
|
73
|
-
overlay =
|
|
78
|
+
overlay = @tui.overlay(
|
|
74
79
|
layers: [
|
|
75
|
-
CheckeredBackground.new,
|
|
76
|
-
|
|
80
|
+
CheckeredBackground.new(@tui),
|
|
81
|
+
@tui.center(
|
|
77
82
|
width_percent: 50,
|
|
78
83
|
height_percent: 50,
|
|
79
|
-
child:
|
|
84
|
+
child: @tui.paragraph(
|
|
80
85
|
text: "Custom Widget Demo\n(CheckeredBackground)",
|
|
81
86
|
alignment: :center,
|
|
82
|
-
block:
|
|
87
|
+
block: @tui.block(borders: :all, title: "Overlay")
|
|
83
88
|
)
|
|
84
89
|
),
|
|
85
90
|
]
|
|
@@ -90,9 +95,11 @@ class WidgetCellDemo
|
|
|
90
95
|
frame.render_widget(table, bottom_area)
|
|
91
96
|
end
|
|
92
97
|
|
|
93
|
-
|
|
94
|
-
|
|
98
|
+
case @tui.poll_event
|
|
99
|
+
in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
|
|
95
100
|
break
|
|
101
|
+
else
|
|
102
|
+
nil
|
|
96
103
|
end
|
|
97
104
|
end
|
|
98
105
|
end
|
|
@@ -100,5 +107,5 @@ class WidgetCellDemo
|
|
|
100
107
|
end
|
|
101
108
|
|
|
102
109
|
if __FILE__ == $0
|
|
103
|
-
WidgetCellDemo.new.
|
|
110
|
+
WidgetCellDemo.new.run
|
|
104
111
|
end
|