glimmer-dsl-swt 4.20.13.12 → 4.20.13.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/README.md +5 -10
  4. data/VERSION +1 -1
  5. data/docs/reference/GLIMMER_SAMPLES.md +84 -2
  6. data/glimmer-dsl-swt.gemspec +0 -0
  7. data/lib/glimmer-dsl-swt.rb +1 -0
  8. data/lib/glimmer/swt/custom/drawable.rb +1 -0
  9. data/lib/glimmer/swt/custom/shape.rb +19 -0
  10. data/lib/glimmer/swt/custom/shape/arc.rb +2 -0
  11. data/lib/glimmer/swt/custom/shape/cubic.rb +1 -0
  12. data/lib/glimmer/swt/custom/shape/line.rb +1 -0
  13. data/lib/glimmer/swt/custom/shape/oval.rb +2 -0
  14. data/lib/glimmer/swt/custom/shape/path.rb +1 -5
  15. data/lib/glimmer/swt/custom/shape/point.rb +1 -0
  16. data/lib/glimmer/swt/custom/shape/polygon.rb +2 -0
  17. data/lib/glimmer/swt/custom/shape/polyline.rb +1 -0
  18. data/lib/glimmer/swt/custom/shape/rectangle.rb +1 -0
  19. data/lib/glimmer/swt/display_proxy.rb +8 -6
  20. data/lib/glimmer/ui/custom_shell.rb +1 -1
  21. data/lib/glimmer/ui/custom_widget.rb +3 -3
  22. data/samples/elaborate/battleship.rb +79 -0
  23. data/samples/elaborate/battleship/model/cell.rb +84 -0
  24. data/samples/elaborate/battleship/model/game.rb +143 -0
  25. data/samples/elaborate/battleship/model/grid.rb +54 -0
  26. data/samples/elaborate/battleship/model/ship.rb +114 -0
  27. data/samples/elaborate/battleship/model/ship_collection.rb +56 -0
  28. data/samples/elaborate/battleship/view/action_panel.rb +59 -0
  29. data/samples/elaborate/battleship/view/cell.rb +163 -0
  30. data/samples/elaborate/battleship/view/grid.rb +77 -0
  31. data/samples/elaborate/battleship/view/ship.rb +65 -0
  32. data/samples/elaborate/battleship/view/ship_collection.rb +49 -0
  33. data/samples/elaborate/connect4.rb +116 -0
  34. data/samples/elaborate/connect4/model/grid.rb +174 -0
  35. data/samples/elaborate/connect4/model/slot.rb +36 -0
  36. data/samples/elaborate/klondike_solitaire.rb +1 -1
  37. data/samples/elaborate/klondike_solitaire/view/column_pile.rb +0 -1
  38. data/samples/elaborate/klondike_solitaire/view/foundation_pile.rb +0 -2
  39. data/samples/elaborate/parking.rb +146 -0
  40. data/samples/elaborate/parking/model/parking_floor.rb +41 -0
  41. data/samples/elaborate/parking/model/parking_presenter.rb +42 -0
  42. data/samples/elaborate/parking/model/parking_spot.rb +46 -0
  43. data/samples/hello/hello_custom_shell.rb +2 -0
  44. metadata +20 -2
@@ -0,0 +1,79 @@
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-dsl-swt'
23
+ require 'facets/string/titlecase'
24
+ require 'facets/string/underscore'
25
+
26
+ require_relative 'battleship/model/game'
27
+
28
+ require_relative 'battleship/view/grid'
29
+ require_relative 'battleship/view/ship_collection'
30
+ require_relative 'battleship/view/action_panel'
31
+
32
+ class Battleship
33
+ include Glimmer::UI::CustomShell
34
+
35
+ COLOR_WATER = rgb(156, 211, 219)
36
+ COLOR_SHIP = :dark_gray
37
+
38
+ before_body do
39
+ @game = Model::Game.new
40
+ end
41
+
42
+ after_body do
43
+ observe(@game, :over) do |game_over_value|
44
+ if game_over_value
45
+ game_over_message = if game_over_value == :you
46
+ "Game over!\nYou Won!"
47
+ else
48
+ "Game over!\nYou Lost!"
49
+ end
50
+
51
+ message_box {
52
+ text 'Game Over!'
53
+ message game_over_message
54
+ }.open
55
+ end
56
+ end
57
+ end
58
+
59
+ body {
60
+ shell(:no_resize) {
61
+ grid_layout(2, false) {
62
+ horizontal_spacing 15
63
+ vertical_spacing 15
64
+ }
65
+
66
+ text 'Glimmer Battleship'
67
+
68
+ @enemy_grid = grid(game: @game, player: :enemy)
69
+ @enemy_ship_collection = ship_collection(game: @game, player: :enemy)
70
+
71
+ @player_grid = grid(game: @game, player: :you)
72
+ @player_ship_collection = ship_collection(game: @game, player: :you)
73
+
74
+ action_panel(game: @game)
75
+ }
76
+ }
77
+ end
78
+
79
+ Battleship.launch
@@ -0,0 +1,84 @@
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
+ class Battleship
23
+ module Model
24
+ class Cell
25
+ attr_reader :grid, :row_index, :column_index
26
+ attr_accessor :hit, :ship, :ship_index
27
+ alias hit? hit
28
+
29
+ def initialize(grid, row_index, column_index)
30
+ @grid = grid
31
+ @row_index = row_index
32
+ @column_index = column_index
33
+ end
34
+
35
+ def reset!
36
+ self.hit = nil
37
+ self.ship = nil
38
+ self.ship_index = nil
39
+ end
40
+
41
+ # Places ship horizontally so that its top left cell is self,
42
+ # automatically figuring out the rest of the cells
43
+ def place_ship!(ship)
44
+ begin
45
+ old_ship_top_left_cell = ship.top_left_cell
46
+ old_ship_orientation = ship.orientation
47
+ ship.top_left_cell = self
48
+ if old_ship_top_left_cell
49
+ ship.cells(old_ship_orientation).each(&:reset!)
50
+ ship.length.times do |index|
51
+ if ship.orientation == :horizontal
52
+ old_cell = grid.cell_rows[old_ship_top_left_cell.row_index][old_ship_top_left_cell.column_index + index]
53
+ else
54
+ old_cell = grid.cell_rows[old_ship_top_left_cell.row_index + index][old_ship_top_left_cell.column_index]
55
+ end
56
+ old_cell.reset!
57
+ end
58
+ end
59
+ ship.length.times do |index|
60
+ if ship.orientation == :horizontal
61
+ cell = grid.cell_rows[row_index][column_index + index]
62
+ else
63
+ cell = grid.cell_rows[row_index + index][column_index]
64
+ end
65
+ cell.ship = ship
66
+ cell.ship_index = index
67
+ end
68
+ rescue => e
69
+ Glimmer::Config.logger.debug(e.full_message)
70
+ end
71
+ end
72
+
73
+ def hit=(value)
74
+ @hit = value
75
+ ship&.sunk = true if ship&.all_cells_hit?
76
+ grid.game.over = grid.game.opposite_player(grid.player) if grid.game.started? && grid.game.ship_collections[grid.player].ships.values.map(&:sunk).all?
77
+ end
78
+
79
+ def to_s
80
+ "#{(Grid::ROW_ALPHABETS[row_index])}#{(column_index + 1)}"
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,143 @@
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_relative 'grid'
23
+ require_relative 'ship'
24
+
25
+ class Battleship
26
+ module Model
27
+ class Game
28
+ BATTLESHIPS = {
29
+ aircraft_carrier: 5,
30
+ battleship: 4,
31
+ submarine: 3,
32
+ cruiser: 3,
33
+ destroyer: 2
34
+ }
35
+ PLAYERS = [:enemy, :you]
36
+
37
+ attr_reader :grids, :ship_collections
38
+ attr_accessor :started, :current_player, :over
39
+ alias started? started
40
+ alias over? over
41
+
42
+ def initialize
43
+ @grids = PLAYERS.reduce({}) { |hash, player| hash.merge(player => Grid.new(self, player)) }
44
+ @ship_collections = PLAYERS.reduce({}) { |hash, player| hash.merge(player => ShipCollection.new(self, player)) }
45
+ @started = false
46
+ @current_player = :enemy
47
+ @enemy_moves = []
48
+ end
49
+
50
+ def battle!
51
+ self.started = true
52
+ place_enemy_ships!
53
+ enemy_attack!
54
+ end
55
+
56
+ def reset!
57
+ self.started = false
58
+ self.over = false
59
+ self.current_player = :enemy
60
+ @grids.values.each(&:reset!)
61
+ @ship_collections.values.each(&:reset!)
62
+ @enemy_moves = []
63
+ end
64
+
65
+ def attack!(row_index, column_index)
66
+ return unless started?
67
+ cell = opposite_grid.cell_rows[row_index][column_index]
68
+ return unless cell.hit.nil?
69
+ cell.hit = !!cell.ship
70
+ switch_player!
71
+ enemy_attack! if current_player == :enemy
72
+ end
73
+
74
+ # Enemy attack artificial intelligence
75
+ def enemy_attack!
76
+ begin
77
+ cell = nil
78
+ if @enemy_moves.any? && @enemy_moves.last.hit? && !@enemy_moves.last.ship.sunk?
79
+ if @enemy_moves[-2].nil? || !@enemy_moves[-2].hit?
80
+ orientation = Ship::ORIENTATIONS[(rand * 2).to_i]
81
+ else
82
+ orientation = @enemy_moves.last.row_index == @enemy_moves[-2].row_index ? :horizontal : :vertical
83
+ end
84
+ offset = 1 * ((rand * 2).to_i == 1 ? 1 : -1)
85
+ if orientation == :horizontal
86
+ offset *= -1 if [-1, Grid::WIDTH].include?(@enemy_moves.last.column_index + offset)
87
+ cell = opposite_grid.cell_rows[@enemy_moves.last.row_index][@enemy_moves.last.column_index + offset]
88
+ else
89
+ offset *= -1 if [-1, Grid::HEIGHT].include?(@enemy_moves.last.row_index + offset)
90
+ cell = opposite_grid.cell_rows[@enemy_moves.last.row_index + offset][@enemy_moves.last.column_index]
91
+ end
92
+ cell = nil if cell.hit?
93
+ end
94
+ if cell.nil?
95
+ random_row_index = (rand * Grid::HEIGHT).to_i
96
+ random_column_index = (rand * Grid::WIDTH).to_i
97
+ cell = opposite_grid.cell_rows[random_row_index][random_column_index]
98
+ end
99
+ end until cell.hit.nil?
100
+ attack!(cell.row_index, cell.column_index)
101
+ @enemy_moves << cell
102
+ end
103
+
104
+ def opposite_grid
105
+ grids[opposite_player]
106
+ end
107
+
108
+ def opposite_player(player = nil)
109
+ player ||= current_player
110
+ PLAYERS[(PLAYERS.index(player) + 1) % PLAYERS.size]
111
+ end
112
+
113
+ def switch_player!
114
+ self.current_player = opposite_player
115
+ end
116
+
117
+ def over=(value)
118
+ @over = value
119
+ self.started = false
120
+ end
121
+
122
+ private
123
+
124
+ def place_enemy_ships!
125
+ ship_collection = @ship_collections[:enemy]
126
+ ship_collection.ships.values.each do |ship|
127
+ until ship.top_left_cell
128
+ random_row_index = (rand * Grid::HEIGHT).to_i
129
+ random_column_index = (rand * Grid::WIDTH).to_i
130
+ enemy_grid = @grids[:enemy]
131
+ top_left_cell = enemy_grid.cell_rows[random_row_index][random_column_index]
132
+ top_left_cell.place_ship!(ship)
133
+ begin
134
+ ship.toggle_orientation! if (rand * 2).to_i == 1
135
+ rescue => e
136
+ Glimmer::Config.logger.debug(e.full_message)
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,54 @@
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_relative 'cell'
23
+
24
+ class Battleship
25
+ module Model
26
+ class Grid
27
+ HEIGHT = 10
28
+ WIDTH = 10
29
+ ROW_ALPHABETS = %w[A B C D E F G H I J]
30
+
31
+ attr_reader :game, :player, :cell_rows
32
+
33
+ def initialize(game, player)
34
+ @game = game
35
+ @player = player
36
+ build
37
+ end
38
+
39
+ def reset!
40
+ @cell_rows.flatten.each(&:reset!)
41
+ end
42
+
43
+ private
44
+
45
+ def build
46
+ @cell_rows = HEIGHT.times.map do |row_index|
47
+ WIDTH.times.map do |column_index|
48
+ Cell.new(self, row_index, column_index)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,114 @@
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_relative 'cell'
23
+
24
+ class Battleship
25
+ module Model
26
+ class Ship
27
+ ORIENTATIONS = [:horizontal, :vertical]
28
+
29
+ attr_reader :ship_collection, :name, :length
30
+ attr_accessor :orientation, :top_left_cell, :sunk
31
+ alias sunk? sunk
32
+
33
+ def initialize(ship_collection, name, length)
34
+ @ship_collection = ship_collection
35
+ @name = name
36
+ @length = length
37
+ @orientation = :horizontal
38
+ end
39
+
40
+ def to_s
41
+ "#{name.titlecase} (#{length} cells)"
42
+ end
43
+
44
+ def top_left_cell=(a_cell)
45
+ if a_cell
46
+ raise "Top left cell #{a_cell} already occupied by ship #{a_cell.ship.name}" if a_cell.ship && a_cell.ship != self
47
+ raise "Top left cell #{a_cell} cannot fit ship #{name}" if a_cell.column_index + length > Grid::WIDTH
48
+ grid = ship_collection.game.grids[ship_collection.player]
49
+ 1.upto(length - 1).each do |index|
50
+ if orientation == :horizontal
51
+ other_cell = grid.cell_rows[a_cell.row_index][a_cell.column_index + index]
52
+ else
53
+ other_cell = grid.cell_rows[a_cell.row_index + index][a_cell.column_index]
54
+ end
55
+ raise "Cell #{other_cell} already occupied by ship #{other_cell.ship.name}" if other_cell.ship && other_cell.ship != self
56
+ end
57
+ end
58
+ @top_left_cell = a_cell
59
+ end
60
+
61
+ def orientation=(value)
62
+ if top_left_cell
63
+ if value == :horizontal
64
+ if top_left_cell.column_index + length > Grid::WIDTH
65
+ raise "Top left cell #{top_left_cell} cannot fit ship #{name}"
66
+ end
67
+ else
68
+ if top_left_cell.row_index + length > Grid::HEIGHT
69
+ raise "Top left cell #{top_left_cell} cannot fit ship #{name}"
70
+ end
71
+ end
72
+ if cells(value)[1..-1].map(&:ship).reject {|s| s == self}.any?
73
+ raise 'Orientation #{value} cells occupied by another ship'
74
+ end
75
+ if value != @orientation
76
+ cells.each(&:reset!)
77
+ @orientation = value
78
+ cells.each_with_index do |cell, index|
79
+ cell.ship = self
80
+ cell.ship_index = index
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ def cells(for_orientation = nil)
87
+ for_orientation ||= orientation
88
+ if top_left_cell
89
+ length.times.map do |index|
90
+ if for_orientation == :horizontal
91
+ top_left_cell.grid.cell_rows[top_left_cell.row_index][top_left_cell.column_index + index]
92
+ else
93
+ top_left_cell.grid.cell_rows[top_left_cell.row_index + index][top_left_cell.column_index]
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ def all_cells_hit?
100
+ cells&.map(&:hit)&.all? {|h| h == true}
101
+ end
102
+
103
+ def reset!
104
+ self.sunk = nil
105
+ self.top_left_cell = nil
106
+ self.orientation = :horizontal
107
+ end
108
+
109
+ def toggle_orientation!
110
+ self.orientation = ORIENTATIONS[(ORIENTATIONS.index(orientation) + 1) % ORIENTATIONS.length]
111
+ end
112
+ end
113
+ end
114
+ end