glimmer-dsl-swt 4.18.5.2 → 4.18.6.1

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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +38 -0
  3. data/README.md +8 -10
  4. data/VERSION +1 -1
  5. data/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md +93 -16
  6. data/docs/reference/GLIMMER_SAMPLES.md +32 -0
  7. data/glimmer-dsl-swt.gemspec +9 -3
  8. data/lib/glimmer/swt/custom/drawable.rb +8 -7
  9. data/lib/glimmer/swt/custom/shape.rb +416 -37
  10. data/lib/glimmer/swt/custom/shape/arc.rb +22 -4
  11. data/lib/glimmer/swt/custom/shape/cubic.rb +117 -0
  12. data/lib/glimmer/swt/custom/shape/image.rb +19 -6
  13. data/lib/glimmer/swt/custom/shape/line.rb +119 -1
  14. data/lib/glimmer/swt/custom/shape/oval.rb +3 -3
  15. data/lib/glimmer/swt/custom/shape/path.rb +211 -0
  16. data/lib/glimmer/swt/custom/shape/path_segment.rb +111 -0
  17. data/lib/glimmer/swt/custom/shape/point.rb +40 -4
  18. data/lib/glimmer/swt/custom/shape/polygon.rb +93 -3
  19. data/lib/glimmer/swt/custom/shape/polyline.rb +76 -4
  20. data/lib/glimmer/swt/custom/shape/quad.rb +113 -0
  21. data/lib/glimmer/swt/custom/shape/rectangle.rb +7 -2
  22. data/lib/glimmer/swt/custom/shape/text.rb +2 -4
  23. data/lib/glimmer/swt/dialog_proxy.rb +4 -0
  24. data/lib/glimmer/swt/proxy_properties.rb +1 -1
  25. data/lib/glimmer/swt/widget_proxy.rb +16 -0
  26. data/samples/elaborate/contact_manager.rb +2 -0
  27. data/samples/elaborate/login.rb +2 -0
  28. data/samples/elaborate/mandelbrot_fractal.rb +2 -1
  29. data/samples/elaborate/meta_sample.rb +1 -0
  30. data/samples/elaborate/stock_ticker.rb +229 -0
  31. data/samples/elaborate/tetris.rb +2 -1
  32. data/samples/elaborate/tic_tac_toe.rb +2 -0
  33. data/samples/elaborate/user_profile.rb +10 -8
  34. data/samples/hello/hello_browser.rb +2 -0
  35. data/samples/hello/hello_button.rb +2 -0
  36. data/samples/hello/hello_canvas.rb +40 -21
  37. data/samples/hello/hello_canvas_animation.rb +2 -0
  38. data/samples/hello/hello_canvas_path.rb +66 -0
  39. data/samples/hello/hello_canvas_transform.rb +2 -0
  40. data/samples/hello/hello_checkbox.rb +2 -0
  41. data/samples/hello/hello_checkbox_group.rb +2 -0
  42. data/samples/hello/hello_code_text.rb +2 -0
  43. data/samples/hello/hello_color_dialog.rb +2 -0
  44. data/samples/hello/hello_combo.rb +2 -0
  45. data/samples/hello/hello_computed.rb +2 -0
  46. data/samples/hello/hello_cursor.rb +2 -0
  47. data/samples/hello/hello_custom_shell.rb +1 -0
  48. data/samples/hello/hello_custom_widget.rb +2 -0
  49. data/samples/hello/hello_date_time.rb +2 -0
  50. data/samples/hello/hello_dialog.rb +2 -0
  51. data/samples/hello/hello_directory_dialog.rb +2 -0
  52. data/samples/hello/hello_drag_and_drop.rb +5 -3
  53. data/samples/hello/hello_expand_bar.rb +2 -0
  54. data/samples/hello/hello_file_dialog.rb +2 -0
  55. data/samples/hello/hello_font_dialog.rb +2 -0
  56. data/samples/hello/hello_group.rb +2 -0
  57. data/samples/hello/hello_link.rb +2 -0
  58. data/samples/hello/hello_list_multi_selection.rb +2 -0
  59. data/samples/hello/hello_list_single_selection.rb +2 -0
  60. data/samples/hello/hello_menu_bar.rb +2 -0
  61. data/samples/hello/hello_message_box.rb +2 -0
  62. data/samples/hello/hello_pop_up_context_menu.rb +2 -0
  63. data/samples/hello/hello_progress_bar.rb +2 -0
  64. data/samples/hello/hello_radio.rb +2 -0
  65. data/samples/hello/hello_radio_group.rb +2 -0
  66. data/samples/hello/hello_sash_form.rb +2 -0
  67. data/samples/hello/hello_spinner.rb +2 -0
  68. data/samples/hello/hello_styled_text.rb +19 -17
  69. data/samples/hello/hello_tab.rb +2 -0
  70. data/samples/hello/hello_table.rb +2 -0
  71. data/samples/hello/hello_world.rb +2 -0
  72. metadata +8 -2
@@ -0,0 +1,111 @@
1
+ # Copyright (c) 2007-2021 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/swt/custom/shape'
23
+
24
+ module Glimmer
25
+ module SWT
26
+ module Custom
27
+ # Represents a path to be drawn on a control/widget/canvas/display
28
+ # That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
29
+ class Shape
30
+ # Represents path segments like point, line, quad, and cubic curves
31
+ # Shapes could mix in
32
+ module PathSegment
33
+ # Subclasses must override and implement to indicate method name to invoke on SWT Path object to add segment
34
+ def path_segment_method_name
35
+ nil
36
+ end
37
+ # Subclasses must override and implement to indicate args to pass when invoking SWT Path object method
38
+ def path_segment_args
39
+ []
40
+ end
41
+ # Subclasses must override to indicate expected complete count of args when previous point is NOT connected (e.g. 4 for line, 6 for quad, 8 for cubic)
42
+ def default_path_segment_arg_count
43
+ end
44
+ # Subclasses must override to indicate expected count of args when previous point IS connected (e.g. 2 for line, 4 for quad, 6 for cubic)
45
+ def default_connected_path_segment_arg_count
46
+ end
47
+ # Subclasses may override to provide name of method to invoke for geometry object obtained from the Java AWT library java.awt.geom.Path2D.Double (e.g. curveTo vs cubicTo)
48
+ def path_segment_geometry_method_name
49
+ path_segment_method_name
50
+ end
51
+ # Subclasses must override and implement to indicate args to pass when invoking SWT Path object method
52
+ def path_segment_geometry_args
53
+ path_segment_args
54
+ end
55
+ # Subclasses must override to indicate otherwise
56
+ def previous_point_connected?
57
+ true
58
+ end
59
+
60
+ def dispose
61
+ parent.post_dispose_content(self) if parent.is_a?(Path)
62
+ end
63
+
64
+ def first_path_segment?
65
+ parent.path_segments.first == self
66
+ end
67
+
68
+ def previous_path_segment
69
+ parent.path_segments[parent.path_segments.index(self) - 1] || self
70
+ end
71
+
72
+ def add_to_swt_path(swt_path)
73
+ if @swt_path != swt_path
74
+ @swt_path = swt_path
75
+ the_path_segment_args = path_segment_args.dup
76
+ if !is_a?(Point) && self.class != Path
77
+ if !previous_point_connected?
78
+ if the_path_segment_args.count == default_path_segment_arg_count
79
+ point = the_path_segment_args.shift, the_path_segment_args.shift
80
+ @swt_path.moveTo(*point)
81
+ elsif first_path_segment?
82
+ point = the_path_segment_args[0..1]
83
+ @swt_path.moveTo(*point)
84
+ end
85
+ end
86
+ end
87
+ @swt_path.send(path_segment_method_name, *the_path_segment_args)
88
+ end
89
+ end
90
+
91
+ def add_to_geometry(geometry)
92
+ the_path_segment_geometry_args = path_segment_geometry_args.dup
93
+ if !is_a?(Point) && self.class != Path
94
+ if !previous_point_connected?
95
+ if the_path_segment_geometry_args.count == default_path_segment_arg_count
96
+ point = the_path_segment_geometry_args.shift, the_path_segment_geometry_args.shift
97
+ @swt_path.moveTo(*point)
98
+ elsif first_path_segment?
99
+ point = the_path_segment_geometry_args[0..1]
100
+ @swt_path.moveTo(*point)
101
+ end
102
+ end
103
+ end
104
+ geometry.send(path_segment_geometry_method_name, *the_path_segment_geometry_args)
105
+ end
106
+
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -20,6 +20,7 @@
20
20
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
21
 
22
22
  require 'glimmer/swt/custom/shape'
23
+ require 'glimmer/swt/custom/shape/path_segment'
23
24
  require 'glimmer/swt/swt_proxy'
24
25
  require 'glimmer/swt/display_proxy'
25
26
  require 'glimmer/swt/color_proxy'
@@ -33,20 +34,55 @@ module Glimmer
33
34
  # That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
34
35
  class Shape
35
36
  class Point < Shape
37
+ include PathSegment
38
+
36
39
  def parameter_names
37
40
  [:x, :y]
38
41
  end
39
42
 
43
+ def width
44
+ 1
45
+ end
46
+
47
+ def height
48
+ 1
49
+ end
50
+
40
51
  def include?(x, y)
41
52
  # give it some fuzz (helps makes mouse clicking easier)
42
- x.to_i.between?(self.x.to_i - 2, self.x.to_i + 2) && y.to_i.between?(self.y.to_i - 2, self.y.to_i + 2)
53
+ x.to_i.between?(self.absolute_x.to_i - 2, self.absolute_x.to_i + 2) && y.to_i.between?(self.absolute_y.to_i - 2, self.absolute_y.to_i + 2)
43
54
  end
44
55
  alias contain? include?
45
56
 
46
- def move_by(x_delta, y_delta)
47
- self.x += x_delta
48
- self.y += y_delta
57
+ def path_segment_method_name
58
+ 'addRectangle'
59
+ end
60
+
61
+ def path_segment_args
62
+ @args + [1, 1]
63
+ end
64
+
65
+ def path_segment_geometry_method_name
66
+ 'moveTo'
49
67
  end
68
+
69
+ def path_segment_geometry_args
70
+ @args
71
+ end
72
+
73
+ def previous_point_connected?
74
+ false
75
+ end
76
+
77
+ def eql?(other)
78
+ x == (other && other.respond_to?(:x) && other.x) && y == (other && other.respond_to?(:y) && other.y)
79
+ end
80
+ alias == eql?
81
+
82
+ def hash
83
+ [x, y].hash
84
+ end
85
+
50
86
  end
51
87
  end
52
88
  end
@@ -37,6 +37,10 @@ module Glimmer
37
37
  [:point_array]
38
38
  end
39
39
 
40
+ def location_parameter_names
41
+ parameter_names
42
+ end
43
+
40
44
  def point_count
41
45
  point_array.count / 2
42
46
  end
@@ -58,14 +62,100 @@ module Glimmer
58
62
  x_array.zip(y_array)
59
63
  end
60
64
 
61
- def include?(x, y)
62
- shape_geometry = java.awt.Polygon.new(x_array.to_java(:int), y_array.to_java(:int), point_count)
63
- shape_geometry.contains(x, y)
65
+ def absolute_point_array
66
+ if parent.is_a?(Shape)
67
+ point_array.each_with_index.map do |coordinate, i|
68
+ if i.even?
69
+ parent.absolute_x + coordinate
70
+ else
71
+ parent.absolute_y + coordinate
72
+ end
73
+ end
74
+ else
75
+ point_array
76
+ end
77
+ end
78
+
79
+ def absolute_x_array
80
+ absolute_point_array.each_with_index.select {|pair| pair.last.even?}.map(&:first)
81
+ end
82
+
83
+ def absolute_y_array
84
+ absolute_point_array.each_with_index.select {|pair| pair.last.odd?}.map(&:first)
85
+ end
86
+
87
+ def absolute_point_xy_array
88
+ absolute_x_array.zip(absolute_y_array)
89
+ end
90
+
91
+ def bounds
92
+ the_point_array = point_array
93
+ if the_point_array != @bounds_point_array
94
+ @bounds_point_array = point_array
95
+ shape_bounds = geometry.getBounds2D
96
+ @bounds = org.eclipse.swt.graphics.Rectangle.new(shape_bounds.x, shape_bounds.y, shape_bounds.width, shape_bounds.height)
97
+ end
98
+ @bounds
99
+ end
100
+
101
+ def size
102
+ the_point_array = point_array
103
+ if the_point_array != @size_point_array
104
+ @size_point_array = point_array
105
+ shape_bounds = geometry.getBounds2D
106
+ @size = org.eclipse.swt.graphics.Point.new(shape_bounds.width, shape_bounds.height)
107
+ end
108
+ @size
109
+ end
110
+
111
+ def geometry
112
+ the_point_array = point_array
113
+ if the_point_array != @geometry_point_array
114
+ @geometry_point_array = point_array
115
+ @geometry = java.awt.Polygon.new(absolute_x_array.to_java(:int), absolute_y_array.to_java(:int), point_count)
116
+ end
117
+ @geometry
64
118
  end
65
119
 
120
+ # Logical x coordinate relative to parent
121
+ def x
122
+ x_value = bounds.x
123
+ x_value -= parent.absolute_x if parent.is_a?(Shape)
124
+ x_value
125
+ end
126
+
127
+ # Logical y coordinate relative to parent
128
+ def y
129
+ y_value = bounds.y
130
+ y_value -= parent.absolute_y if parent.is_a?(Shape)
131
+ y_value
132
+ end
133
+
134
+ def width
135
+ size.x
136
+ end
137
+
138
+ def height
139
+ size.y
140
+ end
141
+
142
+ def contain?(x, y)
143
+ geometry.contains(x, y)
144
+ end
145
+
146
+ def include?(x, y)
147
+ comparison_lines = absolute_point_xy_array.zip(absolute_point_xy_array.rotate(1))
148
+ comparison_lines.any? {|line| Line.include?(line.first.first, line.first.last, line.last.first, line.last.last, x, y)}
149
+ end
150
+
66
151
  def move_by(x_delta, y_delta)
67
152
  self.point_array = point_array.each_with_index.map {|coordinate, i| i.even? ? coordinate + x_delta : coordinate + y_delta}
68
153
  end
154
+
155
+ def irregular?
156
+ true
157
+ end
158
+
69
159
  end
70
160
  end
71
161
  end
@@ -37,10 +37,19 @@ module Glimmer
37
37
  [:point_array]
38
38
  end
39
39
 
40
+ def location_parameter_names
41
+ parameter_names
42
+ end
43
+
40
44
  def point_count
41
45
  point_array.count / 2
42
46
  end
43
47
 
48
+ def [](index)
49
+ index = 0 if index == point_count
50
+ org.eclipse.swt.graphics.Point.new(point_array[index * 2], point_array[index * 2 + 1])
51
+ end
52
+
44
53
  def x_array
45
54
  point_array.each_with_index.select {|pair| pair.last.even?}.map(&:first)
46
55
  end
@@ -53,20 +62,83 @@ module Glimmer
53
62
  x_array.zip(y_array)
54
63
  end
55
64
 
56
- def [](index)
57
- index = 0 if index == point_count
58
- org.eclipse.swt.graphics.Point.new(point_array[index * 2], point_array[index * 2 + 1])
65
+ def absolute_point_array
66
+ if parent.is_a?(Shape)
67
+ point_array.each_with_index.map do |coordinate, i|
68
+ if i.even?
69
+ parent.absolute_x + coordinate
70
+ else
71
+ parent.absolute_y + coordinate
72
+ end
73
+ end
74
+ else
75
+ point_array
76
+ end
77
+ end
78
+
79
+ def absolute_x_array
80
+ absolute_point_array.each_with_index.select {|pair| pair.last.even?}.map(&:first)
81
+ end
82
+
83
+ def absolute_y_array
84
+ absolute_point_array.each_with_index.select {|pair| pair.last.odd?}.map(&:first)
85
+ end
86
+
87
+ def absolute_point_xy_array
88
+ absolute_x_array.zip(absolute_y_array)
89
+ end
90
+
91
+ def bounds
92
+ shape_bounds = geometry.getBounds2D
93
+ org.eclipse.swt.graphics.Rectangle.new(shape_bounds.x, shape_bounds.y, shape_bounds.width, shape_bounds.height)
94
+ end
95
+
96
+ def size
97
+ shape_bounds = geometry.getBounds2D
98
+ org.eclipse.swt.graphics.Point.new(shape_bounds.width, shape_bounds.height)
99
+ end
100
+
101
+ def geometry
102
+ java.awt.Polygon.new(absolute_x_array.to_java(:int), absolute_y_array.to_java(:int), point_count)
103
+ end
104
+
105
+ # Logical x coordinate relative to parent
106
+ def x
107
+ x_value = bounds.x
108
+ x_value -= parent.absolute_x if parent.is_a?(Shape)
109
+ x_value
110
+ end
111
+
112
+ # Logical y coordinate relative to parent
113
+ def y
114
+ y_value = bounds.y
115
+ y_value -= parent.absolute_y if parent.is_a?(Shape)
116
+ y_value
117
+ end
118
+
119
+ def width
120
+ bounds.width
121
+ end
122
+
123
+ def height
124
+ bounds.height
59
125
  end
60
126
 
61
127
  def include?(x, y)
62
- comparison_lines = point_xy_array.zip(point_xy_array.rotate(1))
128
+ comparison_lines = absolute_point_xy_array.zip(absolute_point_xy_array.rotate(1))
63
129
  comparison_lines.pop # ignore last pair since you don't want to compare last point with first point
64
130
  comparison_lines.any? {|line| Line.include?(line.first.first, line.first.last, line.last.first, line.last.last, x, y)}
65
131
  end
132
+ alias contain? include?
66
133
 
67
134
  def move_by(x_delta, y_delta)
68
135
  self.point_array = point_array.each_with_index.map {|coordinate, i| i.even? ? coordinate + x_delta : coordinate + y_delta}
69
136
  end
137
+
138
+ def irregular?
139
+ true
140
+ end
141
+
70
142
  end
71
143
  end
72
144
  end
@@ -0,0 +1,113 @@
1
+ # Copyright (c) 2007-2021 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/swt/custom/shape'
23
+ require 'glimmer/swt/custom/shape/path_segment'
24
+ require 'glimmer/swt/swt_proxy'
25
+ require 'glimmer/swt/display_proxy'
26
+ require 'glimmer/swt/color_proxy'
27
+ require 'glimmer/swt/font_proxy'
28
+ require 'glimmer/swt/transform_proxy'
29
+
30
+ module Glimmer
31
+ module SWT
32
+ module Custom
33
+ # Represents a shape (graphics) to be drawn on a control/widget/canvas/display
34
+ # That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
35
+ class Shape
36
+ class Quad < Path
37
+ def parameter_names
38
+ [:point_array]
39
+ end
40
+
41
+ def geometry
42
+ the_point_array = point_array
43
+ if the_point_array != @geometry_point_array
44
+ @geometry_point_array = the_point_array
45
+ @geometry = Java::JavaAwtGeom::Path2D::Double.new
46
+ add_to_geometry(@geometry)
47
+ end
48
+ @geometry
49
+ end
50
+
51
+ def contain?(x, y)
52
+ include?(x, y, filled: true)
53
+ end
54
+
55
+ # checks if drawn or filled rectangle includes the point denoted by x and y (if drawn, it only returns true if point lies on the edge)
56
+ def include?(x, y, filled: nil)
57
+ filled = filled? if filled.nil?
58
+ makeshift_gc = org.eclipse.swt.graphics.GC.new(Glimmer::SWT::DisplayProxy.instance.swt_display)
59
+ swt_path = org.eclipse.swt.graphics.Path.new(Glimmer::SWT::DisplayProxy.instance.swt_display)
60
+ the_path_segment_args = path_segment_args.dup
61
+ if previous_point_connected?
62
+ the_previous_path_segment = previous_path_segment
63
+ swt_path.moveTo(the_previous_path_segment.x, the_previous_path_segment.y)
64
+ else
65
+ swt_path.moveTo(the_path_segment_args.shift, the_path_segment_args.shift)
66
+ end
67
+ swt_path.quadTo(*the_path_segment_args)
68
+ swt_path.contains(x.to_f, y.to_f, makeshift_gc, !filled)
69
+ ensure
70
+ swt_path.dispose
71
+ end
72
+
73
+ def move_by(x_delta, y_delta)
74
+ the_point_array = @args.compact
75
+ the_point_array = the_point_array.first if the_point_array.first.is_a?(Array)
76
+ self.point_array = the_point_array.each_with_index.map {|coordinate, i| i.even? ? coordinate + x_delta : coordinate + y_delta}
77
+ end
78
+
79
+ def path_segment_method_name
80
+ 'quadTo'
81
+ end
82
+
83
+ def path_segment_args
84
+ # TODO make args auto-infer control points if previous_point_connected is true or if there is only a point_array with 1 point
85
+ @args.to_a
86
+ end
87
+
88
+ def default_path_segment_arg_count
89
+ 6
90
+ end
91
+
92
+ def default_connected_path_segment_arg_count
93
+ 4
94
+ end
95
+
96
+ def previous_point_connected?
97
+ @args.compact.count == 4 && !first_path_segment?
98
+ end
99
+
100
+ def eql?(other)
101
+ point_array == (other && other.respond_to?(:point_array) && other.point_array)
102
+ end
103
+ alias == eql?
104
+
105
+ def hash
106
+ point_array.hash
107
+ end
108
+
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end