teek-ui 0.1.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 +7 -0
- data/CHANGELOG.md +41 -0
- data/README.md +452 -0
- data/lib/teek/ui/canvas_item.rb +270 -0
- data/lib/teek/ui/component_handle.rb +32 -0
- data/lib/teek/ui/document.rb +185 -0
- data/lib/teek/ui/errors.rb +41 -0
- data/lib/teek/ui/event_binding.rb +22 -0
- data/lib/teek/ui/event_bus.rb +53 -0
- data/lib/teek/ui/grid_validator.rb +89 -0
- data/lib/teek/ui/handle.rb +585 -0
- data/lib/teek/ui/image.rb +58 -0
- data/lib/teek/ui/keysyms.rb +72 -0
- data/lib/teek/ui/menu_builder.rb +130 -0
- data/lib/teek/ui/menu_entry_addressing.rb +62 -0
- data/lib/teek/ui/modal_stack.rb +99 -0
- data/lib/teek/ui/mouse_events.rb +31 -0
- data/lib/teek/ui/node.rb +141 -0
- data/lib/teek/ui/option_dump_parsing.rb +31 -0
- data/lib/teek/ui/overlay_anchors.rb +29 -0
- data/lib/teek/ui/overlay_validator.rb +33 -0
- data/lib/teek/ui/pane_validator.rb +30 -0
- data/lib/teek/ui/realized_node.rb +25 -0
- data/lib/teek/ui/realizer.rb +577 -0
- data/lib/teek/ui/scope.rb +40 -0
- data/lib/teek/ui/screens.rb +141 -0
- data/lib/teek/ui/session.rb +417 -0
- data/lib/teek/ui/tab_validator.rb +30 -0
- data/lib/teek/ui/text_content.rb +321 -0
- data/lib/teek/ui/tree_inspector.rb +97 -0
- data/lib/teek/ui/validator.rb +131 -0
- data/lib/teek/ui/var.rb +98 -0
- data/lib/teek/ui/version.rb +7 -0
- data/lib/teek/ui/widget_addressing.rb +47 -0
- data/lib/teek/ui/widget_dsl.rb +512 -0
- data/lib/teek/ui/widget_type.rb +242 -0
- data/lib/teek/ui/widget_types/button.rb +7 -0
- data/lib/teek/ui/widget_types/canvas.rb +15 -0
- data/lib/teek/ui/widget_types/checkbox.rb +7 -0
- data/lib/teek/ui/widget_types/column.rb +14 -0
- data/lib/teek/ui/widget_types/context_menu.rb +15 -0
- data/lib/teek/ui/widget_types/divider.rb +10 -0
- data/lib/teek/ui/widget_types/dropdown.rb +7 -0
- data/lib/teek/ui/widget_types/grid.rb +12 -0
- data/lib/teek/ui/widget_types/group.rb +7 -0
- data/lib/teek/ui/widget_types/label.rb +7 -0
- data/lib/teek/ui/widget_types/list.rb +7 -0
- data/lib/teek/ui/widget_types/menu_bar.rb +26 -0
- data/lib/teek/ui/widget_types/menu_checkbox.rb +14 -0
- data/lib/teek/ui/widget_types/menu_item.rb +20 -0
- data/lib/teek/ui/widget_types/menu_radio.rb +14 -0
- data/lib/teek/ui/widget_types/number_box.rb +7 -0
- data/lib/teek/ui/widget_types/pane.rb +37 -0
- data/lib/teek/ui/widget_types/panel.rb +7 -0
- data/lib/teek/ui/widget_types/progress.rb +7 -0
- data/lib/teek/ui/widget_types/radio.rb +7 -0
- data/lib/teek/ui/widget_types/row.rb +14 -0
- data/lib/teek/ui/widget_types/scrollable.rb +17 -0
- data/lib/teek/ui/widget_types/slider.rb +7 -0
- data/lib/teek/ui/widget_types/spacer.rb +14 -0
- data/lib/teek/ui/widget_types/split.rb +17 -0
- data/lib/teek/ui/widget_types/tab.rb +35 -0
- data/lib/teek/ui/widget_types/table.rb +9 -0
- data/lib/teek/ui/widget_types/tabs.rb +10 -0
- data/lib/teek/ui/widget_types/text_area.rb +7 -0
- data/lib/teek/ui/widget_types/text_box.rb +7 -0
- data/lib/teek/ui/widget_types/tree.rb +9 -0
- data/lib/teek/ui/widget_types/window.rb +50 -0
- data/lib/teek/ui/widget_types.rb +121 -0
- data/lib/teek/ui/widget_validators.rb +62 -0
- data/lib/teek/ui.rb +54 -0
- data/teek-ui.gemspec +24 -0
- data/test/support/fake_app.rb +57 -0
- data/test/test_busy.rb +82 -0
- data/test/test_canvas_items.rb +551 -0
- data/test/test_clipboard.rb +87 -0
- data/test/test_close_handling.rb +118 -0
- data/test/test_component.rb +151 -0
- data/test/test_component_realtk.rb +120 -0
- data/test/test_debug_info.rb +158 -0
- data/test/test_document.rb +317 -0
- data/test/test_event_bus.rb +163 -0
- data/test/test_events.rb +164 -0
- data/test/test_fake_app_contract.rb +62 -0
- data/test/test_grid.rb +97 -0
- data/test/test_handle.rb +386 -0
- data/test/test_handle_destroy_realtk.rb +344 -0
- data/test/test_helper.rb +20 -0
- data/test/test_image.rb +24 -0
- data/test/test_image_realtk.rb +146 -0
- data/test/test_incremental_realize.rb +203 -0
- data/test/test_keysyms.rb +76 -0
- data/test/test_layout.rb +185 -0
- data/test/test_lazy_realize.rb +128 -0
- data/test/test_managed_window.rb +304 -0
- data/test/test_menu_dsl.rb +230 -0
- data/test/test_menu_entry_addressing.rb +73 -0
- data/test/test_menu_realize.rb +296 -0
- data/test/test_modal_handle.rb +147 -0
- data/test/test_modal_stack.rb +219 -0
- data/test/test_modal_stack_realtk.rb +131 -0
- data/test/test_native_scrollable.rb +250 -0
- data/test/test_node.rb +193 -0
- data/test/test_overlay.rb +139 -0
- data/test/test_raw.rb +58 -0
- data/test/test_reactive_vars.rb +118 -0
- data/test/test_realizer.rb +264 -0
- data/test/test_scope.rb +38 -0
- data/test/test_screens.rb +260 -0
- data/test/test_screens_realtk.rb +314 -0
- data/test/test_scrollable.rb +185 -0
- data/test/test_scrollable_wheel.rb +172 -0
- data/test/test_scrollbar_auto_hide.rb +127 -0
- data/test/test_split.rb +145 -0
- data/test/test_tabs.rb +201 -0
- data/test/test_text_content.rb +664 -0
- data/test/test_toast.rb +126 -0
- data/test/test_tree_inspector.rb +183 -0
- data/test/test_ui.rb +428 -0
- data/test/test_validator.rb +209 -0
- data/test/test_var.rb +32 -0
- data/test/test_widget_dsl.rb +621 -0
- data/test/test_widget_introspection.rb +126 -0
- data/test/test_widget_types.rb +429 -0
- data/test/test_widget_types_realtk.rb +82 -0
- data/test/test_widget_validators.rb +82 -0
- metadata +207 -0
data/test/test_tabs.rb
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'minitest/autorun'
|
|
4
|
+
require_relative '../../test/tk_test_helper'
|
|
5
|
+
|
|
6
|
+
# ui.tabs/t.tab realize as a working ttk::notebook - each tab a real Tk
|
|
7
|
+
# frame added as a notebook page (TabRealize.post_create), never pack/grid
|
|
8
|
+
# managed on its own (:tab's own arranged: false). Tab selection is
|
|
9
|
+
# observable via Handle#on_tab_changed, which surfaces Tk's own
|
|
10
|
+
# <<NotebookTabChanged>>.
|
|
11
|
+
class TestTabs < Minitest::Test
|
|
12
|
+
include TeekTestHelper
|
|
13
|
+
|
|
14
|
+
def test_tabs_realizes_as_a_working_notebook_with_labeled_pages
|
|
15
|
+
assert_tk_app("ui.tabs should realize as a ttk::notebook with each tab added as a labeled page") do
|
|
16
|
+
require 'teek/ui'
|
|
17
|
+
|
|
18
|
+
session = Teek::UI.app(title: 'Tabs Test') do |ui|
|
|
19
|
+
ui.tabs(:t) do |t|
|
|
20
|
+
t.tab('General') { |g| g.button(:go, text: 'Go') }
|
|
21
|
+
t.tab('Advanced') { |a| a.label(:info, text: 'Advanced stuff') }
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
session.run_async
|
|
25
|
+
session.app.update
|
|
26
|
+
|
|
27
|
+
notebook_path = session[:t].path
|
|
28
|
+
tab_paths = session.app.split_list(session.app.command(notebook_path, :tabs))
|
|
29
|
+
assert_equal 2, tab_paths.length
|
|
30
|
+
|
|
31
|
+
assert_equal 'General', session.app.command(notebook_path, :tab, tab_paths[0], '-text')
|
|
32
|
+
assert_equal 'Advanced', session.app.command(notebook_path, :tab, tab_paths[1], '-text')
|
|
33
|
+
|
|
34
|
+
session.app.destroy
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def test_tab_content_is_addressable_and_configurable_like_any_other_widget
|
|
39
|
+
assert_tk_app("a widget declared inside a tab should be a normal, addressable, configurable widget") do
|
|
40
|
+
require 'teek/ui'
|
|
41
|
+
|
|
42
|
+
session = Teek::UI.app(title: 'Tabs Test') do |ui|
|
|
43
|
+
ui.tabs { |t| t.tab('General') { |g| g.button(:go, text: 'Go') } }
|
|
44
|
+
end
|
|
45
|
+
session.run_async
|
|
46
|
+
session.app.update
|
|
47
|
+
|
|
48
|
+
session[:go].configure(text: 'Changed')
|
|
49
|
+
session.app.update
|
|
50
|
+
|
|
51
|
+
assert_equal 'Changed', session.app.command(session[:go].path, :cget, '-text')
|
|
52
|
+
|
|
53
|
+
session.app.destroy
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def test_tab_frame_is_not_independently_pack_or_grid_managed
|
|
58
|
+
assert_tk_app("a tab's own frame should be placed only by notebook add, not pack/grid") do
|
|
59
|
+
require 'teek/ui'
|
|
60
|
+
|
|
61
|
+
session = Teek::UI.app(title: 'Tabs Test') do |ui|
|
|
62
|
+
ui.tabs(:t) { |t| t.tab('General', :general) { |g| g.button(text: 'Go') } }
|
|
63
|
+
end
|
|
64
|
+
session.run_async
|
|
65
|
+
session.app.update
|
|
66
|
+
|
|
67
|
+
assert_equal 'notebook', session.app.tcl_eval("winfo manager #{session[:general].path}"),
|
|
68
|
+
"the notebook itself should be the only geometry manager - proves no pack/grid call also ran"
|
|
69
|
+
|
|
70
|
+
session.app.destroy
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def test_on_tab_changed_fires_with_the_tabs_name_when_it_has_one
|
|
75
|
+
assert_tk_app("switching to a named tab should fire on_tab_changed with that name") do
|
|
76
|
+
require 'teek/ui'
|
|
77
|
+
|
|
78
|
+
session = Teek::UI.app(title: 'Tabs Test') do |ui|
|
|
79
|
+
ui.tabs(:t) do |t|
|
|
80
|
+
t.tab('General', :general) { }
|
|
81
|
+
t.tab('Advanced', :advanced) { }
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
session.run_async
|
|
85
|
+
session.app.update
|
|
86
|
+
|
|
87
|
+
received = []
|
|
88
|
+
session[:t].on_tab_changed { |id| received << id }
|
|
89
|
+
|
|
90
|
+
session.app.command(session[:t].path, :select, session[:advanced].path)
|
|
91
|
+
session.app.update
|
|
92
|
+
|
|
93
|
+
assert_equal [:advanced], received
|
|
94
|
+
|
|
95
|
+
session.app.destroy
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def test_on_tab_changed_fires_with_the_index_when_the_tab_is_unnamed
|
|
100
|
+
assert_tk_app("switching to an unnamed tab should fire on_tab_changed with its zero-based index") do
|
|
101
|
+
require 'teek/ui'
|
|
102
|
+
|
|
103
|
+
session = Teek::UI.app(title: 'Tabs Test') do |ui|
|
|
104
|
+
ui.tabs(:t) do |t|
|
|
105
|
+
t.tab('General') { }
|
|
106
|
+
t.tab('Advanced') { }
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
session.run_async
|
|
110
|
+
session.app.update
|
|
111
|
+
|
|
112
|
+
received = []
|
|
113
|
+
session[:t].on_tab_changed { |id| received << id }
|
|
114
|
+
|
|
115
|
+
notebook_path = session[:t].path
|
|
116
|
+
second_tab = session.app.split_list(session.app.command(notebook_path, :tabs))[1]
|
|
117
|
+
session.app.command(notebook_path, :select, second_tab)
|
|
118
|
+
session.app.update
|
|
119
|
+
|
|
120
|
+
assert_equal [1], received
|
|
121
|
+
|
|
122
|
+
session.app.destroy
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def test_on_tab_changed_queued_before_realize_fires_once_wired
|
|
127
|
+
assert_tk_app("on_tab_changed declared before realize should still fire correctly once realized") do
|
|
128
|
+
require 'teek/ui'
|
|
129
|
+
|
|
130
|
+
tabs_handle = nil
|
|
131
|
+
session = Teek::UI.app(title: 'Tabs Test') do |ui|
|
|
132
|
+
tabs_handle = ui.tabs(:t) do |t|
|
|
133
|
+
t.tab('General', :general) { }
|
|
134
|
+
t.tab('Advanced', :advanced) { }
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
received = []
|
|
139
|
+
tabs_handle.on_tab_changed { |id| received << id }
|
|
140
|
+
|
|
141
|
+
session.run_async
|
|
142
|
+
session.app.update
|
|
143
|
+
# realizing the notebook auto-selects its first tab, which is a real
|
|
144
|
+
# <<NotebookTabChanged>> in its own right and (since this binding
|
|
145
|
+
# was queued before realize, unlike the other on_tab_changed tests)
|
|
146
|
+
# gets caught by it too - clear that out to isolate the transition
|
|
147
|
+
# this test actually cares about.
|
|
148
|
+
received.clear
|
|
149
|
+
|
|
150
|
+
session.app.command(session[:t].path, :select, session[:advanced].path)
|
|
151
|
+
session.app.update
|
|
152
|
+
|
|
153
|
+
assert_equal [:advanced], received
|
|
154
|
+
|
|
155
|
+
session.app.destroy
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def test_on_tab_changed_raises_on_a_non_tabs_handle
|
|
160
|
+
assert_tk_app("on_tab_changed should raise a clear error on a non-tabs handle") do
|
|
161
|
+
require 'teek/ui'
|
|
162
|
+
|
|
163
|
+
session = Teek::UI.app(title: 'Tabs Test') { |ui| ui.button(:go, text: 'Go') }
|
|
164
|
+
session.run_async
|
|
165
|
+
session.app.update
|
|
166
|
+
|
|
167
|
+
error = assert_raises(ArgumentError) { session[:go].on_tab_changed { } }
|
|
168
|
+
assert_match(/tabs/i, error.message)
|
|
169
|
+
|
|
170
|
+
session.app.destroy
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def test_a_new_tab_can_be_added_at_runtime_via_incremental_realize
|
|
175
|
+
assert_tk_app("session.add should be able to add a whole new tab to an already-realized ui.tabs") do
|
|
176
|
+
require 'teek/ui'
|
|
177
|
+
|
|
178
|
+
session = Teek::UI.app(title: 'Tabs Test') do |ui|
|
|
179
|
+
ui.tabs(:t) { |t| t.tab('General') { |g| g.button(text: 'Go') } }
|
|
180
|
+
end
|
|
181
|
+
session.run_async
|
|
182
|
+
session.app.update
|
|
183
|
+
|
|
184
|
+
notebook_path = session[:t].path
|
|
185
|
+
assert_equal 1, session.app.split_list(session.app.command(notebook_path, :tabs)).length
|
|
186
|
+
|
|
187
|
+
session.add(:t) { |a| a.tab('New Tab', :new_tab) { |n| n.button(:new_button, text: 'New') } }
|
|
188
|
+
session.app.update
|
|
189
|
+
|
|
190
|
+
tab_paths = session.app.split_list(session.app.command(notebook_path, :tabs))
|
|
191
|
+
assert_equal 2, tab_paths.length
|
|
192
|
+
assert_equal 'New Tab', session.app.command(notebook_path, :tab, tab_paths[1], '-text')
|
|
193
|
+
|
|
194
|
+
session.app.command(notebook_path, :select, session[:new_tab].path)
|
|
195
|
+
session.app.update
|
|
196
|
+
assert session.app.winfo.ismapped?(session[:new_button].path)
|
|
197
|
+
|
|
198
|
+
session.app.destroy
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|