glimmer-dsl-wx 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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