glimmer-dsl-swt 4.18.6.1 → 4.18.6.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 +9 -0
- data/README.md +4 -4
- data/VERSION +1 -1
- data/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md +0 -1
- data/docs/reference/GLIMMER_PACKAGING_AND_DISTRIBUTION.md +2 -0
- data/glimmer-dsl-swt.gemspec +4 -3
- data/lib/glimmer/swt/color_proxy.rb +1 -1
- data/lib/glimmer/swt/custom/shape.rb +10 -6
- data/lib/glimmer/swt/custom/shape/cubic.rb +2 -1
- data/lib/glimmer/swt/custom/shape/line.rb +4 -2
- data/lib/glimmer/swt/custom/shape/path.rb +25 -9
- data/lib/glimmer/swt/custom/shape/path_segment.rb +24 -2
- data/lib/glimmer/swt/custom/shape/point.rb +1 -1
- data/lib/glimmer/swt/custom/shape/quad.rb +3 -2
- data/samples/elaborate/stock_ticker.rb +32 -41
- data/samples/hello/hello_canvas_data_binding.rb +193 -0
- data/samples/hello/hello_canvas_path.rb +105 -51
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6d4f89641fcc2573b43cd52e23cf4dda45aa209e55cd49cbe751f6a4b7bc85b1
|
4
|
+
data.tar.gz: 9cf53e2b5aef11f838314b50188f63b3a69936ea31f54930da77bddfd561b08e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 355fe3aab4e45648832678ce3a2c00411129be61bbff91575f4c19b73254a82ab9fa58ce6acbac78d6dca4daf383340cd074e6ec5ea6128bcdb37df94befe125
|
7
|
+
data.tar.gz: d30171ae846dc373fb4d58426bcdc64a179579c4f86ee749d16cb0a5f3440bc542305a91a1e0d5774b796e14750a1918ae4e8d3bb33b2eaff70da4fd3a7afff1
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
### 4.18.6.2
|
4
|
+
|
5
|
+
- Hello, Canvas Data Binding! Sample
|
6
|
+
- Update Stock Ticker sample to keep stock names visible when scrolling graphs off the screen
|
7
|
+
- `rgb` keyword tolerance of nil values (converts to 0)
|
8
|
+
- Canvas Path DSL Data-Binding
|
9
|
+
- Added `Glimmer::SWT::Custom::Shape::PathSegment` `#path` and `#root_path` API methods to enable determining what path/root-path the path segment is part of.
|
10
|
+
- Fixed issues with geometry calculation of path segments (especially line)
|
11
|
+
|
3
12
|
### 4.18.6.1
|
4
13
|
|
5
14
|
- Fixed issues with Canvas Path DSL handling of connected vs non-connected path segments (including in geometry calculations)
|
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.6.
|
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.6.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)
|
@@ -13,7 +13,7 @@
|
|
13
13
|
[<img src="https://covers.oreillystatic.com/images/9780596519650/lrg.jpg" width=105 /><br />
|
14
14
|
Featured in JRuby Cookbook](http://shop.oreilly.com/product/9780596519650.do) and [Chalmers/Gothenburg University Software Engineering Master's Lecture Material](http://www.cse.chalmers.se/~bergert/slides/guest_lecture_DSLs.pdf)
|
15
15
|
|
16
|
-
[Glimmer DSL for SWT](https://rubygems.org/gems/glimmer-dsl-swt) 4.18.6.
|
16
|
+
[Glimmer DSL for SWT](https://rubygems.org/gems/glimmer-dsl-swt) 4.18.6.2 includes [SWT 4.18](https://download.eclipse.org/eclipse/downloads/drops4/R-4.18-202012021800/), which was released on December 2, 2020. Gem version numbers are in sync with the SWT library versions. The first two digits represent the SWT version number. The last two digits represent the minor and patch versions of Glimmer DSL for SWT.
|
17
17
|
|
18
18
|
[Glimmer DSL for SWT receives two updates per month](https://rubygems.org/gems/glimmer-dsl-swt/versions). You can trust [Glimmer DSL for SWT](https://rubygems.org/gems/glimmer-dsl-swt) with your Ruby desktop GUI development needs! [Glimmer DSL for SWT](https://rubygems.org/gems/glimmer-dsl-swt) brings great ideas to the table, such as declarative programming via domain specific languages, currently under-utilized in the GUI domain. That said, it may not be feature complete enough for everybody's needs, so please help make [Glimmer DSL for SWT](https://rubygems.org/gems/glimmer-dsl-swt) even better by providing feedback and [contributing](#contributing) when possible. The project is very active, so any feature suggestions that are accepted could be implemented within weeks if not days. Also, you are welcome to [hire me](#hire-me) full-time if you want long-term development of [Glimmer DSL for SWT](https://rubygems.org/gems/glimmer-dsl-swt) for your project needs.
|
19
19
|
|
@@ -340,7 +340,7 @@ jgem install glimmer-dsl-swt
|
|
340
340
|
|
341
341
|
Or this command if you want a specific version:
|
342
342
|
```
|
343
|
-
jgem install glimmer-dsl-swt -v 4.18.6.
|
343
|
+
jgem install glimmer-dsl-swt -v 4.18.6.2
|
344
344
|
```
|
345
345
|
|
346
346
|
`jgem` is JRuby's version of `gem` command.
|
@@ -358,7 +358,7 @@ Note: if you're using activerecord or activesupport, keep in mind that Glimmer u
|
|
358
358
|
|
359
359
|
Add the following to `Gemfile`:
|
360
360
|
```
|
361
|
-
gem 'glimmer-dsl-swt', '~> 4.18.6.
|
361
|
+
gem 'glimmer-dsl-swt', '~> 4.18.6.2'
|
362
362
|
```
|
363
363
|
|
364
364
|
And, then run:
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
4.18.6.
|
1
|
+
4.18.6.2
|
@@ -12,6 +12,8 @@ glimmer package
|
|
12
12
|
|
13
13
|
It works out of the box for any application scaffolded by [Glimmer Scaffolding](#scaffolding), generating all available packaging types on the current platform (e.g. `DMG`, `PKG`, `APP` on the Mac) and displaying a message indicating what pre-requisite setup tools are needed if not installed already (e.g. [Wix Toolset](https://wixtoolset.org/) to generate MSI files on Windows). If you install Wix, make sure it is on the system PATH by adding for example "C:\Program Files (x86)\WiX Toolset v3.11\bin" to the Windows Environment Variables.
|
14
14
|
|
15
|
+
(note: if you see this error on the Mac 'Error: Bundler "DMG Installer" (dmg) failed to produce a bundle.', ignore it as it should have produced a bundle anyways. It is a harmless issue in 3rd party dependency: javapackager.)
|
16
|
+
|
15
17
|
You may choose to generate a specific type of packaging instead by addionally passing in the `[type]` option. For example, this generates an MSI setup file on Windows:
|
16
18
|
|
17
19
|
```
|
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.6.
|
5
|
+
# stub: glimmer-dsl-swt 4.18.6.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.6.
|
9
|
+
s.version = "4.18.6.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-03-
|
14
|
+
s.date = "2021-03-02"
|
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]
|
@@ -185,6 +185,7 @@ Gem::Specification.new do |s|
|
|
185
185
|
"samples/hello/hello_button.rb",
|
186
186
|
"samples/hello/hello_canvas.rb",
|
187
187
|
"samples/hello/hello_canvas_animation.rb",
|
188
|
+
"samples/hello/hello_canvas_data_binding.rb",
|
188
189
|
"samples/hello/hello_canvas_path.rb",
|
189
190
|
"samples/hello/hello_canvas_transform.rb",
|
190
191
|
"samples/hello/hello_checkbox.rb",
|
@@ -60,7 +60,6 @@ module Glimmer
|
|
60
60
|
# Represents a shape (graphics) to be drawn on a control/widget/canvas/display
|
61
61
|
# That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
|
62
62
|
class Shape
|
63
|
-
include Packages
|
64
63
|
include Properties
|
65
64
|
|
66
65
|
class << self
|
@@ -253,7 +252,7 @@ module Glimmer
|
|
253
252
|
args = args.dup
|
254
253
|
the_java_method = org.eclipse.swt.graphics.GC.java_class.declared_instance_methods.detect {|m| m.name == method_name}
|
255
254
|
return args if the_java_method.nil?
|
256
|
-
if the_java_method.parameter_types.first == Color.java_class && args.first.is_a?(RGB)
|
255
|
+
if the_java_method.parameter_types.first == org.eclipse.swt.graphics.Color.java_class && args.first.is_a?(org.eclipse.swt.graphics.RGB)
|
257
256
|
args[0] = [args[0].red, args[0].green, args[0].blue]
|
258
257
|
end
|
259
258
|
if ['setBackground', 'setForeground'].include?(method_name.to_s) && args.first.is_a?(Array)
|
@@ -264,7 +263,7 @@ module Glimmer
|
|
264
263
|
args[1..-1] = []
|
265
264
|
end
|
266
265
|
if args.first.is_a?(Symbol) || args.first.is_a?(::String)
|
267
|
-
if the_java_method.parameter_types.first == Color.java_class
|
266
|
+
if the_java_method.parameter_types.first == org.eclipse.swt.graphics.Color.java_class
|
268
267
|
args[0] = ColorProxy.new(args[0])
|
269
268
|
end
|
270
269
|
if the_java_method.parameter_types.first == Java::int.java_class
|
@@ -274,7 +273,7 @@ module Glimmer
|
|
274
273
|
if args.first.is_a?(ColorProxy)
|
275
274
|
args[0] = args[0].swt_color
|
276
275
|
end
|
277
|
-
if (args.first.is_a?(Hash) || args.first.is_a?(FontData)) && the_java_method.parameter_types.first == Font.java_class
|
276
|
+
if (args.first.is_a?(Hash) || args.first.is_a?(org.eclipse.swt.graphics.FontData)) && the_java_method.parameter_types.first == org.eclipse.swt.graphics.Font.java_class
|
278
277
|
args[0] = FontProxy.new(args[0])
|
279
278
|
end
|
280
279
|
if args.first.is_a?(FontProxy)
|
@@ -287,7 +286,7 @@ module Glimmer
|
|
287
286
|
@drawable.requires_shape_disposal = true
|
288
287
|
args = args.first if args.first.is_a?(Array)
|
289
288
|
args.each_with_index do |arg, i|
|
290
|
-
arg = ColorProxy.new(arg.red, arg.green, arg.blue) if arg.is_a?(RGB)
|
289
|
+
arg = ColorProxy.new(arg.red, arg.green, arg.blue) if arg.is_a?(org.eclipse.swt.graphics.RGB)
|
291
290
|
arg = ColorProxy.new(arg) if arg.is_a?(Symbol) || arg.is_a?(::String)
|
292
291
|
arg = arg.swt_color if arg.is_a?(ColorProxy)
|
293
292
|
args[i] = arg
|
@@ -434,6 +433,11 @@ module Glimmer
|
|
434
433
|
end
|
435
434
|
if @content_added && perform_redraw && !drawable.is_disposed
|
436
435
|
@calculated_paint_args = false
|
436
|
+
if is_a?(PathSegment)
|
437
|
+
root_path&.calculated_path_args = @calculated_path_args = false
|
438
|
+
calculated_args_changed!
|
439
|
+
root_path&.calculated_args_changed!
|
440
|
+
end
|
437
441
|
attribute_name = ruby_attribute_getter(attribute_name)
|
438
442
|
if location_parameter_names.map(&:to_s).include?(attribute_name)
|
439
443
|
@calculated_args = nil
|
@@ -811,7 +815,7 @@ module Glimmer
|
|
811
815
|
if @name == 'pixel'
|
812
816
|
@name = 'point'
|
813
817
|
# optimized performance calculation for pixel points
|
814
|
-
if !@properties[:foreground].is_a?(Color)
|
818
|
+
if !@properties[:foreground].is_a?(org.eclipse.swt.graphics.Color)
|
815
819
|
if @properties[:foreground].is_a?(Array)
|
816
820
|
@properties[:foreground] = ColorProxy.new(@properties[:foreground], ensure_bounds: false)
|
817
821
|
end
|
@@ -20,6 +20,7 @@
|
|
20
20
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
21
|
|
22
22
|
require 'glimmer/swt/custom/shape'
|
23
|
+
require 'glimmer/swt/custom/shape/path'
|
23
24
|
require 'glimmer/swt/custom/shape/path_segment'
|
24
25
|
require 'glimmer/swt/swt_proxy'
|
25
26
|
require 'glimmer/swt/display_proxy'
|
@@ -102,7 +103,7 @@ module Glimmer
|
|
102
103
|
end
|
103
104
|
|
104
105
|
def eql?(other)
|
105
|
-
point_array == (other && other.respond_to?(:point_array) && other.point_array)
|
106
|
+
other.is_a?(Cubic) && point_array == (other && other.respond_to?(:point_array) && other.point_array)
|
106
107
|
end
|
107
108
|
alias == eql?
|
108
109
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# Copyright (c) 2007-2021 Andy Maleh
|
2
|
+
# Copyright (c) 2007-2021 Andy Maleh
|
2
3
|
#
|
3
4
|
# Permission is hereby granted, free of charge, to any person obtaining
|
4
5
|
# a copy of this software and associated documentation files (the
|
@@ -157,7 +158,7 @@ module Glimmer
|
|
157
158
|
|
158
159
|
def path_segment_geometry_args
|
159
160
|
# TODO make args auto-infer first point if previous_point_connected is true or if there is only x1,y1 or x2,y2 (but not both), or if there is an x, y, or if there is a point_array with 1 point
|
160
|
-
@args
|
161
|
+
@args
|
161
162
|
end
|
162
163
|
|
163
164
|
def previous_point_connected?
|
@@ -165,7 +166,8 @@ module Glimmer
|
|
165
166
|
end
|
166
167
|
|
167
168
|
def eql?(other)
|
168
|
-
|
169
|
+
other.is_a?(Line) &&
|
170
|
+
x1 == (other && other.respond_to?(:x1) && other.x1) &&
|
169
171
|
y1 == (other && other.respond_to?(:y1) && other.y1) &&
|
170
172
|
x2 == (other && other.respond_to?(:x2) && other.x2) &&
|
171
173
|
y2 == (other && other.respond_to?(:y2) && other.y2)
|
@@ -30,14 +30,15 @@ require 'glimmer/swt/display_proxy'
|
|
30
30
|
module Glimmer
|
31
31
|
module SWT
|
32
32
|
module Custom
|
33
|
-
# Represents a path to be drawn on a control/widget/canvas/display
|
34
|
-
# That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
|
35
33
|
class Shape
|
34
|
+
# Represents a path to be drawn on a control/widget/canvas/display
|
35
|
+
# That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
|
36
|
+
# swt_path is not guaranteed to have any object in it till after rendering
|
36
37
|
class Path < Shape
|
37
38
|
include PathSegment # a path may behave as a path segment in another path
|
38
39
|
|
39
|
-
attr_accessor :flatness, :closed
|
40
40
|
attr_reader :swt_path, :path_segments
|
41
|
+
attr_accessor :calculated_path_args
|
41
42
|
|
42
43
|
def initialize(parent, keyword, *args, &property_block)
|
43
44
|
super
|
@@ -81,15 +82,25 @@ module Glimmer
|
|
81
82
|
def post_dispose_content(path_segment)
|
82
83
|
@path_segments.delete(path_segment)
|
83
84
|
@uncalculated_path_segments = @path_segments.dup
|
84
|
-
dispose
|
85
|
+
@swt_path&.dispose
|
86
|
+
@swt_path = nil
|
87
|
+
@args = []
|
88
|
+
calculated_args_changed!(children: false)
|
85
89
|
end
|
86
90
|
|
87
|
-
def
|
91
|
+
def clear
|
92
|
+
@path_segments.each { |path_segments| path_segments.class == Path && path_segments.dispose }
|
93
|
+
@path_segments.clear
|
94
|
+
@uncalculated_path_segments = @path_segments.dup
|
88
95
|
@swt_path&.dispose
|
89
96
|
@swt_path = nil
|
90
97
|
@args = []
|
91
98
|
calculated_args_changed!(children: false)
|
92
|
-
|
99
|
+
end
|
100
|
+
|
101
|
+
def dispose
|
102
|
+
clear if self.class == Path
|
103
|
+
super if parent.is_a?(Drawable)
|
93
104
|
end
|
94
105
|
|
95
106
|
def calculated_args_changed!(children: true)
|
@@ -97,14 +108,19 @@ module Glimmer
|
|
97
108
|
end
|
98
109
|
|
99
110
|
def calculated_args
|
100
|
-
new_swt_path = @swt_path.nil?
|
101
|
-
|
111
|
+
new_swt_path = @swt_path.nil? || !@calculated_paint_args || !@calculated_path_args
|
112
|
+
if new_swt_path
|
113
|
+
@swt_path&.dispose
|
114
|
+
@swt_path = org.eclipse.swt.graphics.Path.new(Glimmer::SWT::DisplayProxy.instance.swt_display)
|
115
|
+
@uncalculated_path_segments = @path_segments.dup
|
116
|
+
end
|
102
117
|
# TODO recreate @swt_path only if one of the children get disposed (must notify parent on dispose)
|
103
118
|
@args = [@swt_path]
|
104
119
|
@uncalculated_path_segments.each do |path_segment|
|
105
120
|
path_segment.add_to_swt_path(@swt_path)
|
106
121
|
@uncalculated_path_segments.delete(path_segment)
|
107
122
|
end
|
123
|
+
@calculated_path_args = true
|
108
124
|
if new_swt_path
|
109
125
|
@path_calculated_args = super
|
110
126
|
else
|
@@ -196,7 +212,7 @@ module Glimmer
|
|
196
212
|
end
|
197
213
|
|
198
214
|
def eql?(other)
|
199
|
-
geometry.equals(other && other.respond_to?(:geometry) && other.geometry)
|
215
|
+
(other.class == Path) && geometry.equals(other && other.respond_to?(:geometry) && other.geometry)
|
200
216
|
end
|
201
217
|
alias == eql?
|
202
218
|
|
@@ -30,6 +30,26 @@ module Glimmer
|
|
30
30
|
# Represents path segments like point, line, quad, and cubic curves
|
31
31
|
# Shapes could mix in
|
32
32
|
module PathSegment
|
33
|
+
def root_path
|
34
|
+
current_parent = parent
|
35
|
+
until current_parent.class == Path && !current_parent.parent.is_a?(Path)
|
36
|
+
current_parent = current_parent.parent
|
37
|
+
return current_parent if current_parent.nil?
|
38
|
+
end
|
39
|
+
current_parent
|
40
|
+
end
|
41
|
+
def path
|
42
|
+
current_parent = parent
|
43
|
+
until current_parent.class == Path
|
44
|
+
current_parent = current_parent.parent
|
45
|
+
return current_parent if current_parent.nil?
|
46
|
+
end
|
47
|
+
current_parent
|
48
|
+
end
|
49
|
+
# this is needed to indicate if a shape is part of a path or not (e.g. line and point could be either)
|
50
|
+
def part_of_path?
|
51
|
+
!!root_path
|
52
|
+
end
|
33
53
|
# Subclasses must override and implement to indicate method name to invoke on SWT Path object to add segment
|
34
54
|
def path_segment_method_name
|
35
55
|
nil
|
@@ -59,6 +79,8 @@ module Glimmer
|
|
59
79
|
|
60
80
|
def dispose
|
61
81
|
parent.post_dispose_content(self) if parent.is_a?(Path)
|
82
|
+
super if !part_of_path?
|
83
|
+
drawable.redraw unless drawable.is_a?(ImageProxy)
|
62
84
|
end
|
63
85
|
|
64
86
|
def first_path_segment?
|
@@ -94,10 +116,10 @@ module Glimmer
|
|
94
116
|
if !previous_point_connected?
|
95
117
|
if the_path_segment_geometry_args.count == default_path_segment_arg_count
|
96
118
|
point = the_path_segment_geometry_args.shift, the_path_segment_geometry_args.shift
|
97
|
-
|
119
|
+
geometry.moveTo(point[0], point[1])
|
98
120
|
elsif first_path_segment?
|
99
121
|
point = the_path_segment_geometry_args[0..1]
|
100
|
-
|
122
|
+
geometry.moveTo(point[0], point[1])
|
101
123
|
end
|
102
124
|
end
|
103
125
|
end
|
@@ -75,7 +75,7 @@ module Glimmer
|
|
75
75
|
end
|
76
76
|
|
77
77
|
def eql?(other)
|
78
|
-
x == (other && other.respond_to?(:x) && other.x) && y == (other && other.respond_to?(:y) && other.y)
|
78
|
+
other.is_a?(Point) && x == (other && other.respond_to?(:x) && other.x) && y == (other && other.respond_to?(:y) && other.y)
|
79
79
|
end
|
80
80
|
alias == eql?
|
81
81
|
|
@@ -20,6 +20,7 @@
|
|
20
20
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
21
|
|
22
22
|
require 'glimmer/swt/custom/shape'
|
23
|
+
require 'glimmer/swt/custom/shape/path'
|
23
24
|
require 'glimmer/swt/custom/shape/path_segment'
|
24
25
|
require 'glimmer/swt/swt_proxy'
|
25
26
|
require 'glimmer/swt/display_proxy'
|
@@ -82,7 +83,7 @@ module Glimmer
|
|
82
83
|
|
83
84
|
def path_segment_args
|
84
85
|
# TODO make args auto-infer control points if previous_point_connected is true or if there is only a point_array with 1 point
|
85
|
-
@args
|
86
|
+
@args
|
86
87
|
end
|
87
88
|
|
88
89
|
def default_path_segment_arg_count
|
@@ -98,7 +99,7 @@ module Glimmer
|
|
98
99
|
end
|
99
100
|
|
100
101
|
def eql?(other)
|
101
|
-
point_array == (other && other.respond_to?(:point_array) && other.point_array)
|
102
|
+
other.is_a?(Quad) && point_array == (other && other.respond_to?(:point_array) && other.point_array)
|
102
103
|
end
|
103
104
|
alias == eql?
|
104
105
|
|
@@ -26,24 +26,24 @@ require 'glimmer-dsl-swt'
|
|
26
26
|
class StockTicker
|
27
27
|
class Stock
|
28
28
|
class << self
|
29
|
-
attr_writer :
|
29
|
+
attr_writer :price_min, :price_max
|
30
30
|
|
31
|
-
def
|
32
|
-
@
|
31
|
+
def price_min
|
32
|
+
@price_min ||= 1
|
33
33
|
end
|
34
34
|
|
35
|
-
def
|
36
|
-
@
|
35
|
+
def price_max
|
36
|
+
@price_max ||= 600
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
attr_reader :name, :
|
41
|
-
attr_accessor :
|
40
|
+
attr_reader :name, :prices
|
41
|
+
attr_accessor :price
|
42
42
|
|
43
|
-
def initialize(name,
|
43
|
+
def initialize(name, price)
|
44
44
|
@name = name
|
45
|
-
@
|
46
|
-
@
|
45
|
+
@price = price
|
46
|
+
@prices = [@price]
|
47
47
|
@delta_sign = 1
|
48
48
|
start_new_trend!
|
49
49
|
end
|
@@ -55,7 +55,7 @@ class StockTicker
|
|
55
55
|
@delta_sign *= -1
|
56
56
|
start_new_trend!
|
57
57
|
end
|
58
|
-
|
58
|
+
prices << self.price = [[@price + @delta_sign*delta, Stock.price_min].max, Stock.price_max].min
|
59
59
|
end
|
60
60
|
|
61
61
|
def start_new_trend!
|
@@ -73,52 +73,38 @@ class StockTicker
|
|
73
73
|
Stock.new('ADBE', 459),
|
74
74
|
]
|
75
75
|
@stock_colors = [:red, :dark_green, :blue, :dark_magenta]
|
76
|
-
|
77
|
-
|
78
|
-
@tabs = ['Lines', 'Quadratic Bezier Curves', 'Cubic Bezier Curves', 'Points'].map {|title| {title: title, stock_paths: [], stock_transforms: []}}
|
76
|
+
margin = 5
|
77
|
+
@tabs = ['Lines', 'Quadratic Bezier Curves', 'Cubic Bezier Curves', 'Points'].map {|title| {title: title, stock_paths: []}}
|
79
78
|
@stocks.each_with_index do |stock, stock_index|
|
80
|
-
observe(stock, :
|
79
|
+
observe(stock, :price) do |new_price|
|
81
80
|
begin
|
82
81
|
@tabs.each do |tab|
|
83
|
-
new_x = stock.
|
82
|
+
new_x = stock.prices.count - 1
|
84
83
|
new_y = @tabs.first[:canvas].bounds.height - new_price - 1
|
85
|
-
max_stock_name_width = tab[:text]&.bounds&.width if tab[:text]&.bounds&.width.to_f > max_stock_name_width
|
86
84
|
if new_x > 0
|
87
85
|
case tab[:title]
|
88
86
|
when 'Cubic Bezier Curves'
|
89
|
-
if new_x%3 == 0 && stock.
|
87
|
+
if new_x%3 == 0 && stock.prices[new_x] && stock.prices[new_x - 1] && stock.prices[new_x - 2]
|
90
88
|
tab[:stock_paths][stock_index].content {
|
91
|
-
cubic(new_x - 2, @tabs.first[:canvas].bounds.height - stock.
|
92
|
-
tab[:stock_transforms][stock_index] ||= transform {
|
93
|
-
translate max_stock_name_width + 5 + left_margin, tab[:text].bounds.height / 2.0
|
94
|
-
}
|
89
|
+
cubic(new_x - 2 + margin, @tabs.first[:canvas].bounds.height - stock.prices[new_x - 2] - 1, new_x - 1 + margin, @tabs.first[:canvas].bounds.height - stock.prices[new_x - 1] - 1, new_x + margin, new_y)
|
95
90
|
}
|
96
91
|
end
|
97
92
|
when 'Quadratic Bezier Curves'
|
98
|
-
if new_x%2 == 0 && stock.
|
93
|
+
if new_x%2 == 0 && stock.prices[new_x] && stock.prices[new_x - 1]
|
99
94
|
tab[:stock_paths][stock_index].content {
|
100
|
-
quad(new_x - 1, @tabs.first[:canvas].bounds.height - stock.
|
101
|
-
tab[:stock_transforms][stock_index] ||= transform {
|
102
|
-
translate max_stock_name_width + 5 + left_margin, tab[:text].bounds.height / 2.0
|
103
|
-
}
|
95
|
+
quad(new_x - 1 + margin, @tabs.first[:canvas].bounds.height - stock.prices[new_x - 1] - 1, new_x + margin, new_y)
|
104
96
|
}
|
105
97
|
end
|
106
98
|
when 'Lines'
|
107
99
|
tab[:stock_paths][stock_index].content {
|
108
|
-
line(new_x, new_y)
|
109
|
-
tab[:stock_transforms][stock_index] ||= transform {
|
110
|
-
translate max_stock_name_width + 5 + left_margin, tab[:text].bounds.height / 2.0
|
111
|
-
}
|
100
|
+
line(new_x + margin, new_y)
|
112
101
|
}
|
113
102
|
when 'Points'
|
114
103
|
tab[:stock_paths][stock_index].content {
|
115
|
-
point(new_x, new_y)
|
116
|
-
tab[:stock_transforms][stock_index] ||= transform {
|
117
|
-
translate max_stock_name_width + 5 + left_margin, tab[:text].bounds.height / 2.0
|
118
|
-
}
|
104
|
+
point(new_x + margin, new_y)
|
119
105
|
}
|
120
106
|
end
|
121
|
-
new_x_location = new_x +
|
107
|
+
new_x_location = new_x + 2*margin
|
122
108
|
canvas_width = tab[:canvas].bounds.width
|
123
109
|
if new_x_location > canvas_width
|
124
110
|
tab[:canvas].set_size(new_x_location, @tabs.first[:canvas].bounds.height)
|
@@ -127,9 +113,10 @@ class StockTicker
|
|
127
113
|
tab[:scrolled_composite].set_origin(tab[:scrolled_composite].origin.x + 1, tab[:scrolled_composite].origin.y) if (tab[:scrolled_composite].origin.x + tab[:scrolled_composite].client_area.width) == canvas_width
|
128
114
|
end
|
129
115
|
else
|
130
|
-
tab[:
|
131
|
-
|
116
|
+
tab[:canvas_header].content {
|
117
|
+
text(stock.name, 15, new_y - 10) {
|
132
118
|
foreground @stock_colors[stock_index]
|
119
|
+
font height: 14
|
133
120
|
}
|
134
121
|
}
|
135
122
|
end
|
@@ -163,13 +150,17 @@ class StockTicker
|
|
163
150
|
@tab_folder = tab_folder {
|
164
151
|
@tabs.each do |tab|
|
165
152
|
tab_item {
|
166
|
-
|
153
|
+
grid_layout(2, false) {
|
167
154
|
margin_width 0
|
168
155
|
margin_height 0
|
169
156
|
}
|
170
157
|
text tab[:title]
|
171
158
|
|
159
|
+
tab[:canvas_header] = canvas {
|
160
|
+
layout_data(:center, :fill, false, true)
|
161
|
+
}
|
172
162
|
tab[:scrolled_composite] = scrolled_composite {
|
163
|
+
layout_data :fill, :fill, true, true
|
173
164
|
tab[:canvas] = canvas {
|
174
165
|
background :white
|
175
166
|
|
@@ -209,8 +200,8 @@ class StockTicker
|
|
209
200
|
}
|
210
201
|
|
211
202
|
on_swt_show {
|
212
|
-
Stock.
|
213
|
-
Stock.
|
203
|
+
Stock.price_min = 25
|
204
|
+
Stock.price_max = @tabs.first[:canvas].bounds.height - 6
|
214
205
|
# pre-initialize all tabs by selecting them so that they render content when they are later in the background
|
215
206
|
@tab_folder.items.each do |item|
|
216
207
|
@tab_folder.selection = item
|
@@ -0,0 +1,193 @@
|
|
1
|
+
require 'glimmer-dsl-swt'
|
2
|
+
|
3
|
+
class HelloCanvasDataBinding
|
4
|
+
include Glimmer::GUI::CustomWindow
|
5
|
+
|
6
|
+
CANVAS_WIDTH = 300
|
7
|
+
CANVAS_HEIGHT = 300
|
8
|
+
|
9
|
+
attr_accessor :x1_value, :y1_value, :x2_value, :y2_value, :foreground_red, :foreground_green, :foreground_blue, :line_width_value, :line_style_value
|
10
|
+
|
11
|
+
def foreground_value
|
12
|
+
rgb(foreground_red, foreground_green, foreground_blue)
|
13
|
+
end
|
14
|
+
|
15
|
+
def line_style_value_options
|
16
|
+
[:line_solid, :line_dash, :line_dot, :line_dashdot, :line_dashdotdot]
|
17
|
+
end
|
18
|
+
|
19
|
+
before_body {
|
20
|
+
self.x1_value = 0
|
21
|
+
self.y1_value = 0
|
22
|
+
self.x2_value = CANVAS_WIDTH
|
23
|
+
self.y2_value = CANVAS_HEIGHT
|
24
|
+
self.foreground_red = 28
|
25
|
+
self.foreground_green = 128
|
26
|
+
self.foreground_blue = 228
|
27
|
+
self.line_width_value = 3
|
28
|
+
self.line_style_value = :line_dot
|
29
|
+
}
|
30
|
+
|
31
|
+
body {
|
32
|
+
shell {
|
33
|
+
text 'Hello, Canvas Data-Binding!'
|
34
|
+
|
35
|
+
tab_folder {
|
36
|
+
tab_item {
|
37
|
+
grid_layout(6, true) {
|
38
|
+
margin_width 0
|
39
|
+
margin_height 0
|
40
|
+
horizontal_spacing 0
|
41
|
+
vertical_spacing 0
|
42
|
+
}
|
43
|
+
text 'line'
|
44
|
+
|
45
|
+
label {
|
46
|
+
layout_data(:fill, :center, false, false) {
|
47
|
+
horizontal_span 3
|
48
|
+
}
|
49
|
+
text 'x1'
|
50
|
+
}
|
51
|
+
label {
|
52
|
+
layout_data(:fill, :center, false, false) {
|
53
|
+
horizontal_span 3
|
54
|
+
}
|
55
|
+
text 'y1'
|
56
|
+
}
|
57
|
+
spinner {
|
58
|
+
layout_data(:fill, :center, false, false) {
|
59
|
+
horizontal_span 3
|
60
|
+
}
|
61
|
+
maximum CANVAS_WIDTH
|
62
|
+
increment 3
|
63
|
+
selection bind(self, :x1_value)
|
64
|
+
}
|
65
|
+
spinner {
|
66
|
+
layout_data(:fill, :center, false, false) {
|
67
|
+
horizontal_span 3
|
68
|
+
}
|
69
|
+
maximum CANVAS_HEIGHT
|
70
|
+
increment 3
|
71
|
+
selection bind(self, :y1_value)
|
72
|
+
}
|
73
|
+
label {
|
74
|
+
layout_data(:fill, :center, false, false) {
|
75
|
+
horizontal_span 3
|
76
|
+
}
|
77
|
+
text 'x2'
|
78
|
+
}
|
79
|
+
label {
|
80
|
+
layout_data(:fill, :center, false, false) {
|
81
|
+
horizontal_span 3
|
82
|
+
}
|
83
|
+
text 'y2'
|
84
|
+
}
|
85
|
+
spinner {
|
86
|
+
layout_data(:fill, :center, false, false) {
|
87
|
+
horizontal_span 3
|
88
|
+
}
|
89
|
+
maximum CANVAS_WIDTH
|
90
|
+
increment 3
|
91
|
+
selection bind(self, :x2_value)
|
92
|
+
}
|
93
|
+
spinner {
|
94
|
+
layout_data(:fill, :center, false, false) {
|
95
|
+
horizontal_span 3
|
96
|
+
}
|
97
|
+
maximum CANVAS_HEIGHT
|
98
|
+
increment 3
|
99
|
+
selection bind(self, :y2_value)
|
100
|
+
}
|
101
|
+
label {
|
102
|
+
layout_data(:fill, :center, false, false) {
|
103
|
+
horizontal_span 2
|
104
|
+
}
|
105
|
+
text 'foreground red'
|
106
|
+
}
|
107
|
+
label {
|
108
|
+
layout_data(:fill, :center, false, false) {
|
109
|
+
horizontal_span 2
|
110
|
+
}
|
111
|
+
text 'foreground green'
|
112
|
+
}
|
113
|
+
label {
|
114
|
+
layout_data(:fill, :center, false, false) {
|
115
|
+
horizontal_span 2
|
116
|
+
}
|
117
|
+
text 'foreground blue'
|
118
|
+
}
|
119
|
+
spinner {
|
120
|
+
layout_data(:fill, :center, false, false) {
|
121
|
+
horizontal_span 2
|
122
|
+
}
|
123
|
+
maximum 255
|
124
|
+
increment 10
|
125
|
+
selection bind(self, :foreground_red)
|
126
|
+
}
|
127
|
+
spinner {
|
128
|
+
layout_data(:fill, :center, false, false) {
|
129
|
+
horizontal_span 2
|
130
|
+
}
|
131
|
+
maximum 255
|
132
|
+
increment 10
|
133
|
+
selection bind(self, :foreground_green)
|
134
|
+
}
|
135
|
+
spinner {
|
136
|
+
layout_data(:fill, :center, false, false) {
|
137
|
+
horizontal_span 2
|
138
|
+
}
|
139
|
+
maximum 255
|
140
|
+
increment 10
|
141
|
+
selection bind(self, :foreground_blue)
|
142
|
+
}
|
143
|
+
label {
|
144
|
+
layout_data(:fill, :center, false, false) {
|
145
|
+
horizontal_span 3
|
146
|
+
}
|
147
|
+
text 'line width'
|
148
|
+
}
|
149
|
+
label {
|
150
|
+
layout_data(:fill, :center, false, false) {
|
151
|
+
horizontal_span 3
|
152
|
+
}
|
153
|
+
text 'line style'
|
154
|
+
}
|
155
|
+
spinner {
|
156
|
+
layout_data(:fill, :center, false, false) {
|
157
|
+
horizontal_span 3
|
158
|
+
}
|
159
|
+
maximum 255
|
160
|
+
selection bind(self, :line_width_value)
|
161
|
+
}
|
162
|
+
combo(:read_only) {
|
163
|
+
layout_data(:fill, :center, false, false) {
|
164
|
+
horizontal_span 3
|
165
|
+
}
|
166
|
+
selection bind(self, :line_style_value)
|
167
|
+
}
|
168
|
+
canvas {
|
169
|
+
layout_data(:center, :center, false, false) {
|
170
|
+
horizontal_span 6
|
171
|
+
width_hint CANVAS_WIDTH
|
172
|
+
height_hint CANVAS_WIDTH
|
173
|
+
}
|
174
|
+
background :white
|
175
|
+
|
176
|
+
line {
|
177
|
+
x1 bind(self, :x1_value)
|
178
|
+
y1 bind(self, :y1_value)
|
179
|
+
x2 bind(self, :x2_value)
|
180
|
+
y2 bind(self, :y2_value)
|
181
|
+
foreground bind(self, :foreground_value, computed_by: [:foreground_red, :foreground_green, :foreground_blue])
|
182
|
+
line_width bind(self, :line_width_value)
|
183
|
+
line_style bind(self, :line_style_value)
|
184
|
+
}
|
185
|
+
}
|
186
|
+
}
|
187
|
+
}
|
188
|
+
}
|
189
|
+
}
|
190
|
+
|
191
|
+
end
|
192
|
+
|
193
|
+
HelloCanvasDataBinding.launch
|
@@ -1,66 +1,120 @@
|
|
1
|
+
# Copyright (c) 2007-2021 Andy Maleh
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
# a copy of this software and associated documentation files (the
|
5
|
+
# "Software"), to deal in the Software without restriction, including
|
6
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
# the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be
|
12
|
+
# included in all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
1
22
|
require 'glimmer-dsl-swt'
|
2
23
|
|
3
24
|
include Glimmer
|
4
25
|
|
5
26
|
shell {
|
27
|
+
grid_layout {
|
28
|
+
margin_width 0
|
29
|
+
margin_height 0
|
30
|
+
margin_top 5
|
31
|
+
}
|
6
32
|
text 'Hello, Canvas Path!'
|
7
33
|
minimum_size 800, 700
|
8
|
-
background :white
|
9
34
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
@
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
foreground :blue
|
31
|
-
}
|
32
|
-
@path3 = path {
|
33
|
-
antialias :on
|
34
|
-
foreground :blue
|
35
|
-
}
|
35
|
+
@button = button {
|
36
|
+
layout_data :center, :center, true, false
|
37
|
+
text 'Regenerate'
|
38
|
+
enabled false
|
39
|
+
|
40
|
+
on_widget_selected {
|
41
|
+
@regenerate = true
|
42
|
+
@button.enabled = false
|
43
|
+
}
|
44
|
+
}
|
45
|
+
canvas {
|
46
|
+
layout_data :fill, :fill, true, true
|
47
|
+
background :white
|
48
|
+
|
49
|
+
text('line', 15, 200) {
|
50
|
+
foreground :red
|
51
|
+
}
|
52
|
+
@path1 = path {
|
53
|
+
antialias :on
|
54
|
+
foreground :red
|
36
55
|
}
|
56
|
+
|
57
|
+
text('quad', 15, 300) {
|
58
|
+
foreground :dark_green
|
59
|
+
}
|
60
|
+
@path2 = path {
|
61
|
+
antialias :on
|
62
|
+
foreground :dark_green
|
63
|
+
}
|
64
|
+
|
65
|
+
text('cubic', 15, 400) {
|
66
|
+
foreground :blue
|
67
|
+
}
|
68
|
+
@path3 = path {
|
69
|
+
antialias :on
|
70
|
+
foreground :blue
|
71
|
+
}
|
72
|
+
}
|
37
73
|
|
38
74
|
on_swt_show {
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
75
|
+
@regenerate = true
|
76
|
+
@thread = Thread.new {
|
77
|
+
loop {
|
78
|
+
if @regenerate
|
79
|
+
@regenerate = false
|
80
|
+
@path1.clear
|
81
|
+
@path2.clear
|
82
|
+
@path3.clear
|
83
|
+
y1 = y2 = y3 = 300
|
84
|
+
730.times.each do |x|
|
85
|
+
x += 55
|
86
|
+
x1 = x - 2
|
87
|
+
x2 = x - 1
|
88
|
+
x3 = x
|
89
|
+
y1 = y3
|
90
|
+
y2 = y1
|
91
|
+
y3 = [[y3 + (rand*24 - 12), 0].max, 700].min
|
92
|
+
@path1.content {
|
93
|
+
line(x1, y1 - 100)
|
94
|
+
}
|
95
|
+
if x % 2 == 0
|
96
|
+
@path2.content {
|
97
|
+
quad(x1, y1, x2, y2)
|
98
|
+
}
|
99
|
+
end
|
100
|
+
if x % 3 == 0
|
101
|
+
@path3.content {
|
102
|
+
cubic(x1, y1 + 100, x2, y2 + 100, x3, y3 + 100)
|
103
|
+
}
|
104
|
+
end
|
105
|
+
sleep(0.01)
|
106
|
+
end
|
107
|
+
@button.enabled = true
|
56
108
|
end
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
}
|
61
|
-
end
|
62
|
-
sleep(0.01)
|
63
|
-
end
|
109
|
+
sleep(0.1)
|
110
|
+
}
|
111
|
+
|
64
112
|
}
|
113
|
+
|
65
114
|
}
|
115
|
+
|
116
|
+
on_widget_disposed {
|
117
|
+
@thread.kill # safe to kill since data is in memory only
|
118
|
+
}
|
119
|
+
|
66
120
|
}.open
|
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.6.
|
4
|
+
version: 4.18.6.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-03-
|
11
|
+
date: 2021-03-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -504,6 +504,7 @@ files:
|
|
504
504
|
- samples/hello/hello_button.rb
|
505
505
|
- samples/hello/hello_canvas.rb
|
506
506
|
- samples/hello/hello_canvas_animation.rb
|
507
|
+
- samples/hello/hello_canvas_data_binding.rb
|
507
508
|
- samples/hello/hello_canvas_path.rb
|
508
509
|
- samples/hello/hello_canvas_transform.rb
|
509
510
|
- samples/hello/hello_checkbox.rb
|