glimmer-dsl-swt 4.18.2.2 → 4.18.2.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 86c6cb24dde4db7916e8af3e1c2e61c8146d1be0893ff9d59f3546867438032d
4
- data.tar.gz: 63a055522af49c34e2bf1fad56f2fa54fab9842129c99816561bc60081b3373a
3
+ metadata.gz: 813f7cef0d25c94aa62c0cd57d3445a3eb13acb229bdd59264f7d4a0268f1ed3
4
+ data.tar.gz: dccf84bac2d2ca037df0b4157335fd7451fc2701d90a79df18abc61971725df6
5
5
  SHA512:
6
- metadata.gz: 132c53c40c35a0e05a3f44953651b1418b453b6cf8d9bd8cd2f5d90bfa1ce1254b816f5bfb0c26fa7222e924818817dbf8260f4107f92c54816de2c42545e21d
7
- data.tar.gz: cd8c874d5549295a0466944a2a3257405f3f670417dce6cade8c80202a5016d3b86a1cf7393479694c9fd0e2ea080a9fd4e965c57d653ae62653140883d612fc
6
+ metadata.gz: 9702ce2c81c56ddf6c56e590c7f30509149d75fbd6ee8e01da4bb5e0405381fae39da688ec30ab0686ff987cdc4eee06992d7c4b365a32f8bc2d773ea23e3b05
7
+ data.tar.gz: 4d1a2dfa58fffa6dd037ef07463056ccc70d09261bb0720f238332c07284347993c94e96ef5d18bb9a7f1f75d71b72ed2fdfe72202320f8de489624ac9084edc
@@ -1,5 +1,10 @@
1
1
  # Change Log
2
2
 
3
+ ### 4.18.2.3
4
+
5
+ - Added Tetris Elaborate Sample
6
+ - Added support for CustomShell `::launch` and `::shutdown` class methods to treat a top-level custom shell as a self contained launchable app (saving you from writing boilerplate code for launching Glimmer applications)
7
+
3
8
  ### 4.18.2.2
4
9
 
5
10
  - Fixed issue with processing shape color due to missing Color class package name
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for SWT 4.18.2.2
1
+ # [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for SWT 4.18.2.3
2
2
  ## JRuby Desktop Development GUI Framework
3
3
  [![Gem Version](https://badge.fury.io/rb/glimmer-dsl-swt.svg)](http://badge.fury.io/rb/glimmer-dsl-swt)
4
4
  [![Travis CI](https://travis-ci.com/AndyObtiva/glimmer-dsl-swt.svg?branch=master)](https://travis-ci.com/github/AndyObtiva/glimmer-dsl-swt)
@@ -364,6 +364,7 @@ Glimmer App:
364
364
  - [Login](#login)
365
365
  - [Tic Tac Toe Sample](#tic-tac-toe-sample)
366
366
  - [Contact Manager Sample](#contact-manager-sample)
367
+ - [Tetris](#tetris)
367
368
  - [External Samples](#external-samples)
368
369
  - [Glimmer Calculator](#glimmer-calculator)
369
370
  - [Gladiator](#gladiator)
@@ -452,7 +453,7 @@ jgem install glimmer-dsl-swt
452
453
 
453
454
  Or this command if you want a specific version:
454
455
  ```
455
- jgem install glimmer-dsl-swt -v 4.18.2.2
456
+ jgem install glimmer-dsl-swt -v 4.18.2.3
456
457
 
457
458
 
458
459
  ```
@@ -472,7 +473,7 @@ Note: if you're using activerecord or activesupport, keep in mind that Glimmer u
472
473
 
473
474
  Add the following to `Gemfile`:
474
475
  ```
475
- gem 'glimmer-dsl-swt', '~> 4.18.2.2
476
+ gem 'glimmer-dsl-swt', '~> 4.18.2.3
476
477
  '
477
478
  ```
478
479
 
@@ -531,7 +532,7 @@ bin/glimmer samples
531
532
  Below are the full usage instructions that come up when running `glimmer` without args.
532
533
 
533
534
  ```
534
- Glimmer (JRuby Desktop Development GUI Framework) - JRuby Gem: glimmer-dsl-swt v4.18.2.2
535
+ Glimmer (JRuby Desktop Development GUI Framework) - JRuby Gem: glimmer-dsl-swt v4.18.2.3
535
536
 
536
537
 
537
538
 
@@ -1012,7 +1013,7 @@ Output:
1012
1013
 
1013
1014
  Css glimmer-dsl-css 1.1.0 AndyMaleh Glimmer DSL for CSS
1014
1015
  Opal glimmer-dsl-opal 0.10.2 AndyMaleh Glimmer DSL for Opal
1015
- Swt glimmer-dsl-swt 4.18.2.2
1016
+ Swt glimmer-dsl-swt 4.18.2.3
1016
1017
 
1017
1018
  AndyMaleh Glimmer DSL for SWT
1018
1019
  Tk glimmer-dsl-tk 0.0.6 AndyMaleh Glimmer DSL for Tk
@@ -4633,6 +4634,16 @@ Contact Manager - Edit Done
4633
4634
 
4634
4635
  ![Contact Manager](images/glimmer-contact-manager-edit-done.png)
4635
4636
 
4637
+ #### Tetris
4638
+
4639
+ This sample demonstrates how to build an interactive animated game with MVC architecture, custom-shell/custom-widgets, multi-threading, asynchronous programming, data-binding, canvas shape graphic decorations, and keyboard events.
4640
+
4641
+ Code:
4642
+
4643
+ [samples/elaborate/tic_tac_toe.rb](samples/elaborate/tetris.rb)
4644
+
4645
+ ![Tetris](images/glimmer-tetris.png)
4646
+
4636
4647
  ### External Samples
4637
4648
 
4638
4649
  #### Glimmer Calculator
data/VERSION CHANGED
@@ -1 +1 @@
1
- 4.18.2.2
1
+ 4.18.2.3
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: glimmer-dsl-swt 4.18.2.2 ruby lib
5
+ # stub: glimmer-dsl-swt 4.18.2.3 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "glimmer-dsl-swt".freeze
9
- s.version = "4.18.2.2"
9
+ s.version = "4.18.2.3"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib".freeze]
13
13
  s.authors = ["AndyMaleh".freeze]
14
- s.date = "2021-01-22"
14
+ s.date = "2021-01-23"
15
15
  s.description = "Glimmer DSL for SWT (JRuby Desktop Development GUI Framework) is a native-GUI cross-platform desktop development library written in JRuby, an OS-threaded faster JVM version of Ruby. Glimmer's main innovation is a declarative Ruby DSL that enables productive and efficient authoring of desktop application user-interfaces by relying on the robust Eclipse SWT library. Glimmer additionally innovates by having built-in data-binding support, which greatly facilitates synchronizing the GUI with domain models, thus achieving true decoupling of object oriented components and enabling developers to solve business problems (test-first) without worrying about GUI concerns, or alternatively drive development GUI-first, and then write clean business models (test-first) afterwards. Not only does Glimmer provide a large set of GUI widgets, but it also supports drawing Canvas Graphics like Shapes and Animations. To get started quickly, Glimmer offers scaffolding options for Apps, Gems, and Custom Widgets. Glimmer also includes native-executable packaging support, sorely lacking in other libraries, thus enabling the delivery of desktop apps written in Ruby as truly native DMG/PKG/APP files on the Mac + App Store, MSI/EXE files on Windows, and Gem Packaged Shell Scripts on Linux.".freeze
16
16
  s.email = "andy.am@gmail.com".freeze
17
17
  s.executables = ["glimmer".freeze, "girb".freeze]
@@ -132,6 +132,12 @@ Gem::Specification.new do |s|
132
132
  "samples/elaborate/contact_manager/contact_repository.rb",
133
133
  "samples/elaborate/login.rb",
134
134
  "samples/elaborate/meta_sample.rb",
135
+ "samples/elaborate/tetris.rb",
136
+ "samples/elaborate/tetris/model/block.rb",
137
+ "samples/elaborate/tetris/model/game.rb",
138
+ "samples/elaborate/tetris/model/tetromino.rb",
139
+ "samples/elaborate/tetris/view/block.rb",
140
+ "samples/elaborate/tetris/view/playfield.rb",
135
141
  "samples/elaborate/tic_tac_toe.rb",
136
142
  "samples/elaborate/tic_tac_toe/board.rb",
137
143
  "samples/elaborate/tic_tac_toe/cell.rb",
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2007-2021 Andy Maleh
2
- #
2
+ #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
5
5
  # "Software"), to deal in the Software without restriction, including
@@ -7,10 +7,10 @@
7
7
  # distribute, sublicense, and/or sell copies of the Software, and to
8
8
  # permit persons to whom the Software is furnished to do so, subject to
9
9
  # the following conditions:
10
- #
10
+ #
11
11
  # The above copyright notice and this permission notice shall be
12
12
  # included in all copies or substantial portions of the Software.
13
- #
13
+ #
14
14
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
15
  # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
16
  # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -42,6 +42,7 @@ module Glimmer
42
42
  *.gem
43
43
  *.rbc
44
44
  /.config
45
+ /.mvn/
45
46
  /coverage/
46
47
  /InstalledFiles
47
48
  /pkg/
@@ -97,9 +98,9 @@ module Glimmer
97
98
  .gladiator
98
99
 
99
100
  # Glimmer
100
- dist
101
- packages
102
- vendor/jars
101
+ /dist/
102
+ /packages/
103
+ /vendor/jars/
103
104
  MULTI_LINE_STRING
104
105
 
105
106
  GEMFILE = <<~MULTI_LINE_STRING
@@ -45,7 +45,7 @@ module Glimmer
45
45
  class << self
46
46
  # Returns singleton instance
47
47
  def instance(*args)
48
- if @instance.nil? || @instance.swt_display.isDisposed
48
+ if @instance.nil? || @instance.swt_display.nil? || @instance.swt_display.isDisposed
49
49
  @instance = new(*args)
50
50
  end
51
51
  @instance
@@ -74,12 +74,10 @@ module Glimmer
74
74
 
75
75
  DEFAULT_INITIALIZERS = {
76
76
  composite: lambda do |composite|
77
- if composite.get_layout.nil?
78
- layout = GridLayout.new
79
- layout.marginWidth = 15
80
- layout.marginHeight = 15
81
- composite.layout = layout
82
- end
77
+ composite.layout = GridLayout.new if composite.get_layout.nil?
78
+ end,
79
+ canvas: lambda do |canvas|
80
+ canvas.layout = nil unless canvas.get_layout.nil?
83
81
  end,
84
82
  scrolled_composite: lambda do |scrolled_composite|
85
83
  scrolled_composite.expand_horizontal = true
@@ -27,6 +27,19 @@ module Glimmer
27
27
  include SuperModule
28
28
  include Glimmer::UI::CustomWidget
29
29
 
30
+ class << self
31
+ attr_reader :custom_shell
32
+
33
+ def launch
34
+ @custom_shell = send(self.name.underscore.gsub('::', '__'))
35
+ @custom_shell.open
36
+ end
37
+
38
+ def shutdown
39
+ @custom_shell.close
40
+ end
41
+ end
42
+
30
43
  def initialize(parent, *swt_constants, options, &content)
31
44
  super
32
45
  @swt_widget.set_data('custom_shell', self)
@@ -1,3 +1,24 @@
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
+
1
22
  require 'fileutils'
2
23
  require 'etc'
3
24
 
@@ -0,0 +1,102 @@
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
+ # Tetris App View Custom Shell (represents `tetris` keyword)
23
+
24
+ require_relative 'tetris/model/game'
25
+
26
+ require_relative 'tetris/view/playfield'
27
+
28
+ class Tetris
29
+ include Glimmer::UI::CustomShell
30
+
31
+ BLOCK_SIZE = 25
32
+ PLAYFIELD_WIDTH = 10
33
+ PLAYFIELD_HEIGHT = 20
34
+
35
+ before_body {
36
+ Model::Game.configure_beeper do
37
+ display.beep
38
+ end
39
+
40
+ Model::Game.start
41
+
42
+ display {
43
+ on_swt_keydown { |key_event|
44
+ unless Model::Game.current_tetromino.stopped?
45
+ case key_event.keyCode
46
+ when swt(:arrow_down)
47
+ Model::Game.current_tetromino.down
48
+ when swt(:arrow_left)
49
+ Model::Game.current_tetromino.left
50
+ when swt(:arrow_right)
51
+ Model::Game.current_tetromino.right
52
+ when swt(:shift)
53
+ if key_event.keyLocation == swt(:right) # right shift key
54
+ Model::Game.current_tetromino.rotate(:right)
55
+ elsif key_event.keyLocation == swt(:left) # left shift key
56
+ Model::Game.current_tetromino.rotate(:left)
57
+ end
58
+ when 'd'.bytes.first, swt(:arrow_up)
59
+ Model::Game.current_tetromino.rotate(:right)
60
+ when 'a'.bytes.first
61
+ Model::Game.current_tetromino.rotate(:left)
62
+ end
63
+ end
64
+ }
65
+ }
66
+ }
67
+
68
+ after_body {
69
+ Thread.new {
70
+ loop {
71
+ sleep(0.9)
72
+ sync_exec {
73
+ unless @game_over
74
+ Model::Game.current_tetromino.down
75
+ if Model::Game.current_tetromino.stopped? && Model::Game.current_tetromino.row <= 0
76
+ @game_over = true
77
+ display.beep
78
+ message_box(:icon_error) {
79
+ text 'Tetris'
80
+ message 'Game Over!'
81
+ }.open
82
+ Model::Game.restart
83
+ @game_over = false
84
+ end
85
+ Model::Game.consider_adding_tetromino
86
+ end
87
+ }
88
+ }
89
+ }
90
+ }
91
+
92
+ body {
93
+ shell(:no_resize) {
94
+ text 'Glimmer Tetris'
95
+ background :gray
96
+
97
+ playfield(playfield_width: PLAYFIELD_WIDTH, playfield_height: PLAYFIELD_HEIGHT, block_size: BLOCK_SIZE)
98
+ }
99
+ }
100
+ end
101
+
102
+ Tetris.launch
@@ -0,0 +1,48 @@
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 Tetris
23
+ module Model
24
+ class Block
25
+ COLOR_CLEAR = :white
26
+
27
+ attr_accessor :color
28
+
29
+ # Initializes with color. Default color (gray) signifies an empty block
30
+ def initialize(color = COLOR_CLEAR)
31
+ @color = color
32
+ end
33
+
34
+ def clear
35
+ self.color = COLOR_CLEAR
36
+ end
37
+
38
+ def clear?
39
+ self.color == COLOR_CLEAR
40
+ end
41
+
42
+ def occupied?
43
+ !clear?
44
+ end
45
+ end
46
+ end
47
+ end
48
+
@@ -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_relative 'block'
23
+ require_relative 'tetromino'
24
+
25
+ class Tetris
26
+ module Model
27
+ class Game
28
+ class << self
29
+ def consider_adding_tetromino
30
+ if tetrominoes.empty? || Game.current_tetromino.stopped?
31
+ tetrominoes << Tetromino.new
32
+ end
33
+ end
34
+
35
+ def current_tetromino
36
+ tetrominoes.last
37
+ end
38
+
39
+ def tetrominoes
40
+ @tetrominoes ||= reset_tetrominoes
41
+ end
42
+
43
+ # Returns blocks in the playfield
44
+ def playfield
45
+ @playfield ||= PLAYFIELD_HEIGHT.times.map {
46
+ PLAYFIELD_WIDTH.times.map {
47
+ Block.new
48
+ }
49
+ }
50
+ end
51
+
52
+ def consider_eliminating_lines
53
+ cleared_line = false
54
+ playfield.each_with_index do |row, playfield_row|
55
+ if row.all? {|block| !block.clear?}
56
+ cleared_line = true
57
+ shift_blocks_down_above_row(playfield_row)
58
+ end
59
+ end
60
+ beep if cleared_line
61
+ end
62
+
63
+ def beep
64
+ @beeper&.call
65
+ end
66
+
67
+ def configure_beeper(&beeper)
68
+ @beeper = beeper
69
+ end
70
+
71
+ def shift_blocks_down_above_row(row)
72
+ row.downto(0) do |playfield_row|
73
+ playfield[playfield_row].each_with_index do |block, playfield_column|
74
+ previous_row = playfield[playfield_row - 1]
75
+ previous_block = previous_row[playfield_column]
76
+ block.color = previous_block.color
77
+ end
78
+ end
79
+ playfield[0].each(&:clear)
80
+ end
81
+
82
+ def restart
83
+ reset_playfield
84
+ reset_tetrominoes
85
+ end
86
+ alias start restart
87
+
88
+ def reset_tetrominoes
89
+ @tetrominoes = [Tetromino.new]
90
+ end
91
+
92
+ def reset_playfield
93
+ playfield.each do |row|
94
+ row.each do |block|
95
+ block.clear
96
+ end
97
+ end
98
+ end
99
+
100
+ def playfield_remaining_heights(tetromino = nil)
101
+ PLAYFIELD_WIDTH.times.map do |playfield_column|
102
+ (playfield.each_with_index.detect do |row, playfield_row|
103
+ !row[playfield_column].clear? &&
104
+ (
105
+ tetromino.nil? ||
106
+ tetromino.bottom_block_for_column(playfield_column).nil? ||
107
+ (playfield_row > tetromino.row + tetromino.bottom_block_for_column(playfield_column)[:row])
108
+ )
109
+ end || [nil, PLAYFIELD_HEIGHT])[1]
110
+ end.to_a
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
116
+
@@ -0,0 +1,228 @@
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 'block'
23
+
24
+ require 'matrix'
25
+
26
+ class Tetris
27
+ module Model
28
+ class Tetromino
29
+ ORIENTATIONS = [:north, :east, :south, :west]
30
+
31
+ LETTER_COLORS = {
32
+ I: :cyan,
33
+ J: :blue,
34
+ L: :dark_yellow,
35
+ O: :yellow,
36
+ S: :green,
37
+ T: :magenta,
38
+ Z: :red,
39
+ }
40
+
41
+ attr_reader :letter
42
+ attr_accessor :orientation, :blocks, :row, :column
43
+
44
+ def initialize
45
+ @letter = LETTER_COLORS.keys.sample
46
+ @orientation = :north
47
+ @blocks = default_blocks
48
+ new_row = 1 - height
49
+ new_column = (PLAYFIELD_WIDTH - width)/2
50
+ update_playfield(new_row, new_column)
51
+ end
52
+
53
+ def update_playfield(new_row = nil, new_column = nil)
54
+ remove_from_playfield
55
+ if !new_row.nil? && !new_column.nil?
56
+ @row = new_row
57
+ @column = new_column
58
+ add_to_playfield
59
+ end
60
+ end
61
+
62
+ def add_to_playfield
63
+ update_playfield_block do |playfield_row, playfield_column, row_index, column_index|
64
+ Game.playfield[playfield_row][playfield_column].color = blocks[row_index][column_index].color if playfield_row >= 0 && Game.playfield[playfield_row][playfield_column].clear? && !blocks[row_index][column_index].clear?
65
+ end
66
+ end
67
+
68
+ def remove_from_playfield
69
+ return if @row.nil? || @column.nil?
70
+ update_playfield_block do |playfield_row, playfield_column, row_index, column_index|
71
+ Game.playfield[playfield_row][playfield_column].clear if playfield_row >= 0 && !blocks[row_index][column_index].clear? && Game.playfield[playfield_row][playfield_column].color == color
72
+ end
73
+ end
74
+
75
+ def stopped?(blocks: nil)
76
+ blocks ||= @blocks
77
+ playfield_remaining_heights = Game.playfield_remaining_heights(self)
78
+ result = bottom_blocks(blocks).any? do |bottom_block|
79
+ playfield_column = @column + bottom_block[:column_index]
80
+ !bottom_block[:block].clear? &&
81
+ (@row + bottom_block[:row]) >= playfield_remaining_heights[playfield_column] - 1
82
+ end
83
+ Game.consider_eliminating_lines if result
84
+ result
85
+ end
86
+
87
+ # Returns blocks at the bottom of a tetromino, which could be from multiple rows depending on shape (e.g. T)
88
+ def bottom_blocks(blocks = nil)
89
+ blocks ||= @blocks
90
+ width.times.map do |column_index|
91
+ row_blocks_with_row_index = @blocks.each_with_index.to_a.reverse.detect do |row_blocks, row_index|
92
+ !row_blocks[column_index].clear?
93
+ end
94
+ bottom_block = row_blocks_with_row_index[0][column_index]
95
+ bottom_block_row = row_blocks_with_row_index[1]
96
+ {
97
+ block: bottom_block,
98
+ row: bottom_block_row,
99
+ column_index: column_index
100
+ }
101
+ end
102
+ end
103
+
104
+ def bottom_block_for_column(column)
105
+ bottom_blocks.detect {|bottom_block| (@column + bottom_block[:column_index]) == column}
106
+ end
107
+
108
+ def right_blocked?
109
+ (@column == PLAYFIELD_WIDTH - width) || Game.playfield[row][column + width].occupied?
110
+ end
111
+
112
+ def left_blocked?
113
+ (@column == 0) || Game.playfield[row][column - 1].occupied?
114
+ end
115
+
116
+ def width
117
+ @blocks[0].size
118
+ end
119
+
120
+ def height
121
+ @blocks.size
122
+ end
123
+
124
+ def down
125
+ unless stopped?
126
+ new_row = @row + 1
127
+ update_playfield(new_row, @column)
128
+ end
129
+ end
130
+
131
+ def left
132
+ unless left_blocked?
133
+ new_column = @column - 1
134
+ update_playfield(@row, new_column)
135
+ end
136
+ end
137
+
138
+ def right
139
+ unless right_blocked?
140
+ new_column = @column + 1
141
+ update_playfield(@row, new_column)
142
+ end
143
+ end
144
+
145
+ # Rotate in specified direcation, which can be :right (clockwise) or :left (counterclockwise)
146
+ def rotate(direction)
147
+ return if stopped?
148
+ array_rotation_value = direction == :right ? -1 : 1
149
+ self.orientation = ORIENTATIONS[ORIENTATIONS.rotate(array_rotation_value).index(@orientation)]
150
+ new_blocks = Matrix[*@blocks].transpose.to_a
151
+ if direction == :right
152
+ new_blocks = new_blocks.map(&:reverse)
153
+ else
154
+ new_blocks = new_blocks.reverse
155
+ end
156
+ new_blocks = Matrix[*new_blocks].to_a
157
+ unless stopped?(blocks: new_blocks) || right_blocked? || left_blocked?
158
+ remove_from_playfield
159
+ self.blocks = new_blocks
160
+ update_playfield(@row, @column)
161
+ end
162
+ end
163
+
164
+ def default_blocks
165
+ case @letter
166
+ when :I
167
+ [
168
+ [block, block, block, block]
169
+ ]
170
+ when :J
171
+ [
172
+ [block, block, block],
173
+ [empty, empty, block],
174
+ ]
175
+ when :L
176
+ [
177
+ [block, block, block],
178
+ [block, empty, empty],
179
+ ]
180
+ when :O
181
+ [
182
+ [block, block],
183
+ [block, block],
184
+ ]
185
+ when :S
186
+ [
187
+ [empty, block, block],
188
+ [block, block, empty],
189
+ ]
190
+ when :T
191
+ [
192
+ [block, block, block],
193
+ [empty, block, empty],
194
+ ]
195
+ when :Z
196
+ [
197
+ [block, block, empty],
198
+ [empty, block, block],
199
+ ]
200
+ end
201
+ end
202
+
203
+ def color
204
+ LETTER_COLORS[@letter]
205
+ end
206
+
207
+ private
208
+
209
+ def block
210
+ Block.new(color)
211
+ end
212
+
213
+ def empty
214
+ Block.new
215
+ end
216
+
217
+ def update_playfield_block(&updater)
218
+ @row.upto(@row + height - 1) do |playfield_row|
219
+ @column.upto(@column + width - 1) do |playfield_column|
220
+ row_index = playfield_row - @row
221
+ column_index = playfield_column - @column
222
+ updater.call(playfield_row, playfield_column, row_index, column_index)
223
+ end
224
+ end
225
+ end
226
+ end
227
+ end
228
+ end
@@ -0,0 +1,45 @@
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 Tetris
23
+ module View
24
+ class Block
25
+ include Glimmer::UI::CustomWidget
26
+
27
+ options :block_size, :row, :column
28
+
29
+ body {
30
+ composite {
31
+ layout nil
32
+ layout_data {
33
+ width_hint block_size
34
+ height_hint block_size
35
+ }
36
+ background bind(Model::Game.playfield[row][column], :color)
37
+ rectangle(0, 0, block_size, block_size)
38
+ rectangle(3, 3, block_size - 6, block_size - 6) {
39
+ foreground :gray
40
+ }
41
+ }
42
+ }
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,49 @@
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 'block'
23
+
24
+ class Tetris
25
+ module View
26
+ class Playfield
27
+ include Glimmer::UI::CustomWidget
28
+
29
+ options :playfield_width, :playfield_height, :block_size
30
+
31
+ body {
32
+ composite {
33
+ grid_layout(playfield_width, true) {
34
+ margin_width block_size
35
+ margin_height block_size
36
+ horizontal_spacing 0
37
+ vertical_spacing 0
38
+ }
39
+
40
+ playfield_height.times { |row|
41
+ playfield_width.times { |column|
42
+ block(block_size: block_size, row: row, column: column)
43
+ }
44
+ }
45
+ }
46
+ }
47
+ end
48
+ end
49
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glimmer-dsl-swt
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.18.2.2
4
+ version: 4.18.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - AndyMaleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-22 00:00:00.000000000 Z
11
+ date: 2021-01-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -465,6 +465,12 @@ files:
465
465
  - samples/elaborate/contact_manager/contact_repository.rb
466
466
  - samples/elaborate/login.rb
467
467
  - samples/elaborate/meta_sample.rb
468
+ - samples/elaborate/tetris.rb
469
+ - samples/elaborate/tetris/model/block.rb
470
+ - samples/elaborate/tetris/model/game.rb
471
+ - samples/elaborate/tetris/model/tetromino.rb
472
+ - samples/elaborate/tetris/view/block.rb
473
+ - samples/elaborate/tetris/view/playfield.rb
468
474
  - samples/elaborate/tic_tac_toe.rb
469
475
  - samples/elaborate/tic_tac_toe/board.rb
470
476
  - samples/elaborate/tic_tac_toe/cell.rb