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 +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +16 -5
- data/VERSION +1 -1
- data/glimmer-dsl-swt.gemspec +9 -3
- data/lib/glimmer/dsl/swt/display_expression.rb +3 -3
- data/lib/glimmer/rake_task/scaffold.rb +4 -3
- data/lib/glimmer/swt/display_proxy.rb +1 -1
- data/lib/glimmer/swt/widget_proxy.rb +4 -6
- data/lib/glimmer/ui/custom_shell.rb +13 -0
- data/samples/elaborate/meta_sample.rb +21 -0
- data/samples/elaborate/tetris.rb +102 -0
- data/samples/elaborate/tetris/model/block.rb +48 -0
- data/samples/elaborate/tetris/model/game.rb +116 -0
- data/samples/elaborate/tetris/model/tetromino.rb +228 -0
- data/samples/elaborate/tetris/view/block.rb +45 -0
- data/samples/elaborate/tetris/view/playfield.rb +49 -0
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 813f7cef0d25c94aa62c0cd57d3445a3eb13acb229bdd59264f7d4a0268f1ed3
|
4
|
+
data.tar.gz: dccf84bac2d2ca037df0b4157335fd7451fc2701d90a79df18abc61971725df6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9702ce2c81c56ddf6c56e590c7f30509149d75fbd6ee8e01da4bb5e0405381fae39da688ec30ab0686ff987cdc4eee06992d7c4b365a32f8bc2d773ea23e3b05
|
7
|
+
data.tar.gz: 4d1a2dfa58fffa6dd037ef07463056ccc70d09261bb0720f238332c07284347993c94e96ef5d18bb9a7f1f75d71b72ed2fdfe72202320f8de489624ac9084edc
|
data/CHANGELOG.md
CHANGED
@@ -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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
1
|
+
4.18.2.3
|
data/glimmer-dsl-swt.gemspec
CHANGED
@@ -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.
|
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.
|
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-
|
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
|
-
|
79
|
-
|
80
|
-
|
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.
|
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-
|
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
|