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,116 @@
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
+
24
+ require_relative 'connect4/model/grid'
25
+
26
+ class Connect4
27
+ include Glimmer::UI::CustomShell
28
+
29
+ COLOR_BACKGROUND = rgb(63, 104, 212)
30
+ COLOR_EMPTY_SLOT = :white
31
+ COLOR_COIN1 = rgb(236, 223, 56)
32
+ COLOR_COIN2 = rgb(176, 11, 23)
33
+
34
+ attr_accessor :current_player_color
35
+
36
+ before_body do
37
+ @grid = Model::Grid.new
38
+ select_player_color
39
+ end
40
+
41
+ after_body do
42
+ observe(@grid, :current_player) do
43
+ select_player_color
44
+ end
45
+
46
+ observe(@grid, :game_over) do |game_over_value|
47
+ if game_over_value
48
+ game_over_message = case game_over_value
49
+ when true
50
+ "Game over!\nDraw!"
51
+ when 1
52
+ "Game over!\nPlayer 1 (yellow) wins!"
53
+ when 2
54
+ "Game over!\nPlayer 2 (red) wins!"
55
+ end
56
+
57
+ message_box {
58
+ text 'Game Over!'
59
+ message game_over_message
60
+ }.open
61
+
62
+ @grid.restart!
63
+ end
64
+ end
65
+ end
66
+
67
+ body {
68
+ shell(:no_resize) {
69
+ grid_layout(Model::Grid::WIDTH, true)
70
+
71
+ text 'Glimmer Connect 4'
72
+ background COLOR_BACKGROUND
73
+
74
+ Model::Grid::HEIGHT.times do |row_index|
75
+ Model::Grid::WIDTH.times do |column_index|
76
+ canvas {
77
+ layout_data {
78
+ width_hint 50
79
+ height_hint 50
80
+ }
81
+
82
+ background :transparent
83
+
84
+ the_oval = oval(0, 0, 50, 50) {
85
+ background <= [@grid.slot_rows[row_index][column_index], :value, on_read: ->(v) { v == 0 ? COLOR_EMPTY_SLOT : (v == 1 ? COLOR_COIN1 : COLOR_COIN2)}]
86
+ }
87
+
88
+ if row_index == 0
89
+ entered = false
90
+ on_mouse_enter do
91
+ entered = true
92
+ the_oval.background = current_player_color if @grid.slot_rows[row_index][column_index].value == 0
93
+ end
94
+
95
+ on_mouse_exit do
96
+ entered = false
97
+ the_oval.background = COLOR_EMPTY_SLOT if @grid.slot_rows[row_index][column_index].value == 0
98
+ end
99
+
100
+ on_mouse_up do
101
+ @grid.insert!(column_index)
102
+ the_oval.background = current_player_color if entered && @grid.slot_rows[row_index][column_index].value == 0
103
+ end
104
+ end
105
+ }
106
+ end
107
+ end
108
+ }
109
+ }
110
+
111
+ def select_player_color
112
+ self.current_player_color = @grid.current_player == 1 ? COLOR_COIN1 : COLOR_COIN2
113
+ end
114
+ end
115
+
116
+ Connect4.launch
@@ -0,0 +1,174 @@
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 'slot'
23
+
24
+ class Connect4
25
+ module Model
26
+ class Grid
27
+ WIDTH = 7
28
+ HEIGHT = 6
29
+
30
+ attr_reader :slot_rows
31
+ attr_accessor :current_player, :game_over
32
+
33
+ def initialize
34
+ build_slots
35
+ start!
36
+ end
37
+
38
+ def start!
39
+ self.game_over = false
40
+ self.current_player = 1
41
+ reset_slots
42
+ end
43
+ alias restart! start!
44
+
45
+ def insert!(column_index)
46
+ found_row_index = bottom_most_free_row_index(column_index)
47
+ raise "Illegal move at #{column_index}" if found_row_index == -1
48
+ @slot_rows[found_row_index][column_index].value = @current_player
49
+ self.current_player = @current_player%2 + 1
50
+ evaluate_game_over
51
+ end
52
+
53
+ # returns bottom most free row index
54
+ # returns -1 if none
55
+ def bottom_most_free_row_index(column_index)
56
+ found_row_index = @slot_rows.size - 1
57
+ found_row_index -= 1 until found_row_index == -1 || @slot_rows[found_row_index][column_index].value == 0
58
+ found_row_index
59
+ end
60
+
61
+ private
62
+
63
+ def build_slots
64
+ @slot_rows = HEIGHT.times.map do |row_index|
65
+ WIDTH.times.map do |column_index|
66
+ Slot.new(self)
67
+ end
68
+ end
69
+ end
70
+
71
+ def reset_slots
72
+ @slot_rows.flatten.each {|s| s.value = 0}
73
+ end
74
+
75
+ def evaluate_game_over
76
+ evaluate_horizontal_win
77
+ evaluate_vertical_win
78
+ evaluate_sw_ne_diagonal_win
79
+ evaluate_se_nw_diagonal_win
80
+ self.game_over ||= true if @slot_rows.flatten.map(&:value).all? {|v| v > 0}
81
+ end
82
+
83
+ def evaluate_horizontal_win
84
+ connections = nil
85
+ last_slot_value = nil
86
+ HEIGHT.times do |row_index|
87
+ connections = nil
88
+ last_slot_value = nil
89
+ WIDTH.times do |column_index|
90
+ slot = @slot_rows[row_index][column_index]
91
+ if slot.value.to_i > 0 && slot.value == last_slot_value
92
+ connections += 1
93
+ else
94
+ last_slot_value = slot.value
95
+ connections = 1
96
+ end
97
+ break if connections == 4
98
+ end
99
+ break if connections == 4
100
+ end
101
+ self.game_over = last_slot_value if connections == 4
102
+ end
103
+
104
+ def evaluate_vertical_win
105
+ connections = nil
106
+ last_slot_value = nil
107
+ WIDTH.times do |column_index|
108
+ connections = nil
109
+ last_slot_value = nil
110
+ HEIGHT.times do |row_index|
111
+ slot = @slot_rows[row_index][column_index]
112
+ if slot.value.to_i > 0 && slot.value == last_slot_value
113
+ connections += 1
114
+ else
115
+ last_slot_value = slot.value
116
+ connections = 1
117
+ end
118
+ break if connections == 4
119
+ end
120
+ break if connections == 4
121
+ end
122
+ self.game_over = last_slot_value if connections == 4
123
+ end
124
+
125
+ def evaluate_sw_ne_diagonal_win
126
+ sw_ne_coordinates = [
127
+ [[3, 0], [2, 1], [1, 2], [0, 3]],
128
+ [[4, 0], [3, 1], [2, 2], [1, 3], [0, 4]],
129
+ [[5, 0], [4, 1], [3, 2], [2, 3], [1, 4], [0, 5]],
130
+ [[5, 1], [4, 2], [3, 3], [2, 4], [1, 5], [0, 6]],
131
+ [[5, 2], [4, 3], [3, 4], [2, 5], [1, 6]],
132
+ [[5, 3], [4, 4], [3, 5], [2, 6]],
133
+ ]
134
+ evaluate_diagonal_win(sw_ne_coordinates)
135
+ end
136
+
137
+ def evaluate_se_nw_diagonal_win
138
+ sw_ne_coordinates = [
139
+ [[0, 3], [1, 4], [2, 5], [3, 6]],
140
+ [[0, 2], [1, 3], [2, 4], [3, 5], [4, 6]],
141
+ [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6]],
142
+ [[0, 0], [1, 1], [2, 2], [3, 3], [4, 4], [5, 5]],
143
+ [[1, 0], [2, 1], [3, 2], [4, 3], [5, 4]],
144
+ [[2, 0], [3, 1], [4, 2], [5, 3]],
145
+ ]
146
+ evaluate_diagonal_win(sw_ne_coordinates)
147
+ end
148
+
149
+ def evaluate_diagonal_win(diagonal_coordinates)
150
+ connections = nil
151
+ last_slot_value = nil
152
+ diagonal_coordinates.each do |group|
153
+ connections = nil
154
+ last_slot_value = nil
155
+ group.each do |row_index, column_index|
156
+ slot = @slot_rows[row_index][column_index]
157
+ if slot.value.to_i > 0 && slot.value == last_slot_value
158
+ connections += 1
159
+ else
160
+ last_slot_value = slot.value
161
+ connections = 1
162
+ end
163
+ break if connections == 4
164
+ end
165
+ break if connections == 4
166
+ end
167
+ self.game_over = last_slot_value if connections == 4
168
+ end
169
+
170
+ end
171
+
172
+ end
173
+
174
+ end
@@ -0,0 +1,36 @@
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 Connect4
23
+ module Model
24
+ class Slot
25
+ attr_reader :grid
26
+
27
+ # value 0 means empty, 1 means player 1 coin, and 2 means player 2 coin
28
+ attr_accessor :value
29
+
30
+ def initialize(grid)
31
+ @value = 0
32
+ @grid = grid
33
+ end
34
+ end
35
+ end
36
+ end
@@ -29,7 +29,7 @@ class KlondikeSolitaire
29
29
  end
30
30
 
31
31
  body {
32
- shell(:no_resize) {
32
+ shell {
33
33
  row_layout(:vertical) {
34
34
  fill true
35
35
  center true
@@ -43,7 +43,6 @@ class KlondikeSolitaire
43
43
  end
44
44
  drop_event.dragged_shape.dispose
45
45
  rescue => e
46
- # pd e
47
46
  drop_event.doit = false
48
47
  end
49
48
  end
@@ -36,7 +36,6 @@ class KlondikeSolitaire
36
36
 
37
37
  on_drop do |drop_event|
38
38
  begin
39
- # TODO make sure one cannot drag a column pile of cards here
40
39
  card_shape = drop_event.dragged_shape.get_data('custom_shape')
41
40
  card = card_shape.model
42
41
  card_parent_pile = card_shape.parent_pile
@@ -46,7 +45,6 @@ class KlondikeSolitaire
46
45
  card_source_model.remove!(card)
47
46
  drop_event.dragged_shape.dispose
48
47
  rescue => e
49
- # pd e
50
48
  drop_event.doit = false
51
49
  end
52
50
  end
@@ -0,0 +1,146 @@
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
+
24
+ require_relative 'parking/model/parking_presenter'
25
+
26
+ class Parking
27
+ include Glimmer::UI::CustomShell
28
+
29
+ FLOOR_COUNT = 4
30
+
31
+ before_body do
32
+ @parking_spots = Model::ParkingSpot::LETTERS.clone
33
+ @parking_presenter = Model::ParkingPresenter.new(FLOOR_COUNT)
34
+ end
35
+
36
+ body {
37
+ shell(:no_resize) {
38
+ row_layout(:vertical) {
39
+ center true
40
+ }
41
+
42
+ text 'Parking'
43
+
44
+ label {
45
+ text 'Select an available spot to park'
46
+ font height: 30
47
+ }
48
+ label {
49
+ text 'Floor:'
50
+ font height: 20
51
+ }
52
+ spinner {
53
+ minimum 1
54
+ maximum FLOOR_COUNT
55
+ font height: 20
56
+ selection <=> [@parking_presenter, :selected_floor]
57
+
58
+ on_widget_selected do
59
+ @parking_spots = Model::ParkingSpot::LETTERS.clone
60
+ @canvas.dispose_shapes
61
+ @canvas.content {
62
+ parking_floor
63
+ }
64
+ end
65
+ }
66
+ @canvas = canvas {
67
+ layout_data {
68
+ width 600
69
+ height 600
70
+ }
71
+
72
+ background :dark_gray
73
+
74
+ parking_floor
75
+ }
76
+ }
77
+ }
78
+
79
+ def parking_floor
80
+ parking_quad(67.5, 0, 125)
81
+ parking_quad(67.5, 0, 125) { |shp|
82
+ shp.rotate(90)
83
+ }
84
+ parking_quad(67.5, 0, 125) { |shp|
85
+ shp.rotate(180)
86
+ }
87
+ parking_quad(67.5, 0, 125) { |shp|
88
+ shp.rotate(270)
89
+ }
90
+ end
91
+
92
+ def parking_quad(location_x, location_y, length, &block)
93
+ distance = (1.0/3)*length
94
+ parking_spot(location_x, location_y, length, &block)
95
+ parking_spot(location_x + distance, location_y, length, &block)
96
+ parking_spot(location_x + 2*distance, location_y, length, &block)
97
+ parking_spot(location_x + 3*distance, location_y, length, &block)
98
+ end
99
+
100
+ def parking_spot(location_x, location_y, length, &block)
101
+ parking_spot_letter = @parking_spots.shift
102
+ height = length
103
+ width = (2.0/3)*length
104
+ shape(location_x, location_y) { |the_shape|
105
+ line_width (1.0/15)*length
106
+ foreground :white
107
+
108
+ block&.call(the_shape)
109
+
110
+ rectangle(location_x, location_y, width, height) {
111
+ background <= [
112
+ @parking_presenter.floors[@parking_presenter.selected_floor - 1].parking_spots[parking_spot_letter],
113
+ :booked,
114
+ on_read: ->(b) {b ? :red : :dark_gray}
115
+ ]
116
+
117
+ text {
118
+ x :default
119
+ y :default
120
+ string parking_spot_letter
121
+ font height: 20
122
+ }
123
+
124
+ on_mouse_up do
125
+ begin
126
+ @parking_presenter.floors[@parking_presenter.selected_floor - 1].book!(parking_spot_letter)
127
+ message_box {
128
+ text 'Parking Booked!'
129
+ message "Floor #{@parking_presenter.selected_floor} Parking Spot #{parking_spot_letter} Is Booked!"
130
+ }.open
131
+ rescue => e
132
+ # No Op if already booked
133
+ end
134
+ end
135
+ }
136
+
137
+ line(location_x, location_y, location_x, location_y + height)
138
+ line(location_x, location_y, location_x + width, location_y)
139
+ line(location_x + width, location_y, location_x + width, location_y + height)
140
+
141
+ }
142
+ end
143
+ end
144
+
145
+ Parking.launch
146
+