glimmer-dsl-swt 4.18.3.3 → 4.18.3.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 59c5aae689604e6024a5bffb1053cd50cc05c1598dca6fc3a01510f17371deab
4
- data.tar.gz: 5fc97483b96bf334b1e25b30b8455ad41af3e6f56ae6f5310ac31504ce87c41d
3
+ metadata.gz: 63410b8b302bc061b5089d24bcadaacbd54b83bbb581ffecd0a46c7c026329c1
4
+ data.tar.gz: 60da9c410a221130713e209c0e6127d3e04f17feccbcb29788c2234a90802bb9
5
5
  SHA512:
6
- metadata.gz: fdf5681c5632aa64d15c9e2037757d4e7599fbcaeacc14acc1af1dd1669c205ca7a8730551277ae0a3cff5bb435a802dcbdb824e7dbc749f75471ba15079e999
7
- data.tar.gz: 5f96f41c1bdd491da20ae87ad1b2a5f072eeaca78c6e8f15a1a942390c2cc23b07259465452b242e0d61111a6881954458b5fe5214d77bfd4f45dd365ae0eb14
6
+ metadata.gz: 81a1feac2ef1bf9c7329d26714d0d7c61b926f710a785f0b7d2e1a424b2548cf159604ada03f368996c99cb45d0834bb362a715cbfae0fa5ec1b4e5af659ee8b
7
+ data.tar.gz: a4c1e06cf9aa7f3b656e9d5d22d56883f1def62865b1aa56555041c8238c07e0f333f17cd6f6108ada800e1738294f148757752e4609e1dd34dcbdc8183bd1ba
@@ -1,8 +1,16 @@
1
1
  # Change Log
2
2
 
3
+ ### 4.18.3.4
4
+
5
+ - Support building Image objects with the Glimmer Canvas Shape DSL
6
+ - Tetris build icon image in-game by nesting Glimmer Shape DSL syntax
7
+ - Canvas Make shapes auto-fill if you specify a background only (no need to say fill: true) or not fill if you specify a foreground only
8
+ - Tetris option to switch Up Arrow between Instant Down, Rotate Right, and Rotate Left
9
+
3
10
  ### 4.18.3.3
4
11
 
5
12
  - Support Table data binding read_only_sort: true option to allow visual sorting without affecting model data
13
+ - on_quit to
6
14
  - Tetris Add lines and level to High Score Dialog
7
15
  - Tetris Immediate Drop on Arrow Up
8
16
  - Tetris Pause on showing High Score Dialog
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.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.4
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)
@@ -493,7 +493,7 @@ jgem install glimmer-dsl-swt
493
493
 
494
494
  Or this command if you want a specific version:
495
495
  ```
496
- jgem install glimmer-dsl-swt -v 4.18.3.3
496
+ jgem install glimmer-dsl-swt -v 4.18.3.4
497
497
 
498
498
 
499
499
  ```
@@ -513,7 +513,7 @@ Note: if you're using activerecord or activesupport, keep in mind that Glimmer u
513
513
 
514
514
  Add the following to `Gemfile`:
515
515
  ```
516
- gem 'glimmer-dsl-swt', '~> 4.18.3.3
516
+ gem 'glimmer-dsl-swt', '~> 4.18.3.4
517
517
  '
518
518
  ```
519
519
 
@@ -572,7 +572,7 @@ bin/glimmer samples
572
572
  Below are the full usage instructions that come up when running `glimmer` without args.
573
573
 
574
574
  ```
575
- Glimmer (JRuby Desktop Development GUI Framework) - JRuby Gem: glimmer-dsl-swt v4.18.3.3
575
+ Glimmer (JRuby Desktop Development GUI Framework) - JRuby Gem: glimmer-dsl-swt v4.18.3.4
576
576
 
577
577
 
578
578
 
@@ -1053,7 +1053,7 @@ Output:
1053
1053
 
1054
1054
  Css glimmer-dsl-css 1.1.0 AndyMaleh Glimmer DSL for CSS
1055
1055
  Opal glimmer-dsl-opal 0.10.2 AndyMaleh Glimmer DSL for Opal
1056
- Swt glimmer-dsl-swt 4.18.3.3
1056
+ Swt glimmer-dsl-swt 4.18.3.4
1057
1057
 
1058
1058
  AndyMaleh Glimmer DSL for SWT
1059
1059
  Tk glimmer-dsl-tk 0.0.6 AndyMaleh Glimmer DSL for Tk
@@ -2357,7 +2357,7 @@ Shape keywords and their args (including defaults) are listed below (they basica
2357
2357
  - `rectangle​(x, y, width, height, vertical = true, fill: true, gradient: true)` gradient rectangle, which is always filled, and takes an optional extra argument to specify true for vertical gradient (default) and false for horizontal gradient
2358
2358
  - `text(string, x, y, flags = nil)` text with optional flags (flag format is `swt(comma_separated_flags)` where flags can be :draw_delimiter (i.e. new lines), :draw_tab, :draw_mnemonic, and :draw_transparent as explained in [GC API](https://help.eclipse.org/2020-12/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/graphics/GC.html))
2359
2359
 
2360
- Shape keywords that can be filled with color can take an keyword argument `fill: true` (defaults to false when not specified)
2360
+ Shape keywords that can be filled with color can take an keyword argument `fill: true`. Defaults to false when not specified unless background is set with no foreground (or foreground is set with no background), in which case a smart default is applied.
2361
2361
 
2362
2362
  Optionally, a shape keyword takes a block that can set any attributes from [org.eclipse.swt.graphics.GC](https://help.eclipse.org/2020-12/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/graphics/GC.html) (methods starting with `set`), which enable setting the `background` for filling and `foreground` for drawing.
2363
2363
 
@@ -2395,10 +2395,10 @@ shell {
2395
2395
 
2396
2396
  canvas {
2397
2397
  background :dark_yellow
2398
- rectangle(0, 0, 220, 400, fill: true) {
2398
+ rectangle(0, 0, 220, 400) {
2399
2399
  background :dark_red
2400
2400
  }
2401
- rectangle(50, 20, 300, 150, 30, 50, round: true, fill: true) {
2401
+ rectangle(50, 20, 300, 150, 30, 50, round: true) {
2402
2402
  background :yellow
2403
2403
  }
2404
2404
  rectangle(150, 200, 100, 70, true, gradient: true) {
@@ -2468,6 +2468,103 @@ In any case, if there is anything missing you would like added to the Glimmer Sh
2468
2468
 
2469
2469
  Keep in mind that the Shape DSL can be used inside any widget, not just `canvas`. Unlike shapes on a `canvas`, which are standalone graphics, when included in a widget, which already has its own look and feel, shapes are used as a decorative add-on that complements its look by getting painted on top of it. For example, shapes were used to decorate `composite` blocks in the [Tetris](#tetris) sample to have a more bevel look. In summary, Shapes can be used in a hybrid approach (shapes inside a widget), not just standalone in a `canvas`.
2470
2470
 
2471
+ #### Shapes inside an Image
2472
+
2473
+ You can build an image using the Canvas Shape DSL (including setting the icon of the application).
2474
+
2475
+ Example (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
2476
+
2477
+ ```
2478
+ include Glimmer
2479
+
2480
+ shell {
2481
+ text 'Image Shape DSL Example'
2482
+ label {
2483
+ bevel_constant = 20
2484
+ icon_block_size = 64
2485
+ icon_bevel_size = icon_block_size.to_f / 25.to_f
2486
+ icon_bevel_pixel_size = 0.16*icon_block_size.to_f
2487
+ icon_size = 8
2488
+ icon_pixel_size = icon_block_size * icon_size
2489
+ image(icon_pixel_size, icon_pixel_size) {
2490
+ icon_size.times { |row|
2491
+ icon_size.times { |column|
2492
+ colored = row >= 1 && column.between?(1, 6)
2493
+ color = colored ? color([:white, :red, :blue, :green, :yellow, :magenta, :cyan, :dark_blue].sample) : color(:white)
2494
+ x = column * icon_block_size
2495
+ y = row * icon_block_size
2496
+ rectangle(x, y, icon_block_size, icon_block_size) {
2497
+ background color
2498
+ }
2499
+ polygon(x, y, x + icon_block_size, y, x + icon_block_size - icon_bevel_pixel_size, y + icon_bevel_pixel_size, x + icon_bevel_pixel_size, y + icon_bevel_pixel_size) {
2500
+ background rgb(color.red + 4*bevel_constant, color.green + 4*bevel_constant, color.blue + 4*bevel_constant)
2501
+ }
2502
+ polygon(x + icon_block_size, y, x + icon_block_size - icon_bevel_pixel_size, y + icon_bevel_pixel_size, x + icon_block_size - icon_bevel_pixel_size, y + icon_block_size - icon_bevel_pixel_size, x + icon_block_size, y + icon_block_size) {
2503
+ background rgb(color.red - bevel_constant, color.green - bevel_constant, color.blue - bevel_constant)
2504
+ }
2505
+ polygon(x + icon_block_size, y + icon_block_size, x, y + icon_block_size, x + icon_bevel_pixel_size, y + icon_block_size - icon_bevel_pixel_size, x + icon_block_size - icon_bevel_pixel_size, y + icon_block_size - icon_bevel_pixel_size) {
2506
+ background rgb(color.red - 2*bevel_constant, color.green - 2*bevel_constant, color.blue - 2*bevel_constant)
2507
+ }
2508
+ polygon(x, y, x, y + icon_block_size, x + icon_bevel_pixel_size, y + icon_block_size - icon_bevel_pixel_size, x + icon_bevel_pixel_size, y + icon_bevel_pixel_size) {
2509
+ background rgb(color.red - bevel_constant, color.green - bevel_constant, color.blue - bevel_constant)
2510
+ }
2511
+ }
2512
+ }
2513
+ }
2514
+ }
2515
+ }.open
2516
+ ```
2517
+
2518
+ ![Image Shape DSL](images/glimmer-example-image-shape-dsl.png)
2519
+
2520
+ Example setting the icon of the application (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
2521
+
2522
+ ```
2523
+ include Glimmer
2524
+
2525
+ shell {
2526
+ text 'Image Shape DSL Example'
2527
+ label {
2528
+ text 'Image Shape DSL Example'
2529
+ font height: 30
2530
+ }
2531
+ bevel_constant = 20
2532
+ icon_block_size = 64
2533
+ icon_bevel_size = icon_block_size.to_f / 25.to_f
2534
+ icon_bevel_pixel_size = 0.16*icon_block_size.to_f
2535
+ icon_size = 8
2536
+ icon_pixel_size = icon_block_size * icon_size
2537
+ image(icon_pixel_size, icon_pixel_size) {
2538
+ icon_size.times { |row|
2539
+ icon_size.times { |column|
2540
+ colored = row >= 1 && column.between?(1, 6)
2541
+ color = colored ? color([:white, :red, :blue, :green, :yellow, :magenta, :cyan, :dark_blue].sample) : color(:white)
2542
+ x = column * icon_block_size
2543
+ y = row * icon_block_size
2544
+ rectangle(x, y, icon_block_size, icon_block_size) {
2545
+ background color
2546
+ }
2547
+ polygon(x, y, x + icon_block_size, y, x + icon_block_size - icon_bevel_pixel_size, y + icon_bevel_pixel_size, x + icon_bevel_pixel_size, y + icon_bevel_pixel_size) {
2548
+ background rgb(color.red + 4*bevel_constant, color.green + 4*bevel_constant, color.blue + 4*bevel_constant)
2549
+ }
2550
+ polygon(x + icon_block_size, y, x + icon_block_size - icon_bevel_pixel_size, y + icon_bevel_pixel_size, x + icon_block_size - icon_bevel_pixel_size, y + icon_block_size - icon_bevel_pixel_size, x + icon_block_size, y + icon_block_size) {
2551
+ background rgb(color.red - bevel_constant, color.green - bevel_constant, color.blue - bevel_constant)
2552
+ }
2553
+ polygon(x + icon_block_size, y + icon_block_size, x, y + icon_block_size, x + icon_bevel_pixel_size, y + icon_block_size - icon_bevel_pixel_size, x + icon_block_size - icon_bevel_pixel_size, y + icon_block_size - icon_bevel_pixel_size) {
2554
+ background rgb(color.red - 2*bevel_constant, color.green - 2*bevel_constant, color.blue - 2*bevel_constant)
2555
+ }
2556
+ polygon(x, y, x, y + icon_block_size, x + icon_bevel_pixel_size, y + icon_block_size - icon_bevel_pixel_size, x + icon_bevel_pixel_size, y + icon_bevel_pixel_size) {
2557
+ background rgb(color.red - bevel_constant, color.green - bevel_constant, color.blue - bevel_constant)
2558
+ }
2559
+ }
2560
+ }
2561
+ }
2562
+ }.open
2563
+ ```
2564
+
2565
+ ![Image Shape DSL](images/glimmer-example-image-shape-dsl-app-switcher-icon.png)
2566
+
2567
+
2471
2568
  ### Canvas Transform DSL
2472
2569
 
2473
2570
  The transform DSL builds [org.eclipse.swt.graphics.Transform](https://help.eclipse.org/2020-12/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/graphics/Transform.html) objects with a nice declarative syntax.
@@ -2573,7 +2670,7 @@ shell {
2573
2670
 
2574
2671
  frame { |index|
2575
2672
  background rgb(index%100, index%100 + 100, index%55 + 200)
2576
- rectangle(index, index, 20, 20, fill: true) {
2673
+ rectangle(index, index, 20, 20) {
2577
2674
  background :red
2578
2675
  }
2579
2676
  }
@@ -4851,12 +4948,14 @@ Contact Manager - Edit Done
4851
4948
 
4852
4949
  #### Tetris
4853
4950
 
4854
- 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.
4951
+ 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, canvas shape icon image generation, and keyboard events/shortcuts.
4855
4952
 
4856
4953
  Code:
4857
4954
 
4858
4955
  [samples/elaborate/tetris.rb](samples/elaborate/tetris.rb)
4859
4956
 
4957
+ ![Tetris Icon](images/glimmer-tetris-icon.png)
4958
+
4860
4959
  ![Tetris](images/glimmer-tetris.png)
4861
4960
 
4862
4961
  ![Tetris Game Over](images/glimmer-tetris-game-over.png)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 4.18.3.3
1
+ 4.18.3.4
@@ -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.3 ruby lib
5
+ # stub: glimmer-dsl-swt 4.18.3.4 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.3"
9
+ s.version = "4.18.3.4"
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-29"
14
+ s.date = "2021-01-30"
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]
@@ -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
@@ -28,13 +28,21 @@ module Glimmer
28
28
  # image expression
29
29
  # Note: Cannot be a static expression because it clashes with image property expression
30
30
  class ImageExpression < Expression
31
+ include ParentExpression
32
+
31
33
  def can_interpret?(parent, keyword, *args, &block)
32
- keyword.to_s == 'image' and
33
- (parent.nil? or !parent.respond_to?('image'))
34
+ (keyword == 'image') and
35
+ (parent.nil? or parent.respond_to?('image='))
34
36
  end
35
37
 
36
38
  def interpret(parent, keyword, *args, &block)
37
- Glimmer::SWT::ImageProxy.new(*args)
39
+ args.unshift(parent) unless parent.nil?
40
+ Glimmer::SWT::ImageProxy.new(*args, &block)
41
+ end
42
+
43
+ def add_content(parent, &block)
44
+ super
45
+ parent.post_add_content
38
46
  end
39
47
  end
40
48
  end
@@ -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
@@ -33,7 +33,7 @@ module Glimmer
33
33
  include ParentExpression
34
34
 
35
35
  def can_interpret?(parent, keyword, *args, &block)
36
- keyword == 'layout_data' and
36
+ super and
37
37
  parent.respond_to?(:swt_widget)
38
38
  end
39
39
 
@@ -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
@@ -23,6 +23,7 @@ require 'glimmer'
23
23
  require 'glimmer/dsl/expression'
24
24
  require 'glimmer/dsl/parent_expression'
25
25
  require 'glimmer/swt/layout_proxy'
26
+ require 'glimmer/swt/image_proxy'
26
27
 
27
28
  module Glimmer
28
29
  module DSL
@@ -31,6 +32,7 @@ module Glimmer
31
32
  include ParentExpression
32
33
 
33
34
  include_package 'org.eclipse.swt.widgets'
35
+ include_package 'org.eclipse.swt.graphics'
34
36
 
35
37
  def can_interpret?(parent, keyword, *args, &block)
36
38
  keyword.to_s.end_with?('_layout') and
@@ -35,11 +35,12 @@ module Glimmer
35
35
  end
36
36
  end
37
37
 
38
- def resetup_shape_paint_listeners
38
+ def resetup_shape_painting
39
39
  # TODO consider performance optimization relating to order of shape rendering (affecting only further shapes not previous ones)
40
+ reset_gc if respond_to?(:reset_gc)
40
41
  shapes.each do |shape|
41
42
  shape.paint_listener_proxy&.unregister
42
- shape.setup_paint_listener
43
+ shape.setup_painting
43
44
  end
44
45
  end
45
46
  end
@@ -30,7 +30,6 @@ module Glimmer
30
30
  module SWT
31
31
  module Custom
32
32
  # Represents a shape (graphics) to be drawn on a control/widget/canvas/display
33
- # swt_widget returns the parent (e.g. a `canvas` WidgetProxy), equivalent to `parent.swt_widget`
34
33
  # That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
35
34
  class Shape
36
35
  include Packages
@@ -78,9 +77,11 @@ module Glimmer
78
77
  def flyweight_method_names
79
78
  @flyweight_method_names ||= {}
80
79
  end
80
+
81
+
81
82
  end
82
83
 
83
- attr_reader :parent, :name, :args, :options, :swt_widget, :paint_listener_proxy
84
+ attr_reader :parent, :name, :args, :options, :paint_listener_proxy
84
85
 
85
86
  def initialize(parent, keyword, *args, &property_block)
86
87
  @parent = parent
@@ -88,7 +89,6 @@ module Glimmer
88
89
  @method_name = self.class.method_name(keyword, args)
89
90
  @options = self.class.arg_options(args, extract: true)
90
91
  @args = args
91
- @swt_widget = parent.respond_to?(:swt_display) ? parent.swt_display : parent.swt_widget
92
92
  @properties = {}
93
93
  @parent.shapes << self
94
94
  post_add_content if property_block.nil?
@@ -111,7 +111,8 @@ module Glimmer
111
111
  end
112
112
 
113
113
  def post_add_content
114
- setup_paint_listener
114
+ amend_method_name_options_based_on_properties
115
+ setup_painting
115
116
  @content_added = true
116
117
  end
117
118
 
@@ -186,6 +187,15 @@ module Glimmer
186
187
  args[the_java_method_arg_count..-1] = []
187
188
  end
188
189
  end
190
+
191
+ def amend_method_name_options_based_on_properties
192
+ if @properties.keys.map(&:to_s).include?('background') && !@properties.keys.map(&:to_s).include?('foreground')
193
+ @options[:fill] = true
194
+ elsif @properties.keys.map(&:to_s).include?('foreground') && !@properties.keys.map(&:to_s).include?('background')
195
+ @options[:fill] = false
196
+ end
197
+ @method_name = self.class.method_name(@name, @args + [@options])
198
+ end
189
199
 
190
200
  def has_attribute?(attribute_name, *args)
191
201
  self.class.gc_instance_methods.include?(attribute_setter(attribute_name))
@@ -194,7 +204,7 @@ module Glimmer
194
204
  def set_attribute(attribute_name, *args)
195
205
  @properties[attribute_name] = args
196
206
  if @content_added && !@parent.is_disposed
197
- @parent.resetup_shape_paint_listeners
207
+ @parent.resetup_shape_painting
198
208
  @parent.redraw
199
209
  end
200
210
  end
@@ -203,10 +213,13 @@ module Glimmer
203
213
  @properties.symbolize_keys[attribute_name.to_s.to_sym]
204
214
  end
205
215
 
206
- def setup_paint_listener
216
+ def setup_painting
217
+ # TODO consider moving this method to parent (making the logic polymorphic)
207
218
  return if @parent.is_disposed
208
219
  if parent.respond_to?(:swt_display)
209
220
  @paint_listener_proxy = @parent.on_swt_paint(&method(:paint))
221
+ elsif parent.respond_to?(:swt_image)
222
+ paint(parent) # treat parent as paint event since you don't do repaints with images, it's a one time deal.
210
223
  elsif parent.respond_to?(:swt_widget)
211
224
  @paint_listener_proxy = @parent.on_paint_control(&method(:paint))
212
225
  end
@@ -214,9 +227,9 @@ module Glimmer
214
227
 
215
228
  def paint(paint_event)
216
229
  @properties['background'] = [@parent.background] if fill? && !@properties.keys.map(&:to_s).include?('background')
217
- @properties['foreground'] = [@parent.foreground] if draw? && !@properties.keys.map(&:to_s).include?('foreground')
218
- @properties['font'] = [@parent.font] if draw? && !@properties.keys.map(&:to_s).include?('font')
219
- @properties['transform'] = [nil] if !@properties.keys.map(&:to_s).include?('transform')
230
+ @properties['foreground'] = [@parent.foreground] if @parent.respond_to?(:foreground) && draw? && !@properties.keys.map(&:to_s).include?('foreground')
231
+ @properties['font'] = [@parent.font] if @parent.respond_to?(:font) && draw? && !@properties.keys.map(&:to_s).include?('font')
232
+ @properties['transform'] = [nil] if @parent.respond_to?(:transform) && !@properties.keys.map(&:to_s).include?('transform')
220
233
  @properties.each do |property, args|
221
234
  method_name = attribute_setter(property)
222
235
  converted_args = apply_property_arg_conversions(method_name, property, args)
@@ -19,6 +19,9 @@
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 'glimmer/swt/custom/drawable'
23
+ require 'glimmer/swt/properties'
24
+
22
25
  module Glimmer
23
26
  module SWT
24
27
  # Proxy for org.eclipse.swt.graphics.Image
@@ -27,6 +30,9 @@ module Glimmer
27
30
  #
28
31
  # Follows the Proxy Design Pattern
29
32
  class ImageProxy
33
+ include Custom::Drawable
34
+ include Properties
35
+
30
36
  class << self
31
37
  def create(*args)
32
38
  if args.size == 1 && args.first.is_a?(ImageProxy)
@@ -37,6 +43,7 @@ module Glimmer
37
43
  end
38
44
  end
39
45
 
46
+ include_package 'org.eclipse.swt.widgets'
40
47
  include_package 'org.eclipse.swt.graphics'
41
48
 
42
49
  attr_reader :file_path, :jar_file_path, :image_data, :swt_image
@@ -46,8 +53,13 @@ module Glimmer
46
53
  # Takes the same args as the SWT Image class
47
54
  # Alternatively, takes a file path string or a uri:classloader file path string (generated by JRuby when invoking `File.expand_path` inside a JAR file)
48
55
  # and returns an image object.
49
- def initialize(*args)
56
+ def initialize(*args, &content)
50
57
  @args = args
58
+ @parent_proxy = nil
59
+ if @args.first.is_a?(WidgetProxy)
60
+ @parent_proxy = @args.shift
61
+ @parent = @parent_proxy.swt_widget
62
+ end
51
63
  options = @args.last.is_a?(Hash) ? @args.delete_at(-1) : {}
52
64
  options[:swt_image] = @args.first if @args.size == 1 && @args.first.is_a?(Image)
53
65
  @file_path = @args.first if @args.size == 1 && @args.first.is_a?(String)
@@ -55,6 +67,9 @@ module Glimmer
55
67
  if options&.keys&.include?(:swt_image)
56
68
  @swt_image = options[:swt_image]
57
69
  @original_image_data = @image_data = @swt_image.image_data
70
+ elsif args.size == 1 && args.first.is_a?(ImageProxy)
71
+ @swt_image = @args.first.swt_image
72
+ @original_image_data = @image_data = @swt_image.image_data
58
73
  elsif @file_path
59
74
  @original_image_data = @image_data = ImageData.new(input_stream || @file_path)
60
75
  @swt_image = Image.new(DisplayProxy.instance.swt_display, @image_data)
@@ -64,9 +79,15 @@ module Glimmer
64
79
  width = (@image_data.width.to_f / @image_data.height.to_f)*height.to_f if !height.nil? && width.nil?
65
80
  scale_to(width, height) unless width.nil? || height.nil?
66
81
  else
82
+ @args.prepend(DisplayProxy.instance.swt_display) unless @args.first.is_a?(Display)
67
83
  @swt_image = Image.new(*@args)
68
84
  @original_image_data = @image_data = @swt_image.image_data
69
85
  end
86
+ post_add_content if content.nil?
87
+ end
88
+
89
+ def post_add_content
90
+ @parent&.image = swt_image
70
91
  end
71
92
 
72
93
  def input_stream
@@ -91,6 +112,52 @@ module Glimmer
91
112
  self
92
113
  end
93
114
 
115
+ def gc
116
+ @gc ||= reset_gc
117
+ end
118
+
119
+ def reset_gc
120
+ @gc = org.eclipse.swt.graphics.GC.new(swt_image)
121
+ end
122
+
123
+ def has_attribute?(attribute_name, *args)
124
+ @swt_image.respond_to?(attribute_setter(attribute_name), args) || respond_to?(ruby_attribute_setter(attribute_name), args)
125
+ end
126
+
127
+ def set_attribute(attribute_name, *args)
128
+ # TODO consider refactoring/unifying this code with WidgetProxy and elsewhere
129
+ if args.count == 1
130
+ if args.first.is_a?(Symbol) || args.first.is_a?(String)
131
+ args[0] = ColorProxy.new(args.first).swt_color
132
+ end
133
+ if args.first.is_a?(ColorProxy)
134
+ args[0] = args.first.swt_color
135
+ end
136
+ end
137
+
138
+ if @swt_image.respond_to?(attribute_setter(attribute_name))
139
+ @swt_image.send(attribute_setter(attribute_name), *args) unless @swt_image.send(attribute_getter(attribute_name)) == args.first
140
+ elsif @swt_image.respond_to?(ruby_attribute_setter(attribute_name))
141
+ @swt_image.send(ruby_attribute_setter(attribute_name), args)
142
+ else
143
+ send(ruby_attribute_setter(attribute_name), args)
144
+ end
145
+ end
146
+
147
+ def get_attribute(attribute_name)
148
+ if @swt_image.respond_to?(attribute_getter(attribute_name))
149
+ @swt_image.send(attribute_getter(attribute_name))
150
+ elsif @swt_image.respond_to?(ruby_attribute_getter(attribute_name))
151
+ @swt_image.send(ruby_attribute_getter(attribute_name))
152
+ elsif @swt_image.respond_to?(attribute_name)
153
+ @swt_image.send(attribute_name)
154
+ elsif respond_to?(ruby_attribute_getter(attribute_name))
155
+ send(ruby_attribute_getter(attribute_name))
156
+ else
157
+ send(attribute_name)
158
+ end
159
+ end
160
+
94
161
  def method_missing(method, *args, &block)
95
162
  swt_image.send(method, *args, &block)
96
163
  rescue => e
@@ -77,7 +77,7 @@ module Glimmer
77
77
  composite.layout = GridLayout.new if composite.get_layout.nil?
78
78
  end,
79
79
  canvas: lambda do |canvas|
80
- canvas.layout = nil unless canvas.get_layout.nil?
80
+ canvas.layout = nil if canvas.respond_to?('layout=') && !canvas.get_layout.nil?
81
81
  end,
82
82
  scrolled_composite: lambda do |scrolled_composite|
83
83
  scrolled_composite.expand_horizontal = true
@@ -163,8 +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
+ @parent_proxy = @parent = parent
167
+ @parent_proxy = @parent&.get_data('proxy') if @parent.respond_to?(:get_data) && @parent.get_data('proxy')
168
168
  @swt_style = SWT::SWTProxy[*swt_constants]
169
169
  options ||= {}
170
170
  @options = self.class.options.merge(options)
@@ -35,6 +35,7 @@ class Tetris
35
35
  FONT_NAME = 'Menlo'
36
36
  FONT_TITLE_HEIGHT = 32
37
37
  FONT_TITLE_STYLE = :bold
38
+ BEVEL_CONSTANT = 20
38
39
 
39
40
  option :playfield_width, default: Model::Game::PLAYFIELD_WIDTH
40
41
  option :playfield_height, default: Model::Game::PLAYFIELD_HEIGHT
@@ -56,7 +57,14 @@ class Tetris
56
57
  when swt(:arrow_down), 's'.bytes.first
57
58
  game.down!
58
59
  when swt(:arrow_up)
59
- game.down!(immediate: true)
60
+ case game.up_arrow_action
61
+ when :instant_down
62
+ game.down!(instant: true)
63
+ when :rotate_right
64
+ game.rotate!(:right)
65
+ when :rotate_left
66
+ game.rotate!(:left)
67
+ end
60
68
  when swt(:arrow_left), 'a'.bytes.first
61
69
  game.left!
62
70
  when swt(:arrow_right), 'd'.bytes.first
@@ -110,10 +118,10 @@ class Tetris
110
118
  margin_height 0
111
119
  horizontal_spacing 0
112
120
  }
113
-
121
+
114
122
  text 'Glimmer Tetris'
115
123
  minimum_size 475, 500
116
- background :gray
124
+ image tetris_icon
117
125
 
118
126
  tetris_menu_bar(game: game)
119
127
 
@@ -129,6 +137,39 @@ class Tetris
129
137
  }
130
138
  }
131
139
 
140
+ def tetris_icon
141
+ icon_block_size = 64
142
+ icon_bevel_size = icon_block_size.to_f / 25.to_f
143
+ icon_bevel_pixel_size = 0.16*icon_block_size.to_f
144
+ icon_size = 8
145
+ icon_pixel_size = icon_block_size * icon_size
146
+ image(icon_pixel_size, icon_pixel_size) {
147
+ icon_size.times { |row|
148
+ icon_size.times { |column|
149
+ colored = row >= 1 && column.between?(1, 6)
150
+ color = colored ? color(([:white] + Model::Tetromino::LETTER_COLORS.values).sample) : color(:white)
151
+ x = column * icon_block_size
152
+ y = row * icon_block_size
153
+ rectangle(x, y, icon_block_size, icon_block_size, fill: true) {
154
+ background color
155
+ }
156
+ polygon(x, y, x + icon_block_size, y, x + icon_block_size - icon_bevel_pixel_size, y + icon_bevel_pixel_size, x + icon_bevel_pixel_size, y + icon_bevel_pixel_size, fill: true) {
157
+ background rgb(color.red + 4*BEVEL_CONSTANT, color.green + 4*BEVEL_CONSTANT, color.blue + 4*BEVEL_CONSTANT)
158
+ }
159
+ polygon(x + icon_block_size, y, x + icon_block_size - icon_bevel_pixel_size, y + icon_bevel_pixel_size, x + icon_block_size - icon_bevel_pixel_size, y + icon_block_size - icon_bevel_pixel_size, x + icon_block_size, y + icon_block_size, fill: true) {
160
+ background rgb(color.red - BEVEL_CONSTANT, color.green - BEVEL_CONSTANT, color.blue - BEVEL_CONSTANT)
161
+ }
162
+ polygon(x + icon_block_size, y + icon_block_size, x, y + icon_block_size, x + icon_bevel_pixel_size, y + icon_block_size - icon_bevel_pixel_size, x + icon_block_size - icon_bevel_pixel_size, y + icon_block_size - icon_bevel_pixel_size, fill: true) {
163
+ background rgb(color.red - 2*BEVEL_CONSTANT, color.green - 2*BEVEL_CONSTANT, color.blue - 2*BEVEL_CONSTANT)
164
+ }
165
+ polygon(x, y, x, y + icon_block_size, x + icon_bevel_pixel_size, y + icon_block_size - icon_bevel_pixel_size, x + icon_bevel_pixel_size, y + icon_bevel_pixel_size, fill: true) {
166
+ background rgb(color.red - BEVEL_CONSTANT, color.green - BEVEL_CONSTANT, color.blue - BEVEL_CONSTANT)
167
+ }
168
+ }
169
+ }
170
+ }
171
+ end
172
+
132
173
  def start_moving_tetrominos_down
133
174
  Thread.new do
134
175
  @mutex.synchronize do
@@ -38,7 +38,7 @@ class Tetris
38
38
  SCORE_MULTIPLIER = {1 => 40, 2 => 100, 3 => 300, 4 => 1200}
39
39
 
40
40
  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
41
+ attr_accessor :game_over, :paused, :preview_tetromino, :lines, :score, :level, :high_scores, :beeping, :added_high_score, :show_high_scores, :up_arrow_action
42
42
  alias game_over? game_over
43
43
  alias paused? paused
44
44
  alias beeping? beeping
@@ -50,6 +50,7 @@ class Tetris
50
50
  @high_scores = []
51
51
  @show_high_scores = false
52
52
  @beeping = true
53
+ @up_arrow_action = :instant_down
53
54
  load_high_scores!
54
55
  end
55
56
 
@@ -117,9 +118,9 @@ class Tetris
117
118
  File.join(tetris_dir, "high_scores.txt")
118
119
  end
119
120
 
120
- def down!(immediate: false)
121
+ def down!(instant: false)
121
122
  return unless game_in_progress?
122
- current_tetromino.down!(immediate: immediate)
123
+ current_tetromino.down!(instant: instant)
123
124
  game_over! if current_tetromino.row <= 0 && current_tetromino.stopped?
124
125
  end
125
126
 
@@ -204,6 +205,30 @@ class Tetris
204
205
  @beeper&.call if beeping
205
206
  end
206
207
 
208
+ def instant_down_on_up=(value)
209
+ self.up_arrow_action = :instant_down if value
210
+ end
211
+
212
+ def instant_down_on_up
213
+ self.up_arrow_action == :instant_down
214
+ end
215
+
216
+ def rotate_right_on_up=(value)
217
+ self.up_arrow_action = :rotate_right if value
218
+ end
219
+
220
+ def rotate_right_on_up
221
+ self.up_arrow_action == :rotate_right
222
+ end
223
+
224
+ def rotate_left_on_up=(value)
225
+ self.up_arrow_action = :rotate_left if value
226
+ end
227
+
228
+ def rotate_left_on_up
229
+ self.up_arrow_action == :rotate_left
230
+ end
231
+
207
232
  def reset_tetrominoes
208
233
  @tetrominoes = []
209
234
  end
@@ -182,11 +182,11 @@ class Tetris
182
182
  @blocks.size
183
183
  end
184
184
 
185
- def down!(immediate: false)
185
+ def down!(instant: false)
186
186
  launch! if preview?
187
187
  unless stopped?
188
188
  block_count = 1
189
- if immediate
189
+ if instant
190
190
  remaining_height, bottom_touching_block = remaining_height_and_bottom_touching_block
191
191
  block_count = remaining_height - @row
192
192
  end
@@ -26,36 +26,31 @@ class Tetris
26
26
 
27
27
  options :game_playfield, :block_size, :row, :column
28
28
 
29
- before_body {
30
- @bevel_constant = 20
31
- }
32
-
33
29
  body {
34
30
  canvas {
35
- layout nil
36
31
  background bind(game_playfield[row][column], :color)
37
- polygon(0, 0, block_size, 0, block_size - 4, 4, 4, 4, fill: true) {
32
+ polygon(0, 0, block_size, 0, block_size - 4, 4, 4, 4) {
38
33
  background bind(game_playfield[row][column], :color) { |color_value|
39
34
  color = color(color_value)
40
- rgb(color.red + 4*@bevel_constant, color.green + 4*@bevel_constant, color.blue + 4*@bevel_constant)
35
+ rgb(color.red + 4*BEVEL_CONSTANT, color.green + 4*BEVEL_CONSTANT, color.blue + 4*BEVEL_CONSTANT)
41
36
  }
42
37
  }
43
- polygon(block_size, 0, block_size - 4, 4, block_size - 4, block_size - 4, block_size, block_size, fill: true) {
38
+ polygon(block_size, 0, block_size - 4, 4, block_size - 4, block_size - 4, block_size, block_size) {
44
39
  background bind(game_playfield[row][column], :color) { |color_value|
45
40
  color = color(color_value)
46
- rgb(color.red - @bevel_constant, color.green - @bevel_constant, color.blue - @bevel_constant)
41
+ rgb(color.red - BEVEL_CONSTANT, color.green - BEVEL_CONSTANT, color.blue - BEVEL_CONSTANT)
47
42
  }
48
43
  }
49
- polygon(block_size, block_size, 0, block_size, 4, block_size - 4, block_size - 4, block_size - 4, fill: true) {
44
+ polygon(block_size, block_size, 0, block_size, 4, block_size - 4, block_size - 4, block_size - 4) {
50
45
  background bind(game_playfield[row][column], :color) { |color_value|
51
46
  color = color(color_value)
52
- rgb(color.red - 2*@bevel_constant, color.green - 2*@bevel_constant, color.blue - 2*@bevel_constant)
47
+ rgb(color.red - 2*BEVEL_CONSTANT, color.green - 2*BEVEL_CONSTANT, color.blue - 2*BEVEL_CONSTANT)
53
48
  }
54
49
  }
55
- polygon(0, 0, 0, block_size, 4, block_size - 4, 4, 4, fill: true) {
50
+ polygon(0, 0, 0, block_size, 4, block_size - 4, 4, 4) {
56
51
  background bind(game_playfield[row][column], :color) { |color_value|
57
52
  color = color(color_value)
58
- rgb(color.red - @bevel_constant, color.green - @bevel_constant, color.blue - @bevel_constant)
53
+ rgb(color.red - BEVEL_CONSTANT, color.green - BEVEL_CONSTANT, color.blue - BEVEL_CONSTANT)
59
54
  }
60
55
  }
61
56
  rectangle(0, 0, block_size, block_size) {
@@ -29,7 +29,7 @@ class Tetris
29
29
  options :game_playfield, :playfield_width, :playfield_height, :block_size
30
30
 
31
31
  body {
32
- canvas {
32
+ composite {
33
33
  grid_layout {
34
34
  num_columns playfield_width
35
35
  make_columns_equal_width true
@@ -94,6 +94,24 @@ class Tetris
94
94
  accelerator :command, :b
95
95
  selection bind(game, :beeping)
96
96
  }
97
+ menu {
98
+ text 'Up Arrow'
99
+ menu_item(:radio) {
100
+ text '&Instant Down'
101
+ accelerator :command, :shift, :i
102
+ selection bind(game, :instant_down_on_up, computed_by: :up_arrow_action)
103
+ }
104
+ menu_item(:radio) {
105
+ text 'Rotate &Right'
106
+ accelerator :command, :shift, :r
107
+ selection bind(game, :rotate_right_on_up, computed_by: :up_arrow_action)
108
+ }
109
+ menu_item(:radio) {
110
+ text 'Rotate &Left'
111
+ accelerator :command, :shift, :l
112
+ selection bind(game, :rotate_left_on_up, computed_by: :up_arrow_action)
113
+ }
114
+ }
97
115
  } # end of menu
98
116
 
99
117
  menu {
@@ -30,7 +30,7 @@ shell {
30
30
  rectangle(0, 0, 220, 400, fill: true) {
31
31
  background :red
32
32
  }
33
- rectangle(50, 20, 300, 150, 30, 50, round: true, fill: true) {
33
+ rectangle(50, 20, 300, 150, 30, 50, round: true) {
34
34
  background :magenta
35
35
  }
36
36
  rectangle(150, 200, 100, 70, true, gradient: true) {
@@ -49,13 +49,13 @@ shell {
49
49
  foreground :dark_magenta
50
50
  font name: 'Courier', height: 30
51
51
  }
52
- oval(110, 310, 100, 100, fill: true) {
52
+ oval(110, 310, 100, 100) {
53
53
  background rgb(128, 138, 248)
54
54
  }
55
- arc(210, 210, 100, 100, 30, -77, fill: true) {
55
+ arc(210, 210, 100, 100, 30, -77) {
56
56
  background :red
57
57
  }
58
- polygon(250, 210, 260, 170, 270, 210, 290, 230, fill: true) {
58
+ polygon(250, 210, 260, 170, 270, 210, 290, 230) {
59
59
  background :dark_yellow
60
60
  }
61
61
  polyline(250, 110, 260, 70, 270, 110, 290, 130, 250, 110)
@@ -35,7 +35,7 @@ shell {
35
35
  oval(0, 0, 400, 400) { # x, y, width, height
36
36
  foreground :black # sets oval background color
37
37
  }
38
- arc(0, 0, 400, 400, -1.4*index%360, 10, fill: true) { # x, y, width, height, start angle, arc angle
38
+ arc(0, 0, 400, 400, -1.4*index%360, 10) { # x, y, width, height, start angle, arc angle
39
39
  background rgb(200, 200, 50) # sets arc background color
40
40
  }
41
41
  }
@@ -54,10 +54,10 @@ shell {
54
54
 
55
55
  background outside_color # sets canvas background color
56
56
 
57
- rectangle(0, 0, 200, 200, fill: true) {
57
+ rectangle(0, 0, 200, 200) {
58
58
  background inside_color # sets rectangle background color
59
59
  }
60
- rectangle(200, 200, 200, 200, fill: true) {
60
+ rectangle(200, 200, 200, 200) {
61
61
  background inside_color # sets rectangle background color
62
62
  }
63
63
  }
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.3
4
+ version: 4.18.3.4
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-29 00:00:00.000000000 Z
11
+ date: 2021-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement