glimmer-dsl-libui 0.2.13 → 0.2.14

Sign up to get free protection for your applications and to get access to all the features.
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 LibUI 0.2.13
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 LibUI 0.2.14
2
2
  ## Prerequisite-Free Ruby Desktop Development GUI Library
3
3
  [![Gem Version](https://badge.fury.io/rb/glimmer-dsl-libui.svg)](http://badge.fury.io/rb/glimmer-dsl-libui)
4
4
  [![Join the chat at https://gitter.im/AndyObtiva/glimmer](https://badges.gitter.im/AndyObtiva/glimmer.svg)](https://gitter.im/AndyObtiva/glimmer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
@@ -9,13 +9,11 @@
9
9
 
10
10
  The main trade-off in using [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) as opposed to [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt) or [Glimmer DSL for Tk](https://github.com/AndyObtiva/glimmer-dsl-tk) is the fact that [SWT](https://www.eclipse.org/swt/) and [Tk](https://www.tcl.tk/) are more mature than mid-alpha [libui](https://github.com/andlabs/libui) as GUI toolkits. Still, if there is only a need to build a small simple application, [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) could be a good convenient choice due to having zero prerequisites beyond the dependencies included in the [Ruby gem](https://rubygems.org/gems/glimmer-dsl-libui). Also, just like [Glimmer DSL for Tk](https://github.com/AndyObtiva/glimmer-dsl-tk), its apps start instantly and have a small memory footprint. [LibUI](https://github.com/kojix2/LibUI) is a promising new GUI toolkit that might prove quite worthy in the future.
11
11
 
12
- **(Note: although LibUI works on Windows, this project has not been tested on Windows yet. It has only been verified on Mac x64 and Linux x64. Issue reporting for Windows is appreciated in the meantime.)**
13
-
14
12
  [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) aims to provide a DSL similar to the [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt) to enable more productive desktop development in Ruby with:
15
13
  - Declarative DSL syntax that visually maps to the GUI control hierarchy
16
14
  - Convention over configuration via smart defaults and automation of low-level details
17
15
  - Requiring the least amount of syntax possible to build GUI
18
- - Custom Control support
16
+ - Custom Keyword support
19
17
  - [Far Future Plan] Bidirectional Data-Binding to declaratively wire and automatically synchronize GUI with Business Models
20
18
  - [Far Future Plan] Scaffolding for new custom controls, apps, and gems
21
19
  - [Far Future Plan] Native-Executable packaging on Mac, Windows, and Linux.
@@ -119,21 +117,19 @@ window('Area Gallery', 400, 400) {
119
117
  fill r: 202, g: 102, b: 204, a: 0.5
120
118
  stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
121
119
  }
122
- unless OS.windows?
123
- path { # declarative stable path
124
- arc(400, 220, 180, 90, 90, false)
125
-
126
- # radial gradient (has an outer_radius in addition to x0, y0, x1, y1, and stops)
127
- fill outer_radius: 90, x0: 0, y0: 0, x1: 500, y1: 500, stops: [{pos: 0.25, r: 102, g: 102, b: 204, a: 0.5}, {pos: 0.75, r: 204, g: 102, b: 204}]
128
- stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
129
- }
130
- path { # declarative stable path
131
- circle(200, 200, 90)
132
-
133
- fill r: 202, g: 102, b: 204, a: 0.5
134
- stroke r: 0, g: 0, b: 0, thickness: 2
135
- }
136
- end
120
+ path { # declarative stable path
121
+ arc(400, 220, 180, 90, 90, false)
122
+
123
+ # radial gradient (has an outer_radius in addition to x0, y0, x1, y1, and stops)
124
+ fill outer_radius: 90, x0: 0, y0: 0, x1: 500, y1: 500, stops: [{pos: 0.25, r: 102, g: 102, b: 204, a: 0.5}, {pos: 0.75, r: 204, g: 102, b: 204}]
125
+ stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
126
+ }
127
+ path { # declarative stable path
128
+ circle(200, 200, 90)
129
+
130
+ fill r: 202, g: 102, b: 204, a: 0.5
131
+ stroke r: 0, g: 0, b: 0, thickness: 2
132
+ }
137
133
  text(160, 40, 100) { # x, y, width
138
134
  string('Area Gallery') {
139
135
  font family: 'Times', size: 14
@@ -213,7 +209,7 @@ Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interes
213
209
  - [Usage](#usage)
214
210
  - [Girb (Glimmer IRB)](#girb-glimmer-irb)
215
211
  - [API](#api)
216
- - [Supported Controls](#supported-controls)
212
+ - [Supported Keywords](#supported-keywords)
217
213
  - [Common Control Properties](#common-control-properties)
218
214
  - [Common Control Operations](#common-control-operations)
219
215
  - [LibUI Operations](#libui-operations)
@@ -257,10 +253,13 @@ Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interes
257
253
  - [Basic Transform](#basic-transform)
258
254
  - [Login](#login)
259
255
  - [Timer](#timer)
260
- - [Color The Shapes](#color-the-shapes)
256
+ - [Color The Circles](#color-the-circles)
261
257
  - [Basic Draw Text](#basic-draw-text)
262
258
  - [Custom Draw Text](#custom-draw-text)
263
259
  - [Method-Based Custom Keyword](#method-based-custom-keyword)
260
+ - [Applications](#applications)
261
+ - [Manga2PDF](#manga2pdf)
262
+ - [Befunge98 GUI](#befunge98-gui)
264
263
  - [Contributing to glimmer-dsl-libui](#contributing-to-glimmer-dsl-libui)
265
264
  - [Help](#help)
266
265
  - [Issues](#issues)
@@ -281,10 +280,10 @@ The Glimmer GUI DSL provides object-oriented declarative hierarchical syntax for
281
280
  - Requires the minimum amount of syntax needed to describe an app's GUI
282
281
 
283
282
  The Glimmer GUI DSL follows these simple concepts in mapping from [LibUI](https://github.com/kojix2/LibUI) syntax:
284
- - **Control**: [LibUI](https://github.com/kojix2/LibUI) controls may be declared by lower-case underscored name (aka keyword) (e.g. `window` or `button`). Behind the scenes, they are represented by keyword methods that map to corresponding `LibUI.new_keyword` methods receiving args (e.g. `window('hello world', 300, 200, true)`).
285
- - **Content/Properties/Listeners Block**: Any keyword may be optionally followed by a Ruby curly-brace multi-line-block containing nested controls (content) and/or properties (attributes) (e.g. `window('hello world', 300, 200, true) {button('greet')}`). It optionally receives one arg representing the control (e.g. `button('greet') {|b| on_clicked { puts b.text}}`)
286
- - **Property**: Control properties may be declared inside keyword blocks with lower-case underscored name followed by property value args (e.g. `title "hello world"` inside `group`). Behind the scenes, properties correspond to `control_set_property` methods.
287
- - **Listener**: Control listeners may be declared inside keyword blocks with listener lower-case underscored name beginning with `on_` and receiving required block handler (e.g. `on_clicked {puts 'clicked'}` inside `button`). Behind the scenes, listeners correspond to `control_on_event` methods.
283
+ - **Keyword(args)**: [LibUI](https://github.com/kojix2/LibUI) controls may be declared by lower-case underscored name (aka keyword) (e.g. `window` or `button`). Behind the scenes, they are represented by keyword methods that map to corresponding `LibUI.new_keyword` methods receiving args (e.g. `window('hello world', 300, 200, true)`).
284
+ - **Content Block** (Properties/Listeners/Controls): Any keyword may be optionally followed by a Ruby curly-brace multi-line content block containing properties (attributes), listeners, and/or nested controls (e.g. `window {title 'hello world'; on_closing {puts 'Bye'}; button('greet')}`). Content block optionally receives one arg representing the control (e.g. `button('greet') {|b| on_clicked { puts b.text}}`)
285
+ - **Property**: Control properties may be declared inside keyword blocks with lower-case underscored name followed by property value args (e.g. `title "hello world"` inside `group`). Behind the scenes, properties correspond to `LibUI.control_set_property` methods.
286
+ - **Listener**: Control listeners may be declared inside keyword blocks with listener lower-case underscored name beginning with `on_` and receiving required block handler (e.g. `on_clicked {puts 'clicked'}` inside `button`). Optionally, the listener block can receive an arg representing the control (e.g. `on_clicked {|btn| puts btn.text}`). Behind the scenes, listeners correspond to `LibUI.control_on_event` methods.
288
287
 
289
288
  Example of an app written in [LibUI](https://github.com/kojix2/LibUI)'s procedural imperative syntax:
290
289
 
@@ -348,7 +347,7 @@ gem install glimmer-dsl-libui
348
347
  Or install via Bundler `Gemfile`:
349
348
 
350
349
  ```ruby
351
- gem 'glimmer-dsl-libui', '~> 0.2.13'
350
+ gem 'glimmer-dsl-libui', '~> 0.2.14'
352
351
  ```
353
352
 
354
353
  Add `require 'glimmer-dsl-libui'` at the top, and then `include Glimmer` into the top-level main object for testing or into an actual class for serious usage.
@@ -408,7 +407,7 @@ w.set_title 'aloha'
408
407
  puts w.title # => aloha
409
408
  ```
410
409
 
411
- Controls are wrapped as Ruby proxy objects, having a `#libui` method to obtain the wrapped Fiddle pointer object. Ruby proxy objects rely on composition (via [Proxy Design Pattern](https://en.wikipedia.org/wiki/Proxy_pattern)) instead of inheritance to shield consumers from having to deal with lower-level details unless absolutely needed.
410
+ Controls are wrapped as Ruby proxy objects, having a `#libui` method to obtain the wrapped [LibUI](https://github.com/kojix2/LibUI) Fiddle pointer object. Ruby proxy objects rely on composition (via [Proxy Design Pattern](https://en.wikipedia.org/wiki/Proxy_pattern)) instead of inheritance to shield consumers from having to deal with lower-level details unless absolutely needed.
412
411
 
413
412
  Example (you may copy/paste in [`girb`](#girb-glimmer-irb)):
414
413
 
@@ -417,9 +416,11 @@ w = window('hello world') # => #<Glimmer::LibUI::WindowProxy:0x00007fde4ea39fb0
417
416
  w.libui # => #<Fiddle::Pointer:0x00007fde53997980 ptr=0x00007fde51352a60 size=0 free=0x0000000000000000>
418
417
  ```
419
418
 
420
- ### Supported Controls
419
+ ### Supported Keywords
420
+
421
+ These are all the supported keywords. Note that some keywords do not represent controls, but produce objects that are used as the property values of controls (e.g. `image` builds objects to use in `cell_rows` for a `table` with an image column)
421
422
 
422
- Control(Args) | Properties | Listeners
423
+ Keyword(Args) | Properties | Listeners
423
424
  ------------- | ---------- | ---------
424
425
  `about_menu_item` | None | `on_clicked`
425
426
  `area` | None | `on_draw(area_draw_params)`, `on_mouse_event(area_mouse_event)`, `on_mouse_down(area_mouse_event)`, `on_mouse_up(area_mouse_event)`, `on_mouse_drag_started(area_mouse_event)`, `on_mouse_dragged(area_mouse_event)`, `on_mouse_dropped(area_mouse_event)`, `on_mouse_entered`, `on_mouse_exited`, `on_key_event(area_key_event)`, `on_key_down(area_key_event)`, `on_key_up(area_key_event)`
@@ -455,6 +456,8 @@ Control(Args) | Properties | Listeners
455
456
  `matrix(m11 = nil as Numeric, m12 = nil as Numeric, m21 = nil as Numeric, m22 = nil as Numeric, m31 = nil as Numeric, m32 = nil as Numeric)` | `m11` (`Numeric`), `m12` (`Numeric`), `m21` (`Numeric`), `m22` (`Numeric`), `m31` (`Numeric`), `m32` (`Numeric`) | None
456
457
  `menu(text as String)` | None | None
457
458
  `menu_item(text as String)` | `checked` (Boolean) | `on_clicked`
459
+ `message_box` (alias for `msg_box`; see for arguments) | None | None
460
+ `message_box_error` (alias for `msg_box_error`; see for arguments) | None | None
458
461
  `multiline_entry` | `read_only` (Boolean), `text` (`String`) | `on_changed`
459
462
  `msg_box(window = main_window as Glimmer::LibUI::WindowProxy, title as String, description as String)` | None | None
460
463
  `msg_box_error(window = main_window as Glimmer::LibUI::WindowProxy, title as String, description as String)` | None | None
@@ -516,8 +519,8 @@ All operations that could normally be called on `LibUI` can also be called on `G
516
519
 
517
520
  ### Extra Dialogs
518
521
 
519
- - `open_file(window as Glimmer::LibUI::WindowProxy)`: returns selected file (`String`) or `nil` if cancelled
520
- - `save_file(window as Glimmer::LibUI::WindowProxy)`: returns selected file (`String`) or `nil` if cancelled
522
+ - `open_file(window as Glimmer::LibUI::WindowProxy = ControlProxy::main_window_proxy)`: returns selected file (`String`) or `nil` if cancelled
523
+ - `save_file(window as Glimmer::LibUI::WindowProxy = ControlProxy::main_window_proxy)`: returns selected file (`String`) or `nil` if cancelled
521
524
 
522
525
  ### Extra Operations
523
526
 
@@ -530,13 +533,13 @@ All operations that could normally be called on `LibUI` can also be called on `G
530
533
 
531
534
  ### Table API
532
535
 
533
- The `table` control must first declare its columns via one of these column keywords (mentioned in [Supported Controls](#supported-controls)):
536
+ The `table` control must first declare its columns via one of these column keywords (mentioned in [Supported Keywords](#supported-keywords)):
534
537
  - `background_color_column`: expects color cell values
535
538
  - `button_column`: expects `String` cell values
536
539
  - `checkbox_column`: expects Boolean cell values
537
540
  - `checkbox_text_column`: expects dual-element `Array` of Boolean and `String` cell values
538
541
  - `checkbox_text_color_column`: expects triple-element `Array` of Boolean, `String`, and color cell values
539
- - `image_column`: expects `image` cell values (produced by `image` and `image_part` keywords as per [Supported Controls](#supported-controls))
542
+ - `image_column`: expects `image` cell values (produced by `image` and `image_part` keywords as per [Supported Keywords](#supported-keywords))
540
543
  - `image_text_column`: expects dual-element `Array` of `image` and `String` cell values
541
544
  - `image_text_color_column`: expects triple-element `Array` of `image`, `String`, and color cell values
542
545
  - `text_column`: expects `String` cell values
@@ -598,6 +601,7 @@ window('Contacts', 600, 600) { |w|
598
601
  msg_box_error(w, 'Validation Error!', 'All fields are required! Please make sure to enter a value for all fields.')
599
602
  else
600
603
  data << new_row # automatically inserts a row into the table due to implicit data-binding
604
+ @unfiltered_data = data.dup
601
605
  @name_entry.text = ''
602
606
  @email_entry.text = ''
603
607
  @phone_entry.text = ''
@@ -607,6 +611,25 @@ window('Contacts', 600, 600) { |w|
607
611
  end
608
612
  }
609
613
 
614
+ search_entry { |se|
615
+ stretchy false
616
+
617
+ on_changed do
618
+ filter_value = se.text
619
+ @unfiltered_data ||= data.dup
620
+ # Unfilter first to remove any previous filters
621
+ data.replace(@unfiltered_data) # affects table indirectly through implicit data-binding
622
+ # Now, apply filter if entered
623
+ unless filter_value.empty?
624
+ data.filter! do |row_data| # affects table indirectly through implicit data-binding
625
+ row_data.any? do |cell|
626
+ cell.to_s.downcase.include?(filter_value.downcase)
627
+ end
628
+ end
629
+ end
630
+ end
631
+ }
632
+
610
633
  table {
611
634
  text_column('Name')
612
635
  text_column('Email')
@@ -615,6 +638,10 @@ window('Contacts', 600, 600) { |w|
615
638
  text_column('State')
616
639
 
617
640
  cell_rows data # implicit data-binding
641
+
642
+ on_changed do |row, type, row_data|
643
+ puts "Row #{row} #{type}: #{row_data}"
644
+ end
618
645
  }
619
646
  }
620
647
  }.show
@@ -627,8 +654,8 @@ Learn more by checking out [examples](#examples).
627
654
  ### Area API
628
655
 
629
656
  The `area` control is a canvas-like control for drawing paths that can be used in one of two ways:
630
- - Declaratively via stable paths: useful for stable paths that will not change later on. Simply nest `path` and figures like `rectangle` and all drawing logic is generated automatically. Path proxy objects are preserved across redraws assuming there would be few stable paths (mostly for decorative reasons).
631
- - Semi-declaratively via on_draw listener dynamic paths: useful for more dynamic paths that will definitely change. Open an `on_draw` listener block that receives a `area_draw_params` argument and nest `path` and figures like `rectangle` and all drawing logic is generated automatically. Path proxy objects are destroyed (thrown-away) at the end of drawing, thus having less memory overhead for drawing thousands of dynamic paths.
657
+ - Declaratively via stable paths: useful for stable paths that will not change often later on. Simply nest `path` and figures like `rectangle` and all drawing logic is generated automatically. Path proxy objects are preserved across redraws assuming there would be relatively few stable paths (mostly for decorative reasons).
658
+ - Semi-declaratively via on_draw listener dynamic paths: useful for more dynamic paths that will definitely change very often. Open an `on_draw` listener block that receives a `area_draw_params` argument and nest `path` and figures like `rectangle` and all drawing logic is generated automatically. Path proxy objects are destroyed (thrown-away) at the end of drawing, thus having less memory overhead for drawing thousands of dynamic paths.
632
659
 
633
660
  Here is an example of a declarative `area` with a stable path (you may copy/paste in [`girb`](#girb-glimmer-irb)):
634
661
 
@@ -892,6 +919,7 @@ window('area text drawing') {
892
919
  - Table `cell_rows` data has implicit data-binding to table cell values for deletion, insertion, and change (done by diffing `cell_rows` value before and after change and auto-informing `table` of deletions [`LibUI.table_model_row_deleted`], insertions [`LibUI.table_model_row_deleted`], and changes [`LibUI.table_model_row_changed`]). When deleting data rows from `cell_rows` array, then actual rows from the `table` are automatically deleted. When inserting data rows into `cell_rows` array, then actual `table` rows are automatically inserted. When updating data rows in `cell_rows` array, then actual `table` rows are automatically updated.
893
920
  - `image` instances are automatically freed from memory after `window` is destroyed.
894
921
  - `image` `width` and `height` can be left off if it has one `image_part` only as they default to the same `width` and `height` of the `image_part`
922
+ - Automatically provide shifted `:key` characters in `area_key_event` provided in `area` key listeners `on_key_event`, `on_key_down`, and `on_key_up`
895
923
  - `area` paths are specified declaratively with figures underneath (e.g. `rectangle`) and `area` draw listener is automatically generated
896
924
  - Observe figure properties (e.g. `rectangle` `width`) for changes and automatically redraw containing area accordingly
897
925
  - Observe `path` `fill` and `stroke` hashes for changes and automatically redraw containing area accordingly
@@ -1013,12 +1041,13 @@ window('Method-Based Custom Keyword') {
1013
1041
  ### API Gotchas
1014
1042
 
1015
1043
  - There is no proper way to destroy `grid` children due to [libui](https://github.com/andlabs/libui) not offering any API for deleting them from `grid` (no `grid_delete` similar to `box_delete` for `horizontal_box` and `vertical_box`).
1016
- - `table` `checkbox_column` and `checkbox_text_column` checkbox editing only works on Windows and Linux (not Mac) due to a current limitation in [libui](https://github.com/andlabs/ui/issues/357).
1044
+ - `table` `checkbox_column` and `checkbox_text_column` checkbox editing only works on Linux and Windows (not Mac) due to a current limitation in [libui](https://github.com/andlabs/ui/issues/357).
1017
1045
  - `text` `align` property seems not to work on the Mac ([libui](https://github.com/andlabs/libui) has an [issue](https://github.com/andlabs/libui/pull/407) about it)
1018
- - `text` `string` `background` does not work on Windows due to an issue in [libui](https://github.com/andlabs/libui).
1019
- - `arc` shape does not work on Windows due to an issue in [libui](https://github.com/andlabs/libui).
1046
+ - `text` `string` `background` does not work on Windows due to an [issue in libui](https://github.com/andlabs/libui/issues/347).
1047
+ - `arc` shape does not work on Windows unless a figure is started due to implementation of [libui](https://github.com/andlabs/libui).
1020
1048
  - `table` controls on Windows intentionally get an extra empty row at the end because if any row were to be deleted for the first time, double-deletion happens due to an issue in [libui](https://github.com/andlabs/libui) on Windows.
1021
1049
  - `table` `progress_bar` column on Windows cannot be updated with a positive value if it started initially with `-1` (it ignores update to avoid crashing due to an issue in [libui](https://github.com/andlabs/libui) on Windows.
1050
+ - It seems that [libui](https://github.com/andlabs/libui) does not support nesting multiple `area` controls under a `grid` as only the first one shows up in that scenario. To workaround that limitation, use a `vertical_box` with nested `horizontal_box`s instead to include multiple `area`s in a GUI.
1022
1051
 
1023
1052
  ### Original API
1024
1053
 
@@ -1033,7 +1062,7 @@ I am documenting options for packaging, which I have not tried myself, but figur
1033
1062
 
1034
1063
  For Windows, the [LibUI](https://github.com/kojix2/LibUI) project recommends [OCRA](https://github.com/larsch/ocra) (One-Click Ruby Application), which builds Windows executables from Ruby source.
1035
1064
 
1036
- For Mac, consider [Platybus](https://github.com/sveinbjornt/Platypus) (builds a native Mac app from a Ruby script)
1065
+ For Mac, consider [Platypus](https://github.com/sveinbjornt/Platypus) (builds a native Mac app from a Ruby script)
1037
1066
 
1038
1067
  For Linux, simply package your app as a [Ruby Gem](https://guides.rubygems.org/what-is-a-gem/) and [build rpm package from Ruby Gem](https://www.redpill-linpro.com/sysadvent/2015/12/07/building-rpms-from-gems.html) or [build deb package from Ruby Gem](https://openpreservation.org/blogs/building-debian-package-ruby-program/).
1039
1068
 
@@ -3384,8 +3413,6 @@ Linux
3384
3413
  New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
3385
3414
 
3386
3415
  ```ruby
3387
- # frozen_string_literal: true
3388
-
3389
3416
  require 'glimmer-dsl-libui'
3390
3417
 
3391
3418
  include Glimmer
@@ -3901,21 +3928,19 @@ window('Area Gallery', 400, 400) {
3901
3928
  fill r: 202, g: 102, b: 204, a: 0.5
3902
3929
  stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
3903
3930
  }
3904
- unless OS.windows?
3905
- path { # declarative stable path
3906
- arc(400, 220, 180, 90, 90, false)
3907
-
3908
- # radial gradient (has an outer_radius in addition to x0, y0, x1, y1, and stops)
3909
- fill outer_radius: 90, x0: 0, y0: 0, x1: 500, y1: 500, stops: [{pos: 0.25, r: 102, g: 102, b: 204, a: 0.5}, {pos: 0.75, r: 204, g: 102, b: 204}]
3910
- stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
3911
- }
3912
- path { # declarative stable path
3913
- circle(200, 200, 90)
3914
-
3915
- fill r: 202, g: 102, b: 204, a: 0.5
3916
- stroke r: 0, g: 0, b: 0, thickness: 2
3917
- }
3918
- end
3931
+ path { # declarative stable path
3932
+ arc(400, 220, 180, 90, 90, false)
3933
+
3934
+ # radial gradient (has an outer_radius in addition to x0, y0, x1, y1, and stops)
3935
+ fill outer_radius: 90, x0: 0, y0: 0, x1: 500, y1: 500, stops: [{pos: 0.25, r: 102, g: 102, b: 204, a: 0.5}, {pos: 0.75, r: 204, g: 102, b: 204}]
3936
+ stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
3937
+ }
3938
+ path { # declarative stable path
3939
+ circle(200, 200, 90)
3940
+
3941
+ fill r: 202, g: 102, b: 204, a: 0.5
3942
+ stroke r: 0, g: 0, b: 0, thickness: 2
3943
+ }
3919
3944
  text(160, 40, 100) { # x, y, width
3920
3945
  string('Area Gallery') {
3921
3946
  font family: 'Times', size: 14
@@ -4074,32 +4099,30 @@ window('Area Gallery', 400, 400) {
4074
4099
  fill r: 202, g: 102, b: 204, a: 0.5
4075
4100
  stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
4076
4101
  }
4077
- unless OS.windows?
4078
- path { # declarative stable path
4079
- arc {
4080
- x_center 400
4081
- y_center 220
4082
- radius 180
4083
- start_angle 90
4084
- sweep 90
4085
- is_negative false
4086
- }
4087
-
4088
- # radial gradient (has an outer_radius in addition to x0, y0, x1, y1, and stops)
4089
- fill outer_radius: 90, x0: 0, y0: 0, x1: 500, y1: 500, stops: [{pos: 0.25, r: 102, g: 102, b: 204, a: 0.5}, {pos: 0.75, r: 204, g: 102, b: 204}]
4090
- stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
4102
+ path { # declarative stable path
4103
+ arc {
4104
+ x_center 400
4105
+ y_center 220
4106
+ radius 180
4107
+ start_angle 90
4108
+ sweep 90
4109
+ is_negative false
4091
4110
  }
4092
- path { # declarative stable path
4093
- circle {
4094
- x_center 200
4095
- y_center 200
4096
- radius 90
4097
- }
4098
-
4099
- fill r: 202, g: 102, b: 204, a: 0.5
4100
- stroke r: 0, g: 0, b: 0, thickness: 2
4111
+
4112
+ # radial gradient (has an outer_radius in addition to x0, y0, x1, y1, and stops)
4113
+ fill outer_radius: 90, x0: 0, y0: 0, x1: 500, y1: 500, stops: [{pos: 0.25, r: 102, g: 102, b: 204, a: 0.5}, {pos: 0.75, r: 204, g: 102, b: 204}]
4114
+ stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
4115
+ }
4116
+ path { # declarative stable path
4117
+ circle {
4118
+ x_center 200
4119
+ y_center 200
4120
+ radius 90
4101
4121
  }
4102
- end
4122
+
4123
+ fill r: 202, g: 102, b: 204, a: 0.5
4124
+ stroke r: 0, g: 0, b: 0, thickness: 2
4125
+ }
4103
4126
  text {
4104
4127
  x 160
4105
4128
  y 40
@@ -4211,21 +4234,19 @@ window('Area Gallery', 400, 400) {
4211
4234
  fill r: 202, g: 102, b: 204, a: 0.5
4212
4235
  stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
4213
4236
  }
4214
- unless OS.windows?
4215
- path { # a dynamic path is added semi-declaratively inside on_draw block
4216
- arc(400, 220, 180, 90, 90, false)
4217
-
4218
- # radial gradient (has an outer_radius in addition to x0, y0, x1, y1, and stops)
4219
- fill outer_radius: 90, x0: 0, y0: 0, x1: 500, y1: 500, stops: [{pos: 0.25, r: 102, g: 102, b: 204, a: 0.5}, {pos: 0.75, r: 204, g: 102, b: 204}]
4220
- stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
4221
- }
4222
- path { # a dynamic path is added semi-declaratively inside on_draw block
4223
- circle(200, 200, 90)
4224
-
4225
- fill r: 202, g: 102, b: 204, a: 0.5
4226
- stroke r: 0, g: 0, b: 0, thickness: 2
4227
- }
4228
- end
4237
+ path { # a dynamic path is added semi-declaratively inside on_draw block
4238
+ arc(400, 220, 180, 90, 90, false)
4239
+
4240
+ # radial gradient (has an outer_radius in addition to x0, y0, x1, y1, and stops)
4241
+ fill outer_radius: 90, x0: 0, y0: 0, x1: 500, y1: 500, stops: [{pos: 0.25, r: 102, g: 102, b: 204, a: 0.5}, {pos: 0.75, r: 204, g: 102, b: 204}]
4242
+ stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
4243
+ }
4244
+ path { # a dynamic path is added semi-declaratively inside on_draw block
4245
+ circle(200, 200, 90)
4246
+
4247
+ fill r: 202, g: 102, b: 204, a: 0.5
4248
+ stroke r: 0, g: 0, b: 0, thickness: 2
4249
+ }
4229
4250
  text(160, 40, 100) { # x, y, width
4230
4251
  string('Area Gallery') {
4231
4252
  font family: 'Times', size: 14
@@ -4386,32 +4407,30 @@ window('Area Gallery', 400, 400) {
4386
4407
  fill r: 202, g: 102, b: 204, a: 0.5
4387
4408
  stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
4388
4409
  }
4389
- unless OS.windows?
4390
- path { # a dynamic path is added semi-declaratively inside on_draw block
4391
- arc {
4392
- x_center 400
4393
- y_center 220
4394
- radius 180
4395
- start_angle 90
4396
- sweep 90
4397
- is_negative false
4398
- }
4399
-
4400
- # radial gradient (has an outer_radius in addition to x0, y0, x1, y1, and stops)
4401
- fill outer_radius: 90, x0: 0, y0: 0, x1: 500, y1: 500, stops: [{pos: 0.25, r: 102, g: 102, b: 204, a: 0.5}, {pos: 0.75, r: 204, g: 102, b: 204}]
4402
- stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
4410
+ path { # a dynamic path is added semi-declaratively inside on_draw block
4411
+ arc {
4412
+ x_center 400
4413
+ y_center 220
4414
+ radius 180
4415
+ start_angle 90
4416
+ sweep 90
4417
+ is_negative false
4403
4418
  }
4404
- path { # a dynamic path is added semi-declaratively inside on_draw block
4405
- circle {
4406
- x_center 200
4407
- y_center 200
4408
- radius 90
4409
- }
4410
-
4411
- fill r: 202, g: 102, b: 204, a: 0.5
4412
- stroke r: 0, g: 0, b: 0, thickness: 2
4419
+
4420
+ # radial gradient (has an outer_radius in addition to x0, y0, x1, y1, and stops)
4421
+ fill outer_radius: 90, x0: 0, y0: 0, x1: 500, y1: 500, stops: [{pos: 0.25, r: 102, g: 102, b: 204, a: 0.5}, {pos: 0.75, r: 204, g: 102, b: 204}]
4422
+ stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
4423
+ }
4424
+ path { # a dynamic path is added semi-declaratively inside on_draw block
4425
+ circle {
4426
+ x_center 200
4427
+ y_center 200
4428
+ radius 90
4413
4429
  }
4414
- end
4430
+
4431
+ fill r: 202, g: 102, b: 204, a: 0.5
4432
+ stroke r: 0, g: 0, b: 0, thickness: 2
4433
+ }
4415
4434
  text {
4416
4435
  x 160
4417
4436
  y 40
@@ -5114,63 +5133,62 @@ end
5114
5133
  Timer.new
5115
5134
  ```
5116
5135
 
5117
- ### Color The Shapes
5136
+ ### Color The Circles
5118
5137
 
5119
- [examples/color_the_shapes.rb](examples/color_the_shapes.rb)
5138
+ [examples/color_the_circles.rb](examples/color_the_circles.rb)
5120
5139
 
5121
5140
  Run with this command from the root of the project if you cloned the project:
5122
5141
 
5123
5142
  ```
5124
- ruby -r './lib/glimmer-dsl-libui' examples/color_the_shapes.rb
5143
+ ruby -r './lib/glimmer-dsl-libui' examples/color_the_circles.rb
5125
5144
  ```
5126
5145
 
5127
5146
  Run with this command if you installed the [Ruby gem](https://rubygems.org/gems/glimmer-dsl-libui):
5128
5147
 
5129
5148
  ```
5130
- ruby -r glimmer-dsl-libui -e "require 'examples/color_the_shapes'"
5149
+ ruby -r glimmer-dsl-libui -e "require 'examples/color_the_circles'"
5131
5150
  ```
5132
5151
 
5133
5152
  Mac
5134
5153
 
5135
- ![glimmer-dsl-libui-mac-color-the-shapes.png](images/glimmer-dsl-libui-mac-color-the-shapes.png)
5136
- ![glimmer-dsl-libui-mac-color-the-shapes-lost.png](images/glimmer-dsl-libui-mac-color-the-shapes-lost.png)
5137
- ![glimmer-dsl-libui-mac-color-the-shapes-won.png](images/glimmer-dsl-libui-mac-color-the-shapes-won.png)
5154
+ ![glimmer-dsl-libui-mac-color-the-circles.png](images/glimmer-dsl-libui-mac-color-the-circles.png)
5155
+ ![glimmer-dsl-libui-mac-color-the-circles-lost.png](images/glimmer-dsl-libui-mac-color-the-circles-lost.png)
5156
+ ![glimmer-dsl-libui-mac-color-the-circles-won.png](images/glimmer-dsl-libui-mac-color-the-circles-won.png)
5138
5157
 
5139
5158
  Linux
5140
5159
 
5141
- ![glimmer-dsl-libui-linux-color-the-shapes.png](images/glimmer-dsl-libui-linux-color-the-shapes.png)
5142
- ![glimmer-dsl-libui-linux-color-the-shapes-lost.png](images/glimmer-dsl-libui-linux-color-the-shapes-lost.png)
5143
- ![glimmer-dsl-libui-linux-color-the-shapes-won.png](images/glimmer-dsl-libui-linux-color-the-shapes-won.png)
5160
+ ![glimmer-dsl-libui-linux-color-the-circles.png](images/glimmer-dsl-libui-linux-color-the-circles.png)
5161
+ ![glimmer-dsl-libui-linux-color-the-circles-lost.png](images/glimmer-dsl-libui-linux-color-the-circles-lost.png)
5162
+ ![glimmer-dsl-libui-linux-color-the-circles-won.png](images/glimmer-dsl-libui-linux-color-the-circles-won.png)
5144
5163
 
5145
5164
  New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
5146
5165
 
5147
5166
  ```ruby
5148
5167
  require 'glimmer-dsl-libui'
5149
5168
 
5150
- class ColorTheShapes
5169
+ class ColorTheCircles
5151
5170
  include Glimmer
5152
5171
 
5153
5172
  WINDOW_WIDTH = 800
5154
5173
  WINDOW_HEIGHT = 600
5155
5174
  SHAPE_MIN_SIZE = 15
5156
- SHAPE_MAX_SIZE = 100
5175
+ SHAPE_MAX_SIZE = 75
5157
5176
  MARGIN_WIDTH = 55
5158
5177
  MARGIN_HEIGHT = 155
5159
5178
  TIME_MAX_EASY = 4
5160
5179
  TIME_MAX_MEDIUM = 3
5161
5180
  TIME_MAX_HARD = 2
5162
5181
  TIME_MAX_INSANE = 1
5163
- SHAPES = ['square'] + (OS.windows? ? [] : ['circle'])
5164
5182
 
5165
5183
  attr_accessor :score
5166
5184
 
5167
5185
  def initialize
5168
- @shapes_data = []
5186
+ @circles_data = []
5169
5187
  @score = 0
5170
5188
  @time_max = TIME_MAX_HARD
5171
5189
  @game_over = false
5172
5190
  register_observers
5173
- setup_shape_factory
5191
+ setup_circle_factory
5174
5192
  end
5175
5193
 
5176
5194
  def register_observers
@@ -5189,14 +5207,14 @@ class ColorTheShapes
5189
5207
  observer.observe(self, :score) # automatically enhances self to become Glimmer::DataBinding::ObservableModel and notify observer on score attribute changes
5190
5208
  end
5191
5209
 
5192
- def setup_shape_factory
5210
+ def setup_circle_factory
5193
5211
  consumer = Proc.new do
5194
5212
  unless @game_over
5195
- if @shapes_data.empty?
5196
- # start with 3 shapes to make more challenging
5197
- add_shape until @shapes_data.size > 3
5213
+ if @circles_data.empty?
5214
+ # start with 3 circles to make more challenging
5215
+ add_circle until @circles_data.size > 3
5198
5216
  else
5199
- add_shape
5217
+ add_circle
5200
5218
  end
5201
5219
  end
5202
5220
  delay = rand * @time_max
@@ -5205,13 +5223,13 @@ class ColorTheShapes
5205
5223
  Glimmer::LibUI.queue_main(&consumer)
5206
5224
  end
5207
5225
 
5208
- def add_shape
5209
- shape_x = rand * (WINDOW_WIDTH - MARGIN_WIDTH - SHAPE_MAX_SIZE) + SHAPE_MAX_SIZE
5210
- shape_y = rand * (WINDOW_HEIGHT - MARGIN_HEIGHT - SHAPE_MAX_SIZE) + SHAPE_MAX_SIZE
5211
- shape_size = rand * (SHAPE_MAX_SIZE - SHAPE_MIN_SIZE) + SHAPE_MIN_SIZE
5226
+ def add_circle
5227
+ circle_x = rand * (WINDOW_WIDTH - MARGIN_WIDTH - SHAPE_MAX_SIZE) + SHAPE_MAX_SIZE
5228
+ circle_y = rand * (WINDOW_HEIGHT - MARGIN_HEIGHT - SHAPE_MAX_SIZE) + SHAPE_MAX_SIZE
5229
+ circle_size = rand * (SHAPE_MAX_SIZE - SHAPE_MIN_SIZE) + SHAPE_MIN_SIZE
5212
5230
  stroke_color = Glimmer::LibUI.x11_colors.sample
5213
- @shapes_data << {
5214
- args: [shape_x, shape_y, shape_size],
5231
+ @circles_data << {
5232
+ args: [circle_x, circle_y, circle_size],
5215
5233
  fill: nil,
5216
5234
  stroke: stroke_color
5217
5235
  }
@@ -5221,27 +5239,27 @@ class ColorTheShapes
5221
5239
 
5222
5240
  def restart_game
5223
5241
  @score = 0 # update variable directly to avoid notifying observers
5224
- @shapes_data.clear
5242
+ @circles_data.clear
5225
5243
  @game_over = false
5226
5244
  end
5227
5245
 
5228
- def color_shape(x, y)
5229
- clicked_shape_data = @shapes_data.find do |shape_data|
5230
- shape_data[:fill].nil? && shape_data[:shape]&.include?(x, y)
5246
+ def color_circle(x, y)
5247
+ clicked_circle_data = @circles_data.find do |circle_data|
5248
+ circle_data[:fill].nil? && circle_data[:circle]&.include?(x, y)
5231
5249
  end
5232
- if clicked_shape_data
5233
- clicked_shape_data[:fill] = clicked_shape_data[:stroke]
5234
- push_colored_shape_behind_uncolored_shapes(clicked_shape_data)
5250
+ if clicked_circle_data
5251
+ clicked_circle_data[:fill] = clicked_circle_data[:stroke]
5252
+ push_colored_circle_behind_uncolored_circles(clicked_circle_data)
5235
5253
  @area.queue_redraw_all
5236
5254
  self.score += 1 # notifies score observers automatically of change
5237
5255
  end
5238
5256
  end
5239
5257
 
5240
- def push_colored_shape_behind_uncolored_shapes(colored_shape_data)
5241
- removed_colored_shape_data = @shapes_data.delete(colored_shape_data)
5242
- last_colored_shape_data = @shapes_data.select {|cd| cd[:fill]}.last
5243
- last_colored_shape_data_index = @shapes_data.index(last_colored_shape_data) || -1
5244
- @shapes_data.insert(last_colored_shape_data_index + 1, removed_colored_shape_data)
5258
+ def push_colored_circle_behind_uncolored_circles(colored_circle_data)
5259
+ removed_colored_circle_data = @circles_data.delete(colored_circle_data)
5260
+ last_colored_circle_data = @circles_data.select {|cd| cd[:fill]}.last
5261
+ last_colored_circle_data_index = @circles_data.index(last_colored_circle_data) || -1
5262
+ @circles_data.insert(last_colored_circle_data_index + 1, removed_colored_circle_data)
5245
5263
  end
5246
5264
 
5247
5265
  def launch
@@ -5286,12 +5304,12 @@ class ColorTheShapes
5286
5304
  menu('Help') {
5287
5305
  menu_item('Instructions') {
5288
5306
  on_clicked do
5289
- msg_box('Instructions', "Score goes down as shapes are added.\nIf it reaches -20, you lose!\n\nClick shapes to color and score!\nOnce score reaches 0, you win!\n\nBeware of concealed light-colored shapes!\nThey are revealed once darker shapes intersect them.\n\nThere are four levels of difficulty.\nChange via difficulty menu if the game gets too tough.")
5307
+ msg_box('Instructions', "Score goes down as circles are added.\nIf it reaches -20, you lose!\n\nClick circles to color and score!\nOnce score reaches 0, you win!\n\nBeware of concealed light-colored circles!\nThey are revealed once darker circles intersect them.\n\nThere are four levels of difficulty.\nChange via difficulty menu if the game gets too tough.")
5290
5308
  end
5291
5309
  }
5292
5310
  }
5293
5311
 
5294
- window('Color The Shapes', WINDOW_WIDTH, WINDOW_HEIGHT) {
5312
+ window('Color The Circles', WINDOW_WIDTH, WINDOW_HEIGHT) {
5295
5313
  margined true
5296
5314
 
5297
5315
  grid {
@@ -5305,13 +5323,13 @@ class ColorTheShapes
5305
5323
  end
5306
5324
  }
5307
5325
 
5308
- label('Score goes down as shapes are added. If it reaches -20, you lose!') {
5326
+ label('Score goes down as circles are added. If it reaches -20, you lose!') {
5309
5327
  left 0
5310
5328
  top 1
5311
5329
  halign :center
5312
5330
  }
5313
5331
 
5314
- label('Click shapes to color and score! Once score reaches 0, you win!') {
5332
+ label('Click circles to color and score! Once score reaches 0, you win!') {
5315
5333
  left 0
5316
5334
  top 2
5317
5335
  halign :center
@@ -5346,18 +5364,18 @@ class ColorTheShapes
5346
5364
  fill :white
5347
5365
  }
5348
5366
 
5349
- @shapes_data.each do |shape_data|
5367
+ @circles_data.each do |circle_data|
5350
5368
  path {
5351
- shape_data[:shape] = send(SHAPES.sample, *shape_data[:args])
5369
+ circle_data[:circle] = circle(*circle_data[:args])
5352
5370
 
5353
- fill shape_data[:fill]
5354
- stroke shape_data[:stroke]
5371
+ fill circle_data[:fill]
5372
+ stroke circle_data[:stroke]
5355
5373
  }
5356
5374
  end
5357
5375
  end
5358
5376
 
5359
5377
  on_mouse_down do |area_mouse_event|
5360
- color_shape(area_mouse_event[:x], area_mouse_event[:y])
5378
+ color_circle(area_mouse_event[:x], area_mouse_event[:y])
5361
5379
  end
5362
5380
  }
5363
5381
  }
@@ -5365,7 +5383,7 @@ class ColorTheShapes
5365
5383
  end
5366
5384
  end
5367
5385
 
5368
- ColorTheShapes.new.launch
5386
+ ColorTheCircles.new.launch
5369
5387
  ```
5370
5388
 
5371
5389
  ### Basic Draw Text
@@ -5991,6 +6009,26 @@ window('Method-Based Custom Keyword') {
5991
6009
  }.show
5992
6010
  ```
5993
6011
 
6012
+ ## Applications
6013
+
6014
+ Here are some applications built with [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui)
6015
+
6016
+ ### Manga2PDF
6017
+
6018
+ Download and merge manga images into a single pdf file.
6019
+
6020
+ https://github.com/PinGunter/manga2pdf
6021
+
6022
+ ![manga2pdf screenshot](https://raw.githubusercontent.com/PinGunter/manga2pdf/master/screenshots/manga2pdf-gui.png)
6023
+
6024
+ ### Befunge98 GUI
6025
+
6026
+ Ruby implementation of the Befunge-98 programmming language.
6027
+
6028
+ https://github.com/AndyObtiva/befunge98/tree/gui
6029
+
6030
+ ![befunge98 gui screenshot](https://raw.githubusercontent.com/AndyObtiva/befunge98/master/gui/glimmer-dsl-libui/befunge98_gui_glimmer_dsl_libui/screenshots/befunge98_gui_glimmer_dsl_libui_example.png)
6031
+
5994
6032
  ## Contributing to glimmer-dsl-libui
5995
6033
 
5996
6034
  - Check out the latest master to make sure the feature hasn't been