Class: Scarpe::Webview::Drawable
- Inherits:
-
Shoes::Linkable
- Object
- Shoes::Linkable
- Scarpe::Webview::Drawable
- Includes:
- Shoes::Log
- Defined in:
- lib/scarpe/wv/drawable.rb,
lib/scarpe/wv.rb
Overview
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.
Direct Known Subclasses
App, Arc, Arrow, Border, Button, Check, EditBox, EditLine, Image, Line, ListBox, Oval, Para, Progress, Radio, Rect, Shape, Slot, Star, SubscriptionItem, TextDrawable, Video
Constant Summary
Constants included from Shoes::Log
Shoes::Log::DEFAULT_COMPONENT, Shoes::Log::DEFAULT_DEBUG_LOG_CONFIG, Shoes::Log::DEFAULT_LOG_CONFIG
Instance Attribute Summary collapse
-
#children ⇒ Object
readonly
An array of Webview::Drawable children (possibly empty) of this drawable.
-
#parent ⇒ Object
readonly
The Webview::Drawable parent of this drawable.
-
#shoes_linkable_id ⇒ Object
readonly
The Shoes ID corresponding to the Shoes drawable for this Webview drawable.
Attributes inherited from Shoes::Linkable
Class Method Summary collapse
-
.display_class_for(scarpe_class_name) ⇒ Object
Return the corresponding Webview class for a particular Shoes class name.
Instance Method Summary collapse
-
#add_child(child) ⇒ Object
protected
Do not call directly, use set_parent.
-
#bind(event) { ... } ⇒ Object
This binds a Scarpe JS callback, handled via a single dispatch point in the app.
-
#destroy_self ⇒ Scarpe::Promise
Removes the element from both the Ruby Drawable tree and the HTML DOM.
-
#full_window_redraw! ⇒ void
Request a full redraw of the entire window, including the entire tree of drawables and the outer "empty page" frame.
-
#handler_js_code(handler_function_name, *args) ⇒ String
Generate JS code to trigger a specific event name on this drawable with the supplies arguments.
-
#html_element ⇒ Scarpe::WebWrangler::ElementWrangler
This gets an accessor for just this element's HTML ID.
-
#html_id ⇒ String
Get the object's HTML ID.
-
#initialize(properties) ⇒ Drawable
constructor
Set instance variables for the Shoes styles of this drawable.
-
#inspect ⇒ Object
A shorter inspect text for prettier irb output.
-
#needs_update! ⇒ void
Request a full redraw of this drawable, including all its children.
-
#promise_update ⇒ Scarpe::Promise
Return a promise that guarantees all currently-requested changes have completed.
-
#properties_changed(changes) ⇒ Object
Properties_changed will be called automatically when properties change.
-
#remove_child(child) ⇒ Object
protected
Do not call directly, use set_parent.
-
#set_parent(new_parent) ⇒ Object
Give this drawable a new parent, including managing the appropriate child lists for parent drawables.
- #shoes_styles ⇒ Object
-
#to_html ⇒ String
to_html is intended to get the HTML DOM rendering of this object and its children.
Methods included from Shoes::Log
configure_logger, #log_init, logger
Methods inherited from Shoes::Linkable
#bind_shoes_event, #send_self_event, #send_shoes_event, #unsub_all_shoes_events, #unsub_shoes_event
Constructor Details
#initialize(properties) ⇒ Drawable
Set instance variables for the Shoes styles of this drawable. Bind Shoes events for changes of parent drawable and changes of property values.
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/scarpe/wv/drawable.rb', line 40 def initialize(properties) log_init("Webview::Drawable") @shoes_style_names = properties.keys.map(&:to_s) - ["shoes_linkable_id"] @shoes_linkable_id = properties["shoes_linkable_id"] || properties[:shoes_linkable_id] unless @shoes_linkable_id raise Scarpe::MissingAttributeError, "Could not find property shoes_linkable_id in #{properties.inspect}!" end # 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 # Must call this before bind super(linkable_id: @shoes_linkable_id) # This will only be used if moving a drawable from one parent to another. # Shoes doesn't normally do that. bind_shoes_event(event_name: "parent", target: shoes_linkable_id) do |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 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) end properties_changed(prop_changes) end bind_shoes_event(event_name: "destroy", target: shoes_linkable_id) do destroy_self end end |
Instance Attribute Details
#children ⇒ Object (readonly)
An array of Webview::Drawable children (possibly empty) of this drawable
36 37 38 |
# File 'lib/scarpe/wv/drawable.rb', line 36 def children @children end |
#parent ⇒ Object (readonly)
The Webview::Drawable parent of this drawable
33 34 35 |
# File 'lib/scarpe/wv/drawable.rb', line 33 def parent @parent end |
#shoes_linkable_id ⇒ Object (readonly)
The Shoes ID corresponding to the Shoes drawable for this Webview drawable
30 31 32 |
# File 'lib/scarpe/wv/drawable.rb', line 30 def shoes_linkable_id @shoes_linkable_id end |
Class Method Details
.display_class_for(scarpe_class_name) ⇒ Object
Return the corresponding Webview class for a particular Shoes class name
13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/scarpe/wv/drawable.rb', line 13 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 drawables, not #{scarpe_class_name.inspect}!" end klass = Scarpe::Webview.const_get(scarpe_class_name.split("::")[-1]) if klass.nil? raise Scarpe::MissingClassError, "Couldn't find corresponding Scarpe Webview class for #{scarpe_class_name.inspect}!" end klass end |
Instance Method Details
#add_child(child) ⇒ Object (protected)
Do not call directly, use set_parent
139 140 141 142 143 144 145 |
# File 'lib/scarpe/wv/drawable.rb', line 139 def add_child(child) @children ||= [] @children << child # If we add a child, we should redraw ourselves needs_update! end |
#bind(event) { ... } ⇒ Object
This binds a Scarpe JS callback, handled via a single dispatch point in the app
189 190 191 192 193 |
# File 'lib/scarpe/wv/drawable.rb', line 189 def bind(event, &block) raise(Scarpe::MissingAttributeError, "Drawable has no linkable_id! #{inspect}") unless linkable_id DisplayService.instance.app.bind("#{linkable_id}-#{event}", &block) end |
#destroy_self ⇒ Scarpe::Promise
Removes the element from both the Ruby Drawable tree and the HTML DOM. Unsubscribe from all Shoes events. Return a promise for when that HTML change will be visible.
200 201 202 203 204 |
# File 'lib/scarpe/wv/drawable.rb', line 200 def destroy_self @parent&.remove_child(self) unsub_all_shoes_events html_element.remove end |
#full_window_redraw! ⇒ void
This method returns an undefined value.
Request a full redraw of the entire window, including the entire tree of drawables and the outer "empty page" frame.
210 211 212 |
# File 'lib/scarpe/wv/drawable.rb', line 210 def full_window_redraw! DisplayService.instance.app.request_redraw! end |
#handler_js_code(handler_function_name, *args) ⇒ String
Generate JS code to trigger a specific event name on this drawable with the supplies arguments.
232 233 234 235 236 237 |
# File 'lib/scarpe/wv/drawable.rb', line 232 def handler_js_code(handler_function_name, *args) raise(Scarpe::MissingAttributeError, "Drawable has no linkable_id! #{inspect}") unless linkable_id js_args = ["'#{linkable_id}-#{handler_function_name}'", *args].join(", ") "scarpeHandler(#{js_args})" end |
#html_element ⇒ Scarpe::WebWrangler::ElementWrangler
This gets an accessor for just this element's HTML ID. It is normally called by the drawable itself to do its DOM management. Drawables are required to use their html_id for their outermost element, to make sure that remove(), hidden() etc. affect every part of the drawable.
155 156 157 |
# File 'lib/scarpe/wv/drawable.rb', line 155 def html_element @elt_wrangler ||= Scarpe::Webview::WebWrangler::ElementWrangler.new(html_id:) end |
#html_id ⇒ String
Get the object's HTML ID
171 172 173 |
# File 'lib/scarpe/wv/drawable.rb', line 171 def html_id @linkable_id.to_s end |
#inspect ⇒ Object
A shorter inspect text for prettier irb output
122 123 124 |
# File 'lib/scarpe/wv/drawable.rb', line 122 def inspect "#<#{self.class}:#{self.object_id} @shoes_linkable_id=#{@shoes_linkable_id} @children=#{@children.inspect}>" end |
#needs_update! ⇒ void
This method returns an undefined value.
Request a full redraw of this drawable, including all its children. Can be overridden in drawable subclasses if needed. An override would normally only be needed if re-rendering the element with the given html_id wasn't enough (and then remove would also need to be overridden.)
This occurs by default if a property is changed and the drawable doesn't remove its change in property_changed.
223 224 225 |
# File 'lib/scarpe/wv/drawable.rb', line 223 def needs_update! html_element.outer_html = to_html end |
#promise_update ⇒ Scarpe::Promise
Return a promise that guarantees all currently-requested changes have completed
162 163 164 165 166 |
# File 'lib/scarpe/wv/drawable.rb', line 162 def promise_update # Doesn't matter what ElementWrangler we use -- they all return an update promise # that includes all pending updates, no matter who they're for. html_element.promise_update end |
#properties_changed(changes) ⇒ Object
Properties_changed will be called automatically when properties change. 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.
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/scarpe/wv/drawable.rb', line 97 def properties_changed(changes) # 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") if hidden html_element.set_style("display", "none") else # With Calzini we can't easily tell what the display property should be. # Could be flex or inline, not only block or none. Re-render this drawable. needs_update! end end needs_update! unless changes.empty? end |
#remove_child(child) ⇒ Object (protected)
Do not call directly, use set_parent
129 130 131 132 133 134 135 136 |
# File 'lib/scarpe/wv/drawable.rb', line 129 def remove_child(child) @children ||= [] unless @children.include?(child) @log.error("remove_child: no such child(#{child.inspect}) for"\ " parent(#{parent.inspect})!") end @children.delete(child) end |
#set_parent(new_parent) ⇒ Object
Give this drawable a new parent, including managing the appropriate child lists for parent drawables.
115 116 117 118 119 |
# File 'lib/scarpe/wv/drawable.rb', line 115 def set_parent(new_parent) @parent&.remove_child(self) new_parent&.add_child(self) @parent = new_parent end |
#shoes_styles ⇒ Object
82 83 84 85 86 87 88 |
# File 'lib/scarpe/wv/drawable.rb', line 82 def shoes_styles p = {} @shoes_style_names.each do |prop_name| p[prop_name] = instance_variable_get("@#{prop_name}") end p end |
#to_html ⇒ String
to_html is intended to get the HTML DOM rendering of this object and its children. Calling it should be side-effect-free and NOT update the webview.
179 180 181 182 183 |
# File 'lib/scarpe/wv/drawable.rb', line 179 def to_html @children ||= [] child_markup = @children.map(&:to_html).join element { child_markup } end |