glimmer-dsl-libui 0.0.28 → 0.1.3

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.0.28
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.1.3
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
  [![Maintainability](https://api.codeclimate.com/v1/badges/ce2853efdbecf6ebdc73/maintainability)](https://codeclimate.com/github/AndyObtiva/glimmer-dsl-libui/maintainability)
@@ -19,7 +19,7 @@ The main trade-off in using [Glimmer DSL for LibUI](https://rubygems.org/gems/gl
19
19
  - Scaffolding for new custom controls, apps, and gems
20
20
  - Native-Executable packaging on Mac, Windows, and Linux.
21
21
 
22
- Example:
22
+ Hello, World!
23
23
 
24
24
  ```ruby
25
25
  require 'glimmer-dsl-libui'
@@ -32,6 +32,98 @@ window('hello world').show
32
32
  ![glimmer-dsl-libui-mac-basic-window.png](images/glimmer-dsl-libui-mac-basic-window.png)
33
33
  ![glimmer-dsl-libui-linux-basic-window.png](images/glimmer-dsl-libui-linux-basic-window.png)
34
34
 
35
+ Basic Table Progress Bar
36
+
37
+ ```ruby
38
+ require 'glimmer-dsl-libui'
39
+
40
+ include Glimmer
41
+
42
+ data = [
43
+ ['task 1', 0],
44
+ ['task 2', 15],
45
+ ['task 3', 100],
46
+ ['task 4', 75],
47
+ ['task 5', -1],
48
+ ]
49
+
50
+ window('Task progress', 300, 200) {
51
+ horizontal_box {
52
+ table {
53
+ text_column('Task')
54
+ progress_bar_column('Progress')
55
+
56
+ cell_rows data
57
+ }
58
+ }
59
+ }.show
60
+ ```
61
+
62
+ ![glimmer-dsl-libui-mac-basic-table-progress-bar.png](images/glimmer-dsl-libui-mac-basic-table-progress-bar.png)
63
+ ![glimmer-dsl-libui-linux-basic-table-progress-bar.png](images/glimmer-dsl-libui-linux-basic-table-progress-bar.png)
64
+
65
+ Area Gallery
66
+
67
+ ```ruby
68
+ require 'glimmer-dsl-libui'
69
+
70
+ include Glimmer
71
+
72
+ window('Area Gallery', 400, 400) {
73
+ vertical_box {
74
+ area {
75
+ path { # declarative stable path
76
+ square(0, 0, 100)
77
+ square(100, 100, 400)
78
+
79
+ fill r: 102, g: 102, b: 204
80
+ }
81
+ path { # declarative stable path
82
+ rectangle(0, 100, 100, 400)
83
+ rectangle(100, 0, 400, 100)
84
+
85
+ fill r: 204, g: 102, b: 204
86
+ }
87
+ path { # declarative stable path
88
+ figure(100, 100) {
89
+ line(100, 400)
90
+ line(400, 100)
91
+ line(400, 400)
92
+
93
+ closed true
94
+ }
95
+
96
+ fill r: 202, g: 102, b: 104, a: 0.5
97
+ stroke thickness: 1, r: 0, g: 0, b: 0
98
+ }
99
+ path { # declarative stable path
100
+ figure(0, 0) {
101
+ bezier(200, 100, 100, 200, 400, 100)
102
+ bezier(300, 100, 100, 300, 100, 400)
103
+ bezier(100, 300, 300, 100, 400, 400)
104
+
105
+ closed true
106
+ }
107
+
108
+ fill r: 202, g: 102, b: 204, a: 0.5
109
+ stroke thickness: 2, r: 0, g: 0, b: 0
110
+ }
111
+ path { # declarative stable path
112
+ arc(200, 200, 90, 0, 360, false)
113
+
114
+ fill r: 202, g: 102, b: 204, a: 0.5
115
+ stroke thickness: 2, r: 0, g: 0, b: 0
116
+ }
117
+ }
118
+ }
119
+ }.show
120
+ ```
121
+
122
+ ![glimmer-dsl-libui-mac-area-gallery.png](images/glimmer-dsl-libui-mac-area-gallery.png)
123
+ ![glimmer-dsl-libui-linux-area-gallery.png](images/glimmer-dsl-libui-linux-area-gallery.png)
124
+
125
+ [Check Out Many More Examples Over Here!](#examples)
126
+
35
127
  NOTE: [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) is in early alpha mode (only supports included [examples](#examples)). Please help make better by contributing, adopting for small or low risk projects, and providing feedback. It is still an early alpha, so the more feedback and issues you report the better.
36
128
 
37
129
  Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interested in:
@@ -43,9 +135,10 @@ Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interes
43
135
 
44
136
  ## Table of Contents
45
137
 
46
- - [Glimmer DSL for LibUI 0.0.28](#-glimmer-dsl-for-libui-0028)
138
+ - [Glimmer DSL for LibUI 0.1.3](#-glimmer-dsl-for-libui-013)
47
139
  - [Glimmer GUI DSL Concepts](#glimmer-gui-dsl-concepts)
48
140
  - [Usage](#usage)
141
+ - [Girb (Glimmer IRB)](#girb-glimmer-irb)
49
142
  - [API](#api)
50
143
  - [Supported Controls](#supported-controls)
51
144
  - [Common Control Properties](#common-control-properties)
@@ -53,11 +146,11 @@ Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interes
53
146
  - [Extra Dialogs](#extra-dialogs)
54
147
  - [Extra Operations](#extra-operations)
55
148
  - [Table API](#table-api)
149
+ - [Area API](#area-api)
56
150
  - [Smart Defaults and Conventions](#smart-defaults-and-conventions)
57
151
  - [API Gotchas](#api-gotchas)
58
152
  - [Original API](#original-api)
59
153
  - [Glimmer Style Guide](#glimmer-style-guide)
60
- - [Girb (Glimmer IRB)](#girb-glimmer-irb)
61
154
  - [Examples](#examples)
62
155
  - [Basic Window](#basic-window)
63
156
  - [Basic Button](#basic-button)
@@ -80,6 +173,9 @@ Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interes
80
173
  - [Basic Table Checkbox Text](#basic-table-checkbox-text)
81
174
  - [Basic Table Progress Bar](#basic-table-progress-bar)
82
175
  - [Form Table](#form-table)
176
+ - [Basic Area](#basic-area)
177
+ - [Dynamic Area](#dynamic-area)
178
+ - [Area Gallery](#area-gallery)
83
179
  - [Contributing to glimmer-dsl-libui](#contributing-to-glimmer-dsl-libui)
84
180
  - [Help](#help)
85
181
  - [Issues](#issues)
@@ -167,7 +263,7 @@ gem install glimmer-dsl-libui
167
263
  Or install via Bundler `Gemfile`:
168
264
 
169
265
  ```ruby
170
- gem 'glimmer-dsl-libui', '~> 0.0.28'
266
+ gem 'glimmer-dsl-libui', '~> 0.1.3'
171
267
  ```
172
268
 
173
269
  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.
@@ -194,6 +290,24 @@ end
194
290
  Application.new.launch
195
291
  ```
196
292
 
293
+ If you are new to [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui), check out [Girb](#girb-glimmer-irb) and [Examples](#examples) to quickly learn through copy/paste. You may refer to the [API](#api) later on once you have gotten your feet wet with [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) and need more detailed reference information.
294
+
295
+ ## Girb (Glimmer IRB)
296
+
297
+ You can run the `girb` command (`bin/girb` if you cloned the project locally) to do some quick and dirty experimentation and learning:
298
+
299
+ ```
300
+ girb
301
+ ```
302
+
303
+ This gives you `irb` with the `glimmer-dsl-libui` gem loaded and the `Glimmer` module mixed into the main object for easy experimentation with GUI.
304
+
305
+ ![glimmer-dsl-libui-girb.png](images/glimmer-dsl-libui-girb.png)
306
+
307
+ For a more advanced code editing tool, check out the [Meta-Example (The Example of Examples)](#examples).
308
+
309
+ Gotcha: On the Mac, when you close a window opened in `girb`, it remains open until you enter `exit` or open another GUI window.
310
+
197
311
  ## API
198
312
 
199
313
  Any control returned by a [Glimmer GUI DSL](#glimmer-gui-dsl-concepts) keyword declaration can be introspected for its properties and updated via object-oriented attributes (standard Ruby `attr`/`attr=` or `set_attr`).
@@ -223,17 +337,21 @@ w.libui # => #<Fiddle::Pointer:0x00007fde53997980 ptr=0x00007fde51352a60 size=0
223
337
  Control(Args) | Properties | Listeners
224
338
  ------------- | ---------- | ---------
225
339
  `about_menu_item` | None | `on_clicked`
340
+ `area` | None | `on_draw`
341
+ `arc(x_center as Numeric, y_center as Numeric, radius as Numeric, start_angle as Numeric, sweep as Numeric, is_negative as Boolean)` | `x_center` (`Numeric`), `y_center` (`Numeric`), `radius` (`Numeric`), `start_angle` (`Numeric`), `sweep` (`Numeric`), `is_negative` (Boolean) | None
342
+ `bezier(c1_x as Numeric, c1_y as Numeric, c2_x as Numeric, c2_y as Numeric, end_x as Numeric, end_y as Numeric)` | `c1_x` (`Numeric`), `c1_y` (`Numeric`), `c2_x` (`Numeric`), `c2_y` (`Numeric`), `end_x` (`Numeric`), `end_y` (`Numeric`) | None
226
343
  `button(text as String)` | `text` (`String`) | `on_clicked`
227
344
  `button_column(name as String)` | `enabled` (Boolean) | None
228
345
  `checkbox(text as String)` | `checked` (Boolean), `text` (`String`) | `on_toggled`
229
- `checkbox_column(name as String)` | `editable` (Boolean) [Windows-only due to a current libui limitation] | None
230
- `checkbox_text_column(name as String)` | `editable` (Boolean) [Windows-only due to a current libui limitation], `editable_checkbox` (Boolean) [Windows-only due to a current libui limitation], `editable_text` (Boolean) | None
346
+ `checkbox_column(name as String)` | `editable` (Boolean) | None
347
+ `checkbox_text_column(name as String)` | `editable` (Boolean), `editable_checkbox` (Boolean), `editable_text` (Boolean) | None
231
348
  `combobox` | `items` (`Array` of `String`), `selected` (`Integer`) | `on_selected`
232
349
  `color_button` | `color` (Array of `red` as `Float`, `green` as `Float`, `blue` as `Float`, `alpha` as `Float`), `red` as `Float`, `green` as `Float`, `blue` as `Float`, `alpha` as `Float` | `on_changed`
233
350
  `date_picker` | `time` (`Hash` of keys: `sec` as `Integer`, `min` as `Integer`, `hour` as `Integer`, `mday` as `Integer`, `mon` as `Integer`, `year` as `Integer`, `wday` as `Integer`, `yday` as `Integer`, `dst` as Boolean) | `on_changed`
234
351
  `date_time_picker` | `time` (`Hash` of keys: `sec` as `Integer`, `min` as `Integer`, `hour` as `Integer`, `mday` as `Integer`, `mon` as `Integer`, `year` as `Integer`, `wday` as `Integer`, `yday` as `Integer`, `dst` as Boolean) | `on_changed`
235
352
  `editable_combobox` | `items` (`Array` of `String`), `text` (`String`) | `on_changed`
236
353
  `entry` | `read_only` (Boolean), `text` (`String`) | `on_changed`
354
+ `figure(x as Numeric, y as Numeric)` | `x` (`Numeric`), `y` (`Numeric`), `closed` (Boolean) | None
237
355
  `font_button` | `font` [read-only] (`Hash` of keys: `:family`, `:size`, `:weight`, `:italic`, `:stretch`), `family` as `String`, `size` as `Float`, `weight` as `Integer`, `italic` as `Integer`, `stretch` as `Integer` | `on_changed`
238
356
  `form` | `padded` (Boolean) | None
239
357
  `grid` | `padded` (Boolean) | None
@@ -245,19 +363,23 @@ Control(Args) | Properties | Listeners
245
363
  `image_column(name as String)` | None | None
246
364
  `image_text_column(name as String)` | None | None
247
365
  `label(text as String)` | `text` (`String`) | None
366
+ `line(x as Numeric, y as Numeric)` | `x` (`Numeric`), `y` (`Numeric`) | None
248
367
  `menu(text as String)` | None | None
249
368
  `menu_item(text as String)` | `checked` (Boolean) | `on_clicked`
250
369
  `multiline_entry` | `read_only` (Boolean), `text` (`String`) | `on_changed`
251
370
  `msg_box(window as Glimmer::LibUI::WindowProxy, title as String, description as String)` | None | None
252
371
  `msg_box_error(window as Glimmer::LibUI::WindowProxy, title as String, description as String)` | None | None
253
372
  `non_wrapping_multiline_entry` | `read_only` (Boolean), `text` (`String`) | `on_changed`
373
+ `path` | `fill` (`Hash` of `:r` as `0`-`255`, `:g` as `0`-`255`, `:b` as `0`-`255`, `:a` as `0.0`-`1.0`), `stroke` (`Hash` of `:r` as `0`-`255`, `:g` as `0`-`255`, `:b` as `0`-`255`, `:a` as `0.0`-`1.0`, `:cap` as `Numeric`, `:join` as `Numeric`, `:thickness` as `Numeric`, `:miter_limit` as `Numeric` ) | None
254
374
  `preferences_menu_item` | None | `on_clicked`
255
375
  `progress_bar` | `value` (`Numeric`) | None
256
376
  `progress_bar_column(name as String)` | None | None
257
377
  `quit_menu_item` | None | `on_clicked`
258
378
  `radio_buttons` | `selected` (`Integer`) | `on_selected`
379
+ `rectangle(x as Numeric, y as Numeric, width as Numeric, height as Numeric)` | `x` (`Numeric`), `y` (`Numeric`), `width` (`Numeric`), `height` (`Numeric`) | None
259
380
  `slider(min as Numeric, max as Numeric)` | `value` (`Numeric`) | `on_changed`
260
381
  `spinbox(min as Numeric, max as Numeric)` | `value` (`Numeric`) | `on_changed`
382
+ `square(x as Numeric, y as Numeric, length as Numeric)` | `x` (`Numeric`), `y` (`Numeric`), `length` (`Numeric`) | None
261
383
  `tab` | `margined` (Boolean), `num_pages` (`Integer`) | None
262
384
  `tab_item(name as String)` | `index` [read-only] (`Integer`), `margined` (Boolean), `name` [read-only] (`String`) | None
263
385
  `table` | `cell_rows` (`Array` (rows) of `Arrays` (row columns) of cell values (e.g. `String` values for `text_column` cells or `Array` of `image`/`String` for `image_text_column`)), `editable` as Boolean | None
@@ -302,6 +424,7 @@ Control(Args) | Properties | Listeners
302
424
  - `ControlProxy::image_proxies`: returns all instantiated `image` proxies in the application
303
425
  - `ControlProxy::main_window_proxy`: returns the first window proxy instantiated in the application
304
426
  - `ControlProxy#window_proxy`: returns the window proxy parent for a control
427
+ - `ControlProxy#content {...}`: re-opens control's content to add more nested controls or properties
305
428
 
306
429
  ### Table API
307
430
 
@@ -321,6 +444,148 @@ Note that the `cell_rows` property declaration results in "implicit data-binding
321
444
  - Inserting cell rows: Calling `Array#<<`, `Array#push`, `Array#prepend`, or any insertion/addition `Array` method automatically inserts rows in actual `table` control
322
445
  - Changing cell rows: Calling `Array#[]=`, `Array#map!`, or any update `Array` method automatically updates rows in actual `table` control
323
446
 
447
+ Example (you may copy/paste in [`girb`](#girb-glimmer-irb)):
448
+
449
+ ```ruby
450
+ require 'glimmer-dsl-libui'
451
+
452
+ include Glimmer
453
+
454
+ data = [
455
+ ['Lisa Sky', 'lisa@sky.com', '720-523-4329', 'Denver', 'CO', '80014'],
456
+ ['Jordan Biggins', 'jordan@biggins.com', '617-528-5399', 'Boston', 'MA', '02101'],
457
+ ['Mary Glass', 'mary@glass.com', '847-589-8788', 'Elk Grove Village', 'IL', '60007'],
458
+ ['Darren McGrath', 'darren@mcgrath.com', '206-539-9283', 'Seattle', 'WA', '98101'],
459
+ ['Melody Hanheimer', 'melody@hanheimer.com', '213-493-8274', 'Los Angeles', 'CA', '90001'],
460
+ ]
461
+
462
+ window('Contacts', 600, 600) { |w|
463
+ margined true
464
+
465
+ vertical_box {
466
+ form {
467
+ stretchy false
468
+
469
+ @name_entry = entry {
470
+ label 'Name'
471
+ }
472
+ @email_entry = entry {
473
+ label 'Email'
474
+ }
475
+ @phone_entry = entry {
476
+ label 'Phone'
477
+ }
478
+ @city_entry = entry {
479
+ label 'City'
480
+ }
481
+ @state_entry = entry {
482
+ label 'State'
483
+ }
484
+ }
485
+
486
+ button('Save Contact') {
487
+ stretchy false
488
+
489
+ on_clicked do
490
+ new_row = [@name_entry.text, @email_entry.text, @phone_entry.text, @city_entry.text, @state_entry.text]
491
+ if new_row.include?('')
492
+ msg_box_error(w, 'Validation Error!', 'All fields are required! Please make sure to enter a value for all fields.')
493
+ else
494
+ data << new_row # automatically inserts a row into the table due to implicit data-binding
495
+ @name_entry.text = ''
496
+ @email_entry.text = ''
497
+ @phone_entry.text = ''
498
+ @city_entry.text = ''
499
+ @state_entry.text = ''
500
+ end
501
+ end
502
+ }
503
+
504
+ table {
505
+ text_column('Name')
506
+ text_column('Email')
507
+ text_column('Phone')
508
+ text_column('City')
509
+ text_column('State')
510
+
511
+ cell_rows data # implicit data-binding
512
+ }
513
+ }
514
+ }.show
515
+ ```
516
+
517
+ ![glimmer-dsl-libui-linux-form-table.png](images/glimmer-dsl-libui-linux-form-table.png)
518
+
519
+ Learn more by checking out [examples](#examples).
520
+
521
+ ### Area API
522
+
523
+ The `area` control can be used in one of two ways:
524
+ - 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. Paths proxy objects are preserved across redraws assuming there would be few stable paths (mostly for decorative reasons).
525
+ - Semi-declaratively via on_draw listener dynamic paths: useful for more dynamic paths that will definitely change. Open an `on_draw` listener block and nest `path(area_draw_params)` 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.
526
+
527
+ Here is an example of a declarative `area` with a stable path (you may copy/paste in [`girb`](#girb-glimmer-irb)):
528
+
529
+ ```ruby
530
+ require 'glimmer-dsl-libui'
531
+
532
+ include Glimmer
533
+
534
+ window('Basic Area', 400, 400) {
535
+ margined true
536
+
537
+ vertical_box {
538
+ area {
539
+ path { # a stable path is added declaratively
540
+ rectangle(0, 0, 400, 400)
541
+
542
+ fill r: 102, g: 102, b: 204, a: 1.0
543
+ }
544
+ }
545
+ }
546
+ }.show
547
+ ```
548
+
549
+ ![glimmer-dsl-libui-mac-basic-area.png](images/glimmer-dsl-libui-mac-basic-area.png)
550
+
551
+ Here is the same example using a semi-declarative `area` with `on_draw` listener and a dynamic path (you may copy/paste in [`girb`](#girb-glimmer-irb)):
552
+
553
+ ```ruby
554
+ require 'glimmer-dsl-libui'
555
+
556
+ include Glimmer
557
+
558
+ window('Basic Area', 400, 400) {
559
+ margined true
560
+
561
+ vertical_box {
562
+ area {
563
+ on_draw do |area_draw_params|
564
+ path(area_draw_params) { # a dynamic path is added semi-declaratively inside on_draw block
565
+ rectangle(0, 0, 400, 400)
566
+
567
+ fill r: 102, g: 102, b: 204, a: 1.0
568
+ }
569
+ end
570
+ }
571
+ }
572
+ }.show
573
+ ```
574
+
575
+ Check [examples/dynamic_area.rb](#dynamic-area) for a more detailed semi-declarative example.
576
+
577
+ Available nested `path` shapes:
578
+ - `rectangle(x as Numeric, y as Numeric, width as Numeric, height as Numeric)`
579
+ - `square(x as Numeric, y as Numeric, length as Numeric)`
580
+ - `arc(x_center as Numeric, y_center as Numeric, radius as Numeric, start_angle as Numeric, sweep as Numeric, is_negative as Boolean)`
581
+ - `line(x as Numeric, y as Numeric)`
582
+ - `bezier(c1_x as Numeric, c1_y as Numeric, c2_x as Numeric, c2_y as Numeric, end_x as Numeric, end_y as Numeric)`
583
+ - `figure(x as Numeric, y as Numeric)` (composite that can contain other shapes) (can set `closed true` to connect last point to first point automatically)
584
+
585
+ In general, it is recommended to use declarative stable paths whenever feasible since they require less code and simpler maintenance. But, in more advanced cases, semi-declarative dynamic paths could be used instead, especially if there are thousands of paths.
586
+
587
+ To redraw an `area`, you may call `#queue_redraw_all` method.
588
+
324
589
  ### Smart Defaults and Conventions
325
590
 
326
591
  - `horizontal_box`, `vertical_box`, `grid`, and `form` controls have `padded` as `true` upon instantiation to ensure more user-friendly GUI by default
@@ -349,11 +614,14 @@ Note that the `cell_rows` property declaration results in "implicit data-binding
349
614
  - 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.
350
615
  - `image` instances are automatically freed from memory after `window` is destroyed.
351
616
  - `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`
617
+ - `area` paths are specified declaratively with figures underneath (e.g. `rectangle`) and `area` draw listener is automatically generated
618
+ - Observe figure properties (e.g. `rectangle` `width`) for changes and automatically redraw containing area accordingly
619
+ - Observe `path` `fill` and `stroke` hashes for changes and automatically redraw containing area accordingly
352
620
 
353
621
  ### API Gotchas
354
622
 
355
623
  - 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`).
356
- - `table` `checkbox_column` and `checkbox_text_column` checkbox editing currently only works in Windows due to a current limitation in [libui](https://github.com/andlabs/libui).
624
+ - `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).
357
625
 
358
626
  ### Original API
359
627
 
@@ -369,21 +637,9 @@ check out the [libui C headers](https://github.com/andlabs/libui/blob/master/ui.
369
637
  - Control listeners are always declared starting with on_ prefix and affixing listener event method name afterwards in underscored lowercase form. Their multi-line blocks have a `do; end` style.
370
638
  - Pure logic multi-line blocks that do not constitute GUI DSL view elements have `do; end` style to clearly separate logic code from view code.
371
639
 
372
- ## Girb (Glimmer IRB)
373
-
374
- You can run the `girb` command (`bin/girb` if you cloned the project locally):
375
-
376
- ```
377
- girb
378
- ```
379
-
380
- This gives you `irb` with the `glimmer-dsl-libui` gem loaded and the `Glimmer` module mixed into the main object for easy experimentation with GUI.
381
-
382
- Gotcha: On the Mac, when you close a window opened in `girb`, it remains open until you enter `exit` or open another GUI window.
383
-
384
640
  ## Examples
385
641
 
386
- These examples include reimplementions of the examples in the [LibUI](https://github.com/kojix2/LibUI) project utilizing the [Glimmer GUI DSL](#glimmer-gui-dsl-concepts) as well as brand new examples.
642
+ The following examples include reimplementions of the examples in the [LibUI](https://github.com/kojix2/LibUI) project utilizing the [Glimmer GUI DSL](#glimmer-gui-dsl-concepts) as well as brand new examples.
387
643
 
388
644
  To browse all examples, simply launch the [Meta-Example](examples/meta_example.rb), which lists all examples and displays each example's code when selected. It also enables code editing to facilitate experimentation and learning.
389
645
 
@@ -2581,6 +2837,441 @@ window('Contacts', 600, 600) { |w|
2581
2837
  }.show
2582
2838
  ```
2583
2839
 
2840
+ ### Basic Area
2841
+
2842
+ [examples/basic_area.rb](examples/basic_area.rb)
2843
+
2844
+ Run with this command from the root of the project if you cloned the project:
2845
+
2846
+ ```
2847
+ ruby -r './lib/glimmer-dsl-libui' examples/basic_area.rb
2848
+ ```
2849
+
2850
+ Run with this command if you installed the [Ruby gem](https://rubygems.org/gems/glimmer-dsl-libui):
2851
+
2852
+ ```
2853
+ ruby -r glimmer-dsl-libui -e "require 'examples/basic_area'"
2854
+ ```
2855
+
2856
+ Mac
2857
+
2858
+ ![glimmer-dsl-libui-mac-basic-area.png](images/glimmer-dsl-libui-mac-basic-area.png)
2859
+
2860
+ Linux
2861
+
2862
+ ![glimmer-dsl-libui-linux-basic-area.png](images/glimmer-dsl-libui-linux-basic-area.png)
2863
+
2864
+ [LibUI](https://github.com/kojix2/LibUI) Original Version:
2865
+
2866
+ ```ruby
2867
+ require 'libui'
2868
+
2869
+ UI = LibUI
2870
+
2871
+ UI.init
2872
+
2873
+ handler = UI::FFI::AreaHandler.malloc
2874
+ area = UI.new_area(handler)
2875
+ brush = UI::FFI::DrawBrush.malloc
2876
+
2877
+ handler_draw_event = Fiddle::Closure::BlockCaller.new(0, [1, 1, 1]) do |_, _, area_draw_params|
2878
+ path = UI.draw_new_path(0)
2879
+ UI.draw_path_add_rectangle(path, 0, 0, 400, 400)
2880
+ UI.draw_path_end(path)
2881
+ brush.Type = 0
2882
+ brush.R = 0.4
2883
+ brush.G = 0.4
2884
+ brush.B = 0.8
2885
+ brush.A = 1.0
2886
+ area_draw_params = UI::FFI::AreaDrawParams.new(area_draw_params)
2887
+ UI.draw_fill(area_draw_params.Context, path, brush.to_ptr)
2888
+ UI.draw_free_path(path)
2889
+ end
2890
+
2891
+ handler.Draw = handler_draw_event
2892
+ handler.MouseEvent = Fiddle::Closure::BlockCaller.new(0, [0]) {}
2893
+ handler.MouseCrossed = Fiddle::Closure::BlockCaller.new(0, [0]) {}
2894
+ handler.DragBroken = Fiddle::Closure::BlockCaller.new(0, [0]) {}
2895
+ handler.KeyEvent = Fiddle::Closure::BlockCaller.new(0, [0]) {}
2896
+
2897
+ box = UI.new_vertical_box
2898
+ UI.box_set_padded(box, 1)
2899
+ UI.box_append(box, area, 1)
2900
+
2901
+ main_window = UI.new_window('Basic Area', 400, 400, 1)
2902
+ UI.window_set_margined(main_window, 1)
2903
+ UI.window_set_child(main_window, box)
2904
+
2905
+ UI.window_on_closing(main_window) do
2906
+ UI.control_destroy(main_window)
2907
+ UI.quit
2908
+ 0
2909
+ end
2910
+ UI.control_show(main_window)
2911
+
2912
+ UI.main
2913
+ UI.quit
2914
+ ```
2915
+
2916
+ [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
2917
+
2918
+ ```ruby
2919
+ require 'glimmer-dsl-libui'
2920
+
2921
+ include Glimmer
2922
+
2923
+ window('Basic Area', 400, 400) {
2924
+ margined true
2925
+
2926
+ vertical_box {
2927
+ area {
2928
+ path { # a stable path is added declaratively
2929
+ rectangle(0, 0, 400, 400)
2930
+
2931
+ fill r: 102, g: 102, b: 204, a: 1.0
2932
+ }
2933
+ }
2934
+ }
2935
+ }.show
2936
+ ```
2937
+
2938
+ [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2:
2939
+
2940
+ ```ruby
2941
+ require 'glimmer-dsl-libui'
2942
+
2943
+ include Glimmer
2944
+
2945
+ window('Basic Area', 400, 400) {
2946
+ margined true
2947
+
2948
+ vertical_box {
2949
+ area {
2950
+ on_draw do |area_draw_params|
2951
+ path(area_draw_params) { # a dynamic path is added semi-declaratively inside on_draw block
2952
+ rectangle(0, 0, 400, 400)
2953
+
2954
+ fill r: 102, g: 102, b: 204, a: 1.0
2955
+ }
2956
+ end
2957
+ }
2958
+ }
2959
+ }.show
2960
+ ```
2961
+
2962
+ ### Dynamic Area
2963
+
2964
+ [examples/dynamic_area.rb](examples/dynamic_area.rb)
2965
+
2966
+ Run with this command from the root of the project if you cloned the project:
2967
+
2968
+ ```
2969
+ ruby -r './lib/glimmer-dsl-libui' examples/dynamic_area.rb
2970
+ ```
2971
+
2972
+ Run with this command if you installed the [Ruby gem](https://rubygems.org/gems/glimmer-dsl-libui):
2973
+
2974
+ ```
2975
+ ruby -r glimmer-dsl-libui -e "require 'examples/dynamic_area'"
2976
+ ```
2977
+
2978
+ Mac
2979
+
2980
+ ![glimmer-dsl-libui-mac-dynamic-area.png](images/glimmer-dsl-libui-mac-dynamic-area.png)
2981
+ ![glimmer-dsl-libui-mac-dynamic-area-updated.png](images/glimmer-dsl-libui-mac-dynamic-area-updated.png)
2982
+
2983
+ Linux
2984
+
2985
+ ![glimmer-dsl-libui-linux-dynamic-area.png](images/glimmer-dsl-libui-linux-dynamic-area.png)
2986
+ ![glimmer-dsl-libui-linux-dynamic-area-updated.png](images/glimmer-dsl-libui-linux-dynamic-area-updated.png)
2987
+
2988
+ New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
2989
+
2990
+ ```ruby
2991
+ require 'glimmer-dsl-libui'
2992
+
2993
+ include Glimmer
2994
+
2995
+ window('Dynamic Area', 240, 500) {
2996
+ margined true
2997
+
2998
+ vertical_box {
2999
+ label('Rectangle Properties') {
3000
+ stretchy false
3001
+ }
3002
+
3003
+ form {
3004
+ stretchy false
3005
+
3006
+ @x_spinbox = spinbox(0, 1000) {
3007
+ label 'x'
3008
+ value 25
3009
+
3010
+ on_changed do
3011
+ @area.queue_redraw_all
3012
+ end
3013
+ }
3014
+
3015
+ @y_spinbox = spinbox(0, 1000) {
3016
+ label 'y'
3017
+ value 25
3018
+
3019
+ on_changed do
3020
+ @area.queue_redraw_all
3021
+ end
3022
+ }
3023
+
3024
+ @width_spinbox = spinbox(0, 1000) {
3025
+ label 'width'
3026
+ value 150
3027
+
3028
+ on_changed do
3029
+ @area.queue_redraw_all
3030
+ end
3031
+ }
3032
+
3033
+ @height_spinbox = spinbox(0, 1000) {
3034
+ label 'height'
3035
+ value 150
3036
+
3037
+ on_changed do
3038
+ @area.queue_redraw_all
3039
+ end
3040
+ }
3041
+
3042
+ @red_spinbox = spinbox(0, 255) {
3043
+ label 'red'
3044
+ value 102
3045
+
3046
+ on_changed do
3047
+ @area.queue_redraw_all
3048
+ end
3049
+ }
3050
+
3051
+ @green_spinbox = spinbox(0, 255) {
3052
+ label 'green'
3053
+ value 102
3054
+
3055
+ on_changed do
3056
+ @area.queue_redraw_all
3057
+ end
3058
+ }
3059
+
3060
+ @blue_spinbox = spinbox(0, 255) {
3061
+ label 'blue'
3062
+ value 204
3063
+
3064
+ on_changed do
3065
+ @area.queue_redraw_all
3066
+ end
3067
+ }
3068
+
3069
+ @alpha_spinbox = spinbox(0, 100) {
3070
+ label 'alpha'
3071
+ value 100
3072
+
3073
+ on_changed do
3074
+ @area.queue_redraw_all
3075
+ end
3076
+ }
3077
+ }
3078
+
3079
+ @area = area {
3080
+ on_draw do |area_draw_params|
3081
+ path(area_draw_params) { # a dynamic path is added semi-declaratively inside on_draw block
3082
+ rectangle(@x_spinbox.value, @y_spinbox.value, @width_spinbox.value, @height_spinbox.value)
3083
+
3084
+ fill r: @red_spinbox.value, g: @green_spinbox.value, b: @blue_spinbox.value, a: @alpha_spinbox.value / 100.0
3085
+ }
3086
+ end
3087
+ }
3088
+ }
3089
+ }.show
3090
+ ```
3091
+
3092
+ New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2:
3093
+
3094
+ ```ruby
3095
+ require 'glimmer-dsl-libui'
3096
+
3097
+ include Glimmer
3098
+
3099
+ window('Dynamic Area', 240, 600) {
3100
+ margined true
3101
+
3102
+ vertical_box {
3103
+ label('Rectangle Properties') {
3104
+ stretchy false
3105
+ }
3106
+
3107
+ form {
3108
+ stretchy false
3109
+
3110
+ @x_spinbox = spinbox(0, 1000) {
3111
+ label 'x'
3112
+ value 25
3113
+
3114
+ on_changed do
3115
+ @rectangle.x = @x_spinbox.value # updating properties automatically triggers area.queue_redraw_all
3116
+ end
3117
+ }
3118
+
3119
+ @y_spinbox = spinbox(0, 1000) {
3120
+ label 'y'
3121
+ value 25
3122
+
3123
+ on_changed do
3124
+ @rectangle.y = @y_spinbox.value # updating properties automatically triggers area.queue_redraw_all
3125
+ end
3126
+ }
3127
+
3128
+ @width_spinbox = spinbox(0, 1000) {
3129
+ label 'width'
3130
+ value 150
3131
+
3132
+ on_changed do
3133
+ @rectangle.width = @width_spinbox.value # updating properties automatically triggers area.queue_redraw_all
3134
+ end
3135
+ }
3136
+
3137
+ @height_spinbox = spinbox(0, 1000) {
3138
+ label 'height'
3139
+ value 150
3140
+
3141
+ on_changed do
3142
+ @rectangle.height = @height_spinbox.value # updating properties automatically triggers area.queue_redraw_all
3143
+ end
3144
+ }
3145
+
3146
+ @red_spinbox = spinbox(0, 255) {
3147
+ label 'red'
3148
+ value 102
3149
+
3150
+ on_changed do
3151
+ @path.fill[:r] = @red_spinbox.value # updating hash properties automatically triggers area.queue_redraw_all
3152
+ end
3153
+ }
3154
+
3155
+ @green_spinbox = spinbox(0, 255) {
3156
+ label 'green'
3157
+ value 102
3158
+
3159
+ on_changed do
3160
+ @path.fill[:g] = @green_spinbox.value # updating hash properties automatically triggers area.queue_redraw_all
3161
+ end
3162
+ }
3163
+
3164
+ @blue_spinbox = spinbox(0, 255) {
3165
+ label 'blue'
3166
+ value 204
3167
+
3168
+ on_changed do
3169
+ @path.fill[:b] = @blue_spinbox.value # updating hash properties automatically triggers area.queue_redraw_all
3170
+ end
3171
+ }
3172
+
3173
+ @alpha_spinbox = spinbox(0, 100) {
3174
+ label 'alpha'
3175
+ value 100
3176
+
3177
+ on_changed do
3178
+ @path.fill[:a] = @alpha_spinbox.value / 100.0 # updating hash properties automatically triggers area.queue_redraw_all
3179
+ end
3180
+ }
3181
+ }
3182
+
3183
+ area {
3184
+ @path = path { # stable path
3185
+ @rectangle = rectangle(@x_spinbox.value, @y_spinbox.value, @width_spinbox.value, @height_spinbox.value)
3186
+
3187
+ fill r: @red_spinbox.value, g: @green_spinbox.value, b: @blue_spinbox.value, a: @alpha_spinbox.value / 100.0
3188
+ }
3189
+ }
3190
+ }
3191
+ }.show
3192
+ ```
3193
+
3194
+ ### Area Gallery
3195
+
3196
+ [examples/area_gallery.rb](examples/area_gallery.rb)
3197
+
3198
+ Run with this command from the root of the project if you cloned the project:
3199
+
3200
+ ```
3201
+ ruby -r './lib/glimmer-dsl-libui' examples/area_gallery.rb
3202
+ ```
3203
+
3204
+ Run with this command if you installed the [Ruby gem](https://rubygems.org/gems/glimmer-dsl-libui):
3205
+
3206
+ ```
3207
+ ruby -r glimmer-dsl-libui -e "require 'examples/area_gallery'"
3208
+ ```
3209
+
3210
+ Mac
3211
+
3212
+ ![glimmer-dsl-libui-mac-area-gallery.png](images/glimmer-dsl-libui-mac-area-gallery.png)
3213
+
3214
+ Linux
3215
+
3216
+ ![glimmer-dsl-libui-linux-area-gallery.png](images/glimmer-dsl-libui-linux-area-gallery.png)
3217
+
3218
+ New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
3219
+
3220
+ ```ruby
3221
+ require 'glimmer-dsl-libui'
3222
+
3223
+ include Glimmer
3224
+
3225
+ window('Area Gallery', 400, 400) {
3226
+ vertical_box {
3227
+ area {
3228
+ path { # declarative stable path
3229
+ square(0, 0, 100)
3230
+ square(100, 100, 400)
3231
+
3232
+ fill r: 102, g: 102, b: 204
3233
+ }
3234
+ path { # declarative stable path
3235
+ rectangle(0, 100, 100, 400)
3236
+ rectangle(100, 0, 400, 100)
3237
+
3238
+ fill r: 204, g: 102, b: 204
3239
+ }
3240
+ path { # declarative stable path
3241
+ figure(100, 100) {
3242
+ line(100, 400)
3243
+ line(400, 100)
3244
+ line(400, 400)
3245
+
3246
+ closed true
3247
+ }
3248
+
3249
+ fill r: 202, g: 102, b: 104, a: 0.5
3250
+ stroke thickness: 1, r: 0, g: 0, b: 0
3251
+ }
3252
+ path { # declarative stable path
3253
+ figure(0, 0) {
3254
+ bezier(200, 100, 100, 200, 400, 100)
3255
+ bezier(300, 100, 100, 300, 100, 400)
3256
+ bezier(100, 300, 300, 100, 400, 400)
3257
+
3258
+ closed true
3259
+ }
3260
+
3261
+ fill r: 202, g: 102, b: 204, a: 0.5
3262
+ stroke thickness: 2, r: 0, g: 0, b: 0
3263
+ }
3264
+ path { # declarative stable path
3265
+ arc(200, 200, 90, 0, 360, false)
3266
+
3267
+ fill r: 202, g: 102, b: 204, a: 0.5
3268
+ stroke thickness: 2, r: 0, g: 0, b: 0
3269
+ }
3270
+ }
3271
+ }
3272
+ }.show
3273
+ ```
3274
+
2584
3275
  ## Contributing to glimmer-dsl-libui
2585
3276
 
2586
3277
  - Check out the latest master to make sure the feature hasn't been