wxruby3-shapes 0.9.0.pre.beta.3

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