scarpe 0.2.1 → 0.2.2
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/.rubocop.yml +4 -0
- data/.yardopts +11 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +112 -0
- data/README.md +31 -24
- data/Rakefile +13 -1
- data/docs/yard/catscradle.md +44 -0
- data/docs/yard/template/default/fulldoc/html/setup.rb +13 -0
- data/docs/yard/template/default/layout/html/setup.rb +9 -0
- data/examples/background_with_image.rb +16 -0
- data/examples/bloopsaphone/working/bronx_army_knife.rb +66 -0
- data/examples/bloopsaphone/working/morning_serenity.rb +21 -0
- data/examples/bloopsaphone/working/simpsons_theme_song_by_why.rb +6 -4
- data/examples/button_go_away.rb +1 -1
- data/examples/check.rb +18 -0
- data/examples/clear_and_append.rb +24 -0
- data/examples/download_and_show_image.rb +28 -0
- data/examples/edit_box.rb +3 -5
- data/examples/fonts.rb +2 -2
- data/examples/get_headers.rb +10 -0
- data/examples/highlander.rb +2 -0
- data/examples/link.rb +2 -2
- data/examples/local_fonts.rb +4 -0
- data/examples/local_images.rb +4 -0
- data/examples/motion_events.rb +20 -0
- data/examples/parse_xl_funnies.rb +58 -0
- data/examples/radio/radio.rb +16 -0
- data/examples/radio/radio_groups.rb +18 -0
- data/examples/radio/radio_same_slot.rb +6 -0
- data/examples/ruby_racer.rb +13 -15
- data/examples/selfitude.rb +18 -0
- data/examples/shapes/shapes_fill.rb +4 -3
- data/examples/shoes_school.rb +2 -4
- data/examples/show_hide.rb +6 -0
- data/examples/skip_ci/change_my_audio_source.rb +21 -0
- data/examples/skip_ci/guitar_fretboard.rb +137 -0
- data/examples/video.rb +10 -0
- data/exe/scarpe +42 -66
- data/fonts/Pacifico.ttf +0 -0
- data/lacci/Gemfile +22 -0
- data/lacci/Gemfile.lock +72 -0
- data/lacci/Rakefile +12 -0
- data/lacci/lacci.gemspec +37 -0
- data/lacci/lib/lacci/scarpe_cli.rb +70 -0
- data/lacci/lib/lacci/scarpe_core.rb +21 -0
- data/lacci/lib/lacci/version.rb +13 -0
- data/lacci/lib/shoes/app.rb +264 -0
- data/{lib/scarpe → lacci/lib/shoes}/background.rb +1 -1
- data/{lib/scarpe → lacci/lib/shoes}/border.rb +1 -1
- data/{lib/scarpe → lacci/lib/shoes}/colors.rb +1 -1
- data/lacci/lib/shoes/constants.rb +29 -0
- data/{lib/scarpe → lacci/lib/shoes}/display_service.rb +40 -45
- data/lacci/lib/shoes/download.rb +123 -0
- data/lacci/lib/shoes/log.rb +71 -0
- data/lacci/lib/shoes/spacing.rb +9 -0
- data/{lib/scarpe → lacci/lib/shoes}/widget.rb +63 -43
- data/{lib/scarpe → lacci/lib/shoes/widgets}/alert.rb +3 -3
- data/{lib/scarpe → lacci/lib/shoes/widgets}/arc.rb +7 -5
- data/{lib/scarpe → lacci/lib/shoes/widgets}/button.rb +3 -3
- data/lacci/lib/shoes/widgets/check.rb +28 -0
- data/lacci/lib/shoes/widgets/document_root.rb +20 -0
- data/{lib/scarpe → lacci/lib/shoes/widgets}/edit_box.rb +10 -5
- data/{lib/scarpe → lacci/lib/shoes/widgets}/edit_line.rb +2 -2
- data/lacci/lib/shoes/widgets/flow.rb +22 -0
- data/lacci/lib/shoes/widgets/font.rb +14 -0
- data/{lib/scarpe → lacci/lib/shoes/widgets}/image.rb +3 -7
- data/lacci/lib/shoes/widgets/line.rb +18 -0
- data/{lib/scarpe → lacci/lib/shoes/widgets}/link.rb +2 -2
- data/{lib/scarpe → lacci/lib/shoes/widgets}/list_box.rb +2 -2
- data/{lib/scarpe → lacci/lib/shoes/widgets}/para.rb +4 -26
- data/lacci/lib/shoes/widgets/radio.rb +35 -0
- data/lacci/lib/shoes/widgets/shape.rb +37 -0
- data/lacci/lib/shoes/widgets/slot.rb +75 -0
- data/{lib/scarpe → lacci/lib/shoes/widgets}/span.rb +2 -2
- data/lacci/lib/shoes/widgets/stack.rb +24 -0
- data/{lib/scarpe → lacci/lib/shoes/widgets}/star.rb +6 -9
- data/lacci/lib/shoes/widgets/subscription_item.rb +60 -0
- data/lacci/lib/shoes/widgets/text_widget.rb +51 -0
- data/lacci/lib/shoes/widgets/video.rb +15 -0
- data/lacci/lib/shoes/widgets.rb +29 -0
- data/lacci/lib/shoes.rb +127 -0
- data/lacci/test/test_colors.rb +39 -0
- data/lacci/test/test_helper.rb +9 -0
- data/lacci/test/test_lacci.rb +9 -0
- data/lib/scarpe/cats_cradle.rb +249 -0
- data/lib/scarpe/evented_assertions.rb +88 -0
- data/lib/scarpe/version.rb +1 -1
- data/lib/scarpe/wv/alert.rb +3 -2
- data/lib/scarpe/wv/app.rb +30 -8
- data/lib/scarpe/wv/arc.rb +5 -6
- data/lib/scarpe/wv/background.rb +10 -1
- data/lib/scarpe/wv/border.rb +5 -3
- data/lib/scarpe/wv/button.rb +11 -9
- data/lib/scarpe/wv/check.rb +29 -0
- data/lib/scarpe/wv/control_interface.rb +14 -20
- data/lib/scarpe/wv/control_interface_test.rb +13 -28
- data/lib/scarpe/wv/document_root.rb +3 -45
- data/lib/scarpe/wv/edit_box.rb +5 -7
- data/lib/scarpe/wv/edit_line.rb +2 -2
- data/lib/scarpe/wv/flow.rb +10 -20
- data/lib/scarpe/wv/font.rb +36 -0
- data/lib/scarpe/wv/html.rb +3 -2
- data/lib/scarpe/wv/image.rb +7 -2
- data/lib/scarpe/wv/line.rb +4 -7
- data/lib/scarpe/wv/link.rb +1 -0
- data/lib/scarpe/wv/list_box.rb +3 -3
- data/lib/scarpe/wv/para.rb +16 -14
- data/lib/scarpe/wv/radio.rb +34 -0
- data/lib/scarpe/wv/shape.rb +44 -8
- data/lib/scarpe/wv/slot.rb +81 -0
- data/lib/scarpe/wv/spacing.rb +1 -1
- data/lib/scarpe/wv/span.rb +10 -8
- data/lib/scarpe/wv/stack.rb +10 -30
- data/lib/scarpe/wv/star.rb +11 -12
- data/lib/scarpe/wv/subscription_item.rb +50 -0
- data/lib/scarpe/wv/video.rb +34 -0
- data/lib/scarpe/wv/web_wrangler.rb +238 -58
- data/lib/scarpe/wv/webview_local_display.rb +27 -5
- data/lib/scarpe/wv/webview_relay_display.rb +18 -119
- data/lib/scarpe/wv/webview_relay_util.rb +143 -0
- data/lib/scarpe/wv/widget.rb +80 -11
- data/lib/scarpe/wv/wv_display_worker.rb +17 -4
- data/lib/scarpe/wv.rb +33 -4
- data/lib/scarpe/wv_local.rb +1 -1
- data/lib/scarpe/wv_relay.rb +1 -1
- data/lib/scarpe.rb +3 -32
- data/scarpe-components/.gitignore +1 -0
- data/scarpe-components/Gemfile +22 -0
- data/scarpe-components/README.md +35 -0
- data/scarpe-components/Rakefile +12 -0
- data/scarpe-components/lib/scarpe/components/base64.rb +29 -0
- data/scarpe-components/lib/scarpe/components/file_helpers.rb +65 -0
- data/scarpe-components/lib/scarpe/components/modular_logger.rb +113 -0
- data/scarpe-components/lib/scarpe/components/print_logger.rb +43 -0
- data/{lib/scarpe → scarpe-components/lib/scarpe/components}/promises.rb +102 -35
- data/scarpe-components/lib/scarpe/components/segmented_file_loader.rb +170 -0
- data/scarpe-components/lib/scarpe/components/unit_test_helpers.rb +217 -0
- data/scarpe-components/lib/scarpe/components/version.rb +7 -0
- data/scarpe-components/scarpe-components.gemspec +38 -0
- data/scarpe-components/test/test_components.rb +9 -0
- data/scarpe-components/test/test_helper.rb +23 -0
- data/scarpe-components/test/test_promises.rb +260 -0
- data/scarpe-components/test/test_segmented_app_files.rb +182 -0
- data/{lib/scarpe → spikes}/glibui/widget.rb +2 -2
- data/{lib/scarpe → spikes}/glibui.rb +1 -1
- data/templates/basic_class_template.erb +1 -1
- data/templates/class_template_with_event_bind.erb +1 -1
- data/templates/class_template_with_shapes.erb +1 -1
- data/templates/webview_template.erb +0 -3
- metadata +151 -118
- data/examples/fill.rb +0 -25
- data/examples/legacy/not_checked/shoes-contrib/basic/class-book.yaml +0 -387
- data/examples/legacy/not_checked/shoes-contrib/good/good-clock.rb +0 -51
- data/examples/legacy/not_checked/shoes-contrib/good/good-follow.rb +0 -26
- data/examples/legacy/not_checked/shoes-contrib/good/good-reminder.rb +0 -174
- data/examples/legacy/not_checked/shoes-contrib/good/good-vjot.rb +0 -56
- data/examples/legacy/not_checked/shoes-contrib/simple/simple-timer.rb +0 -13
- data/examples/legacy/not_checked/shoes-dep-samples/good-clock.rb +0 -51
- data/examples/legacy/not_checked/shoes-dep-samples/good-follow.rb +0 -26
- data/examples/legacy/not_checked/shoes-dep-samples/good-reminder.rb +0 -174
- data/examples/legacy/not_checked/shoes-dep-samples/good-vjot.rb +0 -56
- data/examples/legacy/not_checked/shoes-dep-samples/simple-accordion.rb +0 -75
- data/examples/legacy/not_checked/shoes-dep-samples/simple-anim-shapes.rb +0 -17
- data/examples/legacy/not_checked/shoes-dep-samples/simple-anim-text.rb +0 -13
- data/examples/legacy/not_checked/shoes-dep-samples/simple-arc.rb +0 -23
- data/examples/legacy/not_checked/shoes-dep-samples/simple-bounce.rb +0 -24
- data/examples/legacy/not_checked/shoes-dep-samples/simple-calc.rb +0 -70
- data/examples/legacy/not_checked/shoes-dep-samples/simple-chipmunk.rb +0 -26
- data/examples/legacy/not_checked/shoes-dep-samples/simple-control-sizes.rb +0 -24
- data/examples/legacy/not_checked/shoes-dep-samples/simple-curve.rb +0 -26
- data/examples/legacy/not_checked/shoes-dep-samples/simple-dialogs.rb +0 -29
- data/examples/legacy/not_checked/shoes-dep-samples/simple-draw.rb +0 -13
- data/examples/legacy/not_checked/shoes-dep-samples/simple-editor.rb +0 -28
- data/examples/legacy/not_checked/shoes-dep-samples/simple-form.rb +0 -28
- data/examples/legacy/not_checked/shoes-dep-samples/simple-form.shy +0 -0
- data/examples/legacy/not_checked/shoes-dep-samples/simple-mask.rb +0 -21
- data/examples/legacy/not_checked/shoes-dep-samples/simple-menu.rb +0 -31
- data/examples/legacy/not_checked/shoes-dep-samples/simple-menu1.rb +0 -35
- data/examples/legacy/not_checked/shoes-dep-samples/simple-rubygems.rb +0 -29
- data/examples/legacy/not_checked/shoes-dep-samples/simple-slide.rb +0 -45
- data/examples/legacy/not_checked/shoes-dep-samples/simple-sphere.rb +0 -28
- data/examples/legacy/not_checked/shoes-dep-samples/simple-sqlite3.rb +0 -13
- data/examples/legacy/not_checked/shoes-dep-samples/simple-timer.rb +0 -13
- data/examples/legacy/not_checked/shoes-dep-samples/simple-video.rb +0 -13
- data/examples/legacy/not_checked/simple/anim-text.rb +0 -13
- data/examples/legacy/not_checked/simple/arc.rb +0 -23
- data/examples/legacy/not_checked/simple/bounce.rb +0 -24
- data/examples/legacy/not_checked/simple/chipmunk.rb +0 -26
- data/examples/legacy/not_checked/simple/curve.rb +0 -26
- data/examples/legacy/not_checked/simple/dialogs.rb +0 -29
- data/examples/legacy/not_checked/simple/downloader.rb +0 -40
- data/examples/legacy/not_checked/simple/draw.rb +0 -13
- data/examples/legacy/not_checked/simple/mask.rb +0 -21
- data/examples/legacy/not_checked/simple/slide.rb +0 -45
- data/examples/legacy/not_checked/simple/sphere.rb +0 -28
- data/lib/constants.rb +0 -5
- data/lib/scarpe/app.rb +0 -78
- data/lib/scarpe/document_root.rb +0 -20
- data/lib/scarpe/fill.rb +0 -23
- data/lib/scarpe/flow.rb +0 -19
- data/lib/scarpe/line.rb +0 -25
- data/lib/scarpe/logger.rb +0 -155
- data/lib/scarpe/shape.rb +0 -19
- data/lib/scarpe/spacing.rb +0 -9
- data/lib/scarpe/stack.rb +0 -70
- data/lib/scarpe/text_widget.rb +0 -42
- data/lib/scarpe/unit_test_helpers.rb +0 -163
- data/lib/scarpe/widgets.rb +0 -30
- data/lib/scarpe/wv/fill.rb +0 -30
- data/lib/scarpe/wv/shape_helper.rb +0 -44
- data/scarpe-0.2.0.gem +0 -0
- /data/{lib/scarpe → spikes}/glibui/README.md +0 -0
- /data/{lib/scarpe → spikes}/glibui/alert.rb +0 -0
- /data/{lib/scarpe → spikes}/glibui/app.rb +0 -0
- /data/{lib/scarpe → spikes}/glibui/background.rb +0 -0
- /data/{lib/scarpe → spikes}/glibui/border.rb +0 -0
- /data/{lib/scarpe → spikes}/glibui/button.rb +0 -0
- /data/{lib/scarpe → spikes}/glibui/dimensions.rb +0 -0
- /data/{lib/scarpe → spikes}/glibui/document_root.rb +0 -0
- /data/{lib/scarpe → spikes}/glibui/edit_box.rb +0 -0
- /data/{lib/scarpe → spikes}/glibui/edit_line.rb +0 -0
- /data/{lib/scarpe → spikes}/glibui/flow.rb +0 -0
- /data/{lib/scarpe → spikes}/glibui/html.rb +0 -0
- /data/{lib/scarpe → spikes}/glibui/image.rb +0 -0
- /data/{lib/scarpe → spikes}/glibui/link.rb +0 -0
- /data/{lib/scarpe → spikes}/glibui/local_display.rb +0 -0
- /data/{lib/scarpe → spikes}/glibui/para.rb +0 -0
- /data/{lib/scarpe → spikes}/glibui/spacing.rb +0 -0
- /data/{lib/scarpe → spikes}/glibui/stack.rb +0 -0
- /data/{lib/scarpe → spikes}/glibui/text_widget.rb +0 -0
- /data/{lib/scarpe → spikes}/libui/alert.rb +0 -0
- /data/{lib/scarpe → spikes}/libui/button.rb +0 -0
- /data/{lib/scarpe → spikes}/libui/colors.rb +0 -0
- /data/{lib/scarpe → spikes}/libui/core.rb +0 -0
- /data/{lib/scarpe → spikes}/libui/flow.rb +0 -0
- /data/{lib/scarpe → spikes}/libui/libui.rb +0 -0
- /data/{lib/scarpe → spikes}/libui/notepad.md +0 -0
- /data/{lib/scarpe → spikes}/libui/para.rb +0 -0
- /data/{lib/scarpe → spikes}/libui/stack.rb +0 -0
|
@@ -1,24 +1,36 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class Scarpe
|
|
4
|
+
# This is the simplest type of Webview DisplayService. It creates Webview widgets
|
|
5
|
+
# corresponding to Shoes widgets, manages the Webview and its DOM tree, and
|
|
6
|
+
# generally keeps the Shoes/Webview connection working.
|
|
7
|
+
#
|
|
4
8
|
# This is an in-process Webview-based display service, with all the limitations that
|
|
5
9
|
# entails. Slow handlers will crash, ending this display service will end the
|
|
6
10
|
# process, too many or too large evals can crash the process, etc.
|
|
7
|
-
#
|
|
11
|
+
# Frequently it's better to use a RelayDisplayService to a second
|
|
8
12
|
# process containing one of these.
|
|
9
|
-
class WebviewDisplayService <
|
|
10
|
-
include
|
|
13
|
+
class WebviewDisplayService < Shoes::DisplayService
|
|
14
|
+
include Shoes::Log
|
|
11
15
|
|
|
12
16
|
class << self
|
|
13
17
|
attr_accessor :instance
|
|
14
18
|
end
|
|
15
19
|
|
|
16
|
-
#
|
|
20
|
+
# The ControlInterface is used to handle internal events in Webview Scarpe
|
|
17
21
|
attr_reader :control_interface
|
|
22
|
+
|
|
23
|
+
# The DocumentRoot is the top widget of the Webview-side widget tree
|
|
18
24
|
attr_reader :doc_root
|
|
25
|
+
|
|
26
|
+
# app is the Scarpe::WebviewApp
|
|
27
|
+
attr_reader :app
|
|
28
|
+
|
|
29
|
+
# wrangler is the Scarpe::WebWrangler
|
|
19
30
|
attr_reader :wrangler
|
|
20
31
|
|
|
21
|
-
# This is called before any of the various WebviewWidgets are created
|
|
32
|
+
# This is called before any of the various WebviewWidgets are created, to be
|
|
33
|
+
# able to create them and look them up.
|
|
22
34
|
def initialize
|
|
23
35
|
if WebviewDisplayService.instance
|
|
24
36
|
raise "ERROR! This is meant to be a singleton!"
|
|
@@ -32,6 +44,13 @@ class Scarpe
|
|
|
32
44
|
@display_widget_for = {}
|
|
33
45
|
end
|
|
34
46
|
|
|
47
|
+
# Create a Webview display widget for a specific Shoes widget, and pair it with
|
|
48
|
+
# the linkable ID for this Shoes widget.
|
|
49
|
+
#
|
|
50
|
+
# @param widget_class_name [String] The class name of the Shoes widget, e.g. Shoes::Button
|
|
51
|
+
# @param widget_id [String] the linkable ID for widget events
|
|
52
|
+
# @param properties [Hash] a JSON-serialisable Hash with the widget's display properties
|
|
53
|
+
# @return [WebviewWidget] the newly-created Webview widget
|
|
35
54
|
def create_display_widget_for(widget_class_name, widget_id, properties)
|
|
36
55
|
if widget_class_name == "App"
|
|
37
56
|
unless @doc_root
|
|
@@ -64,6 +83,9 @@ class Scarpe
|
|
|
64
83
|
display_widget
|
|
65
84
|
end
|
|
66
85
|
|
|
86
|
+
# Destroy the display service and the app. Quit the process (eventually.)
|
|
87
|
+
#
|
|
88
|
+
# @return [void]
|
|
67
89
|
def destroy
|
|
68
90
|
@app.destroy
|
|
69
91
|
WebviewDisplayService.instance = nil
|
|
@@ -3,129 +3,24 @@
|
|
|
3
3
|
require "socket"
|
|
4
4
|
require "rbconfig"
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
class AppShutdownError < Scarpe::Error; end
|
|
8
|
-
|
|
9
|
-
module WVRelayUtil # Make sure the including class also includes Scarpe::Log
|
|
10
|
-
def ready_to_read?(timeout = 0.0)
|
|
11
|
-
r, _, e = IO.select [@from], [], [@from, @to].uniq, timeout
|
|
12
|
-
|
|
13
|
-
# On timeout, select returns nil instead of arrays.
|
|
14
|
-
return if r.nil?
|
|
15
|
-
|
|
16
|
-
unless e.empty?
|
|
17
|
-
raise "#{@i_am}: Got error on connection(s) from IO.select! Dying!"
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
!r.empty?
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def send_datagram(contents)
|
|
24
|
-
str_data = JSON.dump contents
|
|
25
|
-
dgram_str = (str_data.length.to_s + "a" + str_data).encode(Encoding::BINARY)
|
|
26
|
-
to_write = dgram_str.bytesize
|
|
27
|
-
written = 0
|
|
28
|
-
|
|
29
|
-
until written == to_write
|
|
30
|
-
count = @to.write(dgram_str.byteslice(written..-1))
|
|
31
|
-
if count.nil? || count == 0
|
|
32
|
-
raise "Something was wrong in send_datagram! Write returned #{count.inspect}!"
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
written += count
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
nil
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def receive_datagram
|
|
42
|
-
@readbuf ||= String.new.encode(Encoding::BINARY)
|
|
43
|
-
to_read = nil
|
|
44
|
-
|
|
45
|
-
loop do
|
|
46
|
-
# Have we read a packet length already, sitting in @readbuf?
|
|
47
|
-
a_idx = @readbuf.index("a")
|
|
48
|
-
if a_idx
|
|
49
|
-
to_read = @readbuf[0..a_idx].to_i
|
|
50
|
-
@readbuf = @readbuf[(a_idx + 1)..-1]
|
|
51
|
-
break
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# If not, read more bytes
|
|
55
|
-
new_bytes = @from.read(10)
|
|
56
|
-
if new_bytes.nil?
|
|
57
|
-
# This is perfectly normal, if the connection closed
|
|
58
|
-
raise AppShutdownError, "Got an unexpected EOF reading datagram! " +
|
|
59
|
-
"Did the #{@i_am == :child ? "parent" : "child"} process die?"
|
|
60
|
-
end
|
|
61
|
-
@readbuf << new_bytes
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
loop do
|
|
65
|
-
if @readbuf.bytesize >= to_read
|
|
66
|
-
out = @readbuf.byteslice(0, to_read)
|
|
67
|
-
@readbuf = @readbuf.byteslice(to_read, -1)
|
|
68
|
-
return out
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
new_bytes = @from.read(to_read - @readbuf.bytesize)
|
|
72
|
-
@readbuf << new_bytes
|
|
73
|
-
end
|
|
74
|
-
rescue
|
|
75
|
-
raise AppShutdownError, "Got exception #{$!.class} when receiving datagram... #{$!.inspect}"
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def respond_to_datagram
|
|
79
|
-
message = receive_datagram
|
|
80
|
-
m_data = JSON.parse(message)
|
|
81
|
-
|
|
82
|
-
if m_data["type"] == "event"
|
|
83
|
-
kwargs_hash = {}
|
|
84
|
-
m_data["kwargs"].each { |k, v| kwargs_hash[k.to_sym] = v }
|
|
85
|
-
send_shoes_event(
|
|
86
|
-
*m_data["args"],
|
|
87
|
-
event_name: m_data["kwargs"]["event_name"],
|
|
88
|
-
target: m_data["kwargs"]["event_target"],
|
|
89
|
-
**kwargs_hash,
|
|
90
|
-
)
|
|
91
|
-
elsif m_data["type"] == "create"
|
|
92
|
-
raise "Parent process should never receive :create datagram!" if @i_am == :parent
|
|
6
|
+
require_relative "webview_relay_util"
|
|
93
7
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
def event_loop_for(t = 1.5)
|
|
108
|
-
t_start = Time.now
|
|
109
|
-
delay_time = t
|
|
110
|
-
|
|
111
|
-
while Time.now - t_start < delay_time
|
|
112
|
-
if ready_to_read?(0.1)
|
|
113
|
-
respond_to_datagram
|
|
114
|
-
else
|
|
115
|
-
sleep 0.1
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
# This "display service" actually creates a child process and sends events
|
|
122
|
-
# back and forth, but creates no widgets of its own.
|
|
123
|
-
class WVRelayDisplayService < Scarpe::DisplayService
|
|
124
|
-
include Scarpe::Log
|
|
125
|
-
include WVRelayUtil # Needs Scarpe::Log
|
|
8
|
+
class Scarpe
|
|
9
|
+
# This display service creates a child process and sends events
|
|
10
|
+
# back and forth, but creates no widgets of its own. The child
|
|
11
|
+
# process will spawn a worker with its own WebviewDisplayService
|
|
12
|
+
# where the real Webview exists. By splitting the Webview
|
|
13
|
+
# process from the Shoes widgets, it can be easier to return
|
|
14
|
+
# control to Webview's event handler promptly. Also, the Ruby
|
|
15
|
+
# process could run background threads if it wanted, and
|
|
16
|
+
# otherwise behave like a process ***not*** containing Webview.
|
|
17
|
+
class WVRelayDisplayService < Shoes::DisplayService
|
|
18
|
+
include Shoes::Log
|
|
19
|
+
include WVRelayUtil # Needs Shoes::Log
|
|
126
20
|
|
|
127
21
|
attr_accessor :shutdown
|
|
128
22
|
|
|
23
|
+
# Create a Webview Relay Display Service
|
|
129
24
|
def initialize
|
|
130
25
|
super()
|
|
131
26
|
log_init("WV::RelayDisplayService")
|
|
@@ -158,6 +53,7 @@ class Scarpe
|
|
|
158
53
|
end
|
|
159
54
|
end
|
|
160
55
|
|
|
56
|
+
# Run, sending and responding to datagrams continuously.
|
|
161
57
|
def run_event_loop
|
|
162
58
|
until @shutdown
|
|
163
59
|
respond_to_datagram while ready_to_read?
|
|
@@ -169,11 +65,14 @@ class Scarpe
|
|
|
169
65
|
self.destroy
|
|
170
66
|
end
|
|
171
67
|
|
|
68
|
+
# This method sends a message to the worker process to create a widget. No actual
|
|
69
|
+
# widget is created or registered with the display service.
|
|
172
70
|
def create_display_widget_for(widget_class_name, widget_id, properties)
|
|
173
71
|
send_datagram({ type: :create, class_name: widget_class_name, id: widget_id, properties: })
|
|
174
72
|
# Don't need to return anything. It wouldn't be used anyway.
|
|
175
73
|
end
|
|
176
74
|
|
|
75
|
+
# Tell the worker process to quit, and set a flag telling the event loop to shut down.
|
|
177
76
|
def destroy
|
|
178
77
|
unless @shutdown
|
|
179
78
|
send_datagram({ type: :destroy })
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "socket"
|
|
4
|
+
|
|
5
|
+
class Scarpe
|
|
6
|
+
# An error occurred which would normally be handled by shutting down the app
|
|
7
|
+
class AppShutdownError < Scarpe::Error; end
|
|
8
|
+
|
|
9
|
+
# WVRelayUtil defines the datagram format for the sockets that connect a parent
|
|
10
|
+
# Shoes application with a child display server.
|
|
11
|
+
#
|
|
12
|
+
# The class including this module should also include Shoes::Log so that it can
|
|
13
|
+
# be used.
|
|
14
|
+
module WVRelayUtil
|
|
15
|
+
# Checks whether the internal socket is ready to be read from.
|
|
16
|
+
# If timeout is greater than 0, this will block for up to that long.
|
|
17
|
+
#
|
|
18
|
+
# @param timeout [Float] the longest to wait for more input to read
|
|
19
|
+
# @return [Boolean] whether the socket has data ready for reading
|
|
20
|
+
def ready_to_read?(timeout = 0.0)
|
|
21
|
+
r, _, e = IO.select [@from], [], [@from, @to].uniq, timeout
|
|
22
|
+
|
|
23
|
+
# On timeout, select returns nil instead of arrays.
|
|
24
|
+
return if r.nil?
|
|
25
|
+
|
|
26
|
+
unless e.empty?
|
|
27
|
+
raise "#{@i_am}: Got error on connection(s) from IO.select! Dying!"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
!r.empty?
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Send bytes on the internal socket to the opposite side.
|
|
34
|
+
#
|
|
35
|
+
# @param contents [String] data to send
|
|
36
|
+
# @return [void]
|
|
37
|
+
def send_datagram(contents)
|
|
38
|
+
str_data = JSON.dump contents
|
|
39
|
+
dgram_str = (str_data.length.to_s + "a" + str_data).encode(Encoding::BINARY)
|
|
40
|
+
to_write = dgram_str.bytesize
|
|
41
|
+
written = 0
|
|
42
|
+
|
|
43
|
+
until written == to_write
|
|
44
|
+
count = @to.write(dgram_str.byteslice(written..-1))
|
|
45
|
+
if count.nil? || count == 0
|
|
46
|
+
raise "Something was wrong in send_datagram! Write returned #{count.inspect}!"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
written += count
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
nil
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Read data from the internal socket. Read until a whole datagram
|
|
56
|
+
# has been received and then return it.
|
|
57
|
+
#
|
|
58
|
+
# @return [String] the received datagram
|
|
59
|
+
def receive_datagram
|
|
60
|
+
@readbuf ||= String.new.encode(Encoding::BINARY)
|
|
61
|
+
to_read = nil
|
|
62
|
+
|
|
63
|
+
loop do
|
|
64
|
+
# Have we read a packet length already, sitting in @readbuf?
|
|
65
|
+
a_idx = @readbuf.index("a")
|
|
66
|
+
if a_idx
|
|
67
|
+
to_read = @readbuf[0..a_idx].to_i
|
|
68
|
+
@readbuf = @readbuf[(a_idx + 1)..-1]
|
|
69
|
+
break
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# If not, read more bytes
|
|
73
|
+
new_bytes = @from.read(10)
|
|
74
|
+
if new_bytes.nil?
|
|
75
|
+
# This is perfectly normal, if the connection closed
|
|
76
|
+
raise AppShutdownError, "Got an unexpected EOF reading datagram! " +
|
|
77
|
+
"Did the #{@i_am == :child ? "parent" : "child"} process die?"
|
|
78
|
+
end
|
|
79
|
+
@readbuf << new_bytes
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
loop do
|
|
83
|
+
if @readbuf.bytesize >= to_read
|
|
84
|
+
out = @readbuf.byteslice(0, to_read)
|
|
85
|
+
@readbuf = @readbuf.byteslice(to_read, -1)
|
|
86
|
+
return out
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
new_bytes = @from.read(to_read - @readbuf.bytesize)
|
|
90
|
+
@readbuf << new_bytes
|
|
91
|
+
end
|
|
92
|
+
rescue
|
|
93
|
+
raise AppShutdownError, "Got exception #{$!.class} when receiving datagram... #{$!.inspect}"
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Read a datagram from the internal buffer and then dispatch it to the
|
|
97
|
+
# appropriate handler.
|
|
98
|
+
def respond_to_datagram
|
|
99
|
+
message = receive_datagram
|
|
100
|
+
m_data = JSON.parse(message)
|
|
101
|
+
|
|
102
|
+
if m_data["type"] == "event"
|
|
103
|
+
kwargs_hash = {}
|
|
104
|
+
m_data["kwargs"].each { |k, v| kwargs_hash[k.to_sym] = v }
|
|
105
|
+
send_shoes_event(
|
|
106
|
+
*m_data["args"],
|
|
107
|
+
event_name: m_data["kwargs"]["event_name"],
|
|
108
|
+
target: m_data["kwargs"]["event_target"],
|
|
109
|
+
**kwargs_hash,
|
|
110
|
+
)
|
|
111
|
+
elsif m_data["type"] == "create"
|
|
112
|
+
raise "Parent process should never receive :create datagram!" if @i_am == :parent
|
|
113
|
+
|
|
114
|
+
@wv_display.create_display_widget_for(m_data["class_name"], m_data["id"], m_data["properties"])
|
|
115
|
+
elsif m_data["type"] == "destroy"
|
|
116
|
+
if @i_am == :parent
|
|
117
|
+
@shutdown = true
|
|
118
|
+
else
|
|
119
|
+
@log.info("Shutting down...")
|
|
120
|
+
exit 0
|
|
121
|
+
end
|
|
122
|
+
else
|
|
123
|
+
@log.error("Unrecognized datagram type:event: #{m_data.inspect}!")
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Loop for up to `t` seconds, reading data and waiting.
|
|
128
|
+
#
|
|
129
|
+
# @param t [Float] the number of seconds to loop for
|
|
130
|
+
def event_loop_for(t = 1.5)
|
|
131
|
+
t_start = Time.now
|
|
132
|
+
delay_time = t
|
|
133
|
+
|
|
134
|
+
while Time.now - t_start < delay_time
|
|
135
|
+
if ready_to_read?(0.1)
|
|
136
|
+
respond_to_datagram
|
|
137
|
+
else
|
|
138
|
+
sleep 0.1
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
data/lib/scarpe/wv/widget.rb
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class Scarpe
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
# The WebviewWidget parent class helps connect a Webview widget with
|
|
5
|
+
# its Shoes equivalent, render itself to the Webview DOM, handle
|
|
6
|
+
# Javascript events and generally keep things working in Webview.
|
|
7
|
+
class WebviewWidget < Shoes::Linkable
|
|
8
|
+
include Shoes::Log
|
|
6
9
|
|
|
7
10
|
class << self
|
|
11
|
+
# Return the corresponding Webview class for a particular Shoes class name
|
|
8
12
|
def display_class_for(scarpe_class_name)
|
|
9
|
-
scarpe_class =
|
|
10
|
-
unless scarpe_class.ancestors.include?(
|
|
11
|
-
raise "Scarpe Webview can only get display classes for
|
|
13
|
+
scarpe_class = Shoes.const_get(scarpe_class_name)
|
|
14
|
+
unless scarpe_class.ancestors.include?(Shoes::Linkable)
|
|
15
|
+
raise "Scarpe Webview can only get display classes for Shoes " +
|
|
12
16
|
"linkable widgets, not #{scarpe_class_name.inspect}!"
|
|
13
17
|
end
|
|
14
18
|
|
|
@@ -21,10 +25,17 @@ class Scarpe
|
|
|
21
25
|
end
|
|
22
26
|
end
|
|
23
27
|
|
|
28
|
+
# The Shoes ID corresponding to the Shoes widget for this Webview widget
|
|
24
29
|
attr_reader :shoes_linkable_id
|
|
30
|
+
|
|
31
|
+
# The WebviewWidget parent of this widget
|
|
25
32
|
attr_reader :parent
|
|
33
|
+
|
|
34
|
+
# An array of WebviewWidget children (possibly empty) of this widget
|
|
26
35
|
attr_reader :children
|
|
27
36
|
|
|
37
|
+
# Set instance variables for the display properties of this widget. Bind Shoes
|
|
38
|
+
# events for changes of parent widget and changes of property values.
|
|
28
39
|
def initialize(properties)
|
|
29
40
|
log_init("WV::Widget")
|
|
30
41
|
|
|
@@ -64,17 +75,42 @@ class Scarpe
|
|
|
64
75
|
super(linkable_id: @shoes_linkable_id)
|
|
65
76
|
end
|
|
66
77
|
|
|
67
|
-
#
|
|
78
|
+
# Properties_changed will be called automatically when properties change.
|
|
79
|
+
# The widget should delete any changes from the Hash that it knows how
|
|
80
|
+
# to incrementally handle, and pass the rest to super. If any changes
|
|
81
|
+
# go entirely un-handled, a full redraw will be scheduled.
|
|
82
|
+
# This exists to be overridden by children watching for changes.
|
|
83
|
+
#
|
|
84
|
+
# @param changes [Hash] a Hash of new values for properties that have changed
|
|
68
85
|
def properties_changed(changes)
|
|
86
|
+
# If a widget does something really nonstandard with its html_id or element, it will
|
|
87
|
+
# need to override to prevent this from happening. That's easy enough, though.
|
|
88
|
+
if changes.key?("hidden")
|
|
89
|
+
hidden = changes.delete("hidden")
|
|
90
|
+
if hidden
|
|
91
|
+
html_element.set_style("display", "none")
|
|
92
|
+
else
|
|
93
|
+
new_style = style # Get current display CSS property, which may vary by subclass
|
|
94
|
+
disp = new_style[:display]
|
|
95
|
+
html_element.set_style("display", disp || "block")
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
69
99
|
needs_update! unless changes.empty?
|
|
70
100
|
end
|
|
71
101
|
|
|
102
|
+
# Give this widget a new parent, including managing the appropriate child lists for parent widgets.
|
|
72
103
|
def set_parent(new_parent)
|
|
73
104
|
@parent&.remove_child(self)
|
|
74
105
|
new_parent&.add_child(self)
|
|
75
106
|
@parent = new_parent
|
|
76
107
|
end
|
|
77
108
|
|
|
109
|
+
# A shorter inspect text for prettier irb output
|
|
110
|
+
def inspect
|
|
111
|
+
"#<#{self.class}:#{self.object_id} @shoes_linkable_id=#{@shoes_linkable_id} @parent=#{@parent.inspect} @children=#{@children.inspect}>"
|
|
112
|
+
end
|
|
113
|
+
|
|
78
114
|
protected
|
|
79
115
|
|
|
80
116
|
# Do not call directly, use set_parent
|
|
@@ -122,24 +158,43 @@ class Scarpe
|
|
|
122
158
|
"#%0.2X%0.2X%0.2X" % [r_int, g_int, b_int]
|
|
123
159
|
end
|
|
124
160
|
|
|
161
|
+
# CSS styles
|
|
162
|
+
def style
|
|
163
|
+
styles = {}
|
|
164
|
+
if @hidden
|
|
165
|
+
styles[:display] = "none"
|
|
166
|
+
end
|
|
167
|
+
styles
|
|
168
|
+
end
|
|
169
|
+
|
|
125
170
|
public
|
|
126
171
|
|
|
127
|
-
# This gets a mini-webview for just this element and its children, if any
|
|
172
|
+
# This gets a mini-webview for just this element and its children, if any.
|
|
173
|
+
# It is normally called by the widget itself to do its DOM management.
|
|
174
|
+
#
|
|
175
|
+
# @return [Scarpe::WebWrangler::ElementWrangler] a DOM object manager
|
|
128
176
|
def html_element
|
|
129
|
-
@elt_wrangler ||=
|
|
177
|
+
@elt_wrangler ||= Scarpe::WebWrangler::ElementWrangler.new(html_id)
|
|
130
178
|
end
|
|
131
179
|
|
|
132
180
|
# Return a promise that guarantees all currently-requested changes have completed
|
|
181
|
+
#
|
|
182
|
+
# @return [Scarpe::Promise] a promise that will be fulfilled when all pending changes have finished
|
|
133
183
|
def promise_update
|
|
134
184
|
html_element.promise_update
|
|
135
185
|
end
|
|
136
186
|
|
|
187
|
+
# Get the object's HTML ID
|
|
188
|
+
#
|
|
189
|
+
# @return [String] the HTML ID
|
|
137
190
|
def html_id
|
|
138
191
|
object_id.to_s
|
|
139
192
|
end
|
|
140
193
|
|
|
141
194
|
# to_html is intended to get the HTML DOM rendering of this object and its children.
|
|
142
195
|
# Calling it should be side-effect-free and NOT update the webview.
|
|
196
|
+
#
|
|
197
|
+
# @return [String] the rendered HTML
|
|
143
198
|
def to_html
|
|
144
199
|
@children ||= []
|
|
145
200
|
child_markup = @children.map(&:to_html).join
|
|
@@ -150,27 +205,41 @@ class Scarpe
|
|
|
150
205
|
end
|
|
151
206
|
end
|
|
152
207
|
|
|
153
|
-
# This binds a Scarpe JS callback, handled via a single dispatch point in the
|
|
208
|
+
# This binds a Scarpe JS callback, handled via a single dispatch point in the app
|
|
209
|
+
#
|
|
210
|
+
# @param event [String] the Scarpe widget event name
|
|
211
|
+
# @yield the block to call when the event occurs
|
|
154
212
|
def bind(event, &block)
|
|
155
213
|
raise("Widget has no linkable_id! #{inspect}") unless linkable_id
|
|
156
214
|
|
|
157
|
-
WebviewDisplayService.instance.
|
|
215
|
+
WebviewDisplayService.instance.app.bind("#{linkable_id}-#{event}", &block)
|
|
158
216
|
end
|
|
159
217
|
|
|
160
218
|
# Removes the element from both the Ruby Widget tree and the HTML DOM.
|
|
161
219
|
# Return a promise for when that HTML change will be visible.
|
|
220
|
+
#
|
|
221
|
+
# @return [Scarpe::Promise] a promise that is fulfilled when the HTML change is complete
|
|
162
222
|
def destroy_self
|
|
163
223
|
@parent&.remove_child(self)
|
|
164
224
|
html_element.remove
|
|
165
225
|
end
|
|
166
226
|
|
|
227
|
+
# Request a full redraw of all widgets.
|
|
228
|
+
#
|
|
167
229
|
# It's really hard to do dirty-tracking here because the redraws are fully asynchronous.
|
|
168
230
|
# And so we can't easily cancel one "in flight," and we can't easily pick up the latest
|
|
169
231
|
# changes... And we probably don't want to, because we may be halfway through a batch.
|
|
232
|
+
#
|
|
233
|
+
# @return [void]
|
|
170
234
|
def needs_update!
|
|
171
|
-
WebviewDisplayService.instance.
|
|
235
|
+
WebviewDisplayService.instance.app.request_redraw!
|
|
172
236
|
end
|
|
173
237
|
|
|
238
|
+
# Generate JS code to trigger a specific event name on this widget with the supplies arguments.
|
|
239
|
+
#
|
|
240
|
+
# @param handler_function_name [String] the event name - @see #bind
|
|
241
|
+
# @param args [Array] additional arguments that will be passed to the event in the generated JS
|
|
242
|
+
# @return [String] the generated JS code
|
|
174
243
|
def handler_js_code(handler_function_name, *args)
|
|
175
244
|
raise("Widget has no linkable_id! #{inspect}") unless linkable_id
|
|
176
245
|
|
|
@@ -7,9 +7,12 @@ require "socket"
|
|
|
7
7
|
SCARPE_DIR = File.join(__dir__, "../..")
|
|
8
8
|
|
|
9
9
|
$LOAD_PATH.prepend(SCARPE_DIR)
|
|
10
|
+
ENV["SCARPE_DISPLAY_SERVICE"] = "wv_local"
|
|
10
11
|
require "scarpe"
|
|
11
12
|
require "scarpe/wv_local"
|
|
12
13
|
|
|
14
|
+
require_relative "webview_relay_util"
|
|
15
|
+
|
|
13
16
|
# This script exists to create a WebviewDisplayService that can be operated remotely over a socket.
|
|
14
17
|
|
|
15
18
|
if ARGV.length != 1
|
|
@@ -17,12 +20,22 @@ if ARGV.length != 1
|
|
|
17
20
|
exit(-1)
|
|
18
21
|
end
|
|
19
22
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
# This is the implementation of a freestanding Scarpe Webview display server,
|
|
24
|
+
# which connects via sockets and sends events and properties back and forth
|
|
25
|
+
# with a display-less Shoes app. The interface is designed to allow fork-based
|
|
26
|
+
# usage, where a parent process could create a paired sockets and start the
|
|
27
|
+
# child server. It can also be used via TCP sockets or similar, where a single
|
|
28
|
+
# socket is both input and output.
|
|
29
|
+
class Scarpe::Webview::ContainedService < Shoes::Linkable
|
|
30
|
+
include Shoes::Log
|
|
31
|
+
include Scarpe::WVRelayUtil # Needs Shoes::Log
|
|
23
32
|
|
|
24
33
|
attr_reader :log
|
|
25
34
|
|
|
35
|
+
# Create a new DisplayService.
|
|
36
|
+
#
|
|
37
|
+
# @param from [Socket] a readable socket to get input from the Shoes process
|
|
38
|
+
# @param to [Socket] a writable socket on which to send output to the Shoes process
|
|
26
39
|
def initialize(from, to)
|
|
27
40
|
super()
|
|
28
41
|
log_init("WV::DisplayWorker")
|
|
@@ -60,6 +73,6 @@ end
|
|
|
60
73
|
|
|
61
74
|
s = TCPSocket.new("localhost", ARGV[0].to_i)
|
|
62
75
|
|
|
63
|
-
SERVICE =
|
|
76
|
+
SERVICE = Scarpe::Webview::ContainedService.new(s, s)
|
|
64
77
|
|
|
65
78
|
SERVICE.log.info("Finished event loop. Exiting!")
|
data/lib/scarpe/wv.rb
CHANGED
|
@@ -2,29 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
# Scarpe Webview Display Services
|
|
4
4
|
|
|
5
|
+
# This file is for everything that should be included by *both* wv_local and wv_relay
|
|
6
|
+
|
|
7
|
+
require "securerandom"
|
|
8
|
+
require "json"
|
|
9
|
+
|
|
10
|
+
require "bloops"
|
|
11
|
+
require "scarpe/components/modular_logger"
|
|
12
|
+
require "scarpe/components/promises"
|
|
13
|
+
|
|
14
|
+
# Module to contain the various Scarpe Webview classes
|
|
15
|
+
module Scarpe::Webview; end
|
|
16
|
+
|
|
17
|
+
# Set up hierarchical logging using the SCARPE_LOG_CONFIG var for configuration
|
|
18
|
+
log_config = if ENV["SCARPE_LOG_CONFIG"]
|
|
19
|
+
JSON.load_file(ENV["SCARPE_LOG_CONFIG"])
|
|
20
|
+
else
|
|
21
|
+
ENV["SCARPE_DEBUG"] ? Shoes::Log::DEFAULT_DEBUG_LOG_CONFIG : Shoes::Log::DEFAULT_LOG_CONFIG
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
Shoes::Log.instance = Scarpe::Components::ModularLogImpl.new
|
|
25
|
+
Shoes::Log.configure_logger(log_config)
|
|
26
|
+
|
|
27
|
+
require "scarpe/components/segmented_file_loader"
|
|
28
|
+
loader = Scarpe::Components::SegmentedFileLoader.new
|
|
29
|
+
Shoes.add_file_loader loader
|
|
30
|
+
|
|
5
31
|
require_relative "wv/web_wrangler"
|
|
6
32
|
require_relative "wv/control_interface"
|
|
7
33
|
|
|
8
34
|
require_relative "wv/widget"
|
|
9
|
-
require_relative "wv/webview_local_display"
|
|
10
|
-
require_relative "wv/webview_relay_display"
|
|
11
35
|
|
|
12
36
|
require_relative "wv/dimensions"
|
|
13
37
|
require_relative "wv/html"
|
|
14
38
|
|
|
15
39
|
require_relative "wv/spacing"
|
|
16
40
|
require_relative "wv/star"
|
|
41
|
+
require_relative "wv/radio"
|
|
17
42
|
require_relative "wv/background"
|
|
18
43
|
require_relative "wv/border"
|
|
19
44
|
|
|
20
|
-
require_relative "wv/fill"
|
|
21
45
|
require_relative "wv/arc"
|
|
46
|
+
require_relative "wv/font"
|
|
22
47
|
|
|
23
48
|
require_relative "wv/app"
|
|
24
|
-
require_relative "wv/document_root"
|
|
25
49
|
require_relative "wv/para"
|
|
50
|
+
require_relative "wv/slot"
|
|
26
51
|
require_relative "wv/stack"
|
|
27
52
|
require_relative "wv/flow"
|
|
53
|
+
require_relative "wv/document_root"
|
|
54
|
+
require_relative "wv/subscription_item"
|
|
28
55
|
require_relative "wv/button"
|
|
29
56
|
require_relative "wv/image"
|
|
30
57
|
require_relative "wv/edit_box"
|
|
@@ -37,3 +64,5 @@ require_relative "wv/shape"
|
|
|
37
64
|
require_relative "wv/text_widget"
|
|
38
65
|
require_relative "wv/link"
|
|
39
66
|
require_relative "wv/line"
|
|
67
|
+
require_relative "wv/video"
|
|
68
|
+
require_relative "wv/check"
|
data/lib/scarpe/wv_local.rb
CHANGED
data/lib/scarpe/wv_relay.rb
CHANGED