glimmer-dsl-swt 4.18.6.0 → 4.18.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/VERSION +1 -1
- data/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md +9 -5
- data/docs/reference/GLIMMER_SAMPLES.md +24 -0
- data/glimmer-dsl-swt.gemspec +4 -3
- data/lib/glimmer/swt/custom/shape.rb +4 -4
- data/lib/glimmer/swt/custom/shape/cubic.rb +15 -6
- data/lib/glimmer/swt/custom/shape/line.rb +8 -0
- data/lib/glimmer/swt/custom/shape/path.rb +20 -6
- data/lib/glimmer/swt/custom/shape/path_segment.rb +31 -6
- data/lib/glimmer/swt/custom/shape/quad.rb +13 -4
- data/samples/elaborate/stock_ticker.rb +229 -0
- data/samples/hello/hello_canvas_path.rb +54 -211
- 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: 6951b42a995fd393c82fcb406f5bb308aacf9330d75b85e0050104451044870c
|
4
|
+
data.tar.gz: 1de171314b2b6da4c80e295152a91697085e8bc7b00502fb0af88aef2890defc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d996c3707e136ec0e059396a3a06d301953236acbde4012f428fdc85dab3e13843296ace25426d41fa6fe7d87031ab5990a40e62a2b572bfbd47b97759575892
|
7
|
+
data.tar.gz: 5c317cdc5e75597d03bf241436cad374cd05e64d4a91739d08945ed2b4a5464807128eb25f23b271a057fdb4dd7b79372eee3c68f6f336a4fd27af8448ce31a9
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
### 4.18.6.1
|
4
|
+
|
5
|
+
- Fixed issues with Canvas Path DSL handling of connected vs non-connected path segments (including in geometry calculations)
|
6
|
+
- Optimized Canvas Path DSL redraw performance by removing extra redraws
|
7
|
+
- Fixed issues in the Hello, Canvas Path! sample and renamed to Stock Ticker
|
8
|
+
- Added a new simpler Hello, Canvas Path! sample
|
9
|
+
|
3
10
|
### 4.18.6.0
|
4
11
|
|
5
12
|
- Canvas Path DSL support (Alpha) for `path` as drawn or filled (`fill: true`) to the Canvas Shape DSL, supporting `point`, `line` (first point is auto-derived from previous point if not specified)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
4.18.6.
|
1
|
+
4.18.6.1
|
@@ -1956,9 +1956,9 @@ As they say, there are many ways to skin a cat! This is in line with the Ruby wa
|
|
1956
1956
|
|
1957
1957
|
### Canvas Path DSL
|
1958
1958
|
|
1959
|
-
**(
|
1959
|
+
**(ALPHA FEATURE)**
|
1960
1960
|
|
1961
|
-
Unlike common imperative GUI
|
1961
|
+
Unlike common imperative GUI graphing toolkits, Glimmer enables declarative rendering of paths with the new Canvas Path DSL (Early Alpha) via the new `path { }` keyword and by nesting one of the following path segment keywords underneath:
|
1962
1962
|
- `point(x1, y1)`: renders a Point (Dot) as part of a path.
|
1963
1963
|
- `line(x1, y1, x2=nil, y2=nil)`: renders a Line as part of a path. If you drop x2, y2, it joins to the previous point automatically. You may repeat for a series of lines forming a curve.
|
1964
1964
|
- `quad(x1, y1, x2, y2, x3=nil, y3=nil)`: renders a Quadratic Bezier Curve. If you drop x3 and y3, it joins to the previous point automatically.
|
@@ -1967,8 +1967,10 @@ Unlike common imperative GUI charting toolkits, Glimmer enables declarative rend
|
|
1967
1967
|
Example:
|
1968
1968
|
|
1969
1969
|
```ruby
|
1970
|
+
include Glimmer
|
1971
|
+
|
1970
1972
|
shell {
|
1971
|
-
text 'Canvas Path
|
1973
|
+
text 'Canvas Path Example'
|
1972
1974
|
minimum_size 300, 300
|
1973
1975
|
|
1974
1976
|
canvas {
|
@@ -1984,9 +1986,11 @@ shell {
|
|
1984
1986
|
}.open
|
1985
1987
|
```
|
1986
1988
|
|
1987
|
-
|
1989
|
+
![Canvas Path Example](/images/glimmer-example-canvas-path.png)
|
1990
|
+
|
1991
|
+
Learn more at the [Hello, Canvas Path!](GLIMMER_SAMPLES.md#hello-canvas-path) and [Stock Ticker](GLIMMER_SAMPLES.md#stock-ticker) samples.
|
1988
1992
|
|
1989
|
-
![
|
1993
|
+
![Stock Ticker](/images/glimmer-stock-ticker.gif)
|
1990
1994
|
|
1991
1995
|
### Canvas Transform DSL
|
1992
1996
|
|
@@ -33,6 +33,7 @@
|
|
33
33
|
- [Hello, Canvas!](#hello-canvas)
|
34
34
|
- [Hello, Canvas Animation!](#hello-canvas-animation)
|
35
35
|
- [Hello, Canvas Transform!](#hello-canvas-transform)
|
36
|
+
- [Hello, Canvas Path!](#hello-canvas-path)
|
36
37
|
- [Hello, Cursor!](#hello-cursor)
|
37
38
|
- [Hello, Progress Bar!](#hello-progress-bar)
|
38
39
|
- [Hello, Tree!](#hello-tree)
|
@@ -45,6 +46,7 @@
|
|
45
46
|
- [Contact Manager](#contact-manager)
|
46
47
|
- [Glimmer Tetris](#glimmer-tetris)
|
47
48
|
- [Mandelbrot Fractal](#mandelbrot-fractal)
|
49
|
+
- [Stock Ticker](#stock-ticker)
|
48
50
|
- [External Samples](#external-samples)
|
49
51
|
- [Glimmer Calculator](#glimmer-calculator)
|
50
52
|
- [Gladiator](#gladiator)
|
@@ -616,6 +618,18 @@ Hello, Canvas Transform!
|
|
616
618
|
|
617
619
|
![Hello Canvas Transform](/images/glimmer-hello-canvas-transform.png)
|
618
620
|
|
621
|
+
#### Hello, Canvas Path!
|
622
|
+
|
623
|
+
This sample demonstrates the use of the `path`, `quad`, `cubic`, `line`, and `point` keywords as part of the [Canvas Path DSL](/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#canvas-path-dsl) within the [Canvas Shape DSL](/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#canvas-shape-dsl).
|
624
|
+
|
625
|
+
Code:
|
626
|
+
|
627
|
+
[samples/hello/hello_canvas_path.rb](/samples/hello/hello_canvas_path.rb)
|
628
|
+
|
629
|
+
Hello, Canvas Path!
|
630
|
+
|
631
|
+
![Hello Canvas Path](/images/glimmer-hello-canvas-path.png)
|
632
|
+
|
619
633
|
#### Hello, Cursor!
|
620
634
|
|
621
635
|
This sample demonstrates the use of the `cursor` property keyword to change the mouse cursor.
|
@@ -812,6 +826,16 @@ Code:
|
|
812
826
|
|
813
827
|
![Mandelbrot Fractal Help Menu](/images/glimmer-mandelbrot-menu-help.png)
|
814
828
|
|
829
|
+
#### Stock Ticker
|
830
|
+
|
831
|
+
This sample demonstrates a Stock Ticker that generates random stock price data for 4 different stocks and provides 4 different tab views of the graphed data using the [Canvas Path DSL](/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#canvas-path-dsl). It leverages a thread that runs in the background and ticks the stocks to generate random new stock prices before amending the graphed paths with them.
|
832
|
+
|
833
|
+
Code:
|
834
|
+
|
835
|
+
[samples/elaborate/stock_ticker.rb](/samples/elaborate/stock_ticker.rb)
|
836
|
+
|
837
|
+
![Stock Ticker](/images/glimmer-stock-ticker.gif)
|
838
|
+
|
815
839
|
### External Samples
|
816
840
|
|
817
841
|
#### Glimmer Calculator
|
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.1 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.1"
|
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-
|
14
|
+
s.date = "2021-03-01"
|
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]
|
@@ -166,6 +166,7 @@ Gem::Specification.new do |s|
|
|
166
166
|
"samples/elaborate/login.rb",
|
167
167
|
"samples/elaborate/mandelbrot_fractal.rb",
|
168
168
|
"samples/elaborate/meta_sample.rb",
|
169
|
+
"samples/elaborate/stock_ticker.rb",
|
169
170
|
"samples/elaborate/tetris.rb",
|
170
171
|
"samples/elaborate/tetris/model/block.rb",
|
171
172
|
"samples/elaborate/tetris/model/game.rb",
|
@@ -230,7 +230,6 @@ module Glimmer
|
|
230
230
|
Glimmer::SWT::DisplayProxy.instance.auto_exec do
|
231
231
|
Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::SWT::ShapeExpression.new, &block)
|
232
232
|
calculated_args_changed!(children: false)
|
233
|
-
drawable.redraw unless drawable.is_a?(ImageProxy)
|
234
233
|
end
|
235
234
|
end
|
236
235
|
|
@@ -243,11 +242,11 @@ module Glimmer
|
|
243
242
|
end
|
244
243
|
|
245
244
|
def post_add_content
|
246
|
-
|
247
|
-
|
245
|
+
amend_method_name_options_based_on_properties!
|
246
|
+
if !@content_added || @method_name != @original_method_name
|
248
247
|
@drawable.setup_shape_painting unless @drawable.is_a?(ImageProxy)
|
249
248
|
@content_added = true
|
250
|
-
|
249
|
+
end
|
251
250
|
end
|
252
251
|
|
253
252
|
def apply_property_arg_conversions(method_name, property, args)
|
@@ -367,6 +366,7 @@ module Glimmer
|
|
367
366
|
end
|
368
367
|
|
369
368
|
def amend_method_name_options_based_on_properties!
|
369
|
+
@original_method_name = @method_name
|
370
370
|
return if @name == 'point'
|
371
371
|
if @name != 'text' && @name != 'string' && has_some_background? && !has_some_foreground?
|
372
372
|
@options[:fill] = true
|
@@ -39,14 +39,15 @@ module Glimmer
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def geometry
|
42
|
-
|
43
|
-
|
42
|
+
the_point_array = point_array
|
43
|
+
if the_point_array != @geometry_point_array
|
44
|
+
@geometry_point_array = the_point_array
|
44
45
|
@geometry = Java::JavaAwtGeom::Path2D::Double.new
|
45
|
-
@geometry
|
46
|
+
add_to_geometry(@geometry)
|
46
47
|
end
|
47
48
|
@geometry
|
48
49
|
end
|
49
|
-
|
50
|
+
|
50
51
|
def contain?(x, y)
|
51
52
|
include?(x, y, filled: true)
|
52
53
|
end
|
@@ -74,7 +75,7 @@ module Glimmer
|
|
74
75
|
the_point_array = the_point_array.first if the_point_array.first.is_a?(Array)
|
75
76
|
self.point_array = the_point_array.each_with_index.map {|coordinate, i| i.even? ? coordinate + x_delta : coordinate + y_delta}
|
76
77
|
end
|
77
|
-
|
78
|
+
|
78
79
|
def path_segment_method_name
|
79
80
|
'cubicTo'
|
80
81
|
end
|
@@ -84,12 +85,20 @@ module Glimmer
|
|
84
85
|
@args.to_a
|
85
86
|
end
|
86
87
|
|
88
|
+
def default_path_segment_arg_count
|
89
|
+
8
|
90
|
+
end
|
91
|
+
|
92
|
+
def default_connected_path_segment_arg_count
|
93
|
+
6
|
94
|
+
end
|
95
|
+
|
87
96
|
def path_segment_geometry_method_name
|
88
97
|
'curveTo'
|
89
98
|
end
|
90
99
|
|
91
100
|
def previous_point_connected?
|
92
|
-
@args.compact.count
|
101
|
+
@args.compact.count == 6 && !first_path_segment?
|
93
102
|
end
|
94
103
|
|
95
104
|
def eql?(other)
|
@@ -147,6 +147,14 @@ module Glimmer
|
|
147
147
|
@args
|
148
148
|
end
|
149
149
|
|
150
|
+
def default_path_segment_arg_count
|
151
|
+
4
|
152
|
+
end
|
153
|
+
|
154
|
+
def default_connected_path_segment_arg_count
|
155
|
+
2
|
156
|
+
end
|
157
|
+
|
150
158
|
def path_segment_geometry_args
|
151
159
|
# 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
|
152
160
|
@args[0..1]
|
@@ -97,16 +97,22 @@ module Glimmer
|
|
97
97
|
end
|
98
98
|
|
99
99
|
def calculated_args
|
100
|
+
new_swt_path = @swt_path.nil?
|
100
101
|
@swt_path ||= org.eclipse.swt.graphics.Path.new(Glimmer::SWT::DisplayProxy.instance.swt_display)
|
101
102
|
# TODO recreate @swt_path only if one of the children get disposed (must notify parent on dispose)
|
102
103
|
@args = [@swt_path]
|
103
|
-
@uncalculated_path_segments.
|
104
|
+
@uncalculated_path_segments.each do |path_segment|
|
104
105
|
path_segment.add_to_swt_path(@swt_path)
|
105
106
|
@uncalculated_path_segments.delete(path_segment)
|
106
107
|
end
|
107
|
-
|
108
|
+
if new_swt_path
|
109
|
+
@path_calculated_args = super
|
110
|
+
else
|
111
|
+
@path_calculated_args
|
112
|
+
end
|
108
113
|
rescue => e
|
109
114
|
Glimmer::Config.logger.error {e.full_message}
|
115
|
+
@args
|
110
116
|
end
|
111
117
|
|
112
118
|
def move_by(x_delta, y_delta)
|
@@ -158,7 +164,7 @@ module Glimmer
|
|
158
164
|
@geometry_path_segments = @path_segments
|
159
165
|
@geometry = Java::JavaAwtGeom::Path2D::Double.new
|
160
166
|
@path_segments.each do |path_segment|
|
161
|
-
@geometry
|
167
|
+
path_segment.add_to_geometry(@geometry)
|
162
168
|
end
|
163
169
|
end
|
164
170
|
@geometry
|
@@ -173,12 +179,20 @@ module Glimmer
|
|
173
179
|
end
|
174
180
|
|
175
181
|
def path_segment_geometry_method_name
|
176
|
-
|
182
|
+
if self.class == Path
|
183
|
+
'append'
|
184
|
+
else
|
185
|
+
super
|
186
|
+
end
|
177
187
|
end
|
178
188
|
|
179
189
|
def path_segment_geometry_args
|
180
|
-
|
181
|
-
|
190
|
+
if self.class == Path
|
191
|
+
# TODO consider supporting connected true instead of false (2nd arg)
|
192
|
+
[geometry, false]
|
193
|
+
else
|
194
|
+
super
|
195
|
+
end
|
182
196
|
end
|
183
197
|
|
184
198
|
def eql?(other)
|
@@ -38,6 +38,12 @@ module Glimmer
|
|
38
38
|
def path_segment_args
|
39
39
|
[]
|
40
40
|
end
|
41
|
+
# Subclasses must override to indicate expected complete count of args when previous point is NOT connected (e.g. 4 for line, 6 for quad, 8 for cubic)
|
42
|
+
def default_path_segment_arg_count
|
43
|
+
end
|
44
|
+
# Subclasses must override to indicate expected count of args when previous point IS connected (e.g. 2 for line, 4 for quad, 6 for cubic)
|
45
|
+
def default_connected_path_segment_arg_count
|
46
|
+
end
|
41
47
|
# Subclasses may override to provide name of method to invoke for geometry object obtained from the Java AWT library java.awt.geom.Path2D.Double (e.g. curveTo vs cubicTo)
|
42
48
|
def path_segment_geometry_method_name
|
43
49
|
path_segment_method_name
|
@@ -67,18 +73,37 @@ module Glimmer
|
|
67
73
|
if @swt_path != swt_path
|
68
74
|
@swt_path = swt_path
|
69
75
|
the_path_segment_args = path_segment_args.dup
|
70
|
-
if !
|
71
|
-
if
|
72
|
-
|
76
|
+
if !is_a?(Point) && self.class != Path
|
77
|
+
if !previous_point_connected?
|
78
|
+
if the_path_segment_args.count == default_path_segment_arg_count
|
79
|
+
point = the_path_segment_args.shift, the_path_segment_args.shift
|
80
|
+
@swt_path.moveTo(*point)
|
81
|
+
elsif first_path_segment?
|
82
|
+
point = the_path_segment_args[0..1]
|
83
|
+
@swt_path.moveTo(*point)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
@swt_path.send(path_segment_method_name, *the_path_segment_args)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def add_to_geometry(geometry)
|
92
|
+
the_path_segment_geometry_args = path_segment_geometry_args.dup
|
93
|
+
if !is_a?(Point) && self.class != Path
|
94
|
+
if !previous_point_connected?
|
95
|
+
if the_path_segment_geometry_args.count == default_path_segment_arg_count
|
96
|
+
point = the_path_segment_geometry_args.shift, the_path_segment_geometry_args.shift
|
73
97
|
@swt_path.moveTo(*point)
|
74
|
-
elsif first_path_segment?
|
75
|
-
point =
|
98
|
+
elsif first_path_segment?
|
99
|
+
point = the_path_segment_geometry_args[0..1]
|
76
100
|
@swt_path.moveTo(*point)
|
77
101
|
end
|
78
102
|
end
|
79
|
-
@swt_path.send(path_segment_method_name, *the_path_segment_args)
|
80
103
|
end
|
104
|
+
geometry.send(path_segment_geometry_method_name, *the_path_segment_geometry_args)
|
81
105
|
end
|
106
|
+
|
82
107
|
end
|
83
108
|
end
|
84
109
|
end
|
@@ -39,10 +39,11 @@ module Glimmer
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def geometry
|
42
|
-
|
43
|
-
|
42
|
+
the_point_array = point_array
|
43
|
+
if the_point_array != @geometry_point_array
|
44
|
+
@geometry_point_array = the_point_array
|
44
45
|
@geometry = Java::JavaAwtGeom::Path2D::Double.new
|
45
|
-
@geometry
|
46
|
+
add_to_geometry(@geometry)
|
46
47
|
end
|
47
48
|
@geometry
|
48
49
|
end
|
@@ -84,8 +85,16 @@ module Glimmer
|
|
84
85
|
@args.to_a
|
85
86
|
end
|
86
87
|
|
88
|
+
def default_path_segment_arg_count
|
89
|
+
6
|
90
|
+
end
|
91
|
+
|
92
|
+
def default_connected_path_segment_arg_count
|
93
|
+
4
|
94
|
+
end
|
95
|
+
|
87
96
|
def previous_point_connected?
|
88
|
-
@args.compact.count
|
97
|
+
@args.compact.count == 4 && !first_path_segment?
|
89
98
|
end
|
90
99
|
|
91
100
|
def eql?(other)
|
@@ -0,0 +1,229 @@
|
|
1
|
+
# Copyright (c) 2007-2021 Andy Maleh
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
# a copy of this software and associated documentation files (the
|
5
|
+
# "Software"), to deal in the Software without restriction, including
|
6
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
# the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be
|
12
|
+
# included in all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
require 'glimmer-dsl-swt'
|
23
|
+
|
24
|
+
# This Sample is an Early Alpha (New Canvas Path DSL Feature)
|
25
|
+
|
26
|
+
class StockTicker
|
27
|
+
class Stock
|
28
|
+
class << self
|
29
|
+
attr_writer :stock_price_min, :stock_price_max
|
30
|
+
|
31
|
+
def stock_price_min
|
32
|
+
@stock_price_min ||= 1
|
33
|
+
end
|
34
|
+
|
35
|
+
def stock_price_max
|
36
|
+
@stock_price_max ||= 600
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
attr_reader :name, :stock_prices
|
41
|
+
attr_accessor :stock_price
|
42
|
+
|
43
|
+
def initialize(name, stock_price)
|
44
|
+
@name = name
|
45
|
+
@stock_price = stock_price
|
46
|
+
@stock_prices = [@stock_price]
|
47
|
+
@delta_sign = 1
|
48
|
+
start_new_trend!
|
49
|
+
end
|
50
|
+
|
51
|
+
def tick!
|
52
|
+
@tick_count = @tick_count.to_i + 1
|
53
|
+
delta = @tick_count%@trend_length
|
54
|
+
if delta == 0
|
55
|
+
@delta_sign *= -1
|
56
|
+
start_new_trend!
|
57
|
+
end
|
58
|
+
stock_prices << self.stock_price = [[@stock_price + @delta_sign*delta, Stock.stock_price_min].max, Stock.stock_price_max].min
|
59
|
+
end
|
60
|
+
|
61
|
+
def start_new_trend!
|
62
|
+
@trend_length = (rand*12).to_i + 1
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
include Glimmer::UI::CustomShell
|
67
|
+
|
68
|
+
before_body {
|
69
|
+
@stocks = [
|
70
|
+
Stock.new('DELL', 81),
|
71
|
+
Stock.new('AAPL', 121),
|
72
|
+
Stock.new('MSFT', 232),
|
73
|
+
Stock.new('ADBE', 459),
|
74
|
+
]
|
75
|
+
@stock_colors = [:red, :dark_green, :blue, :dark_magenta]
|
76
|
+
max_stock_name_width = 0
|
77
|
+
left_margin = 5
|
78
|
+
@tabs = ['Lines', 'Quadratic Bezier Curves', 'Cubic Bezier Curves', 'Points'].map {|title| {title: title, stock_paths: [], stock_transforms: []}}
|
79
|
+
@stocks.each_with_index do |stock, stock_index|
|
80
|
+
observe(stock, :stock_price) do |new_price|
|
81
|
+
begin
|
82
|
+
@tabs.each do |tab|
|
83
|
+
new_x = stock.stock_prices.count - 1
|
84
|
+
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
|
+
if new_x > 0
|
87
|
+
case tab[:title]
|
88
|
+
when 'Cubic Bezier Curves'
|
89
|
+
if new_x%3 == 0 && stock.stock_prices[new_x] && stock.stock_prices[new_x - 1] && stock.stock_prices[new_x - 2]
|
90
|
+
tab[:stock_paths][stock_index].content {
|
91
|
+
cubic(new_x - 2, @tabs.first[:canvas].bounds.height - stock.stock_prices[new_x - 2] - 1, new_x - 1, @tabs.first[:canvas].bounds.height - stock.stock_prices[new_x - 1] - 1, new_x, new_y)
|
92
|
+
tab[:stock_transforms][stock_index] ||= transform {
|
93
|
+
translate max_stock_name_width + 5 + left_margin, tab[:text].bounds.height / 2.0
|
94
|
+
}
|
95
|
+
}
|
96
|
+
end
|
97
|
+
when 'Quadratic Bezier Curves'
|
98
|
+
if new_x%2 == 0 && stock.stock_prices[new_x] && stock.stock_prices[new_x - 1]
|
99
|
+
tab[:stock_paths][stock_index].content {
|
100
|
+
quad(new_x - 1, @tabs.first[:canvas].bounds.height - stock.stock_prices[new_x - 1] - 1, new_x, new_y)
|
101
|
+
tab[:stock_transforms][stock_index] ||= transform {
|
102
|
+
translate max_stock_name_width + 5 + left_margin, tab[:text].bounds.height / 2.0
|
103
|
+
}
|
104
|
+
}
|
105
|
+
end
|
106
|
+
when 'Lines'
|
107
|
+
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
|
+
}
|
112
|
+
}
|
113
|
+
when 'Points'
|
114
|
+
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
|
+
}
|
119
|
+
}
|
120
|
+
end
|
121
|
+
new_x_location = new_x + max_stock_name_width + 5 + left_margin + 5
|
122
|
+
canvas_width = tab[:canvas].bounds.width
|
123
|
+
if new_x_location > canvas_width
|
124
|
+
tab[:canvas].set_size(new_x_location, @tabs.first[:canvas].bounds.height)
|
125
|
+
tab[:canvas].cursor = :hand
|
126
|
+
tab[:scrolled_composite].set_min_size(new_x_location, @tabs.first[:canvas].bounds.height)
|
127
|
+
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
|
+
end
|
129
|
+
else
|
130
|
+
tab[:canvas].content {
|
131
|
+
tab[:text] = text(stock.name, new_x + left_margin, new_y) {
|
132
|
+
foreground @stock_colors[stock_index]
|
133
|
+
}
|
134
|
+
}
|
135
|
+
end
|
136
|
+
end
|
137
|
+
rescue => e
|
138
|
+
Glimmer::Config.logger.error {e.full_message}
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
}
|
143
|
+
|
144
|
+
after_body {
|
145
|
+
@thread = Thread.new {
|
146
|
+
loop {
|
147
|
+
@stocks.each(&:tick!)
|
148
|
+
sleep(0.01)
|
149
|
+
}
|
150
|
+
}
|
151
|
+
}
|
152
|
+
|
153
|
+
body {
|
154
|
+
shell {
|
155
|
+
fill_layout {
|
156
|
+
margin_width 15
|
157
|
+
margin_height 15
|
158
|
+
}
|
159
|
+
text 'Stock Ticker'
|
160
|
+
minimum_size 650, 650
|
161
|
+
background :white
|
162
|
+
|
163
|
+
@tab_folder = tab_folder {
|
164
|
+
@tabs.each do |tab|
|
165
|
+
tab_item {
|
166
|
+
fill_layout {
|
167
|
+
margin_width 0
|
168
|
+
margin_height 0
|
169
|
+
}
|
170
|
+
text tab[:title]
|
171
|
+
|
172
|
+
tab[:scrolled_composite] = scrolled_composite {
|
173
|
+
tab[:canvas] = canvas {
|
174
|
+
background :white
|
175
|
+
|
176
|
+
@stocks.count.times do |stock_index|
|
177
|
+
tab[:stock_paths][stock_index] = path {
|
178
|
+
antialias :on
|
179
|
+
foreground @stock_colors[stock_index]
|
180
|
+
}
|
181
|
+
end
|
182
|
+
|
183
|
+
on_mouse_down {
|
184
|
+
@drag_detected = false
|
185
|
+
}
|
186
|
+
|
187
|
+
on_drag_detected { |drag_detect_event|
|
188
|
+
@drag_detected = true
|
189
|
+
@drag_start_x = drag_detect_event.x
|
190
|
+
@drag_start_y = drag_detect_event.y
|
191
|
+
}
|
192
|
+
|
193
|
+
on_mouse_move { |mouse_event|
|
194
|
+
if @drag_detected
|
195
|
+
origin = tab[:scrolled_composite].origin
|
196
|
+
new_x = origin.x - (mouse_event.x - @drag_start_x)
|
197
|
+
new_y = origin.y - (mouse_event.y - @drag_start_y)
|
198
|
+
tab[:scrolled_composite].set_origin(new_x, new_y)
|
199
|
+
end
|
200
|
+
}
|
201
|
+
|
202
|
+
on_mouse_up { |mouse_event|
|
203
|
+
@drag_detected = false
|
204
|
+
}
|
205
|
+
}
|
206
|
+
}
|
207
|
+
}
|
208
|
+
end
|
209
|
+
}
|
210
|
+
|
211
|
+
on_swt_show {
|
212
|
+
Stock.stock_price_min = 25
|
213
|
+
Stock.stock_price_max = @tabs.first[:canvas].bounds.height - 6
|
214
|
+
# pre-initialize all tabs by selecting them so that they render content when they are later in the background
|
215
|
+
@tab_folder.items.each do |item|
|
216
|
+
@tab_folder.selection = item
|
217
|
+
end
|
218
|
+
@tab_folder.selection = @tab_folder.items.first
|
219
|
+
}
|
220
|
+
|
221
|
+
on_widget_disposed {
|
222
|
+
@thread.kill # safe to kill as data is in memory only
|
223
|
+
}
|
224
|
+
}
|
225
|
+
}
|
226
|
+
end
|
227
|
+
|
228
|
+
StockTicker.launch
|
229
|
+
|
@@ -1,223 +1,66 @@
|
|
1
|
-
# Copyright (c) 2007-2021 Andy Maleh
|
2
|
-
#
|
3
|
-
# Permission is hereby granted, free of charge, to any person obtaining
|
4
|
-
# a copy of this software and associated documentation files (the
|
5
|
-
# "Software"), to deal in the Software without restriction, including
|
6
|
-
# without limitation the rights to use, copy, modify, merge, publish,
|
7
|
-
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
-
# permit persons to whom the Software is furnished to do so, subject to
|
9
|
-
# the following conditions:
|
10
|
-
#
|
11
|
-
# The above copyright notice and this permission notice shall be
|
12
|
-
# included in all copies or substantial portions of the Software.
|
13
|
-
#
|
14
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
-
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
-
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
-
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
-
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
-
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
-
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
-
|
22
1
|
require 'glimmer-dsl-swt'
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
class HelloCanvasPath
|
27
|
-
class Stock
|
28
|
-
class << self
|
29
|
-
attr_writer :stock_price_min, :stock_price_max
|
30
|
-
|
31
|
-
def stock_price_min
|
32
|
-
@stock_price_min ||= 1
|
33
|
-
end
|
34
|
-
|
35
|
-
def stock_price_max
|
36
|
-
@stock_price_max ||= 600
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
attr_reader :name, :stock_prices
|
41
|
-
attr_accessor :stock_price
|
42
|
-
|
43
|
-
def initialize(name, stock_price)
|
44
|
-
@name = name
|
45
|
-
@stock_price = stock_price
|
46
|
-
@stock_prices = [@stock_price]
|
47
|
-
@delta_sign = 1
|
48
|
-
start_new_trend!
|
49
|
-
end
|
50
|
-
|
51
|
-
def tick!
|
52
|
-
@tick_count = @tick_count.to_i + 1
|
53
|
-
delta = @tick_count%@trend_length
|
54
|
-
if delta == 0
|
55
|
-
@delta_sign *= -1
|
56
|
-
start_new_trend!
|
57
|
-
end
|
58
|
-
stock_prices << self.stock_price = [[@stock_price + @delta_sign*delta, Stock.stock_price_min].max, Stock.stock_price_max].min
|
59
|
-
end
|
60
|
-
|
61
|
-
def start_new_trend!
|
62
|
-
@trend_length = (rand*25).to_i + 1
|
63
|
-
end
|
64
|
-
end
|
2
|
+
|
3
|
+
include Glimmer
|
65
4
|
|
66
|
-
|
5
|
+
shell {
|
6
|
+
text 'Hello, Canvas Path!'
|
7
|
+
minimum_size 800, 700
|
8
|
+
background :white
|
67
9
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
@stock_colors = [:red, :dark_green, :blue, :magenta]
|
74
|
-
max_stock_name_width = 0
|
75
|
-
left_margin = 5
|
76
|
-
@tabs = ['Cubic Bezier Curves', 'Quadratic Bezier Curves', 'Lines', 'Points'].map {|title| {title: title, paths: [], transforms: []}}
|
77
|
-
@stocks.each_with_index do |stock, i|
|
78
|
-
x = 0
|
79
|
-
observe(stock, :stock_price) do |new_price|
|
80
|
-
begin
|
81
|
-
@tabs.each do |tab|
|
82
|
-
new_x = x
|
83
|
-
new_y = @tabs.first[:canvas].bounds.height - new_price - 1
|
84
|
-
max_stock_name_width = tab[:text]&.bounds&.width if tab[:text]&.bounds&.width.to_f > max_stock_name_width
|
85
|
-
if new_x > 0
|
86
|
-
case tab[:title]
|
87
|
-
when 'Cubic Bezier Curves'
|
88
|
-
if stock.stock_prices[i] && stock.stock_prices[i - 1] && stock.stock_prices[i - 2]
|
89
|
-
tab[:paths][i].content {
|
90
|
-
cubic(new_x - 2, @tabs.first[:canvas].bounds.height - stock.stock_prices[i - 2] - 1, new_x - 1, @tabs.first[:canvas].bounds.height - stock.stock_prices[i - 1] - 1, new_x, new_y)
|
91
|
-
tab[:transforms][i] ||= transform {
|
92
|
-
translate max_stock_name_width + 5 + left_margin, tab[:text].bounds.height / 2.0
|
93
|
-
}
|
94
|
-
}
|
95
|
-
end
|
96
|
-
when 'Quadratic Bezier Curves'
|
97
|
-
if stock.stock_prices[i] && stock.stock_prices[i - 1]
|
98
|
-
tab[:paths][i].content {
|
99
|
-
quad(new_x - 1, @tabs.first[:canvas].bounds.height - stock.stock_prices[i - 1] - 1, new_x, new_y)
|
100
|
-
tab[:transforms][i] ||= transform {
|
101
|
-
translate max_stock_name_width + 5 + left_margin, tab[:text].bounds.height / 2.0
|
102
|
-
}
|
103
|
-
}
|
104
|
-
end
|
105
|
-
when 'Lines'
|
106
|
-
tab[:paths][i].content {
|
107
|
-
line(new_x, new_y)
|
108
|
-
tab[:transforms][i] ||= transform {
|
109
|
-
translate max_stock_name_width + 5 + left_margin, tab[:text].bounds.height / 2.0
|
110
|
-
}
|
111
|
-
}
|
112
|
-
when 'Points'
|
113
|
-
tab[:paths][i].content {
|
114
|
-
point(new_x, new_y)
|
115
|
-
tab[:transforms][i] ||= transform {
|
116
|
-
translate max_stock_name_width + 5 + left_margin, tab[:text].bounds.height / 2.0
|
117
|
-
}
|
118
|
-
}
|
119
|
-
end
|
120
|
-
new_x_location = new_x + max_stock_name_width + 5 + left_margin + 5
|
121
|
-
canvas_width = tab[:canvas].bounds.width
|
122
|
-
if new_x_location > canvas_width
|
123
|
-
tab[:canvas].set_size(new_x_location, @tabs.first[:canvas].bounds.height)
|
124
|
-
tab[:canvas].cursor = :hand
|
125
|
-
tab[:scrolled_composite].set_min_size(new_x_location, @tabs.first[:canvas].bounds.height)
|
126
|
-
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
|
127
|
-
end
|
128
|
-
else
|
129
|
-
tab[:canvas].content {
|
130
|
-
tab[:text] = text(stock.name, new_x + left_margin, new_y) {
|
131
|
-
foreground @stock_colors[i]
|
132
|
-
}
|
133
|
-
}
|
134
|
-
end
|
135
|
-
end
|
136
|
-
x += 1
|
137
|
-
rescue => e
|
138
|
-
Glimmer::Config.logger.error {e.full_message}
|
139
|
-
end
|
140
|
-
end
|
141
|
-
end
|
142
|
-
}
|
143
|
-
|
144
|
-
after_body {
|
145
|
-
@thread = Thread.new {
|
146
|
-
loop {
|
147
|
-
@stocks.each(&:tick!)
|
148
|
-
sleep(0.01)
|
10
|
+
canvas {
|
11
|
+
background :white
|
12
|
+
|
13
|
+
text('line', 15, 200) {
|
14
|
+
foreground :red
|
149
15
|
}
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
body {
|
154
|
-
shell {
|
155
|
-
fill_layout {
|
156
|
-
margin_width 15
|
157
|
-
margin_height 15
|
16
|
+
@path1 = path {
|
17
|
+
antialias :on
|
18
|
+
foreground :red
|
158
19
|
}
|
159
|
-
text 'Hello, Canvas Path!'
|
160
|
-
minimum_size 650, 650
|
161
|
-
background :white
|
162
20
|
|
163
|
-
|
164
|
-
|
165
|
-
tab_item {
|
166
|
-
fill_layout {
|
167
|
-
margin_width 0
|
168
|
-
margin_height 0
|
169
|
-
}
|
170
|
-
text tab[:title]
|
171
|
-
|
172
|
-
tab[:scrolled_composite] = scrolled_composite {
|
173
|
-
tab[:canvas] = canvas {
|
174
|
-
background :white
|
175
|
-
|
176
|
-
@stocks.count.times do |n|
|
177
|
-
tab[:paths][n] = path {
|
178
|
-
foreground @stock_colors[n]
|
179
|
-
}
|
180
|
-
end
|
181
|
-
|
182
|
-
on_mouse_down {
|
183
|
-
@drag_detected = false
|
184
|
-
}
|
185
|
-
|
186
|
-
on_drag_detected { |drag_detect_event|
|
187
|
-
@drag_detected = true
|
188
|
-
@drag_start_x = drag_detect_event.x
|
189
|
-
@drag_start_y = drag_detect_event.y
|
190
|
-
}
|
191
|
-
|
192
|
-
on_mouse_move { |mouse_event|
|
193
|
-
if @drag_detected
|
194
|
-
origin = tab[:scrolled_composite].origin
|
195
|
-
new_x = origin.x - (mouse_event.x - @drag_start_x)
|
196
|
-
new_y = origin.y - (mouse_event.y - @drag_start_y)
|
197
|
-
tab[:scrolled_composite].set_origin(new_x, new_y)
|
198
|
-
end
|
199
|
-
}
|
200
|
-
|
201
|
-
on_mouse_up { |mouse_event|
|
202
|
-
@drag_detected = false
|
203
|
-
}
|
204
|
-
}
|
205
|
-
}
|
206
|
-
}
|
207
|
-
end
|
21
|
+
text('quad', 15, 300) {
|
22
|
+
foreground :dark_green
|
208
23
|
}
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
Stock.stock_price_max = @tabs.first[:canvas].bounds.height - 6
|
24
|
+
@path2 = path {
|
25
|
+
antialias :on
|
26
|
+
foreground :dark_green
|
213
27
|
}
|
214
28
|
|
215
|
-
|
216
|
-
|
29
|
+
text('cubic', 15, 400) {
|
30
|
+
foreground :blue
|
217
31
|
}
|
32
|
+
@path3 = path {
|
33
|
+
antialias :on
|
34
|
+
foreground :blue
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
on_swt_show {
|
39
|
+
Thread.new {
|
40
|
+
y1 = y2 = y3 = 300
|
41
|
+
800.times.each do |x|
|
42
|
+
x += 55
|
43
|
+
x1 = x - 2
|
44
|
+
x2 = x - 1
|
45
|
+
x3 = x
|
46
|
+
y1 = y3
|
47
|
+
y2 = y1
|
48
|
+
y3 = [[y3 + (rand*24 - 12), 0].max, 700].min
|
49
|
+
@path1.content {
|
50
|
+
line(x1, y1 - 100)
|
51
|
+
}
|
52
|
+
if x % 2 == 0
|
53
|
+
@path2.content {
|
54
|
+
quad(x1, y1, x2, y2)
|
55
|
+
}
|
56
|
+
end
|
57
|
+
if x % 3 == 0
|
58
|
+
@path3.content {
|
59
|
+
cubic(x1, y1 + 100, x2, y2 + 100, x3, y3 + 100)
|
60
|
+
}
|
61
|
+
end
|
62
|
+
sleep(0.01)
|
63
|
+
end
|
218
64
|
}
|
219
65
|
}
|
220
|
-
|
221
|
-
|
222
|
-
HelloCanvasPath.launch
|
223
|
-
|
66
|
+
}.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.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- AndyMaleh
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-03-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -485,6 +485,7 @@ files:
|
|
485
485
|
- samples/elaborate/login.rb
|
486
486
|
- samples/elaborate/mandelbrot_fractal.rb
|
487
487
|
- samples/elaborate/meta_sample.rb
|
488
|
+
- samples/elaborate/stock_ticker.rb
|
488
489
|
- samples/elaborate/tetris.rb
|
489
490
|
- samples/elaborate/tetris/model/block.rb
|
490
491
|
- samples/elaborate/tetris/model/game.rb
|