wxruby3-shapes 0.9.0.pre.beta.3

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.
Files changed (112) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +12 -0
  3. data/CREDITS.md +18 -0
  4. data/INSTALL.md +39 -0
  5. data/LICENSE +21 -0
  6. data/README.md +118 -0
  7. data/assets/screenshot.png +0 -0
  8. data/bin/wx-shapes +9 -0
  9. data/lib/wx/shapes/arrow_base.rb +86 -0
  10. data/lib/wx/shapes/arrows/circle_arrow.rb +39 -0
  11. data/lib/wx/shapes/arrows/diamond_arrow.rb +33 -0
  12. data/lib/wx/shapes/arrows/open_arrow.rb +56 -0
  13. data/lib/wx/shapes/arrows/solid_arrow.rb +69 -0
  14. data/lib/wx/shapes/art/shape_canvas/page.xpm +73 -0
  15. data/lib/wx/shapes/auto_layout.rb +358 -0
  16. data/lib/wx/shapes/base.rb +33 -0
  17. data/lib/wx/shapes/canvas_history.rb +84 -0
  18. data/lib/wx/shapes/connection_point.rb +238 -0
  19. data/lib/wx/shapes/core.rb +19 -0
  20. data/lib/wx/shapes/diagram.rb +659 -0
  21. data/lib/wx/shapes/events.rb +389 -0
  22. data/lib/wx/shapes/printout.rb +136 -0
  23. data/lib/wx/shapes/serializable.rb +440 -0
  24. data/lib/wx/shapes/serialize/core.rb +40 -0
  25. data/lib/wx/shapes/serialize/id.rb +82 -0
  26. data/lib/wx/shapes/serialize/wx.rb +104 -0
  27. data/lib/wx/shapes/serializer/json.rb +258 -0
  28. data/lib/wx/shapes/serializer/yaml.rb +125 -0
  29. data/lib/wx/shapes/shape.rb +2129 -0
  30. data/lib/wx/shapes/shape_canvas.rb +3285 -0
  31. data/lib/wx/shapes/shape_data_object.rb +43 -0
  32. data/lib/wx/shapes/shape_handle.rb +287 -0
  33. data/lib/wx/shapes/shape_list.rb +161 -0
  34. data/lib/wx/shapes/shapes/bitmap_shape.rb +257 -0
  35. data/lib/wx/shapes/shapes/circle_shape.rb +136 -0
  36. data/lib/wx/shapes/shapes/control_shape.rb +483 -0
  37. data/lib/wx/shapes/shapes/curve_shape.rb +231 -0
  38. data/lib/wx/shapes/shapes/diamond_shape.rb +62 -0
  39. data/lib/wx/shapes/shapes/edit_text_shape.rb +317 -0
  40. data/lib/wx/shapes/shapes/ellipse_shape.rb +106 -0
  41. data/lib/wx/shapes/shapes/flex_grid_shape.rb +78 -0
  42. data/lib/wx/shapes/shapes/grid_shape.rb +404 -0
  43. data/lib/wx/shapes/shapes/line_shape.rb +907 -0
  44. data/lib/wx/shapes/shapes/multi_sel_rect.rb +214 -0
  45. data/lib/wx/shapes/shapes/ortho_shape.rb +357 -0
  46. data/lib/wx/shapes/shapes/polygon_shape.rb +294 -0
  47. data/lib/wx/shapes/shapes/rect_shape.rb +378 -0
  48. data/lib/wx/shapes/shapes/round_ortho_shape.rb +131 -0
  49. data/lib/wx/shapes/shapes/round_rect_shape.rb +142 -0
  50. data/lib/wx/shapes/shapes/square_shape.rb +119 -0
  51. data/lib/wx/shapes/shapes/text_shape.rb +324 -0
  52. data/lib/wx/shapes/thumbnail.rb +234 -0
  53. data/lib/wx/shapes/version.rb +12 -0
  54. data/lib/wx/shapes/wx.rb +29 -0
  55. data/lib/wx/shapes.rb +18 -0
  56. data/lib/wx/wx-shapes/base.rb +87 -0
  57. data/lib/wx/wx-shapes/cmd/sampler.rb +58 -0
  58. data/lib/wx/wx-shapes/cmd/test.rb +27 -0
  59. data/rakelib/yard/templates/default/fulldoc/html/css/wxruby3.css +7 -0
  60. data/rakelib/yard/templates/default/layout/html/setup.rb +5 -0
  61. data/rakelib/yard/yard/relative_markdown_links/version.rb +8 -0
  62. data/rakelib/yard/yard/relative_markdown_links.rb +39 -0
  63. data/rakelib/yard/yard-custom-templates.rb +2 -0
  64. data/rakelib/yard/yard-relative_markdown_links.rb +4 -0
  65. data/samples/demo/art/AlignBottom.xpm +35 -0
  66. data/samples/demo/art/AlignCenter.xpm +35 -0
  67. data/samples/demo/art/AlignLeft.xpm +35 -0
  68. data/samples/demo/art/AlignMiddle.xpm +35 -0
  69. data/samples/demo/art/AlignRight.xpm +35 -0
  70. data/samples/demo/art/AlignTop.xpm +35 -0
  71. data/samples/demo/art/Bitmap.xpm +25 -0
  72. data/samples/demo/art/Circle.xpm +22 -0
  73. data/samples/demo/art/Curve.xpm +21 -0
  74. data/samples/demo/art/Diamond.xpm +22 -0
  75. data/samples/demo/art/EditText.xpm +21 -0
  76. data/samples/demo/art/Ellipse.xpm +22 -0
  77. data/samples/demo/art/FixedRect.xpm +22 -0
  78. data/samples/demo/art/FlexGrid.xpm +22 -0
  79. data/samples/demo/art/GC.xpm +23 -0
  80. data/samples/demo/art/Grid.xpm +22 -0
  81. data/samples/demo/art/Line.xpm +21 -0
  82. data/samples/demo/art/NoSource.xpm +69 -0
  83. data/samples/demo/art/OrthoLine.xpm +21 -0
  84. data/samples/demo/art/Rect.xpm +22 -0
  85. data/samples/demo/art/RoundOrthoLine.xpm +21 -0
  86. data/samples/demo/art/RoundRect.xpm +22 -0
  87. data/samples/demo/art/Shadow.xpm +23 -0
  88. data/samples/demo/art/StandAloneLine.xpm +22 -0
  89. data/samples/demo/art/Text.xpm +21 -0
  90. data/samples/demo/art/Tool.xpm +23 -0
  91. data/samples/demo/art/sample.xpm +251 -0
  92. data/samples/demo/demo.rb +658 -0
  93. data/samples/demo/frame_canvas.rb +422 -0
  94. data/samples/demo/images/motyl.bmp +0 -0
  95. data/samples/demo/images/motyl2.bmp +0 -0
  96. data/samples/sample1/art/sample.xpm +251 -0
  97. data/samples/sample1/sample.rb +263 -0
  98. data/samples/sample2/art/sample.xpm +251 -0
  99. data/samples/sample2/sample.rb +133 -0
  100. data/samples/sample2/sample_canvas.rb +35 -0
  101. data/samples/sample2/sample_shape.rb +108 -0
  102. data/samples/sample3/art/sample.xpm +251 -0
  103. data/samples/sample3/sample.rb +281 -0
  104. data/samples/sample4/art/sample.xpm +251 -0
  105. data/samples/sample4/sample.rb +180 -0
  106. data/tests/art/motyl.bmp +0 -0
  107. data/tests/lib/wxapp_runner.rb +64 -0
  108. data/tests/serializer_tests.rb +521 -0
  109. data/tests/test_grid_shapes.rb +42 -0
  110. data/tests/test_serialize.rb +7 -0
  111. data/tests/test_serialize_yaml.rb +17 -0
  112. metadata +242 -0
@@ -0,0 +1,440 @@
1
+ # Wx::SF::Serializer - shape serializer module
2
+ # Copyright (c) M.J.N. Corino, The Netherlands
3
+
4
+ require 'set'
5
+
6
+ module Wx::SF
7
+
8
+ module Serializable
9
+
10
+ class Property
11
+ def initialize(klass, prop, proc=nil, force: false, handler: nil, &block)
12
+ ::Kernel.raise ArgumentError, "Invalid property id [#{prop}]" unless ::String === prop || ::Symbol === prop
13
+ ::Kernel.raise ArgumentError, "Duplicate property id [#{prop}]" if klass.has_serializer_property?(prop)
14
+ @klass = klass
15
+ @id = prop.to_sym
16
+ @forced = force
17
+ if block || handler
18
+ if handler
19
+ ::Kernel.raise ArgumentError,
20
+ "Invalid property handler #{handler} for #{prop}" unless ::Proc === handler || ::Symbol === handler
21
+ if handler.is_a?(::Proc)
22
+ ::Kernel.raise ArgumentError, "Invalid property block #{proc} for #{prop}" unless block.arity == -3
23
+ @getter = ->(obj) { handler.call(@id, obj) }
24
+ @setter = ->(obj, val) { handler.call(@id, obj, val) }
25
+ else
26
+ @getter = ->(obj) { obj.send(handler, @id) }
27
+ @setter = ->(obj, val) { obj.send(handler, @id, val) }
28
+ end
29
+ else
30
+ # any property block MUST accept 2 or 3 args; property name, instance and value (for setter)
31
+ ::Kernel.raise ArgumentError, "Invalid property block #{proc} for #{prop}" unless block.arity == -3
32
+ @getter = ->(obj) { block.call(@id, obj) }
33
+ @setter = ->(obj, val) { block.call(@id, obj, val) }
34
+ end
35
+ elsif proc
36
+ ::Kernel.raise ArgumentError,
37
+ "Invalid property proc #{proc} for #{prop}" unless ::Proc === proc || ::Symbol === proc
38
+ if ::Proc === proc
39
+ # any property proc should be callable with a single arg (instance)
40
+ @getter = proc
41
+ # a property proc combining getter/setter functionality should accept a single or more args (instance + value)
42
+ @setter = (proc.arity == -2) ? proc : nil
43
+ else
44
+ @getter = ->(obj) { obj.send(proc) }
45
+ @setter = ->(obj, val) { obj.send(proc, val) }
46
+ end
47
+ end
48
+ end
49
+
50
+ attr_reader :id
51
+
52
+ def serialize(obj, data, excludes)
53
+ unless excludes.include?(@id)
54
+ val = getter.call(obj)
55
+ unless Serializable === val && val.serialize_disabled? && !@forced
56
+ data[@id] = case val
57
+ when ::Array
58
+ val.select { |elem| !(Serializable === elem && elem.serialize_disabled?) }
59
+ when ::Set
60
+ ::Set.new(val.select { |elem| !(Serializable === elem && elem.serialize_disabled?) })
61
+ else
62
+ val
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ def deserialize(obj, data)
69
+ if data.has_key?(@id)
70
+ setter.call(obj, data[@id])
71
+ end
72
+ end
73
+
74
+ def get(obj)
75
+ getter.call(obj)
76
+ end
77
+
78
+ def get_method(id)
79
+ begin
80
+ @klass.instance_method(id)
81
+ rescue NameError
82
+ nil
83
+ end
84
+ end
85
+ private :get_method
86
+
87
+ def getter
88
+ unless @getter
89
+ inst_meth = get_method(@id)
90
+ inst_meth = get_method("get_#{@id}") unless inst_meth
91
+ if inst_meth
92
+ @getter = ->(obj) { inst_meth.bind(obj).call }
93
+ else
94
+ return self.method(:getter_fail)
95
+ end
96
+ end
97
+ @getter
98
+ end
99
+ private :getter
100
+
101
+ def setter
102
+ unless @setter
103
+ inst_meth = get_method("#{@id}=")
104
+ inst_meth = get_method("set_#{@id}") unless inst_meth
105
+ unless inst_meth
106
+ im = get_method(@id)
107
+ if im && im.arity == -1
108
+ inst_meth = im
109
+ else
110
+ inst_meth = nil
111
+ end
112
+ end
113
+ if inst_meth
114
+ @setter = ->(obj, val) { inst_meth.bind(obj).call(val) }
115
+ else
116
+ return self.method(:setter_noop)
117
+ end
118
+ end
119
+ @setter
120
+ end
121
+ private :setter
122
+
123
+ def getter_fail(obj)
124
+ ::Kernel.raise RuntimeError, "Missing getter for property #{@id} of #{@klass}"
125
+ end
126
+ private :getter_fail
127
+
128
+ def setter_noop(_, _)
129
+ # do nothing
130
+ end
131
+ private :setter_noop
132
+ end
133
+
134
+ # Serializable unique ids.
135
+ # This class makes sure to maintain uniqueness across serialization/deserialization cycles
136
+ # and keeps all shared instances within a single (serialized/deserialized) object set in
137
+ # sync.
138
+ class ID; end
139
+
140
+ class << self
141
+
142
+ def serializables
143
+ @serializables ||= ::Set.new
144
+ end
145
+
146
+ def formatters
147
+ @formatters ||= {}
148
+ end
149
+ private :formatters
150
+
151
+ # Registers a serialization formatting engine
152
+ # @param [Symbol,String] format format id
153
+ # @param [Object] engine formatting engine
154
+ def register(format, engine)
155
+ if formatters.has_key?(format.to_s.downcase)
156
+ ::Kernel.raise ArgumentError,
157
+ "Duplicate serialization formatter registration for #{format}"
158
+ end
159
+ formatters[format.to_s.downcase] = engine
160
+ end
161
+
162
+ # Return a serialization formatting engine
163
+ # @param [Symbol,String] format format id
164
+ # @return [Object] formatting engine
165
+ def [](format)
166
+ formatters[format.to_s.downcase]
167
+ end
168
+
169
+ def default_format
170
+ @default_format ||= :json
171
+ end
172
+
173
+ def default_format=(format)
174
+ @default_format = format
175
+ end
176
+
177
+ end
178
+
179
+ # Mixin module for classes that get Wx::SF::Serializable included.
180
+ # This module is used to extend the class methods of the serializable class.
181
+ module SerializeClassMethods
182
+
183
+ # Adds (a) serializable property(-ies) for instances of his class (and derived classes)
184
+ # @overload property(*props, force: false)
185
+ # Specifies one or more serialized properties.
186
+ # The serialization framework will determine the availability of setter and getter methods
187
+ # automatically by looking for methods <code>"#{prop_id}=(v)"</code>, <code>"set_#{prop_id}(v)"</code> or <code>"#{prop}(v)"</code>
188
+ # for setters and <code>"#{prop_id}()"</code> or <code>"get_#{prop_id}"</code> for getters.
189
+ # @param [Symbol,String] props one or more ids of serializable properties
190
+ # @param [Boolean] force overrides any #disable_serialize for the properties specified
191
+ # @overload property(hash, force: false)
192
+ # Specifies one or more serialized properties with associated setter/getter method ids/procs/lambda-s.
193
+ # @example
194
+ # property(
195
+ # prop_a: ->(obj, *val) {
196
+ # obj.my_prop_a_setter(val.first) unless val.empty?
197
+ # obj.my_prop_a_getter
198
+ # },
199
+ # prop_b: Proc.new { |obj, *val|
200
+ # obj.my_prop_b_setter(val.first) unless val.empty?
201
+ # obj.my_prop_b_getter
202
+ # },
203
+ # prop_c: :serialization_method)
204
+ # Procs with setter support MUST accept 1 or 2 arguments (1 for getter, 2 for setter).
205
+ # @note Use `*val` to specify the optional value argument for setter requests instead of `val=nil`
206
+ # to be able to support setting explicit nil values.
207
+ # @param [Hash] hash a hash of pairs of property ids and getter/setter procs
208
+ # @param [Boolean] force overrides any #disable_serialize for the properties specified
209
+ # @overload property(*props, force: false, handler: nil, &block)
210
+ # Specifies one or more serialized properties with a getter/setter handler proc/method/block.
211
+ # The getter/setter proc or block should accept either 2 (property id and object for getter) or 3 arguments
212
+ # (property id, object and value for setter) and is assumed to handle getter/setter requests
213
+ # for all specified properties.
214
+ # The getter/setter method should accept either 1 (property id for getter) or 2 arguments
215
+ # (property id and value for setter) and is assumed to handle getter/setter requests
216
+ # for all specified properties.
217
+ # @example
218
+ # property(:property_a, :property_b, :property_c) do |id, obj, *val|
219
+ # case id
220
+ # when :property_a
221
+ # ...
222
+ # when :property_b
223
+ # ...
224
+ # when :property_c
225
+ # ...
226
+ # end
227
+ # end
228
+ # @note Use `*val` to specify the optional value argument for setter requests instead of `val=nil`
229
+ # to be able to support setting explicit nil values.
230
+ # @param [Symbol,String] props one or more ids of serializable properties
231
+ # @param [Boolean] force overrides any #disable_serialize for the properties specified
232
+ # @yieldparam [Symbol,String] id property id
233
+ # @yieldparam [Object] obj object instance
234
+ # @yieldparam [Object] val optional property value to set in case of setter request
235
+ def property(*props, **kwargs, &block)
236
+ forced = !!kwargs.delete(:force)
237
+ if block || kwargs[:handler]
238
+ props.each do |prop|
239
+ serializer_properties << Property.new(self, prop, force: forced, handler: kwargs[:handler], &block)
240
+ end
241
+ else
242
+ props.flatten.each do |prop|
243
+ if ::Hash === prop
244
+ prop.each_pair do |pn, pp|
245
+ serializer_properties << Property.new(self, pn, pp, force: forced)
246
+ end
247
+ else
248
+ serializer_properties << Property.new(self, prop, force: forced)
249
+ end
250
+ end
251
+ unless kwargs.empty?
252
+ kwargs.each_pair do |pn, pp|
253
+ serializer_properties << Property.new(self, pn, pp, force: forced)
254
+ end
255
+ end
256
+ end
257
+ end
258
+ alias :properties :property
259
+ alias :contains :property
260
+
261
+ # excludes a serializable property for instances of this class
262
+ # (mostly/only useful to exclude properties from base classes which
263
+ # do not require serialization for derived class)
264
+ def excluded_property(*props)
265
+ excluded_serializer_properties.merge props.flatten.collect { |prop| prop.to_s }
266
+ end
267
+ alias :excluded_properties :excluded_property
268
+ alias :excludes :excluded_property
269
+
270
+ # Creates a new instance for subsequent deserialization and optionally initialize
271
+ # it using the given data hash.
272
+ # The default implementation creates a new instance using the default constructor
273
+ # (no arguments, no initialization) and leaves the initialization to a subsequent call
274
+ # to the instance method #from_serialized(data).
275
+ # Classes that do not support a default constructor can override this class method and
276
+ # implement a custom creation scheme.
277
+ # @param [Hash] _data hash containing deserialized property data (symbol keys)
278
+ # @return [Object] the newly created object
279
+ def create_for_deserialize(_data)
280
+ self.new
281
+ end
282
+
283
+ end
284
+
285
+ # Mixin module for classes that get Wx::SF::Serializable included.
286
+ # This module is used to extend the instance methods of the serializable class.
287
+ module SerializeInstanceMethods
288
+
289
+ # Serialize this object
290
+ # @overload serialize(pretty: false, format: Serializable.default_format)
291
+ # @param [Boolean] pretty if true specifies to generate pretty formatted output if possible
292
+ # @param [Symbol,String] format specifies output format
293
+ # @return [String] serialized data
294
+ # @overload serialize(io, pretty: false, format: Serializable.default_format)
295
+ # @param [IO] io output stream to write serialized data to
296
+ # @param [Boolean] pretty if true specifies to generate pretty formatted output if possible
297
+ # @param [Symbol,String] format specifies output format
298
+ # @return [IO]
299
+ def serialize(io = nil, pretty: false, format: Serializable.default_format)
300
+ Serializable[format].dump(self, io, pretty: pretty)
301
+ end
302
+
303
+ # Returns true if regular serialization for this object has been disabled, false otherwise (default).
304
+ # Disabled serialization can be overridden for single objects (not objects maintained in property containers
305
+ # like arrays and sets).
306
+ # @return [Boolean]
307
+ def serialize_disabled?
308
+ !!@serialize_disabled # true for any value but false
309
+ end
310
+
311
+ # Disables serialization for this object as a single property or as part of a property container
312
+ # (array or set).
313
+ # @return [void]
314
+ def disable_serialize
315
+ # by default unset (nil) so serializing enabled
316
+ @serialize_disabled = true
317
+ end
318
+
319
+ # @!method for_serialize(hash, excludes = Set.new)
320
+ # Serializes the properties of a serializable instance to the given hash
321
+ # except when the property id is included in excludes.
322
+ # @param [Hash] hash property serialization hash
323
+ # @param [Set] excludes set with excluded property ids
324
+ # @return [Hash] property serialization hash
325
+
326
+ # @!method from_serialized(hash)
327
+ # Restores the properties of a deserialized instance.
328
+ # @param [Hash] hash deserialized properties hash
329
+ # @return [self]
330
+
331
+ end
332
+
333
+ # Serialize the given object
334
+ # @overload serialize(obj, pretty: false, format: Serializable.default_format)
335
+ # @param [Object] obj object to serialize
336
+ # @param [Boolean] pretty if true specifies to generate pretty formatted output if possible
337
+ # @param [Symbol,String] format specifies output format
338
+ # @return [String] serialized data
339
+ # @overload serialize(obj, io, pretty: false, format: Serializable.default_format)
340
+ # @param [Object] obj object to serialize
341
+ # @param [IO] io output stream to write serialized data to
342
+ # @param [Boolean] pretty if true specifies to generate pretty formatted output if possible
343
+ # @param [Symbol,String] format specifies output format
344
+ # @return [IO]
345
+ def self.serialize(obj, io = nil, pretty: false, format: Serializable.default_format)
346
+ self[format].dump(obj, io, pretty: pretty)
347
+ end
348
+
349
+ # Deserializes object from source data
350
+ # @param [IO,String] source source data (stream)
351
+ # @param [Symbol, String] format data format of source
352
+ # @return [Object] deserialized object
353
+ def self.deserialize(source, format: Serializable.default_format)
354
+ self[format].load(::IO === source || source.respond_to?(:read) ? source.read : source)
355
+ end
356
+
357
+ def self.included(base)
358
+ ::Kernel.raise RuntimeError, "#{self} should only be included in classes" if base.instance_of?(::Module)
359
+
360
+ # register as serializable class
361
+ Serializable.serializables << base
362
+
363
+ return if base == Serializable::ID # special case which does not need the rest
364
+
365
+ # provide serialized property definition support
366
+
367
+ # provide serialized classes with their own serialized properties (exclusion) list
368
+ base.singleton_class.class_eval do
369
+ def serializer_properties
370
+ @serializer_props ||= []
371
+ end
372
+ def excluded_serializer_properties
373
+ @excluded_serializer_props ||= ::Set.new
374
+ end
375
+ end
376
+ # add class methods
377
+ base.extend(SerializeClassMethods)
378
+
379
+ # add instance property (de-)serialization methods for base class
380
+ base.class_eval <<~__CODE
381
+ def for_serialize(hash, excludes = ::Set.new)
382
+ hash[:'@explicit'] = true if serialize_disabled? # mark explicit serialize overriding disabling
383
+ #{base.name}.serializer_properties.each { |prop, h| prop.serialize(self, hash, excludes) }
384
+ hash
385
+ end
386
+ protected :for_serialize
387
+
388
+ def from_serialized(hash)
389
+ disable_serialize if hash[:'@explicit'] # re-instate serialization disabling
390
+ #{base.name}.serializer_properties.each { |prop| prop.deserialize(self, hash) }
391
+ self
392
+ end
393
+ protected :from_serialized
394
+
395
+ def self.has_serializer_property?(id)
396
+ self.serializer_properties.any? { |p| p.id == id.to_sym }
397
+ end
398
+ __CODE
399
+ # add inheritance support
400
+ base.class_eval do
401
+ def self.inherited(derived)
402
+ # add instance property (de-)serialization methods for derived classes
403
+ derived.class_eval <<~__CODE
404
+ module SerializerMethods
405
+ def for_serialize(hash, excludes = ::Set.new)
406
+ hash = super(hash, excludes | #{derived.name}.excluded_serializer_properties)
407
+ #{derived.name}.serializer_properties.each { |prop| prop.serialize(self, hash, excludes) }
408
+ hash
409
+ end
410
+ protected :for_serialize
411
+
412
+ def from_serialized(hash)
413
+ #{derived.name}.serializer_properties.each { |prop| prop.deserialize(self, hash) }
414
+ super(hash)
415
+ end
416
+ protected :from_serialized
417
+ end
418
+ include SerializerMethods
419
+ __CODE
420
+ derived.class_eval do
421
+ def self.has_serializer_property?(id)
422
+ self.serializer_properties.any? { |p| p.id == id.to_sym } || self.superclass.has_serializer_property?(id)
423
+ end
424
+ end
425
+
426
+ # register as serializable class
427
+ Serializable.serializables << derived
428
+ end
429
+ end
430
+
431
+ # add instance serialization method
432
+ base.include(SerializeInstanceMethods)
433
+ end
434
+
435
+ end # module Serializable
436
+
437
+ end # module Wx::SF
438
+
439
+ Dir[File.join(__dir__, 'serializer', '*.rb')].each { |fnm| require "wx/shapes/serializer/#{File.basename(fnm)}" }
440
+ Dir[File.join(__dir__, 'serialize', '*.rb')].each { |fnm| require "wx/shapes/serialize/#{File.basename(fnm)}" }
@@ -0,0 +1,40 @@
1
+ # Wx::SF::Serializer - Ruby core serializer extensions
2
+ # Copyright (c) M.J.N. Corino, The Netherlands
3
+
4
+ # we do not include Wx::SF::Serializer::SerializeMethod here as that would
5
+ # also extend these classes with the engine specific extension that we do not
6
+ # need or want here
7
+
8
+ class Array
9
+ def serialize(io = nil, pretty: false, format: Wx::SF::Serializable.default_format)
10
+ Wx::SF::Serializable[format].dump(self, io, pretty: pretty)
11
+ end
12
+ end
13
+
14
+ class Hash
15
+ def serialize(io = nil, pretty: false, format: Wx::SF::Serializable.default_format)
16
+ Wx::SF::Serializable[format].dump(self, io, pretty: pretty)
17
+ end
18
+ end
19
+
20
+ class Struct
21
+ def serialize(io = nil, pretty: false, format: Wx::SF::Serializable.default_format)
22
+ Wx::SF::Serializable[format].dump(self, io, pretty: pretty)
23
+ end
24
+ end
25
+
26
+ require 'set'
27
+
28
+ class Set
29
+ def serialize(io = nil, pretty: false, format: Wx::SF::Serializable.default_format)
30
+ Wx::SF::Serializable[format].dump(self, io, pretty: pretty)
31
+ end
32
+ end
33
+
34
+ require 'ostruct'
35
+
36
+ class OpenStruct
37
+ def serialize(io = nil, pretty: false, format: Wx::SF::Serializable.default_format)
38
+ Wx::SF::Serializable[format].dump(self, io, pretty: pretty)
39
+ end
40
+ end
@@ -0,0 +1,82 @@
1
+ # Wx::SF::Serializer - Wx::SF serializable ID class
2
+ # Copyright (c) M.J.N. Corino, The Netherlands
3
+
4
+ module Wx::SF::Serializable
5
+
6
+ class ID
7
+
8
+ include Wx::SF::Serializable
9
+
10
+ class << self
11
+
12
+ TLS_RESTORATION_MAP_KEY = :wx_sf_serializable_id_restoration_map.freeze
13
+ private_constant :TLS_RESTORATION_MAP_KEY
14
+
15
+ def init_restoration_map
16
+ (::Thread.current[TLS_RESTORATION_MAP_KEY] ||= []) << {}
17
+ end
18
+
19
+ def clear_restoration_map
20
+ ::Thread.current[TLS_RESTORATION_MAP_KEY].pop
21
+ end
22
+
23
+ def restoration_map
24
+ ::Thread.current[TLS_RESTORATION_MAP_KEY].last
25
+ end
26
+
27
+ end
28
+
29
+ # Returns a Serialized::Id instance matching the deserialized id number
30
+ # either by retrieving an earlier restored Id from the (thread/fiber-)current
31
+ # restoration map or creating (and mapping) a new Id instance.
32
+ # @param [Hash] data deserialized properties hash
33
+ # @return [ID] restored ID instance
34
+ # @see SerializeClassMethods#create_for_deserialize
35
+ def self.create_for_deserialize(data)
36
+ serialized_id = data[:id] || 0
37
+ restoration_map[serialized_id] ||= self.new
38
+ end
39
+
40
+ # Collects the ID's object_id for serialization.
41
+ # Note that this is fixed and cannot be excluded.
42
+ # @param [Hash] hash property serialization hash
43
+ # @param [Set] _excludes ignored
44
+ # @return [Hash] property serialization hash
45
+ def for_serialize(hash, _excludes=nil)
46
+ hash[:id] = self.object_id
47
+ hash
48
+ end
49
+ protected :for_serialize
50
+
51
+ # Noop for ID instances.
52
+ # @param [Hash] _hash ignored
53
+ # @return [self]
54
+ def from_serialized(_hash)
55
+ # no deserializing necessary
56
+ self
57
+ end
58
+ protected :from_serialized
59
+
60
+ # Always returns false for IDs.
61
+ # @return [Boolean]
62
+ def serialize_disabled?
63
+ false
64
+ end
65
+
66
+ def to_s
67
+ "Wx::SF::Serializable::ID<#{object_id}>"
68
+ end
69
+
70
+ def inspect
71
+ to_s
72
+ end
73
+
74
+ def to_i
75
+ object_id
76
+ end
77
+
78
+ end
79
+
80
+ serializables << ID
81
+
82
+ end
@@ -0,0 +1,104 @@
1
+ # Wx::SF::Serializer - Wx class serializer extensions
2
+ # Copyright (c) M.J.N. Corino, The Netherlands
3
+
4
+ class Wx::Point
5
+
6
+ include Wx::SF::Serializable
7
+
8
+ properties :x, :y
9
+
10
+ end
11
+
12
+ class Wx::RealPoint
13
+
14
+ include Wx::SF::Serializable
15
+
16
+ properties :x, :y
17
+
18
+ end
19
+
20
+ class Wx::Size
21
+
22
+ include Wx::SF::Serializable
23
+
24
+ properties :width, :height
25
+
26
+ end
27
+
28
+ class Wx::Rect
29
+
30
+ include Wx::SF::Serializable
31
+
32
+ properties :x, :y, :width, :height
33
+
34
+ end
35
+
36
+ class Wx::Enum
37
+
38
+ include Wx::SF::Serializable
39
+
40
+ property :value => ->(enum) { enum.to_i }
41
+
42
+ def self.create_for_deserialize(data)
43
+ self.new(data[:value] || 0)
44
+ end
45
+
46
+ end
47
+
48
+ class Wx::Colour
49
+
50
+ include Wx::SF::Serializable
51
+
52
+ property :colour => ->(col, *val) { col.set(*val.first) unless val.empty?; [col.red, col.green, col.blue, col.alpha] }
53
+
54
+ end
55
+
56
+ # need to add this Enum explicitly as it was initially defined before we extended the Wx::Enum class above
57
+ class Wx::BrushStyle
58
+
59
+ property :value => ->(enum) { enum.to_i }
60
+
61
+ include Wx::SF::Serializable
62
+
63
+ end
64
+
65
+ class Wx::Brush
66
+
67
+ include Wx::SF::Serializable
68
+
69
+ property :colour, :style
70
+
71
+ end
72
+
73
+ # need to add this Enum explicitly as it was initially defined before we extended the Wx::Enum class above
74
+ class Wx::PenStyle
75
+
76
+ property :value => ->(enum) { enum.to_i }
77
+
78
+ include Wx::SF::Serializable
79
+
80
+ end
81
+
82
+ class Wx::Pen
83
+
84
+ include Wx::SF::Serializable
85
+
86
+ property :colour, :width, :style
87
+
88
+ end
89
+
90
+ class Wx::Font
91
+
92
+ include Wx::SF::Serializable
93
+
94
+ property font_info: ->(font, *info) { font.set_native_font_info_user_desc(info.shift) unless info.empty?; font.get_native_font_info_user_desc }
95
+
96
+ end
97
+
98
+ class Wx::BitmapType
99
+
100
+ property :value => ->(enum) { enum.to_i }
101
+
102
+ include Wx::SF::Serializable
103
+
104
+ end