Class: RubyTUI::Widgets::AsyncImage
- Inherits:
-
Object
- Object
- RubyTUI::Widgets::AsyncImage
- Includes:
- RubyTUI::Widget
- Defined in:
- lib/rubytui/widgets/async_image.rb
Overview
Asynchronously loads and renders images with placeholder support.
Handles background image loading with thread-safe cache handoff, displays a placeholder while loading, and signals when ready for redraw.
Constant Summary collapse
- STATE_PENDING =
Loading not started (auto_start: false and no cache hit).
:pending- STATE_LOADING =
Loader running on the background thread.
:loading- STATE_READY =
Image data loaded and ready to render.
:ready- STATE_ERROR =
Loading or image validation failed; see #error.
:error
Instance Attribute Summary collapse
-
#error ⇒ String?
readonly
Error message if state is :error.
-
#state ⇒ Symbol
readonly
Current loading state.
Instance Method Summary collapse
-
#cancel ⇒ void
Cancel the background loading thread.
-
#error? ⇒ Boolean
Check if loading failed.
-
#initialize(loader:, key: nil, cache: nil, placeholder: nil, error_placeholder: nil, on_ready: nil, on_error: nil, style: Style::DEFAULT, block: nil, fit: nil, cell_size: nil, auto_start: true) ⇒ AsyncImage
constructor
A new instance of AsyncImage.
-
#loading? ⇒ Boolean
Check if loading is in progress.
-
#ready? ⇒ Boolean
Check if the image is ready for rendering.
-
#render(area, buf) ⇒ void
Render the async image or placeholder.
-
#start_loading ⇒ self
Start background loading if not already started.
Constructor Details
#initialize(loader:, key: nil, cache: nil, placeholder: nil, error_placeholder: nil, on_ready: nil, on_error: nil, style: Style::DEFAULT, block: nil, fit: nil, cell_size: nil, auto_start: true) ⇒ AsyncImage
Returns a new instance of AsyncImage.
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/rubytui/widgets/async_image.rb', line 74 def initialize(loader:, key: nil, cache: nil, placeholder: nil, error_placeholder: nil, on_ready: nil, on_error: nil, style: Style::DEFAULT, block: nil, fit: nil, cell_size: nil, auto_start: true) @loader = loader @key = key || loader.object_id @cache = cache || {} @placeholder = placeholder @error_placeholder = error_placeholder || "[Error]" @on_ready = on_ready @on_error = on_error @style = style @block = block @fit = fit @cell_size = cell_size @mutex = Mutex.new @state = STATE_PENDING @image_data = nil @image_widget = nil @error = nil @thread = nil # Check cache first if @cache.key?(@key) @image_data = @cache[@key] @state = STATE_READY elsif auto_start start_loading end end |
Instance Attribute Details
#error ⇒ String? (readonly)
Returns error message if state is :error.
50 51 52 |
# File 'lib/rubytui/widgets/async_image.rb', line 50 def error @error end |
#state ⇒ Symbol (readonly)
Returns current loading state.
47 48 49 |
# File 'lib/rubytui/widgets/async_image.rb', line 47 def state @state end |
Instance Method Details
#cancel ⇒ void
This method returns an undefined value.
Cancel the background loading thread.
Kills the thread if one is running. The state is not changed, so a load
cancelled mid-flight stays :loading and #start_loading will not restart it.
171 172 173 174 |
# File 'lib/rubytui/widgets/async_image.rb', line 171 def cancel @thread&.kill @thread = nil end |
#error? ⇒ Boolean
Check if loading failed.
161 162 163 |
# File 'lib/rubytui/widgets/async_image.rb', line 161 def error? @state == STATE_ERROR end |
#loading? ⇒ Boolean
Check if loading is in progress.
154 155 156 |
# File 'lib/rubytui/widgets/async_image.rb', line 154 def loading? @state == STATE_LOADING end |
#ready? ⇒ Boolean
Check if the image is ready for rendering.
147 148 149 |
# File 'lib/rubytui/widgets/async_image.rb', line 147 def ready? @state == STATE_READY end |
#render(area, buf) ⇒ void
This method returns an undefined value.
Render the async image or placeholder.
When ready, the loaded Image is rendered; otherwise the placeholder described in #initialize is drawn.
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/rubytui/widgets/async_image.rb', line 184 def render(area, buf) return if area.empty? render_area = area if @block @block.render(area, buf) render_area = @block.inner(area) end return if render_area.empty? case @state when STATE_READY @image_widget&.render(render_area, buf) when STATE_LOADING render_placeholder(render_area, buf, "Loading...") when STATE_ERROR render_placeholder(render_area, buf, @error_placeholder) when STATE_PENDING render_placeholder(render_area, buf, @placeholder || "") end end |
#start_loading ⇒ self
Start background loading if not already started.
Does nothing unless the state is :pending. Otherwise sets the state to
:loading and calls loader on a new thread. On success the data is
stored in the cache and the state becomes :ready; if loader raises a
StandardError the state becomes :error.
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/rubytui/widgets/async_image.rb', line 115 def start_loading @mutex.synchronize do return self unless @state == STATE_PENDING @state = STATE_LOADING end @thread = Thread.new do begin data = @loader.call @mutex.synchronize do @image_data = data @cache[@key] = data @state = STATE_READY end @on_ready&.call rescue => e @mutex.synchronize do @error = e. @state = STATE_ERROR end @on_error&.call(e) end end self end |