glimmer-dsl-swt 4.18.1.1 → 4.18.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/README.md +84 -37
- data/VERSION +1 -1
- data/glimmer-dsl-swt.gemspec +3 -3
- data/lib/glimmer/swt/custom/animation.rb +138 -15
- data/lib/glimmer/swt/custom/code_text.rb +2 -1
- data/lib/glimmer/swt/custom/shape.rb +51 -12
- data/samples/hello/hello_canvas.rb +28 -8
- metadata +14 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: beefdf4e3985d47de8a553ea073466812c89a738a1efa691bac62a9d375bb5b9
|
4
|
+
data.tar.gz: ed6373191af3b73886ae171313d0fbcd279205c883f887e2c940cbc0318275a3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 52eaa3d36b54333a9c457233a00de3975c3e932f99ef7b9b484fdff20c6f96ea2b7465a63f6e2cc46b91b86a3631edef913643b2303103fc2901920402459bea
|
7
|
+
data.tar.gz: 84273ec05bc34a8a233d403edba5ad372a631560252cfec36d3d5bd200410a1a0f9184e07ebb77d0241ae3ea723d6c7575f7441575a61115f53d9c302fb54fb5
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
### 4.18.2.0
|
4
|
+
|
5
|
+
- Canvas animation start method (useful if animation had a frame count limit or cycle count limit and needed to be started again after it stopped)
|
6
|
+
- Canvas animation stop method
|
7
|
+
- Canvas animation restart method (restarts from frame 1)
|
8
|
+
- Canvas animation started? # meaning it is animating
|
9
|
+
- Canvas animation stopped? # meaning it has stopped animating
|
10
|
+
- Canvas animation duration_limit option
|
11
|
+
- Make gradient/round rectangles in Shape DSL receive an option of `gradient: true` and `round: true` instead of prefix
|
12
|
+
- Canvas Shape DSL support for Background/Foreground Pattern (NOTE: not extensively tested yet)
|
13
|
+
- Canvas Shape DSL smart defaults for background/foreground depending on shape being drawn
|
14
|
+
- Canvas Shape DSL smart defaults for fill option depending on shape being drawn
|
15
|
+
- Added fallback font "Courier" for `code_text` widget when "Consolas" is not available.
|
16
|
+
|
3
17
|
### 4.18.1.1
|
4
18
|
|
5
19
|
- Add smart defaults for round rectangle angles (defaults to 60 degrees angles)
|
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.
|
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.2.0
|
2
2
|
|
3
3
|
|
4
4
|
## JRuby Desktop Development GUI Framework
|
@@ -12,7 +12,7 @@
|
|
12
12
|
|
13
13
|
(The Original Glimmer Library Since 2007. Beware of Imitators!)
|
14
14
|
|
15
|
-
[Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer) is a native-GUI cross-platform desktop development library written in [JRuby](https://www.jruby.org/), an OS-threaded faster version of [Ruby](https://www.ruby-lang.org/en/). [Glimmer](https://github.com/AndyObtiva/glimmer)'s main innovation is a declarative [Ruby DSL](#glimmer-dsl-syntax) that enables productive and efficient authoring of desktop application user-interfaces
|
15
|
+
[Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer) is a native-GUI cross-platform desktop development library written in [JRuby](https://www.jruby.org/), an OS-threaded faster version of [Ruby](https://www.ruby-lang.org/en/). [Glimmer](https://github.com/AndyObtiva/glimmer)'s main innovation is a declarative [Ruby DSL](#glimmer-dsl-syntax) that enables productive and efficient authoring of desktop application user-interfaces by relying on the robust [Eclipse SWT library](https://www.eclipse.org/swt/). [Glimmer](https://rubygems.org/gems/glimmer) additionally innovates by having built-in [data-binding](#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](#widgets), but also supports drawing Canvas Graphics like [Shapes](#canvas-shape-dsl) and [Animations](#canvas-animation-dsl). To get started quickly, [Glimmer](https://rubygems.org/gems/glimmer) offers [scaffolding](#scaffolding) options for [Apps](#in-production), [Gems](#custom-shell-gem), and [Custom Widgets](#custom-widgets). [Glimmer](https://rubygems.org/gems/glimmer) also includes native-executable [packaging](#packaging--distribution) support, sorely lacking in other libraries, thus enabling the delivery of desktop apps written in [Ruby](https://www.ruby-lang.org/en/) as truly native DMG/PKG/APP files on the [Mac](https://www.apple.com/ca/macos) + [App Store](https://developer.apple.com/macos/distribution/), MSI/EXE files on [Windows](https://www.microsoft.com/en-ca/windows), and [Gem Packaged Shell Scripts](#custom-shell-gem) on [Linux](https://www.linux.org/).
|
16
16
|
|
17
17
|
[Glimmer receives two updates per month](https://rubygems.org/gems/glimmer-dsl-swt/versions). You can trust [Glimmer](https://rubygems.org/gems/glimmer) with your Ruby desktop GUI development needs. Please make [Glimmer](https://rubygems.org/gems/glimmer) even better by providing feedback and [contributing](#contributing) when possible.
|
18
18
|
|
@@ -456,7 +456,7 @@ jgem install glimmer-dsl-swt
|
|
456
456
|
|
457
457
|
Or this command if you want a specific version:
|
458
458
|
```
|
459
|
-
jgem install glimmer-dsl-swt -v 4.18.
|
459
|
+
jgem install glimmer-dsl-swt -v 4.18.2.0
|
460
460
|
|
461
461
|
|
462
462
|
```
|
@@ -476,7 +476,7 @@ Note: if you're using activerecord or activesupport, keep in mind that Glimmer u
|
|
476
476
|
|
477
477
|
Add the following to `Gemfile`:
|
478
478
|
```
|
479
|
-
gem 'glimmer-dsl-swt', '~> 4.18.
|
479
|
+
gem 'glimmer-dsl-swt', '~> 4.18.2.0
|
480
480
|
'
|
481
481
|
```
|
482
482
|
|
@@ -535,7 +535,7 @@ bin/glimmer samples
|
|
535
535
|
Below are the full usage instructions that come up when running `glimmer` without args.
|
536
536
|
|
537
537
|
```
|
538
|
-
Glimmer (JRuby Desktop Development GUI Framework) - JRuby Gem: glimmer-dsl-swt v4.18.
|
538
|
+
Glimmer (JRuby Desktop Development GUI Framework) - JRuby Gem: glimmer-dsl-swt v4.18.2.0
|
539
539
|
|
540
540
|
|
541
541
|
|
@@ -1016,7 +1016,7 @@ Output:
|
|
1016
1016
|
|
1017
1017
|
Css glimmer-dsl-css 1.1.0 AndyMaleh Glimmer DSL for CSS
|
1018
1018
|
Opal glimmer-dsl-opal 0.10.2 AndyMaleh Glimmer DSL for Opal
|
1019
|
-
Swt glimmer-dsl-swt 4.18.
|
1019
|
+
Swt glimmer-dsl-swt 4.18.2.0
|
1020
1020
|
|
1021
1021
|
AndyMaleh Glimmer DSL for SWT
|
1022
1022
|
Tk glimmer-dsl-tk 0.0.6 AndyMaleh Glimmer DSL for Tk
|
@@ -2294,43 +2294,46 @@ https://help.eclipse.org/2019-12/nftopic/org.eclipse.platform.doc.isv/reference/
|
|
2294
2294
|
|
2295
2295
|
### Canvas Shape DSL
|
2296
2296
|
|
2297
|
-
(note: this is a very new feature of Glimmer. It may change a bit while getting battle tested. As always, you could default to basic SWT usage if needed.)
|
2298
|
-
|
2299
2297
|
Glimmer supports drawing graphics directly on a `canvas` widget via SWT (or any widget for that matter though `canvas` is recommended for drawing).
|
2300
2298
|
|
2301
2299
|
This is accomplished via the Shape DSL a sub-DSL of the Glimmer GUI DSL, which makes it possible to draw graphics declaratively with very understandable and maintainable syntax.
|
2302
2300
|
|
2303
2301
|
Shape keywords and their args (including defaults) are listed below (they basically match method names and arguments on [org.eclipse.swt.graphics.GC](https://help.eclipse.org/2020-12/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/graphics/GC.html) minus the `draw` or `fill` prefix in downcase):
|
2304
|
-
- `arc(x, y, width, height, startAngle, arcAngle, fill: false)`
|
2305
|
-
- `focus(x, y, width, height)`
|
2306
|
-
- `image(image, x, y)`
|
2307
|
-
- `line(x1, y1, x2, y2)`
|
2308
|
-
- `oval(x, y, width, height, fill: false)`
|
2309
|
-
- `point(x, y)`
|
2310
|
-
- `polygon(pointArray, fill: false)`
|
2311
|
-
- `polyline(pointArray)`
|
2312
|
-
- `rectangle(x, y, width, height, fill: false)`
|
2313
|
-
- `
|
2314
|
-
- `
|
2315
|
-
- `text(
|
2302
|
+
- `arc(x, y, width, height, startAngle, arcAngle, fill: false)` arc is part of a circle within an oval area, denoted by start angle (degrees) and end angle (degrees)
|
2303
|
+
- `focus(x, y, width, height)` this is just like rectangle but its foreground color is always that of the OS widget focus color (useful when capturing user interaction via a shape)
|
2304
|
+
- `image(image, x, y)` [image](#image)
|
2305
|
+
- `line(x1, y1, x2, y2)` line
|
2306
|
+
- `oval(x, y, width, height, fill: false)` oval if width does not match heigh and circle if width matches height. Can be optionally filled.
|
2307
|
+
- `point(x, y)` point
|
2308
|
+
- `polygon(pointArray, fill: false)` polygon consisting of points, which close automatically to form a shape that can be optionally filled (when points only form a line, it does not show up as filled)
|
2309
|
+
- `polyline(pointArray)` polyline is just like a polygon, but it does not close up to form a shape, remaining open (unless the points close themselves by having the last point or an intermediate point match the first)
|
2310
|
+
- `rectangle(x, y, width, height, fill: false)` standard rectangle, which can be optionally filled
|
2311
|
+
- `rectangle(x, y, width, height, arcWidth = 60, arcHeight = 60, fill: false, round: true)` round rectangle, which can be optionally filled, and takes optional extra round angle arguments
|
2312
|
+
- `rectangle(x, y, width, height, vertical = true, fill: true, gradient: true)` gradient rectangle, which is always filled, and takes an optional extra argument to specify true for vertical gradient (default) and false for horizontal gradient
|
2313
|
+
- `text(string, x, y, flags = nil)` text with optional flags (flag format is `swt(comma_separated_flags)` where flags can be :draw_delimiter (i.e. new lines), :draw_tab, :draw_mnemonic, and :draw_transparent as explained in [GC API](https://help.eclipse.org/2020-12/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/graphics/GC.html))
|
2316
2314
|
|
2317
2315
|
Shape keywords that can be filled with color can take an keyword argument `fill: true` (defaults to false when not specified)
|
2318
2316
|
|
2319
2317
|
Optionally, a shape keyword takes a block that can set any attributes from [org.eclipse.swt.graphics.GC](https://help.eclipse.org/2020-12/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/graphics/GC.html) (methods starting with `set`), which enable setting the `background` for filling and `foreground` for drawing.
|
2320
2318
|
|
2321
2319
|
Here is a list of supported attributes nestable within a block under shapes:
|
2322
|
-
- `
|
2323
|
-
- `
|
2324
|
-
- `
|
2325
|
-
- `
|
2326
|
-
- `
|
2327
|
-
- `
|
2328
|
-
- `
|
2329
|
-
- `
|
2330
|
-
- `
|
2331
|
-
- `
|
2320
|
+
- `advanced` enables advanced graphics subsystem (boolean value). Typically gets enabled automatically when setting alpha, antialias, patterns, interpolation, clipping. Rendering sometimes differs between advanced and non-advanced mode for basic graphics too, so you could enable manually if you prefer its look even for basic graphics.
|
2321
|
+
- `alpha` sets transparency (integer between `0` and `255`)
|
2322
|
+
- `antialias` enables antialiasing (SWT style value of `:default`, `:off`, `:on` whereby `:default` applies OS default, which varies per OS)
|
2323
|
+
- `background` sets fill color for fillable shapes (standard color symbol (e.g. `:red`), `rgb(red_integer, green_integer, blue_integer)` color, or Color/ColorProxy object directly)
|
2324
|
+
- `background_pattern` sets fill gradient/image pattern for fillable shape background (takes the same arguments as the SWT [Pattern](https://help.eclipse.org/2020-12/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/graphics/Pattern.html) class [e.g. `background_pattern 2.3, 4.2, 5.4, 7.2, :red, :blue`] / note: this feature isn't extensively tested yet)
|
2325
|
+
- `clipping` clips area of painting (numeric values for `(x, y, width, height)`)
|
2326
|
+
- `fill_rule` sets filling rule (SWT style value of `:fill_even_odd` or `:fill_winding`)
|
2327
|
+
- `font` sets font (Hash of `:name`, `:height`, and `:style` just like standard widget font property, or Font/FontProxy object directly)
|
2328
|
+
- `foreground` sets draw color for drawable shapes (standard color symbol (e.g. `:red`), `rgb(red_integer, green_integer, blue_integer)` color, or Color/ColorProxy object directly)
|
2329
|
+
- `foreground_pattern` sets foreground gradient/image pattern for drawable shape lines (takes the same arguments as the SWT [Pattern](https://help.eclipse.org/2020-12/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/graphics/Pattern.html) class [e.g. `foreground_pattern 2.3, 4.2, 5.4, 7.2, :red, :blue`] / note: this feature isn't extensively tested yet)
|
2330
|
+
- `interpolation` sets the interpolation value (SWT style value of `:default`, `:none`, `:low`, `:high`)
|
2331
|
+
- `line_cap` sets line cap (SWT style value of `:cap_flat`, `:cap_round`, or `:cap_square`)
|
2332
|
+
- `line_dash` line dash float values (automatically sets `line_style` to SWT style value of `:line_custom`)
|
2333
|
+
- `line_join` line join style (SWT style value of `:join_miter`, `:join_round`, or `:join_bevel`)
|
2334
|
+
- `line_style` line join style (SWT style value of `:line_solid`, `:line_dash`, `:line_dot`, `:line_dashdot`, or `:line_dashdotdot`)
|
2332
2335
|
- `line_width` line width in integer (used in draw operations)
|
2333
|
-
- `text_anti_alias` enables text antialiasing (SWT style value of
|
2336
|
+
- `text_anti_alias` enables text antialiasing (SWT style value of `:default`, `:off`, `:on` whereby `:default` applies OS default, which varies per OS)
|
2334
2337
|
|
2335
2338
|
Example (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
|
2336
2339
|
|
@@ -2346,10 +2349,10 @@ shell {
|
|
2346
2349
|
rectangle(0, 0, 220, 400, fill: true) {
|
2347
2350
|
background :red
|
2348
2351
|
}
|
2349
|
-
|
2352
|
+
rectangle(50, 20, 300, 150, 30, 50, round: true, fill: true) {
|
2350
2353
|
background :magenta
|
2351
2354
|
}
|
2352
|
-
|
2355
|
+
rectangle(150, 200, 100, 70, true, gradient: true) {
|
2353
2356
|
background :dark_magenta
|
2354
2357
|
foreground :yellow
|
2355
2358
|
}
|
@@ -2366,6 +2369,39 @@ Screenshot:
|
|
2366
2369
|
|
2367
2370
|
Learn more at the [Hello, Canvas! Sample](#hello-canvas).
|
2368
2371
|
|
2372
|
+
If you get extremely stuck, remember that you could always default to direct [SWT GC usage]([org.eclipse.swt.graphics.GC](https://help.eclipse.org/2020-12/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/graphics/GC.html) and learn more at the [SWT Graphics Guide](https://www.eclipse.org/articles/Article-SWT-graphics/SWT_graphics.html) and [SWT Image Guide](https://www.eclipse.org/articles/Article-SWT-images/graphics-resources.html#Saving%20Images).
|
2373
|
+
|
2374
|
+
Example of manually doing the same things as in the above example without relying on the declarative Glimmer Shape DSL:
|
2375
|
+
|
2376
|
+
```ruby
|
2377
|
+
include Glimmer
|
2378
|
+
|
2379
|
+
shell {
|
2380
|
+
text 'Canvas Manual Example'
|
2381
|
+
minimum_size 320, 400
|
2382
|
+
|
2383
|
+
canvas {
|
2384
|
+
background :yellow
|
2385
|
+
|
2386
|
+
on_paint_control { |event|
|
2387
|
+
event.gc.setBackground(color(:red).swt_color)
|
2388
|
+
event.gc.fillRectangle(0, 0, 220, 400)
|
2389
|
+
|
2390
|
+
event.gc.setBackground(color(:magenta).swt_color)
|
2391
|
+
event.gc.fillRoundRectangle(50, 20, 300, 150, 30, 50)
|
2392
|
+
|
2393
|
+
event.gc.setBackground(color(:dark_magenta).swt_color)
|
2394
|
+
event.gc.fillGradientRectangle(150, 200, 100, 70, true)
|
2395
|
+
|
2396
|
+
event.gc.setForeground(color(:dark_blue).swt_color)
|
2397
|
+
event.gc.drawRectangle(200, 80, 108, 36)
|
2398
|
+
}
|
2399
|
+
}
|
2400
|
+
}.open
|
2401
|
+
```
|
2402
|
+
|
2403
|
+
In any case, if there is anything you would like added to the Glimmer Shape DSL that you saw available in the SWT APIs, you may [report and issue](https://github.com/AndyObtiva/glimmer-dsl-swt/issues) or implement yourself and [contribute](#contributing) via a Pull Request.
|
2404
|
+
|
2369
2405
|
### Canvas Animation DSL
|
2370
2406
|
|
2371
2407
|
(note: this is a very new feature of Glimmer. It may change a bit while getting battle tested. As always, you could default to basic SWT usage if needed.)
|
@@ -2374,7 +2410,7 @@ Glimmer additionally provides built-in support for animations via a declarative
|
|
2374
2410
|
|
2375
2411
|
Animations take advantage of multi-threading, each animation runs in its own independent thread of execution while updating the GUI asynchronously.
|
2376
2412
|
|
2377
|
-
This example says it all (it moves a tiny red square across a blue background):
|
2413
|
+
This example says it all (it moves a tiny red square across a blue background) (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
|
2378
2414
|
|
2379
2415
|
```ruby
|
2380
2416
|
include Glimmer
|
@@ -2411,12 +2447,23 @@ Keywords:
|
|
2411
2447
|
- `frame_count` an optional frame count limit after which the animation stops
|
2412
2448
|
- `started` a boolean indicating if the animation is started right away or stopped waiting for manual startup via `#start` method
|
2413
2449
|
|
2414
|
-
API:
|
2415
|
-
- `#start` starts animation
|
2416
|
-
- `#stop` stops animation
|
2450
|
+
API of Animation Object (returned from `animation` keyword):
|
2451
|
+
- `#start` starts an animation that is indefinite or has never been started before (i.e. having `started: false` option). Otherwise, resumes a stopped animation that has not been completed.
|
2452
|
+
- `#stop` stops animation. Maintains progress when `frame_count`, `cycle_count`, or `duration_limit` are set and haven't finished. That way, if `#start` is called, animation resumes from where it stopped exactly to completion.
|
2453
|
+
- `#restart` restarts animation, restarting progress of `frame_count`, `cycle_count`, and `duration_limit` if set.
|
2454
|
+
- `#started?` returns whether animation started
|
2455
|
+
- `#stopped?` returns whether animation stopped
|
2456
|
+
- `#indefinite?` (alias `infinite?`) returns true if animation does not have `frame_count`, `cycle_count`, or `duration_limit`
|
2457
|
+
- `#finite?` returns true if animation has `frame_count`, `cycle_count` (with `cycle`), or `duration_limit`
|
2458
|
+
- `#frame_count_limited?` returns true if `frame_count` is specified
|
2459
|
+
- `#cycle_enabled?` returns true if `cycle` is specified
|
2460
|
+
- `#cycle_limited?` returns true if `cycle_count` is specified
|
2461
|
+
- `#duration_limited?` returns true if `duration_limit` is specified
|
2417
2462
|
|
2418
2463
|
Learn more at the [Hello, Canvas Animation! Sample](#hello-canvas-animation).
|
2419
2464
|
|
2465
|
+
If there is anything you would like added to the Glimmer Animation DSL that you saw available in the SWT APIs, you may [report and issue](https://github.com/AndyObtiva/glimmer-dsl-swt/issues) or implement yourself and [contribute](#contributing) via a Pull Request.
|
2466
|
+
|
2420
2467
|
### Data-Binding
|
2421
2468
|
|
2422
2469
|
Data-binding is done with `bind` command following widget property to bind and taking model and bindable attribute as arguments.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
4.18.
|
1
|
+
4.18.2.0
|
data/glimmer-dsl-swt.gemspec
CHANGED
@@ -2,17 +2,17 @@
|
|
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.
|
5
|
+
# stub: glimmer-dsl-swt 4.18.2.0 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "glimmer-dsl-swt".freeze
|
9
|
-
s.version = "4.18.
|
9
|
+
s.version = "4.18.2.0"
|
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
14
|
s.date = "2021-01-20"
|
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 version of Ruby. Glimmer's main innovation is a declarative Ruby DSL that enables productive and efficient authoring of desktop application user-interfaces
|
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 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 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]
|
18
18
|
s.extra_rdoc_files = [
|
@@ -28,42 +28,126 @@ module Glimmer
|
|
28
28
|
class Animation
|
29
29
|
include Properties # TODO rename to Properties
|
30
30
|
|
31
|
+
class << self
|
32
|
+
def schedule_frame_animation(animation, &frame_animation_block)
|
33
|
+
frame_animation_queue(animation).prepend(frame_animation_block)
|
34
|
+
swt_display.async_exec do
|
35
|
+
frame_animation_queue(next_animation)&.pop&.call
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def next_animation
|
40
|
+
animation = nil
|
41
|
+
while frame_animation_queues.values.reduce(:+)&.any? && (animation.nil? || frame_animation_queue(animation).last.nil?)
|
42
|
+
animation = frame_animation_queues.keys[next_animation_index]
|
43
|
+
frame_animation_queues.delete(animation) if frame_animation_queues.values.reduce(:+)&.any? && !animation.nil? && frame_animation_queue(animation).empty?
|
44
|
+
end
|
45
|
+
animation
|
46
|
+
end
|
47
|
+
|
48
|
+
def next_animation_index
|
49
|
+
next_schedule_index % frame_animation_queues.keys.size
|
50
|
+
end
|
51
|
+
|
52
|
+
def next_schedule_index
|
53
|
+
unless defined? @@next_schedule_index
|
54
|
+
@@next_schedule_index = 0
|
55
|
+
else
|
56
|
+
@@next_schedule_index += 1
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def frame_animation_queues
|
61
|
+
unless defined? @@frame_animation_queues
|
62
|
+
@@frame_animation_queues = {}
|
63
|
+
end
|
64
|
+
@@frame_animation_queues
|
65
|
+
end
|
66
|
+
|
67
|
+
def frame_animation_queue(animation)
|
68
|
+
frame_animation_queues[animation] ||= []
|
69
|
+
end
|
70
|
+
|
71
|
+
def swt_display
|
72
|
+
unless defined? @@swt_display
|
73
|
+
@@swt_display = DisplayProxy.instance.swt_display
|
74
|
+
end
|
75
|
+
@@swt_display
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
31
79
|
attr_reader :parent, :options, :frame_index, :cycle
|
32
80
|
alias current_frame_index frame_index
|
33
|
-
attr_accessor :frame_block, :every, :cycle_count, :frame_count, :started
|
81
|
+
attr_accessor :frame_block, :every, :cycle_count, :frame_count, :started, :duration_limit
|
82
|
+
alias started? started
|
34
83
|
# TODO consider supporting an async: false option
|
35
84
|
|
36
85
|
def initialize(parent)
|
37
86
|
@parent = parent
|
38
87
|
@started = true
|
39
88
|
@frame_index = 0
|
89
|
+
@cycle_count_index = 0
|
90
|
+
@start_number = 0 # denotes the number of starts (increments on every start)
|
91
|
+
self.class.swt_display # ensures initializing variable to set from GUI thread
|
40
92
|
end
|
41
93
|
|
42
94
|
def post_add_content
|
43
95
|
@parent.on_widget_disposed { stop }
|
44
|
-
start if
|
96
|
+
start if started?
|
45
97
|
end
|
46
98
|
|
99
|
+
# Starts an animation that is indefinite or has never been started before (i.e. having `started: false` option).
|
100
|
+
# Otherwise, resumes a stopped animation that has not been completed.
|
47
101
|
def start
|
48
|
-
|
102
|
+
return if @start_number > 0 && started?
|
103
|
+
@start_number += 1
|
104
|
+
@started = true
|
105
|
+
@start_time = Time.now
|
106
|
+
@original_start_time = @start_time if @duration.nil?
|
107
|
+
# TODO track when finished in a variable for finite animations (whether by frame count, cycle count, or duration limit)
|
49
108
|
Thread.new do
|
109
|
+
start_number = @start_number
|
50
110
|
if cycle_count.is_a?(Integer) && cycle.is_a?(Array)
|
51
111
|
(cycle_count * cycle.length).times do
|
52
|
-
break unless draw_frame(
|
112
|
+
break unless draw_frame(start_number)
|
53
113
|
end
|
54
114
|
else
|
55
115
|
loop do
|
56
116
|
# this code has to be duplicated to break from a loop (break keyword only works when literally in a loop block)
|
57
|
-
break unless draw_frame(
|
117
|
+
break unless draw_frame(start_number)
|
58
118
|
end
|
59
119
|
end
|
60
|
-
@started = false
|
61
120
|
end
|
62
121
|
end
|
63
122
|
|
64
123
|
def stop
|
124
|
+
return if stopped?
|
65
125
|
@started = false
|
126
|
+
@duration = (Time.now - @start_time) + @duration.to_f if duration_limited? && !@start_time.nil?
|
127
|
+
end
|
128
|
+
|
129
|
+
# Restarts an animation (whether indefinite or not and whether stopped or not)
|
130
|
+
def restart
|
131
|
+
@original_start_time = @start_time = nil
|
132
|
+
@duration = nil
|
133
|
+
@frame_index = 0
|
134
|
+
@cycle_count_index = 0
|
135
|
+
stop
|
136
|
+
start
|
137
|
+
end
|
138
|
+
|
139
|
+
def stopped?
|
140
|
+
!started?
|
141
|
+
end
|
142
|
+
|
143
|
+
def finite?
|
144
|
+
frame_count_limited? || cycle_limited? || duration_limited?
|
145
|
+
end
|
146
|
+
|
147
|
+
def infinite?
|
148
|
+
!finite?
|
66
149
|
end
|
150
|
+
alias indefinite? infinite?
|
67
151
|
|
68
152
|
def has_attribute?(attribute_name, *args)
|
69
153
|
respond_to?(ruby_attribute_setter(attribute_name)) && respond_to?(ruby_attribute_getter(attribute_name))
|
@@ -89,21 +173,60 @@ module Glimmer
|
|
89
173
|
end
|
90
174
|
end
|
91
175
|
|
176
|
+
def cycle_enabled?
|
177
|
+
@cycle.is_a?(Array)
|
178
|
+
end
|
179
|
+
|
180
|
+
def cycle_limited?
|
181
|
+
cycle_enabled? && @cycle_count.is_a?(Integer)
|
182
|
+
end
|
183
|
+
|
184
|
+
def duration_limited?
|
185
|
+
@duration_limit.is_a?(Integer)
|
186
|
+
end
|
187
|
+
|
188
|
+
def frame_count_limited?
|
189
|
+
@frame_count.is_a?(Integer)
|
190
|
+
end
|
191
|
+
|
192
|
+
def surpassed_duration_limit?
|
193
|
+
duration_limited? && ((Time.now - @start_time) > (@duration_limit - @duration.to_f))
|
194
|
+
end
|
195
|
+
|
196
|
+
def within_duration_limit?
|
197
|
+
!surpassed_duration_limit?
|
198
|
+
end
|
199
|
+
|
92
200
|
private
|
93
201
|
|
94
202
|
# Returns true on success of painting a frame and false otherwise
|
95
|
-
def draw_frame(
|
96
|
-
return false if
|
203
|
+
def draw_frame(start_number)
|
204
|
+
return false if stopped? ||
|
205
|
+
start_number != @start_number ||
|
206
|
+
(frame_count_limited? && @frame_index == @frame_count) ||
|
207
|
+
(cycle_limited? && @cycle_count_index == @cycle_count) ||
|
208
|
+
surpassed_duration_limit?
|
97
209
|
block_args = [@frame_index]
|
98
|
-
block_args << @cycle[@frame_index % @cycle.length] if
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
210
|
+
block_args << @cycle[@frame_index % @cycle.length] if cycle_enabled?
|
211
|
+
current_frame_index = @frame_index
|
212
|
+
current_cycle_count_index = @cycle_count_index
|
213
|
+
self.class.schedule_frame_animation(self) do
|
214
|
+
if started? && start_number == @start_number && within_duration_limit?
|
215
|
+
@parent.clear_shapes
|
216
|
+
@parent.content {
|
217
|
+
frame_block.call(*block_args)
|
218
|
+
}
|
219
|
+
@parent.redraw
|
220
|
+
else
|
221
|
+
if stopped? && @frame_index > current_frame_index
|
222
|
+
@started = false
|
223
|
+
@frame_index = current_frame_index
|
224
|
+
@cycle_count_index = current_cycle_count_index
|
225
|
+
end
|
226
|
+
end
|
105
227
|
end
|
106
228
|
@frame_index += 1
|
229
|
+
@cycle_count_index += 1 if cycle_limited? && (@frame_index % @cycle&.length&.to_i) == 0
|
107
230
|
sleep(every) if every.is_a?(Numeric)
|
108
231
|
true
|
109
232
|
rescue => e
|
@@ -61,11 +61,12 @@ module Glimmer
|
|
61
61
|
|
62
62
|
before_body {
|
63
63
|
@swt_style = swt_style == 0 ? [:border, :multi, :v_scroll, :h_scroll] : swt_style
|
64
|
+
@font_name = display.get_font_list(nil, true).map(&:name).include?('Consolas') ? 'Consolas' : 'Courier'
|
64
65
|
}
|
65
66
|
|
66
67
|
body {
|
67
68
|
styled_text(swt_style) {
|
68
|
-
font name:
|
69
|
+
font name: @font_name, height: 15
|
69
70
|
foreground rgb(75, 75, 75)
|
70
71
|
left_margin 5
|
71
72
|
top_margin 5
|
@@ -20,6 +20,10 @@
|
|
20
20
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
21
|
|
22
22
|
require 'glimmer/swt/properties'
|
23
|
+
require 'glimmer/swt/swt_proxy'
|
24
|
+
require 'glimmer/swt/display_proxy'
|
25
|
+
require 'glimmer/swt/color_proxy'
|
26
|
+
require 'glimmer/swt/font_proxy'
|
23
27
|
|
24
28
|
module Glimmer
|
25
29
|
module SWT
|
@@ -29,7 +33,7 @@ module Glimmer
|
|
29
33
|
# That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
|
30
34
|
class Shape
|
31
35
|
include Properties
|
32
|
-
# TODO support textExtent
|
36
|
+
# TODO support textExtent sized shapes nested within text/string
|
33
37
|
# TODO support a Pattern DSL for methods that take Pattern arguments
|
34
38
|
|
35
39
|
class << self
|
@@ -48,8 +52,11 @@ module Glimmer
|
|
48
52
|
end
|
49
53
|
|
50
54
|
def method_name(keyword, args)
|
51
|
-
|
52
|
-
|
55
|
+
keyword = keyword.to_s
|
56
|
+
gradient = 'gradient_' if arg_options(args)[:gradient]
|
57
|
+
round = 'round_' if arg_options(args)[:round]
|
58
|
+
gc_instance_method_name_prefix = !['polyline', 'point', 'image', 'focus'].include?(keyword) && (arg_options(args)[:fill] || arg_options(args)[:gradient]) ? 'fill_' : 'draw_'
|
59
|
+
"#{gc_instance_method_name_prefix}#{gradient}#{round}#{keyword}"
|
53
60
|
end
|
54
61
|
end
|
55
62
|
|
@@ -67,18 +74,26 @@ module Glimmer
|
|
67
74
|
post_add_content if property_block.nil?
|
68
75
|
end
|
69
76
|
|
77
|
+
def draw?
|
78
|
+
!fill?
|
79
|
+
end
|
80
|
+
|
70
81
|
def fill?
|
71
|
-
|
82
|
+
@options[:fill]
|
72
83
|
end
|
73
84
|
|
74
|
-
def
|
75
|
-
|
85
|
+
def gradient?
|
86
|
+
@options[:gradient]
|
87
|
+
end
|
88
|
+
|
89
|
+
def round?
|
90
|
+
@options[:round]
|
76
91
|
end
|
77
92
|
|
78
93
|
def post_add_content
|
79
94
|
event_handler = lambda do |event|
|
80
|
-
@properties['background'] = [
|
81
|
-
@properties['foreground'] = [
|
95
|
+
@properties['background'] = [@parent.background] if fill? && !@properties.keys.map(&:to_s).include?('background')
|
96
|
+
@properties['foreground'] = [@parent.foreground] if draw? && !@properties.keys.map(&:to_s).include?('foreground')
|
82
97
|
@properties.each do |property, args|
|
83
98
|
method_name = attribute_setter(property)
|
84
99
|
apply_property_arg_conversions(method_name, args)
|
@@ -86,6 +101,7 @@ module Glimmer
|
|
86
101
|
end
|
87
102
|
apply_shape_arg_conversions(@method_name, @args)
|
88
103
|
apply_shape_arg_defaults(@method_name, @args)
|
104
|
+
tolerate_shape_extra_args(@method_name, @args)
|
89
105
|
event.gc.send(@method_name, *@args)
|
90
106
|
end
|
91
107
|
if parent.respond_to?(:swt_display)
|
@@ -102,7 +118,7 @@ module Glimmer
|
|
102
118
|
args[0] = ColorProxy.new(args[0])
|
103
119
|
end
|
104
120
|
if the_java_method.parameter_types.first == Java::int.java_class
|
105
|
-
args[0] = SWTProxy
|
121
|
+
args[0] = SWTProxy.constant(args[0])
|
106
122
|
end
|
107
123
|
end
|
108
124
|
if args.first.is_a?(ColorProxy)
|
@@ -114,6 +130,18 @@ module Glimmer
|
|
114
130
|
if args.first.is_a?(FontProxy)
|
115
131
|
args[0] = args[0].swt_font
|
116
132
|
end
|
133
|
+
if ['setBackgroundPattern', 'setForegroundPattern'].include?(method_name.to_s)
|
134
|
+
args.each_with_index do |arg, i|
|
135
|
+
if arg.is_a?(Symbol) || arg.is_a?(String)
|
136
|
+
args[i] = ColorProxy.new(arg).swt_color
|
137
|
+
elsif arg.is_a?(ColorProxy)
|
138
|
+
args[i] = arg.swt_color
|
139
|
+
end
|
140
|
+
end
|
141
|
+
new_args = [DisplayProxy.instance.swt_display] + args
|
142
|
+
args[0] = org.eclipse.swt.graphics.Pattern.new(*new_args)
|
143
|
+
args[1..-1] = []
|
144
|
+
end
|
117
145
|
end
|
118
146
|
|
119
147
|
def apply_shape_arg_conversions(method_name, args)
|
@@ -126,18 +154,29 @@ module Glimmer
|
|
126
154
|
def apply_shape_arg_defaults(method_name, args)
|
127
155
|
if method_name.include?('round_rectangle') && args.size.between?(4, 5)
|
128
156
|
(6 - args.size).times {args << 60}
|
129
|
-
elsif method_name.include?('
|
157
|
+
elsif method_name.include?('rectangle') && gradient? && args.size == 4
|
158
|
+
args << true
|
159
|
+
elsif (method_name.include?('text') || method_name.include?('string')) && !@properties.keys.map(&:to_s).include?('background') && args.size == 3
|
130
160
|
args << true
|
131
161
|
end
|
132
162
|
end
|
133
163
|
|
164
|
+
# Tolerates shape extra args added by user by mistake
|
165
|
+
# (e.g. happens when switching from round rectangle to a standard one without removing all extra args)
|
166
|
+
def tolerate_shape_extra_args(method_name, args)
|
167
|
+
the_java_method_arg_count = org.eclipse.swt.graphics.GC.java_class.declared_instance_methods.select do |m|
|
168
|
+
m.name == method_name.camelcase(:lower)
|
169
|
+
end.map(&:parameter_types).map(&:size).max
|
170
|
+
if args.size > the_java_method_arg_count
|
171
|
+
args[the_java_method_arg_count..-1] = []
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
134
175
|
def has_attribute?(attribute_name, *args)
|
135
|
-
# TODO test that attribute getter responds too
|
136
176
|
self.class.gc_instance_methods.include?(attribute_setter(attribute_name))
|
137
177
|
end
|
138
178
|
|
139
179
|
def set_attribute(attribute_name, *args)
|
140
|
-
# TODO special treatment for color symbols
|
141
180
|
@properties[attribute_name] = args
|
142
181
|
end
|
143
182
|
|
@@ -1,27 +1,48 @@
|
|
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
|
include Glimmer
|
2
23
|
|
3
24
|
shell {
|
4
25
|
text 'Hello, Canvas!'
|
5
26
|
minimum_size 320, 400
|
6
27
|
|
7
|
-
canvas {
|
28
|
+
canvas {
|
8
29
|
background :yellow
|
9
30
|
rectangle(0, 0, 220, 400, fill: true) {
|
10
31
|
background :red
|
11
32
|
}
|
12
|
-
|
33
|
+
rectangle(50, 20, 300, 150, 30, 50, round: true, fill: true) {
|
13
34
|
background :magenta
|
14
35
|
}
|
15
|
-
|
36
|
+
rectangle(150, 200, 100, 70, true, gradient: true) {
|
16
37
|
background :dark_magenta
|
17
38
|
foreground :yellow
|
18
39
|
}
|
19
|
-
|
40
|
+
rectangle(50, 200, 30, 70, false, gradient: true) {
|
20
41
|
background :magenta
|
21
42
|
foreground :dark_blue
|
22
43
|
}
|
23
44
|
rectangle(205, 50, 88, 96) {
|
24
|
-
foreground
|
45
|
+
foreground :yellow
|
25
46
|
}
|
26
47
|
text('Picasso', 60, 80) {
|
27
48
|
background :yellow
|
@@ -34,10 +55,9 @@ shell {
|
|
34
55
|
arc(210, 210, 100, 100, 30, -77, fill: true) {
|
35
56
|
background :red
|
36
57
|
}
|
37
|
-
polygon(250, 210, 260, 170, 270, 210, 290, 230,
|
58
|
+
polygon(250, 210, 260, 170, 270, 210, 290, 230, fill: true) {
|
38
59
|
background :dark_yellow
|
39
|
-
foreground :yellow
|
40
60
|
}
|
41
|
-
|
61
|
+
polyline(250, 110, 260, 70, 270, 110, 290, 130, 250, 110)
|
42
62
|
}
|
43
63
|
}.open
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: glimmer-dsl-swt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.18.
|
4
|
+
version: 4.18.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- AndyMaleh
|
@@ -331,17 +331,19 @@ dependencies:
|
|
331
331
|
description: Glimmer DSL for SWT (JRuby Desktop Development GUI Framework) is a native-GUI
|
332
332
|
cross-platform desktop development library written in JRuby, an OS-threaded faster
|
333
333
|
version of Ruby. Glimmer's main innovation is a declarative Ruby DSL that enables
|
334
|
-
productive and efficient authoring of desktop application user-interfaces
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
334
|
+
productive and efficient authoring of desktop application user-interfaces by relying
|
335
|
+
on the robust Eclipse SWT library. Glimmer additionally innovates by having built-in
|
336
|
+
data-binding support, which greatly facilitates synchronizing the GUI with domain
|
337
|
+
models, thus achieving true decoupling of object oriented components and enabling
|
338
|
+
developers to solve business problems (test-first) without worrying about GUI concerns,
|
339
|
+
or alternatively drive development GUI-first, and then write clean business models
|
340
|
+
(test-first) afterwards. Not only does Glimmer provide a large set of GUI widgets,
|
341
|
+
but also supports drawing Canvas Graphics like Shapes and Animations. To get started
|
342
|
+
quickly, Glimmer offers scaffolding options for Apps, Gems, and Custom Widgets.
|
343
|
+
Glimmer also includes native-executable packaging support, sorely lacking in other
|
344
|
+
libraries, thus enabling the delivery of desktop apps written in Ruby as truly native
|
345
|
+
DMG/PKG/APP files on the Mac + App Store, MSI/EXE files on Windows, and Gem Packaged
|
346
|
+
Shell Scripts on Linux.
|
345
347
|
email: andy.am@gmail.com
|
346
348
|
executables:
|
347
349
|
- glimmer
|