glimmer-dsl-swt 4.18.3.1 → 4.18.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -1
- data/README.md +71 -13
- data/VERSION +1 -1
- data/glimmer-dsl-swt.gemspec +5 -4
- data/lib/glimmer/swt/shell_proxy.rb +3 -0
- data/lib/glimmer/swt/table_proxy.rb +19 -4
- data/lib/glimmer/ui/custom_shell.rb +1 -0
- data/lib/glimmer/ui/custom_widget.rb +6 -3
- data/samples/elaborate/tetris.rb +38 -18
- data/samples/elaborate/tetris/model/game.rb +55 -3
- data/samples/elaborate/tetris/{view/game_over_dialog.rb → model/past_game.rb} +2 -44
- data/samples/elaborate/tetris/view/high_score_dialog.rb +114 -0
- data/samples/elaborate/tetris/view/score_lane.rb +6 -6
- data/samples/elaborate/tetris/view/tetris_menu_bar.rb +53 -2
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ed3de759196522f355d23f94734175e7bd1f5957b25637005d2b266f0868cd3d
|
4
|
+
data.tar.gz: 4cf0d426d9ab01d53de2c52246be5521bce14e963b1269568d8ecee6f0d01326
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f2a0569e88e07cedbd989aae075e1bf03721f88dc647906e1ce7c16492a59d129f282dd8ce53f535e76027cb402b3ea07a5b56d1ac8d2303dbdc468c1cd17741
|
7
|
+
data.tar.gz: d58989c1839bbe0d15e8fd8a96cdfb917a4c2a2bc9cc0382e2271ef40445b0b891d3ddd06e8f05b361535cfa57915e57e8cbbca0e2d19c2b2425670addfdbfba
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
### 4.18.3.2
|
4
|
+
|
5
|
+
- Tetris High Scores
|
6
|
+
- Tetris Modify High Score Player Name
|
7
|
+
- Tetris Show High Scores (Menu Item + Accelerator)
|
8
|
+
- Tetris add a menu item with beep enablement option
|
9
|
+
- Tetris Clear High Scores
|
10
|
+
- Tetris Add left and right alt (option) buttons as alternative to shift for rotation. Use left ctrl as rotate left. Use a, s, d as left, down, right.
|
11
|
+
- Fix issues relating to setting parenthood with custom widgets before building their body (instead of after)
|
12
|
+
- Fix issues relating to not respecting arity of passed in table editing callbacks: before_write, after_write, and after_cancel
|
13
|
+
|
3
14
|
### 4.18.3.1
|
4
15
|
|
5
16
|
- Provide an auto_sync_exec all data-binding config option to automatically sync_exec GUI calls from other threads instead of requiring users to use sync_exec on model attribute-change logic. Default value to false.
|
@@ -10,9 +21,9 @@
|
|
10
21
|
- Supporting deregistering Display listeners just like standard listeners via deregister
|
11
22
|
- Enhance performance of excluded keyword check
|
12
23
|
- Remove CustomWidget support for multiple before_body/after_body blocks instead of one each since it is not needed.
|
24
|
+
- Add new :fill_screen style for `shell` to start app filling the screen size (not full screen mode though)
|
13
25
|
- Tetris Menu Bar with Game Menu -> Start, Pause, Restart, and Exit
|
14
26
|
- Tetris refactor mutation methods to end with bangs
|
15
|
-
- Add new :fill_screen style for `shell` to start app filling the screen size (not full screen mode though)
|
16
27
|
- Tetris Stop game if user does not play again in the end (instead of closing it)
|
17
28
|
- End Tetris Thread loop gracefully if game over is encountered
|
18
29
|
- Tetris use more observers instead of callbacks to Game
|
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.3.
|
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.3.2
|
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)
|
@@ -241,6 +241,7 @@ If you see anything that needs to be improved, please do not hesitate to contact
|
|
241
241
|
- [Desktop Apps Built with Glimmer DSL for SWT](#desktop-apps-built-with-glimmer-dsl-for-swt)
|
242
242
|
- [Table of contents](#table-of-contents)
|
243
243
|
- [Background](#background)
|
244
|
+
- [Software Architecture](#software-architecture)
|
244
245
|
- [Platform Support](#platform-support)
|
245
246
|
- [Pre-requisites](#pre-requisites)
|
246
247
|
- [Setup](#setup)
|
@@ -407,6 +408,38 @@ If you see anything that needs to be improved, please do not hesitate to contact
|
|
407
408
|
|
408
409
|
[Ruby](https://www.ruby-lang.org) is a dynamically-typed object-oriented language, which provides great productivity gains due to its powerful expressive syntax and dynamic nature. While it is proven by the [Ruby](https://www.ruby-lang.org) on Rails framework for web development, it currently lacks a robust platform-independent framework for building desktop applications. Given that Java libraries can now be utilized in Ruby code through JRuby, Eclipse technologies, such as [SWT](https://www.eclipse.org/swt/), JFace, and RCP can help fill the gap of desktop application development with Ruby.
|
409
410
|
|
411
|
+
## Software Architecture
|
412
|
+
|
413
|
+
There are several requirements for building enterprise-level/consumer-level desktop GUI applications:
|
414
|
+
- Cross-Platform Support (Mac, Windows, Linux) without compilation/recompilation
|
415
|
+
- OS Native Look & Feel
|
416
|
+
- High Performance
|
417
|
+
- Productivity
|
418
|
+
- Maintainability
|
419
|
+
- Extensibility
|
420
|
+
- Native Executable Packaging
|
421
|
+
- Multi-Threading / Parallel Programming
|
422
|
+
- Arbitrary Graphics Painting
|
423
|
+
- Audio Support
|
424
|
+
|
425
|
+
Glimmer provides cross-platform support that does not require Ruby compilation (like Tk does), thanks to JRuby, a JVM (Java Virtual Machine) faster OS-threaded version of Ruby.
|
426
|
+
|
427
|
+
Glimmer leverages SWT (Standard Widget Toolkit), which provides cross-platform widgets that automatically use the native GUI libraries under each operating system, such as Win32 on Windows, Cocoa on Mac, and GTK on Linux.
|
428
|
+
|
429
|
+
Furthermore, what is special about SWT regarding "High Performance" is that it does all the GUI painting natively outside of Java, thus producing GUI that runs at maximum performance even in Ruby. As such, you do not need to worry about Ruby dynamic typing getting in the way of GUI performance. It has ZERO effect on it and since SWT supports making asynchronous calls for GUI rendering, you could avoid blocking the GUI completely with any computations happening in Ruby no matter how complex, thus never affecting the responsiveness of GUI of applications while taking full advantage of the productivity benefits of Ruby dynamic typing.
|
430
|
+
|
431
|
+
Glimmer takes this further by providing a very programmer friendly DSL (Domain Specific Language) that visually maps lightweight Ruby syntax to the containment hierarchy of GUI widgets (meaning Ruby blocks nested within each other map to GUI widgets nested within each other). This provides maximum productivity and maintainability.
|
432
|
+
|
433
|
+
Extensibility has never been simpler in desktop GUI application development than with Glimmer, which provides the ability to support any new custom keywords through custom widgets and custom shells (windows). Basically, you map a keyword by declaring a view class matching its name by convention with a GUI body that simply consists of reusable Glimmer GUI syntax. They can be passive views or smart views with additional logic. This provides the ultimate realization of Object Oriented Programming and micro-level MVC pattern.
|
434
|
+
|
435
|
+
Thanks to Java and JRuby, Glimmer apps can be packaged as cross-platform JAR files (with JRuby Warbler) and native executables (with Java Packager) as Mac APP/DMG/PACKAGE or Windows EXE/MSI.
|
436
|
+
|
437
|
+
The Java Virtual Machine already supports OS-native threads, so Glimmer apps can have multiple things running in parallel with no problem.
|
438
|
+
|
439
|
+
SWT supports Canvas graphics drawing, and Glimmer takes that further by provding a Canvas Shape/Transform/Animation DSL, making it very simple to decorate any existing widgets or add new widgets with a completely custom look and feel if needed for branding or entertainment (gaming) purposes.
|
440
|
+
|
441
|
+
Audio is supported via the Java Sound library in a cross-platform approach and video is supported via a Glimmer custom widget, so any Glimmer app can be enhanced with audio and video where needed.
|
442
|
+
|
410
443
|
## Platform Support
|
411
444
|
|
412
445
|
Glimmer runs on the following platforms:
|
@@ -460,7 +493,7 @@ jgem install glimmer-dsl-swt
|
|
460
493
|
|
461
494
|
Or this command if you want a specific version:
|
462
495
|
```
|
463
|
-
jgem install glimmer-dsl-swt -v 4.18.3.
|
496
|
+
jgem install glimmer-dsl-swt -v 4.18.3.2
|
464
497
|
|
465
498
|
|
466
499
|
```
|
@@ -480,7 +513,7 @@ Note: if you're using activerecord or activesupport, keep in mind that Glimmer u
|
|
480
513
|
|
481
514
|
Add the following to `Gemfile`:
|
482
515
|
```
|
483
|
-
gem 'glimmer-dsl-swt', '~> 4.18.3.
|
516
|
+
gem 'glimmer-dsl-swt', '~> 4.18.3.2
|
484
517
|
'
|
485
518
|
```
|
486
519
|
|
@@ -539,7 +572,7 @@ bin/glimmer samples
|
|
539
572
|
Below are the full usage instructions that come up when running `glimmer` without args.
|
540
573
|
|
541
574
|
```
|
542
|
-
Glimmer (JRuby Desktop Development GUI Framework) - JRuby Gem: glimmer-dsl-swt v4.18.3.
|
575
|
+
Glimmer (JRuby Desktop Development GUI Framework) - JRuby Gem: glimmer-dsl-swt v4.18.3.2
|
543
576
|
|
544
577
|
|
545
578
|
|
@@ -815,7 +848,7 @@ glimmer run
|
|
815
848
|
|
816
849
|
#### Custom Shell
|
817
850
|
|
818
|
-
To scaffold a Glimmer custom shell (full window view) for an existing Glimmer app, run the following command:
|
851
|
+
To scaffold a Glimmer [custom shell](#custom-shells) (full window view) for an existing Glimmer app, run the following command:
|
819
852
|
|
820
853
|
```
|
821
854
|
glimmer scaffold:customshell[name]
|
@@ -829,7 +862,7 @@ glimmer scaffold:cs[name]
|
|
829
862
|
|
830
863
|
#### Custom Widget
|
831
864
|
|
832
|
-
To scaffold a Glimmer custom widget (part of a view) for an existing Glimmer app, run the following command:
|
865
|
+
To scaffold a Glimmer [custom widget](#custom-widgets) (part of a view) for an existing Glimmer app, run the following command:
|
833
866
|
|
834
867
|
```
|
835
868
|
glimmer scaffold:customwidget[name]
|
@@ -843,7 +876,7 @@ glimmer scaffold:cw[name]
|
|
843
876
|
|
844
877
|
#### Custom Shell Gem
|
845
878
|
|
846
|
-
Custom shell gems are self-contained Glimmer apps as well as reusable custom shells.
|
879
|
+
Custom shell gems are self-contained Glimmer apps as well as reusable [custom shells](#custom-shells).
|
847
880
|
They have everything scaffolded Glimmer apps come with in addition to gem content like a [Juwelier](https://rubygems.org/gems/juwelier) Rakefile that can build gemspec and release gems.
|
848
881
|
Unlike scaffolded Glimmer apps, custom shell gem content lives under the `lib` directory (not `app`).
|
849
882
|
They can be packaged as both a native executable (e.g. Mac DMG/PKG/APP) and a Ruby gem.
|
@@ -878,7 +911,7 @@ Examples:
|
|
878
911
|
|
879
912
|
#### Custom Widget Gem
|
880
913
|
|
881
|
-
To scaffold a Glimmer custom widget gem (part of a view distributed as a Ruby gem), run the following command:
|
914
|
+
To scaffold a Glimmer [custom widget](#custom-widgets) gem (part of a view distributed as a Ruby gem), run the following command:
|
882
915
|
|
883
916
|
```
|
884
917
|
glimmer scaffold:gem:customwidget[name,namespace]
|
@@ -904,7 +937,7 @@ Examples:
|
|
904
937
|
|
905
938
|
### Gem Listing
|
906
939
|
|
907
|
-
The `glimmer` command comes with tasks for listing Glimmer related gems to make it easy to find Glimmer Custom Shells, Custom Widgets, and DSLs published by others in the Glimmer community on [rubygems.org](http://www.rubygems.org).
|
940
|
+
The `glimmer` command comes with tasks for listing Glimmer related gems to make it easy to find Glimmer [Custom Shells](#custom-shells), [Custom Widgets](#custom-widgets), and DSLs published by others in the Glimmer community on [rubygems.org](http://www.rubygems.org).
|
908
941
|
|
909
942
|
#### Listing Custom Shell Gems
|
910
943
|
|
@@ -1020,7 +1053,7 @@ Output:
|
|
1020
1053
|
|
1021
1054
|
Css glimmer-dsl-css 1.1.0 AndyMaleh Glimmer DSL for CSS
|
1022
1055
|
Opal glimmer-dsl-opal 0.10.2 AndyMaleh Glimmer DSL for Opal
|
1023
|
-
Swt glimmer-dsl-swt 4.18.3.
|
1056
|
+
Swt glimmer-dsl-swt 4.18.3.2
|
1024
1057
|
|
1025
1058
|
AndyMaleh Glimmer DSL for SWT
|
1026
1059
|
Tk glimmer-dsl-tk 0.0.6 AndyMaleh Glimmer DSL for Tk
|
@@ -1098,9 +1131,12 @@ bin/girb
|
|
1098
1131
|
|
1099
1132
|
Watch out for hands-on examples in this README indicated by "you may copy/paste in [`girb`](#girb-glimmer-irb-command)"
|
1100
1133
|
|
1101
|
-
Keep in mind that all samples live under [https://github.com/AndyObtiva/glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt)
|
1134
|
+
Keep in mind that all samples live under [https://github.com/AndyObtiva/glimmer-dsl-swt/samples](https://github.com/AndyObtiva/glimmer-dsl-swt/samples)
|
1102
1135
|
|
1103
|
-
If you need a more GUI interactive option to experiement with Glimmer GUI DSL Syntax, you may try
|
1136
|
+
If you need a more GUI interactive option to experiement with Glimmer GUI DSL Syntax, you may try:
|
1137
|
+
- [Glimmer Meta-Sample (The Sample of Samples)](#samples): allows launching Glimmer samples and viewing/editing code to learn/experiment too.
|
1138
|
+
- ["Ugliest Editor Ever"](https://github.com/AndyObtiva/glimmer-cs-gladiator)
|
1139
|
+
- Just build your own GUI editor using the [Glimmer DSL for SWT Ruby Gem](https://rubygems.org/gems/glimmer-dsl-swt).
|
1104
1140
|
|
1105
1141
|
## Glimmer GUI DSL Syntax
|
1106
1142
|
|
@@ -3496,6 +3532,8 @@ shell { |app_shell|
|
|
3496
3532
|
}.open
|
3497
3533
|
```
|
3498
3534
|
|
3535
|
+
If you use a Custom Shell as the top-level app shell, you may invoke the class method `::launch` instead to avoid building an app class yourself or including Glimmer into the top-level namespace (e.g. `Tetris.launch` instead of `include Glimmer; tetris.open`)
|
3536
|
+
|
3499
3537
|
You may check out [Hello, Custom Shell!](#hello-custom-shell) for another example.
|
3500
3538
|
|
3501
3539
|
### Drag and Drop
|
@@ -4147,8 +4185,18 @@ end
|
|
4147
4185
|
|
4148
4186
|
### log_excluded_keywords
|
4149
4187
|
|
4188
|
+
(default = false)
|
4189
|
+
|
4150
4190
|
This just tells Glimmer whether to log excluded keywords or not (at the debug level). It is off by default.
|
4151
4191
|
|
4192
|
+
### auto_sync_exec
|
4193
|
+
|
4194
|
+
(default = false)
|
4195
|
+
|
4196
|
+
This automatically uses sync_exec on GUI calls from threads other than the main GUI thread instead of requiring users to manually use sync_exec. Default value to false.
|
4197
|
+
|
4198
|
+
Keep in mind the caveat that it would force redraws on every minor changein the models instead of applying large scope changes all together, thus causing too much drawing/stutter in the GUI. As such, this is a good fit for simpler GUIs, not ones used with highly sophisticated 2D graphics. It may be mitigated in the future by introducing the idea of large-scale observation events that wrap around smaller events. Until then, keep the caveat in mind or just use sync_exec manually as usually done with Java SWT apps.
|
4199
|
+
|
4152
4200
|
## Glimmer Style Guide
|
4153
4201
|
|
4154
4202
|
- Widgets are declared with underscored lowercase versions of their SWT names minus the SWT package name.
|
@@ -4227,7 +4275,7 @@ You may edit the code of any sample before launching it by clicking on the "Laun
|
|
4227
4275
|
Note that if you fail to run any sample through the Glimmer Meta-Sample for whatever reason, you could always run directly by cloning the project, running `bundle`, and then this command (drop the "bin" if you install the glimmer-dsl-swt gem instead):
|
4228
4276
|
|
4229
4277
|
```ruby
|
4230
|
-
bin/glimmer samples/hello/hello_canvas_transform.rb
|
4278
|
+
bin/glimmer samples/hello/hello_canvas_transform.rb
|
4231
4279
|
```
|
4232
4280
|
|
4233
4281
|
### Hello Samples
|
@@ -4812,6 +4860,16 @@ Code:
|
|
4812
4860
|
|
4813
4861
|
![Tetris Game Over](images/glimmer-tetris-game-over.png)
|
4814
4862
|
|
4863
|
+
![Tetris High Scores](images/glimmer-tetris-high-score-dialog.png)
|
4864
|
+
|
4865
|
+
![Tetris Game Menu](images/glimmer-tetris-game-menu.png)
|
4866
|
+
|
4867
|
+
![Tetris View Menu](images/glimmer-tetris-view-menu.png)
|
4868
|
+
|
4869
|
+
![Tetris Options Menu](images/glimmer-tetris-options-menu.png)
|
4870
|
+
|
4871
|
+
![Tetris Help Menu](images/glimmer-tetris-help-menu.png)
|
4872
|
+
|
4815
4873
|
### External Samples
|
4816
4874
|
|
4817
4875
|
#### Glimmer Calculator
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
4.18.3.
|
1
|
+
4.18.3.2
|
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.3.
|
5
|
+
# stub: glimmer-dsl-swt 4.18.3.2 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "glimmer-dsl-swt".freeze
|
9
|
-
s.version = "4.18.3.
|
9
|
+
s.version = "4.18.3.2"
|
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-28"
|
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]
|
@@ -138,9 +138,10 @@ Gem::Specification.new do |s|
|
|
138
138
|
"samples/elaborate/tetris.rb",
|
139
139
|
"samples/elaborate/tetris/model/block.rb",
|
140
140
|
"samples/elaborate/tetris/model/game.rb",
|
141
|
+
"samples/elaborate/tetris/model/past_game.rb",
|
141
142
|
"samples/elaborate/tetris/model/tetromino.rb",
|
142
143
|
"samples/elaborate/tetris/view/block.rb",
|
143
|
-
"samples/elaborate/tetris/view/
|
144
|
+
"samples/elaborate/tetris/view/high_score_dialog.rb",
|
144
145
|
"samples/elaborate/tetris/view/playfield.rb",
|
145
146
|
"samples/elaborate/tetris/view/score_lane.rb",
|
146
147
|
"samples/elaborate/tetris/view/tetris_menu_bar.rb",
|
@@ -117,10 +117,12 @@ module Glimmer
|
|
117
117
|
def nested?
|
118
118
|
!swt_widget&.parent.nil?
|
119
119
|
end
|
120
|
+
alias nested nested?
|
120
121
|
|
121
122
|
def disposed?
|
122
123
|
swt_widget.isDisposed
|
123
124
|
end
|
125
|
+
alias disposed disposed?
|
124
126
|
|
125
127
|
def hide
|
126
128
|
@swt_widget.setVisible(false)
|
@@ -129,6 +131,7 @@ module Glimmer
|
|
129
131
|
def visible?
|
130
132
|
@swt_widget.isDisposed ? false : @swt_widget.isVisible
|
131
133
|
end
|
134
|
+
alias visible visible?
|
132
135
|
|
133
136
|
# Setting to true opens/shows shell. Setting to false hides the shell.
|
134
137
|
def visible=(visibility)
|
@@ -265,6 +265,10 @@ module Glimmer
|
|
265
265
|
end
|
266
266
|
end
|
267
267
|
|
268
|
+
def items
|
269
|
+
swt_widget.get_items
|
270
|
+
end
|
271
|
+
|
268
272
|
def model_binding
|
269
273
|
swt_widget.data
|
270
274
|
end
|
@@ -445,7 +449,6 @@ module Glimmer
|
|
445
449
|
end
|
446
450
|
|
447
451
|
def edit_table_item(table_item, column_index, before_write: nil, after_write: nil, after_cancel: nil)
|
448
|
-
require 'facets/hash/symbolize_keys'
|
449
452
|
return if table_item.nil?
|
450
453
|
model = table_item.data
|
451
454
|
property = column_properties[column_index]
|
@@ -467,7 +470,11 @@ module Glimmer
|
|
467
470
|
@cancel_in_progress = true
|
468
471
|
@table_editor_widget_proxy&.swt_widget&.dispose
|
469
472
|
@table_editor_widget_proxy = nil
|
470
|
-
after_cancel&.
|
473
|
+
if after_cancel&.arity == 0
|
474
|
+
after_cancel&.call
|
475
|
+
else
|
476
|
+
after_cancel&.call(table_item)
|
477
|
+
end
|
471
478
|
@edit_in_progress = false
|
472
479
|
@cancel_in_progress = false
|
473
480
|
@cancel_edit = nil
|
@@ -484,14 +491,22 @@ module Glimmer
|
|
484
491
|
if new_value == model.send(model_editing_property)
|
485
492
|
@cancel_edit.call
|
486
493
|
else
|
487
|
-
before_write&.
|
494
|
+
if before_write&.arity == 0
|
495
|
+
before_write&.call
|
496
|
+
else
|
497
|
+
before_write&.call(edited_table_item)
|
498
|
+
end
|
488
499
|
model.send("#{model_editing_property}=", new_value) # makes table update itself, so must search for selected table item again
|
489
500
|
# Table refresh happens here because of model update triggering observers, so must retrieve table item again
|
490
501
|
edited_table_item = search { |ti| ti.getData == model }.first
|
491
502
|
swt_widget.showItem(edited_table_item)
|
492
503
|
@table_editor_widget_proxy&.swt_widget&.dispose
|
493
504
|
@table_editor_widget_proxy = nil
|
494
|
-
after_write&.
|
505
|
+
if after_write&.arity == 0
|
506
|
+
after_write&.call
|
507
|
+
else
|
508
|
+
after_write&.call(edited_table_item)
|
509
|
+
end
|
495
510
|
@edit_in_progress = false
|
496
511
|
end
|
497
512
|
end
|
@@ -32,6 +32,7 @@ module Glimmer
|
|
32
32
|
|
33
33
|
def launch(*args, &content)
|
34
34
|
@launched_custom_shell = send(keyword, *args, &content) if @launched_custom_shell.nil? || @launched_custom_shell.disposed?
|
35
|
+
@launched_custom_shell.swt_widget.set_data('launched', true)
|
35
36
|
@launched_custom_shell.open
|
36
37
|
end
|
37
38
|
end
|
@@ -163,6 +163,8 @@ module Glimmer
|
|
163
163
|
attr_reader :body_root, :swt_widget, :parent, :parent_proxy, :swt_style, :options
|
164
164
|
|
165
165
|
def initialize(parent, *swt_constants, options, &content)
|
166
|
+
@parent = parent
|
167
|
+
@parent_proxy = @parent&.get_data('proxy')
|
166
168
|
@swt_style = SWT::SWTProxy[*swt_constants]
|
167
169
|
options ||= {}
|
168
170
|
@options = self.class.options.merge(options)
|
@@ -174,9 +176,6 @@ module Glimmer
|
|
174
176
|
raise Glimmer::Error, 'Invalid custom widget for having an empty body! Please fill body block!' if @body_root.nil?
|
175
177
|
@swt_widget = @body_root.swt_widget
|
176
178
|
@swt_widget.set_data('custom_widget', self)
|
177
|
-
@parent = parent
|
178
|
-
@parent ||= @swt_widget.parent
|
179
|
-
@parent_proxy ||= @parent&.get_data('proxy')
|
180
179
|
execute_hook('after_body')
|
181
180
|
end
|
182
181
|
|
@@ -254,6 +253,10 @@ module Glimmer
|
|
254
253
|
def has_style?(style)
|
255
254
|
(swt_style & SWT::SWTProxy[style]) == SWT::SWTProxy[style]
|
256
255
|
end
|
256
|
+
|
257
|
+
def pack(*args)
|
258
|
+
body_root.pack(*args)
|
259
|
+
end
|
257
260
|
|
258
261
|
# TODO see if it is worth it to eliminate duplication of async_exec/sync_exec
|
259
262
|
# delegation to DisplayProxy, via a module
|
data/samples/elaborate/tetris.rb
CHANGED
@@ -25,13 +25,16 @@ require_relative 'tetris/model/game'
|
|
25
25
|
|
26
26
|
require_relative 'tetris/view/playfield'
|
27
27
|
require_relative 'tetris/view/score_lane'
|
28
|
-
require_relative 'tetris/view/
|
28
|
+
require_relative 'tetris/view/high_score_dialog'
|
29
29
|
require_relative 'tetris/view/tetris_menu_bar'
|
30
30
|
|
31
31
|
class Tetris
|
32
32
|
include Glimmer::UI::CustomShell
|
33
33
|
|
34
34
|
BLOCK_SIZE = 25
|
35
|
+
FONT_NAME = 'Menlo'
|
36
|
+
FONT_TITLE_HEIGHT = 32
|
37
|
+
FONT_TITLE_STYLE = :bold
|
35
38
|
|
36
39
|
option :playfield_width, default: Model::Game::PLAYFIELD_WIDTH
|
37
40
|
option :playfield_height, default: Model::Game::PLAYFIELD_HEIGHT
|
@@ -50,32 +53,36 @@ class Tetris
|
|
50
53
|
display {
|
51
54
|
@keyboard_listener = on_swt_keydown { |key_event|
|
52
55
|
case key_event.keyCode
|
53
|
-
when swt(:arrow_down)
|
56
|
+
when swt(:arrow_down), 's'.bytes.first
|
54
57
|
game.down!
|
55
|
-
when swt(:arrow_left)
|
58
|
+
when swt(:arrow_left), 'a'.bytes.first
|
56
59
|
game.left!
|
57
|
-
when swt(:arrow_right)
|
60
|
+
when swt(:arrow_right), 'd'.bytes.first
|
58
61
|
game.right!
|
59
|
-
when swt(:shift)
|
62
|
+
when swt(:shift), swt(:alt)
|
60
63
|
if key_event.keyLocation == swt(:right) # right shift key
|
61
64
|
game.rotate!(:right)
|
62
65
|
elsif key_event.keyLocation == swt(:left) # left shift key
|
63
66
|
game.rotate!(:left)
|
64
67
|
end
|
65
|
-
when
|
68
|
+
when swt(:arrow_up)
|
66
69
|
game.rotate!(:right)
|
67
|
-
when
|
70
|
+
when swt(:ctrl)
|
68
71
|
game.rotate!(:left)
|
69
72
|
end
|
70
73
|
}
|
74
|
+
|
75
|
+
# if running in app mode, set the Mac app about dialog (ignored in platforms)
|
76
|
+
@about_observer = on_about {
|
77
|
+
show_about_dialog
|
78
|
+
}
|
71
79
|
}
|
72
80
|
}
|
73
81
|
|
74
82
|
after_body {
|
75
83
|
@game_over_observer = observe(@game, :game_over) do |game_over|
|
76
84
|
if game_over
|
77
|
-
|
78
|
-
@game_over_dialog.show
|
85
|
+
show_high_score_dialog
|
79
86
|
else
|
80
87
|
start_moving_tetrominos_down
|
81
88
|
end
|
@@ -92,19 +99,19 @@ class Tetris
|
|
92
99
|
margin_height 0
|
93
100
|
horizontal_spacing 0
|
94
101
|
}
|
95
|
-
|
102
|
+
|
96
103
|
text 'Glimmer Tetris'
|
97
104
|
minimum_size 475, 500
|
98
105
|
background :gray
|
99
|
-
|
106
|
+
|
100
107
|
tetris_menu_bar(game: game)
|
101
|
-
|
108
|
+
|
102
109
|
playfield(game_playfield: game.playfield, playfield_width: playfield_width, playfield_height: playfield_height, block_size: BLOCK_SIZE)
|
103
|
-
|
110
|
+
|
104
111
|
score_lane(game: game, block_size: BLOCK_SIZE) {
|
105
112
|
layout_data(:fill, :fill, true, true)
|
106
113
|
}
|
107
|
-
|
114
|
+
|
108
115
|
on_widget_disposed {
|
109
116
|
deregister_observers
|
110
117
|
}
|
@@ -126,11 +133,24 @@ class Tetris
|
|
126
133
|
end
|
127
134
|
end
|
128
135
|
|
136
|
+
def show_high_score_dialog
|
137
|
+
return if @high_score_dialog&.visible?
|
138
|
+
@high_score_dialog = high_score_dialog(parent_shell: body_root, game: @game) if @high_score_dialog.nil? || @high_score_dialog.disposed?
|
139
|
+
@high_score_dialog.show
|
140
|
+
end
|
141
|
+
|
142
|
+
def show_about_dialog
|
143
|
+
message_box {
|
144
|
+
text 'Glimmer Tetris'
|
145
|
+
message "Glimmer Tetris\n\nGlimmer DSL for SWT Sample\n\nCopyright (c) 2007-2021 Andy Maleh"
|
146
|
+
}.open
|
147
|
+
end
|
148
|
+
|
129
149
|
def deregister_observers
|
130
|
-
@
|
131
|
-
@game_over_observer
|
132
|
-
@keyboard_listener
|
133
|
-
@
|
150
|
+
@show_high_scores_observer.deregister
|
151
|
+
@game_over_observer.deregister
|
152
|
+
@keyboard_listener.deregister
|
153
|
+
@about_observer&.deregister
|
134
154
|
end
|
135
155
|
end
|
136
156
|
|
@@ -19,8 +19,14 @@
|
|
19
19
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
20
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
21
|
|
22
|
+
require 'fileutils'
|
23
|
+
require 'etc'
|
24
|
+
require 'glimmer/data_binding/observer'
|
25
|
+
require 'glimmer/config'
|
26
|
+
|
22
27
|
require_relative 'block'
|
23
28
|
require_relative 'tetromino'
|
29
|
+
require_relative 'past_game'
|
24
30
|
|
25
31
|
class Tetris
|
26
32
|
module Model
|
@@ -32,13 +38,18 @@ class Tetris
|
|
32
38
|
SCORE_MULTIPLIER = {1 => 40, 2 => 100, 3 => 300, 4 => 1200}
|
33
39
|
|
34
40
|
attr_reader :playfield_width, :playfield_height
|
35
|
-
attr_accessor :game_over, :paused, :preview_tetromino, :lines, :score, :level
|
41
|
+
attr_accessor :game_over, :paused, :preview_tetromino, :lines, :score, :level, :high_scores, :beeping, :added_high_score
|
36
42
|
alias game_over? game_over
|
37
43
|
alias paused? paused
|
44
|
+
alias beeping? beeping
|
45
|
+
alias added_high_score? added_high_score
|
38
46
|
|
39
47
|
def initialize(playfield_width = PLAYFIELD_WIDTH, playfield_height = PLAYFIELD_HEIGHT)
|
40
48
|
@playfield_width = playfield_width
|
41
49
|
@playfield_height = playfield_height
|
50
|
+
@high_scores = []
|
51
|
+
@beeping = true
|
52
|
+
load_high_scores!
|
42
53
|
end
|
43
54
|
|
44
55
|
def configure_beeper(&beeper)
|
@@ -63,10 +74,51 @@ class Tetris
|
|
63
74
|
end
|
64
75
|
alias restart! start!
|
65
76
|
|
77
|
+
def game_over!
|
78
|
+
add_high_score!
|
79
|
+
beep
|
80
|
+
self.game_over = true
|
81
|
+
end
|
82
|
+
|
83
|
+
def clear_high_scores!
|
84
|
+
high_scores.clear
|
85
|
+
end
|
86
|
+
|
87
|
+
def add_high_score!
|
88
|
+
self.added_high_score = true
|
89
|
+
high_scores.prepend(PastGame.new("Player #{high_scores.count + 1}", score))
|
90
|
+
end
|
91
|
+
|
92
|
+
def save_high_scores!
|
93
|
+
high_score_file_content = @high_scores.map {|past_game| past_game.to_a.join("\t") }.join("\n")
|
94
|
+
FileUtils.mkdir_p(tetris_dir)
|
95
|
+
File.write(tetris_high_score_file, high_score_file_content)
|
96
|
+
rescue => e
|
97
|
+
# Fail safely by keeping high scores in memory if unable to access disk
|
98
|
+
Glimmer::Config.logger.error {"Failed to save high scores in: #{tetris_high_score_file}\n#{e.full_message}"}
|
99
|
+
end
|
100
|
+
|
101
|
+
def load_high_scores!
|
102
|
+
if File.exist?(tetris_high_score_file)
|
103
|
+
self.high_scores = File.read(tetris_high_score_file).split("\n").map {|line| PastGame.new(*line.split("\t")) }
|
104
|
+
end
|
105
|
+
rescue => e
|
106
|
+
# Fail safely by keeping high scores in memory if unable to access disk
|
107
|
+
Glimmer::Config.logger.error {"Failed to load high scores from: #{tetris_high_score_file}\n#{e.full_message}"}
|
108
|
+
end
|
109
|
+
|
110
|
+
def tetris_dir
|
111
|
+
@tetris_dir ||= File.join(Etc.getpwuid.dir, '.glimmer-tetris')
|
112
|
+
end
|
113
|
+
|
114
|
+
def tetris_high_score_file
|
115
|
+
File.join(tetris_dir, "high_scores.txt")
|
116
|
+
end
|
117
|
+
|
66
118
|
def down!
|
67
119
|
return unless game_in_progress?
|
68
120
|
current_tetromino.down!
|
69
|
-
|
121
|
+
game_over! if current_tetromino.row <= 0 && current_tetromino.stopped?
|
70
122
|
end
|
71
123
|
|
72
124
|
def right!
|
@@ -147,7 +199,7 @@ class Tetris
|
|
147
199
|
end
|
148
200
|
|
149
201
|
def beep
|
150
|
-
@beeper&.call
|
202
|
+
@beeper&.call if beeping
|
151
203
|
end
|
152
204
|
|
153
205
|
def reset_tetrominoes
|
@@ -19,50 +19,8 @@
|
|
19
19
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
20
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
21
|
|
22
|
-
require_relative 'tetris_menu_bar'
|
23
|
-
|
24
22
|
class Tetris
|
25
|
-
module
|
26
|
-
|
27
|
-
include Glimmer::UI::CustomShell
|
28
|
-
|
29
|
-
options :parent_shell, :game
|
30
|
-
|
31
|
-
after_body {
|
32
|
-
observe(game, :game_over) do |game_over|
|
33
|
-
hide if !game_over
|
34
|
-
end
|
35
|
-
}
|
36
|
-
|
37
|
-
body {
|
38
|
-
dialog(parent_shell) {
|
39
|
-
row_layout {
|
40
|
-
type :vertical
|
41
|
-
center true
|
42
|
-
}
|
43
|
-
text 'Tetris'
|
44
|
-
|
45
|
-
tetris_menu_bar(game: game)
|
46
|
-
|
47
|
-
label(:center) {
|
48
|
-
text 'Game Over!'
|
49
|
-
font name: 'Menlo', height: 30, style: :bold
|
50
|
-
}
|
51
|
-
label # filler
|
52
|
-
button {
|
53
|
-
text 'Play Again?'
|
54
|
-
|
55
|
-
on_widget_selected {
|
56
|
-
hide
|
57
|
-
game.restart!
|
58
|
-
}
|
59
|
-
}
|
60
|
-
|
61
|
-
on_shell_activated {
|
62
|
-
display.beep
|
63
|
-
}
|
64
|
-
}
|
65
|
-
}
|
66
|
-
end
|
23
|
+
module Model
|
24
|
+
PastGame = Struct.new(:name, :score)
|
67
25
|
end
|
68
26
|
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 'tetris_menu_bar'
|
23
|
+
|
24
|
+
class Tetris
|
25
|
+
module View
|
26
|
+
class HighScoreDialog
|
27
|
+
include Glimmer::UI::CustomShell
|
28
|
+
|
29
|
+
options :parent_shell, :game
|
30
|
+
|
31
|
+
after_body {
|
32
|
+
@game_over_observer = observe(game, :game_over) do |game_over|
|
33
|
+
close if !game_over
|
34
|
+
end
|
35
|
+
}
|
36
|
+
|
37
|
+
body {
|
38
|
+
dialog(parent_shell) {
|
39
|
+
row_layout {
|
40
|
+
type :vertical
|
41
|
+
center true
|
42
|
+
}
|
43
|
+
text 'Tetris'
|
44
|
+
|
45
|
+
tetris_menu_bar(game: game)
|
46
|
+
|
47
|
+
label(:center) {
|
48
|
+
text bind(game, :game_over) {|game_over| game_over ? 'Game Over!' : 'High Scores'}
|
49
|
+
font name: FONT_NAME, height: FONT_TITLE_HEIGHT, style: FONT_TITLE_STYLE
|
50
|
+
}
|
51
|
+
@high_score_table = table {
|
52
|
+
layout_data {
|
53
|
+
height 100
|
54
|
+
}
|
55
|
+
|
56
|
+
table_column {
|
57
|
+
text 'Name'
|
58
|
+
}
|
59
|
+
table_column {
|
60
|
+
text 'Score'
|
61
|
+
}
|
62
|
+
|
63
|
+
items bind(game, :high_scores), column_properties(:name, :score)
|
64
|
+
}
|
65
|
+
composite {
|
66
|
+
row_layout :horizontal
|
67
|
+
|
68
|
+
button {
|
69
|
+
text 'Clear'
|
70
|
+
|
71
|
+
on_widget_selected {
|
72
|
+
game.clear_high_scores!
|
73
|
+
}
|
74
|
+
}
|
75
|
+
@play_close_button = button {
|
76
|
+
text bind(game, :game_over) {|game_over| game_over ? 'Play Again?' : 'Close'}
|
77
|
+
focus true # initial focus
|
78
|
+
|
79
|
+
on_widget_selected {
|
80
|
+
close
|
81
|
+
game.restart! if game.game_over?
|
82
|
+
}
|
83
|
+
}
|
84
|
+
}
|
85
|
+
|
86
|
+
on_swt_show {
|
87
|
+
if game.game_over? && game.added_high_score?
|
88
|
+
game.added_high_score = false
|
89
|
+
@high_score_table.edit_table_item(
|
90
|
+
@high_score_table.items.first, # row item
|
91
|
+
0, # column
|
92
|
+
after_write: -> {
|
93
|
+
game.save_high_scores!
|
94
|
+
@play_close_button.set_focus
|
95
|
+
},
|
96
|
+
after_cancel: -> {
|
97
|
+
@play_close_button.set_focus
|
98
|
+
},
|
99
|
+
)
|
100
|
+
end
|
101
|
+
}
|
102
|
+
|
103
|
+
on_shell_closed {
|
104
|
+
@high_score_table.cancel_edit!
|
105
|
+
}
|
106
|
+
|
107
|
+
on_widget_disposed {
|
108
|
+
@game_over_observer.deregister
|
109
|
+
}
|
110
|
+
}
|
111
|
+
}
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -30,8 +30,8 @@ class Tetris
|
|
30
30
|
options :block_size, :game
|
31
31
|
|
32
32
|
before_body {
|
33
|
-
@font_name =
|
34
|
-
@font_height =
|
33
|
+
@font_name = FONT_NAME
|
34
|
+
@font_height = FONT_TITLE_HEIGHT
|
35
35
|
}
|
36
36
|
|
37
37
|
body {
|
@@ -46,13 +46,13 @@ class Tetris
|
|
46
46
|
}
|
47
47
|
label(:center) {
|
48
48
|
text 'Next'
|
49
|
-
font name: @font_name, height: @font_height, style:
|
49
|
+
font name: @font_name, height: @font_height, style: FONT_TITLE_STYLE
|
50
50
|
}
|
51
51
|
playfield(game_playfield: game.preview_playfield, playfield_width: Model::Game::PREVIEW_PLAYFIELD_WIDTH, playfield_height: Model::Game::PREVIEW_PLAYFIELD_HEIGHT, block_size: block_size)
|
52
52
|
|
53
53
|
label(:center) {
|
54
54
|
text 'Score'
|
55
|
-
font name: @font_name, height: @font_height, style:
|
55
|
+
font name: @font_name, height: @font_height, style: FONT_TITLE_STYLE
|
56
56
|
}
|
57
57
|
label(:center) {
|
58
58
|
text bind(game, :score)
|
@@ -63,7 +63,7 @@ class Tetris
|
|
63
63
|
|
64
64
|
label(:center) {
|
65
65
|
text 'Lines'
|
66
|
-
font name: @font_name, height: @font_height, style:
|
66
|
+
font name: @font_name, height: @font_height, style: FONT_TITLE_STYLE
|
67
67
|
}
|
68
68
|
label(:center) {
|
69
69
|
text bind(game, :lines)
|
@@ -74,7 +74,7 @@ class Tetris
|
|
74
74
|
|
75
75
|
label(:center) {
|
76
76
|
text 'Level'
|
77
|
-
font name: @font_name, height: @font_height, style:
|
77
|
+
font name: @font_name, height: @font_height, style: FONT_TITLE_STYLE
|
78
78
|
}
|
79
79
|
label(:center) {
|
80
80
|
text bind(game, :level)
|
@@ -49,7 +49,6 @@ class Tetris
|
|
49
49
|
menu_item {
|
50
50
|
text '&Restart'
|
51
51
|
accelerator :command, :r
|
52
|
-
enabled bind(game, :game_over, on_read: :!)
|
53
52
|
|
54
53
|
on_widget_selected {
|
55
54
|
game.restart!
|
@@ -64,9 +63,61 @@ class Tetris
|
|
64
63
|
parent_proxy.close
|
65
64
|
}
|
66
65
|
}
|
67
|
-
}
|
66
|
+
} # end of menu
|
67
|
+
|
68
|
+
menu {
|
69
|
+
text '&View'
|
70
|
+
|
71
|
+
menu {
|
72
|
+
text '&High Scores'
|
73
|
+
menu_item {
|
74
|
+
text '&Show'
|
75
|
+
accelerator :command, :shift, :h
|
76
|
+
|
77
|
+
on_widget_selected {
|
78
|
+
parent_custom_shell&.show_high_score_dialog
|
79
|
+
}
|
80
|
+
}
|
81
|
+
menu_item {
|
82
|
+
text '&Clear'
|
83
|
+
accelerator :command, :shift, :c
|
84
|
+
|
85
|
+
on_widget_selected {
|
86
|
+
game.clear_high_scores!
|
87
|
+
}
|
88
|
+
}
|
89
|
+
}
|
90
|
+
} # end of menu
|
91
|
+
|
92
|
+
menu {
|
93
|
+
text '&Options'
|
94
|
+
menu_item(:check) {
|
95
|
+
text '&Beeping'
|
96
|
+
accelerator :command, :b
|
97
|
+
selection bind(game, :beeping)
|
98
|
+
}
|
99
|
+
} # end of menu
|
100
|
+
|
101
|
+
menu {
|
102
|
+
text '&Help'
|
103
|
+
|
104
|
+
menu_item {
|
105
|
+
text '&About'
|
106
|
+
accelerator :command, :shift, :a
|
107
|
+
|
108
|
+
on_widget_selected {
|
109
|
+
parent_custom_shell&.show_about_dialog
|
110
|
+
}
|
111
|
+
}
|
112
|
+
} # end of menu
|
68
113
|
}
|
69
114
|
}
|
115
|
+
|
116
|
+
def parent_custom_shell
|
117
|
+
# grab custom shell widget wrapping parent widget proxy (i.e. Tetris) and invoke method on it
|
118
|
+
the_parent_custom_shell = parent_proxy&.get_data('custom_shell')
|
119
|
+
the_parent_custom_shell if the_parent_custom_shell&.visible?
|
120
|
+
end
|
70
121
|
end
|
71
122
|
end
|
72
123
|
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.3.
|
4
|
+
version: 4.18.3.2
|
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-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -471,9 +471,10 @@ files:
|
|
471
471
|
- samples/elaborate/tetris.rb
|
472
472
|
- samples/elaborate/tetris/model/block.rb
|
473
473
|
- samples/elaborate/tetris/model/game.rb
|
474
|
+
- samples/elaborate/tetris/model/past_game.rb
|
474
475
|
- samples/elaborate/tetris/model/tetromino.rb
|
475
476
|
- samples/elaborate/tetris/view/block.rb
|
476
|
-
- samples/elaborate/tetris/view/
|
477
|
+
- samples/elaborate/tetris/view/high_score_dialog.rb
|
477
478
|
- samples/elaborate/tetris/view/playfield.rb
|
478
479
|
- samples/elaborate/tetris/view/score_lane.rb
|
479
480
|
- samples/elaborate/tetris/view/tetris_menu_bar.rb
|