glimmer-dsl-gtk 0.0.8 → 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/README.md +123 -60
- data/VERSION +1 -1
- data/glimmer-dsl-gtk.gemspec +0 -0
- data/lib/glimmer/gtk/widget_proxy.rb +15 -3
- data/samples/cairo/arc.rb +1 -1
- data/samples/elaborate/tetris/model/game.rb +28 -34
- data/samples/elaborate/tetris.rb +66 -20
- data/samples/elaborate/widget_gallery.rb +18 -7
- data/samples/hello/hello_button.rb +2 -2
- data/samples/hello/hello_entry.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2ab4c99f4b7c76ccba6486f536961778245670be78b77dc7950b38a5215af013
|
4
|
+
data.tar.gz: dcd6cef4cec807cd5d79bd18c91a718f6cd29565b740796fe3c8ef139e7f09a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c04c2ef4ec968d84b731370348175fb662ae5f3891013ba65f450d4a0046491ca60c8528977924e6ecb784be70da1b5d98dce6718bfbc4143f7dd821532cce36
|
7
|
+
data.tar.gz: ae07c805d27a87b307e9d9d31bd5e3ae1074e2c5c16a6275ad842116216f583275631b40c777310458bb6c5f054d1b534132d4a5af4f6c9cb487ae64d814fd56
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 0.0.9
|
4
|
+
|
5
|
+
- Add the text "Next" before the Next Tetromino Preview area
|
6
|
+
- Tetris "Show Next Block Preview" menu item under "View" menu
|
7
|
+
- Tetris "Speed" menu
|
8
|
+
- Fix Tetris Help menu (was called Options by mistake)
|
9
|
+
- Fix issue with Tetris game restarting immediately on game over
|
10
|
+
- Fix issue with Tetris not accelerating upon level ups
|
11
|
+
- Fix warning message: glimmer-dsl-gtk-0.0.8/lib/glimmer/gtk/widget_proxy.rb:192:in `new': 'Gtk::MessageDialog#initialize(parent, flags, type, buttons_type, message)' style has been deprecated. Use 'Gtk::MessageDialog#initialize(:parent => nil, :flags => 0, :type => :info, :buttons => :ok, :message => "")' style.
|
12
|
+
- Fix warning message: Attempting to add a widget with type GtkMenu to a container of type GtkMenuItem, but the widget is already inside a container of type GtkWindow, please remove the widget from its existing container first.
|
13
|
+
|
3
14
|
## 0.0.8
|
4
15
|
|
5
16
|
- Download `images/breaking-blue-wave.png` from web in Cairo examples that use it (`image.rb`, `clip_image.rb`, `image_gradient.rb`) to avoid bloating Ruby gem
|
data/README.md
CHANGED
@@ -1,11 +1,11 @@
|
|
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 GTK 0.0.
|
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 GTK 0.0.9
|
2
2
|
## Ruby-GNOME Desktop Development GUI Library
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/glimmer-dsl-gtk.svg)](http://badge.fury.io/rb/glimmer-dsl-gtk)
|
4
4
|
[![Join the chat at https://gitter.im/AndyObtiva/glimmer](https://badges.gitter.im/AndyObtiva/glimmer.svg)](https://gitter.im/AndyObtiva/glimmer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
5
5
|
|
6
|
-
[Glimmer](https://github.com/AndyObtiva/glimmer) DSL for [GTK](https://www.gtk.org/) enables building desktop applications with [Ruby-GNOME](https://github.com/ruby-gnome/ruby-gnome) (including [Cairo graphics](#declarative-cairo-graphics)).
|
6
|
+
[Glimmer](https://github.com/AndyObtiva/glimmer) DSL for [GTK](https://www.gtk.org/) enables building desktop applications with [Ruby-GNOME](https://github.com/ruby-gnome/ruby-gnome) (including [Cairo graphics](#declarative-cairo-graphics)) using [MRI Ruby](https://www.ruby-lang.org).
|
7
7
|
|
8
|
-
[GTK](https://www.gtk.org/) (aka GIMP-Toolkit or [incorrectly] GNOME-Toolkit) is the premiere desktop GUI toolkit on [Linux](https://www.gtk.org/docs/installations/linux/), which also runs on [Mac](https://www.gtk.org/docs/installations/macos/) ([Quartz GTK+](https://wiki.gnome.org/Projects/GTK/OSX)) and [Windows](https://www.gtk.org/docs/installations/windows).
|
8
|
+
[GTK](https://www.gtk.org/) (aka GIMP-Toolkit or [incorrectly] GNOME-Toolkit) is the premiere desktop GUI toolkit on [Linux](https://www.gtk.org/docs/installations/linux/) (included in [GNOME flavors of Linux](https://www.gnome.org/getting-gnome/), where [Glimmer DSL for GTK](https://rubygems.org/gems/glimmer-dsl-gtk)'s forte is), which also runs on [Mac](https://www.gtk.org/docs/installations/macos/) ([Quartz GTK+](https://wiki.gnome.org/Projects/GTK/OSX)) and [Windows](https://www.gtk.org/docs/installations/windows).
|
9
9
|
|
10
10
|
[Glimmer DSL for GTK](https://rubygems.org/gems/glimmer-dsl-gtk) aims to supercharge productivity and maintainability in developing [Ruby-GNOME](https://github.com/ruby-gnome/ruby-gnome) applications by providing a DSL similar to [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt) having:
|
11
11
|
- Declarative DSL syntax that visually maps to the GUI widget hierarchy
|
@@ -32,19 +32,25 @@ Linux | Mac | Windows
|
|
32
32
|
|
33
33
|
NOTE: Glimmer DSL for GTK is currently in early alpha mode (incomplete proof-of-concept). If you want it developed faster, then [open an issue report](https://github.com/AndyObtiva/glimmer-dsl-gtk/issues/new). I have completed some GitHub project features much faster before due to [issue reports](https://github.com/AndyObtiva/glimmer-dsl-gtk/issues) and [pull requests](https://github.com/AndyObtiva/glimmer-dsl-gtk/pulls). Please help make better by contributing, adopting for small or low risk projects, and providing feedback. It is still an early alpha, so the more feedback and issues you report the better.
|
34
34
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
-
|
40
|
-
-
|
41
|
-
|
35
|
+
**[Glimmer](https://rubygems.org/gems/glimmer) DSL Comparison Table:**
|
36
|
+
DSL | Platforms | Native? | Vector Graphics? | Pros | Cons | Prereqs
|
37
|
+
----|-----------|---------|------------------|------|------|--------
|
38
|
+
[Glimmer DSL for SWT (JRuby Desktop Development GUI Framework)](https://github.com/AndyObtiva/glimmer-dsl-swt) | Mac / Windows / Linux | Yes | Yes (Canvas Shape DSL) | Very Mature / Scaffolding / Native Executable Packaging / Custom Widgets | Slow JRuby Startup Time / Heavy Memory Footprint | Java / JRuby
|
39
|
+
[Glimmer DSL for Opal (Pure Ruby Web GUI and Auto-Webifier of Desktop Apps)](https://github.com/AndyObtiva/glimmer-dsl-opal) | All Web Browsers | No | Yes (Canvas Shape DSL) | Simpler than All JavaScript Technologies / Auto-Webify Desktop Apps | Setup Process / Only Rails 5 Support for Now | Rails
|
40
|
+
[Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development GUI Library)](https://github.com/AndyObtiva/glimmer-dsl-libui) | Mac / Windows / Linux | Yes | Yes (Area API) | Fast Startup Time / Light Memory Footprint | LibUI is an Incomplete Mid-Alpha Only | None Other Than MRI Ruby
|
41
|
+
[Glimmer DSL for Tk (MRI Ruby Desktop Development GUI Library)](https://github.com/AndyObtiva/glimmer-dsl-tk) | Mac / Windows / Linux | Some Native-Themed Widgets (Not Truly Native) | Yes (Canvas) | Fast Startup Time / Light Memory Footprint | Widgets Do Not Look Truly Native, Espcially on Linux | ActiveTcl / MRI Ruby
|
42
|
+
[Glimmer DSL for GTK (Ruby-GNOME Desktop Development GUI Library)](https://github.com/AndyObtiva/glimmer-dsl-gtk) | Mac / Windows / Linux | Only on Linux | Yes (Cairo) | Complete Access to GNOME Features on Linux (Forte) | Not Native on Mac and Windows | None Other Than MRI Ruby on Linux / Brew Packages on Mac / MSYS & MING Toolchains on Windows / MRI Ruby
|
43
|
+
[Glimmer DSL for FX (FOX Toolkit Ruby Desktop Development GUI Library)](https://github.com/AndyObtiva/glimmer-dsl-fx) | Mac (requires XQuartz) / Windows / Linux | No | Yes (Canvas) | No Prerequisites on Windows (Forte Since Binaries Are Included Out of The Box) | Widgets Do Not Look Native / Mac Usage Obtrusively Starts XQuartz | None Other Than MRI Ruby on Windows / XQuarts on Mac / MRI Ruby
|
44
|
+
[Glimmer DSL for JFX (JRuby JavaFX Desktop Development GUI Library)](https://github.com/AndyObtiva/glimmer-dsl-jfx) | Mac / Windows / Linux | No | Yes (javafx.scene.shape and javafx.scene.canvas) | Rich in Custom Widgets | Slow JRuby Startup Time / Heavy Memory Footprint / Widgets Do Not Look Native | Java / JRuby / JavaFX SDK
|
45
|
+
[Glimmer DSL for Swing (JRuby Swing Desktop Development GUI Library)](https://github.com/AndyObtiva/glimmer-dsl-swing) | Mac / Windows / Linux | No | Yes (Java2D) | Very Mature | Slow JRuby Startup Time / Heavy Memory Footprint / Widgets Do Not Look Native | Java / JRuby
|
46
|
+
[Glimmer DSL for XML (& HTML)](https://github.com/AndyObtiva/glimmer-dsl-xml) | All Web Browsers | No | Yes (SVG) | Programmable / Lighter-weight Than Actual XML | XML Elements Are Sometimes Not Well-Named (Many Types of Input) | None
|
47
|
+
[Glimmer DSL for CSS](https://github.com/AndyObtiva/glimmer-dsl-css) | All Web Browsers | No | Yes | Programmable | CSS Is Over-Engineered / Too Many Features To Learn | None
|
42
48
|
|
43
49
|
## Prerequisites
|
44
50
|
|
45
51
|
### Linux
|
46
52
|
|
47
|
-
GNOME-based Linux installations do not need any
|
53
|
+
GNOME-based Linux installations do not need any prerequisites since they have GTK built-in, so you can skip to [Setup](#setup) right away.
|
48
54
|
|
49
55
|
Still, if you run into issues installing the GTK gem in [Setup](#setup), you may try these commands first:
|
50
56
|
```
|
@@ -80,7 +86,7 @@ gem install glimmer-dsl-gtk
|
|
80
86
|
|
81
87
|
Add the following to `Gemfile`:
|
82
88
|
```
|
83
|
-
gem 'glimmer-dsl-gtk', '~> 0.0.
|
89
|
+
gem 'glimmer-dsl-gtk', '~> 0.0.9'
|
84
90
|
```
|
85
91
|
|
86
92
|
And, then run:
|
@@ -156,7 +162,7 @@ In [Glimmer DSL for GTK](https://rubygems.org/gems/glimmer-dsl-gtk), you can dra
|
|
156
162
|
|
157
163
|
Below is a quick tutorial consisting of samples inspired and ported from [Mohit Sindhwani's blog post "Cairo with Ruby - Samples using RCairo"](https://notepad.onghu.com/2021/cairo-samples-in-ruby/).
|
158
164
|
|
159
|
-
|
165
|
+
#### Arc
|
160
166
|
|
161
167
|
[samples/cairo/arc.rb](/samples/cairo/arc.rb)
|
162
168
|
|
@@ -166,7 +172,7 @@ require 'glimmer-dsl-gtk'
|
|
166
172
|
include Glimmer
|
167
173
|
|
168
174
|
window {
|
169
|
-
title '
|
175
|
+
title 'Arc'
|
170
176
|
default_size 256, 256
|
171
177
|
|
172
178
|
drawing_area {
|
@@ -209,7 +215,7 @@ window {
|
|
209
215
|
|
210
216
|
![Arc](/screenshots/glimmer-dsl-gtk-mac-cairo-arc.png)
|
211
217
|
|
212
|
-
|
218
|
+
#### Arc Negative
|
213
219
|
|
214
220
|
[samples/cairo/arc_negative.rb](/samples/cairo/arc_negative.rb)
|
215
221
|
|
@@ -262,7 +268,7 @@ window {
|
|
262
268
|
|
263
269
|
![Arc Negative](/screenshots/glimmer-dsl-gtk-mac-cairo-arc-negative.png)
|
264
270
|
|
265
|
-
|
271
|
+
#### Clip
|
266
272
|
|
267
273
|
[samples/cairo/clip.rb](/samples/cairo/clip.rb)
|
268
274
|
|
@@ -305,7 +311,7 @@ window {
|
|
305
311
|
|
306
312
|
![Clip](/screenshots/glimmer-dsl-gtk-mac-cairo-clip.png)
|
307
313
|
|
308
|
-
|
314
|
+
#### Clip Image
|
309
315
|
|
310
316
|
[samples/cairo/clip_image.rb](/samples/cairo/clip_image.rb)
|
311
317
|
|
@@ -347,7 +353,7 @@ window {
|
|
347
353
|
|
348
354
|
![Clip Image](/screenshots/glimmer-dsl-gtk-mac-cairo-clip-image.png)
|
349
355
|
|
350
|
-
|
356
|
+
#### Curve to
|
351
357
|
|
352
358
|
[samples/cairo/curve_to.rb](/samples/cairo/curve_to.rb)
|
353
359
|
|
@@ -395,7 +401,7 @@ window {
|
|
395
401
|
|
396
402
|
![Curve to](/screenshots/glimmer-dsl-gtk-mac-cairo-curve-to.png)
|
397
403
|
|
398
|
-
|
404
|
+
#### Dashes
|
399
405
|
|
400
406
|
[samples/cairo/dashes.rb](/samples/cairo/dashes.rb)
|
401
407
|
|
@@ -434,7 +440,7 @@ window {
|
|
434
440
|
|
435
441
|
![Dashes](/screenshots/glimmer-dsl-gtk-mac-cairo-dashes.png)
|
436
442
|
|
437
|
-
|
443
|
+
#### Fill and Stroke 2
|
438
444
|
|
439
445
|
(note: there is no Fill and Stroke 1; this was adopted from [Mohit's blog post](https://notepad.onghu.com/2021/cairo-samples-in-ruby/), which only mentioned Fill and Stroke 2)
|
440
446
|
|
@@ -481,7 +487,7 @@ window {
|
|
481
487
|
|
482
488
|
![Fill and Stroke 2](/screenshots/glimmer-dsl-gtk-mac-cairo-fill-and-stroke2.png)
|
483
489
|
|
484
|
-
|
490
|
+
#### Fill Style
|
485
491
|
|
486
492
|
[samples/cairo/fill_style.rb](/samples/cairo/fill_style.rb)
|
487
493
|
|
@@ -533,7 +539,7 @@ window {
|
|
533
539
|
|
534
540
|
![Fill Style](/screenshots/glimmer-dsl-gtk-mac-cairo-fill-style.png)
|
535
541
|
|
536
|
-
|
542
|
+
#### Gradient
|
537
543
|
|
538
544
|
[samples/cairo/gradient.rb](/samples/cairo/gradient.rb)
|
539
545
|
|
@@ -573,7 +579,7 @@ window {
|
|
573
579
|
|
574
580
|
![Gradient](/screenshots/glimmer-dsl-gtk-mac-cairo-gradient.png)
|
575
581
|
|
576
|
-
|
582
|
+
#### Image
|
577
583
|
|
578
584
|
[samples/cairo/image.rb](/samples/cairo/image.rb)
|
579
585
|
|
@@ -610,7 +616,7 @@ window {
|
|
610
616
|
|
611
617
|
![Image](/screenshots/glimmer-dsl-gtk-mac-cairo-image.png)
|
612
618
|
|
613
|
-
|
619
|
+
#### Image Gradient
|
614
620
|
|
615
621
|
[samples/cairo/image_gradient.rb](/samples/cairo/image_gradient.rb)
|
616
622
|
|
@@ -656,7 +662,7 @@ window {
|
|
656
662
|
|
657
663
|
![Image Gradient](/screenshots/glimmer-dsl-gtk-mac-cairo-image-gradient.png)
|
658
664
|
|
659
|
-
|
665
|
+
#### Multi Segment Caps
|
660
666
|
|
661
667
|
[samples/cairo/multi_segment_caps.rb](/samples/cairo/multi_segment_caps.rb)
|
662
668
|
|
@@ -692,7 +698,7 @@ window {
|
|
692
698
|
|
693
699
|
![Multi Segment Caps](/screenshots/glimmer-dsl-gtk-mac-cairo-multi-segment-caps.png)
|
694
700
|
|
695
|
-
|
701
|
+
#### Rounded Rectangle
|
696
702
|
|
697
703
|
[samples/cairo/rounded_rectangle.rb](/samples/cairo/rounded_rectangle.rb)
|
698
704
|
|
@@ -721,7 +727,7 @@ window {
|
|
721
727
|
|
722
728
|
![Rounded Rectangle](/screenshots/glimmer-dsl-gtk-mac-cairo-rounded-rectangle.png)
|
723
729
|
|
724
|
-
|
730
|
+
#### Set line cap
|
725
731
|
|
726
732
|
[samples/cairo/set_line_cap.rb](/samples/cairo/set_line_cap.rb)
|
727
733
|
|
@@ -783,7 +789,7 @@ window {
|
|
783
789
|
|
784
790
|
![Set line cap](/screenshots/glimmer-dsl-gtk-mac-cairo-set-line-cap.png)
|
785
791
|
|
786
|
-
|
792
|
+
#### Set line join
|
787
793
|
|
788
794
|
[samples/cairo/set_line_join.rb](/samples/cairo/set_line_join.rb)
|
789
795
|
|
@@ -835,7 +841,7 @@ window {
|
|
835
841
|
|
836
842
|
![Set line join](/screenshots/glimmer-dsl-gtk-mac-cairo-set-line-join.png)
|
837
843
|
|
838
|
-
|
844
|
+
#### Text
|
839
845
|
|
840
846
|
[samples/cairo/text.rb](/samples/cairo/text.rb)
|
841
847
|
|
@@ -1016,9 +1022,9 @@ include Glimmer
|
|
1016
1022
|
window { |w|
|
1017
1023
|
title 'Hello, Button!'
|
1018
1024
|
|
1019
|
-
button('Button') {
|
1025
|
+
button(label: 'Button') {
|
1020
1026
|
on(:clicked) do
|
1021
|
-
message_dialog(w) { |md|
|
1027
|
+
message_dialog(parent: w) { |md|
|
1022
1028
|
title 'Information'
|
1023
1029
|
text 'You clicked the button'
|
1024
1030
|
|
@@ -1070,9 +1076,9 @@ window { |w|
|
|
1070
1076
|
end
|
1071
1077
|
}
|
1072
1078
|
|
1073
|
-
button('Button') {
|
1079
|
+
button(label: 'Button') {
|
1074
1080
|
on(:clicked) do
|
1075
|
-
message_dialog(w) { |md|
|
1081
|
+
message_dialog(parent: w) { |md|
|
1076
1082
|
title 'You entered'
|
1077
1083
|
text e.text
|
1078
1084
|
|
@@ -1394,7 +1400,7 @@ include Glimmer
|
|
1394
1400
|
|
1395
1401
|
application('org.glimmer.hello-application') {
|
1396
1402
|
on(:activate) do |app|
|
1397
|
-
application_window(app) {
|
1403
|
+
application_window(app) { |aw|
|
1398
1404
|
title 'Widget Gallery'
|
1399
1405
|
|
1400
1406
|
notebook { |n|
|
@@ -1436,13 +1442,24 @@ application('org.glimmer.hello-application') {
|
|
1436
1442
|
spacing 10
|
1437
1443
|
|
1438
1444
|
label('Button')
|
1439
|
-
button('Push Me')
|
1445
|
+
button(label: 'Push Me') {
|
1446
|
+
on(:clicked) do
|
1447
|
+
message_dialog(parent: aw) { |md|
|
1448
|
+
title 'Information'
|
1449
|
+
text 'You clicked the button'
|
1450
|
+
|
1451
|
+
on(:response) do
|
1452
|
+
md.destroy
|
1453
|
+
end
|
1454
|
+
}.show
|
1455
|
+
end
|
1456
|
+
}
|
1440
1457
|
|
1441
1458
|
label('Radio Button')
|
1442
1459
|
box(:horizontal) {
|
1443
|
-
rb = radio_button('One')
|
1444
|
-
radio_button(
|
1445
|
-
radio_button(
|
1460
|
+
rb = radio_button(label: 'One')
|
1461
|
+
radio_button(label: 'Two', member: rb)
|
1462
|
+
radio_button(label: 'Three', member: rb)
|
1446
1463
|
}
|
1447
1464
|
|
1448
1465
|
label('Check Button')
|
@@ -1464,12 +1481,12 @@ application('org.glimmer.hello-application') {
|
|
1464
1481
|
spacing 10
|
1465
1482
|
|
1466
1483
|
label('Horizontal Scale')
|
1467
|
-
|
1484
|
+
scale(:horizontal, 1, 100, 1) {
|
1468
1485
|
visible true
|
1469
1486
|
}
|
1470
1487
|
|
1471
1488
|
label('Vertical Scale')
|
1472
|
-
|
1489
|
+
scale(:vertical, 1, 100, 1) {
|
1473
1490
|
visible true
|
1474
1491
|
height_request 200
|
1475
1492
|
}
|
@@ -1650,17 +1667,32 @@ class Tetris
|
|
1650
1667
|
|
1651
1668
|
Model::Game::PREVIEW_PLAYFIELD_HEIGHT.times do |row|
|
1652
1669
|
Model::Game::PREVIEW_PLAYFIELD_WIDTH.times do |column|
|
1653
|
-
|
1654
|
-
color = new_color
|
1670
|
+
preview_updater = proc do
|
1655
1671
|
block = @preview_playfield_blocks[row][column]
|
1656
|
-
|
1657
|
-
|
1658
|
-
|
1659
|
-
|
1660
|
-
|
1661
|
-
|
1672
|
+
if @game.show_preview_tetromino?
|
1673
|
+
new_color = @game.preview_playfield[row][column].color
|
1674
|
+
block[:background_square].fill = new_color
|
1675
|
+
block[:top_bevel_edge].fill = [new_color[0] + 4*BEVEL_CONSTANT, new_color[1] + 4*BEVEL_CONSTANT, new_color[2] + 4*BEVEL_CONSTANT]
|
1676
|
+
block[:right_bevel_edge].fill = [new_color[0] - BEVEL_CONSTANT, new_color[1] - BEVEL_CONSTANT, new_color[2] - BEVEL_CONSTANT]
|
1677
|
+
block[:bottom_bevel_edge].fill = [new_color[0] - BEVEL_CONSTANT, new_color[1] - BEVEL_CONSTANT, new_color[2] - BEVEL_CONSTANT]
|
1678
|
+
block[:left_bevel_edge].fill = [new_color[0] - BEVEL_CONSTANT, new_color[1] - BEVEL_CONSTANT, new_color[2] - BEVEL_CONSTANT]
|
1679
|
+
block[:border_square].stroke = new_color == Model::Block::COLOR_CLEAR ? COLOR_GRAY : new_color
|
1680
|
+
@next_label.text = 'Next'
|
1681
|
+
else
|
1682
|
+
transparent_color = [0, 0, 0, 0]
|
1683
|
+
block[:background_square].fill = transparent_color
|
1684
|
+
block[:top_bevel_edge].fill = transparent_color
|
1685
|
+
block[:right_bevel_edge].fill = transparent_color
|
1686
|
+
block[:bottom_bevel_edge].fill = transparent_color
|
1687
|
+
block[:left_bevel_edge].fill = transparent_color
|
1688
|
+
block[:border_square].stroke = transparent_color
|
1689
|
+
@next_label.text = ''
|
1690
|
+
end
|
1662
1691
|
block[:drawing_area].queue_draw
|
1663
1692
|
end
|
1693
|
+
|
1694
|
+
observe(@game.preview_playfield[row][column], :color, &preview_updater)
|
1695
|
+
observe(@game, :show_preview_tetromino, &preview_updater)
|
1664
1696
|
end
|
1665
1697
|
end
|
1666
1698
|
|
@@ -1706,6 +1738,16 @@ class Tetris
|
|
1706
1738
|
|
1707
1739
|
menu_item(label: 'View') { |mi|
|
1708
1740
|
m = menu {
|
1741
|
+
check_menu_item(label: 'Show Next Block Preview') {
|
1742
|
+
active @game.show_preview_tetromino?
|
1743
|
+
|
1744
|
+
on(:activate) do
|
1745
|
+
@game.show_preview_tetromino = !@game.show_preview_tetromino?
|
1746
|
+
end
|
1747
|
+
}
|
1748
|
+
|
1749
|
+
separator_menu_item
|
1750
|
+
|
1709
1751
|
menu_item(label: 'Show High Scores') {
|
1710
1752
|
on(:activate) do
|
1711
1753
|
show_high_score_dialog
|
@@ -1721,6 +1763,27 @@ class Tetris
|
|
1721
1763
|
mi.submenu = m.gtk
|
1722
1764
|
}
|
1723
1765
|
|
1766
|
+
menu_item(label: 'Speed') { |mi|
|
1767
|
+
m = menu {
|
1768
|
+
rmi = radio_menu_item(nil, Model::Game::SPEEDS.first.to_s.capitalize) {
|
1769
|
+
active true
|
1770
|
+
|
1771
|
+
on(:activate) do
|
1772
|
+
@game.send("speed_#{Model::Game::SPEEDS.first}=", true)
|
1773
|
+
end
|
1774
|
+
}
|
1775
|
+
|
1776
|
+
Model::Game::SPEEDS.drop(1).each do |speed|
|
1777
|
+
radio_menu_item(rmi.group, speed.to_s.capitalize) {
|
1778
|
+
on(:activate) do
|
1779
|
+
@game.send("speed_#{speed}=", true)
|
1780
|
+
end
|
1781
|
+
}
|
1782
|
+
end
|
1783
|
+
}
|
1784
|
+
mi.submenu = m.gtk
|
1785
|
+
}
|
1786
|
+
|
1724
1787
|
menu_item(label: 'Options') { |mi|
|
1725
1788
|
m = menu {
|
1726
1789
|
rmi = radio_menu_item(nil, 'Instant Down on Up') {
|
@@ -1745,7 +1808,7 @@ class Tetris
|
|
1745
1808
|
mi.submenu = m.gtk
|
1746
1809
|
}
|
1747
1810
|
|
1748
|
-
menu_item(label: '
|
1811
|
+
menu_item(label: 'Help') { |mi|
|
1749
1812
|
m = menu {
|
1750
1813
|
menu_item(label: 'About') {
|
1751
1814
|
on(:activate) do
|
@@ -1761,6 +1824,7 @@ class Tetris
|
|
1761
1824
|
def score_board
|
1762
1825
|
box(:vertical) {
|
1763
1826
|
label
|
1827
|
+
@next_label = label('Next')
|
1764
1828
|
@preview_playfield_blocks = playfield(playfield_width: Model::Game::PREVIEW_PLAYFIELD_WIDTH, playfield_height: Model::Game::PREVIEW_PLAYFIELD_HEIGHT, block_size: BLOCK_SIZE)
|
1765
1829
|
|
1766
1830
|
label
|
@@ -1834,29 +1898,29 @@ class Tetris
|
|
1834
1898
|
def start_moving_tetrominos_down
|
1835
1899
|
unless @tetrominos_start_moving_down
|
1836
1900
|
@tetrominos_start_moving_down = true
|
1837
|
-
|
1901
|
+
tetromino_move = proc do
|
1838
1902
|
@game.down! if !@game.game_over? && !@game.paused?
|
1839
|
-
|
1903
|
+
GLib::Timeout.add(@game.delay*1000, &tetromino_move)
|
1904
|
+
false # do not repeat
|
1840
1905
|
end
|
1906
|
+
GLib::Timeout.add(@game.delay*1000, &tetromino_move)
|
1841
1907
|
end
|
1842
1908
|
end
|
1843
1909
|
|
1844
1910
|
def show_game_over_dialog
|
1845
|
-
|
1911
|
+
@game.paused = true
|
1912
|
+
message_dialog(parent: @main_window) { |md|
|
1846
1913
|
title 'Game Over!'
|
1847
1914
|
text "Score: #{@game.high_scores.first.score}\nLines: #{@game.high_scores.first.lines}\nLevel: #{@game.high_scores.first.level}"
|
1848
1915
|
|
1849
1916
|
on(:response) do
|
1917
|
+
@game.restart!
|
1850
1918
|
md.destroy
|
1851
1919
|
end
|
1852
1920
|
}.show
|
1853
|
-
|
1854
|
-
@game.restart!
|
1855
|
-
false
|
1856
1921
|
end
|
1857
1922
|
|
1858
1923
|
def show_high_score_dialog
|
1859
|
-
game_paused = !!@game.paused
|
1860
1924
|
@game.paused = true
|
1861
1925
|
|
1862
1926
|
if @game.high_scores.empty?
|
@@ -1867,20 +1931,19 @@ class Tetris
|
|
1867
1931
|
end.join("\n")
|
1868
1932
|
end
|
1869
1933
|
|
1870
|
-
message_dialog(@main_window) { |md|
|
1934
|
+
message_dialog(parent: @main_window) { |md|
|
1871
1935
|
title 'High Scores'
|
1872
1936
|
text high_scores_string
|
1873
1937
|
|
1874
1938
|
on(:response) do
|
1939
|
+
@game.paused = false
|
1875
1940
|
md.destroy
|
1876
1941
|
end
|
1877
1942
|
}.show
|
1878
|
-
|
1879
|
-
@game.paused = game_paused
|
1880
1943
|
end
|
1881
1944
|
|
1882
1945
|
def show_about_dialog
|
1883
|
-
message_dialog(@main_window) { |md|
|
1946
|
+
message_dialog(parent: @main_window) { |md|
|
1884
1947
|
title 'About'
|
1885
1948
|
text "Glimmer Tetris\n\nGlimmer DSL for GTK\n\nElaborate Sample\n\nCopyright (c) 2021-2022 Andy Maleh"
|
1886
1949
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.9
|
data/glimmer-dsl-gtk.gemspec
CHANGED
Binary file
|
@@ -147,7 +147,7 @@ module Glimmer
|
|
147
147
|
|
148
148
|
# Subclasses may override to perform post initialization work on an added child (normally must also call super)
|
149
149
|
def post_initialize_child(child)
|
150
|
-
@gtk.add(child.gtk) if @gtk.respond_to?(:add)
|
150
|
+
@gtk.add(child.gtk) if @gtk.respond_to?(:add) # && child.keyword != 'menu' # TODO consider moving this code to a MenuProxy
|
151
151
|
child.gtk&.show if child.gtk&.respond_to?(:show)
|
152
152
|
end
|
153
153
|
|
@@ -193,8 +193,20 @@ module Glimmer
|
|
193
193
|
end
|
194
194
|
|
195
195
|
def normalize_args(args)
|
196
|
-
args.
|
197
|
-
|
196
|
+
if args.size == 1 && args.first.is_a?(Hash)
|
197
|
+
hash_arg = args.first
|
198
|
+
hash_arg = Hash[hash_arg.map do |key, value|
|
199
|
+
normalized_value = value.respond_to?(:gtk) ? value.gtk : value
|
200
|
+
[key, normalized_value]
|
201
|
+
end]
|
202
|
+
args[0] = hash_arg
|
203
|
+
args
|
204
|
+
elsif args.is_a?(Array)
|
205
|
+
args.map do |arg|
|
206
|
+
arg.is_a?(WidgetProxy) ? arg.gtk : arg
|
207
|
+
end
|
208
|
+
else
|
209
|
+
args
|
198
210
|
end
|
199
211
|
end
|
200
212
|
end
|
data/samples/cairo/arc.rb
CHANGED
@@ -36,21 +36,27 @@ class Tetris
|
|
36
36
|
PREVIEW_PLAYFIELD_WIDTH = 4
|
37
37
|
PREVIEW_PLAYFIELD_HEIGHT = 2
|
38
38
|
SCORE_MULTIPLIER = {1 => 40, 2 => 100, 3 => 300, 4 => 1200}
|
39
|
+
UP_ARROW_ACTIONS = %i[instant_down rotate_right rotate_left]
|
40
|
+
SPEEDS = %i[snail sloth turtle rabbit gorilla bear horse gazelle cheetah falcon]
|
41
|
+
SPEED_INITIAL_DELAYS = SPEEDS.each_with_index.inject({}) {|hash, speed_index_pair| hash.merge(speed_index_pair.first => 1.1 - speed_index_pair.last*(0.1)) }
|
39
42
|
|
40
43
|
attr_reader :playfield_width, :playfield_height
|
41
|
-
attr_accessor :game_over, :paused, :preview_tetromino, :lines, :score, :level, :high_scores, :beeping, :added_high_score, :show_high_scores, :up_arrow_action
|
44
|
+
attr_accessor :game_over, :paused, :preview_tetromino, :lines, :score, :level, :high_scores, :beeping, :added_high_score, :show_high_scores, :up_arrow_action, :show_preview_tetromino, :initial_delay
|
42
45
|
alias game_over? game_over
|
43
46
|
alias paused? paused
|
44
47
|
alias beeping? beeping
|
45
48
|
alias added_high_score? added_high_score
|
49
|
+
alias show_preview_tetromino? show_preview_tetromino
|
46
50
|
|
47
51
|
def initialize(playfield_width = PLAYFIELD_WIDTH, playfield_height = PLAYFIELD_HEIGHT)
|
52
|
+
@initial_delay = SPEED_INITIAL_DELAYS[:snail]
|
48
53
|
@playfield_width = playfield_width
|
49
54
|
@playfield_height = playfield_height
|
50
55
|
@high_scores = []
|
51
56
|
@show_high_scores = false
|
52
57
|
@beeping = true
|
53
58
|
@up_arrow_action = :rotate_left
|
59
|
+
@show_preview_tetromino = true
|
54
60
|
load_high_scores!
|
55
61
|
end
|
56
62
|
|
@@ -200,47 +206,35 @@ class Tetris
|
|
200
206
|
end
|
201
207
|
|
202
208
|
def delay
|
203
|
-
[
|
209
|
+
[@initial_delay - (level.to_i * 0.1), 0.001].max
|
204
210
|
end
|
205
211
|
|
206
212
|
def beep
|
207
213
|
@beeper&.call if beeping
|
208
214
|
end
|
209
215
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
def instant_down_on_up!
|
219
|
-
self.up_arrow_action = :instant_down
|
220
|
-
end
|
221
|
-
|
222
|
-
def rotate_right_on_up=(value)
|
223
|
-
self.up_arrow_action = :rotate_right if value
|
224
|
-
end
|
225
|
-
|
226
|
-
def rotate_right_on_up
|
227
|
-
self.up_arrow_action == :rotate_right
|
228
|
-
end
|
229
|
-
|
230
|
-
def rotate_right_on_up!
|
231
|
-
self.up_arrow_action = :rotate_right
|
232
|
-
end
|
233
|
-
|
234
|
-
def rotate_left_on_up=(value)
|
235
|
-
self.up_arrow_action = :rotate_left if value
|
236
|
-
end
|
237
|
-
|
238
|
-
def rotate_left_on_up
|
239
|
-
self.up_arrow_action == :rotate_left
|
216
|
+
SPEED_INITIAL_DELAYS.each do |speed, speed_initial_day|
|
217
|
+
define_method("speed_#{speed}=") do |is_true|
|
218
|
+
self.initial_delay = speed_initial_day if is_true
|
219
|
+
end
|
220
|
+
|
221
|
+
define_method("speed_#{speed}") do
|
222
|
+
self.initial_delay == speed_initial_day
|
223
|
+
end
|
240
224
|
end
|
241
225
|
|
242
|
-
|
243
|
-
|
226
|
+
UP_ARROW_ACTIONS.each do |up_arrow_action_symbol|
|
227
|
+
define_method("#{up_arrow_action_symbol}_on_up=") do |is_true|
|
228
|
+
self.up_arrow_action = up_arrow_action_symbol if is_true
|
229
|
+
end
|
230
|
+
|
231
|
+
define_method("#{up_arrow_action_symbol}_on_up") do
|
232
|
+
self.up_arrow_action == up_arrow_action_symbol
|
233
|
+
end
|
234
|
+
|
235
|
+
define_method("#{up_arrow_action_symbol}_on_up!") do
|
236
|
+
self.up_arrow_action = up_arrow_action_symbol
|
237
|
+
end
|
244
238
|
end
|
245
239
|
|
246
240
|
def reset_tetrominoes
|
data/samples/elaborate/tetris.rb
CHANGED
@@ -94,17 +94,32 @@ class Tetris
|
|
94
94
|
|
95
95
|
Model::Game::PREVIEW_PLAYFIELD_HEIGHT.times do |row|
|
96
96
|
Model::Game::PREVIEW_PLAYFIELD_WIDTH.times do |column|
|
97
|
-
|
98
|
-
color = new_color
|
97
|
+
preview_updater = proc do
|
99
98
|
block = @preview_playfield_blocks[row][column]
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
99
|
+
if @game.show_preview_tetromino?
|
100
|
+
new_color = @game.preview_playfield[row][column].color
|
101
|
+
block[:background_square].fill = new_color
|
102
|
+
block[:top_bevel_edge].fill = [new_color[0] + 4*BEVEL_CONSTANT, new_color[1] + 4*BEVEL_CONSTANT, new_color[2] + 4*BEVEL_CONSTANT]
|
103
|
+
block[:right_bevel_edge].fill = [new_color[0] - BEVEL_CONSTANT, new_color[1] - BEVEL_CONSTANT, new_color[2] - BEVEL_CONSTANT]
|
104
|
+
block[:bottom_bevel_edge].fill = [new_color[0] - BEVEL_CONSTANT, new_color[1] - BEVEL_CONSTANT, new_color[2] - BEVEL_CONSTANT]
|
105
|
+
block[:left_bevel_edge].fill = [new_color[0] - BEVEL_CONSTANT, new_color[1] - BEVEL_CONSTANT, new_color[2] - BEVEL_CONSTANT]
|
106
|
+
block[:border_square].stroke = new_color == Model::Block::COLOR_CLEAR ? COLOR_GRAY : new_color
|
107
|
+
@next_label.text = 'Next'
|
108
|
+
else
|
109
|
+
transparent_color = [0, 0, 0, 0]
|
110
|
+
block[:background_square].fill = transparent_color
|
111
|
+
block[:top_bevel_edge].fill = transparent_color
|
112
|
+
block[:right_bevel_edge].fill = transparent_color
|
113
|
+
block[:bottom_bevel_edge].fill = transparent_color
|
114
|
+
block[:left_bevel_edge].fill = transparent_color
|
115
|
+
block[:border_square].stroke = transparent_color
|
116
|
+
@next_label.text = ''
|
117
|
+
end
|
106
118
|
block[:drawing_area].queue_draw
|
107
119
|
end
|
120
|
+
|
121
|
+
observe(@game.preview_playfield[row][column], :color, &preview_updater)
|
122
|
+
observe(@game, :show_preview_tetromino, &preview_updater)
|
108
123
|
end
|
109
124
|
end
|
110
125
|
|
@@ -150,6 +165,16 @@ class Tetris
|
|
150
165
|
|
151
166
|
menu_item(label: 'View') { |mi|
|
152
167
|
m = menu {
|
168
|
+
check_menu_item(label: 'Show Next Block Preview') {
|
169
|
+
active @game.show_preview_tetromino?
|
170
|
+
|
171
|
+
on(:activate) do
|
172
|
+
@game.show_preview_tetromino = !@game.show_preview_tetromino?
|
173
|
+
end
|
174
|
+
}
|
175
|
+
|
176
|
+
separator_menu_item
|
177
|
+
|
153
178
|
menu_item(label: 'Show High Scores') {
|
154
179
|
on(:activate) do
|
155
180
|
show_high_score_dialog
|
@@ -165,6 +190,27 @@ class Tetris
|
|
165
190
|
mi.submenu = m.gtk
|
166
191
|
}
|
167
192
|
|
193
|
+
menu_item(label: 'Speed') { |mi|
|
194
|
+
m = menu {
|
195
|
+
rmi = radio_menu_item(nil, Model::Game::SPEEDS.first.to_s.capitalize) {
|
196
|
+
active true
|
197
|
+
|
198
|
+
on(:activate) do
|
199
|
+
@game.send("speed_#{Model::Game::SPEEDS.first}=", true)
|
200
|
+
end
|
201
|
+
}
|
202
|
+
|
203
|
+
Model::Game::SPEEDS.drop(1).each do |speed|
|
204
|
+
radio_menu_item(rmi.group, speed.to_s.capitalize) {
|
205
|
+
on(:activate) do
|
206
|
+
@game.send("speed_#{speed}=", true)
|
207
|
+
end
|
208
|
+
}
|
209
|
+
end
|
210
|
+
}
|
211
|
+
mi.submenu = m.gtk
|
212
|
+
}
|
213
|
+
|
168
214
|
menu_item(label: 'Options') { |mi|
|
169
215
|
m = menu {
|
170
216
|
rmi = radio_menu_item(nil, 'Instant Down on Up') {
|
@@ -189,7 +235,7 @@ class Tetris
|
|
189
235
|
mi.submenu = m.gtk
|
190
236
|
}
|
191
237
|
|
192
|
-
menu_item(label: '
|
238
|
+
menu_item(label: 'Help') { |mi|
|
193
239
|
m = menu {
|
194
240
|
menu_item(label: 'About') {
|
195
241
|
on(:activate) do
|
@@ -205,6 +251,7 @@ class Tetris
|
|
205
251
|
def score_board
|
206
252
|
box(:vertical) {
|
207
253
|
label
|
254
|
+
@next_label = label('Next')
|
208
255
|
@preview_playfield_blocks = playfield(playfield_width: Model::Game::PREVIEW_PLAYFIELD_WIDTH, playfield_height: Model::Game::PREVIEW_PLAYFIELD_HEIGHT, block_size: BLOCK_SIZE)
|
209
256
|
|
210
257
|
label
|
@@ -278,29 +325,29 @@ class Tetris
|
|
278
325
|
def start_moving_tetrominos_down
|
279
326
|
unless @tetrominos_start_moving_down
|
280
327
|
@tetrominos_start_moving_down = true
|
281
|
-
|
328
|
+
tetromino_move = proc do
|
282
329
|
@game.down! if !@game.game_over? && !@game.paused?
|
283
|
-
|
330
|
+
GLib::Timeout.add(@game.delay*1000, &tetromino_move)
|
331
|
+
false # do not repeat
|
284
332
|
end
|
333
|
+
GLib::Timeout.add(@game.delay*1000, &tetromino_move)
|
285
334
|
end
|
286
335
|
end
|
287
336
|
|
288
337
|
def show_game_over_dialog
|
289
|
-
|
338
|
+
@game.paused = true
|
339
|
+
message_dialog(parent: @main_window) { |md|
|
290
340
|
title 'Game Over!'
|
291
341
|
text "Score: #{@game.high_scores.first.score}\nLines: #{@game.high_scores.first.lines}\nLevel: #{@game.high_scores.first.level}"
|
292
342
|
|
293
343
|
on(:response) do
|
344
|
+
@game.restart!
|
294
345
|
md.destroy
|
295
346
|
end
|
296
347
|
}.show
|
297
|
-
|
298
|
-
@game.restart!
|
299
|
-
false
|
300
348
|
end
|
301
349
|
|
302
350
|
def show_high_score_dialog
|
303
|
-
game_paused = !!@game.paused
|
304
351
|
@game.paused = true
|
305
352
|
|
306
353
|
if @game.high_scores.empty?
|
@@ -311,20 +358,19 @@ class Tetris
|
|
311
358
|
end.join("\n")
|
312
359
|
end
|
313
360
|
|
314
|
-
message_dialog(@main_window) { |md|
|
361
|
+
message_dialog(parent: @main_window) { |md|
|
315
362
|
title 'High Scores'
|
316
363
|
text high_scores_string
|
317
364
|
|
318
365
|
on(:response) do
|
366
|
+
@game.paused = false
|
319
367
|
md.destroy
|
320
368
|
end
|
321
369
|
}.show
|
322
|
-
|
323
|
-
@game.paused = game_paused
|
324
370
|
end
|
325
371
|
|
326
372
|
def show_about_dialog
|
327
|
-
message_dialog(@main_window) { |md|
|
373
|
+
message_dialog(parent: @main_window) { |md|
|
328
374
|
title 'About'
|
329
375
|
text "Glimmer Tetris\n\nGlimmer DSL for GTK\n\nElaborate Sample\n\nCopyright (c) 2021-2022 Andy Maleh"
|
330
376
|
|
@@ -4,7 +4,7 @@ include Glimmer
|
|
4
4
|
|
5
5
|
application('org.glimmer.hello-application') {
|
6
6
|
on(:activate) do |app|
|
7
|
-
application_window(app) {
|
7
|
+
application_window(app) { |aw|
|
8
8
|
title 'Widget Gallery'
|
9
9
|
|
10
10
|
notebook { |n|
|
@@ -46,13 +46,24 @@ application('org.glimmer.hello-application') {
|
|
46
46
|
spacing 10
|
47
47
|
|
48
48
|
label('Button')
|
49
|
-
button('Push Me')
|
49
|
+
button(label: 'Push Me') {
|
50
|
+
on(:clicked) do
|
51
|
+
message_dialog(parent: aw) { |md|
|
52
|
+
title 'Information'
|
53
|
+
text 'You clicked the button'
|
54
|
+
|
55
|
+
on(:response) do
|
56
|
+
md.destroy
|
57
|
+
end
|
58
|
+
}.show
|
59
|
+
end
|
60
|
+
}
|
50
61
|
|
51
62
|
label('Radio Button')
|
52
63
|
box(:horizontal) {
|
53
|
-
rb = radio_button('One')
|
54
|
-
radio_button(
|
55
|
-
radio_button(
|
64
|
+
rb = radio_button(label: 'One')
|
65
|
+
radio_button(label: 'Two', member: rb)
|
66
|
+
radio_button(label: 'Three', member: rb)
|
56
67
|
}
|
57
68
|
|
58
69
|
label('Check Button')
|
@@ -74,12 +85,12 @@ application('org.glimmer.hello-application') {
|
|
74
85
|
spacing 10
|
75
86
|
|
76
87
|
label('Horizontal Scale')
|
77
|
-
|
88
|
+
scale(:horizontal, 1, 100, 1) {
|
78
89
|
visible true
|
79
90
|
}
|
80
91
|
|
81
92
|
label('Vertical Scale')
|
82
|
-
|
93
|
+
scale(:vertical, 1, 100, 1) {
|
83
94
|
visible true
|
84
95
|
height_request 200
|
85
96
|
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: glimmer-dsl-gtk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Maleh
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: glimmer
|