scarpe 0.3.0 → 0.5.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/.cursor/rules/commit-style-preferences.mdc +72 -0
- data/.cursor/rules/component_context.mdc +82 -0
- data/.cursor/rules/debug-failed-tests.mdc +100 -0
- data/.cursor/rules/display_service_context.mdc +80 -0
- data/.cursor/rules/event_handling_context.mdc +100 -0
- data/.cursor/rules/git-pager-handling.mdc +64 -0
- data/.cursor/rules/lacci-context.mdc +52 -0
- data/.cursor/rules/scarpe_design_context.mdc +46 -0
- data/.cursor/rules/shoes_compatibility_context.mdc +75 -0
- data/.cursor/rules/timeout_context.mdc +78 -0
- data/.cursor/rules/update_lacci_and_wv.mdc +8 -0
- data/.cursor/rules/what_is_scarpe.mdc +22 -0
- data/.cursor/rules/writing-new-rules.mdc +73 -0
- data/CHANGELOG.md +46 -5
- data/CLAUDE.md +223 -0
- data/Gemfile +2 -2
- data/Gemfile.lock +85 -55
- data/LICENSE.txt +7 -1
- data/README.md +80 -20
- data/Rakefile +73 -14
- data/docs/SCARPE_FEATURES.md +38 -0
- data/docs/_config.yml +13 -0
- data/docs/calzini_components_and_updates.md +78 -0
- data/docs/display_service_separation.md +39 -0
- data/docs/documentation.md +43 -0
- data/docs/event_loops.md +66 -0
- data/docs/image.png +0 -0
- data/docs/index.md +118 -0
- data/docs/lacci.md +121 -0
- data/docs/scarpe_shoes_incompatibilities.md +71 -0
- data/docs/shoes_and_display_events.md +55 -0
- data/docs/shoes_implementations.md +79 -0
- data/docs/static/manual.md +5 -0
- data/docs/static/scarpe-logo.png +0 -0
- data/docs/timeouts_and_handlers.md +66 -0
- data/docs/web_archaeology.md +76 -0
- data/examples/Edit_box_Styles.rb +8 -0
- data/examples/Kerning.rb +7 -0
- data/examples/background_with_image.rb +14 -5
- data/examples/bloopsaphone/working/feepogram.rb +1 -1
- data/examples/bloopsaphone/working/le_dance_des_rubis.rb +135 -0
- data/examples/bloopsaphone/working/pixel_dreams_in_ruby.rb +131 -0
- data/examples/bloopsaphone/working/type_rebellion.rb +157 -0
- data/examples/border.rb +11 -0
- data/examples/check.rb +2 -0
- data/examples/download_and_show_image.rb +3 -0
- data/examples/flags/finland.rb +15 -0
- data/examples/flags/italy.rb +11 -0
- data/examples/flags/mauritius.rb +14 -0
- data/examples/font_family.rb +17 -0
- data/examples/font_shorthand.rb +9 -0
- data/examples/gen.rb +4 -0
- data/examples/internal_link_navigation.rb +19 -0
- data/examples/legacy/not_checked/shoes-manual/append.rb +10 -0
- data/examples/legacy/not_checked/shoes-manual/background_change.rb +12 -0
- data/examples/legacy/not_checked/shoes-manual/background_pattern.rb +5 -0
- data/examples/legacy/not_checked/shoes-manual/basic_app.rb +8 -0
- data/examples/legacy/not_checked/shoes-manual/border.rb +9 -0
- data/examples/legacy/not_checked/shoes-manual/builtins/FONTS.rb +5 -0
- data/examples/legacy/not_checked/shoes-manual/builtins/ask.rb +2 -0
- data/examples/legacy/not_checked/shoes-manual/builtins/ask_color.rb +5 -0
- data/examples/legacy/not_checked/shoes-manual/builtins/ask_open_file.rb +5 -0
- data/examples/legacy/not_checked/shoes-manual/builtins/ask_save_folder.rb +2 -0
- data/examples/legacy/not_checked/shoes-manual/builtins/confirm.rb +4 -0
- data/examples/legacy/not_checked/shoes-manual/builtins/debug.rb +2 -0
- data/examples/legacy/not_checked/shoes-manual/builtins/info.rb +3 -0
- data/examples/legacy/not_checked/shoes-manual/button.rb +9 -0
- data/examples/legacy/not_checked/shoes-manual/clear.rb +7 -0
- data/examples/legacy/not_checked/shoes-manual/custom_header.rb +13 -0
- data/examples/legacy/not_checked/shoes-manual/displace.rb +14 -0
- data/examples/legacy/not_checked/shoes-manual/edit_box.rb +8 -0
- data/examples/legacy/not_checked/shoes-manual/fill_pattern.rb +5 -0
- data/examples/legacy/not_checked/shoes-manual/fonts.rb +7 -0
- data/examples/legacy/not_checked/shoes-manual/gutter.rb +6 -0
- data/examples/legacy/not_checked/shoes-manual/image_web.rb +4 -0
- data/examples/legacy/not_checked/shoes-manual/keypress.rb +7 -0
- data/examples/legacy/not_checked/shoes-manual/list_box.rb +10 -0
- data/examples/legacy/not_checked/shoes-manual/motion.rb +10 -0
- data/examples/legacy/not_checked/shoes-manual/mouse.rb +8 -0
- data/examples/legacy/not_checked/shoes-manual/move.rb +14 -0
- data/examples/legacy/not_checked/shoes-manual/nested_ovals.rb +8 -0
- data/examples/legacy/not_checked/shoes-manual/oval.rb +7 -0
- data/examples/legacy/not_checked/shoes-manual/ovals.rb +6 -0
- data/examples/legacy/not_checked/shoes-manual/ovals_image.rb +8 -0
- data/examples/legacy/not_checked/shoes-manual/prepend.rb +7 -0
- data/examples/legacy/not_checked/shoes-manual/progress_bar.rb +10 -0
- data/examples/legacy/not_checked/shoes-manual/radio.rb +18 -0
- data/examples/legacy/not_checked/shoes-manual/radio_alternative_1.rb +7 -0
- data/examples/legacy/not_checked/shoes-manual/radio_alternative_2.rb +9 -0
- data/examples/legacy/not_checked/shoes-manual/rotate_rectangle.rb +6 -0
- data/examples/legacy/not_checked/shoes-manual/shape.rb +11 -0
- data/examples/legacy/not_checked/shoes-manual/static/avatar.png +0 -0
- data/examples/legacy/not_checked/shoes-manual/stroke.rb +5 -0
- data/examples/legacy/not_checked/shoes-manual/style.rb +3 -0
- data/examples/legacy/not_checked/shoes-manual/style_alternative_1.rb +4 -0
- data/examples/legacy/not_checked/shoes-manual/style_alternative_2.rb +5 -0
- data/examples/legacy/not_checked/shoes-manual/style_length.rb +5 -0
- data/examples/legacy/not_checked/shoes-manual/timer.rb +6 -0
- data/examples/legacy/not_checked/shoes-manual/trigger_window.rb +8 -0
- data/examples/legacy/not_checked/shoes-manual/window_owner.rb +8 -0
- data/examples/legacy/working/shoes_manual/alert_button.rb +2 -0
- data/examples/legacy/working/shoes_manual/animate.rb +7 -0
- data/examples/legacy/working/shoes_manual/background_para.rb +4 -0
- data/examples/legacy/working/shoes_manual/button_alternative.rb +7 -0
- data/examples/legacy/working/shoes_manual/checkbox.rb +17 -0
- data/examples/legacy/working/shoes_manual/download.rb +12 -0
- data/examples/legacy/working/shoes_manual/edit_box.rb +6 -0
- data/examples/legacy/working/shoes_manual/editline.rb +7 -0
- data/examples/legacy/working/shoes_manual/fixed_height.rb +8 -0
- data/examples/legacy/working/shoes_manual/fixed_width.rb +12 -0
- data/examples/legacy/working/shoes_manual/image.rb +5 -0
- data/examples/legacy/working/shoes_manual/instance_variable_check.rb +10 -0
- data/examples/legacy/working/shoes_manual/message.rb +18 -0
- data/examples/legacy/working/shoes_manual/rectangle.rb +6 -0
- data/examples/legacy/working/shoes_manual/save_download.rb +12 -0
- data/examples/legacy/working/shoes_manual/self_check.rb +10 -0
- data/examples/legacy/working/shoes_manual/stack.rb +7 -0
- data/examples/legacy/working/shoes_manual/style_info.rb +8 -0
- data/examples/legacy/working/shoes_manual/utf8_support.rb +8 -0
- data/examples/legacy/working/shoes_manual/width.rb +4 -0
- data/examples/local_assets/multi_image.rb +5 -0
- data/examples/local_assets/small.png +0 -0
- data/examples/local_fonts.rb +3 -0
- data/examples/margin.rb +13 -0
- data/examples/margin_check.rb +27 -0
- data/examples/oval-with-kwargs.rb +3 -0
- data/examples/oval.rb +26 -0
- data/examples/page_navigation_single_app.rb +42 -0
- data/examples/para_font_styles.rb +17 -0
- data/examples/para_font_variant.rb +6 -0
- data/examples/para_fontweight.rb +13 -0
- data/examples/parse_xl_funnies.rb +3 -0
- data/examples/rect.rb +1 -1
- data/examples/scarpe_ext.rb +3 -0
- data/examples/shapes/star.rb +1 -3
- data/examples/shoes_subclass_app.rb +25 -0
- data/examples/spacing.rb +1 -1
- data/examples/span.rb +4 -2
- data/examples/url_routing_example.rb +67 -0
- data/lacci/Gemfile +0 -2
- data/lacci/Gemfile.lock +4 -32
- data/lacci/lacci.gemspec +3 -3
- data/lacci/lib/lacci/scarpe_cli.rb +0 -1
- data/lacci/lib/lacci/version.rb +1 -1
- data/lacci/lib/scarpe/niente/app.rb +12 -1
- data/lacci/lib/scarpe/niente/display_service.rb +5 -1
- data/lacci/lib/scarpe/niente/drawable.rb +2 -0
- data/lacci/lib/scarpe/niente/shoes_spec.rb +10 -5
- data/lacci/lib/scarpe/niente.rb +15 -2
- data/lacci/lib/shoes/app.rb +204 -105
- data/lacci/lib/shoes/constants.rb +24 -2
- data/lacci/lib/shoes/display_service.rb +43 -4
- data/lacci/lib/shoes/drawable.rb +326 -36
- data/lacci/lib/shoes/drawables/arc.rb +4 -26
- data/lacci/lib/shoes/drawables/arrow.rb +3 -23
- data/lacci/lib/shoes/drawables/border.rb +28 -0
- data/lacci/lib/shoes/drawables/button.rb +5 -21
- data/lacci/lib/shoes/drawables/check.rb +7 -3
- data/lacci/lib/shoes/drawables/document_root.rb +4 -4
- data/lacci/lib/shoes/drawables/edit_box.rb +6 -5
- data/lacci/lib/shoes/drawables/edit_line.rb +5 -4
- data/lacci/lib/shoes/drawables/flow.rb +4 -6
- data/lacci/lib/shoes/drawables/font_helper.rb +62 -0
- data/lacci/lib/shoes/drawables/image.rb +2 -2
- data/lacci/lib/shoes/drawables/line.rb +3 -6
- data/lacci/lib/shoes/drawables/link.rb +16 -9
- data/lacci/lib/shoes/drawables/list_box.rb +8 -5
- data/lacci/lib/shoes/drawables/oval.rb +48 -0
- data/lacci/lib/shoes/drawables/para.rb +106 -18
- data/lacci/lib/shoes/drawables/progress.rb +2 -1
- data/lacci/lib/shoes/drawables/radio.rb +5 -3
- data/lacci/lib/shoes/drawables/rect.rb +7 -6
- data/lacci/lib/shoes/drawables/shape.rb +4 -3
- data/lacci/lib/shoes/drawables/slot.rb +102 -9
- data/lacci/lib/shoes/drawables/stack.rb +7 -12
- data/lacci/lib/shoes/drawables/star.rb +9 -31
- data/lacci/lib/shoes/drawables/text_drawable.rb +93 -34
- data/lacci/lib/shoes/drawables/video.rb +3 -2
- data/lacci/lib/shoes/drawables/widget.rb +9 -4
- data/lacci/lib/shoes/drawables.rb +2 -1
- data/lacci/lib/shoes/errors.rb +13 -3
- data/lacci/lib/shoes/margin_helper.rb +79 -0
- data/lacci/lib/shoes.rb +98 -20
- data/lacci/test/.gitignore +1 -0
- data/lacci/test/test_draw_context.rb +167 -0
- data/lacci/test/test_font_helper.rb +57 -0
- data/lacci/test/test_helper.rb +31 -4
- data/lacci/test/test_lacci.rb +93 -6
- data/lacci/test/test_margin_helper.rb +82 -0
- data/lacci/test/test_niente_test_infra.rb +40 -0
- data/lacci/test/test_oval.rb +82 -0
- data/lacci/test/test_parenting.rb +140 -0
- data/lacci/test/test_shoes_errors.rb +15 -13
- data/lacci/test/test_text_drawables.rb +23 -0
- data/lib/scarpe/assets.rb +19 -0
- data/lib/scarpe/cats_cradle.rb +57 -98
- data/lib/scarpe/shoes_spec.rb +24 -44
- data/lib/scarpe/version.rb +1 -1
- data/lib/scarpe/wv/app.rb +1 -0
- data/lib/scarpe/wv/arc.rb +0 -4
- data/lib/scarpe/wv/border.rb +15 -0
- data/lib/scarpe/wv/control_interface.rb +2 -10
- data/lib/scarpe/wv/document_root.rb +2 -2
- data/lib/scarpe/wv/drawable.rb +6 -40
- data/lib/scarpe/wv/edit_box.rb +4 -1
- data/lib/scarpe/wv/edit_line.rb +4 -1
- data/lib/scarpe/wv/image.rb +2 -5
- data/lib/scarpe/wv/link.rb +4 -2
- data/lib/scarpe/wv/oval.rb +13 -0
- data/lib/scarpe/wv/para.rb +1 -0
- data/lib/scarpe/wv/scarpe_extensions.rb +8 -0
- data/lib/scarpe/wv/shape.rb +10 -5
- data/lib/scarpe/wv/text_drawable.rb +72 -14
- data/lib/scarpe/wv/web_wrangler.rb +33 -11
- data/lib/scarpe/wv/webview_local_display.rb +6 -2
- data/lib/scarpe/wv.rb +16 -2
- data/scarpe-components/Gemfile +4 -3
- data/scarpe-components/Gemfile.lock +6 -37
- data/scarpe-components/README.md +2 -2
- data/scarpe-components/assets/bootstrap-themes/bootstrap-cerulean.css +12229 -0
- data/scarpe-components/assets/bootstrap-themes/bootstrap-cosmo.css +11810 -0
- data/scarpe-components/assets/bootstrap-themes/bootstrap-cyborg.css +12210 -0
- data/scarpe-components/assets/bootstrap-themes/bootstrap-darkly.css +12153 -0
- data/scarpe-components/assets/bootstrap-themes/bootstrap-flatly.css +12126 -0
- data/scarpe-components/assets/bootstrap-themes/bootstrap-icons.min.css +5 -0
- data/scarpe-components/assets/bootstrap-themes/bootstrap-journal.css +12099 -0
- data/scarpe-components/assets/bootstrap-themes/bootstrap-litera.css +12211 -0
- data/scarpe-components/assets/bootstrap-themes/bootstrap-lumen.css +12369 -0
- data/scarpe-components/assets/bootstrap-themes/bootstrap-lux.css +11928 -0
- data/scarpe-components/assets/bootstrap-themes/bootstrap-materia.css +13184 -0
- data/scarpe-components/assets/bootstrap-themes/bootstrap-minty.css +12177 -0
- data/scarpe-components/assets/bootstrap-themes/bootstrap-morph.css +12750 -0
- data/scarpe-components/assets/bootstrap-themes/bootstrap-pulse.css +11890 -0
- data/scarpe-components/assets/bootstrap-themes/bootstrap-quartz.css +12622 -0
- data/scarpe-components/assets/bootstrap-themes/bootstrap-sandstone.css +12201 -0
- data/scarpe-components/assets/bootstrap-themes/bootstrap-simplex.css +12186 -0
- data/scarpe-components/assets/bootstrap-themes/bootstrap-sketchy.css +12451 -0
- data/scarpe-components/assets/bootstrap-themes/bootstrap-slate.css +12492 -0
- data/scarpe-components/assets/bootstrap-themes/bootstrap-solar.css +12149 -0
- data/scarpe-components/assets/bootstrap-themes/bootstrap-spacelab.css +12266 -0
- data/scarpe-components/assets/bootstrap-themes/bootstrap-superhero.css +12216 -0
- data/scarpe-components/assets/bootstrap-themes/bootstrap-united.css +12077 -0
- data/scarpe-components/assets/bootstrap-themes/bootstrap-vapor.css +12549 -0
- data/scarpe-components/assets/bootstrap-themes/bootstrap-yeti.css +12325 -0
- data/scarpe-components/assets/bootstrap-themes/bootstrap-zephyr.css +12283 -0
- data/scarpe-components/assets/bootstrap-themes/bootstrap.bundle.min.js +7 -0
- data/scarpe-components/lib/scarpe/components/asset_server.rb +219 -0
- data/scarpe-components/lib/scarpe/components/base64.rb +22 -0
- data/scarpe-components/lib/scarpe/components/calzini/{art_widgets.rb → art_drawables.rb} +42 -18
- data/scarpe-components/lib/scarpe/components/calzini/border.rb +38 -0
- data/scarpe-components/lib/scarpe/components/calzini/button.rb +6 -8
- data/scarpe-components/lib/scarpe/components/calzini/misc.rb +14 -16
- data/scarpe-components/lib/scarpe/components/calzini/para.rb +218 -11
- data/scarpe-components/lib/scarpe/components/calzini/slots.rb +16 -60
- data/scarpe-components/lib/scarpe/components/calzini.rb +88 -1
- data/scarpe-components/lib/scarpe/components/errors.rb +4 -0
- data/scarpe-components/lib/scarpe/components/html.rb +4 -1
- data/scarpe-components/lib/scarpe/components/minitest_export_reporter.rb +11 -3
- data/scarpe-components/lib/scarpe/components/minitest_result.rb +41 -0
- data/scarpe-components/lib/scarpe/components/port_helpers.rb +30 -0
- data/scarpe-components/lib/scarpe/components/print_logger.rb +17 -2
- data/scarpe-components/lib/scarpe/components/process_helpers.rb +37 -0
- data/scarpe-components/lib/scarpe/components/segmented_file_loader.rb +1 -1
- data/scarpe-components/lib/scarpe/components/tiranti.rb +42 -100
- data/scarpe-components/lib/scarpe/components/unit_test_helpers.rb +3 -1
- data/scarpe-components/lib/scarpe/components/version.rb +1 -1
- data/scarpe-components/scarpe-components.gemspec +1 -1
- data/scarpe-components/test/assets/big-image.png +0 -0
- data/scarpe-components/test/assets/big-stylesheet.css +497 -0
- data/scarpe-components/test/assets/little-image.png +0 -0
- data/scarpe-components/test/assets/little-stylesheet.css +1 -0
- data/scarpe-components/test/calzini/test_calzini_art_drawables.rb +7 -7
- data/scarpe-components/test/calzini/test_calzini_button.rb +7 -5
- data/scarpe-components/test/calzini/test_calzini_misc.rb +9 -9
- data/scarpe-components/test/calzini/test_calzini_para.rb +6 -9
- data/scarpe-components/test/calzini/test_calzini_slots.rb +12 -57
- data/scarpe-components/test/calzini/test_calzini_text_drawables.rb +83 -18
- data/scarpe-components/test/calzini/test_various.rb +133 -0
- data/scarpe-components/test/test_asset_server.rb +72 -0
- data/scarpe-components/test/test_components.rb +31 -2
- data/scarpe-components/test/test_helper.rb +0 -1
- data/scarpe-components/test/test_minitest_result.rb +7 -0
- data/scarpe-components/test/test_port_helpers.rb +12 -0
- data/scarpe-components/test/test_segmented_app_files.rb +2 -0
- data/tasks/check_html_fixtures.rb +140 -0
- data/tasks/regenerate_html_fixtures.rb +104 -0
- data/templates/class_template_with_shapes.erb +0 -11
- metadata +225 -39
- data/.rubocop.yml +0 -88
- data/lacci/lib/scarpe/niente/logger.rb +0 -29
- data/lacci/lib/shoes/drawables/span.rb +0 -27
- data/lacci/lib/shoes/spacing.rb +0 -9
- data/lib/scarpe/evented_assertions.rb +0 -121
- data/lib/scarpe/wv/span.rb +0 -44
- data/scarpe-components/lib/scarpe/components/calzini/text_widgets.rb +0 -65
- /data/examples/legacy/{not_checked → working}/shoes3-tests/editline/editline.rb +0 -0
data/lacci/lib/shoes/app.rb
CHANGED
|
@@ -4,66 +4,93 @@ class Shoes
|
|
|
4
4
|
class App < Shoes::Drawable
|
|
5
5
|
include Shoes::Log
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
attr_accessor :instance
|
|
9
|
-
end
|
|
10
|
-
|
|
7
|
+
# The Shoes root of the drawable tree
|
|
11
8
|
attr_reader :document_root
|
|
12
9
|
|
|
13
|
-
|
|
10
|
+
# The application directory for this app. Often this will be the directory
|
|
11
|
+
# containing the launched application file.
|
|
12
|
+
attr_reader :dir
|
|
13
|
+
|
|
14
|
+
shoes_styles :title, :width, :height, :resizable, :features
|
|
15
|
+
|
|
16
|
+
# This is defined to avoid the linkable-id check in the Shoes-style method_missing def'n
|
|
17
|
+
attr_reader :features
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
# These are the allowed values for custom_event_loop events.
|
|
20
|
+
#
|
|
21
|
+
# * displaylib means the display library is not going to return from running the app
|
|
22
|
+
# * return means the display library will return and the loop will be handled outside Lacci's control
|
|
23
|
+
# * wait means Lacci should busy-wait and send eternal heartbeats from the "run" event
|
|
24
|
+
#
|
|
25
|
+
# If the display service grabs control and keeps it, Webview-style, that means "displaylib"
|
|
26
|
+
# should be the value. A Scarpe-Wasm-style "return" is appropriate if the code can finish
|
|
27
|
+
# without Ruby ending the process at the end of the source file. A "wait" can prevent Ruby
|
|
28
|
+
# from finishing early, but also prevents multiple applications. Only "return" will normally
|
|
29
|
+
# allow multiple Shoes applications.
|
|
30
|
+
CUSTOM_EVENT_LOOP_TYPES = %w[displaylib return wait]
|
|
16
31
|
|
|
32
|
+
class << self
|
|
33
|
+
attr_accessor :set_test_code
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
init_args
|
|
17
37
|
def initialize(
|
|
18
|
-
title:
|
|
38
|
+
title: 'Shoes!',
|
|
19
39
|
width: 480,
|
|
20
40
|
height: 420,
|
|
21
41
|
resizable: true,
|
|
42
|
+
features: [],
|
|
22
43
|
&app_code_body
|
|
23
44
|
)
|
|
24
|
-
log_init(
|
|
45
|
+
log_init('Shoes::App')
|
|
25
46
|
|
|
26
|
-
if Shoes::
|
|
27
|
-
|
|
28
|
-
raise Shoes::Errors::TooManyInstancesError, "Cannot create multiple Shoes::App objects!"
|
|
47
|
+
if Shoes::FEATURES.include?(:multi_app) || Shoes.APPS.empty?
|
|
48
|
+
Shoes.APPS.push self
|
|
29
49
|
else
|
|
30
|
-
Shoes::App
|
|
50
|
+
@log.error('Trying to create a second Shoes::App in the same process! Fail!')
|
|
51
|
+
raise Shoes::Errors::TooManyInstancesError, 'Cannot create multiple Shoes::App objects!'
|
|
31
52
|
end
|
|
32
53
|
|
|
33
|
-
|
|
34
|
-
@
|
|
54
|
+
# We cd to the app's containing dir when running the app
|
|
55
|
+
@dir = Dir.pwd
|
|
35
56
|
|
|
36
|
-
|
|
57
|
+
@do_shutdown = false
|
|
58
|
+
@event_loop_type = 'displaylib' # the default
|
|
37
59
|
|
|
38
|
-
|
|
39
|
-
# plus potentially other current state that changes from drawable
|
|
40
|
-
# to drawable and slot to slot.
|
|
41
|
-
@draw_context = {
|
|
42
|
-
"fill" => "",
|
|
43
|
-
"stroke" => "",
|
|
44
|
-
"rotate" => 0,
|
|
45
|
-
}
|
|
60
|
+
@features = features
|
|
46
61
|
|
|
47
|
-
|
|
48
|
-
|
|
62
|
+
unknown_ext = features - Shoes::FEATURES - Shoes::EXTENSIONS
|
|
63
|
+
unsupported_features = unknown_ext & Shoes::KNOWN_FEATURES
|
|
64
|
+
unless unsupported_features.empty?
|
|
65
|
+
@log.error("Shoes app requires feature(s) not supported by this display service: #{unsupported_features.inspect}!")
|
|
66
|
+
raise Shoes::Errors::UnsupportedFeatureError, "Shoes app needs features: #{unsupported_features.inspect}"
|
|
67
|
+
end
|
|
68
|
+
unless unknown_ext.empty?
|
|
69
|
+
@log.warn("Shoes app requested unknown features #{unknown_ext.inspect}! Known: #{(Shoes::FEATURES + Shoes::EXTENSIONS).inspect}")
|
|
70
|
+
end
|
|
49
71
|
|
|
50
72
|
@slots = []
|
|
51
73
|
|
|
74
|
+
@content_container = nil
|
|
75
|
+
|
|
76
|
+
@routes = {}
|
|
77
|
+
|
|
78
|
+
super
|
|
79
|
+
|
|
80
|
+
# This creates the DocumentRoot, including its corresponding display drawable
|
|
81
|
+
Drawable.with_current_app(self) do
|
|
82
|
+
@document_root = Shoes::DocumentRoot.new
|
|
83
|
+
end
|
|
84
|
+
|
|
52
85
|
# Now create the App display drawable
|
|
53
86
|
create_display_drawable
|
|
54
87
|
|
|
55
|
-
# Set up testing
|
|
56
|
-
if ENV["SCARPE_APP_TEST"]
|
|
57
|
-
test_code = File.read ENV["SCARPE_APP_TEST"]
|
|
58
|
-
if test_code != ""
|
|
59
|
-
@test_obj = Object.new
|
|
60
|
-
@test_obj.instance_eval test_code
|
|
61
|
-
end
|
|
62
|
-
end
|
|
88
|
+
# Set up testing *after* Display Service basic objects exist
|
|
63
89
|
|
|
64
|
-
if ENV[
|
|
65
|
-
test_code = File.read ENV[
|
|
90
|
+
if ENV['SHOES_SPEC_TEST'] && !Shoes::App.set_test_code
|
|
91
|
+
test_code = File.read ENV['SHOES_SPEC_TEST']
|
|
66
92
|
unless test_code.empty?
|
|
93
|
+
Shoes::App.set_test_code = true
|
|
67
94
|
Shoes::Spec.instance.run_shoes_spec_test_code test_code
|
|
68
95
|
end
|
|
69
96
|
end
|
|
@@ -72,30 +99,34 @@ class Shoes
|
|
|
72
99
|
|
|
73
100
|
# Try to de-dup as much as possible and not send repeat or multiple
|
|
74
101
|
# destroy events
|
|
75
|
-
@watch_for_destroy = bind_shoes_event(event_name:
|
|
102
|
+
@watch_for_destroy = bind_shoes_event(event_name: 'destroy') do
|
|
76
103
|
Shoes::DisplayService.unsub_from_events(@watch_for_destroy) if @watch_for_destroy
|
|
77
104
|
@watch_for_destroy = nil
|
|
78
|
-
|
|
105
|
+
destroy(send_event: false)
|
|
79
106
|
end
|
|
80
107
|
|
|
81
|
-
@watch_for_event_loop = bind_shoes_event(event_name:
|
|
82
|
-
|
|
108
|
+
@watch_for_event_loop = bind_shoes_event(event_name: 'custom_event_loop') do |loop_type|
|
|
109
|
+
unless CUSTOM_EVENT_LOOP_TYPES.include?(loop_type)
|
|
110
|
+
raise(Shoes::Errors::InvalidAttributeValueError,
|
|
111
|
+
"Unknown event loop type: #{loop_type.inspect}!")
|
|
112
|
+
end
|
|
83
113
|
|
|
84
114
|
@event_loop_type = loop_type
|
|
85
115
|
end
|
|
86
116
|
|
|
87
|
-
Signal.trap(
|
|
88
|
-
@log.warn(
|
|
117
|
+
Signal.trap('INT') do
|
|
118
|
+
@log.warn('App interrupted by signal, stopping...')
|
|
89
119
|
puts "\nStopping Shoes app..."
|
|
90
120
|
destroy
|
|
91
121
|
end
|
|
92
122
|
end
|
|
93
123
|
|
|
94
124
|
def init
|
|
95
|
-
send_shoes_event(event_name:
|
|
125
|
+
send_shoes_event(event_name: 'init')
|
|
96
126
|
return if @do_shutdown
|
|
97
127
|
|
|
98
|
-
|
|
128
|
+
with_slot(@document_root, &@app_code_body)
|
|
129
|
+
render_index_if_defined_on_first_boot
|
|
99
130
|
end
|
|
100
131
|
|
|
101
132
|
# "Container" drawables like flows, stacks, masks and the document root
|
|
@@ -119,7 +150,7 @@ class Shoes
|
|
|
119
150
|
return unless block_given?
|
|
120
151
|
|
|
121
152
|
push_slot(slot_item)
|
|
122
|
-
|
|
153
|
+
instance_eval(&block)
|
|
123
154
|
ensure
|
|
124
155
|
pop_slot
|
|
125
156
|
end
|
|
@@ -133,22 +164,19 @@ class Shoes
|
|
|
133
164
|
return super unless klass
|
|
134
165
|
|
|
135
166
|
::Shoes::App.define_method(name) do |*args, **kwargs, &block|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
unless klass.ancestors.include?(::Shoes::TextDrawable)
|
|
140
|
-
# Create this drawable in the current app slot
|
|
141
|
-
drawable_instance.set_parent ::Shoes::App.instance.current_slot
|
|
167
|
+
Drawable.with_current_app(self) do
|
|
168
|
+
klass.new(*args, **kwargs, &block)
|
|
142
169
|
end
|
|
143
|
-
|
|
144
|
-
drawable_instance
|
|
145
170
|
end
|
|
146
171
|
|
|
147
172
|
send(name, *args, **kwargs, &block)
|
|
148
173
|
end
|
|
149
174
|
|
|
175
|
+
# Get the current draw context for the current slot
|
|
176
|
+
#
|
|
177
|
+
# @return [Hash] a hash of Shoes styles for the current draw context
|
|
150
178
|
def current_draw_context
|
|
151
|
-
|
|
179
|
+
current_slot&.current_draw_context
|
|
152
180
|
end
|
|
153
181
|
|
|
154
182
|
# This usually doesn't return. The display service may take control
|
|
@@ -157,40 +185,39 @@ class Shoes
|
|
|
157
185
|
# want to (and/or can't) take control of the event loop.
|
|
158
186
|
def run
|
|
159
187
|
if @do_shutdown
|
|
160
|
-
|
|
188
|
+
warn 'Destroy has already been signaled, but we just called Shoes::App.run!'
|
|
161
189
|
return
|
|
162
190
|
end
|
|
163
191
|
|
|
164
192
|
# The display lib can send us an event to customise the event loop handling.
|
|
165
193
|
# But it must do so before the "run" event returns.
|
|
166
|
-
send_shoes_event(event_name:
|
|
194
|
+
send_shoes_event(event_name: 'run')
|
|
167
195
|
|
|
168
196
|
case @event_loop_type
|
|
169
|
-
when
|
|
197
|
+
when 'wait'
|
|
170
198
|
# Display lib wants us to busy-wait instead of it.
|
|
171
|
-
until @do_shutdown
|
|
172
|
-
|
|
173
|
-
end
|
|
174
|
-
when "displaylib"
|
|
199
|
+
Shoes::DisplayService.dispatch_event('heartbeat', nil) until @do_shutdown
|
|
200
|
+
when 'displaylib'
|
|
175
201
|
# If run event returned, that means we're done.
|
|
176
202
|
destroy
|
|
177
|
-
when
|
|
203
|
+
when 'return'
|
|
178
204
|
# We can just return to the main event loop. But we shouldn't call destroy.
|
|
179
205
|
# Presumably some event loop *outside* our event loop is handling things.
|
|
180
206
|
else
|
|
181
|
-
raise Shoes::Errors::InvalidAttributeValueError,
|
|
207
|
+
raise Shoes::Errors::InvalidAttributeValueError,
|
|
208
|
+
"Internal error! Incorrect event loop type: #{@event_loop_type.inspect}!"
|
|
182
209
|
end
|
|
183
210
|
end
|
|
184
211
|
|
|
185
212
|
def destroy(send_event: true)
|
|
186
213
|
@do_shutdown = true
|
|
187
|
-
send_shoes_event(event_name:
|
|
214
|
+
send_shoes_event(event_name: 'destroy') if send_event
|
|
188
215
|
end
|
|
189
216
|
|
|
190
217
|
def all_drawables
|
|
191
218
|
out = []
|
|
192
219
|
|
|
193
|
-
to_add = @document_root.children
|
|
220
|
+
to_add = [@document_root, @document_root.children]
|
|
194
221
|
until to_add.empty?
|
|
195
222
|
out.concat(to_add)
|
|
196
223
|
to_add = to_add.flat_map { |w| w.respond_to?(:children) ? w.children : [] }.compact
|
|
@@ -199,40 +226,52 @@ class Shoes
|
|
|
199
226
|
out
|
|
200
227
|
end
|
|
201
228
|
|
|
229
|
+
# We can add various ways to find drawables here.
|
|
230
|
+
# These are sort of like Shoes selectors, used for testing.
|
|
231
|
+
# This method finds a drawable across all active Shoes apps.
|
|
232
|
+
def self.find_drawables_by(*specs)
|
|
233
|
+
Shoes.APPS.flat_map do |app|
|
|
234
|
+
app.find_drawables_by(*specs)
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
202
238
|
# We can add various ways to find drawables here.
|
|
203
239
|
# These are sort of like Shoes selectors, used for testing.
|
|
204
240
|
def find_drawables_by(*specs)
|
|
205
241
|
drawables = all_drawables
|
|
206
242
|
specs.each do |spec|
|
|
207
243
|
if spec == Shoes::App
|
|
208
|
-
drawables = [
|
|
244
|
+
drawables = [@app]
|
|
209
245
|
elsif spec.is_a?(Class)
|
|
210
246
|
drawables.select! { |w| spec === w }
|
|
211
247
|
elsif spec.is_a?(Symbol) || spec.is_a?(String)
|
|
212
248
|
s = spec.to_s
|
|
213
249
|
case s[0]
|
|
214
|
-
when
|
|
250
|
+
when '$'
|
|
215
251
|
begin
|
|
216
252
|
# I'm not finding a global_variable_get or similar...
|
|
217
253
|
global_value = eval s
|
|
218
254
|
drawables &= [global_value]
|
|
219
255
|
rescue
|
|
220
|
-
raise Shoes::Errors::InvalidAttributeValueError, "Error getting global variable: #{spec.inspect}"
|
|
256
|
+
# raise Shoes::Errors::InvalidAttributeValueError, "Error getting global variable: #{spec.inspect}"
|
|
257
|
+
drawables = []
|
|
221
258
|
end
|
|
222
|
-
when
|
|
223
|
-
if
|
|
224
|
-
drawables &= [
|
|
259
|
+
when '@'
|
|
260
|
+
if @app.instance_variables.include?(spec.to_sym)
|
|
261
|
+
drawables &= [@app.instance_variable_get(spec)]
|
|
225
262
|
else
|
|
226
|
-
raise Shoes::Errors::InvalidAttributeValueError, "Can't find top-level instance variable: #{spec.inspect}!"
|
|
263
|
+
# raise Shoes::Errors::InvalidAttributeValueError, "Can't find top-level instance variable: #{spec.inspect}!"
|
|
264
|
+
drawables = []
|
|
227
265
|
end
|
|
228
266
|
else
|
|
229
|
-
|
|
230
|
-
find_id = Integer(s[3..-1])
|
|
231
|
-
drawable = Shoes::Drawable.drawable_by_id(find_id)
|
|
232
|
-
drawables &= [drawable]
|
|
233
|
-
else
|
|
267
|
+
unless s.start_with?('id:')
|
|
234
268
|
raise Shoes::Errors::InvalidAttributeValueError, "Don't know how to find drawables by #{spec.inspect}!"
|
|
235
269
|
end
|
|
270
|
+
|
|
271
|
+
find_id = Integer(s[3..-1])
|
|
272
|
+
drawable = Shoes::Drawable.drawable_by_id(find_id)
|
|
273
|
+
drawables &= [drawable]
|
|
274
|
+
|
|
236
275
|
end
|
|
237
276
|
else
|
|
238
277
|
raise(Shoes::Errors::InvalidAttributeValueError, "Don't know how to find drawables by #{spec.inspect}!")
|
|
@@ -240,11 +279,67 @@ class Shoes
|
|
|
240
279
|
end
|
|
241
280
|
drawables
|
|
242
281
|
end
|
|
282
|
+
|
|
283
|
+
def page(name, &block)
|
|
284
|
+
@pages ||= {}
|
|
285
|
+
@pages[name] = proc do
|
|
286
|
+
stack(width: 1.0, height: 1.0) do
|
|
287
|
+
instance_eval(&block)
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
def visit(name_or_path)
|
|
293
|
+
# First, check for exact page match (symbol)
|
|
294
|
+
if @pages && @pages[name_or_path]
|
|
295
|
+
@document_root.clear do
|
|
296
|
+
instance_eval(&@pages[name_or_path])
|
|
297
|
+
end
|
|
298
|
+
return
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
# Second, check URL routes
|
|
302
|
+
route, method_name = @routes.find { |r, _| r === name_or_path }
|
|
303
|
+
if route
|
|
304
|
+
@document_root.clear do
|
|
305
|
+
if route.is_a?(Regexp)
|
|
306
|
+
match_data = route.match(name_or_path)
|
|
307
|
+
send(method_name, *match_data.captures)
|
|
308
|
+
else
|
|
309
|
+
send(method_name)
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
return
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
# Third, if it's a string path like "/page2", try matching page :page2
|
|
316
|
+
if name_or_path.is_a?(String) && name_or_path.start_with?("/")
|
|
317
|
+
page_name = name_or_path[1..-1].to_sym # "/page2" -> :page2
|
|
318
|
+
if @pages && @pages[page_name]
|
|
319
|
+
@document_root.clear do
|
|
320
|
+
instance_eval(&@pages[page_name])
|
|
321
|
+
end
|
|
322
|
+
return
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
puts "Error: URL '#{name_or_path}' not found"
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
def url(path, method_name)
|
|
330
|
+
if path.is_a?(String) && path.include?('(')
|
|
331
|
+
# Convert string patterns to regex
|
|
332
|
+
regex = Regexp.new("^#{path.gsub(/\(.*?\)/, '(.*?)')}$")
|
|
333
|
+
@routes[regex] = method_name
|
|
334
|
+
else
|
|
335
|
+
@routes[path] = method_name
|
|
336
|
+
end
|
|
337
|
+
end
|
|
243
338
|
end
|
|
244
339
|
end
|
|
245
340
|
|
|
246
341
|
# Event handler DSLs get defined in both App and Slot - same code, slightly different results
|
|
247
|
-
events = [
|
|
342
|
+
events = %i[motion hover leave click release keypress animate every timer]
|
|
248
343
|
events.each do |event|
|
|
249
344
|
Shoes::App.define_method(event) do |*args, &block|
|
|
250
345
|
subscription_item(args:, shoes_api_name: event.to_s, &block)
|
|
@@ -256,54 +351,58 @@ end
|
|
|
256
351
|
|
|
257
352
|
# These methods will need to be defined on Slots too, but probably need a rework in general.
|
|
258
353
|
class Shoes::App < Shoes::Drawable
|
|
354
|
+
# This is going to go away. See issue #496
|
|
259
355
|
def background(...)
|
|
260
356
|
current_slot.background(...)
|
|
261
357
|
end
|
|
262
358
|
|
|
359
|
+
# This is going to go away. See issue #498
|
|
263
360
|
def border(...)
|
|
264
361
|
current_slot.border(...)
|
|
265
362
|
end
|
|
266
363
|
|
|
267
|
-
# Draw
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
def nofill
|
|
274
|
-
@draw_context["fill"] = ""
|
|
275
|
-
end
|
|
276
|
-
|
|
277
|
-
def stroke(color)
|
|
278
|
-
@draw_context["stroke"] = color
|
|
279
|
-
end
|
|
280
|
-
|
|
281
|
-
def nostroke
|
|
282
|
-
@draw_context["stroke"] = ""
|
|
364
|
+
# Draw Context methods -- forward to the current slot
|
|
365
|
+
%i[fill nofill stroke strokewidth nostroke rotate].each do |dc_method|
|
|
366
|
+
define_method(dc_method) do |*args|
|
|
367
|
+
current_slot.send(dc_method, *args)
|
|
368
|
+
end
|
|
283
369
|
end
|
|
284
370
|
|
|
285
371
|
# Shape DSL methods
|
|
286
372
|
|
|
287
373
|
def move_to(x, y)
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
current_slot.add_shape_command(["move_to", x, y])
|
|
374
|
+
unless x.is_a?(Numeric) && y.is_a?(Numeric)
|
|
375
|
+
raise(Shoes::Errors::InvalidAttributeValueError,
|
|
376
|
+
'Pass only Numeric arguments to move_to!')
|
|
292
377
|
end
|
|
378
|
+
|
|
379
|
+
return unless current_slot.is_a?(::Shoes::Shape)
|
|
380
|
+
|
|
381
|
+
current_slot.add_shape_command(['move_to', x, y])
|
|
293
382
|
end
|
|
294
383
|
|
|
295
384
|
def line_to(x, y)
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
current_slot.add_shape_command(["line_to", x, y])
|
|
385
|
+
unless x.is_a?(Numeric) && y.is_a?(Numeric)
|
|
386
|
+
raise(Shoes::Errors::InvalidAttributeValueError,
|
|
387
|
+
'Pass only Numeric arguments to line_to!')
|
|
300
388
|
end
|
|
301
|
-
end
|
|
302
389
|
|
|
303
|
-
|
|
304
|
-
|
|
390
|
+
return unless current_slot.is_a?(::Shoes::Shape)
|
|
391
|
+
|
|
392
|
+
current_slot.add_shape_command(['line_to', x, y])
|
|
305
393
|
end
|
|
394
|
+
|
|
306
395
|
# Not implemented yet: curve_to, arc_to
|
|
307
396
|
|
|
308
|
-
|
|
397
|
+
alias info puts
|
|
398
|
+
|
|
399
|
+
private
|
|
400
|
+
|
|
401
|
+
def render_index_if_defined_on_first_boot
|
|
402
|
+
return if @first_boot_finished
|
|
403
|
+
|
|
404
|
+
visit('/') if @routes['/'] == :index
|
|
405
|
+
|
|
406
|
+
@first_boot_finished = true
|
|
407
|
+
end
|
|
309
408
|
end
|
|
@@ -13,10 +13,10 @@ class Shoes
|
|
|
13
13
|
[ENV["LOCALAPPDATA"], "Shoes"],
|
|
14
14
|
[ENV["APPDATA"], "Shoes"],
|
|
15
15
|
[ENV["HOME"], ".shoes"],
|
|
16
|
-
[Dir.tmpdir, "shoes"],
|
|
17
16
|
]
|
|
18
17
|
|
|
19
18
|
top, file = homes.detect { |home_top, _| home_top && File.exist?(home_top) }
|
|
19
|
+
return nil if top.nil?
|
|
20
20
|
File.join(top, file)
|
|
21
21
|
end
|
|
22
22
|
|
|
@@ -32,8 +32,30 @@ class Shoes
|
|
|
32
32
|
HALF_PI = 1.57079632679489661923
|
|
33
33
|
PI = 3.14159265358979323846
|
|
34
34
|
|
|
35
|
-
#
|
|
35
|
+
# These should be set up by the Display Service when it loads. They are intentionally
|
|
36
|
+
# *not* frozen so that the Display Service can add to them (and then optionally
|
|
37
|
+
# freeze them.)
|
|
38
|
+
|
|
39
|
+
# Fonts currently loaded and available
|
|
36
40
|
FONTS = []
|
|
41
|
+
|
|
42
|
+
# Standard features available in this display service - see KNOWN_FEATURES.
|
|
43
|
+
# These may or may not require the Shoes.app requesting them per-app.
|
|
44
|
+
FEATURES = []
|
|
45
|
+
|
|
46
|
+
# Nonstandard extensions, e.g. Scarpe extensions, supported by this display lib.
|
|
47
|
+
# An application may have to request the extensions for them to be available so
|
|
48
|
+
# that a casual reader can see Shoes.app(features: :scarpe) and realize why
|
|
49
|
+
# there are nonstandard styles or drawables.
|
|
50
|
+
EXTENSIONS = []
|
|
51
|
+
|
|
52
|
+
# These are all known features supported by this version of Lacci.
|
|
53
|
+
# Features on this list are allowed to be in FEATURES. Anything else
|
|
54
|
+
# goes in EXTENSIONS and is nonstandard.
|
|
55
|
+
KNOWN_FEATURES = [
|
|
56
|
+
:html, # Supports .to_html on display objects, HTML classes on drawables, etc.
|
|
57
|
+
:multi_app, # Supports multiple applications at once
|
|
58
|
+
].freeze
|
|
37
59
|
end
|
|
38
60
|
|
|
39
61
|
# Access and assign the release constants
|
|
@@ -32,7 +32,14 @@ class Shoes
|
|
|
32
32
|
# This is in the eigenclass/metaclass, *not* instances of DisplayService
|
|
33
33
|
include Shoes::Log
|
|
34
34
|
|
|
35
|
+
# Send a Shoes event to all subscribers.
|
|
35
36
|
# An event_target may be nil, to indicate there is no target.
|
|
37
|
+
#
|
|
38
|
+
# @param event_name [String] the name of the event
|
|
39
|
+
# @param event_target [String] the specific target, if any
|
|
40
|
+
# @param args [Array] arguments to pass to the subscribing block
|
|
41
|
+
# @param args [Array] keyword arguments to pass to the subscribing block
|
|
42
|
+
# @return [void]
|
|
36
43
|
def dispatch_event(event_name, event_target, *args, **kwargs)
|
|
37
44
|
@@display_event_handlers ||= {}
|
|
38
45
|
|
|
@@ -69,10 +76,20 @@ class Shoes
|
|
|
69
76
|
kwargs[:event_name] = event_name
|
|
70
77
|
kwargs[:event_target] = event_target if event_target
|
|
71
78
|
handlers.each { |h| h[:handler].call(*args, **kwargs) }
|
|
79
|
+
nil
|
|
72
80
|
end
|
|
73
81
|
|
|
74
|
-
#
|
|
75
|
-
#
|
|
82
|
+
# Subscribe to the given event name and target.
|
|
83
|
+
# It's permitted to subscribe to event_name :any for all event names,
|
|
84
|
+
# and event_target :any for all targets. An event_target of nil means
|
|
85
|
+
# "no target", and only matches events dispatched with a nil target.
|
|
86
|
+
# The subscription will return an unsubscribe ID, which can be used
|
|
87
|
+
# later to unsubscribe from the notification.
|
|
88
|
+
#
|
|
89
|
+
# @param event_name [String,Symbol] the event name to subscribe to, or :any for all event names
|
|
90
|
+
# @param event_target [String,Symbol,NilClass] the event target to subscribe to, or :any for all targets - nil is a valid target
|
|
91
|
+
# @block the block to call when the event occurs - it will receive arguments from the event-dispatch call
|
|
92
|
+
# @return [Integer] an unsubscription ID which can be used later to cancel the subscription
|
|
76
93
|
def subscribe_to_event(event_name, event_target, &handler)
|
|
77
94
|
@@display_event_handlers ||= {}
|
|
78
95
|
@@display_event_unsub_id ||= 0
|
|
@@ -96,6 +113,10 @@ class Shoes
|
|
|
96
113
|
id
|
|
97
114
|
end
|
|
98
115
|
|
|
116
|
+
# Unsubscribe from any event subscriptions matching the unsub ID.
|
|
117
|
+
#
|
|
118
|
+
# @param unsub_id [Integer] the unsub ID returned when subscribing
|
|
119
|
+
# @return [void]
|
|
99
120
|
def unsub_from_events(unsub_id)
|
|
100
121
|
raise "Must provide an unsubscribe ID!" if unsub_id.nil?
|
|
101
122
|
|
|
@@ -106,17 +127,32 @@ class Shoes
|
|
|
106
127
|
end
|
|
107
128
|
end
|
|
108
129
|
|
|
130
|
+
# Reset the display service, for instance between unit tests.
|
|
131
|
+
# This destroys all existing subscriptions.
|
|
132
|
+
#
|
|
133
|
+
# @return [void]
|
|
109
134
|
def full_reset!
|
|
110
135
|
@@display_event_handlers = {}
|
|
111
136
|
@json_debug_serialize = nil
|
|
112
137
|
end
|
|
113
138
|
|
|
139
|
+
# Set the Display Service class which will handle display service functions
|
|
140
|
+
# for this process. This can only be set once. The display service can be
|
|
141
|
+
# a subclass of Shoes::DisplayService, but isn't required to be.
|
|
142
|
+
#
|
|
143
|
+
# Shoes will create an instance of this class with no arguments passed to
|
|
144
|
+
# initialize, and use it as the display service for the lifetime of the
|
|
145
|
+
# process.
|
|
146
|
+
#
|
|
147
|
+
# @param klass [Class] the class for the display service
|
|
114
148
|
def set_display_service_class(klass)
|
|
115
149
|
raise "Can only set a single display service class!" if @display_service_klass
|
|
116
150
|
|
|
117
151
|
@display_service_klass = klass
|
|
118
152
|
end
|
|
119
153
|
|
|
154
|
+
# Get the current display service instance. This requires a display service
|
|
155
|
+
# class having been set first. @see set_display_service_class
|
|
120
156
|
def display_service
|
|
121
157
|
return @service if @service
|
|
122
158
|
|
|
@@ -126,9 +162,13 @@ class Shoes
|
|
|
126
162
|
end
|
|
127
163
|
end
|
|
128
164
|
|
|
165
|
+
def initialize
|
|
166
|
+
@display_drawable_for = {}
|
|
167
|
+
end
|
|
168
|
+
|
|
129
169
|
# These methods are an interface to DisplayService objects.
|
|
130
170
|
|
|
131
|
-
def create_display_drawable_for(drawable_class_name, drawable_id, properties, is_widget:)
|
|
171
|
+
def create_display_drawable_for(drawable_class_name, drawable_id, properties, parent_id:, is_widget:)
|
|
132
172
|
raise "Override in DisplayService implementation!"
|
|
133
173
|
end
|
|
134
174
|
|
|
@@ -174,7 +214,6 @@ class Shoes
|
|
|
174
214
|
def initialize(linkable_id: object_id)
|
|
175
215
|
@linkable_id = linkable_id
|
|
176
216
|
@subscriptions = {}
|
|
177
|
-
@display_drawable_for ||= {}
|
|
178
217
|
end
|
|
179
218
|
|
|
180
219
|
def send_self_event(*args, event_name:, **kwargs)
|