glimmer-dsl-wx 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,39 @@
1
+ # Copyright (c) 2007-2022 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ require 'delegate'
23
+
24
+ module Glimmer
25
+ class ProcTracker < DelegateClass(Proc)
26
+ def initialize(proc)
27
+ super(proc)
28
+ end
29
+
30
+ def call(*args)
31
+ __getobj__.call(*args)
32
+ @called = true
33
+ end
34
+
35
+ def called?
36
+ !!@called
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,409 @@
1
+ # Copyright (c) 2021-2023 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ require 'glimmer/libui/data_bindable'
23
+
24
+ module Glimmer
25
+ module LibUI
26
+ # Proxy for LibUI control objects
27
+ #
28
+ # Follows the Proxy Design Pattern
29
+ class ControlProxy
30
+ class << self
31
+ def exists?(keyword)
32
+ ::LibUI.respond_to?("new_#{keyword}") or
33
+ ::LibUI.respond_to?(keyword) or
34
+ descendant_keyword_constant_map.keys.include?(keyword)
35
+ end
36
+
37
+ def create(keyword, parent, args, &block)
38
+ widget_proxy_class(keyword).new(keyword, parent, args, &block).tap {|c| control_proxies << c}
39
+ end
40
+
41
+ def widget_proxy_class(keyword)
42
+ descendant_keyword_constant_map[keyword] || ControlProxy
43
+ end
44
+
45
+ # autosave all controls in this array to avoid garbage collection
46
+ def control_proxies
47
+ @@control_proxies = [] unless defined?(@@control_proxies)
48
+ @@control_proxies
49
+ end
50
+
51
+ def main_window_proxy
52
+ control_proxies.find {|c| c.is_a?(WindowProxy)}
53
+ end
54
+
55
+ def menu_proxies
56
+ control_proxies.select {|c| c.keyword == 'menu' }
57
+ end
58
+
59
+ def image_proxies
60
+ control_proxies.select {|c| c.keyword == 'image' }
61
+ end
62
+
63
+ def new_control(keyword, args)
64
+ ::LibUI.send("new_#{keyword}", *args)
65
+ end
66
+
67
+ def constant_symbol(keyword)
68
+ "#{keyword.camelcase(:upper)}Proxy".to_sym
69
+ end
70
+
71
+ def keyword(constant_symbol)
72
+ constant_symbol.to_s.underscore.sub(/_proxy$/, '')
73
+ end
74
+
75
+ def descendant_keyword_constant_map
76
+ @descendant_keyword_constant_map ||= add_aliases_to_keyword_constant_map(map_descendant_keyword_constants_for(self))
77
+ end
78
+
79
+ def reset_descendant_keyword_constant_map
80
+ @descendant_keyword_constant_map = nil
81
+ descendant_keyword_constant_map
82
+ end
83
+
84
+ def map_descendant_keyword_constants_for(klass, accumulator: {})
85
+ klass.constants.map do |constant_symbol|
86
+ [constant_symbol, klass.const_get(constant_symbol)]
87
+ end.select do |constant_symbol, constant|
88
+ constant.is_a?(Module) && !accumulator.values.include?(constant)
89
+ end.each do |constant_symbol, constant|
90
+ accumulator[keyword(constant_symbol)] = constant
91
+ map_descendant_keyword_constants_for(constant, accumulator: accumulator)
92
+ end
93
+ accumulator
94
+ end
95
+
96
+ private
97
+
98
+ def add_aliases_to_keyword_constant_map(keyword_constant_map)
99
+ KEYWORD_ALIASES.each do |keyword, alias_keyword|
100
+ keyword_constant_map[alias_keyword] = keyword_constant_map[keyword]
101
+ end
102
+ keyword_constant_map
103
+ end
104
+ end
105
+
106
+ include DataBindable
107
+
108
+ KEYWORD_ALIASES = {
109
+ 'msg_box' => 'message_box',
110
+ 'msg_box_error' => 'message_box_error',
111
+ }
112
+
113
+ BOOLEAN_PROPERTIES = %w[
114
+ padded
115
+ checked
116
+ enabled toplevel visible
117
+ read_only
118
+ margined
119
+ borderless fullscreen
120
+ stretchy
121
+ ]
122
+
123
+ STRING_PROPERTIES = %w[
124
+ text
125
+ title
126
+ ]
127
+
128
+ # libui returns the contained LibUI object
129
+ attr_reader :parent_proxy, :libui, :args, :keyword, :block, :content_added
130
+ alias content_added? content_added
131
+
132
+ def initialize(keyword, parent, args, &block)
133
+ @keyword = keyword
134
+ @parent_proxy = parent
135
+ @args = args
136
+ @block = block
137
+ @enabled = true
138
+ build_control
139
+ post_add_content if @block.nil?
140
+ end
141
+
142
+ # Subclasses may override to perform post add_content work (normally must call super)
143
+ def post_add_content
144
+ unless @content_added
145
+ @parent_proxy&.post_initialize_child(self)
146
+ @content_added = true
147
+ end
148
+ end
149
+
150
+ # Subclasses may override to perform post initialization work on an added child
151
+ def post_initialize_child(child)
152
+ # No Op by default
153
+ end
154
+
155
+ def window_proxy
156
+ found_proxy = self
157
+ until found_proxy.nil? || found_proxy.is_a?(WindowProxy)
158
+ found_proxy = found_proxy.parent_proxy
159
+ end
160
+ found_proxy
161
+ end
162
+
163
+ def can_handle_listener?(listener_name)
164
+ ::LibUI.respond_to?("#{libui_api_keyword}_#{listener_name}") ||
165
+ ::LibUI.respond_to?("control_#{listener_name}") ||
166
+ has_custom_listener?(listener_name)
167
+ end
168
+
169
+ def handle_listener(listener_name, &listener)
170
+ # replace first listener argument (control libui pointer) with actual Ruby libui object
171
+ safe_listener = Proc.new { |*args| listener.call(self, *args[1..-1]) }
172
+ if ::LibUI.respond_to?("#{libui_api_keyword}_#{listener_name}")
173
+ if listeners[listener_name].nil?
174
+ ::LibUI.send("#{libui_api_keyword}_#{listener_name}", libui) do |*args|
175
+ listeners_for(listener_name).map { |listener| listener.call(*args) }.last
176
+ end
177
+ end
178
+ listeners_for(listener_name) << safe_listener
179
+ elsif ::LibUI.respond_to?("control_#{listener_name}")
180
+ if listeners[listener_name].nil?
181
+ ::LibUI.send("control_#{listener_name}", libui) do |*args|
182
+ listeners_for(listener_name).map { |listener| listener.call(*args) }.last
183
+ end
184
+ end
185
+ listeners_for(listener_name) << safe_listener
186
+ elsif has_custom_listener?(listener_name)
187
+ handle_custom_listener(listener_name, &listener)
188
+ end
189
+ end
190
+
191
+ def listeners
192
+ @listeners ||= {}
193
+ end
194
+
195
+ def listeners_for(listener_name)
196
+ listeners[listener_name] ||= []
197
+ end
198
+
199
+ def has_custom_listener?(listener_name)
200
+ listener_name = listener_name.to_s
201
+ custom_listener_names.include?(listener_name) || custom_listener_name_aliases.stringify_keys.keys.include?(listener_name)
202
+ end
203
+
204
+ def custom_listener_names
205
+ self.class.constants.include?(:CUSTOM_LISTENER_NAMES) ? self.class::CUSTOM_LISTENER_NAMES : []
206
+ end
207
+
208
+ def custom_listener_name_aliases
209
+ self.class.constants.include?(:CUSTOM_LISTENER_NAME_ALIASES) ? self.class::CUSTOM_LISTENER_NAME_ALIASES : {}
210
+ end
211
+
212
+ def handle_custom_listener(listener_name, &listener)
213
+ listener_name = listener_name.to_s
214
+ listener_name = custom_listener_name_aliases.stringify_keys[listener_name] || listener_name
215
+ instance_variable_name = "@#{listener_name}_procs" # TODO ensure clearing custom listeners on destroy of a control
216
+ instance_variable_set(instance_variable_name, []) if instance_variable_get(instance_variable_name).nil?
217
+ if listener.nil?
218
+ instance_variable_get(instance_variable_name)
219
+ else
220
+ instance_variable_get(instance_variable_name) << listener
221
+ listener
222
+ end
223
+ end
224
+
225
+ def notify_custom_listeners(listener_name, *args)
226
+ handle_custom_listener(listener_name).each do |listener|
227
+ listener.call(*args)
228
+ end
229
+ end
230
+
231
+ def deregister_custom_listeners(listener_name)
232
+ handle_custom_listener(listener_name).clear
233
+ end
234
+
235
+ # deregisters all custom listeners except on_destroy, which can only be deregistered after destruction of a control, using deregister_custom_listeners
236
+ def deregister_all_custom_listeners
237
+ (custom_listener_names - ['on_destroy']).each { |listener_name| deregister_custom_listeners(listener_name) }
238
+ end
239
+
240
+ def respond_to?(method_name, *args, &block)
241
+ respond_to_libui?(method_name, *args, &block) ||
242
+ (
243
+ append_properties.include?(method_name.to_s) ||
244
+ (append_properties.include?(method_name.to_s.sub(/\?$/, '')) && BOOLEAN_PROPERTIES.include?(method_name.to_s.sub(/\?$/, ''))) ||
245
+ append_properties.include?(method_name.to_s.sub(/=$/, ''))
246
+ ) ||
247
+ can_handle_listener?(method_name.to_s) ||
248
+ super(method_name, true)
249
+ end
250
+
251
+ def respond_to_libui?(method_name, *args, &block)
252
+ ::LibUI.respond_to?("control_#{method_name}") or
253
+ (::LibUI.respond_to?("control_#{method_name.to_s.sub(/\?$/, '')}") && BOOLEAN_PROPERTIES.include?(method_name.to_s.sub(/\?$/, '')) ) or
254
+ ::LibUI.respond_to?("control_set_#{method_name.to_s.sub(/=$/, '')}") or
255
+ ::LibUI.respond_to?("#{libui_api_keyword}_#{method_name}") or
256
+ (::LibUI.respond_to?("#{libui_api_keyword}_#{method_name.to_s.sub(/\?$/, '')}") && BOOLEAN_PROPERTIES.include?(method_name.to_s.sub(/\?$/, '')) ) or
257
+ ::LibUI.respond_to?("#{libui_api_keyword}_set_#{method_name.to_s.sub(/=$/, '')}")
258
+ end
259
+
260
+ def method_missing(method_name, *args, &block)
261
+ if respond_to_libui?(method_name, *args, &block)
262
+ send_to_libui(method_name, *args, &block)
263
+ elsif append_properties.include?(method_name.to_s) ||
264
+ append_properties.include?(method_name.to_s.sub(/(=|\?)$/, ''))
265
+ append_property(method_name, *args)
266
+ elsif can_handle_listener?(method_name.to_s)
267
+ handle_listener(method_name.to_s, &block)
268
+ else
269
+ super
270
+ end
271
+ end
272
+
273
+ def send_to_libui(method_name, *args, &block)
274
+ if ::LibUI.respond_to?("#{libui_api_keyword}_#{method_name.to_s.sub(/\?$/, '')}") && args.empty?
275
+ property = method_name.to_s.sub(/\?$/, '')
276
+ value = ::LibUI.send("#{libui_api_keyword}_#{property}", libui, *args)
277
+ handle_string_property(property, handle_boolean_property(property, value))
278
+ elsif ::LibUI.respond_to?("#{libui_api_keyword}_get_#{method_name.to_s.sub(/\?$/, '')}") && args.empty?
279
+ property = method_name.to_s.sub(/\?$/, '')
280
+ value = ::LibUI.send("#{libui_api_keyword}_get_#{property}", libui, *args)
281
+ handle_string_property(property, handle_boolean_property(property, value))
282
+ elsif ::LibUI.respond_to?("#{libui_api_keyword}_set_#{method_name.to_s.sub(/=$/, '')}") && !args.empty?
283
+ property = method_name.to_s.sub(/=$/, '')
284
+ args[0] = Glimmer::LibUI.boolean_to_integer(args.first) if BOOLEAN_PROPERTIES.include?(property) && (args.first.is_a?(TrueClass) || args.first.is_a?(FalseClass))
285
+ args[0] = '' if STRING_PROPERTIES.include?(property) && args.first == nil
286
+ if property.to_s == 'checked'
287
+ current_value = Glimmer::LibUI.integer_to_boolean(::LibUI.send("#{libui_api_keyword}_checked", libui), allow_nil: false)
288
+ new_value = Glimmer::LibUI.integer_to_boolean(args[0], allow_nil: false)
289
+ ::LibUI.send("#{libui_api_keyword}_set_#{property}", libui, *args) if new_value != current_value
290
+ else
291
+ ::LibUI.send("#{libui_api_keyword}_set_#{property}", libui, *args)
292
+ end
293
+ elsif ::LibUI.respond_to?("#{libui_api_keyword}_#{method_name}") && !args.empty?
294
+ ::LibUI.send("#{libui_api_keyword}_#{method_name}", libui, *args)
295
+ elsif ::LibUI.respond_to?("control_#{method_name.to_s.sub(/\?$/, '')}") && args.empty?
296
+ property = method_name.to_s.sub(/\?$/, '')
297
+ value = ::LibUI.send("control_#{property}", libui, *args)
298
+ handle_string_property(property, handle_boolean_property(property, value))
299
+ elsif ::LibUI.respond_to?("control_set_#{method_name.to_s.sub(/=$/, '')}")
300
+ property = method_name.to_s.sub(/=$/, '')
301
+ args[0] = Glimmer::LibUI.boolean_to_integer(args.first) if BOOLEAN_PROPERTIES.include?(property) && (args.first.is_a?(TrueClass) || args.first.is_a?(FalseClass))
302
+ args[0] = '' if STRING_PROPERTIES.include?(property) && args.first == nil
303
+ ::LibUI.send("control_set_#{method_name.to_s.sub(/=$/, '')}", libui, *args)
304
+ elsif ::LibUI.respond_to?("control_#{method_name}") && !args.empty?
305
+ ::LibUI.send("control_#{method_name}", libui, *args)
306
+ end
307
+ end
308
+
309
+ def append_properties
310
+ @parent_proxy&.class&.constants&.include?(:APPEND_PROPERTIES) ? @parent_proxy.class::APPEND_PROPERTIES : []
311
+ end
312
+
313
+ def append_property(property, value = nil)
314
+ property = property.to_s.sub(/(=|\?)$/, '')
315
+ @append_property_hash ||= {}
316
+ if value.nil?
317
+ value = @append_property_hash[property]
318
+ handle_string_property(property, handle_boolean_property(property, value))
319
+ else
320
+ value = Glimmer::LibUI.boolean_to_integer(value) if BOOLEAN_PROPERTIES.include?(property) && (value.is_a?(TrueClass) || value.is_a?(FalseClass))
321
+ @append_property_hash[property] = value
322
+ end
323
+ end
324
+
325
+ def libui_api_keyword
326
+ @keyword
327
+ end
328
+
329
+ def destroy
330
+ # TODO exclude menus from this initial return
331
+ return if !is_a?(ControlProxy::WindowProxy) && ControlProxy.main_window_proxy&.destroying?
332
+ data_binding_model_attribute_observer_registrations.each(&:deregister)
333
+ if parent_proxy.nil?
334
+ default_destroy
335
+ else
336
+ parent_proxy.destroy_child(self)
337
+ end
338
+ end
339
+
340
+ def destroy_child(child)
341
+ child.default_destroy
342
+ children.delete(child)
343
+ end
344
+
345
+ def default_destroy
346
+ deregister_all_custom_listeners
347
+ send_to_libui('destroy')
348
+ ControlProxy.control_proxies.delete(self)
349
+ end
350
+
351
+ def enabled(value = nil)
352
+ if value.nil?
353
+ @enabled
354
+ elsif value != @enabled
355
+ @enabled = value == 1 || value
356
+ if value == 1 || value
357
+ send_to_libui('enable')
358
+ else
359
+ send_to_libui('disable')
360
+ end
361
+ end
362
+ end
363
+ alias enabled? enabled
364
+ alias set_enabled enabled
365
+ alias enabled= enabled
366
+
367
+ def visible(value = nil)
368
+ current_value = send_to_libui('visible')
369
+ if value.nil?
370
+ current_value
371
+ elsif value != current_value
372
+ if value == 1 || value
373
+ send_to_libui('show')
374
+ else
375
+ send_to_libui('hide')
376
+ end
377
+ end
378
+ end
379
+ alias visible? visible
380
+ alias set_visible visible
381
+ alias visible= visible
382
+
383
+ def content(&block)
384
+ Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::Libui::ControlExpression.new, @keyword, {post_add_content: @content_added}, &block)
385
+ end
386
+
387
+ private
388
+
389
+ def build_control
390
+ @libui = if ::LibUI.respond_to?("new_#{keyword}")
391
+ ControlProxy.new_control(@keyword, @args)
392
+ elsif ::LibUI.respond_to?(keyword)
393
+ @args[0] = @args.first.libui if @args.first.is_a?(ControlProxy)
394
+ ::LibUI.send(@keyword, *@args)
395
+ end
396
+ end
397
+
398
+ def handle_boolean_property(property, value)
399
+ BOOLEAN_PROPERTIES.include?(property) ? Glimmer::LibUI.integer_to_boolean(value) : value
400
+ end
401
+
402
+ def handle_string_property(property, value)
403
+ STRING_PROPERTIES.include?(property) ? value.to_s : value
404
+ end
405
+ end
406
+ end
407
+ end
408
+
409
+ Dir[File.expand_path("./#{File.basename(__FILE__, '.rb')}/*.rb", __dir__)].each {|f| require f}
@@ -0,0 +1,69 @@
1
+ # Copyright (c) 2021-2023 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ module Glimmer
23
+ module LibUI
24
+ # Parent controls and shapes who have children and add child post_initialize_child
25
+ module DataBindable
26
+ # Sets up read/write (bidirectional) data-binding
27
+ #
28
+ # classes are expected to implement `data_bind_write(property, model_binding)` to setup write data-binding
29
+ # by observing view property for changes and writing to model attribute via model binding accordingly
30
+ #
31
+ # classes can override data_bind_read to disable read data-binding in rare scenarios that might need it
32
+ #
33
+ # returns model attribute reading observer registration by default
34
+ def data_bind(property, model_binding)
35
+ data_bind_read(property, model_binding).tap do
36
+ data_bind_write(property, model_binding) unless model_binding.binding_options[:read_only]
37
+ end
38
+ end
39
+
40
+ # Sets up read data-binding (reading from model to update view)
41
+ #
42
+ # Default implementation observes model attribute for changes via model binding
43
+ # and updates view property accordingly
44
+ def data_bind_read(property, model_binding)
45
+ model_attribute_observer = Glimmer::DataBinding::Observer.proc do
46
+ new_value = model_binding.evaluate_property
47
+ send("#{property}=", new_value) unless send(property) == new_value
48
+ end
49
+ observer_registration = model_attribute_observer.observe(model_binding, attribute_writer_type: [:attribute=, :set_attribute])
50
+ model_attribute_observer.call # initial update
51
+ data_binding_model_attribute_observer_registrations << observer_registration
52
+ observer_registration
53
+ end
54
+
55
+ # Sets up write data-binding (writing to model from view)
56
+ #
57
+ # Has no implementation by default. Classes are expected
58
+ # to implement this method by observing view property
59
+ # for changes and writing them to model accordingly via model binding
60
+ def data_bind_write(property, model_binding)
61
+ # No Op by default
62
+ end
63
+
64
+ def data_binding_model_attribute_observer_registrations
65
+ @data_binding_model_attribute_observer_registrations ||= []
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,36 @@
1
+ # Copyright (c) 2021-2023 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ module Glimmer
23
+ module LibUI
24
+ # Parent controls and shapes who have children and add child post_initialize_child
25
+ module Parent
26
+ # Subclasses can override and must call super (passing add_child: false to cancel adding child to children)
27
+ def post_initialize_child(child, add_child: true)
28
+ children << child if add_child
29
+ end
30
+
31
+ def children
32
+ @children ||= []
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,7 @@
1
+ module Glimmer
2
+ class << self
3
+ def included(klass)
4
+ klass.extend(Glimmer)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,53 @@
1
+ # Copyright (c) 2021-2023 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ $LOAD_PATH.unshift(File.expand_path('..', __FILE__))
23
+
24
+ # External requires
25
+ require 'glimmer'
26
+ # require 'perfect-shape'
27
+ # require 'logging'
28
+ # require 'puts_debuggerer' if ENV['pd'].to_s.downcase == 'true'
29
+ # require 'super_module'
30
+ # require 'color'
31
+ require 'os'
32
+ # require 'equalizer'
33
+ require 'array_include_methods'
34
+ require 'facets/hash/stringify_keys'
35
+ require 'facets/string/underscore'
36
+ require 'wx'
37
+
38
+ # Internal requires
39
+ # require 'ext/glimmer/config'
40
+ require 'glimmer-dsl-wx/ext/glimmer'
41
+ require 'glimmer/dsl/wx/dsl'
42
+ Glimmer::Config.loop_max_count = -1
43
+ Glimmer::Config.excluded_keyword_checkers << lambda do |method_symbol, *args|
44
+ method = method_symbol.to_s
45
+ result = false
46
+ result ||= method == 'load_iseq'
47
+ end
48
+
49
+ # begin
50
+ # PutsDebuggerer.printer = lambda { |m| puts m; $stdout.flush}
51
+ # rescue
52
+ ##### No Op if puts_debuggerer is not loaded
53
+ # end
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+ # wxRuby2 Sample Code. Copyright (c) 2004-2008 wxRuby development team
3
+ # Adapted for wxRuby3
4
+ # Copyright (c) M.J.N. Corino, The Netherlands
5
+ ###
6
+
7
+ # require 'wx'
8
+
9
+ # This is the minimum code to start a WxRuby app - create a Frame, and
10
+ # show it.
11
+ # Wx::App.run do
12
+ ### self.app_name = 'Nothing'
13
+ ### frame = Wx::Frame.new(nil, title: "Empty wxRuby App")
14
+ # frame = Wx::Frame.new(nil)
15
+ # frame.title = "Empty wxRuby App"
16
+ # frame.show
17
+ # frame
18
+ # end
19
+
20
+ require './lib/glimmer-dsl-wx'
21
+
22
+ include Glimmer
23
+
24
+ frame
Binary file
Binary file