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, Button, Check, EditBox, EditLine, Image, Line, ListBox, 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.
-
#rgb_to_hex(color) ⇒ Object
protected
Convert an [r, g, b, a] array to an HTML hex color code Arrays support alpha.
-
#set_parent(new_parent) ⇒ Object
Give this drawable a new parent, including managing the appropriate child lists for parent drawables.
- #shoes_styles ⇒ Object
-
#style ⇒ Object
protected
CSS styles.
-
#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 |
# 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"] # Call method, which looks up the parent @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) 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
138 139 140 141 142 143 144 |
# File 'lib/scarpe/wv/drawable.rb', line 138 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
223 224 225 226 227 |
# File 'lib/scarpe/wv/drawable.rb', line 223 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.
234 235 236 237 238 |
# File 'lib/scarpe/wv/drawable.rb', line 234 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.
244 245 246 |
# File 'lib/scarpe/wv/drawable.rb', line 244 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.
266 267 268 269 270 271 |
# File 'lib/scarpe/wv/drawable.rb', line 266 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.
189 190 191 |
# File 'lib/scarpe/wv/drawable.rb', line 189 def html_element @elt_wrangler ||= Scarpe::Webview::WebWrangler::ElementWrangler.new(html_id) end |
#html_id ⇒ String
Get the object's HTML ID
205 206 207 |
# File 'lib/scarpe/wv/drawable.rb', line 205 def html_id @linkable_id.to_s end |
#inspect ⇒ Object
A shorter inspect text for prettier irb output
121 122 123 |
# File 'lib/scarpe/wv/drawable.rb', line 121 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.
257 258 259 |
# File 'lib/scarpe/wv/drawable.rb', line 257 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
196 197 198 199 200 |
# File 'lib/scarpe/wv/drawable.rb', line 196 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.
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/scarpe/wv/drawable.rb', line 96 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 new_style = style # Get current display CSS property, which may vary by subclass disp = new_style[:display] html_element.set_style("display", disp || "block") end end needs_update! unless changes.empty? end |
#remove_child(child) ⇒ Object (protected)
Do not call directly, use set_parent
128 129 130 131 132 133 134 135 |
# File 'lib/scarpe/wv/drawable.rb', line 128 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 |
#rgb_to_hex(color) ⇒ Object (protected)
Convert an [r, g, b, a] array to an HTML hex color code Arrays support alpha. HTML hex does not. So premultiply.
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/scarpe/wv/drawable.rb', line 148 def rgb_to_hex(color) return color if color.nil? r, g, b, a = *color if r.is_a?(Float) a ||= 1.0 r_float = r * a g_float = g * a b_float = b * a else a ||= 255 a_float = (a / 255.0) r_float = (r.to_f / 255.0) * a_float g_float = (g.to_f / 255.0) * a_float b_float = (b.to_f / 255.0) * a_float end r_int = (r_float * 255.0).to_i.clamp(0, 255) g_int = (g_float * 255.0).to_i.clamp(0, 255) b_int = (b_float * 255.0).to_i.clamp(0, 255) "#%0.2X%0.2X%0.2X" % [r_int, g_int, b_int] end |
#set_parent(new_parent) ⇒ Object
Give this drawable a new parent, including managing the appropriate child lists for parent drawables.
114 115 116 117 118 |
# File 'lib/scarpe/wv/drawable.rb', line 114 def set_parent(new_parent) @parent&.remove_child(self) new_parent&.add_child(self) @parent = new_parent end |
#shoes_styles ⇒ Object
81 82 83 84 85 86 87 |
# File 'lib/scarpe/wv/drawable.rb', line 81 def shoes_styles p = {} @shoes_style_names.each do |prop_name| p[prop_name] = instance_variable_get("@#{prop_name}") end p end |
#style ⇒ Object (protected)
CSS styles
173 174 175 176 177 178 179 |
# File 'lib/scarpe/wv/drawable.rb', line 173 def style styles = {} if @hidden styles[:display] = "none" end styles 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.
213 214 215 216 217 |
# File 'lib/scarpe/wv/drawable.rb', line 213 def to_html @children ||= [] child_markup = @children.map(&:to_html).join element { child_markup } end |