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,258 @@
1
+ # Wx::SF::Serializer - shape serializer module
2
+ # Copyright (c) M.J.N. Corino, The Netherlands
3
+
4
+ require 'json'
5
+ require 'json/add/core'
6
+ require 'json/add/set'
7
+ require 'json/add/ostruct'
8
+
9
+ module Wx::SF
10
+
11
+ module Serializable
12
+
13
+ module JSON
14
+
15
+ # Derived Hash class to use for deserialized JSON object data which
16
+ # supports using Symbol keys.
17
+ class ObjectHash < ::Hash
18
+ # Returns the object associated with given key.
19
+ # @param [String,Symbol] key key value
20
+ # @return [Object] associated object
21
+ # @see ::Hash#[]
22
+ def [](key)
23
+ super(key.to_s)
24
+ end
25
+ # Returns true if the given key exists in self otherwise false.
26
+ # @param [String,Symbol] key key value
27
+ # @return [Boolean]
28
+ # @see ::Hash#include?
29
+ def include?(key)
30
+ super(key.to_s)
31
+ end
32
+ alias member? include?
33
+ alias has_key? include?
34
+ alias key? include?
35
+ end
36
+
37
+ # Mixin module to patch hash objects during JSON serialization.
38
+ # By default JSON will not consider hash keys for custom serialization
39
+ # but assumes any key should be serialized as it's string representation.
40
+ # This is restrictive but compatible with "pure" JSON object notation.
41
+ # JSON however also does not (correctly?) honour overriding Hash#to_json to
42
+ # customize serialization of Hash-es which seems too restrictive (stupid?)
43
+ # as using more complex custom keys for Hash-es instead of String/Symbol-s
44
+ # is not that uncommon.
45
+ # This mixin is used to "patch" Hash **instances** through #extend.
46
+ module HashInstancePatch
47
+ def patch_nested_hashes(obj)
48
+ case obj
49
+ when ::Hash
50
+ obj.extend(HashInstancePatch) unless obj.singleton_class.include?(HashInstancePatch)
51
+ obj.each_pair { |k, v| patch_nested_hashes(k); patch_nested_hashes(v) }
52
+ when ::Array
53
+ obj.each { |e| patch_nested_hashes(e) }
54
+ end
55
+ obj
56
+ end
57
+ private :patch_nested_hashes
58
+
59
+ # Returns JSON representation (String) of self.
60
+ # Hash data which is part of object properties/members being serialized
61
+ # (including any nested Hash-es) will be patched with HashInstancePatch.
62
+ # Patched Hash instances will be serialized as JSON-creatable objects
63
+ # (so provided with a JSON#create_id) with the hash contents represented
64
+ # as an array of key/value pairs (arrays).
65
+ # @param [Array<Object>] args any args passed by the JSON generator
66
+ # @return [String] JSON representation
67
+ def to_json(*args)
68
+ if self.has_key?(::JSON.create_id)
69
+ if self.has_key?('data')
70
+ if (data = self['data']).is_a?(::Hash)
71
+ data.each_value { |v| patch_nested_hashes(v) }
72
+ end
73
+ else # core class extensions use different data members for property serialization
74
+ self.each_value { |v| patch_nested_hashes(v) }
75
+ end
76
+ super
77
+ else
78
+ {
79
+ ::JSON.create_id => self.class.name,
80
+ 'data' => patch_nested_hashes(to_a)
81
+ }.to_json(*args)
82
+ end
83
+ end
84
+ end
85
+
86
+ # Mixin module to patch singleton_clas of the Hash class to make Hash-es
87
+ # JSON creatable (#json_creatable? returns true).
88
+ module HashClassPatch
89
+ # Create a new Hash instance from deserialized JSON data.
90
+ # @param [Hash] object deserialized JSON object
91
+ # @return [Hash] restored Hash instance
92
+ def json_create(object)
93
+ object['data'].to_h
94
+ end
95
+ end
96
+
97
+ class ::Hash
98
+ include Wx::SF::Serializable::JSON::HashInstancePatch
99
+ class << self
100
+ include Wx::SF::Serializable::JSON::HashClassPatch
101
+ end
102
+ end
103
+
104
+ class << self
105
+ def serializables
106
+ ::Set.new [::NilClass, ::TrueClass, ::FalseClass, ::Integer, ::Float, ::String, ::Array, ::Hash,
107
+ ::Date, ::DateTime, ::Exception, ::Range, ::Regexp, ::Struct, ::Symbol, ::Time, ::Set, ::OpenStruct]
108
+ end
109
+
110
+ TLS_SAFE_DESERIALIZE_KEY = :wx_sf_json_safe_deserialize.freeze
111
+ private_constant :TLS_SAFE_DESERIALIZE_KEY
112
+
113
+ TLS_PARSE_STACK_KEY = :wx_sf_json_parse_stack.freeze
114
+ private_constant :TLS_PARSE_STACK_KEY
115
+
116
+ def safe_deserialize
117
+ ::Thread.current[TLS_SAFE_DESERIALIZE_KEY] ||= []
118
+ end
119
+ private :safe_deserialize
120
+
121
+ def start_safe_deserialize
122
+ safe_deserialize.push(true)
123
+ end
124
+
125
+ def end_safe_deserialize
126
+ safe_deserialize.pop
127
+ end
128
+
129
+ def parse_stack
130
+ ::Thread.current[TLS_PARSE_STACK_KEY] ||= []
131
+ end
132
+ private :parse_stack
133
+
134
+ def start_parse
135
+ parse_stack.push(safe_deserialize.pop)
136
+ end
137
+
138
+ def end_parse
139
+ unless (val = parse_stack.pop).nil?
140
+ safe_deserialize.push(val)
141
+ end
142
+ end
143
+
144
+ def safe_parsing?
145
+ !!parse_stack.last
146
+ end
147
+ end
148
+
149
+ def self.dump(obj, io=nil, pretty: false)
150
+ obj.extend(HashInstancePatch) if obj.is_a?(::Hash)
151
+ if pretty
152
+ if io || io.respond_to?(:write)
153
+ io.write(::JSON.pretty_generate(obj))
154
+ io
155
+ else
156
+ ::JSON.pretty_generate(obj)
157
+ end
158
+ else
159
+ ::JSON.dump(obj, io)
160
+ end
161
+ end
162
+
163
+ def self.load(source)
164
+ begin
165
+ # initialize ID restoration map
166
+ Serializable::ID.init_restoration_map
167
+ # enable safe deserializing
168
+ self.start_safe_deserialize
169
+ ::JSON.parse!(source,
170
+ **{create_additions: true,
171
+ object_class: Serializable::JSON::ObjectHash})
172
+ ensure
173
+ # reset safe deserializing
174
+ self.end_safe_deserialize
175
+ # reset ID restoration map
176
+ Serializable::ID.clear_restoration_map
177
+ end
178
+ end
179
+
180
+ end
181
+
182
+ # extend serialization class methods
183
+ module SerializeClassMethods
184
+
185
+ def json_create(object)
186
+ create_for_deserialize(data = object['data'])
187
+ .__send__(:from_serialized, data)
188
+ end
189
+
190
+ end
191
+
192
+ # extend instance serialization methods
193
+ module SerializeInstanceMethods
194
+
195
+ def to_json(*args)
196
+ {
197
+ ::JSON.create_id => self.class.name,
198
+ 'data' => for_serialize(Hash.new)
199
+ }.to_json(*args)
200
+ end
201
+
202
+ end
203
+
204
+ class ID
205
+
206
+ def self.json_create(object)
207
+ create_for_deserialize(data = object['data'])
208
+ end
209
+
210
+ def to_json(*args)
211
+ {
212
+ ::JSON.create_id => self.class.name,
213
+ 'data' => for_serialize(Hash.new)
214
+ }.to_json(*args)
215
+ end
216
+
217
+ end
218
+
219
+ register(Serializable.default_format, JSON)
220
+
221
+ end
222
+
223
+ end
224
+
225
+ module ::JSON
226
+ class << self
227
+
228
+ alias :pre_wxsf_parse! :parse!
229
+ def parse!(*args, **kwargs)
230
+ begin
231
+ # setup parsing stack for safe or normal deserializing
232
+ # the double bracketing provided from Wx::SF::Serializable::JSON#load and here
233
+ # makes sure to support both nested Wx::SF deserializing as well as nested
234
+ # hybrid deserializing (Wx::SF -> common JSON -> ...)
235
+ Wx::SF::Serializable::JSON.start_parse
236
+ pre_wxsf_parse!(*args, **kwargs)
237
+ ensure
238
+ # reset parsing stack
239
+ Wx::SF::Serializable::JSON.end_parse
240
+ end
241
+ end
242
+
243
+ end
244
+ end
245
+
246
+ class ::Class
247
+
248
+ # override this to be able to do safe deserializing
249
+ def json_creatable?
250
+ if Wx::SF::Serializable::JSON.safe_parsing?
251
+ return false unless Wx::SF::Serializable::JSON.serializables.include?(self) ||
252
+ Wx::SF::Serializable.serializables.include?(self) ||
253
+ ::Struct > self
254
+ end
255
+ respond_to?(:json_create)
256
+ end
257
+
258
+ end
@@ -0,0 +1,125 @@
1
+ # Wx::SF::Serializer - shape serializer module
2
+ # Copyright (c) M.J.N. Corino, The Netherlands
3
+
4
+ require 'yaml'
5
+ require 'set'
6
+ require 'ostruct'
7
+
8
+ module Wx::SF
9
+
10
+ module Serializable
11
+
12
+ module YAML
13
+
14
+ class << self
15
+ def serializables
16
+ [Date, DateTime, Exception, Range, Regexp, Struct, Symbol, Time, Set, OpenStruct]
17
+ end
18
+ end
19
+
20
+ module YamlSerializePatch
21
+
22
+ ALLOWED_ALIASES = [Serializable::ID, Wx::Pen, Wx::Colour, Wx::Brush, Wx::Enum, Wx::Rect, Wx::Point, Wx::RealPoint, Wx::Size]
23
+
24
+ if ::RUBY_VERSION >= '3.1.0'
25
+ def revive(klass, node)
26
+ if Wx::SF::Serializable > klass
27
+ s = register(node, klass.create_for_deserialize(data = revive_hash({}, node, true)))
28
+ init_with(s, data, node)
29
+ else
30
+ super
31
+ end
32
+ end
33
+ else
34
+ def revive(klass, node)
35
+ if Wx::SF::Serializable > klass
36
+ s = register(node, klass.create_for_deserialize(data = revive_hash({}, node)))
37
+ init_with(s, data, node)
38
+ else
39
+ super
40
+ end
41
+ end
42
+ end
43
+ def visit_Psych_Nodes_Alias o
44
+ rc = @st.fetch(o.anchor) { raise ::YAML::AnchorNotDefined, o.anchor }
45
+ # only allow Serializable::ID aliases
46
+ raise ::YAML::AliasesNotEnabled unless ALLOWED_ALIASES.any? { |klass| klass === rc }
47
+ rc
48
+ end
49
+ end
50
+
51
+ class RestrictedRelaxed < ::YAML::ClassLoader
52
+ def initialize(classes)
53
+ @classes = classes
54
+ @allow_struct = @classes.include?('Struct')
55
+ super()
56
+ end
57
+
58
+ private
59
+
60
+ def find(klassname)
61
+ if @classes.include?(klassname)
62
+ super
63
+ elsif @allow_struct && ::Struct > super
64
+ @cache[klassname]
65
+ else
66
+ raise ::YAML::DisallowedClass.new('load', klassname)
67
+ end
68
+ end
69
+ end
70
+
71
+ def self.dump(obj, io=nil, pretty: false)
72
+ ::YAML.dump(obj, io)
73
+ end
74
+
75
+ def self.load(source)
76
+ result = ::YAML.parse(source, filename: nil)
77
+ return nil unless result
78
+ begin
79
+ # initialize ID restoration map
80
+ Serializable::ID.init_restoration_map
81
+ allowed_classes =(YAML.serializables + Serializable.serializables.to_a).map(&:to_s)
82
+ class_loader = RestrictedRelaxed.new(allowed_classes)
83
+ scanner = ::YAML::ScalarScanner.new(class_loader)
84
+ visitor = ::YAML::Visitors::NoAliasRuby.new(scanner, class_loader)
85
+ visitor.extend(YamlSerializePatch)
86
+ result = visitor.accept result
87
+ ensure
88
+ # reset ID restoration map
89
+ Serializable::ID.clear_restoration_map
90
+ end
91
+ result
92
+ end
93
+
94
+ end
95
+
96
+ # extend instance serialization methods
97
+ module SerializeInstanceMethods
98
+
99
+ def encode_with(coder)
100
+ for_serialize(coder)
101
+ end
102
+
103
+ def init_with(coder)
104
+ from_serialized(coder.map)
105
+ end
106
+
107
+ end
108
+
109
+ class ID
110
+
111
+ def encode_with(coder)
112
+ for_serialize(coder)
113
+ end
114
+
115
+ def init_with(_coder)
116
+ # noop
117
+ end
118
+
119
+ end
120
+
121
+ register(:yaml, YAML)
122
+
123
+ end
124
+
125
+ end