draw_color_repeat 1.0.0

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 (49) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +20 -0
  3. data/README.md +556 -0
  4. data/VERSION +1 -0
  5. data/app/dcr.rb +51 -0
  6. data/app/dcr/launch.rb +3 -0
  7. data/app/models/dcr/command.rb +129 -0
  8. data/app/models/dcr/command/backward.rb +45 -0
  9. data/app/models/dcr/command/color.rb +120 -0
  10. data/app/models/dcr/command/empty.rb +30 -0
  11. data/app/models/dcr/command/forward.rb +47 -0
  12. data/app/models/dcr/command/left.rb +37 -0
  13. data/app/models/dcr/command/repeat.rb +42 -0
  14. data/app/models/dcr/command/right.rb +36 -0
  15. data/app/models/dcr/polygon.rb +37 -0
  16. data/app/models/dcr/program.rb +130 -0
  17. data/app/views/dcr/app_view.rb +128 -0
  18. data/app/views/dcr/compass.rb +56 -0
  19. data/bin/dcr +13 -0
  20. data/config/warble.rb +183 -0
  21. data/dcr.gemspec +0 -0
  22. data/lib/icon.rb +53 -0
  23. data/package/linux/Draw Color Repeat.png +0 -0
  24. data/package/macosx/Draw Color Repeat.icns +0 -0
  25. data/package/windows/Draw Color Repeat.ico +0 -0
  26. data/samples/aztec_pyramid.dcr +15 -0
  27. data/samples/bee_hive.dcr +15 -0
  28. data/samples/circle.dcr +4 -0
  29. data/samples/circle_of_circles.dcr +7 -0
  30. data/samples/envelope.dcr +14 -0
  31. data/samples/equilateral_triangle.dcr +6 -0
  32. data/samples/five_pointed_star.dcr +4 -0
  33. data/samples/house.dcr +25 -0
  34. data/samples/octagon.dcr +4 -0
  35. data/samples/octagon_of_octagons.dcr +6 -0
  36. data/samples/octagon_of_squares.dcr +7 -0
  37. data/samples/playing_cards.dcr +9 -0
  38. data/samples/rectangle.dcr +6 -0
  39. data/samples/sherrif_badge_star.dcr +8 -0
  40. data/samples/spider_web.dcr +6 -0
  41. data/samples/square.dcr +4 -0
  42. data/samples/stairs.dcr +16 -0
  43. data/samples/stick_figure.dcr +21 -0
  44. data/samples/sun.dcr +9 -0
  45. data/samples/swirl.dcr +7 -0
  46. data/samples/traffic_light.dcr +29 -0
  47. data/samples/triangle.dcr +5 -0
  48. data/vendor/jars/org/yaml/snakeyaml/1.28/snakeyaml-1.28.jar +0 -0
  49. metadata +207 -0
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
data/app/dcr.rb ADDED
@@ -0,0 +1,51 @@
1
+ # Copyright (c) 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
+ $LOAD_PATH.unshift(File.expand_path('..', __FILE__))
23
+
24
+ begin
25
+ require 'bundler/setup'
26
+ Bundler.require(:default)
27
+ rescue
28
+ # gem mode requires manually
29
+ require 'glimmer-dsl-swt'
30
+ require 'glimmer-cp-stickfigure'
31
+ require 'strategic'
32
+ require 'equalizer'
33
+ end
34
+
35
+ require 'puts_debuggerer'
36
+ require 'views/dcr/app_view'
37
+
38
+ class Dcr
39
+ include Glimmer
40
+
41
+ APP_ROOT = File.expand_path('../..', __FILE__)
42
+ VERSION = File.read(File.join(APP_ROOT, 'VERSION'))
43
+ LICENSE = File.read(File.join(APP_ROOT, 'LICENSE.txt'))
44
+
45
+ def open
46
+ app_view.open
47
+ end
48
+ end
49
+
50
+ org.eclipse.swt.widgets.Display.app_name = 'Draw Color Repeat'
51
+ org.eclipse.swt.widgets.Display.app_version = Dcr::VERSION
data/app/dcr/launch.rb ADDED
@@ -0,0 +1,3 @@
1
+ require_relative '../dcr'
2
+
3
+ Dcr.new.open
@@ -0,0 +1,129 @@
1
+ # Copyright (c) 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
+ class Dcr
23
+ # Follows the Command, Strategy, and Chain of Responsibility Design Patterns
24
+ class Command
25
+ include Strategic
26
+ include Glimmer
27
+
28
+ class << self
29
+ def create(program: , text: )
30
+ operation = parse_operation(text)
31
+ operation_strategy = strategies.detect { |strategy| strategy.match?(operation) } unless operation.nil?
32
+ operation_strategy ||= Command::Empty
33
+ operation_strategy&.new(program: program, text: text)
34
+ end
35
+
36
+ def parse_operation(text)
37
+ text.to_s.strip.downcase.match(/([^ 0-9]+)/).to_a[1]
38
+ end
39
+
40
+ def parse_value(text)
41
+ text.to_s.strip.downcase.match(/[^ 0-9]+[ ]*([^ ]*)/).to_a[1]
42
+ end
43
+
44
+ def command_alias(alias_value)
45
+ command_aliases << alias_value
46
+ end
47
+
48
+ def command_aliases
49
+ @command_aliases ||= []
50
+ end
51
+
52
+ def command_exclusion(exclusion_value)
53
+ command_exclusions << exclusion_value
54
+ end
55
+
56
+ def command_exclusions
57
+ @command_exclusions ||= []
58
+ end
59
+
60
+ def match?(operation)
61
+ (operation_derivatives(command_operation) + command_aliases - command_exclusions).include?(operation.to_s.downcase)
62
+ end
63
+
64
+ def command_operation
65
+ name.split('::').last.downcase
66
+ end
67
+
68
+ def operation_derivatives(operation)
69
+ operation_length = operation.length
70
+ operation_length.times.map {|n| operation.chars.combination(operation_length - n).to_a}.reduce(:+).map(&:join)
71
+ end
72
+ end
73
+
74
+ attr_reader :text
75
+
76
+ def initialize(program: , text: )
77
+ @program = program
78
+ @text = text
79
+ end
80
+
81
+ def operation=(new_operation)
82
+ return if parse_operation(new_operation) == parsed_operation
83
+ @text.sub(parsed_operation, new_operation)
84
+ command_index_of_self = @program.commands.index(self)
85
+ @program.commands[command_index_of_self..command_index_of_self] = create(program: @program, text: @text)
86
+ end
87
+
88
+ def value=(new_value)
89
+ return if parse_value(new_value) == parsed_value
90
+ @text.sub(parsed_value, new_value)
91
+ @program.notify_observers('commands')
92
+ end
93
+
94
+ # Subclasses must override to provide parsed operation (e.g. 'f' becomes 'forward')
95
+ def operation
96
+ parsed_operation
97
+ end
98
+
99
+ def parsed_operation
100
+ Command.parse_operation(@text)
101
+ end
102
+
103
+ def operation_options
104
+ Command.strategy_names
105
+ end
106
+
107
+ # Subclasses must override to provide parsed value (e.g. 'r' becomes 'red' or '30' becomes 30)
108
+ def value
109
+ parsed_value
110
+ end
111
+
112
+ def parsed_value
113
+ parsed_value = Command.parse_value(@text)
114
+ parsed_value.to_s.match(/\d+/) ? parsed_value.to_i : parsed_value
115
+ end
116
+
117
+ def normalized_text
118
+ "#{operation} #{value}"
119
+ end
120
+
121
+ # Subclasses must implement
122
+ def call
123
+ # No Op
124
+ end
125
+ end
126
+ end
127
+
128
+ # Require all command strategies
129
+ Dir[File.expand_path(File.join('command', '**', '*.rb'), __dir__)].each {|f| require f}
@@ -0,0 +1,45 @@
1
+ # Copyright (c) 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
+ class Dcr
23
+ class Command
24
+ class Backward < Command
25
+ command_alias 'b'
26
+
27
+ def call
28
+ p1 = java.awt.geom.Point2D::Double.new(value, 0)
29
+ p2 = java.awt.geom.Point2D::Double.new(0, 0)
30
+ t = java.awt.geom.AffineTransform.new
31
+ t.set_to_rotation(@program.angle*(Math::PI/2.0)/90.0 - Math::PI/2.0)
32
+ t.transform(p1, p2)
33
+ new_x = @program.location_x - p2.x
34
+ new_y = @program.location_y - p2.y
35
+ @program.polygons.last.point_array += [new_x, new_y]
36
+ @program.location_x = new_x
37
+ @program.location_y = new_y
38
+ end
39
+
40
+ def value
41
+ super.to_f == 0 ? 1.0 : super.to_f
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,120 @@
1
+ # Copyright (c) 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
+ class Dcr
23
+ class Command
24
+ class Color < Command
25
+ # color map from strings to Glimmer DSL for SWT colors
26
+ COLOR_MAP = {
27
+ 'black' => :black,
28
+ 'blue' => :cyan,
29
+ 'gray' => :gray,
30
+ 'grey' => :gray,
31
+ 'green' => :green,
32
+ 'orange' => [255, 127, 0],
33
+ 'pink' => :magenta,
34
+ 'purple' => :dark_magenta,
35
+ 'red' => :red,
36
+ 'white' => :white,
37
+ 'yellow' => :yellow,
38
+ }
39
+ COLOR_MAP_ALIASES = {
40
+ 'grey' => :gray,
41
+ 'k' => :black,
42
+ 'b' => :cyan,
43
+ 'a' => :gray,
44
+ 'g' => :green,
45
+ 'o' => [255, 127, 0],
46
+ 'i' => :magenta,
47
+ 'p' => :dark_magenta,
48
+ 'r' => :red,
49
+ 'w' => :white,
50
+ 'y' => :yellow,
51
+ }
52
+ command_alias 'c'
53
+ command_exclusion 'r'
54
+
55
+ class << self
56
+ attr_reader :next_color_index
57
+
58
+ def expanded_color_map
59
+ @expanded_color_map ||= COLOR_MAP.reduce({}) do |hash, pair|
60
+ color_string = pair.first
61
+ color_value = pair.last
62
+ color_hash = color_derivatives(color_string).reduce({}) do |color_derivative_hash, color_derivative|
63
+ color_derivative_hash.merge(color_derivative => color_value)
64
+ end
65
+ hash.merge(color_hash)
66
+ end.merge(COLOR_MAP_ALIASES)
67
+ end
68
+
69
+ def color_derivatives(color_string)
70
+ color_string_length = color_string.length
71
+ color_string_length.times.map {|n| color_string.chars.combination(color_string_length - n).to_a}.reduce(:+).map(&:join)
72
+ end
73
+
74
+ def next_color_string
75
+ reset_next_color_index! if @next_color_index.nil?
76
+ @next_color_index += 1
77
+ COLOR_MAP.keys[@next_color_index % COLOR_MAP.count]
78
+ end
79
+
80
+ def next_color
81
+ COLOR_MAP[next_color_string]
82
+ end
83
+
84
+ def reset_next_color_index!(next_color_index_value=nil)
85
+ @next_color_index = next_color_index_value || -2 # start at yellow (since it skips one with the first addition)
86
+ end
87
+
88
+ def normalize_color_string(color_string)
89
+ color_value = Color.expanded_color_map[color_string]
90
+ COLOR_MAP.invert[color_value]
91
+ end
92
+ end
93
+
94
+ def call
95
+ @program.polygons.last&.background = interpreted_value
96
+ @program.new_polygon!
97
+ end
98
+
99
+ def value
100
+ value_string = super.to_s
101
+ if @value_string != value_string || @value_string.empty?
102
+ @value_string = value_string
103
+ # TODO beware of the edge case where if the last value string is empty, the comparable, which includes value, ends up returning a match with yellow (first color in series) thus not updating GUI
104
+ @value = Color.expanded_color_map.keys.include?(value_string) ? Color.normalize_color_string(value_string) : next_color_string
105
+ end
106
+ @value
107
+ end
108
+
109
+ # interpreted value is used by GUI
110
+ def interpreted_value
111
+ the_value = value
112
+ COLOR_MAP[the_value]
113
+ end
114
+
115
+ def next_color_string
116
+ Color.next_color_string
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,30 @@
1
+ # Copyright (c) 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
+ class Dcr
23
+ class Command
24
+ # This command represents an empty line,
25
+ # which separates repeatable groups of commands
26
+ class Empty < Command
27
+ command_alias ''
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,47 @@
1
+ # Copyright (c) 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_relative '../polygon'
23
+
24
+ class Dcr
25
+ class Command
26
+ class Forward < Command
27
+ command_alias 'f'
28
+
29
+ def call
30
+ p1 = java.awt.geom.Point2D::Double.new(value, 0)
31
+ p2 = java.awt.geom.Point2D::Double.new(0, 0)
32
+ t = java.awt.geom.AffineTransform.new
33
+ t.set_to_rotation(@program.angle*(Math::PI/2.0)/90.0 - Math::PI/2.0)
34
+ t.transform(p1, p2)
35
+ new_x = @program.location_x + p2.x
36
+ new_y = @program.location_y + p2.y
37
+ @program.polygons.last.point_array += [new_x, new_y]
38
+ @program.location_x = new_x
39
+ @program.location_y = new_y
40
+ end
41
+
42
+ def value
43
+ super.to_f == 0 ? 1.0 : super.to_f
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,37 @@
1
+ # Copyright (c) 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
+ class Dcr
23
+ class Command
24
+ class Left < Command
25
+ command_alias 'l'
26
+ command_exclusion 'f'
27
+
28
+ def call
29
+ @program.angle -= value
30
+ end
31
+
32
+ def value
33
+ super.to_f == 0 ? 90.0 : super.to_f
34
+ end
35
+ end
36
+ end
37
+ end