From 6abd50fbf5b541ca770065f9df94a369a3ff0dd3 Mon Sep 17 00:00:00 2001 From: Noah Gibbs Date: Tue, 10 Oct 2023 11:46:17 +0100 Subject: [PATCH] Several large renames and a version bump (#401) * Scarpe should be a module, not a class. * Rename 'widget' to 'drawable' throughout Scarpe. Bump version number. * Rename display properties to Shoes styles * Fix error declaration problem for scarpe-components tests and update Gemfile.lock for sub-gems * Fix merge conflict --- Gemfile.lock | 6 +- examples/gen.rb | 12 +- lacci/Gemfile.lock | 2 +- lacci/lib/lacci/scarpe_cli.rb | 2 +- lacci/lib/lacci/scarpe_core.rb | 2 +- lacci/lib/lacci/version.rb | 2 +- lacci/lib/shoes.rb | 6 +- lacci/lib/shoes/app.rb | 36 ++--- lacci/lib/shoes/background.rb | 2 +- lacci/lib/shoes/border.rb | 2 +- lacci/lib/shoes/display_service.rb | 32 +++-- lacci/lib/shoes/download.rb | 2 +- lacci/lib/shoes/{widget.rb => drawable.rb} | 132 +++++++++--------- lacci/lib/shoes/drawables.rb | 29 ++++ .../lib/shoes/{widgets => drawables}/alert.rb | 6 +- lacci/lib/shoes/{widgets => drawables}/arc.rb | 10 +- .../shoes/{widgets => drawables}/button.rb | 6 +- .../lib/shoes/{widgets => drawables}/check.rb | 6 +- .../{widgets => drawables}/document_root.rb | 2 +- .../shoes/{widgets => drawables}/edit_box.rb | 6 +- .../shoes/{widgets => drawables}/edit_line.rb | 6 +- .../lib/shoes/{widgets => drawables}/flow.rb | 6 +- .../lib/shoes/{widgets => drawables}/font.rb | 6 +- .../lib/shoes/{widgets => drawables}/image.rb | 6 +- .../lib/shoes/{widgets => drawables}/line.rb | 6 +- .../lib/shoes/{widgets => drawables}/link.rb | 10 +- .../shoes/{widgets => drawables}/list_box.rb | 6 +- .../lib/shoes/{widgets => drawables}/para.rb | 16 +-- .../lib/shoes/{widgets => drawables}/radio.rb | 8 +- .../lib/shoes/{widgets => drawables}/shape.rb | 8 +- .../lib/shoes/{widgets => drawables}/slot.rb | 8 +- .../lib/shoes/{widgets => drawables}/span.rb | 8 +- .../lib/shoes/{widgets => drawables}/stack.rb | 6 +- .../lib/shoes/{widgets => drawables}/star.rb | 12 +- .../subscription_item.rb | 16 +-- lacci/lib/shoes/drawables/text_drawable.rb | 54 +++++++ .../lib/shoes/{widgets => drawables}/video.rb | 6 +- lacci/lib/shoes/spacing.rb | 2 +- lacci/lib/shoes/widgets.rb | 29 ---- lacci/lib/shoes/widgets/text_widget.rb | 54 ------- lib/scarpe/cats_cradle.rb | 24 ++-- lib/scarpe/errors.rb | 8 +- lib/scarpe/version.rb | 4 +- lib/scarpe/wv.rb | 6 +- lib/scarpe/wv/alert.rb | 2 +- lib/scarpe/wv/app.rb | 6 +- lib/scarpe/wv/arc.rb | 2 +- lib/scarpe/wv/button.rb | 2 +- lib/scarpe/wv/check.rb | 2 +- lib/scarpe/wv/{widget.rb => drawable.rb} | 52 +++---- lib/scarpe/wv/edit_box.rb | 4 +- lib/scarpe/wv/edit_line.rb | 4 +- lib/scarpe/wv/font.rb | 2 +- lib/scarpe/wv/image.rb | 2 +- lib/scarpe/wv/line.rb | 2 +- lib/scarpe/wv/link.rb | 2 +- lib/scarpe/wv/list_box.rb | 3 +- lib/scarpe/wv/para.rb | 6 +- lib/scarpe/wv/radio.rb | 4 +- lib/scarpe/wv/shape.rb | 2 +- lib/scarpe/wv/slot.rb | 4 +- lib/scarpe/wv/span.rb | 2 +- lib/scarpe/wv/star.rb | 2 +- lib/scarpe/wv/subscription_item.rb | 4 +- .../wv/{text_widget.rb => text_drawable.rb} | 14 +- lib/scarpe/wv/video.rb | 4 +- lib/scarpe/wv/web_wrangler.rb | 8 +- lib/scarpe/wv/webview_local_display.rb | 52 ++++--- lib/scarpe/wv/webview_relay_display.rb | 14 +- lib/scarpe/wv/webview_relay_util.rb | 4 +- scarpe-components/Gemfile.lock | 4 +- .../lib/scarpe/components/base64.rb | 4 +- .../lib/scarpe/components/calzini.rb | 15 +- .../lib/scarpe/components/calzini/alert.rb | 4 +- .../scarpe/components/calzini/art_widgets.rb | 6 +- .../lib/scarpe/components/calzini/button.rb | 2 +- .../lib/scarpe/components/calzini/misc.rb | 14 +- .../lib/scarpe/components/calzini/para.rb | 2 +- .../lib/scarpe/components/calzini/slots.rb | 2 +- .../scarpe/components/calzini/text_widgets.rb | 2 +- .../lib/scarpe/components/errors.rb | 3 + .../lib/scarpe/components/file_helpers.rb | 2 +- .../lib/scarpe/components/modular_logger.rb | 4 +- .../lib/scarpe/components/print_logger.rb | 2 +- .../lib/scarpe/components/promises.rb | 4 +- .../lib/scarpe/components/version.rb | 4 +- ...dgets.rb => test_calzini_art_drawables.rb} | 2 +- .../test/calzini/test_calzini_misc.rb | 2 +- ...gets.rb => test_calzini_text_drawables.rb} | 2 +- scarpegen.rb | 28 ++-- sig/scarpe.rbs | 2 +- templates/basic_class_template.erb | 25 ++-- templates/class_template_with_event_bind.erb | 8 +- templates/class_template_with_shapes.erb | 25 ++-- templates/example_template.erb | 2 +- templates/module_template.erb | 8 +- templates/webview_template.erb | 3 +- test/{test_widgets.rb => test_drawables.rb} | 46 +++--- test/test_edit_box.rb | 2 +- test/test_link.rb | 2 - test/test_para.rb | 4 +- test/test_scarpe.rb | 4 +- test/test_slots.rb | 2 +- test/test_web_wrangler.rb | 2 +- 104 files changed, 533 insertions(+), 533 deletions(-) rename lacci/lib/shoes/{widget.rb => drawable.rb} (53%) create mode 100644 lacci/lib/shoes/drawables.rb rename lacci/lib/shoes/{widgets => drawables}/alert.rb (68%) rename lacci/lib/shoes/{widgets => drawables}/arc.rb (82%) rename lacci/lib/shoes/{widgets => drawables}/button.rb (78%) rename lacci/lib/shoes/{widgets => drawables}/check.rb (80%) rename lacci/lib/shoes/{widgets => drawables}/document_root.rb (92%) rename lacci/lib/shoes/{widgets => drawables}/edit_box.rb (80%) rename lacci/lib/shoes/{widgets => drawables}/edit_line.rb (77%) rename lacci/lib/shoes/{widgets => drawables}/flow.rb (64%) rename lacci/lib/shoes/{widgets => drawables}/font.rb (58%) rename lacci/lib/shoes/{widgets => drawables}/image.rb (76%) rename lacci/lib/shoes/{widgets => drawables}/line.rb (67%) rename lacci/lib/shoes/{widgets => drawables}/link.rb (74%) rename lacci/lib/shoes/{widgets => drawables}/list_box.rb (77%) rename lacci/lib/shoes/{widgets => drawables}/para.rb (79%) rename lacci/lib/shoes/{widgets => drawables}/radio.rb (76%) rename lacci/lib/shoes/{widgets => drawables}/shape.rb (77%) rename lacci/lib/shoes/{widgets => drawables}/slot.rb (91%) rename lacci/lib/shoes/{widgets => drawables}/span.rb (65%) rename lacci/lib/shoes/{widgets => drawables}/stack.rb (73%) rename lacci/lib/shoes/{widgets => drawables}/star.rb (78%) rename lacci/lib/shoes/{widgets => drawables}/subscription_item.rb (86%) create mode 100644 lacci/lib/shoes/drawables/text_drawable.rb rename lacci/lib/shoes/{widgets => drawables}/video.rb (61%) delete mode 100644 lacci/lib/shoes/widgets.rb delete mode 100644 lacci/lib/shoes/widgets/text_widget.rb rename lib/scarpe/wv/{widget.rb => drawable.rb} (79%) rename lib/scarpe/wv/{text_widget.rb => text_drawable.rb} (51%) rename scarpe-components/test/calzini/{test_calzini_art_widgets.rb => test_calzini_art_drawables.rb} (98%) rename scarpe-components/test/calzini/{test_calzini_text_widgets.rb => test_calzini_text_drawables.rb} (96%) rename test/{test_widgets.rb => test_drawables.rb} (55%) diff --git a/Gemfile.lock b/Gemfile.lock index 0ed4ac823..3e2c17af9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - scarpe (0.2.2) + scarpe (0.3.0) bloops (~> 0.5) fastimage lacci @@ -14,12 +14,12 @@ PATH PATH remote: lacci specs: - lacci (0.2.2) + lacci (0.3.0) PATH remote: scarpe-components specs: - scarpe-components (0.2.2) + scarpe-components (0.3.0) GEM remote: https://rubygems.org/ diff --git a/examples/gen.rb b/examples/gen.rb index 4e60a379f..813c95bdd 100755 --- a/examples/gen.rb +++ b/examples/gen.rb @@ -2,9 +2,9 @@ require 'erb' class ScarpeGenerator - def initialize(filename, display_properties) + def initialize(filename, shoes_styles) @filename = filename - @display_properties = display_properties + @shoes_styles = shoes_styles end def generate_files(choice, class_template_choice) @@ -96,7 +96,7 @@ def binding_with_argument capitalized_argument = @filename.capitalize binding.dup.tap do |b| b.local_variable_set(:argument, capitalized_argument) - b.local_variable_set(:display_properties, @display_properties) + b.local_variable_set(:shoes_styles, @shoes_styles) end end end @@ -109,7 +109,7 @@ def binding_with_argument end stack width: 400 do - para 'Enter display properties (like :height,:text) ' + para 'Enter Shoes styles (like :height,:text) ' $properties_input = edit_line end @@ -125,10 +125,10 @@ def binding_with_argument button 'Generate Files!',color:"#FF7116",padding_bottom:"8",padding_top:"8",text_color:"white",font_size:"16" do filename = $filename_input.text - display_properties = $properties_input.text + shoes_styles = $properties_input.text choice = $choice_input.selected_item - generator = ScarpeGenerator.new(filename, display_properties) + generator = ScarpeGenerator.new(filename, shoes_styles) if choice == 'Class' generator.generate_files(choice, $class_template_choice_input.selected_item) diff --git a/lacci/Gemfile.lock b/lacci/Gemfile.lock index eea326fcf..6c9577cec 100644 --- a/lacci/Gemfile.lock +++ b/lacci/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - lacci (0.2.2) + lacci (0.3.0) GEM remote: https://rubygems.org/ diff --git a/lacci/lib/lacci/scarpe_cli.rb b/lacci/lib/lacci/scarpe_cli.rb index cb506fd27..92acff15f 100644 --- a/lacci/lib/lacci/scarpe_cli.rb +++ b/lacci/lib/lacci/scarpe_cli.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class Scarpe +module Scarpe module CLI DEFAULT_USAGE = <<~'USAGE' Usage: scarpe_core [OPTIONS] # Same as "scarpe run" diff --git a/lacci/lib/lacci/scarpe_core.rb b/lacci/lib/lacci/scarpe_core.rb index 746dbd471..9314ca8ec 100644 --- a/lacci/lib/lacci/scarpe_core.rb +++ b/lacci/lib/lacci/scarpe_core.rb @@ -12,7 +12,7 @@ exit(-1) end -class Scarpe; end +module Scarpe; end # The base error class for Scarpe errors, but not necessarily {Shoes::Error}s class Scarpe::Error < StandardError; end diff --git a/lacci/lib/lacci/version.rb b/lacci/lib/lacci/version.rb index bc320f834..a20630d7f 100644 --- a/lacci/lib/lacci/version.rb +++ b/lacci/lib/lacci/version.rb @@ -9,5 +9,5 @@ # mostly invisible. Instead, look at the {Shoes} module # to see what's in Lacci. module Lacci - VERSION = "0.2.2" + VERSION = "0.3.0" end diff --git a/lacci/lib/shoes.rb b/lacci/lib/shoes.rb index 0e3bf1e6a..cd012481d 100644 --- a/lacci/lib/shoes.rb +++ b/lacci/lib/shoes.rb @@ -31,9 +31,9 @@ module Kernel require_relative "shoes/border" require_relative "shoes/spacing" -require_relative "shoes/widget" +require_relative "shoes/drawable" require_relative "shoes/app" -require_relative "shoes/widgets" +require_relative "shoes/drawables" require_relative "shoes/download" @@ -46,7 +46,7 @@ module Shoes class << self # Creates a Shoes app with a new window. The block parameter is used to create - # widgets and set up handlers. Arguments are passed to Shoes::App.new internally. + # drawables and set up handlers. Arguments are passed to Shoes::App.new internally. # # @incompatibility In Shoes3, this method will return normally. # In Scarpe, after the block is executed, the method will not return and Scarpe diff --git a/lacci/lib/shoes/app.rb b/lacci/lib/shoes/app.rb index f1290c4ab..048af3909 100644 --- a/lacci/lib/shoes/app.rb +++ b/lacci/lib/shoes/app.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Shoes - class App < Shoes::Widget + class App < Shoes::Drawable include Shoes::Log class << self @@ -10,7 +10,7 @@ class << self attr_reader :document_root - display_properties :title, :width, :height, :resizable + shoes_styles :title, :width, :height, :resizable CUSTOM_EVENT_LOOP_TYPES = ["displaylib", "return", "wait"] @@ -36,20 +36,20 @@ def initialize( super # The draw context tracks current settings like fill and stroke, - # plus potentially other current state that changes from widget - # to widget and slot to slot. + # plus potentially other current state that changes from drawable + # to drawable and slot to slot. @draw_context = { "fill" => "", "stroke" => "", } - # This creates the DocumentRoot, including its corresponding display widget + # This creates the DocumentRoot, including its corresponding display drawable @document_root = Shoes::DocumentRoot.new @slots = [] - # Now create the App display widget - create_display_widget + # Now create the App display drawable + create_display_drawable # Set up testing events *after* Display Service basic objects exist if ENV["SCARPE_APP_TEST"] @@ -90,9 +90,9 @@ def init ::Shoes::App.instance.with_slot(@document_root, &@app_code_body) end - # "Container" widgets like flows, stacks, masks and the document root + # "Container" drawables like flows, stacks, masks and the document root # are considered "slots" in Shoes parlance. When a new slot is created, - # we push it here in order to track what widgets are found in that slot. + # we push it here in order to track what drawables are found in that slot. def push_slot(slot) @slots.push(slot) end @@ -154,7 +154,7 @@ def destroy(send_event: true) send_shoes_event(event_name: "destroy") if send_event end - def all_widgets + def all_drawables out = [] to_add = @document_root.children @@ -166,13 +166,13 @@ def all_widgets out end - # We can add various ways to find widgets here. + # We can add various ways to find drawables here. # These are sort of like Shoes selectors, used for testing. - def find_widgets_by(*specs) - widgets = all_widgets + def find_drawables_by(*specs) + drawables = all_drawables specs.each do |spec| if spec.is_a?(Class) - widgets.select! { |w| spec === w } + drawables.select! { |w| spec === w } elsif spec.is_a?(Symbol) || spec.is_a?(String) s = spec.to_s case s[0] @@ -180,23 +180,23 @@ def find_widgets_by(*specs) begin # I'm not finding a global_variable_get or similar... global_value = eval s - widgets &= [global_value] + drawables &= [global_value] rescue raise InvalidAttributeValueError, "Error getting global variable: #{spec.inspect}" end when "@" if Shoes::App.instance.instance_variables.include?(spec.to_sym) - widgets &= [self.instance_variable_get(spec)] + drawables &= [self.instance_variable_get(spec)] else raise InvalidAttributeValueError, "Can't find top-level instance variable: #{spec.inspect}!" end else end else - raise(InvalidAttributeValueError, "Don't know how to find widgets by #{spec.inspect}!") + raise(InvalidAttributeValueError, "Don't know how to find drawables by #{spec.inspect}!") end end - widgets + drawables end end end diff --git a/lacci/lib/shoes/background.rb b/lacci/lib/shoes/background.rb index 80a7ee00d..6e05097d8 100644 --- a/lacci/lib/shoes/background.rb +++ b/lacci/lib/shoes/background.rb @@ -3,7 +3,7 @@ module Shoes module Background def self.included(includer) - includer.display_property(:background_color) + includer.shoes_style(:background_color) end # NOTE: this needs to be passed through in order for the styling to work diff --git a/lacci/lib/shoes/border.rb b/lacci/lib/shoes/border.rb index 3f6e7d87e..c7305c918 100644 --- a/lacci/lib/shoes/border.rb +++ b/lacci/lib/shoes/border.rb @@ -3,7 +3,7 @@ module Shoes module Border def self.included(includer) - includer.display_properties :border_color, :options + includer.shoes_styles :border_color, :options end # Considering a signature like this: diff --git a/lacci/lib/shoes/display_service.rb b/lacci/lib/shoes/display_service.rb index 5a61c12b8..94858553d 100644 --- a/lacci/lib/shoes/display_service.rb +++ b/lacci/lib/shoes/display_service.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true -# Lacci Shoes apps operate in multiple layers. A Shoes widget tree exists as fairly -# plain, simple Ruby objects. And then a display-service widget tree integrates with +# Lacci Shoes apps operate in multiple layers. A Shoes drawable tree exists as fairly +# plain, simple Ruby objects. And then a display-service drawable tree integrates with # the display technology. This lets us use Ruby as our API while # not tying it too closely to the limitations of Webview, WASM, LibUI, etc. # @@ -15,16 +15,16 @@ # # ## Events # -# Events are a lot of what tie the Shoes widgets and the display service together. +# Events are a lot of what tie the Shoes drawables and the display service together. # -# Shoes widgets *expect* to operate in a fairly "hands off" mode where they record +# Shoes drawables *expect* to operate in a fairly "hands off" mode where they record # to an event queue to send to the display service, and the display service records # events to send back. # # When a Shoes handler takes an action (e.g. some_para.replace(),) the relevant # call will be dispatched as a :display event, to be sent to the display service. # And when a display-side event occurs (e.g. user pushes a button,) it will be -# dispatched as a :shoes event, to be sent to the Shoes tree of widgets. +# dispatched as a :shoes event, to be sent to the Shoes tree of drawables. # module Shoes class DisplayService @@ -128,22 +128,26 @@ def display_service # These methods are an interface to DisplayService objects. - def create_display_widget_for(widget_class_name, widget_id, properties) + def create_display_drawable_for(drawable_class_name, drawable_id, properties) raise "Override in DisplayService implementation!" end - def set_widget_pairing(id, display_widget) - @display_widget_for ||= {} - @display_widget_for[id] = display_widget + def set_drawable_pairing(id, display_drawable) + @display_drawable_for ||= {} + if @display_drawable_for[id] + @log.warn("There is already a drawable for #{id.inspect}! Not setting a new one.") + return + end + @display_drawable_for[id] = display_drawable end - def query_display_widget_for(id, nil_ok: false) - display_widget = @display_widget_for[id] - unless display_widget || nil_ok - raise "Could not find display widget for linkable ID #{id.inspect}!" + def query_display_drawable_for(id, nil_ok: false) + display_drawable = @display_drawable_for[id] + unless display_drawable || nil_ok + raise "Could not find display drawable for linkable ID #{id.inspect}!" end - display_widget + display_drawable end def destroy diff --git a/lacci/lib/shoes/download.rb b/lacci/lib/shoes/download.rb index 1c6e5fdf2..bb75c3dc5 100644 --- a/lacci/lib/shoes/download.rb +++ b/lacci/lib/shoes/download.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Shoes - class Widget + class Drawable class ResponseWrapper attr_reader :response diff --git a/lacci/lib/shoes/widget.rb b/lacci/lib/shoes/drawable.rb similarity index 53% rename from lacci/lib/shoes/widget.rb rename to lacci/lib/shoes/drawable.rb index 56e1227c9..420a89e66 100644 --- a/lacci/lib/shoes/widget.rb +++ b/lacci/lib/shoes/drawable.rb @@ -1,45 +1,45 @@ # frozen_string_literal: true module Shoes - # Shoes::Widget + # Shoes::Drawable # - # This is the display-service portable Shoes Widget interface. Visible Shoes - # widgets like buttons inherit from this. Compound widgets made of multiple - # different smaller Widgets inherit from it in their various apps or libraries. - # The Shoes Widget helps build a Shoes-side widget tree, with parents and - # children. Any API that applies to all widgets (e.g. remove) should be + # This is the display-service portable Shoes Drawable interface. Visible Shoes + # drawables like buttons inherit from this. Compound drawables made of multiple + # different smaller Drawables inherit from it in their various apps or libraries. + # The Shoes Drawable helps build a Shoes-side drawable tree, with parents and + # children. Any API that applies to all drawables (e.g. remove) should be # defined here. # - class Widget < Shoes::Linkable + class Drawable < Shoes::Linkable include Shoes::Log include Shoes::Colors class << self - attr_accessor :widget_classes - attr_accessor :widget_default_styles + attr_accessor :drawable_classes + attr_accessor :drawable_default_styles def inherited(subclass) - Shoes::Widget.widget_classes ||= [] - Shoes::Widget.widget_classes << subclass + Shoes::Drawable.drawable_classes ||= [] + Shoes::Drawable.drawable_classes << subclass - Shoes::Widget.widget_default_styles ||= {} - Shoes::Widget.widget_default_styles[subclass] = {} + Shoes::Drawable.drawable_default_styles ||= {} + Shoes::Drawable.drawable_default_styles[subclass] = {} super end def dsl_name - n = name.split("::").last.chomp("Widget") + n = name.split("::").last.chomp("Drawable") n.gsub(/(.)([A-Z])/, '\1_\2').downcase end - def widget_class_by_name(name) - widget_classes.detect { |k| k.dsl_name == name.to_s } + def drawable_class_by_name(name) + drawable_classes.detect { |k| k.dsl_name == name.to_s } end def validate_as(prop_name, value) prop_name = prop_name.to_s - hashes = display_property_hashes + hashes = shoes_style_hashes h = hashes.detect { |hash| hash[:name] == prop_name } raise(Shoes::NoSuchStyleError, "Can't find property #{prop_name.inspect} in #{self} property list: #{hashes.inspect}!") unless h @@ -60,10 +60,10 @@ def linkable_properties_hash public - # Display properties in Shoes Linkables are automatically sync'd with the display side objects. - # If a block is passed to display_property, that's the validation for the property. It should + # Shoes styles in Shoes Linkables are automatically sync'd with the display side objects. + # If a block is passed to shoes_style, that's the validation for the property. It should # convert a given value to a valid value for the property or throw an exception. - def display_property(name, &validator) + def shoes_style(name, &validator) name = name.to_s return if linkable_properties_hash[name] @@ -72,38 +72,38 @@ def display_property(name, &validator) linkable_properties_hash[name] = true end - # Add these names as display properties - def display_properties(*names) - names.each { |n| display_property(n) } + # Add these names as Shoes styles + def shoes_styles(*names) + names.each { |n| shoes_style(n) } end - def display_property_names - parent_prop_names = self != Shoes::Widget ? self.superclass.display_property_names : [] + def shoes_style_names + parent_prop_names = self != Shoes::Drawable ? self.superclass.shoes_style_names : [] parent_prop_names | linkable_properties.map { |prop| prop[:name] } end - def display_property_hashes - parent_hashes = self != Shoes::Widget ? self.superclass.display_property_hashes : [] + def shoes_style_hashes + parent_hashes = self != Shoes::Drawable ? self.superclass.shoes_style_hashes : [] parent_hashes + linkable_properties end - def display_property_name?(name) + def shoes_style_name?(name) linkable_properties_hash[name.to_s] || - (self != Shoes::Widget && superclass.display_property_name?(name)) + (self != Shoes::Drawable && superclass.shoes_style_name?(name)) end end # Shoes uses a "hidden" style property for hide/show - display_property :hidden + shoes_style :hidden def initialize(*args, **kwargs) - log_init("Widget") + log_init("Drawable") - default_styles = Shoes::Widget.widget_default_styles[self.class] + default_styles = Shoes::Drawable.drawable_default_styles[self.class] - self.class.display_property_names.each do |prop| + self.class.shoes_style_names.each do |prop| prop_sym = prop.to_sym if kwargs[prop_sym] val = self.class.validate_as(prop, kwargs[prop_sym]) @@ -120,13 +120,13 @@ def initialize(*args, **kwargs) def inspect "#<#{self.class}:#{self.object_id} " + "@linkable_id=#{@linkable_id.inspect} @parent=#{@parent.inspect} " + - "@children=#{@children.inspect} properties=#{display_property_values.inspect}>" + "@children=#{@children.inspect} properties=#{shoes_style_values.inspect}>" end private def bind_self_event(event_name, &block) - raise(Shoes::NoLinkableIdError, "Widget has no linkable_id! #{inspect}") unless linkable_id + raise(Shoes::NoLinkableIdError, "Drawable has no linkable_id! #{inspect}") unless linkable_id bind_shoes_event(event_name: event_name, target: linkable_id, &block) end @@ -137,8 +137,8 @@ def bind_no_target_event(event_name, &block) public - def display_property_values - all_property_names = self.class.display_property_names + def shoes_style_values + all_property_names = self.class.shoes_style_names properties = {} all_property_names.each do |prop| @@ -151,22 +151,22 @@ def display_property_values def style(*args, **kwargs) if args.empty? && kwargs.empty? # Just called as .style() - display_property_values + shoes_style_values elsif args.empty? - # This is called to set one or more Shoes styles (display properties.) - prop_names = self.class.display_property_names + # This is called to set one or more Shoes styles + prop_names = self.class.shoes_style_names unknown_styles = kwargs.keys.select { |k| !prop_names.include?(k.to_s) } unless unknown_styles.empty? - raise Shoes::NoSuchStyleError, "Unknown styles for widget type #{self.class.name}: #{unknown_styles.join(", ")}" + raise Shoes::NoSuchStyleError, "Unknown styles for drawable type #{self.class.name}: #{unknown_styles.join(", ")}" end kwargs.each do |name, val| instance_variable_set("@#{name}", val) end - elsif args.length == 1 && args[0] < Shoes::Widget + elsif args.length == 1 && args[0] < Shoes::Drawable # Shoes supports calling .style with a Shoes class, e.g. .style(Shoes::Button, displace_left: 5) kwargs.each do |name, val| - Shoes::Widget.widget_default_styles[args[0]][name.to_sym] = val + Shoes::Drawable.drawable_default_styles[args[0]][name.to_sym] = val end else raise Shoes::InvalidAttributeValueError, "Unexpected arguments to style! args: #{args.inspect}, keyword args: #{kwargs.inspect}" @@ -175,11 +175,11 @@ def style(*args, **kwargs) private - def create_display_widget + def create_display_drawable klass_name = self.class.name.delete_prefix("Scarpe::").delete_prefix("Shoes::") - # Should we save a reference to widget for later reference? - ::Shoes::DisplayService.display_service.create_display_widget_for(klass_name, self.linkable_id, display_property_values) + # Should we save a reference to drawable for later reference? + ::Shoes::DisplayService.display_service.create_display_drawable_for(klass_name, self.linkable_id, shoes_style_values) end public @@ -193,38 +193,38 @@ def set_parent(new_parent) send_shoes_event(new_parent.linkable_id, event_name: "parent", target: linkable_id) end - # Removes the element from the Shoes::Widget tree + # Removes the element from the Shoes::Drawable tree def destroy @parent&.remove_child(self) send_shoes_event(event_name: "destroy", target: linkable_id) end alias_method :remove, :destroy - # Hide the widget. + # Hide the drawable. def hide self.hidden = true end - # Show the widget. + # Show the drawable. def show self.hidden = false end - # Hide the widget if it is currently shown. Show it if it is currently hidden. + # Hide the drawable if it is currently shown. Show it if it is currently hidden. def toggle self.hidden = !self.hidden end - # We use method_missing for widget-creating methods like "button", - # and also to auto-create display-property getters and setters. + # We use method_missing for drawable-creating methods like "button", + # and also to auto-create Shoes style getters and setters. def method_missing(name, *args, **kwargs, &block) name_s = name.to_s if name_s[-1] == "=" prop_name = name_s[0..-2] - if self.class.display_property_name?(prop_name) + if self.class.shoes_style_name?(prop_name) self.class.define_method(name) do |new_value| - raise Shoes::NoLinkableIdError, "Trying to set display properties in an object with no linkable ID!" unless linkable_id + raise Shoes::NoLinkableIdError, "Trying to set Shoes styles in an object with no linkable ID!" unless linkable_id new_value = self.class.validate_as(prop_name, new_value) instance_variable_set("@" + prop_name, new_value) @@ -235,9 +235,9 @@ def method_missing(name, *args, **kwargs, &block) end end - if self.class.display_property_name?(name_s) + if self.class.shoes_style_name?(name_s) self.class.define_method(name) do - raise Shoes::NoLinkableIdError, "Trying to get display properties in an object with no linkable ID!" unless linkable_id + raise Shoes::NoLinkableIdError, "Trying to get Shoes styles in an object with no linkable ID!" unless linkable_id instance_variable_get("@" + name_s) end @@ -245,18 +245,18 @@ def method_missing(name, *args, **kwargs, &block) return self.send(name, *args, **kwargs, &block) end - klass = Widget.widget_class_by_name(name) + klass = Drawable.drawable_class_by_name(name) return super unless klass - ::Shoes::Widget.define_method(name) do |*args, **kwargs, &block| - # Look up the Shoes widget and create it... - widget_instance = klass.new(*args, **kwargs, &block) + ::Shoes::Drawable.define_method(name) do |*args, **kwargs, &block| + # Look up the Shoes drawable and create it... + drawable_instance = klass.new(*args, **kwargs, &block) - unless klass.ancestors.include?(Shoes::TextWidget) - widget_instance.set_parent Shoes::App.instance.current_slot + unless klass.ancestors.include?(Shoes::TextDrawable) + drawable_instance.set_parent Shoes::App.instance.current_slot end - widget_instance + drawable_instance end send(name, *args, **kwargs, &block) @@ -264,9 +264,9 @@ def method_missing(name, *args, **kwargs, &block) def respond_to_missing?(name, include_private = false) name_s = name.to_s - return true if self.class.display_property_name?(name_s) - return true if self.class.display_property_name?(name_s[0..-2]) && name_s[-1] == "=" - return true if Widget.widget_class_by_name(name_s) + return true if self.class.shoes_style_name?(name_s) + return true if self.class.shoes_style_name?(name_s[0..-2]) && name_s[-1] == "=" + return true if Drawable.drawable_class_by_name(name_s) super end diff --git a/lacci/lib/shoes/drawables.rb b/lacci/lib/shoes/drawables.rb new file mode 100644 index 000000000..d9fd36ab6 --- /dev/null +++ b/lacci/lib/shoes/drawables.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require "shoes/drawables/slot" +require "shoes/drawables/stack" +require "shoes/drawables/flow" +require "shoes/drawables/document_root" + +require "shoes/drawables/text_drawable" + +require "shoes/drawables/font" +require "shoes/drawables/subscription_item" + +require "shoes/drawables/arc" +require "shoes/drawables/line" +require "shoes/drawables/shape" +require "shoes/drawables/star" + +require "shoes/drawables/alert" +require "shoes/drawables/button" +require "shoes/drawables/check" +require "shoes/drawables/edit_box" +require "shoes/drawables/edit_line" +require "shoes/drawables/image" +require "shoes/drawables/link" +require "shoes/drawables/list_box" +require "shoes/drawables/para" +require "shoes/drawables/radio" +require "shoes/drawables/span" +require "shoes/drawables/video" diff --git a/lacci/lib/shoes/widgets/alert.rb b/lacci/lib/shoes/drawables/alert.rb similarity index 68% rename from lacci/lib/shoes/widgets/alert.rb rename to lacci/lib/shoes/drawables/alert.rb index 398cd447e..ceb81bb2c 100644 --- a/lacci/lib/shoes/widgets/alert.rb +++ b/lacci/lib/shoes/drawables/alert.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true module Shoes - class Alert < Shoes::Widget - display_property :text + class Alert < Shoes::Drawable + shoes_style :text def initialize(text) @text = text @@ -13,7 +13,7 @@ def initialize(text) remove end - create_display_widget + create_display_drawable end end end diff --git a/lacci/lib/shoes/widgets/arc.rb b/lacci/lib/shoes/drawables/arc.rb similarity index 82% rename from lacci/lib/shoes/widgets/arc.rb rename to lacci/lib/shoes/drawables/arc.rb index e0dfee34c..6024f8ba5 100644 --- a/lacci/lib/shoes/widgets/arc.rb +++ b/lacci/lib/shoes/drawables/arc.rb @@ -1,15 +1,15 @@ # frozen_string_literal: true module Shoes - class Arc < Shoes::Widget - display_properties :left, :top, :width, :height, :angle1, :angle2, :draw_context + class Arc < Shoes::Drawable + shoes_style :draw_context [:left, :top, :width, :height].each do |prop| - display_property(prop) { |val| convert_to_integer(val, prop) } + shoes_style(prop) { |val| convert_to_integer(val, prop) } end [:angle1, :angle2].each do |prop| - display_property(prop) { |val| convert_to_float(val, prop) } + shoes_style(prop) { |val| convert_to_float(val, prop) } end def initialize(*args) @@ -18,7 +18,7 @@ def initialize(*args) super self.left, self.top, self.width, self.height, self.angle1, self.angle2 = args - create_display_widget + create_display_drawable end def self.convert_to_integer(value, attribute_name) diff --git a/lacci/lib/shoes/widgets/button.rb b/lacci/lib/shoes/drawables/button.rb similarity index 78% rename from lacci/lib/shoes/widgets/button.rb rename to lacci/lib/shoes/drawables/button.rb index 3ac25038f..b641422d3 100644 --- a/lacci/lib/shoes/widgets/button.rb +++ b/lacci/lib/shoes/drawables/button.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true module Shoes - class Button < Shoes::Widget + class Button < Shoes::Drawable include Shoes::Log - display_properties :text, :width, :height, :top, :left, :color, :padding_top, :padding_bottom, :text_color, :size, :font_size + shoes_styles :text, :width, :height, :top, :left, :color, :padding_top, :padding_bottom, :text_color, :size, :font_size def initialize(text, width: nil, height: nil, top: nil, left: nil, color: nil, padding_top: nil, padding_bottom: nil, size: 12, text_color: nil, font_size: nil, &block) @@ -22,7 +22,7 @@ def initialize(text, width: nil, height: nil, top: nil, left: nil, color: nil, p @block&.call end - create_display_widget + create_display_drawable end # Set the click handler diff --git a/lacci/lib/shoes/widgets/check.rb b/lacci/lib/shoes/drawables/check.rb similarity index 80% rename from lacci/lib/shoes/widgets/check.rb rename to lacci/lib/shoes/drawables/check.rb index 9ca311ca6..9374e220b 100644 --- a/lacci/lib/shoes/widgets/check.rb +++ b/lacci/lib/shoes/drawables/check.rb @@ -1,15 +1,15 @@ # frozen_string_literal: true module Shoes - class Check < Shoes::Widget - display_properties :checked + class Check < Shoes::Drawable + shoes_styles :checked def initialize(checked = nil, &block) @block = block super bind_self_event("click") { click } - create_display_widget + create_display_drawable end def click(&block) diff --git a/lacci/lib/shoes/widgets/document_root.rb b/lacci/lib/shoes/drawables/document_root.rb similarity index 92% rename from lacci/lib/shoes/widgets/document_root.rb rename to lacci/lib/shoes/drawables/document_root.rb index 79267abf3..e086cf8c9 100644 --- a/lacci/lib/shoes/widgets/document_root.rb +++ b/lacci/lib/shoes/drawables/document_root.rb @@ -9,7 +9,7 @@ def initialize super - create_display_widget + create_display_drawable end # The default inspect string can be absolutely huge in console output, and it's frequently printed. diff --git a/lacci/lib/shoes/widgets/edit_box.rb b/lacci/lib/shoes/drawables/edit_box.rb similarity index 80% rename from lacci/lib/shoes/widgets/edit_box.rb rename to lacci/lib/shoes/drawables/edit_box.rb index 73ed38c92..a5c2bb4fa 100644 --- a/lacci/lib/shoes/widgets/edit_box.rb +++ b/lacci/lib/shoes/drawables/edit_box.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true module Shoes - class EditBox < Shoes::Widget - display_properties :text, :height, :width + class EditBox < Shoes::Drawable + shoes_styles :text, :height, :width def initialize(text = "", height: nil, width: nil, &block) super @@ -14,7 +14,7 @@ def initialize(text = "", height: nil, width: nil, &block) @callback&.call(self) end - create_display_widget + create_display_drawable end def change(&block) diff --git a/lacci/lib/shoes/widgets/edit_line.rb b/lacci/lib/shoes/drawables/edit_line.rb similarity index 77% rename from lacci/lib/shoes/widgets/edit_line.rb rename to lacci/lib/shoes/drawables/edit_line.rb index 9149bb27a..e7efe5b76 100644 --- a/lacci/lib/shoes/widgets/edit_line.rb +++ b/lacci/lib/shoes/drawables/edit_line.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true module Shoes - class EditLine < Shoes::Widget - display_properties :text, :width + class EditLine < Shoes::Drawable + shoes_styles :text, :width def initialize(text = "", width: nil, &block) super @@ -14,7 +14,7 @@ def initialize(text = "", width: nil, &block) @block&.call(new_text) end - create_display_widget + create_display_drawable end def change(&block) diff --git a/lacci/lib/shoes/widgets/flow.rb b/lacci/lib/shoes/drawables/flow.rb similarity index 64% rename from lacci/lib/shoes/widgets/flow.rb rename to lacci/lib/shoes/drawables/flow.rb index 93b25a245..38bb6a396 100644 --- a/lacci/lib/shoes/widgets/flow.rb +++ b/lacci/lib/shoes/drawables/flow.rb @@ -6,14 +6,14 @@ class Flow < Shoes::Slot include Shoes::Border include Shoes::Spacing - display_properties :width, :height, :margin, :padding + shoes_styles :width, :height, :margin, :padding def initialize(width: "100%", height: nil, margin: nil, padding: nil, **options, &block) super @options = options - # Create the display-side widget *before* instance_eval, which will add child widgets with their display widgets - create_display_widget + # Create the display-side drawable *before* instance_eval, which will add child drawables with their display drawables + create_display_drawable Shoes::App.instance.with_slot(self, &block) if block_given? end diff --git a/lacci/lib/shoes/widgets/font.rb b/lacci/lib/shoes/drawables/font.rb similarity index 58% rename from lacci/lib/shoes/widgets/font.rb rename to lacci/lib/shoes/drawables/font.rb index 2f24de236..3f07dd8b1 100644 --- a/lacci/lib/shoes/widgets/font.rb +++ b/lacci/lib/shoes/drawables/font.rb @@ -1,14 +1,14 @@ # frozen_string_literal: true module Shoes - class Font < Shoes::Widget - display_properties :font + class Font < Shoes::Drawable + shoes_styles :font def initialize(font) super @font = font - create_display_widget + create_display_drawable end end end diff --git a/lacci/lib/shoes/widgets/image.rb b/lacci/lib/shoes/drawables/image.rb similarity index 76% rename from lacci/lib/shoes/widgets/image.rb rename to lacci/lib/shoes/drawables/image.rb index df8d5f83c..0244ee631 100644 --- a/lacci/lib/shoes/widgets/image.rb +++ b/lacci/lib/shoes/drawables/image.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true module Shoes - class Image < Shoes::Widget - display_properties :url, :width, :height, :top, :left, :click + class Image < Shoes::Drawable + shoes_styles :url, :width, :height, :top, :left, :click def initialize(url, width: nil, height: nil, top: nil, left: nil, click: nil) super @@ -11,7 +11,7 @@ def initialize(url, width: nil, height: nil, top: nil, left: nil, click: nil) # Get the image dimensions # @width, @height = size - create_display_widget + create_display_drawable end def replace(url) diff --git a/lacci/lib/shoes/widgets/line.rb b/lacci/lib/shoes/drawables/line.rb similarity index 67% rename from lacci/lib/shoes/widgets/line.rb rename to lacci/lib/shoes/drawables/line.rb index ff3dd1aae..24534f9de 100644 --- a/lacci/lib/shoes/widgets/line.rb +++ b/lacci/lib/shoes/drawables/line.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true module Shoes - class Line < Shoes::Widget - display_properties :left, :top, :x2, :y2, :draw_context + class Line < Shoes::Drawable + shoes_styles :left, :top, :x2, :y2, :draw_context def initialize(left, top, x2, y2) super @@ -13,7 +13,7 @@ def initialize(left, top, x2, y2) @y2 = y2 @draw_context = Shoes::App.instance.current_draw_context - create_display_widget + create_display_drawable end end end diff --git a/lacci/lib/shoes/widgets/link.rb b/lacci/lib/shoes/drawables/link.rb similarity index 74% rename from lacci/lib/shoes/widgets/link.rb rename to lacci/lib/shoes/drawables/link.rb index b220139da..203fa1655 100644 --- a/lacci/lib/shoes/widgets/link.rb +++ b/lacci/lib/shoes/drawables/link.rb @@ -1,25 +1,25 @@ # frozen_string_literal: true module Shoes - class Link < Shoes::TextWidget - display_properties :text, :click, :has_block + class Link < Shoes::TextDrawable + shoes_styles :text, :click, :has_block def initialize(text, click: nil, &block) super @text = text @block = block - # We can't send a block to the display widget, but we can send a boolean + # We can't send a block to the display drawable, but we can send a boolean @has_block = !block.nil? - # The click property should be changed before it gets sent to the display widget + # The click property should be changed before it gets sent to the display drawable @click ||= "#" bind_self_event("click") do @block&.call end - create_display_widget + create_display_drawable end end diff --git a/lacci/lib/shoes/widgets/list_box.rb b/lacci/lib/shoes/drawables/list_box.rb similarity index 77% rename from lacci/lib/shoes/widgets/list_box.rb rename to lacci/lib/shoes/drawables/list_box.rb index 50a3dc893..2b4898f7c 100644 --- a/lacci/lib/shoes/widgets/list_box.rb +++ b/lacci/lib/shoes/drawables/list_box.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true module Shoes - class ListBox < Shoes::Widget - display_properties :selected_item, :items, :height, :width, :choose + class ListBox < Shoes::Drawable + shoes_styles :selected_item, :items, :height, :width, :choose def initialize(args = {}, &block) super @@ -17,7 +17,7 @@ def initialize(args = {}, &block) @callback&.call(new_item) end - create_display_widget + create_display_drawable end def change(&block) diff --git a/lacci/lib/shoes/widgets/para.rb b/lacci/lib/shoes/drawables/para.rb similarity index 79% rename from lacci/lib/shoes/widgets/para.rb rename to lacci/lib/shoes/drawables/para.rb index 1f815b1c5..cec3fbfda 100644 --- a/lacci/lib/shoes/widgets/para.rb +++ b/lacci/lib/shoes/drawables/para.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true module Shoes - class Para < Shoes::Widget - display_properties :text_items, :size, :font, :html_attributes, :hidden - display_property(:stroke) { |val| Shoes::Colors.to_rgb(val) } + class Para < Shoes::Drawable + shoes_styles :text_items, :size, :font, :html_attributes, :hidden + shoes_style(:stroke) { |val| Shoes::Colors.to_rgb(val) } def initialize(*args, stroke: nil, size: :para, font: nil, hidden: false, **html_attributes) super @@ -13,15 +13,15 @@ def initialize(*args, stroke: nil, size: :para, font: nil, hidden: false, **html @hidden_text_items = text_children_to_items(@text_children) @text_items = [] else - # Text_children alternates strings and TextWidgets, so we can't just pass - # it as a display property. It won't serialize. + # Text_children alternates strings and TextDrawables, so we can't just pass + # it as a Shoes style. It won't serialize. @text_items = text_children_to_items(@text_children) @hidden_text_items = [] end @html_attributes = html_attributes || {} - create_display_widget + create_display_drawable end def text_children_to_items(text_children) @@ -40,14 +40,14 @@ def text=(children) def update_text_children(*children) @text_children = children - # This should signal the display widget to change + # This should signal the display drawable to change self.text_items = text_children_to_items(@text_children) end end end module Shoes - class Widget + class Drawable def banner(*args, **kwargs) para(*args, **{ size: :banner }.merge(kwargs)) end diff --git a/lacci/lib/shoes/widgets/radio.rb b/lacci/lib/shoes/drawables/radio.rb similarity index 76% rename from lacci/lib/shoes/widgets/radio.rb rename to lacci/lib/shoes/drawables/radio.rb index 7393279b4..cc2a0d621 100644 --- a/lacci/lib/shoes/widgets/radio.rb +++ b/lacci/lib/shoes/drawables/radio.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true module Shoes - # A Radio button widget. Only a single radio button may be checked in each + # A Radio button drawable. Only a single radio button may be checked in each # group. If no group is specified, or the group is nil, default to all # radio buttons in the same slot being treated as being in the same group. - class Radio < Shoes::Widget - display_properties :group, :checked + class Radio < Shoes::Drawable + shoes_styles :group, :checked def initialize(group = nil, checked: nil, &block) super @@ -13,7 +13,7 @@ def initialize(group = nil, checked: nil, &block) @block = block bind_self_event("click") { click } - create_display_widget + create_display_drawable end def click(&block) diff --git a/lacci/lib/shoes/widgets/shape.rb b/lacci/lib/shoes/drawables/shape.rb similarity index 77% rename from lacci/lib/shoes/widgets/shape.rb rename to lacci/lib/shoes/drawables/shape.rb index f0c9e9d00..58c7e18ee 100644 --- a/lacci/lib/shoes/widgets/shape.rb +++ b/lacci/lib/shoes/drawables/shape.rb @@ -5,19 +5,19 @@ module Shoes # ovals, arcs, stars, etc. into a single drawn shape. # # In Shoes3, a Shape isn't really a Slot. It's a kind of DSL with drawing commands that happen - # to have the same name as the Art widgets like star, arc, etc. Here we're treating it as - # a slot containing those widgets, which is wrong but not *too* wrong. + # to have the same name as the Art drawables like star, arc, etc. Here we're treating it as + # a slot containing those drawables, which is wrong but not *too* wrong. # # @incompatibility A Shoes3 Shape is *not* a slot; Scarpe does *not* do union shapes class Shape < Shoes::Slot - display_properties :left, :top, :shape_commands, :draw_context + shoes_styles :left, :top, :shape_commands, :draw_context def initialize(left: nil, top: nil, &block) @shape_commands = [] @draw_context = Shoes::App.instance.current_draw_context super - create_display_widget + create_display_drawable Shoes::App.instance.with_slot(self, &block) if block_given? end diff --git a/lacci/lib/shoes/widgets/slot.rb b/lacci/lib/shoes/drawables/slot.rb similarity index 91% rename from lacci/lib/shoes/widgets/slot.rb rename to lacci/lib/shoes/drawables/slot.rb index 318953975..a0df3c9c9 100644 --- a/lacci/lib/shoes/widgets/slot.rb +++ b/lacci/lib/shoes/drawables/slot.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class Shoes::Slot < Shoes::Widget +class Shoes::Slot < Shoes::Drawable # @incompatibility Shoes uses #content, not #children, for this attr_reader :children @@ -19,7 +19,7 @@ def add_child(child) @children << child end - # Get a list of child widgets + # Get a list of child drawables def contents @children ||= [] @children.dup @@ -41,7 +41,7 @@ def app(&block) Shoes::App.instance end - # Remove all children from this widget. If a block + # Remove all children from this drawable. If a block # is given, call the block to replace the children with # new contents from that block. # @@ -50,7 +50,7 @@ def app(&block) # # @incompatibility Shoes Classic calls the clear block with current self, while Scarpe uses the Shoes::App as self # - # @yield The block to call to replace the contents of the widget (optional) + # @yield The block to call to replace the contents of the drawable (optional) # @return [void] def clear(&block) @children.dup.each(&:destroy) diff --git a/lacci/lib/shoes/widgets/span.rb b/lacci/lib/shoes/drawables/span.rb similarity index 65% rename from lacci/lib/shoes/widgets/span.rb rename to lacci/lib/shoes/drawables/span.rb index b072f7527..103d8ff47 100644 --- a/lacci/lib/shoes/widgets/span.rb +++ b/lacci/lib/shoes/drawables/span.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true module Shoes - class Span < Shoes::Widget - display_properties :text, :stroke, :size, :font, :html_attributes + class Span < Shoes::Drawable + shoes_styles :text, :stroke, :size, :font, :html_attributes def initialize(text, stroke: nil, size: :span, font: nil, **html_attributes) super @@ -13,13 +13,13 @@ def initialize(text, stroke: nil, size: :span, font: nil, **html_attributes) @font = font @html_attributes = html_attributes - create_display_widget + create_display_drawable end def replace(text) @text = text - # This should signal the display widget to change + # This should signal the display drawable to change self.text = @text end end diff --git a/lacci/lib/shoes/widgets/stack.rb b/lacci/lib/shoes/drawables/stack.rb similarity index 73% rename from lacci/lib/shoes/widgets/stack.rb rename to lacci/lib/shoes/drawables/stack.rb index 999484633..316c796c8 100644 --- a/lacci/lib/shoes/widgets/stack.rb +++ b/lacci/lib/shoes/drawables/stack.rb @@ -7,7 +7,7 @@ class Stack < Shoes::Slot include Shoes::Spacing # TODO: sort out various margin and padding properties, including putting stuff into spacing - display_properties :width, :height, :scroll + shoes_styles :width, :height, :scroll def initialize(width: nil, height: nil, margin: nil, padding: nil, scroll: false, margin_top: nil, margin_bottom: nil, margin_left: nil, margin_right: nil, **options, &block) @@ -16,8 +16,8 @@ def initialize(width: nil, height: nil, margin: nil, padding: nil, scroll: false super - create_display_widget - # Create the display-side widget *before* running the block, which will add child widgets with their display widgets + create_display_drawable + # Create the display-side drawable *before* running the block, which will add child drawables with their display drawables Shoes::App.instance.with_slot(self, &block) if block_given? end end diff --git a/lacci/lib/shoes/widgets/star.rb b/lacci/lib/shoes/drawables/star.rb similarity index 78% rename from lacci/lib/shoes/widgets/star.rb rename to lacci/lib/shoes/drawables/star.rb index 5513d6265..77603916e 100644 --- a/lacci/lib/shoes/widgets/star.rb +++ b/lacci/lib/shoes/drawables/star.rb @@ -1,12 +1,12 @@ # frozen_string_literal: true module Shoes - class Star < Shoes::Widget - display_properties :left, :top, :points, :outer, :inner, :draw_context + class Star < Shoes::Drawable + shoes_styles :left, :top, :draw_context - display_property(:points) { |val| convert_to_integer(val, "points") } - display_property(:outer) { |val| convert_to_float(val, "outer") } - display_property(:inner) { |val| convert_to_float(val, "inner") } + shoes_style(:points) { |val| convert_to_integer(val, "points") } + shoes_style(:outer) { |val| convert_to_float(val, "outer") } + shoes_style(:inner) { |val| convert_to_float(val, "inner") } def initialize(left, top, points = 10, outer = 100, inner = 50) super @@ -14,7 +14,7 @@ def initialize(left, top, points = 10, outer = 100, inner = 50) @draw_context = Shoes::App.instance.current_draw_context - create_display_widget + create_display_drawable end private diff --git a/lacci/lib/shoes/widgets/subscription_item.rb b/lacci/lib/shoes/drawables/subscription_item.rb similarity index 86% rename from lacci/lib/shoes/widgets/subscription_item.rb rename to lacci/lib/shoes/drawables/subscription_item.rb index 63745e798..8e553577a 100644 --- a/lacci/lib/shoes/widgets/subscription_item.rb +++ b/lacci/lib/shoes/drawables/subscription_item.rb @@ -2,18 +2,18 @@ # Certain Shoes calls like motion and keydown are basically an # event subscription, with no other visible presence. However, -# they have a place in the widget tree and can be deleted. +# they have a place in the drawable tree and can be deleted. # # Depending on the display library they may not have any # direct visual (or similar) presence there either. # -# Inheriting from Widget gives these a parent slot and a +# Inheriting from Drawable gives these a parent slot and a # linkable_id automatically. # # Events not yet implemented: start, finish events for slots - # start is first draw, finish is widget destroyed -class Shoes::SubscriptionItem < Shoes::Widget - display_properties :shoes_api_name, :args +class Shoes::SubscriptionItem < Shoes::Drawable + shoes_styles :shoes_api_name, :args def initialize(args: [], shoes_api_name:, &block) super @@ -34,7 +34,7 @@ def initialize(args: [], shoes_api_name:, &block) @callback.call end when "hover" - # Hover passes the Shoes widget as the block param + # Hover passes the Shoes drawable as the block param @unsub_id = bind_self_event("hover") do @callback&.call(self) end @@ -77,9 +77,9 @@ def initialize(args: [], shoes_api_name:, &block) @callback&.call(*args) end - # This won't create a visible display widget, but will turn into - # an invisible widget and a stream of events. - create_display_widget + # This won't create a visible display drawable, but will turn into + # an invisible drawable and a stream of events. + create_display_drawable end def destroy diff --git a/lacci/lib/shoes/drawables/text_drawable.rb b/lacci/lib/shoes/drawables/text_drawable.rb new file mode 100644 index 000000000..6beacb298 --- /dev/null +++ b/lacci/lib/shoes/drawables/text_drawable.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +# Shoes::TextDrawable + +module Shoes + class TextDrawable < Shoes::Drawable + class << self + # rubocop:disable Lint/MissingSuper + def inherited(subclass) + Shoes::Drawable.drawable_classes ||= [] + Shoes::Drawable.drawable_classes << subclass + + Shoes::Drawable.drawable_default_styles ||= {} + Shoes::Drawable.drawable_default_styles[subclass] = {} + end + # rubocop:enable Lint/MissingSuper + end + end + + class << self + def default_text_drawable_with(element) + class_name = element.capitalize + + drawable_class = Class.new(Shoes::TextDrawable) do + # Can we just change content to text to match the Shoes API? + shoes_style :content + + def initialize(content) + super + + @content = content + + create_display_drawable + end + + def text + self.content + end + + def text=(new_text) + self.content = new_text + end + end + Shoes.const_set class_name, drawable_class + drawable_class.class_eval do + shoes_style :content + end + end + end +end + +Shoes.default_text_drawable_with(:code) +Shoes.default_text_drawable_with(:em) +Shoes.default_text_drawable_with(:strong) diff --git a/lacci/lib/shoes/widgets/video.rb b/lacci/lib/shoes/drawables/video.rb similarity index 61% rename from lacci/lib/shoes/widgets/video.rb rename to lacci/lib/shoes/drawables/video.rb index 7e00acd8f..9df02f1b7 100644 --- a/lacci/lib/shoes/widgets/video.rb +++ b/lacci/lib/shoes/drawables/video.rb @@ -1,13 +1,13 @@ # frozen_string_literal: true module Shoes - class Video < Shoes::Widget - display_properties :url + class Video < Shoes::Drawable + shoes_styles :url def initialize(url) super @url = url - create_display_widget + create_display_drawable end # other methods diff --git a/lacci/lib/shoes/spacing.rb b/lacci/lib/shoes/spacing.rb index 9af9b9ed3..3472ca15c 100644 --- a/lacci/lib/shoes/spacing.rb +++ b/lacci/lib/shoes/spacing.rb @@ -3,7 +3,7 @@ module Shoes module Spacing def self.included(includer) - includer.display_properties :margin, :padding, :margin_top, :margin_left, :margin_right, :margin_bottom, :options + includer.shoes_styles :margin, :padding, :margin_top, :margin_left, :margin_right, :margin_bottom, :options end end end diff --git a/lacci/lib/shoes/widgets.rb b/lacci/lib/shoes/widgets.rb deleted file mode 100644 index 41325c4a3..000000000 --- a/lacci/lib/shoes/widgets.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -require "shoes/widgets/slot" -require "shoes/widgets/stack" -require "shoes/widgets/flow" -require "shoes/widgets/document_root" - -require "shoes/widgets/text_widget" - -require "shoes/widgets/font" -require "shoes/widgets/subscription_item" - -require "shoes/widgets/arc" -require "shoes/widgets/line" -require "shoes/widgets/shape" -require "shoes/widgets/star" - -require "shoes/widgets/alert" -require "shoes/widgets/button" -require "shoes/widgets/check" -require "shoes/widgets/edit_box" -require "shoes/widgets/edit_line" -require "shoes/widgets/image" -require "shoes/widgets/link" -require "shoes/widgets/list_box" -require "shoes/widgets/para" -require "shoes/widgets/radio" -require "shoes/widgets/span" -require "shoes/widgets/video" diff --git a/lacci/lib/shoes/widgets/text_widget.rb b/lacci/lib/shoes/widgets/text_widget.rb deleted file mode 100644 index 3a16a586f..000000000 --- a/lacci/lib/shoes/widgets/text_widget.rb +++ /dev/null @@ -1,54 +0,0 @@ -# frozen_string_literal: true - -# Shoes::TextWidget - -module Shoes - class TextWidget < Shoes::Widget - class << self - # rubocop:disable Lint/MissingSuper - def inherited(subclass) - Shoes::Widget.widget_classes ||= [] - Shoes::Widget.widget_classes << subclass - - Shoes::Widget.widget_default_styles ||= {} - Shoes::Widget.widget_default_styles[subclass] = {} - end - # rubocop:enable Lint/MissingSuper - end - end - - class << self - def default_text_widget_with(element) - class_name = element.capitalize - - widget_class = Class.new(Shoes::TextWidget) do - # Can we just change content to text to match the Shoes API? - display_property :content - - def initialize(content) - super - - @content = content - - create_display_widget - end - - def text - self.content - end - - def text=(new_text) - self.content = new_text - end - end - Shoes.const_set class_name, widget_class - widget_class.class_eval do - display_property :content - end - end - end -end - -Shoes.default_text_widget_with(:code) -Shoes.default_text_widget_with(:em) -Shoes.default_text_widget_with(:strong) diff --git a/lib/scarpe/cats_cradle.rb b/lib/scarpe/cats_cradle.rb index b49d1777e..c6c25afbf 100644 --- a/lib/scarpe/cats_cradle.rb +++ b/lib/scarpe/cats_cradle.rb @@ -6,8 +6,8 @@ require "fiber" module Scarpe::Test - # We'd like something we can call Shoes widget methods on, such as para.replace. - # But we'd also like to be able to grab the corresponding display widget and + # We'd like something we can call Shoes drawable methods on, such as para.replace. + # But we'd also like to be able to grab the corresponding display drawable and # call some of *those* methods. class CCProxy attr_reader :display @@ -16,7 +16,7 @@ class CCProxy def initialize(obj) @obj = obj # TODO: how to do this with Webview relay? Proxy object to send a message, maybe? - @display = ::Shoes::DisplayService.display_service.query_display_widget_for(obj.linkable_id) + @display = ::Shoes::DisplayService.display_service.query_display_drawable_for(obj.linkable_id) end def method_missing(method, ...) @@ -136,24 +136,24 @@ def on_event(event, &block) @waiting_fibers << { promise: event_promise(event), fiber: f } end - # What to do about TextWidgets? Link, code, em, strong? + # What to do about TextDrawables? Link, code, em, strong? # Also, wait, what's up with span? What *is* that? - Shoes::Widget.widget_classes.each do |widget_class| - finder_name = widget_class.dsl_name + Shoes::Drawable.drawable_classes.each do |drawable_class| + finder_name = drawable_class.dsl_name define_method(finder_name) do |*args| app = Shoes::App.instance - widgets = app.find_widgets_by(widget_class, *args) - raise Scarpe::MultipleWidgetsFoundError, "Found more than one #{finder_name} matching #{args.inspect}!" if widgets.size > 1 - raise Scarpe::NoWidgetsFoundError, "Found no #{finder_name} matching #{args.inspect}!" if widgets.empty? + drawables = app.find_drawables_by(drawable_class, *args) + raise Scarpe::MultipleDrawablesFoundError, "Found more than one #{finder_name} matching #{args.inspect}!" if drawables.size > 1 + raise Scarpe::NoDrawablesFoundError, "Found no #{finder_name} matching #{args.inspect}!" if drawables.empty? - CCProxy.new(widgets[0]) + CCProxy.new(drawables[0]) end end - def proxy_for(shoes_widget) - CCProxy.new(shoes_widget) + def proxy_for(shoes_drawable) + CCProxy.new(shoes_drawable) end def die_after(time) diff --git a/lib/scarpe/errors.rb b/lib/scarpe/errors.rb index d299bb3c4..d8ea10fb3 100644 --- a/lib/scarpe/errors.rb +++ b/lib/scarpe/errors.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class Scarpe +module Scarpe class UnknownShoesEventAPIError < Scarpe::Error; end class UnknownShapeCommandError < Scarpe::Error; end @@ -9,9 +9,9 @@ class UnknownEventTypeError < Scarpe::Error; end class UnexpectedFiberTransferError < Scarpe::Error; end - class MultipleWidgetsFoundError < Scarpe::Error; end + class MultipleDrawablesFoundError < Scarpe::Error; end - class NoWidgetsFoundError < Scarpe::Error; end + class NoDrawablesFoundError < Scarpe::Error; end class InvalidPromiseError < Scarpe::Error; end @@ -51,8 +51,6 @@ class InvalidOperationError < Scarpe::Error; end class MissingAttributeError < Scarpe::Error; end - class SearchWidgetError < Scarpe::Error; end - # This error indicates a problem when running ConfirmedEval class JSEvalError < Scarpe::Error def initialize(data) diff --git a/lib/scarpe/version.rb b/lib/scarpe/version.rb index 3ac17e9c2..5d81b6d00 100644 --- a/lib/scarpe/version.rb +++ b/lib/scarpe/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -class Scarpe - VERSION = "0.2.2" +module Scarpe + VERSION = "0.3.0" end diff --git a/lib/scarpe/wv.rb b/lib/scarpe/wv.rb index 0ad05bf41..6832cfc5f 100644 --- a/lib/scarpe/wv.rb +++ b/lib/scarpe/wv.rb @@ -16,7 +16,7 @@ module Scarpe::Webview HTML = Scarpe::Components::HTML - class Widget < Shoes::Linkable + class Drawable < Shoes::Linkable # This is where we would make the HTML renderer modular by choosing another require "scarpe/components/calzini" include Scarpe::Components::Calzini @@ -40,7 +40,7 @@ class Widget < Shoes::Linkable require_relative "wv/web_wrangler" require_relative "wv/control_interface" -require_relative "wv/widget" +require_relative "wv/drawable" require_relative "wv/star" require_relative "wv/radio" @@ -64,7 +64,7 @@ class Widget < Shoes::Linkable require_relative "wv/span" require_relative "wv/shape" -require_relative "wv/text_widget" +require_relative "wv/text_drawable" require_relative "wv/link" require_relative "wv/line" require_relative "wv/video" diff --git a/lib/scarpe/wv/alert.rb b/lib/scarpe/wv/alert.rb index 9c379029e..1fe628847 100644 --- a/lib/scarpe/wv/alert.rb +++ b/lib/scarpe/wv/alert.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Scarpe::Webview - class Alert < Widget + class Alert < Drawable def initialize(properties) super diff --git a/lib/scarpe/wv/app.rb b/lib/scarpe/wv/app.rb index 813cbbcd1..d67c5541b 100644 --- a/lib/scarpe/wv/app.rb +++ b/lib/scarpe/wv/app.rb @@ -2,7 +2,7 @@ module Scarpe::Webview # Scarpe::Webview::App must only be used from the main thread, due to GTK+ limitations. - class App < Widget + class App < Drawable attr_reader :control_interface attr_writer :shoes_linkable_id @@ -80,14 +80,14 @@ def destroy end end - # All JS callbacks to Scarpe widgets are dispatched + # All JS callbacks to Scarpe drawables are dispatched # via this handler def handle_callback(name, *args) @callbacks[name].call(*args) end # Bind a Scarpe callback name; see handle_callback above. - # See Scarpe::Widget for how the naming is set up + # See Scarpe::Drawable for how the naming is set up def bind(name, &block) @callbacks[name] = block end diff --git a/lib/scarpe/wv/arc.rb b/lib/scarpe/wv/arc.rb index 7946e21f6..ef8d9b930 100644 --- a/lib/scarpe/wv/arc.rb +++ b/lib/scarpe/wv/arc.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Scarpe::Webview - class Arc < Widget + class Arc < Drawable def initialize(properties) super(properties) end diff --git a/lib/scarpe/wv/button.rb b/lib/scarpe/wv/button.rb index 1ef842472..3b616ff8b 100644 --- a/lib/scarpe/wv/button.rb +++ b/lib/scarpe/wv/button.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Scarpe::Webview - class Button < Widget + class Button < Drawable def initialize(properties) super diff --git a/lib/scarpe/wv/check.rb b/lib/scarpe/wv/check.rb index 3067421b8..7ae1b4bd1 100644 --- a/lib/scarpe/wv/check.rb +++ b/lib/scarpe/wv/check.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Scarpe::Webview - class Check < Widget + class Check < Drawable attr_reader :text def initialize(properties) diff --git a/lib/scarpe/wv/widget.rb b/lib/scarpe/wv/drawable.rb similarity index 79% rename from lib/scarpe/wv/widget.rb rename to lib/scarpe/wv/drawable.rb index 2c4ab95f2..3dd6fd6b6 100644 --- a/lib/scarpe/wv/widget.rb +++ b/lib/scarpe/wv/drawable.rb @@ -1,10 +1,10 @@ # frozen_string_literal: true module Scarpe::Webview - # The Webview::Widget parent class helps connect a Webview widget with + # The Webview::Drawable parent class helps connect a Webview drawable with # its Shoes equivalent, render itself to the Webview DOM, handle # Javascript events and generally keep things working in Webview. - class Widget < Shoes::Linkable + class Drawable < Shoes::Linkable # This will pick up the log implementation from wv.rb include Shoes::Log @@ -14,7 +14,7 @@ def display_class_for(scarpe_class_name) scarpe_class = Shoes.const_get(scarpe_class_name) unless scarpe_class.ancestors.include?(Shoes::Linkable) raise Scarpe::InvalidClassError, "Scarpe Webview can only get display classes for Shoes " + - "linkable widgets, not #{scarpe_class_name.inspect}!" + "linkable drawables, not #{scarpe_class_name.inspect}!" end klass = Scarpe::Webview.const_get(scarpe_class_name.split("::")[-1]) @@ -26,21 +26,21 @@ def display_class_for(scarpe_class_name) end end - # The Shoes ID corresponding to the Shoes widget for this Webview widget + # The Shoes ID corresponding to the Shoes drawable for this Webview drawable attr_reader :shoes_linkable_id - # The Webview::Widget parent of this widget + # The Webview::Drawable parent of this drawable attr_reader :parent - # An array of Webview::Widget children (possibly empty) of this widget + # An array of Webview::Drawable children (possibly empty) of this drawable attr_reader :children - # Set instance variables for the display properties of this widget. Bind Shoes - # events for changes of parent widget and changes of property values. + # Set instance variables for the Shoes styles of this drawable. Bind Shoes + # events for changes of parent drawable and changes of property values. def initialize(properties) - log_init("Webview::Widget") + log_init("Webview::Drawable") - @display_property_names = properties.keys.map(&:to_s) - ["shoes_linkable_id"] + @shoes_style_names = properties.keys.map(&:to_s) - ["shoes_linkable_id"] # Call method, which looks up the parent @shoes_linkable_id = properties["shoes_linkable_id"] || properties[:shoes_linkable_id] @@ -48,22 +48,22 @@ def initialize(properties) raise Scarpe::MissingAttributeError, "Could not find property shoes_linkable_id in #{properties.inspect}!" end - # Set the display properties + # Set the Shoes styles as instance variables properties.each do |k, v| next if k == "shoes_linkable_id" instance_variable_set("@" + k.to_s, v) end - # The parent field is *almost* simple enough that a typed display property would handle it. + # The parent field is *almost* simple enough that a validated Shoes style would handle it. bind_shoes_event(event_name: "parent", target: shoes_linkable_id) do |new_parent_id| - display_parent = DisplayService.instance.query_display_widget_for(new_parent_id) + display_parent = DisplayService.instance.query_display_drawable_for(new_parent_id) if @parent != display_parent set_parent(display_parent) end end - # When Shoes widgets change properties, we get a change notification here + # When Shoes drawables change properties, we get a change notification here bind_shoes_event(event_name: "prop_change", target: shoes_linkable_id) do |prop_changes| prop_changes.each do |k, v| instance_variable_set("@" + k, v) @@ -78,23 +78,23 @@ def initialize(properties) super(linkable_id: @shoes_linkable_id) end - def display_properties + def shoes_styles p = {} - @display_property_names.each do |prop_name| + @shoes_style_names.each do |prop_name| p[prop_name] = instance_variable_get("@#{prop_name}") end p end # Properties_changed will be called automatically when properties change. - # The widget should delete any changes from the Hash that it knows how + # The drawable should delete any changes from the Hash that it knows how # to incrementally handle, and pass the rest to super. If any changes # go entirely un-handled, a full redraw will be scheduled. # This exists to be overridden by children watching for changes. # # @param changes [Hash] a Hash of new values for properties that have changed def properties_changed(changes) - # If a widget does something really nonstandard with its html_id or element, it will + # If a drawable does something really nonstandard with its html_id or element, it will # need to override to prevent this from happening. That's easy enough, though. if changes.key?("hidden") hidden = changes.delete("hidden") @@ -110,7 +110,7 @@ def properties_changed(changes) needs_update! unless changes.empty? end - # Give this widget a new parent, including managing the appropriate child lists for parent widgets. + # Give this drawable a new parent, including managing the appropriate child lists for parent drawables. def set_parent(new_parent) @parent&.remove_child(self) new_parent&.add_child(self) @@ -181,7 +181,7 @@ def style public # This gets a mini-webview for just this element and its children, if any. - # It is normally called by the widget itself to do its DOM management. + # It is normally called by the drawable itself to do its DOM management. # # @return [Scarpe::WebWrangler::ElementWrangler] a DOM object manager def html_element @@ -218,15 +218,15 @@ def to_html # This binds a Scarpe JS callback, handled via a single dispatch point in the app # - # @param event [String] the Scarpe widget event name + # @param event [String] the Scarpe drawable event name # @yield the block to call when the event occurs def bind(event, &block) - raise(Scarpe::MissingAttributeError, "Widget has no linkable_id! #{inspect}") unless linkable_id + raise(Scarpe::MissingAttributeError, "Drawable has no linkable_id! #{inspect}") unless linkable_id DisplayService.instance.app.bind("#{linkable_id}-#{event}", &block) end - # Removes the element from both the Ruby Widget tree and the HTML DOM. + # Removes the element from both the Ruby Drawable tree and the HTML DOM. # Return a promise for when that HTML change will be visible. # # @return [Scarpe::Promise] a promise that is fulfilled when the HTML change is complete @@ -235,7 +235,7 @@ def destroy_self html_element.remove end - # Request a full redraw of all widgets. + # Request a full redraw of all drawables. # # It's really hard to do dirty-tracking here because the redraws are fully asynchronous. # And so we can't easily cancel one "in flight," and we can't easily pick up the latest @@ -246,13 +246,13 @@ def needs_update! DisplayService.instance.app.request_redraw! end - # Generate JS code to trigger a specific event name on this widget with the supplies arguments. + # Generate JS code to trigger a specific event name on this drawable with the supplies arguments. # # @param handler_function_name [String] the event name - @see #bind # @param args [Array] additional arguments that will be passed to the event in the generated JS # @return [String] the generated JS code def handler_js_code(handler_function_name, *args) - raise(Scarpe::MissingAttributeError, "Widget has no linkable_id! #{inspect}") unless linkable_id + raise(Scarpe::MissingAttributeError, "Drawable has no linkable_id! #{inspect}") unless linkable_id js_args = ["'#{linkable_id}-#{handler_function_name}'", *args].join(", ") "scarpeHandler(#{js_args})" diff --git a/lib/scarpe/wv/edit_box.rb b/lib/scarpe/wv/edit_box.rb index 757aa844f..7a585a663 100644 --- a/lib/scarpe/wv/edit_box.rb +++ b/lib/scarpe/wv/edit_box.rb @@ -1,13 +1,13 @@ # frozen_string_literal: true module Scarpe::Webview - class EditBox < Widget + class EditBox < Drawable attr_reader :text, :height, :width def initialize(properties) super - # The JS handler sends a "change" event, which we forward to the Shoes widget tree + # The JS handler sends a "change" event, which we forward to the Shoes drawable tree bind("change") do |new_text| send_self_event(new_text, event_name: "change") end diff --git a/lib/scarpe/wv/edit_line.rb b/lib/scarpe/wv/edit_line.rb index b6784d274..88b9413c6 100644 --- a/lib/scarpe/wv/edit_line.rb +++ b/lib/scarpe/wv/edit_line.rb @@ -1,13 +1,13 @@ # frozen_string_literal: true module Scarpe::Webview - class EditLine < Widget + class EditLine < Drawable attr_reader :text, :width def initialize(properties) super - # The JS handler sends a "change" event, which we forward to the Shoes widget tree + # The JS handler sends a "change" event, which we forward to the Shoes drawable tree bind("change") do |new_text| send_self_event(new_text, event_name: "change") end diff --git a/lib/scarpe/wv/font.rb b/lib/scarpe/wv/font.rb index 04527608f..f8c219be4 100644 --- a/lib/scarpe/wv/font.rb +++ b/lib/scarpe/wv/font.rb @@ -3,7 +3,7 @@ require "scarpe/components/base64" module Scarpe::Webview - class Font < Widget + class Font < Drawable include Scarpe::Components::Base64 attr_accessor :font diff --git a/lib/scarpe/wv/image.rb b/lib/scarpe/wv/image.rb index 212c8ad93..1e1d1e7a8 100644 --- a/lib/scarpe/wv/image.rb +++ b/lib/scarpe/wv/image.rb @@ -3,7 +3,7 @@ require "scarpe/components/base64" module Scarpe::Webview - class Image < Widget + class Image < Drawable include Scarpe::Components::Base64 def initialize(properties) diff --git a/lib/scarpe/wv/line.rb b/lib/scarpe/wv/line.rb index de9bc6057..70cb462b4 100644 --- a/lib/scarpe/wv/line.rb +++ b/lib/scarpe/wv/line.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Scarpe::Webview - class Line < Widget + class Line < Drawable def initialize(properties) super(properties) end diff --git a/lib/scarpe/wv/link.rb b/lib/scarpe/wv/link.rb index 19b85d737..06a0f8214 100644 --- a/lib/scarpe/wv/link.rb +++ b/lib/scarpe/wv/link.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Scarpe::Webview - class Link < Widget + class Link < Drawable def initialize(properties) super diff --git a/lib/scarpe/wv/list_box.rb b/lib/scarpe/wv/list_box.rb index d56c2d89a..fd7806ec5 100644 --- a/lib/scarpe/wv/list_box.rb +++ b/lib/scarpe/wv/list_box.rb @@ -1,13 +1,12 @@ # frozen_string_literal: true module Scarpe::Webview - class ListBox < Widget + class ListBox < Drawable attr_reader :selected_item, :items, :height, :width, :choose def initialize(properties) super(properties) - # The JS handler sends a "change" event, which we forward to the Shoes widget tree bind("change") do |new_item| send_self_event(new_item, event_name: "change") end diff --git a/lib/scarpe/wv/para.rb b/lib/scarpe/wv/para.rb index fc4c79787..1ecf499e7 100644 --- a/lib/scarpe/wv/para.rb +++ b/lib/scarpe/wv/para.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Scarpe::Webview - class Para < Widget + class Para < Drawable # Currently this is duplicated in Calzini. How to refactor? # Similarly, we make some assumptions about when size is a symbol # versus string that may not survive JSON deserialization. @@ -41,7 +41,7 @@ def items_to_display_children(items) if item.is_a?(String) item else - Scarpe::Webview::DisplayService.instance.query_display_widget_for(item) + Scarpe::Webview::DisplayService.instance.query_display_drawable_for(item) end end end @@ -51,7 +51,7 @@ def element(&block) end # Because para's to_html takes a block, and it needs to convert IDs into display - # widgets, it needs to also override to_html + # drawables, it needs to also override to_html def to_html @children ||= [] diff --git a/lib/scarpe/wv/radio.rb b/lib/scarpe/wv/radio.rb index 052244691..769bf3ac4 100644 --- a/lib/scarpe/wv/radio.rb +++ b/lib/scarpe/wv/radio.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Scarpe::Webview - class Radio < Widget + class Radio < Drawable # TODO: is this needed? attr_reader :text @@ -21,7 +21,7 @@ def properties_changed(changes) end def element - props = display_properties + props = shoes_styles # If a group isn't set, default to the linkable ID of the parent slot unless @group diff --git a/lib/scarpe/wv/shape.rb b/lib/scarpe/wv/shape.rb index 0586c0aec..884075cbe 100644 --- a/lib/scarpe/wv/shape.rb +++ b/lib/scarpe/wv/shape.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Scarpe::Webview - class Shape < Widget + class Shape < Drawable def initialize(properties) super(properties) diff --git a/lib/scarpe/wv/slot.rb b/lib/scarpe/wv/slot.rb index 7ac835adb..4f182b571 100644 --- a/lib/scarpe/wv/slot.rb +++ b/lib/scarpe/wv/slot.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Scarpe::Webview - class Slot < Widget + class Slot < Drawable def initialize(properties) @event_callbacks = {} @@ -9,7 +9,7 @@ def initialize(properties) end def element(&block) - props = display_properties.merge("html_attributes" => html_attributes) + props = shoes_styles.merge("html_attributes" => html_attributes) render_name = self.class.name.split("::")[-1].downcase # usually "stack" or "flow" or "documentroot" render(render_name, props, &block) end diff --git a/lib/scarpe/wv/span.rb b/lib/scarpe/wv/span.rb index 15374e135..222bb55a8 100644 --- a/lib/scarpe/wv/span.rb +++ b/lib/scarpe/wv/span.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Scarpe::Webview - class Span < Widget + class Span < Drawable SIZES = { inscription: 10, ins: 10, diff --git a/lib/scarpe/wv/star.rb b/lib/scarpe/wv/star.rb index d37b6337d..bea5d5d73 100644 --- a/lib/scarpe/wv/star.rb +++ b/lib/scarpe/wv/star.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Scarpe::Webview - class Star < Widget + class Star < Drawable def initialize(properties) super(properties) end diff --git a/lib/scarpe/wv/subscription_item.rb b/lib/scarpe/wv/subscription_item.rb index 8855f764e..809edf1ab 100644 --- a/lib/scarpe/wv/subscription_item.rb +++ b/lib/scarpe/wv/subscription_item.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class Scarpe::Webview::SubscriptionItem < Scarpe::Webview::Widget +class Scarpe::Webview::SubscriptionItem < Scarpe::Webview::Drawable def initialize(properties) super @@ -48,7 +48,7 @@ def set_parent(new_parent) case @shoes_api_name when "motion" # TODO: what do we do for whole-screen mousemove outside the window? - # Those should be set on body, which right now doesn't have a widget. + # Those should be set on body, which right now doesn't have a drawable. # TODO: figure out how to handle alt and meta keys - does Shoes3 recognise those? new_parent.set_event_callback( self, diff --git a/lib/scarpe/wv/text_widget.rb b/lib/scarpe/wv/text_drawable.rb similarity index 51% rename from lib/scarpe/wv/text_widget.rb rename to lib/scarpe/wv/text_drawable.rb index 2ef98e95c..67ead3e7f 100644 --- a/lib/scarpe/wv/text_widget.rb +++ b/lib/scarpe/wv/text_drawable.rb @@ -1,13 +1,13 @@ # frozen_string_literal: true module Scarpe::Webview - class TextWidget < Widget + class TextDrawable < Drawable end class << self - def default_wv_text_widget_with(element) + def default_wv_text_drawable_with(element) webview_class_name = element.capitalize - webview_widget_class = Class.new(Scarpe::Webview::TextWidget) do + webview_drawable_class = Class.new(Scarpe::Webview::TextDrawable) do def initialize(properties) class_name = self.class.name.split("::")[-1] @html_tag = class_name.delete_prefix("Webview").downcase @@ -18,11 +18,11 @@ def element render(@html_tag) { @content.to_s } end end - Scarpe::Webview.const_set webview_class_name, webview_widget_class + Scarpe::Webview.const_set webview_class_name, webview_drawable_class end end end -Scarpe::Webview.default_wv_text_widget_with(:code) -Scarpe::Webview.default_wv_text_widget_with(:em) -Scarpe::Webview.default_wv_text_widget_with(:strong) +Scarpe::Webview.default_wv_text_drawable_with(:code) +Scarpe::Webview.default_wv_text_drawable_with(:em) +Scarpe::Webview.default_wv_text_drawable_with(:strong) diff --git a/lib/scarpe/wv/video.rb b/lib/scarpe/wv/video.rb index b41916082..e71f1d7f7 100644 --- a/lib/scarpe/wv/video.rb +++ b/lib/scarpe/wv/video.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Scarpe::Webview - class Video < Widget + class Video < Drawable SUPPORTED_FORMATS = { "video/mp4" => [".mp4"], "video/webp" => [".webp"], @@ -27,7 +27,7 @@ def initialize(properties) end def element - render "video", display_properties.merge("format" => @format) + render "video", shoes_styles.merge("format" => @format) end end end diff --git a/lib/scarpe/wv/web_wrangler.rb b/lib/scarpe/wv/web_wrangler.rb index cd3cd30f2..9eaa2cdb2 100644 --- a/lib/scarpe/wv/web_wrangler.rb +++ b/lib/scarpe/wv/web_wrangler.rb @@ -10,7 +10,7 @@ module Scarpe::Webview # The Scarpe WebWrangler, for Webview, manages a lot of Webviews quirks. It provides - # a simpler underlying abstraction for DOMWrangler and the Webview widgets. + # a simpler underlying abstraction for DOMWrangler and the Webview drawables. # Webview can be picky - if you send it too many messages, it can crash. If the # messages you send it are too large, it can crash. If you don't return control # to its event loop, it can crash. It doesn't save references to all event handlers, @@ -725,12 +725,12 @@ def schedule_waiting_changes end end - # An ElementWrangler provides a way for a Widget to manipulate is DOM element(s) - # via their HTML IDs. The most straightforward Widgets can have a single HTML ID + # An ElementWrangler provides a way for a Drawable to manipulate is DOM element(s) + # via their HTML IDs. The most straightforward Drawables can have a single HTML ID # and use a single ElementWrangler to make any needed changes. # # For now we don't need an ElementWrangler to add DOM elements, just to manipulate them - # after initial render. New DOM objects for Widgets are normally added via full + # after initial render. New DOM objects for Drawables are normally added via full # redraws rather than incremental updates. # # Any changes made via ElementWrangler may be cancelled if a full redraw occurs, diff --git a/lib/scarpe/wv/webview_local_display.rb b/lib/scarpe/wv/webview_local_display.rb index 4a7d0ed35..cc6f323b4 100644 --- a/lib/scarpe/wv/webview_local_display.rb +++ b/lib/scarpe/wv/webview_local_display.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true -class Scarpe - # This is the simplest type of Webview DisplayService. It creates Webview widgets - # corresponding to Shoes widgets, manages the Webview and its DOM tree, and +module Scarpe + # This is the simplest type of Webview DisplayService. It creates Webview drawables + # corresponding to Shoes drawables, manages the Webview and its DOM tree, and # generally keeps the Shoes/Webview connection working. # # This is an in-process Webview-based display service, with all the limitations that @@ -20,7 +20,7 @@ class << self # The ControlInterface is used to handle internal events in Webview Scarpe attr_reader :control_interface - # The DocumentRoot is the top widget of the Webview-side widget tree + # The DocumentRoot is the top drawable of the Webview-side drawable tree attr_reader :doc_root # app is the Scarpe::Webview::App @@ -29,7 +29,7 @@ class << self # wrangler is the Scarpe::WebWrangler attr_reader :wrangler - # This is called before any of the various Webview::Widgets are created, to be + # This is called before any of the various Webview::Drawables are created, to be # able to create them and look them up. def initialize if Webview::DisplayService.instance @@ -41,18 +41,24 @@ def initialize super() log_init("Webview::DisplayService") - @display_widget_for = {} + @display_drawable_for = {} end - # Create a Webview display widget for a specific Shoes widget, and pair it with - # the linkable ID for this Shoes widget. + # Create a Webview display drawable for a specific Shoes drawable, and pair it with + # the linkable ID for this Shoes drawable. # - # @param widget_class_name [String] The class name of the Shoes widget, e.g. Shoes::Button - # @param widget_id [String] the linkable ID for widget events - # @param properties [Hash] a JSON-serialisable Hash with the widget's display properties - # @return [Webview::Widget] the newly-created Webview widget - def create_display_widget_for(widget_class_name, widget_id, properties) - if widget_class_name == "App" + # @param drawable_class_name [String] The class name of the Shoes drawable, e.g. Shoes::Button + # @param drawable_id [String] the linkable ID for drawable events + # @param properties [Hash] a JSON-serialisable Hash with the drawable's Shoes styles + # @return [Webview::Drawable] the newly-created Webview drawable + def create_display_drawable_for(drawable_class_name, drawable_id, properties) + existing = query_display_drawable_for(drawable_id, nil_ok: true) + if existing + @log.warn("There is already a display drawable for #{drawable_id.inspect}! Returning #{existing.class.name}.") + return existing + end + + if drawable_class_name == "App" unless @doc_root raise Scarpe::MissingDocRootError, "Webview::DocumentRoot is supposed to be created before Webview::App!" end @@ -64,23 +70,23 @@ def create_display_widget_for(widget_class_name, widget_id, properties) @app = @control_interface.app @wrangler = @control_interface.wrangler - set_widget_pairing(widget_id, display_app) + set_drawable_pairing(drawable_id, display_app) return display_app end - # Create a corresponding display widget - display_class = Scarpe::Webview::Widget.display_class_for(widget_class_name) - display_widget = display_class.new(properties) - set_widget_pairing(widget_id, display_widget) + # Create a corresponding display drawable + display_class = Scarpe::Webview::Drawable.display_class_for(drawable_class_name) + display_drawable = display_class.new(properties) + set_drawable_pairing(drawable_id, display_drawable) - if widget_class_name == "DocumentRoot" - # DocumentRoot is created before App. Mostly doc_root is just like any other widget, + if drawable_class_name == "DocumentRoot" + # DocumentRoot is created before App. Mostly doc_root is just like any other drawable, # but we'll want a reference to it when we create App. - @doc_root = display_widget + @doc_root = display_drawable end - display_widget + display_drawable end # Destroy the display service and the app. Quit the process (eventually.) diff --git a/lib/scarpe/wv/webview_relay_display.rb b/lib/scarpe/wv/webview_relay_display.rb index 662244ee9..aa22d5751 100644 --- a/lib/scarpe/wv/webview_relay_display.rb +++ b/lib/scarpe/wv/webview_relay_display.rb @@ -5,12 +5,12 @@ require_relative "webview_relay_util" -class Scarpe +module Scarpe # This display service creates a child process and sends events - # back and forth, but creates no widgets of its own. The child + # back and forth, but creates no drawables of its own. The child # process will spawn a worker with its own Webview::DisplayService # where the real Webview exists. By splitting the Webview - # process from the Shoes widgets, it can be easier to return + # process from the Shoes drawables, it can be easier to return # control to Webview's event handler promptly. Also, the Ruby # process could run background threads if it wanted, and # otherwise behave like a process ***not*** containing Webview. @@ -65,10 +65,10 @@ def run_event_loop self.destroy end - # This method sends a message to the worker process to create a widget. No actual - # widget is created or registered with the display service. - def create_display_widget_for(widget_class_name, widget_id, properties) - send_datagram({ type: :create, class_name: widget_class_name, id: widget_id, properties: }) + # This method sends a message to the worker process to create a drawable. No actual + # drawable is created or registered with the display service. + def create_display_drawable_for(drawable_class_name, drawable_id, properties) + send_datagram({ type: :create, class_name: drawable_class_name, id: drawable_id, properties: }) # Don't need to return anything. It wouldn't be used anyway. end diff --git a/lib/scarpe/wv/webview_relay_util.rb b/lib/scarpe/wv/webview_relay_util.rb index a9f401afb..14209d725 100644 --- a/lib/scarpe/wv/webview_relay_util.rb +++ b/lib/scarpe/wv/webview_relay_util.rb @@ -2,7 +2,7 @@ require "socket" -class Scarpe +module Scarpe # WVRelayUtil defines the datagram format for the sockets that connect a parent # Shoes application with a child display server. @@ -109,7 +109,7 @@ def respond_to_datagram elsif m_data["type"] == "create" raise Scarpe::InvalidOperationError, "Parent process should never receive :create datagram!" if @i_am == :parent - @wv_display.create_display_widget_for(m_data["class_name"], m_data["id"], m_data["properties"]) + @wv_display.create_display_drawable_for(m_data["class_name"], m_data["id"], m_data["properties"]) elsif m_data["type"] == "destroy" if @i_am == :parent @shutdown = true diff --git a/scarpe-components/Gemfile.lock b/scarpe-components/Gemfile.lock index 715f29160..c0704e223 100644 --- a/scarpe-components/Gemfile.lock +++ b/scarpe-components/Gemfile.lock @@ -1,12 +1,12 @@ PATH remote: ../lacci specs: - lacci (0.2.2) + lacci (0.3.0) PATH remote: . specs: - scarpe-components (0.2.2) + scarpe-components (0.3.0) GEM remote: https://rubygems.org/ diff --git a/scarpe-components/lib/scarpe/components/base64.rb b/scarpe-components/lib/scarpe/components/base64.rb index a61693516..87a1528f1 100644 --- a/scarpe-components/lib/scarpe/components/base64.rb +++ b/scarpe-components/lib/scarpe/components/base64.rb @@ -3,9 +3,9 @@ require "base64" require "uri" -class Scarpe; end +module Scarpe; end module Scarpe::Components; end -class Scarpe +module Scarpe module Components::Base64 def valid_url?(string) uri = URI.parse(string) diff --git a/scarpe-components/lib/scarpe/components/calzini.rb b/scarpe-components/lib/scarpe/components/calzini.rb index 59ed156f4..b03a5ff5f 100644 --- a/scarpe-components/lib/scarpe/components/calzini.rb +++ b/scarpe-components/lib/scarpe/components/calzini.rb @@ -2,10 +2,11 @@ require_relative "html" require_relative "base64" +require_relative "errors" -# Require all widget rendering code under calzini directory -Dir.glob("calzini/*.rb", base: __dir__) do |widget| - require_relative widget +# Require all drawable rendering code under calzini directory +Dir.glob("calzini/*.rb", base: __dir__) do |drawable| + require_relative drawable end # The Calzini module expects to be included by a class defining @@ -13,7 +14,7 @@ # # * html_id - the HTML ID for the specific rendered DOM object # * handler_js_code(event_name) - the JS handler code for this DOM object and event name -# * (optional) display_properties - the display properties for this object, unless overridden in render() +# * (optional) shoes_styles - the Shoes styles for this object, unless overridden in render() module Scarpe::Components::Calzini extend self @@ -32,8 +33,8 @@ module Scarpe::Components::Calzini }.freeze private_constant :SIZES - def render(widget, properties = display_properties, &block) - send("#{widget}_element", properties, &block) + def render(drawable, properties = shoes_styles, &block) + send("#{drawable}_element", properties, &block) end def empty_page_element @@ -88,7 +89,7 @@ def dimensions_length(value) end end - def widget_style(props) + def drawable_style(props) styles = {} if props["hidden"] styles[:display] = "none" diff --git a/scarpe-components/lib/scarpe/components/calzini/alert.rb b/scarpe-components/lib/scarpe/components/calzini/alert.rb index 438072ad0..da1dd9727 100644 --- a/scarpe-components/lib/scarpe/components/calzini/alert.rb +++ b/scarpe-components/lib/scarpe/components/calzini/alert.rb @@ -16,7 +16,7 @@ def alert_element(props) private - # If the whole widget is hidden, the parent style adds display:none + # If the whole drawable is hidden, the parent style adds display:none def alert_overlay_style(props) { position: "fixed", @@ -30,7 +30,7 @@ def alert_overlay_style(props) display: "flex", "align-items": "center", "justify-content": "center", - }.merge(widget_style(props)) + }.merge(drawable_style(props)) end def alert_modal_style diff --git a/scarpe-components/lib/scarpe/components/calzini/art_widgets.rb b/scarpe-components/lib/scarpe/components/calzini/art_widgets.rb index d991c7c64..9fe05ae91 100644 --- a/scarpe-components/lib/scarpe/components/calzini/art_widgets.rb +++ b/scarpe-components/lib/scarpe/components/calzini/art_widgets.rb @@ -41,7 +41,7 @@ def star_element(props, &block) private def arc_style(props) - widget_style(props).merge({ + drawable_style(props).merge({ left: "#{props["left"]}px", top: "#{props["top"]}px", width: "#{props["width"]}px", @@ -65,7 +65,7 @@ def arc_path(props) end def line_div_style(props) - widget_style(props).merge({ + drawable_style(props).merge({ left: "#{props["left"]}px", top: "#{props["top"]}px", }) @@ -79,7 +79,7 @@ def line_svg_style(props) end def star_style(props) - widget_style(props).merge({ + drawable_style(props).merge({ width: dimensions_length(props["width"]), height: dimensions_length(props["height"]), }).compact diff --git a/scarpe-components/lib/scarpe/components/calzini/button.rb b/scarpe-components/lib/scarpe/components/calzini/button.rb index e9bff40c1..6bc154a16 100644 --- a/scarpe-components/lib/scarpe/components/calzini/button.rb +++ b/scarpe-components/lib/scarpe/components/calzini/button.rb @@ -12,7 +12,7 @@ def button_element(props) private def button_style(props) - styles = widget_style(props) + styles = drawable_style(props) styles[:"background-color"] = props["color"] if props["color"] styles[:"padding-top"] = props["padding_top"] if props["padding_top"] diff --git a/scarpe-components/lib/scarpe/components/calzini/misc.rb b/scarpe-components/lib/scarpe/components/calzini/misc.rb index 064295f6c..91b7af2ba 100644 --- a/scarpe-components/lib/scarpe/components/calzini/misc.rb +++ b/scarpe-components/lib/scarpe/components/calzini/misc.rb @@ -8,7 +8,7 @@ def check_element(props) onclick: handler_js_code("click"), value: props["text"], checked: props["checked"], - style: widget_style(props) + style: drawable_style(props) end end @@ -77,14 +77,14 @@ def radio_element(props) name: group_name, value: props["text"], checked: props["checked"], - style: widget_style(props), + style: drawable_style(props), ) end end def video_element(props) HTML.render do |h| - h.video(id: html_id, style: widget_style(props), controls: true) do + h.video(id: html_id, style: drawable_style(props), controls: true) do h.source(src: @url, type: props["format"]) end end @@ -93,14 +93,14 @@ def video_element(props) private def edit_box_style(props) - widget_style(props).merge({ + drawable_style(props).merge({ height: dimensions_length(props["height"]), width: dimensions_length(props["width"]), }.compact) end def edit_line_style(props) - styles = widget_style(props) + styles = drawable_style(props) styles[:width] = dimensions_length(props["width"]) if props["width"] @@ -108,7 +108,7 @@ def edit_line_style(props) end def image_style(props) - styles = widget_style(props) + styles = drawable_style(props) styles[:width] = dimensions_length(props["width"]) if props["width"] styles[:height] = dimensions_length(props["height"]) if props["height"] @@ -121,7 +121,7 @@ def image_style(props) end def list_box_style(props) - styles = widget_style(props) + styles = drawable_style(props) styles[:height] = dimensions_length(props["height"]) if props["height"] styles[:width] = dimensions_length(props["width"]) if props["width"] diff --git a/scarpe-components/lib/scarpe/components/calzini/para.rb b/scarpe-components/lib/scarpe/components/calzini/para.rb index 1c50987ba..e7346f099 100644 --- a/scarpe-components/lib/scarpe/components/calzini/para.rb +++ b/scarpe-components/lib/scarpe/components/calzini/para.rb @@ -17,7 +17,7 @@ def para_options(props) end def para_style(props) - widget_style(props).merge({ + drawable_style(props).merge({ color: rgb_to_hex(props["stroke"]), "font-size": para_font_size(props), "font-family": props["font"], diff --git a/scarpe-components/lib/scarpe/components/calzini/slots.rb b/scarpe-components/lib/scarpe/components/calzini/slots.rb index 464d7db8e..162e44da2 100644 --- a/scarpe-components/lib/scarpe/components/calzini/slots.rb +++ b/scarpe-components/lib/scarpe/components/calzini/slots.rb @@ -29,7 +29,7 @@ def documentroot_element(props, &block) private def slot_style(props) - styles = widget_style(props) + styles = drawable_style(props) styles = background_style(props, styles) styles = border_style(props, styles) styles = spacing_styles_for_attr("margin", props, styles) diff --git a/scarpe-components/lib/scarpe/components/calzini/text_widgets.rb b/scarpe-components/lib/scarpe/components/calzini/text_widgets.rb index 15ed4125c..06cb2ddeb 100644 --- a/scarpe-components/lib/scarpe/components/calzini/text_widgets.rb +++ b/scarpe-components/lib/scarpe/components/calzini/text_widgets.rb @@ -40,7 +40,7 @@ def link_attributes(props) id: html_id, href: props["click"], onclick: (handler_js_code("click") if props["has_block"]), - style: widget_style(props), + style: drawable_style(props), }.compact end diff --git a/scarpe-components/lib/scarpe/components/errors.rb b/scarpe-components/lib/scarpe/components/errors.rb index d4b3980cb..5892c9f24 100644 --- a/scarpe-components/lib/scarpe/components/errors.rb +++ b/scarpe-components/lib/scarpe/components/errors.rb @@ -1,5 +1,8 @@ # frozen_string_literal: true +# Also defined in scarpe_core +class Scarpe::Error < StandardError; end + module Scarpe class InternalError < Scarpe::Error; end diff --git a/scarpe-components/lib/scarpe/components/file_helpers.rb b/scarpe-components/lib/scarpe/components/file_helpers.rb index 776c3ce81..b5bf05dda 100644 --- a/scarpe-components/lib/scarpe/components/file_helpers.rb +++ b/scarpe-components/lib/scarpe/components/file_helpers.rb @@ -4,7 +4,7 @@ # These can be used for unit tests, but also more generally. -class Scarpe; module Components; end; end +module Scarpe; module Components; end; end module Scarpe::Components::FileHelpers # Create a temporary file with the given prefix and contents. # Execute the block of code with it in place. Make sure diff --git a/scarpe-components/lib/scarpe/components/modular_logger.rb b/scarpe-components/lib/scarpe/components/modular_logger.rb index 139492136..935e1b35a 100644 --- a/scarpe-components/lib/scarpe/components/modular_logger.rb +++ b/scarpe-components/lib/scarpe/components/modular_logger.rb @@ -7,9 +7,9 @@ # Requires the logging gem -class Scarpe; end +module Scarpe; end module Scarpe::Components; end -class Scarpe +module Scarpe class Components::ModularLogImpl include Shoes::Log # for constants diff --git a/scarpe-components/lib/scarpe/components/print_logger.rb b/scarpe-components/lib/scarpe/components/print_logger.rb index 8a175c232..6728edbe8 100644 --- a/scarpe-components/lib/scarpe/components/print_logger.rb +++ b/scarpe-components/lib/scarpe/components/print_logger.rb @@ -3,7 +3,7 @@ require "shoes/log" require "json" -class Scarpe; end +module Scarpe; end module Scarpe::Components; end class Scarpe::Components::PrintLogImpl include Shoes::Log # for constants diff --git a/scarpe-components/lib/scarpe/components/promises.rb b/scarpe-components/lib/scarpe/components/promises.rb index 35ed446f5..e5cc24991 100644 --- a/scarpe-components/lib/scarpe/components/promises.rb +++ b/scarpe-components/lib/scarpe/components/promises.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true -class Scarpe; end +module Scarpe; end module Scarpe::Components; end -class Scarpe +module Scarpe # Scarpe::Promise is a promises library, but one with no form of built-in # concurrency. Instead, promise callbacks are executed synchronously. # Even execution is usually synchronous, but can also be handled manually diff --git a/scarpe-components/lib/scarpe/components/version.rb b/scarpe-components/lib/scarpe/components/version.rb index de0569840..9a64c3dd2 100644 --- a/scarpe-components/lib/scarpe/components/version.rb +++ b/scarpe-components/lib/scarpe/components/version.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true -class Scarpe +module Scarpe module Components - VERSION = "0.2.2" + VERSION = "0.3.0" end end diff --git a/scarpe-components/test/calzini/test_calzini_art_widgets.rb b/scarpe-components/test/calzini/test_calzini_art_drawables.rb similarity index 98% rename from scarpe-components/test/calzini/test_calzini_art_widgets.rb rename to scarpe-components/test/calzini/test_calzini_art_drawables.rb index 055f6aee7..36fa90c48 100644 --- a/scarpe-components/test/calzini/test_calzini_art_widgets.rb +++ b/scarpe-components/test/calzini/test_calzini_art_drawables.rb @@ -2,7 +2,7 @@ require_relative "../test_helper" -class TestCalziniArtWidgets < Minitest::Test +class TestCalziniArtDrawables < Minitest::Test def setup @calzini = CalziniRenderer.new end diff --git a/scarpe-components/test/calzini/test_calzini_misc.rb b/scarpe-components/test/calzini/test_calzini_misc.rb index ec51d3327..a0803f252 100644 --- a/scarpe-components/test/calzini/test_calzini_misc.rb +++ b/scarpe-components/test/calzini/test_calzini_misc.rb @@ -2,7 +2,7 @@ require_relative "../test_helper" -class TestCalziniMiscWidgets < Minitest::Test +class TestCalziniMiscDrawables < Minitest::Test def setup @calzini = CalziniRenderer.new end diff --git a/scarpe-components/test/calzini/test_calzini_text_widgets.rb b/scarpe-components/test/calzini/test_calzini_text_drawables.rb similarity index 96% rename from scarpe-components/test/calzini/test_calzini_text_widgets.rb rename to scarpe-components/test/calzini/test_calzini_text_drawables.rb index bb80989c9..63ec114df 100644 --- a/scarpe-components/test/calzini/test_calzini_text_widgets.rb +++ b/scarpe-components/test/calzini/test_calzini_text_drawables.rb @@ -2,7 +2,7 @@ require_relative "../test_helper" -class TestCalziniTextWidgets < Minitest::Test +class TestCalziniTextDrawables < Minitest::Test def setup @calzini = CalziniRenderer.new end diff --git a/scarpegen.rb b/scarpegen.rb index cbead433f..42ed98581 100644 --- a/scarpegen.rb +++ b/scarpegen.rb @@ -5,7 +5,7 @@ class ScarpeGenerator def initialize @filename = "" - @display_properties = "" + @shoes_styles = "" end def generate @@ -14,7 +14,7 @@ def generate choice = get_choice if choice == "1" class_template_choice = get_class_template_choice - get_display_properties if class_template_choice != "1" + get_shoes_styles if class_template_choice != "1" end generate_files(choice, class_template_choice) end @@ -89,14 +89,14 @@ def get_class_template_choice end end - def get_display_properties - print "\n\e[33mDo you want to enter display properties? (y/n):\e[0m " + def get_shoes_styles + print "\n\e[33mDo you want to enter Shoes styles? (y/n):\e[0m " response = gets.chomp.downcase - @display_properties = response == "y" || response == "yes" ? get_properties_input : ":dummy" + @shoes_styles = response == "y" || response == "yes" ? get_properties_input : ":dummy" end def get_properties_input - print "\e[33mEnter the display properties:(enter like :width,:height)\e[0m " + print "\e[33mEnter the Shoes styles:(enter like :width,:height)\e[0m " gets.chomp end @@ -112,20 +112,20 @@ def generate_files(choice, class_template_choice) end generate_webview_file generate_example_file - add_require_relative_to_widgets_file + add_require_relative_to_drawables_file puts "\n\e[1;32mYayyyy! Files generated successfully!\e[0m\n" end - def add_require_relative_to_widgets_file - widgets_file_path = "lacci/lib/shoes/widgets.rb" + def add_require_relative_to_drawables_file + drawables_file_path = "lacci/lib/shoes/drawables.rb" filename = @filename.downcase - require_line = "require \"shoes/widgets/#{filename}\"" + require_line = "require \"shoes/drawables/#{filename}\"" - File.open(widgets_file_path, "a") do |file| + File.open(drawables_file_path, "a") do |file| file.puts require_line end - puts "Added require_relative to widgets.rb file" + puts "Added require_relative to drawables.rb file" end def generate_webview_file @@ -169,7 +169,7 @@ def generate_class_file(class_template_choice) class_template = File.read(class_template_file) class_content = ERB.new(class_template).result(binding_with_argument(class_template_choice)) - File.write("lacci/lib/shoes/widgets/#{@filename}.rb", class_content) + File.write("lacci/lib/shoes/drawables/#{@filename}.rb", class_content) end def generate_module_file @@ -183,7 +183,7 @@ def binding_with_argument(class_template_choice = nil) capitalized_argument = @filename.capitalize binding.dup.tap do |b| b.local_variable_set(:argument, capitalized_argument) - b.local_variable_set(:display_properties, @display_properties) + b.local_variable_set(:shoes_styles, @shoes_styles) b.local_variable_set(:class_template_choice, class_template_choice) unless class_template_choice.nil? end end diff --git a/sig/scarpe.rbs b/sig/scarpe.rbs index 36b4e917b..a56c33921 100644 --- a/sig/scarpe.rbs +++ b/sig/scarpe.rbs @@ -1,4 +1,4 @@ -class Scarpe +module Scarpe VERSION: String # See the writing guide of rbs: https://github.com/ruby/rbs#guides end diff --git a/templates/basic_class_template.erb b/templates/basic_class_template.erb index f9dc6ae9a..eb059c7f0 100644 --- a/templates/basic_class_template.erb +++ b/templates/basic_class_template.erb @@ -2,18 +2,18 @@ # frozen_string_literal: true module Shoes - class <%= argument %> < Shoes::Widget + class <%= argument %> < Shoes::Drawable - # Display Properties - # These properties determine the visual characteristics of the widget + # Shoes styles + # These properties determine the visual characteristics of the drawable # Customize them according to your requirements - # Example display properties: - # :background_color - Sets the background color of the widget (<%= argument %>) - # :width - Specifies the width of the widget(<%= argument %>) - # :height - Specifies the height of the widget(<%= argument %>) + # Example Shoes styles: + # :background_color - Sets the background color of the drawable (<%= argument %>) + # :width - Specifies the width of the drawable(<%= argument %>) + # :height - Specifies the height of the drawable(<%= argument %>) - display_properties <%= display_properties %> + shoes_styles <%= shoes_styles %> def initialize super @@ -26,13 +26,12 @@ module Shoes # # Event handling code goes here # end - - # This method uses the DisplayService to create a visual representation of the widget - # It generates a display widget based on the specified display properties - create_display_widget + # This method uses the DisplayService to create a visual representation of the drawable + # It generates a display drawable based on the specified Shoes styles + create_display_drawable end - # other methods + # other methods end end diff --git a/templates/class_template_with_event_bind.erb b/templates/class_template_with_event_bind.erb index 204e522d3..3e52b71d5 100644 --- a/templates/class_template_with_event_bind.erb +++ b/templates/class_template_with_event_bind.erb @@ -1,8 +1,8 @@ # frozen_string_literal: true -class Scarpe - class <%= argument %> < Shoes::Widget - display_properties <%= display_properties %> # Write your display proporties here +module Scarpe + class <%= argument %> < Shoes::Drawable + shoes_styles <%= shoes_styles %> # Write your shoes styles here def initialize(text, width: nil, height: nil, top: nil, left: nil, &block) # Properties passed as positional args, not keywords, don't get auto-set @@ -16,7 +16,7 @@ class Scarpe @block&.call end - create_display_widget + create_display_drawable end # Set the click handler diff --git a/templates/class_template_with_shapes.erb b/templates/class_template_with_shapes.erb index 8b39ed74c..1278ccd07 100644 --- a/templates/class_template_with_shapes.erb +++ b/templates/class_template_with_shapes.erb @@ -1,17 +1,20 @@ # frozen_string_literal: true -class Scarpe - class InvalidAttributeValueError < StandardError; end +module Scarpe + #class InvalidAttributeValueError < Scarpe::Error; end # add new errors to errors.rb - class <%= argument %> < Shoes::Widget - display_properties <%= display_properties %> # Write your display proporties here + class <%= argument %> < Shoes::Drawable + # Shoes style with verification or value mapping: + # shoes_style(:left) { |val| convert_to_integer(val, "left") } + + shoes_styles <%= shoes_styles %> # Write your shoes styles here def initialize(left, top) @left = convert_to_integer(left, "left") @top = convert_to_integer(top, "top") super() - create_display_widget + create_display_drawable end private @@ -27,17 +30,5 @@ class Scarpe raise InvalidAttributeValueError, error_message end end - - def convert_to_float(value, attribute_name, default = 0.0) - begin - value = Float(value) - raise InvalidAttributeValueError, "Negative num '#{value}' not allowed for attribute '#{attribute_name}'" if value < 0 - - value - rescue ArgumentError - error_message = "Invalid value '#{value}' provided for attribute '#{attribute_name}'. The value should be a number." - raise InvalidAttributeValueError, error_message - end - end end end diff --git a/templates/example_template.erb b/templates/example_template.erb index 083b933f8..109c1d509 100644 --- a/templates/example_template.erb +++ b/templates/example_template.erb @@ -1,3 +1,3 @@ Shoes.app do - para "heyya ssup!" + para "heyya ssup!" end diff --git a/templates/module_template.erb b/templates/module_template.erb index 2394f22c3..f78aadcc0 100644 --- a/templates/module_template.erb +++ b/templates/module_template.erb @@ -1,12 +1,12 @@ # frozen_string_literal: true -class Scarpe +module Scarpe module <%= argument %> def self.included(includer) - <%# add display propeties below... for this example :background_color is added as display_property %> - includer.display_property(:background_color) + <%# add shoes styles below... for this example :background_color is added as shoes_style %> + includer.shoes_style(:background_color) end -# Write any methods here! + # Write any methods here! end end diff --git a/templates/webview_template.erb b/templates/webview_template.erb index 80fd83e51..d9af294e0 100644 --- a/templates/webview_template.erb +++ b/templates/webview_template.erb @@ -1,13 +1,14 @@ # frozen_string_literal: true module Scarpe::Webview - class <%= argument %> < Widget + class <%= argument %> < Drawable def initialize(properties) super end + # If the drawable is intended to be overridable, add element and style to Calzini instead def element HTML.render do |h| h.textarea(id: html_id, style: style) diff --git a/test/test_widgets.rb b/test/test_drawables.rb similarity index 55% rename from test/test_widgets.rb rename to test/test_drawables.rb index 1e73fe2da..2b660ca6c 100644 --- a/test/test_widgets.rb +++ b/test/test_drawables.rb @@ -2,35 +2,35 @@ require "test_helper" -# Widgets Testing -class TestWidgets < LoggedScarpeTest +# Drawables Testing +class TestDrawables < LoggedScarpeTest self.logger_dir = File.expand_path("#{__dir__}/../logger") def test_hide_show run_test_scarpe_code(<<-'SCARPE_APP', app_test_code: <<-'TEST_CODE') Shoes.app do - @widgets = [] - @widgets << alert("YOLO!") - @widgets << arc(400, 0, 120, 100, 175, 175) - @widgets << button("Press Me") - @widgets << check - @widgets << edit_line("foo") - @widgets << edit_box("bar") - @widgets << flow {} # Slightly weird thing here: empty flow - @widgets << image("https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png") - @widgets << line(0, 0, 100, 100) - @widgets << list_box(items: ['A', 'B']) - @widgets << para("Hello") - @widgets << radio("ooga") - @widgets << shape { line(0, 0, 10, 10) } - @widgets << stack {} - @widgets << star(230, 100, 6, 50, 25) - @widgets << video("http://techslides.com/demos/sample-videos/small.mp4") + @drawables = [] + @drawables << alert("YOLO!") + @drawables << arc(400, 0, 120, 100, 175, 175) + @drawables << button("Press Me") + @drawables << check + @drawables << edit_line("foo") + @drawables << edit_box("bar") + @drawables << flow {} # Slightly weird thing here: empty flow + @drawables << image("https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png") + @drawables << line(0, 0, 100, 100) + @drawables << list_box(items: ['A', 'B']) + @drawables << para("Hello") + @drawables << radio("ooga") + @drawables << shape { line(0, 0, 10, 10) } + @drawables << stack {} + @drawables << star(230, 100, 6, 50, 25) + @drawables << video("http://techslides.com/demos/sample-videos/small.mp4") end SCARPE_APP on_heartbeat do - # Get proxy objects for the Shoes widgets so we can get their display objects, etc. - w = Shoes::App.instance.instance_variable_get("@widgets").map { |sw| proxy_for(sw) } + # Get proxy objects for the Shoes drawables so we can get their display objects, etc. + w = Shoes::App.instance.instance_variable_get("@drawables").map { |sw| proxy_for(sw) } w.each { |i| i.hide } w.each { |i| assert_include i.display.to_html, "display:none" } @@ -54,7 +54,7 @@ def test_hide_show def test_app_method run_test_scarpe_code(<<-'SCARPE_APP', app_test_code: <<-'TEST_CODE') - class NotAWidget + class NotADrawable def self.magic(stack) stack.app do @s2.para "Hello!" @@ -64,7 +64,7 @@ def self.magic(stack) Shoes.app do @s = stack do - button("Press Me") { NotAWidget.magic(@s) } + button("Press Me") { NotADrawable.magic(@s) } end @s2 = stack {} end diff --git a/test/test_edit_box.rb b/test/test_edit_box.rb index 88ba87afd..cfe917ce5 100644 --- a/test/test_edit_box.rb +++ b/test/test_edit_box.rb @@ -73,7 +73,7 @@ def test_textarea_width # Amusingly, this hits a Webview bug. You can do the same thing in the console. # The value updates, including on the screen, but querying the innerHTML of the # enclosing element shows the *old* value, not the new one. - #def test_textarea_widget_change + #def test_textarea_drawable_change # run_test_scarpe_code(<<-'SCARPE_APP', app_test_code: <<-'TEST_CODE') # Shoes.app do # edit_box "Hello, World!" diff --git a/test/test_link.rb b/test/test_link.rb index 704a96172..d4d0f0a10 100644 --- a/test/test_link.rb +++ b/test/test_link.rb @@ -2,8 +2,6 @@ require "test_helper" -# Link display properties: text, click, has_block - class TestWebviewLink < ScarpeWebviewTest def setup @default_properties = { diff --git a/test/test_para.rb b/test/test_para.rb index 5da9d6b14..573e58eaa 100644 --- a/test/test_para.rb +++ b/test/test_para.rb @@ -103,7 +103,7 @@ def test_replace_children mocked_html_element.verify end - def test_children_can_be_text_widgets + def test_children_can_be_text_drawables strong = Scarpe::Webview::Strong.new("content" => "I am strong", "shoes_linkable_id" => 2) para = Scarpe::Webview::Para.new(@default_properties.merge("text_items" => [strong])) para.stub :items_to_display_children, [strong], [2] do @@ -113,7 +113,7 @@ def test_children_can_be_text_widgets end end - def test_can_replace_widgets_with_other_widgets + def test_can_replace_drawables_with_other_drawables strong = Scarpe::Webview::Strong.new("content" => "I am strong", "shoes_linkable_id" => 2) em = Scarpe::Webview::Em.new("content" => "I am em", "shoes_linkable_id" => 3) para = Scarpe::Webview::Para.new(@default_properties.merge("text_items" => [strong])) diff --git a/test/test_scarpe.rb b/test/test_scarpe.rb index 51c48bb4e..8a2950696 100644 --- a/test/test_scarpe.rb +++ b/test/test_scarpe.rb @@ -46,7 +46,7 @@ def test_button_app SCARPE_APP end - def test_text_widgets + def test_text_drawables run_test_scarpe_code(<<-'SCARPE_APP', exit_immediately: true) Shoes.app do para "This is plain." @@ -73,7 +73,7 @@ def test_stack_args_optional SCARPE_APP end - def test_widgets_exist + def test_drawables_exist run_test_scarpe_code(<<-'SCARPE_APP', exit_immediately: true) Shoes.app do stack do diff --git a/test/test_slots.rb b/test/test_slots.rb index 398a6d4d5..8c2599643 100644 --- a/test/test_slots.rb +++ b/test/test_slots.rb @@ -14,7 +14,7 @@ def test_stack_child end SCARPE_APP on_next_redraw do - assert para.parent.is_a?(Shoes::Stack), "A widget created in a Stack's block should be a child of the stack!" + assert para.parent.is_a?(Shoes::Stack), "A drawable created in a Stack's block should be a child of the stack!" test_finished end TEST_CODE diff --git a/test/test_web_wrangler.rb b/test/test_web_wrangler.rb index 5771b8d42..df464c50b 100644 --- a/test/test_web_wrangler.rb +++ b/test/test_web_wrangler.rb @@ -8,7 +8,7 @@ class TestWebWranglerInScarpeApp < LoggedScarpeTest self.logger_dir = File.expand_path("#{__dir__}/../logger") - # Need to make sure that even with no widgets we still get at least one redraw + # Need to make sure that even with no drawables we still get at least one redraw def test_empty_app run_test_scarpe_code(<<-'SCARPE_APP', app_test_code: <<-'TEST_CODE') Shoes.app do