tuile 0.15.0 → 0.16.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/CHANGELOG.md +121 -80
- data/README.md +28 -12
- data/book/04-event-loop.md +12 -12
- data/book/05-focus.md +95 -26
- data/book/06-theming.md +58 -26
- data/book/07-components.md +61 -6
- data/book/08-testing.md +24 -22
- data/book/10-locale.md +2 -2
- data/book/README.md +6 -5
- data/examples/file_commander.rb +14 -5
- data/examples/hello_world.rb +17 -4
- data/examples/sampler.rb +392 -18
- data/lib/tuile/component/abstract_string_field.rb +16 -18
- data/lib/tuile/component/abstract_wrapping_field.rb +47 -11
- data/lib/tuile/component/button.rb +8 -8
- data/lib/tuile/component/checkbox.rb +9 -9
- data/lib/tuile/component/checkbox_group.rb +6 -5
- data/lib/tuile/component/combo_box.rb +50 -35
- data/lib/tuile/component/confirm_window.rb +7 -5
- data/lib/tuile/component/date_field.rb +28 -3
- data/lib/tuile/component/date_time_field.rb +275 -0
- data/lib/tuile/component/has_bad_input.rb +2 -2
- data/lib/tuile/component/has_content.rb +3 -3
- data/lib/tuile/component/has_placeholder.rb +1 -1
- data/lib/tuile/component/has_validation.rb +2 -2
- data/lib/tuile/component/has_value.rb +1 -1
- data/lib/tuile/component/label.rb +1 -1
- data/lib/tuile/component/layout/box.rb +4 -1
- data/lib/tuile/component/layout.rb +3 -3
- data/lib/tuile/component/list.rb +42 -32
- data/lib/tuile/component/list_dropdown.rb +3 -3
- data/lib/tuile/component/menu_bar/cascade.rb +5 -5
- data/lib/tuile/component/menu_bar.rb +18 -18
- data/lib/tuile/component/notification.rb +32 -18
- data/lib/tuile/component/overlay.rb +9 -8
- data/lib/tuile/component/picker_window.rb +27 -8
- data/lib/tuile/component/popup.rb +2 -2
- data/lib/tuile/component/progress_bar.rb +10 -4
- data/lib/tuile/component/radio_group.rb +6 -5
- data/lib/tuile/component/select.rb +11 -12
- data/lib/tuile/component/slot.rb +3 -3
- data/lib/tuile/component/tab_sheet.rb +6 -6
- data/lib/tuile/component/tabs.rb +11 -11
- data/lib/tuile/component/text_area.rb +12 -10
- data/lib/tuile/component/text_field.rb +14 -12
- data/lib/tuile/component/text_view.rb +15 -11
- data/lib/tuile/component/time_field.rb +29 -4
- data/lib/tuile/component.rb +201 -93
- data/lib/tuile/event_queue.rb +4 -4
- data/lib/tuile/fake_event_queue.rb +1 -1
- data/lib/tuile/fake_screen.rb +84 -2
- data/lib/tuile/mouse/router.rb +217 -0
- data/lib/tuile/mouse.rb +177 -0
- data/lib/tuile/screen.rb +98 -61
- data/lib/tuile/screen_pane.rb +41 -36
- data/lib/tuile/styled_string.rb +5 -5
- data/lib/tuile/testing.rb +8 -8
- data/lib/tuile/theme.rb +22 -34
- data/lib/tuile/version.rb +1 -1
- data/lib/tuile/vertical_scroll_bar.rb +1 -1
- data/sig/tuile.rbs +1211 -427
- metadata +4 -16
- data/COMPARISON.md +0 -101
- data/DECISIONS.md +0 -8562
- data/TERMINOLOGY.md +0 -85
- data/ideas/arrow-key-navigation.md +0 -221
- data/ideas/binder.md +0 -177
- data/ideas/composite-field.md +0 -77
- data/ideas/focus-accent.md +0 -116
- data/ideas/form-layout.md +0 -151
- data/ideas/hover/probe.rb +0 -241
- data/ideas/hover/probe_spec.rb +0 -82
- data/ideas/hover.md +0 -909
- data/ideas/modal-backdrop.md +0 -24
- data/ideas/new-components.md +0 -144
- data/ideas/per-component-buffers.md +0 -55
- data/lib/tuile/mouse_event.rb +0 -68
data/book/10-locale.md
CHANGED
|
@@ -181,7 +181,7 @@ forever.
|
|
|
181
181
|
|
|
182
182
|
## When the locale changes under you
|
|
183
183
|
|
|
184
|
-
{Tuile::Screen#locale=} fires {Tuile::Component#
|
|
184
|
+
{Tuile::Screen#locale=} fires {Tuile::Component#handle_locale_changed}
|
|
185
185
|
across the attached tree and then invalidates all of it — the same
|
|
186
186
|
machinery {Tuile::Screen#theme=} uses, for the same reason.
|
|
187
187
|
|
|
@@ -194,7 +194,7 @@ The hook is for state you *pushed* somewhere when you last read the
|
|
|
194
194
|
conventions. A date field's typing hint is the worked example: it lives
|
|
195
195
|
in its editor's `placeholder`, written when the formats were last set, so
|
|
196
196
|
a repaint alone would faithfully repaint the stale `dd.mm.yyyy`. The
|
|
197
|
-
field overrides `
|
|
197
|
+
field overrides `handle_locale_changed` to re-derive it — and, while it is
|
|
198
198
|
there, to rewrite a buffer that still parses into the new primary format.
|
|
199
199
|
Your own code does the same for a date you rendered into a
|
|
200
200
|
{Tuile::Component::Label}, either by overriding the hook or by assigning
|
data/book/README.md
CHANGED
|
@@ -65,16 +65,17 @@ one, not to fill an outline.
|
|
|
65
65
|
same queue rather than handled off the signal.
|
|
66
66
|
5. **[Focus and the keyboard](05-focus.md).** The focus chain and
|
|
67
67
|
`focusable?`, and the three-rung order in which a keystroke is offered
|
|
68
|
-
to the tree — Tab, global shortcuts, then `handle_key
|
|
68
|
+
to the tree — Tab, global shortcuts, then `handle_key?` delivered to
|
|
69
69
|
focus and bubbling up its ancestors. Why scope-wide keys (pane jumps, a
|
|
70
70
|
form's default button) belong on an ancestor, why a paste rides its own
|
|
71
|
-
path rather than the ladder, and how
|
|
72
|
-
|
|
71
|
+
path rather than the ladder, and how the mouse takes a road of its own —
|
|
72
|
+
a press bubbling to one claimant that is then grabbed. Ends on writing a
|
|
73
|
+
status line over `on_focus_changed` — Tuile draws none for you.
|
|
73
74
|
6. **[Theming](06-theming.md).** Semantic color tokens read at paint
|
|
74
75
|
time, opt-in component backgrounds that inherit down the tree
|
|
75
76
|
(`bg_color`), light/dark auto-detection at startup and live OS
|
|
76
77
|
appearance flips, pairing variants in a `ThemeDef`, app-specific custom
|
|
77
|
-
tokens, and rebuilding theme-derived content in `
|
|
78
|
+
tokens, and rebuilding theme-derived content in `handle_theme_changed`.
|
|
78
79
|
7. **[The component library](07-components.md).** A narrative tour of
|
|
79
80
|
the shipped toolbox — the text inputs and views, the value fields, the
|
|
80
81
|
selectors, Button, ProgressBar, Window, TabSheet, MenuBar, Popup and the
|
|
@@ -94,5 +95,5 @@ one, not to fill an outline.
|
|
|
94
95
|
never prose*, detected from `locale(1)` only when the environment
|
|
95
96
|
actually asked, with `Locale::ISO` as the floor. Why the name tables
|
|
96
97
|
are keyed by the `Date` accessor that reads them, how a field follows
|
|
97
|
-
the session until you override it, and what `
|
|
98
|
+
the session until you override it, and what `handle_locale_changed` is
|
|
98
99
|
for.
|
data/examples/file_commander.rb
CHANGED
|
@@ -20,6 +20,14 @@ require "rainbow"
|
|
|
20
20
|
require "tuile"
|
|
21
21
|
|
|
22
22
|
module FileCommanderExample
|
|
23
|
+
# `hint` is the app's token, not Tuile's — the framework carries accents only
|
|
24
|
+
# for the chrome it paints itself, and the status line below is ours. Paired
|
|
25
|
+
# in a ThemeDef so it survives an OS appearance flip.
|
|
26
|
+
APP_THEME = Tuile::ThemeDef.new(
|
|
27
|
+
dark: Tuile::Theme::DARK.with(custom: { hint: Tuile::Color::GREY54 }),
|
|
28
|
+
light: Tuile::Theme::LIGHT.with(custom: { hint: Tuile::Color::GREY62 })
|
|
29
|
+
)
|
|
30
|
+
|
|
23
31
|
# Pastel X11 colors chosen to read on a black background.
|
|
24
32
|
TYPE_COLORS = {
|
|
25
33
|
directory: :lightskyblue,
|
|
@@ -45,7 +53,7 @@ module FileCommanderExample
|
|
|
45
53
|
attr_reader :cwd
|
|
46
54
|
attr_accessor :on_cwd_changed
|
|
47
55
|
|
|
48
|
-
def handle_key(key)
|
|
56
|
+
def handle_key?(key)
|
|
49
57
|
return false unless active?
|
|
50
58
|
|
|
51
59
|
if Tuile::Keys::BACKSPACES.include?(key)
|
|
@@ -56,7 +64,7 @@ module FileCommanderExample
|
|
|
56
64
|
end
|
|
57
65
|
end
|
|
58
66
|
|
|
59
|
-
def
|
|
67
|
+
def handle_focus
|
|
60
68
|
super
|
|
61
69
|
@on_cwd_changed&.call
|
|
62
70
|
end
|
|
@@ -135,13 +143,13 @@ module FileCommanderExample
|
|
|
135
143
|
# The status line. Every key here works in both panes, so the row never
|
|
136
144
|
# changes and nothing needs to watch focus — a status line is only worth
|
|
137
145
|
# wiring to Tuile::Screen#on_focus_changed= when its text actually varies
|
|
138
|
-
# with the focused component. `theme.
|
|
146
|
+
# with the focused component. `theme.fg` bakes its colors in, so the
|
|
139
147
|
# one thing this label does watch is a light/dark flip.
|
|
140
148
|
@status = Tuile::Component::Label.new
|
|
141
149
|
render_status = lambda do
|
|
142
150
|
t = screen.theme
|
|
143
|
-
@status.text = "q #{t.hint
|
|
144
|
-
"Enter #{t.hint
|
|
151
|
+
@status.text = "q #{t.fg(:hint, "quit")} Tab #{t.fg(:hint, "Switch")} " \
|
|
152
|
+
"Enter #{t.fg(:hint, "Open")} Bksp #{t.fg(:hint, "Up")}"
|
|
145
153
|
end
|
|
146
154
|
render_status.call
|
|
147
155
|
@status.on_theme_changed = render_status
|
|
@@ -180,6 +188,7 @@ unless File.directory?(start_dir)
|
|
|
180
188
|
end
|
|
181
189
|
|
|
182
190
|
screen = Tuile::Screen.new
|
|
191
|
+
screen.theme_def = FileCommanderExample::APP_THEME
|
|
183
192
|
commander = FileCommanderExample::FileCommander.new(start_dir, start_dir)
|
|
184
193
|
screen.content = commander
|
|
185
194
|
commander.left_window.focus
|
data/examples/hello_world.rb
CHANGED
|
@@ -11,18 +11,31 @@
|
|
|
11
11
|
|
|
12
12
|
require "tuile"
|
|
13
13
|
|
|
14
|
+
# `hint` is the app's token, not Tuile's: the framework carries accents for the
|
|
15
|
+
# chrome *it* paints, and a status line is the app's own (Tuile draws none).
|
|
16
|
+
# Pairing the two shades in a ThemeDef is what makes it survive the user
|
|
17
|
+
# flipping OS appearance — a bare `theme=` would be replaced on the next flip.
|
|
18
|
+
# Both greys quantize to :bright_black on a 16-color terminal, so the
|
|
19
|
+
# description stays dimmer than the key beside it even there.
|
|
20
|
+
APP_THEME = Tuile::ThemeDef.new(
|
|
21
|
+
dark: Tuile::Theme::DARK.with(custom: { hint: Tuile::Color::GREY54 }),
|
|
22
|
+
light: Tuile::Theme::LIGHT.with(custom: { hint: Tuile::Color::GREY62 })
|
|
23
|
+
)
|
|
24
|
+
|
|
14
25
|
# Screen must exist before any Component is built: components reach for
|
|
15
26
|
# Tuile::Screen.instance during invalidate/repaint hooks.
|
|
16
27
|
screen = Tuile::Screen.new
|
|
28
|
+
screen.theme_def = APP_THEME
|
|
17
29
|
|
|
18
30
|
window = Tuile::Component::Window.new("Tuile")
|
|
19
31
|
window.content = Tuile::Component::Label.new("Hello, world!")
|
|
20
32
|
|
|
21
|
-
# The status line. `theme.
|
|
22
|
-
# pair,
|
|
23
|
-
# `on_theme_changed` to follow a
|
|
33
|
+
# The status line. `theme.fg` styles the *description* half of a "key what"
|
|
34
|
+
# pair — dimmed, so the key is the element that pulls the eye — and bakes the
|
|
35
|
+
# color in, so the label rebuilds itself from its `on_theme_changed` slot to follow a
|
|
36
|
+
# light/dark flip.
|
|
24
37
|
status = Tuile::Component::Label.new
|
|
25
|
-
render_status = -> { status.text = "q #{screen.theme.hint
|
|
38
|
+
render_status = -> { status.text = "q #{screen.theme.fg(:hint, "quit")}" }
|
|
26
39
|
render_status.call
|
|
27
40
|
status.on_theme_changed = render_status
|
|
28
41
|
|