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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6951b42a995fd393c82fcb406f5bb308aacf9330d75b85e0050104451044870c
4
- data.tar.gz: 1de171314b2b6da4c80e295152a91697085e8bc7b00502fb0af88aef2890defc
3
+ metadata.gz: 6d4f89641fcc2573b43cd52e23cf4dda45aa209e55cd49cbe751f6a4b7bc85b1
4
+ data.tar.gz: 9cf53e2b5aef11f838314b50188f63b3a69936ea31f54930da77bddfd561b08e
5
5
  SHA512:
6
- metadata.gz: d996c3707e136ec0e059396a3a06d301953236acbde4012f428fdc85dab3e13843296ace25426d41fa6fe7d87031ab5990a40e62a2b572bfbd47b97759575892
7
- data.tar.gz: 5c317cdc5e75597d03bf241436cad374cd05e64d4a91739d08945ed2b4a5464807128eb25f23b271a057fdb4dd7b79372eee3c68f6f336a4fd27af8448ce31a9
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.0
1
+ # [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for 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.0 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.
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.0
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.0'
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
1
+ 4.18.6.2
@@ -1976,7 +1976,6 @@ shell {
1976
1976
  canvas {
1977
1977
  path {
1978
1978
  foreground :black
1979
- point(0, 0)
1980
1979
  250.times {|n|
1981
1980
  cubic(n + n%30, n+ n%50, 40, 40, 70, 70, n + 20 + n%30, n%30*-1 * n%50)
1982
1981
  }
@@ -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
  ```
@@ -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.1 ruby lib
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.1"
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-01"
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",
@@ -99,7 +99,7 @@ module Glimmer
99
99
  def ensure_arg_values_within_valid_bounds
100
100
  if @args.to_a.size >= 3
101
101
  @args = @args.map do |value|
102
- [[value, 255].min, 0].max
102
+ [[value.to_f, 255].min, 0].max
103
103
  end
104
104
  end
105
105
  end
@@ -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[0..1]
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
- x1 == (other && other.respond_to?(:x1) && other.x1) &&
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 dispose
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
- super
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
- @swt_path ||= org.eclipse.swt.graphics.Path.new(Glimmer::SWT::DisplayProxy.instance.swt_display)
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
- @swt_path.moveTo(*point)
119
+ geometry.moveTo(point[0], point[1])
98
120
  elsif first_path_segment?
99
121
  point = the_path_segment_geometry_args[0..1]
100
- @swt_path.moveTo(*point)
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.to_a
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 :stock_price_min, :stock_price_max
29
+ attr_writer :price_min, :price_max
30
30
 
31
- def stock_price_min
32
- @stock_price_min ||= 1
31
+ def price_min
32
+ @price_min ||= 1
33
33
  end
34
34
 
35
- def stock_price_max
36
- @stock_price_max ||= 600
35
+ def price_max
36
+ @price_max ||= 600
37
37
  end
38
38
  end
39
39
 
40
- attr_reader :name, :stock_prices
41
- attr_accessor :stock_price
40
+ attr_reader :name, :prices
41
+ attr_accessor :price
42
42
 
43
- def initialize(name, stock_price)
43
+ def initialize(name, price)
44
44
  @name = name
45
- @stock_price = stock_price
46
- @stock_prices = [@stock_price]
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
- stock_prices << self.stock_price = [[@stock_price + @delta_sign*delta, Stock.stock_price_min].max, Stock.stock_price_max].min
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
- 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: []}}
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, :stock_price) do |new_price|
79
+ observe(stock, :price) do |new_price|
81
80
  begin
82
81
  @tabs.each do |tab|
83
- new_x = stock.stock_prices.count - 1
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.stock_prices[new_x] && stock.stock_prices[new_x - 1] && stock.stock_prices[new_x - 2]
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.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
- }
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.stock_prices[new_x] && stock.stock_prices[new_x - 1]
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.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
- }
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 + max_stock_name_width + 5 + left_margin + 5
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[:canvas].content {
131
- tab[:text] = text(stock.name, new_x + left_margin, new_y) {
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
- fill_layout {
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.stock_price_min = 25
213
- Stock.stock_price_max = @tabs.first[:canvas].bounds.height - 6
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
- canvas {
11
- background :white
12
-
13
- text('line', 15, 200) {
14
- foreground :red
15
- }
16
- @path1 = path {
17
- antialias :on
18
- foreground :red
19
- }
20
-
21
- text('quad', 15, 300) {
22
- foreground :dark_green
23
- }
24
- @path2 = path {
25
- antialias :on
26
- foreground :dark_green
27
- }
28
-
29
- text('cubic', 15, 400) {
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
- 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
- }
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
- 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
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.1
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-01 00:00:00.000000000 Z
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