Class: Glimmer::SWT::DisplayProxy
- Inherits:
-
Object
- Object
- Glimmer::SWT::DisplayProxy
- Includes:
- Custom::Drawable
- Defined in:
- lib/glimmer/swt/display_proxy.rb
Overview
Proxy for org.eclipse.swt.widgets.Display
Maintains a singleton instance since SWT only supports a single active display at a time.
Supports SWT Display’s very useful asyncExec and syncExec methods to support proper multi-threaded manipulation of SWT UI objects
Invoking ‘#swt_display` returns the SWT Display object wrapped by this proxy
Follows the Proxy Design Pattern
Defined Under Namespace
Classes: ConcreteListener
Constant Summary collapse
- OBSERVED_MENU_ITEMS =
['about', 'preferences', 'quit']
Instance Attribute Summary collapse
-
#swt_display ⇒ Object
readonly
SWT Display object wrapped.
Attributes included from Custom::Drawable
#image_double_buffered, #requires_shape_disposal
Class Method Summary collapse
-
.current_custom_widgets_and_shapes ⇒ Object
Current custom widgets, shells, and shapes being rendered.
-
.instance(*args) ⇒ Object
Returns singleton instance.
- .thread ⇒ Object
Instance Method Summary collapse
- #add_swt_event_filter(swt_constant, &block) ⇒ Object
-
#async_exec(&block) ⇒ Object
asynchronously executes the block (required from threads other than first GUI thread) does not return the value produced by the block since it is async, running after the return.
- #async_exec_in_progress? ⇒ Boolean
-
#auto_exec(override_sync_exec: nil, override_async_exec: nil, &block) ⇒ Object
Invoke block with ‘sync_exec` only when necessary (running from a separate thread) Override sync_exec as `true` to force using or `false` to force avoiding Override async_exec as `true` to force using or `:unless_in_progress` to force using only if no `async_exec` is in progress Disable auto execution of `sync_exec` via `Glimmer::Config.auto_sync_exec = false` Otherwise, runs normally, thus allowing SWT to decide how to batch/optimize GUI updates.
- #can_handle_observation_request?(observation_request) ⇒ Boolean
- #content(&block) ⇒ Object
- #disposed? ⇒ Boolean
- #execs_in_progress ⇒ Object
- #handle_observation_request(observation_request, &block) ⇒ Object
-
#initialize(*args) ⇒ DisplayProxy
constructor
A new instance of DisplayProxy.
- #method_missing(method_name, *args, &block) ⇒ Object
- #on_widget_disposed(&block) ⇒ Object
- #respond_to?(method_name, *args, &block) ⇒ Boolean
-
#sync_exec(&block) ⇒ Object
synchronously executes the block (required from threads other than first GUI thread) returns the value produced by the block.
- #sync_exec_in_progress? ⇒ Boolean
-
#sync_exec_required? ⇒ Boolean
Indicates whether ‘sync_exec` is required because of running in a different thread from the GUI thread `async_exec` could be used as an alternative to `sync_exec` when required.
- #timer_exec(delay_in_millis, &block) ⇒ Object
Methods included from Custom::Drawable
#add_shape, #clear_shapes, #deregister_shape_painting, #drop_shapes, #expanded_shapes, #image_buffered_shapes, #paint_pixel_by_pixel, #setup_shape_painting, #shape_at_location, #shapes, #swt_drawable
Constructor Details
#initialize(*args) ⇒ DisplayProxy
Returns a new instance of DisplayProxy.
81 82 83 84 85 86 87 88 89 |
# File 'lib/glimmer/swt/display_proxy.rb', line 81 def initialize(*args) Display.app_name ||= 'Glimmer' @swt_display = Display.new(*args) @swt_display.set_data('proxy', self) @execs_in_progress = {} on_swt_Dispose { clear_shapes } end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_name, *args, &block) ⇒ Object
168 169 170 171 172 173 174 175 176 177 |
# File 'lib/glimmer/swt/display_proxy.rb', line 168 def method_missing(method_name, *args, &block) if block && can_handle_observation_request?(method_name) handle_observation_request(method_name, &block) else swt_display.send(method_name, *args, &block) end rescue => e Glimmer::Config.logger.debug {"Neither DisplayProxy nor #{swt_display.class.name} can handle the method ##{method_name}"} super end |
Instance Attribute Details
#swt_display ⇒ Object (readonly)
SWT Display object wrapped
79 80 81 |
# File 'lib/glimmer/swt/display_proxy.rb', line 79 def swt_display @swt_display end |
Class Method Details
.current_custom_widgets_and_shapes ⇒ Object
Current custom widgets, shells, and shapes being rendered. Useful to yoke all observers evaluated during rendering of their custom widgets/shells/shapes for automatical disposal on_widget_disposed/on_shape_disposed
73 74 75 |
# File 'lib/glimmer/swt/display_proxy.rb', line 73 def @current_custom_widgets_and_shapes ||= [] end |
.instance(*args) ⇒ Object
Returns singleton instance
59 60 61 62 63 64 65 |
# File 'lib/glimmer/swt/display_proxy.rb', line 59 def instance(*args) if @instance.nil? || @instance.swt_display.nil? || @instance.swt_display.isDisposed @thread = Thread.current @instance = new(*args) end @instance end |
.thread ⇒ Object
67 68 69 70 |
# File 'lib/glimmer/swt/display_proxy.rb', line 67 def thread instance # ensure instance @thread end |
Instance Method Details
#add_swt_event_filter(swt_constant, &block) ⇒ Object
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 |
# File 'lib/glimmer/swt/display_proxy.rb', line 220 def add_swt_event_filter(swt_constant, &block) event_type = SWTProxy[swt_constant] swt_listener = ConcreteListener.new(&block) @swt_display.addFilter(event_type, swt_listener) #WidgetListenerProxy.new(@swt_display.getListeners(event_type).last) WidgetListenerProxy.new( swt_display: @swt_display, event_type: event_type, filter: true, swt_listener: swt_listener, widget_add_listener_method: 'addFilter', swt_listener_class: ConcreteListener, swt_listener_method: 'handleEvent' ) end |
#async_exec(&block) ⇒ Object
asynchronously executes the block (required from threads other than first GUI thread) does not return the value produced by the block since it is async, running after the return
97 98 99 100 101 102 103 104 105 106 |
# File 'lib/glimmer/swt/display_proxy.rb', line 97 def async_exec(&block) @swt_display.asyncExec do execs_in_progress << :async_exec begin result = block.call ensure execs_in_progress.pop end end end |
#async_exec_in_progress? ⇒ Boolean
133 134 135 |
# File 'lib/glimmer/swt/display_proxy.rb', line 133 def async_exec_in_progress? execs_in_progress.last == :async_exec end |
#auto_exec(override_sync_exec: nil, override_async_exec: nil, &block) ⇒ Object
Invoke block with ‘sync_exec` only when necessary (running from a separate thread) Override sync_exec as `true` to force using or `false` to force avoiding Override async_exec as `true` to force using or `:unless_in_progress` to force using only if no `async_exec` is in progress Disable auto execution of `sync_exec` via `Glimmer::Config.auto_sync_exec = false` Otherwise, runs normally, thus allowing SWT to decide how to batch/optimize GUI updates
150 151 152 153 154 155 156 157 158 |
# File 'lib/glimmer/swt/display_proxy.rb', line 150 def auto_exec(override_sync_exec: nil, override_async_exec: nil, &block) if override_sync_exec || override_sync_exec.nil? && !override_async_exec && sync_exec_required? && Config.auto_sync_exec? && !sync_exec_in_progress? && !async_exec_in_progress? sync_exec(&block) elsif override_async_exec || override_async_exec.to_s == 'unless_in_progress' && !async_exec_in_progress? async_exec(&block) else block.call end end |
#can_handle_observation_request?(observation_request) ⇒ Boolean
185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/glimmer/swt/display_proxy.rb', line 185 def can_handle_observation_request?(observation_request) observation_request = observation_request.to_s if observation_request.start_with?('on_swt_') constant_name = observation_request.sub(/^on_swt_/, '') SWTProxy.has_constant?(constant_name) elsif observation_request.start_with?('on_') event_name = observation_request.sub(/^on_/, '') OBSERVED_MENU_ITEMS.include?(event_name) else false end end |
#content(&block) ⇒ Object
91 92 93 |
# File 'lib/glimmer/swt/display_proxy.rb', line 91 def content(&block) Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::SWT::DisplayExpression.new, 'display', &block) end |
#disposed? ⇒ Boolean
164 165 166 |
# File 'lib/glimmer/swt/display_proxy.rb', line 164 def disposed? @swt_display.isDisposed end |
#execs_in_progress ⇒ Object
141 142 143 |
# File 'lib/glimmer/swt/display_proxy.rb', line 141 def execs_in_progress @execs_in_progress[Thread.current] ||= [] end |
#handle_observation_request(observation_request, &block) ⇒ Object
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/glimmer/swt/display_proxy.rb', line 198 def handle_observation_request(observation_request, &block) observation_request = observation_request.to_s if observation_request.start_with?('on_swt_') constant_name = observation_request.sub(/^on_swt_/, '') swt_event_reg = add_swt_event_filter(constant_name, &block) DisplayProxy..last&.observer_registrations&.push(swt_event_reg) swt_event_reg elsif observation_request.start_with?('on_') event_name = observation_request.sub(/^on_/, '') if OBSERVED_MENU_ITEMS.include?(event_name) && OS.mac? auto_exec do = swt_display.getSystemMenu = .getItems.find {|| .getID == SWTProxy["ID_#{event_name.upcase}"]} listener = ConcreteListener.new(&block) display_mac_event_registration = .addListener(SWTProxy[:Selection], listener) DisplayProxy..last&.observer_registrations&.push(display_mac_event_registration) display_mac_event_registration end end end end |
#on_widget_disposed(&block) ⇒ Object
160 161 162 |
# File 'lib/glimmer/swt/display_proxy.rb', line 160 def (&block) on_swt_Dispose(&block) end |
#respond_to?(method_name, *args, &block) ⇒ Boolean
179 180 181 182 183 |
# File 'lib/glimmer/swt/display_proxy.rb', line 179 def respond_to?(method_name, *args, &block) super || can_handle_observation_request?(method_name) || swt_display.respond_to?(method_name, *args, &block) end |
#sync_exec(&block) ⇒ Object
synchronously executes the block (required from threads other than first GUI thread) returns the value produced by the block
110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/glimmer/swt/display_proxy.rb', line 110 def sync_exec(&block) result = nil @swt_display.syncExec do execs_in_progress << :sync_exec begin result = block.call ensure execs_in_progress.pop end end result end |
#sync_exec_in_progress? ⇒ Boolean
137 138 139 |
# File 'lib/glimmer/swt/display_proxy.rb', line 137 def sync_exec_in_progress? execs_in_progress.include?(:sync_exec) end |
#sync_exec_required? ⇒ Boolean
Indicates whether ‘sync_exec` is required because of running in a different thread from the GUI thread `async_exec` could be used as an alternative to `sync_exec` when required.
129 130 131 |
# File 'lib/glimmer/swt/display_proxy.rb', line 129 def sync_exec_required? Thread.current != DisplayProxy.thread end |
#timer_exec(delay_in_millis, &block) ⇒ Object
123 124 125 |
# File 'lib/glimmer/swt/display_proxy.rb', line 123 def timer_exec(delay_in_millis, &block) @swt_display.timerExec(delay_in_millis, &block) end |