glimmer-dsl-libui 0.1.1 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +40 -0
- data/README.md +1215 -30
- data/VERSION +1 -1
- data/examples/area_gallery.rb +50 -0
- data/examples/area_gallery2.rb +111 -0
- data/examples/area_gallery3.rb +52 -0
- data/examples/area_gallery4.rb +113 -0
- data/examples/basic_area2.rb +1 -1
- data/examples/basic_table_progress_bar.rb +13 -3
- data/examples/basic_transform.rb +27 -0
- data/examples/dynamic_area.rb +1 -1
- data/examples/dynamic_area2.rb +97 -0
- data/examples/histogram.rb +119 -0
- data/glimmer-dsl-libui.gemspec +0 -0
- data/lib/glimmer/dsl/libui/control_expression.rb +1 -1
- data/lib/glimmer/dsl/libui/dsl.rb +1 -0
- data/lib/glimmer/dsl/libui/property_expression.rb +5 -1
- data/lib/glimmer/dsl/libui/shape_expression.rb +56 -0
- data/lib/glimmer/libui/{rectangle_proxy.rb → arc.rb} +11 -26
- data/lib/glimmer/libui/area_proxy.rb +21 -11
- data/lib/glimmer/libui/bezier.rb +36 -0
- data/lib/glimmer/libui/box.rb +1 -1
- data/lib/glimmer/libui/color_button_proxy.rb +67 -15
- data/lib/glimmer/libui/control_proxy.rb +10 -14
- data/lib/glimmer/libui/figure.rb +52 -0
- data/lib/glimmer/libui/form_proxy.rb +1 -1
- data/lib/glimmer/libui/grid_proxy.rb +1 -1
- data/lib/glimmer/libui/line.rb +36 -0
- data/lib/glimmer/libui/matrix_proxy.rb +145 -0
- data/lib/glimmer/libui/parent.rb +36 -0
- data/lib/glimmer/libui/path_proxy.rb +35 -18
- data/lib/glimmer/libui/rectangle.rb +36 -0
- data/lib/glimmer/libui/shape.rb +143 -0
- data/lib/glimmer/libui/square.rb +36 -0
- data/lib/glimmer/libui/transformable.rb +72 -0
- data/lib/glimmer/libui/window_proxy.rb +8 -1
- data/lib/glimmer/libui.rb +50 -0
- data/lib/glimmer-dsl-libui.rb +1 -0
- metadata +23 -5
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.1.
|
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.4
|
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
|
-
|
22
|
+
Hello, World!
|
23
23
|
|
24
24
|
```ruby
|
25
25
|
require 'glimmer-dsl-libui'
|
@@ -32,6 +32,106 @@ 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
|
+
vertical_box {
|
52
|
+
table {
|
53
|
+
text_column('Task')
|
54
|
+
progress_bar_column('Progress')
|
55
|
+
|
56
|
+
cell_rows data # implicit data-binding
|
57
|
+
}
|
58
|
+
|
59
|
+
button('Mark All As Done') {
|
60
|
+
stretchy false
|
61
|
+
|
62
|
+
on_clicked do
|
63
|
+
data.each_with_index do |row_data, row|
|
64
|
+
data[row] = [row_data[0], 100] # automatically updates table due to implicit data-binding
|
65
|
+
end
|
66
|
+
end
|
67
|
+
}
|
68
|
+
}
|
69
|
+
}.show
|
70
|
+
```
|
71
|
+
|
72
|
+
![glimmer-dsl-libui-mac-basic-table-progress-bar.png](images/glimmer-dsl-libui-mac-basic-table-progress-bar.png)
|
73
|
+
![glimmer-dsl-libui-linux-basic-table-progress-bar.png](images/glimmer-dsl-libui-linux-basic-table-progress-bar.png)
|
74
|
+
|
75
|
+
Area Gallery
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
require 'glimmer-dsl-libui'
|
79
|
+
|
80
|
+
include Glimmer
|
81
|
+
|
82
|
+
window('Area Gallery', 400, 400) {
|
83
|
+
area {
|
84
|
+
path { # declarative stable path
|
85
|
+
square(0, 0, 100)
|
86
|
+
square(100, 100, 400)
|
87
|
+
|
88
|
+
fill r: 102, g: 102, b: 204
|
89
|
+
}
|
90
|
+
path { # declarative stable path
|
91
|
+
rectangle(0, 100, 100, 400)
|
92
|
+
rectangle(100, 0, 400, 100)
|
93
|
+
|
94
|
+
fill r: 204, g: 102, b: 204
|
95
|
+
}
|
96
|
+
path { # declarative stable path
|
97
|
+
figure(100, 100) {
|
98
|
+
line(100, 400)
|
99
|
+
line(400, 100)
|
100
|
+
line(400, 400)
|
101
|
+
|
102
|
+
closed true
|
103
|
+
}
|
104
|
+
|
105
|
+
fill r: 202, g: 102, b: 104, a: 0.5
|
106
|
+
stroke r: 0, g: 0, b: 0
|
107
|
+
}
|
108
|
+
path { # declarative stable path
|
109
|
+
figure(0, 0) {
|
110
|
+
bezier(200, 100, 100, 200, 400, 100)
|
111
|
+
bezier(300, 100, 100, 300, 100, 400)
|
112
|
+
bezier(100, 300, 300, 100, 400, 400)
|
113
|
+
|
114
|
+
closed true
|
115
|
+
}
|
116
|
+
|
117
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
118
|
+
stroke thickness: 2, r: 0, g: 0, b: 0
|
119
|
+
}
|
120
|
+
path { # declarative stable path
|
121
|
+
arc(200, 200, 90, 0, 360, false)
|
122
|
+
|
123
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
124
|
+
stroke thickness: 2, r: 0, g: 0, b: 0
|
125
|
+
}
|
126
|
+
}
|
127
|
+
}.show
|
128
|
+
```
|
129
|
+
|
130
|
+
![glimmer-dsl-libui-mac-area-gallery.png](images/glimmer-dsl-libui-mac-area-gallery.png)
|
131
|
+
![glimmer-dsl-libui-linux-area-gallery.png](images/glimmer-dsl-libui-linux-area-gallery.png)
|
132
|
+
|
133
|
+
[Check Out Many More Examples Over Here!](#examples)
|
134
|
+
|
35
135
|
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
136
|
|
37
137
|
Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interested in:
|
@@ -43,9 +143,10 @@ Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interes
|
|
43
143
|
|
44
144
|
## Table of Contents
|
45
145
|
|
46
|
-
|
146
|
+
- [Glimmer DSL for LibUI 0.1.4](#-glimmer-dsl-for-libui-014)
|
47
147
|
- [Glimmer GUI DSL Concepts](#glimmer-gui-dsl-concepts)
|
48
148
|
- [Usage](#usage)
|
149
|
+
- [Girb (Glimmer IRB)](#girb-glimmer-irb)
|
49
150
|
- [API](#api)
|
50
151
|
- [Supported Controls](#supported-controls)
|
51
152
|
- [Common Control Properties](#common-control-properties)
|
@@ -58,7 +159,6 @@ Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interes
|
|
58
159
|
- [API Gotchas](#api-gotchas)
|
59
160
|
- [Original API](#original-api)
|
60
161
|
- [Glimmer Style Guide](#glimmer-style-guide)
|
61
|
-
- [Girb (Glimmer IRB)](#girb-glimmer-irb)
|
62
162
|
- [Examples](#examples)
|
63
163
|
- [Basic Window](#basic-window)
|
64
164
|
- [Basic Button](#basic-button)
|
@@ -83,6 +183,9 @@ Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interes
|
|
83
183
|
- [Form Table](#form-table)
|
84
184
|
- [Basic Area](#basic-area)
|
85
185
|
- [Dynamic Area](#dynamic-area)
|
186
|
+
- [Area Gallery](#area-gallery)
|
187
|
+
- [Histogram](#histogram)
|
188
|
+
- [Basic Transform](#basic-transform)
|
86
189
|
- [Contributing to glimmer-dsl-libui](#contributing-to-glimmer-dsl-libui)
|
87
190
|
- [Help](#help)
|
88
191
|
- [Issues](#issues)
|
@@ -170,7 +273,7 @@ gem install glimmer-dsl-libui
|
|
170
273
|
Or install via Bundler `Gemfile`:
|
171
274
|
|
172
275
|
```ruby
|
173
|
-
gem 'glimmer-dsl-libui', '~> 0.1.
|
276
|
+
gem 'glimmer-dsl-libui', '~> 0.1.4'
|
174
277
|
```
|
175
278
|
|
176
279
|
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.
|
@@ -197,6 +300,24 @@ end
|
|
197
300
|
Application.new.launch
|
198
301
|
```
|
199
302
|
|
303
|
+
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.
|
304
|
+
|
305
|
+
## Girb (Glimmer IRB)
|
306
|
+
|
307
|
+
You can run the `girb` command (`bin/girb` if you cloned the project locally) to do some quick and dirty experimentation and learning:
|
308
|
+
|
309
|
+
```
|
310
|
+
girb
|
311
|
+
```
|
312
|
+
|
313
|
+
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.
|
314
|
+
|
315
|
+
![glimmer-dsl-libui-girb.png](images/glimmer-dsl-libui-girb.png)
|
316
|
+
|
317
|
+
For a more advanced code editing tool, check out the [Meta-Example (The Example of Examples)](#examples).
|
318
|
+
|
319
|
+
Gotcha: On the Mac, when you close a window opened in `girb`, it remains open until you enter `exit` or open another GUI window.
|
320
|
+
|
200
321
|
## API
|
201
322
|
|
202
323
|
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`).
|
@@ -227,6 +348,8 @@ Control(Args) | Properties | Listeners
|
|
227
348
|
------------- | ---------- | ---------
|
228
349
|
`about_menu_item` | None | `on_clicked`
|
229
350
|
`area` | None | `on_draw`
|
351
|
+
`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
|
352
|
+
`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
|
230
353
|
`button(text as String)` | `text` (`String`) | `on_clicked`
|
231
354
|
`button_column(name as String)` | `enabled` (Boolean) | None
|
232
355
|
`checkbox(text as String)` | `checked` (Boolean), `text` (`String`) | `on_toggled`
|
@@ -238,6 +361,7 @@ Control(Args) | Properties | Listeners
|
|
238
361
|
`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`
|
239
362
|
`editable_combobox` | `items` (`Array` of `String`), `text` (`String`) | `on_changed`
|
240
363
|
`entry` | `read_only` (Boolean), `text` (`String`) | `on_changed`
|
364
|
+
`figure(x=nil as Numeric, y=nil as Numeric)` | `x` (`Numeric`), `y` (`Numeric`), `closed` (Boolean) | None
|
241
365
|
`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`
|
242
366
|
`form` | `padded` (Boolean) | None
|
243
367
|
`grid` | `padded` (Boolean) | None
|
@@ -249,6 +373,8 @@ Control(Args) | Properties | Listeners
|
|
249
373
|
`image_column(name as String)` | None | None
|
250
374
|
`image_text_column(name as String)` | None | None
|
251
375
|
`label(text as String)` | `text` (`String`) | None
|
376
|
+
`line(x as Numeric, y as Numeric)` | `x` (`Numeric`), `y` (`Numeric`) | None
|
377
|
+
`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
|
252
378
|
`menu(text as String)` | None | None
|
253
379
|
`menu_item(text as String)` | `checked` (Boolean) | `on_clicked`
|
254
380
|
`multiline_entry` | `read_only` (Boolean), `text` (`String`) | `on_changed`
|
@@ -261,9 +387,10 @@ Control(Args) | Properties | Listeners
|
|
261
387
|
`progress_bar_column(name as String)` | None | None
|
262
388
|
`quit_menu_item` | None | `on_clicked`
|
263
389
|
`radio_buttons` | `selected` (`Integer`) | `on_selected`
|
264
|
-
`rectangle(x as Numeric, y as Numeric, width as Numeric, height as Numeric)` |
|
390
|
+
`rectangle(x as Numeric, y as Numeric, width as Numeric, height as Numeric)` | `x` (`Numeric`), `y` (`Numeric`), `width` (`Numeric`), `height` (`Numeric`) | None
|
265
391
|
`slider(min as Numeric, max as Numeric)` | `value` (`Numeric`) | `on_changed`
|
266
392
|
`spinbox(min as Numeric, max as Numeric)` | `value` (`Numeric`) | `on_changed`
|
393
|
+
`square(x as Numeric, y as Numeric, length as Numeric)` | `x` (`Numeric`), `y` (`Numeric`), `length` (`Numeric`) | None
|
267
394
|
`tab` | `margined` (Boolean), `num_pages` (`Integer`) | None
|
268
395
|
`tab_item(name as String)` | `index` [read-only] (`Integer`), `margined` (Boolean), `name` [read-only] (`String`) | None
|
269
396
|
`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
|
@@ -308,6 +435,7 @@ Control(Args) | Properties | Listeners
|
|
308
435
|
- `ControlProxy::image_proxies`: returns all instantiated `image` proxies in the application
|
309
436
|
- `ControlProxy::main_window_proxy`: returns the first window proxy instantiated in the application
|
310
437
|
- `ControlProxy#window_proxy`: returns the window proxy parent for a control
|
438
|
+
- `ControlProxy#content {...}`: re-opens control's content to add more nested controls or properties
|
311
439
|
|
312
440
|
### Table API
|
313
441
|
|
@@ -327,11 +455,85 @@ Note that the `cell_rows` property declaration results in "implicit data-binding
|
|
327
455
|
- Inserting cell rows: Calling `Array#<<`, `Array#push`, `Array#prepend`, or any insertion/addition `Array` method automatically inserts rows in actual `table` control
|
328
456
|
- Changing cell rows: Calling `Array#[]=`, `Array#map!`, or any update `Array` method automatically updates rows in actual `table` control
|
329
457
|
|
458
|
+
Example (you may copy/paste in [`girb`](#girb-glimmer-irb)):
|
459
|
+
|
460
|
+
```ruby
|
461
|
+
require 'glimmer-dsl-libui'
|
462
|
+
|
463
|
+
include Glimmer
|
464
|
+
|
465
|
+
data = [
|
466
|
+
['Lisa Sky', 'lisa@sky.com', '720-523-4329', 'Denver', 'CO', '80014'],
|
467
|
+
['Jordan Biggins', 'jordan@biggins.com', '617-528-5399', 'Boston', 'MA', '02101'],
|
468
|
+
['Mary Glass', 'mary@glass.com', '847-589-8788', 'Elk Grove Village', 'IL', '60007'],
|
469
|
+
['Darren McGrath', 'darren@mcgrath.com', '206-539-9283', 'Seattle', 'WA', '98101'],
|
470
|
+
['Melody Hanheimer', 'melody@hanheimer.com', '213-493-8274', 'Los Angeles', 'CA', '90001'],
|
471
|
+
]
|
472
|
+
|
473
|
+
window('Contacts', 600, 600) { |w|
|
474
|
+
margined true
|
475
|
+
|
476
|
+
vertical_box {
|
477
|
+
form {
|
478
|
+
stretchy false
|
479
|
+
|
480
|
+
@name_entry = entry {
|
481
|
+
label 'Name'
|
482
|
+
}
|
483
|
+
@email_entry = entry {
|
484
|
+
label 'Email'
|
485
|
+
}
|
486
|
+
@phone_entry = entry {
|
487
|
+
label 'Phone'
|
488
|
+
}
|
489
|
+
@city_entry = entry {
|
490
|
+
label 'City'
|
491
|
+
}
|
492
|
+
@state_entry = entry {
|
493
|
+
label 'State'
|
494
|
+
}
|
495
|
+
}
|
496
|
+
|
497
|
+
button('Save Contact') {
|
498
|
+
stretchy false
|
499
|
+
|
500
|
+
on_clicked do
|
501
|
+
new_row = [@name_entry.text, @email_entry.text, @phone_entry.text, @city_entry.text, @state_entry.text]
|
502
|
+
if new_row.include?('')
|
503
|
+
msg_box_error(w, 'Validation Error!', 'All fields are required! Please make sure to enter a value for all fields.')
|
504
|
+
else
|
505
|
+
data << new_row # automatically inserts a row into the table due to implicit data-binding
|
506
|
+
@name_entry.text = ''
|
507
|
+
@email_entry.text = ''
|
508
|
+
@phone_entry.text = ''
|
509
|
+
@city_entry.text = ''
|
510
|
+
@state_entry.text = ''
|
511
|
+
end
|
512
|
+
end
|
513
|
+
}
|
514
|
+
|
515
|
+
table {
|
516
|
+
text_column('Name')
|
517
|
+
text_column('Email')
|
518
|
+
text_column('Phone')
|
519
|
+
text_column('City')
|
520
|
+
text_column('State')
|
521
|
+
|
522
|
+
cell_rows data # implicit data-binding
|
523
|
+
}
|
524
|
+
}
|
525
|
+
}.show
|
526
|
+
```
|
527
|
+
|
528
|
+
![glimmer-dsl-libui-linux-form-table.png](images/glimmer-dsl-libui-linux-form-table.png)
|
529
|
+
|
530
|
+
Learn more by checking out [examples](#examples).
|
531
|
+
|
330
532
|
### Area API
|
331
533
|
|
332
|
-
The `area` control can be used in one of two ways:
|
333
|
-
- 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.
|
334
|
-
- 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
|
534
|
+
The `area` control is a canvas-like control for drawing paths that can be used in one of two ways:
|
535
|
+
- 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).
|
536
|
+
- 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.
|
335
537
|
|
336
538
|
Here is an example of a declarative `area` with a stable path (you may copy/paste in [`girb`](#girb-glimmer-irb)):
|
337
539
|
|
@@ -357,7 +559,7 @@ window('Basic Area', 400, 400) {
|
|
357
559
|
|
358
560
|
![glimmer-dsl-libui-mac-basic-area.png](images/glimmer-dsl-libui-mac-basic-area.png)
|
359
561
|
|
360
|
-
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)):
|
562
|
+
Here is the same example using a semi-declarative `area` with `on_draw` listener that receives a `area_draw_params` argument and a dynamic path (you may copy/paste in [`girb`](#girb-glimmer-irb)):
|
361
563
|
|
362
564
|
```ruby
|
363
565
|
require 'glimmer-dsl-libui'
|
@@ -370,7 +572,7 @@ window('Basic Area', 400, 400) {
|
|
370
572
|
vertical_box {
|
371
573
|
area {
|
372
574
|
on_draw do |area_draw_params|
|
373
|
-
path
|
575
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
374
576
|
rectangle(0, 0, 400, 400)
|
375
577
|
|
376
578
|
fill r: 102, g: 102, b: 204, a: 1.0
|
@@ -383,7 +585,93 @@ window('Basic Area', 400, 400) {
|
|
383
585
|
|
384
586
|
Check [examples/dynamic_area.rb](#dynamic-area) for a more detailed semi-declarative example.
|
385
587
|
|
386
|
-
|
588
|
+
Available nested `path` shapes:
|
589
|
+
- `rectangle(x as Numeric, y as Numeric, width as Numeric, height as Numeric)`
|
590
|
+
- `square(x as Numeric, y as Numeric, length as Numeric)`
|
591
|
+
- `arc(x_center as Numeric, y_center as Numeric, radius as Numeric, start_angle as Numeric, sweep as Numeric, is_negative as Boolean)`
|
592
|
+
- `line(x as Numeric, y as Numeric)`
|
593
|
+
- `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)`
|
594
|
+
- `figure(x=nil as Numeric, y=nil as Numeric)` (composite that can contain other shapes) (can set `closed true` to connect last point to first point automatically)
|
595
|
+
|
596
|
+
Check [examples/area_gallery.rb](#area-gallery) for an overiew of all `path` shapes.
|
597
|
+
|
598
|
+
The `area_draw_params` argument for `on_draw` block is a hash consisting of the following keys:
|
599
|
+
- `:context`: the drawing context object
|
600
|
+
- `:area_width`: area width
|
601
|
+
- `:area_height`: area height
|
602
|
+
- `:clip_x`: clip region top-left x coordinate
|
603
|
+
- `:clip_y`: clip region top-left y coordinate
|
604
|
+
- `:clip_width`: clip region width
|
605
|
+
- `:clip_height`: clip region height
|
606
|
+
|
607
|
+
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 dynamic paths that need maximum performance and low memory footprint.
|
608
|
+
|
609
|
+
To redraw an `area`, you may call the `#queue_redraw_all` method, or simply `#redraw`.
|
610
|
+
|
611
|
+
A transform `matrix` can be set on a path by building a `matrix(m11 = nil, m12 = nil, m21 = nil, m22 = nil, m31 = nil, m32 = nil) {operations}` proxy object and then setting via `transform` property, or alternatively by building and setting the matrix in one call to `transform(m11 = nil, m12 = nil, m21 = nil, m22 = nil, m31 = nil, m32 = nil) {operations}` passing it the matrix arguments and/or content operations.
|
612
|
+
|
613
|
+
When instantiating a `matrix` object, it always starts with identity matrix.
|
614
|
+
|
615
|
+
Here are the following operations that can be performed in a `matrix` body:
|
616
|
+
- `identity` [alias: `set_identity`]: resets matrix to identity matrix
|
617
|
+
- `translate(x as Numeric, y as Numeric)`
|
618
|
+
- `scale(x_center = 0 as Numeric, y_center = 0 as Numeric, x as Numeric, y as Numeric)`
|
619
|
+
- `skew(x = 0 as Numeric, y = 0 as Numeric, x_amount as Numeric, y_amount as Numeric)`
|
620
|
+
- `rotate(x = 0 as Numeric, y = 0 as Numeric, degrees as Numeric)`
|
621
|
+
|
622
|
+
Example of using transform matrix (you may copy/paste in [`girb`](#girb-glimmer-irb)):
|
623
|
+
|
624
|
+
```ruby
|
625
|
+
require 'glimmer-dsl-libui'
|
626
|
+
|
627
|
+
include Glimmer
|
628
|
+
|
629
|
+
window('Basic Transform', 350, 350) {
|
630
|
+
area {
|
631
|
+
path {
|
632
|
+
square(0, 0, 350)
|
633
|
+
|
634
|
+
fill r: 255, g: 255, b: 0
|
635
|
+
}
|
636
|
+
40.times do |n|
|
637
|
+
path {
|
638
|
+
square(0, 0, 100)
|
639
|
+
|
640
|
+
fill r: [255 - n*5, 0].max, g: [n*5, 255].min, b: 0, a: 0.5
|
641
|
+
stroke color: 0, thickness: 2
|
642
|
+
transform {
|
643
|
+
skew 0.15, 0.15
|
644
|
+
translate 50, 50
|
645
|
+
rotate 100, 100, -9 * n
|
646
|
+
scale 1.1, 1.1
|
647
|
+
}
|
648
|
+
}
|
649
|
+
end
|
650
|
+
}
|
651
|
+
}.show
|
652
|
+
```
|
653
|
+
|
654
|
+
Keep in mind that this part could be written differently when there is a need to reuse the matrix:
|
655
|
+
|
656
|
+
```ruby
|
657
|
+
transform {
|
658
|
+
translate 100, 100
|
659
|
+
rotate 100, 100, -9 * n
|
660
|
+
}
|
661
|
+
```
|
662
|
+
|
663
|
+
Alternatively:
|
664
|
+
|
665
|
+
```ruby
|
666
|
+
m1 = matrix {
|
667
|
+
translate 100, 100
|
668
|
+
rotate 100, 100, -9 * n
|
669
|
+
}
|
670
|
+
transform m1
|
671
|
+
# and then reuse m1 elsewhere too
|
672
|
+
```
|
673
|
+
|
674
|
+
Note that `area`, `path`, and nested shapes are all truly declarative, meaning they do not care about the ordering of calls to `fill`, `stroke`, and `transform`. Furthermore, any transform that is applied is reversed at the end of the block, so you never have to worry about the ordering of `transform` calls among different paths. You simply set a transform on the `path`s that need it and it is guaranteed to be called before all its content is drawn, and then undone afterwards to avoid affecting later paths. Matrix `transform` can be set on an entire `area` too, applying to all nested `path`s.
|
387
675
|
|
388
676
|
### Smart Defaults and Conventions
|
389
677
|
|
@@ -414,11 +702,16 @@ To redraw an `area`, you may call `#queue_redraw_all` method.
|
|
414
702
|
- `image` instances are automatically freed from memory after `window` is destroyed.
|
415
703
|
- `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`
|
416
704
|
- `area` paths are specified declaratively with figures underneath (e.g. `rectangle`) and `area` draw listener is automatically generated
|
705
|
+
- Observe figure properties (e.g. `rectangle` `width`) for changes and automatically redraw containing area accordingly
|
706
|
+
- Observe `path` `fill` and `stroke` hashes for changes and automatically redraw containing area accordingly
|
707
|
+
- All controls are protected from garbage collection until no longer needed (explicitly destroyed), so there is no need to worry about surprises.
|
708
|
+
- All resources are freed automatically once no longer needed or left to garbage collection.
|
417
709
|
|
418
710
|
### API Gotchas
|
419
711
|
|
420
712
|
- 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`).
|
421
713
|
- `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).
|
714
|
+
- It seems that `arc` `start_angle` and `sweep` properties are ignored by [libui](https://github.com/andlabs/libui) and always set to `0` and `360` respectively, producing a full circle.
|
422
715
|
|
423
716
|
### Original API
|
424
717
|
|
@@ -434,21 +727,9 @@ check out the [libui C headers](https://github.com/andlabs/libui/blob/master/ui.
|
|
434
727
|
- 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.
|
435
728
|
- 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.
|
436
729
|
|
437
|
-
## Girb (Glimmer IRB)
|
438
|
-
|
439
|
-
You can run the `girb` command (`bin/girb` if you cloned the project locally):
|
440
|
-
|
441
|
-
```
|
442
|
-
girb
|
443
|
-
```
|
444
|
-
|
445
|
-
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.
|
446
|
-
|
447
|
-
Gotcha: On the Mac, when you close a window opened in `girb`, it remains open until you enter `exit` or open another GUI window.
|
448
|
-
|
449
730
|
## Examples
|
450
731
|
|
451
|
-
|
732
|
+
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.
|
452
733
|
|
453
734
|
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.
|
454
735
|
|
@@ -608,7 +889,7 @@ window('hello world', 300, 200, true) {
|
|
608
889
|
}.show
|
609
890
|
```
|
610
891
|
|
611
|
-
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2:
|
892
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (setting `window` properties instead of arguments):
|
612
893
|
|
613
894
|
```ruby
|
614
895
|
require 'glimmer-dsl-libui'
|
@@ -2538,13 +2819,23 @@ data = [
|
|
2538
2819
|
['task 5', -1],
|
2539
2820
|
]
|
2540
2821
|
|
2541
|
-
window('Task
|
2542
|
-
|
2822
|
+
window('Task Progress', 300, 200) {
|
2823
|
+
vertical_box {
|
2543
2824
|
table {
|
2544
2825
|
text_column('Task')
|
2545
2826
|
progress_bar_column('Progress')
|
2546
2827
|
|
2547
|
-
cell_rows data
|
2828
|
+
cell_rows data # implicit data-binding
|
2829
|
+
}
|
2830
|
+
|
2831
|
+
button('Mark All As Done') {
|
2832
|
+
stretchy false
|
2833
|
+
|
2834
|
+
on_clicked do
|
2835
|
+
data.each_with_index do |row_data, row|
|
2836
|
+
data[row] = [row_data[0], 100] # automatically updates table due to implicit data-binding
|
2837
|
+
end
|
2838
|
+
end
|
2548
2839
|
}
|
2549
2840
|
}
|
2550
2841
|
}.show
|
@@ -2744,6 +3035,30 @@ window('Basic Area', 400, 400) {
|
|
2744
3035
|
}.show
|
2745
3036
|
```
|
2746
3037
|
|
3038
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (semi-declarative `on_draw` dynamic `path` approach):
|
3039
|
+
|
3040
|
+
```ruby
|
3041
|
+
require 'glimmer-dsl-libui'
|
3042
|
+
|
3043
|
+
include Glimmer
|
3044
|
+
|
3045
|
+
window('Basic Area', 400, 400) {
|
3046
|
+
margined true
|
3047
|
+
|
3048
|
+
vertical_box {
|
3049
|
+
area {
|
3050
|
+
on_draw do |area_draw_params|
|
3051
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3052
|
+
rectangle(0, 0, 400, 400)
|
3053
|
+
|
3054
|
+
fill r: 102, g: 102, b: 204, a: 1.0
|
3055
|
+
}
|
3056
|
+
end
|
3057
|
+
}
|
3058
|
+
}
|
3059
|
+
}.show
|
3060
|
+
```
|
3061
|
+
|
2747
3062
|
### Dynamic Area
|
2748
3063
|
|
2749
3064
|
[examples/dynamic_area.rb](examples/dynamic_area.rb)
|
@@ -2863,7 +3178,7 @@ window('Dynamic Area', 240, 500) {
|
|
2863
3178
|
|
2864
3179
|
@area = area {
|
2865
3180
|
on_draw do |area_draw_params|
|
2866
|
-
path
|
3181
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
2867
3182
|
rectangle(@x_spinbox.value, @y_spinbox.value, @width_spinbox.value, @height_spinbox.value)
|
2868
3183
|
|
2869
3184
|
fill r: @red_spinbox.value, g: @green_spinbox.value, b: @blue_spinbox.value, a: @alpha_spinbox.value / 100.0
|
@@ -2874,6 +3189,876 @@ window('Dynamic Area', 240, 500) {
|
|
2874
3189
|
}.show
|
2875
3190
|
```
|
2876
3191
|
|
3192
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (declarative stable `path` approach):
|
3193
|
+
|
3194
|
+
```ruby
|
3195
|
+
require 'glimmer-dsl-libui'
|
3196
|
+
|
3197
|
+
include Glimmer
|
3198
|
+
|
3199
|
+
window('Dynamic Area', 240, 600) {
|
3200
|
+
margined true
|
3201
|
+
|
3202
|
+
vertical_box {
|
3203
|
+
label('Rectangle Properties') {
|
3204
|
+
stretchy false
|
3205
|
+
}
|
3206
|
+
|
3207
|
+
form {
|
3208
|
+
stretchy false
|
3209
|
+
|
3210
|
+
@x_spinbox = spinbox(0, 1000) {
|
3211
|
+
label 'x'
|
3212
|
+
value 25
|
3213
|
+
|
3214
|
+
on_changed do
|
3215
|
+
@rectangle.x = @x_spinbox.value # updating properties automatically triggers area.queue_redraw_all
|
3216
|
+
end
|
3217
|
+
}
|
3218
|
+
|
3219
|
+
@y_spinbox = spinbox(0, 1000) {
|
3220
|
+
label 'y'
|
3221
|
+
value 25
|
3222
|
+
|
3223
|
+
on_changed do
|
3224
|
+
@rectangle.y = @y_spinbox.value # updating properties automatically triggers area.queue_redraw_all
|
3225
|
+
end
|
3226
|
+
}
|
3227
|
+
|
3228
|
+
@width_spinbox = spinbox(0, 1000) {
|
3229
|
+
label 'width'
|
3230
|
+
value 150
|
3231
|
+
|
3232
|
+
on_changed do
|
3233
|
+
@rectangle.width = @width_spinbox.value # updating properties automatically triggers area.queue_redraw_all
|
3234
|
+
end
|
3235
|
+
}
|
3236
|
+
|
3237
|
+
@height_spinbox = spinbox(0, 1000) {
|
3238
|
+
label 'height'
|
3239
|
+
value 150
|
3240
|
+
|
3241
|
+
on_changed do
|
3242
|
+
@rectangle.height = @height_spinbox.value # updating properties automatically triggers area.queue_redraw_all
|
3243
|
+
end
|
3244
|
+
}
|
3245
|
+
|
3246
|
+
@red_spinbox = spinbox(0, 255) {
|
3247
|
+
label 'red'
|
3248
|
+
value 102
|
3249
|
+
|
3250
|
+
on_changed do
|
3251
|
+
@path.fill[:r] = @red_spinbox.value # updating hash properties automatically triggers area.queue_redraw_all
|
3252
|
+
end
|
3253
|
+
}
|
3254
|
+
|
3255
|
+
@green_spinbox = spinbox(0, 255) {
|
3256
|
+
label 'green'
|
3257
|
+
value 102
|
3258
|
+
|
3259
|
+
on_changed do
|
3260
|
+
@path.fill[:g] = @green_spinbox.value # updating hash properties automatically triggers area.queue_redraw_all
|
3261
|
+
end
|
3262
|
+
}
|
3263
|
+
|
3264
|
+
@blue_spinbox = spinbox(0, 255) {
|
3265
|
+
label 'blue'
|
3266
|
+
value 204
|
3267
|
+
|
3268
|
+
on_changed do
|
3269
|
+
@path.fill[:b] = @blue_spinbox.value # updating hash properties automatically triggers area.queue_redraw_all
|
3270
|
+
end
|
3271
|
+
}
|
3272
|
+
|
3273
|
+
@alpha_spinbox = spinbox(0, 100) {
|
3274
|
+
label 'alpha'
|
3275
|
+
value 100
|
3276
|
+
|
3277
|
+
on_changed do
|
3278
|
+
@path.fill[:a] = @alpha_spinbox.value / 100.0 # updating hash properties automatically triggers area.queue_redraw_all
|
3279
|
+
end
|
3280
|
+
}
|
3281
|
+
}
|
3282
|
+
|
3283
|
+
area {
|
3284
|
+
@path = path { # stable path
|
3285
|
+
@rectangle = rectangle(@x_spinbox.value, @y_spinbox.value, @width_spinbox.value, @height_spinbox.value)
|
3286
|
+
|
3287
|
+
fill r: @red_spinbox.value, g: @green_spinbox.value, b: @blue_spinbox.value, a: @alpha_spinbox.value / 100.0
|
3288
|
+
}
|
3289
|
+
}
|
3290
|
+
}
|
3291
|
+
}.show
|
3292
|
+
```
|
3293
|
+
|
3294
|
+
### Area Gallery
|
3295
|
+
|
3296
|
+
[examples/area_gallery.rb](examples/area_gallery.rb)
|
3297
|
+
|
3298
|
+
Run with this command from the root of the project if you cloned the project:
|
3299
|
+
|
3300
|
+
```
|
3301
|
+
ruby -r './lib/glimmer-dsl-libui' examples/area_gallery.rb
|
3302
|
+
```
|
3303
|
+
|
3304
|
+
Run with this command if you installed the [Ruby gem](https://rubygems.org/gems/glimmer-dsl-libui):
|
3305
|
+
|
3306
|
+
```
|
3307
|
+
ruby -r glimmer-dsl-libui -e "require 'examples/area_gallery'"
|
3308
|
+
```
|
3309
|
+
|
3310
|
+
Mac
|
3311
|
+
|
3312
|
+
![glimmer-dsl-libui-mac-area-gallery.png](images/glimmer-dsl-libui-mac-area-gallery.png)
|
3313
|
+
|
3314
|
+
Linux
|
3315
|
+
|
3316
|
+
![glimmer-dsl-libui-linux-area-gallery.png](images/glimmer-dsl-libui-linux-area-gallery.png)
|
3317
|
+
|
3318
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
3319
|
+
|
3320
|
+
```ruby
|
3321
|
+
require 'glimmer-dsl-libui'
|
3322
|
+
|
3323
|
+
include Glimmer
|
3324
|
+
|
3325
|
+
window('Area Gallery', 400, 400) {
|
3326
|
+
area {
|
3327
|
+
path { # declarative stable path
|
3328
|
+
square(0, 0, 100)
|
3329
|
+
square(100, 100, 400)
|
3330
|
+
|
3331
|
+
fill r: 102, g: 102, b: 204
|
3332
|
+
}
|
3333
|
+
path { # declarative stable path
|
3334
|
+
rectangle(0, 100, 100, 400)
|
3335
|
+
rectangle(100, 0, 400, 100)
|
3336
|
+
|
3337
|
+
fill r: 204, g: 102, b: 204
|
3338
|
+
}
|
3339
|
+
path { # declarative stable path
|
3340
|
+
figure(100, 100) {
|
3341
|
+
line(100, 400)
|
3342
|
+
line(400, 100)
|
3343
|
+
line(400, 400)
|
3344
|
+
|
3345
|
+
closed true
|
3346
|
+
}
|
3347
|
+
|
3348
|
+
fill r: 202, g: 102, b: 104, a: 0.5
|
3349
|
+
stroke r: 0, g: 0, b: 0
|
3350
|
+
}
|
3351
|
+
path { # declarative stable path
|
3352
|
+
figure(0, 0) {
|
3353
|
+
bezier(200, 100, 100, 200, 400, 100)
|
3354
|
+
bezier(300, 100, 100, 300, 100, 400)
|
3355
|
+
bezier(100, 300, 300, 100, 400, 400)
|
3356
|
+
|
3357
|
+
closed true
|
3358
|
+
}
|
3359
|
+
|
3360
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
3361
|
+
stroke thickness: 2, r: 0, g: 0, b: 0
|
3362
|
+
}
|
3363
|
+
path { # declarative stable path
|
3364
|
+
arc(200, 200, 90, 0, 360, false)
|
3365
|
+
|
3366
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
3367
|
+
stroke thickness: 2, r: 0, g: 0, b: 0
|
3368
|
+
}
|
3369
|
+
}
|
3370
|
+
}.show
|
3371
|
+
```
|
3372
|
+
|
3373
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (setting shape properties instead of arguments):
|
3374
|
+
|
3375
|
+
```ruby
|
3376
|
+
require 'glimmer-dsl-libui'
|
3377
|
+
|
3378
|
+
include Glimmer
|
3379
|
+
|
3380
|
+
window('Area Gallery', 400, 400) {
|
3381
|
+
area {
|
3382
|
+
path { # declarative stable path
|
3383
|
+
square {
|
3384
|
+
x 0
|
3385
|
+
y 0
|
3386
|
+
length 100
|
3387
|
+
}
|
3388
|
+
square {
|
3389
|
+
x 100
|
3390
|
+
y 100
|
3391
|
+
length 400
|
3392
|
+
}
|
3393
|
+
|
3394
|
+
fill r: 102, g: 102, b: 204
|
3395
|
+
}
|
3396
|
+
path { # declarative stable path
|
3397
|
+
rectangle {
|
3398
|
+
x 0
|
3399
|
+
y 100
|
3400
|
+
width 100
|
3401
|
+
height 400
|
3402
|
+
}
|
3403
|
+
rectangle {
|
3404
|
+
x 100
|
3405
|
+
y 0
|
3406
|
+
width 400
|
3407
|
+
height 100
|
3408
|
+
}
|
3409
|
+
|
3410
|
+
fill r: 204, g: 102, b: 204
|
3411
|
+
}
|
3412
|
+
path { # declarative stable path
|
3413
|
+
figure {
|
3414
|
+
x 100
|
3415
|
+
y 100
|
3416
|
+
|
3417
|
+
line {
|
3418
|
+
x 100
|
3419
|
+
y 400
|
3420
|
+
}
|
3421
|
+
line {
|
3422
|
+
x 400
|
3423
|
+
y 100
|
3424
|
+
}
|
3425
|
+
line {
|
3426
|
+
x 400
|
3427
|
+
y 400
|
3428
|
+
}
|
3429
|
+
|
3430
|
+
closed true
|
3431
|
+
}
|
3432
|
+
|
3433
|
+
fill r: 202, g: 102, b: 104, a: 0.5
|
3434
|
+
stroke r: 0, g: 0, b: 0
|
3435
|
+
}
|
3436
|
+
path { # declarative stable path
|
3437
|
+
figure {
|
3438
|
+
x 0
|
3439
|
+
y 0
|
3440
|
+
|
3441
|
+
bezier {
|
3442
|
+
c1_x 200
|
3443
|
+
c1_y 100
|
3444
|
+
c2_x 100
|
3445
|
+
c2_y 200
|
3446
|
+
end_x 400
|
3447
|
+
end_y 100
|
3448
|
+
}
|
3449
|
+
bezier {
|
3450
|
+
c1_x 300
|
3451
|
+
c1_y 100
|
3452
|
+
c2_x 100
|
3453
|
+
c2_y 300
|
3454
|
+
end_x 100
|
3455
|
+
end_y 400
|
3456
|
+
}
|
3457
|
+
bezier {
|
3458
|
+
c1_x 100
|
3459
|
+
c1_y 300
|
3460
|
+
c2_x 300
|
3461
|
+
c2_y 100
|
3462
|
+
end_x 400
|
3463
|
+
end_y 400
|
3464
|
+
}
|
3465
|
+
|
3466
|
+
closed true
|
3467
|
+
}
|
3468
|
+
|
3469
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
3470
|
+
stroke thickness: 2, r: 0, g: 0, b: 0
|
3471
|
+
}
|
3472
|
+
path { # declarative stable path
|
3473
|
+
arc {
|
3474
|
+
x_center 200
|
3475
|
+
y_center 200
|
3476
|
+
radius 90
|
3477
|
+
start_angle 0
|
3478
|
+
sweep 360
|
3479
|
+
is_negative false
|
3480
|
+
}
|
3481
|
+
|
3482
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
3483
|
+
stroke thickness: 2, r: 0, g: 0, b: 0
|
3484
|
+
}
|
3485
|
+
}
|
3486
|
+
}.show
|
3487
|
+
```
|
3488
|
+
|
3489
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 3 (semi-declarative `on_draw` dynamic `path` approach):
|
3490
|
+
|
3491
|
+
```ruby
|
3492
|
+
require 'glimmer-dsl-libui'
|
3493
|
+
|
3494
|
+
include Glimmer
|
3495
|
+
|
3496
|
+
window('Area Gallery', 400, 400) {
|
3497
|
+
area {
|
3498
|
+
on_draw do |area_draw_params|
|
3499
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3500
|
+
square(0, 0, 100)
|
3501
|
+
square(100, 100, 400)
|
3502
|
+
|
3503
|
+
fill r: 102, g: 102, b: 204
|
3504
|
+
}
|
3505
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3506
|
+
rectangle(0, 100, 100, 400)
|
3507
|
+
rectangle(100, 0, 400, 100)
|
3508
|
+
|
3509
|
+
fill r: 204, g: 102, b: 204
|
3510
|
+
}
|
3511
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3512
|
+
figure(100, 100) {
|
3513
|
+
line(100, 400)
|
3514
|
+
line(400, 100)
|
3515
|
+
line(400, 400)
|
3516
|
+
|
3517
|
+
closed true
|
3518
|
+
}
|
3519
|
+
|
3520
|
+
fill r: 202, g: 102, b: 104, a: 0.5
|
3521
|
+
stroke r: 0, g: 0, b: 0
|
3522
|
+
}
|
3523
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3524
|
+
figure(0, 0) {
|
3525
|
+
bezier(200, 100, 100, 200, 400, 100)
|
3526
|
+
bezier(300, 100, 100, 300, 100, 400)
|
3527
|
+
bezier(100, 300, 300, 100, 400, 400)
|
3528
|
+
|
3529
|
+
closed true
|
3530
|
+
}
|
3531
|
+
|
3532
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
3533
|
+
stroke thickness: 2, r: 0, g: 0, b: 0
|
3534
|
+
}
|
3535
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3536
|
+
arc(200, 200, 90, 0, 360, false)
|
3537
|
+
|
3538
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
3539
|
+
stroke thickness: 2, r: 0, g: 0, b: 0
|
3540
|
+
}
|
3541
|
+
end
|
3542
|
+
}
|
3543
|
+
}.show
|
3544
|
+
```
|
3545
|
+
|
3546
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 4 (setting shape properties instead of arguments with semi-declarative `on_draw` dynamic `path` approach):
|
3547
|
+
|
3548
|
+
```ruby
|
3549
|
+
require 'glimmer-dsl-libui'
|
3550
|
+
|
3551
|
+
include Glimmer
|
3552
|
+
|
3553
|
+
window('Area Gallery', 400, 400) {
|
3554
|
+
area {
|
3555
|
+
on_draw do |area_draw_params|
|
3556
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3557
|
+
square {
|
3558
|
+
x 0
|
3559
|
+
y 0
|
3560
|
+
length 100
|
3561
|
+
}
|
3562
|
+
square {
|
3563
|
+
x 100
|
3564
|
+
y 100
|
3565
|
+
length 400
|
3566
|
+
}
|
3567
|
+
|
3568
|
+
fill r: 102, g: 102, b: 204
|
3569
|
+
}
|
3570
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3571
|
+
rectangle {
|
3572
|
+
x 0
|
3573
|
+
y 100
|
3574
|
+
width 100
|
3575
|
+
height 400
|
3576
|
+
}
|
3577
|
+
rectangle {
|
3578
|
+
x 100
|
3579
|
+
y 0
|
3580
|
+
width 400
|
3581
|
+
height 100
|
3582
|
+
}
|
3583
|
+
|
3584
|
+
fill r: 204, g: 102, b: 204
|
3585
|
+
}
|
3586
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3587
|
+
figure {
|
3588
|
+
x 100
|
3589
|
+
y 100
|
3590
|
+
|
3591
|
+
line {
|
3592
|
+
x 100
|
3593
|
+
y 400
|
3594
|
+
}
|
3595
|
+
line {
|
3596
|
+
x 400
|
3597
|
+
y 100
|
3598
|
+
}
|
3599
|
+
line {
|
3600
|
+
x 400
|
3601
|
+
y 400
|
3602
|
+
}
|
3603
|
+
|
3604
|
+
closed true
|
3605
|
+
}
|
3606
|
+
|
3607
|
+
fill r: 202, g: 102, b: 104, a: 0.5
|
3608
|
+
stroke r: 0, g: 0, b: 0
|
3609
|
+
}
|
3610
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3611
|
+
figure {
|
3612
|
+
x 0
|
3613
|
+
y 0
|
3614
|
+
|
3615
|
+
bezier {
|
3616
|
+
c1_x 200
|
3617
|
+
c1_y 100
|
3618
|
+
c2_x 100
|
3619
|
+
c2_y 200
|
3620
|
+
end_x 400
|
3621
|
+
end_y 100
|
3622
|
+
}
|
3623
|
+
bezier {
|
3624
|
+
c1_x 300
|
3625
|
+
c1_y 100
|
3626
|
+
c2_x 100
|
3627
|
+
c2_y 300
|
3628
|
+
end_x 100
|
3629
|
+
end_y 400
|
3630
|
+
}
|
3631
|
+
bezier {
|
3632
|
+
c1_x 100
|
3633
|
+
c1_y 300
|
3634
|
+
c2_x 300
|
3635
|
+
c2_y 100
|
3636
|
+
end_x 400
|
3637
|
+
end_y 400
|
3638
|
+
}
|
3639
|
+
|
3640
|
+
closed true
|
3641
|
+
}
|
3642
|
+
|
3643
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
3644
|
+
stroke thickness: 2, r: 0, g: 0, b: 0
|
3645
|
+
}
|
3646
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3647
|
+
arc {
|
3648
|
+
x_center 200
|
3649
|
+
y_center 200
|
3650
|
+
radius 90
|
3651
|
+
start_angle 0
|
3652
|
+
sweep 360
|
3653
|
+
is_negative false
|
3654
|
+
}
|
3655
|
+
|
3656
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
3657
|
+
stroke thickness: 2, r: 0, g: 0, b: 0
|
3658
|
+
}
|
3659
|
+
end
|
3660
|
+
}
|
3661
|
+
}.show
|
3662
|
+
```
|
3663
|
+
|
3664
|
+
### Histogram
|
3665
|
+
|
3666
|
+
[examples/histogram.rb](examples/histogram.rb)
|
3667
|
+
|
3668
|
+
Run with this command from the root of the project if you cloned the project:
|
3669
|
+
|
3670
|
+
```
|
3671
|
+
ruby -r './lib/glimmer-dsl-libui' examples/histogram.rb
|
3672
|
+
```
|
3673
|
+
|
3674
|
+
Run with this command if you installed the [Ruby gem](https://rubygems.org/gems/glimmer-dsl-libui):
|
3675
|
+
|
3676
|
+
```
|
3677
|
+
ruby -r glimmer-dsl-libui -e "require 'examples/histogram'"
|
3678
|
+
```
|
3679
|
+
|
3680
|
+
Mac
|
3681
|
+
|
3682
|
+
![glimmer-dsl-libui-mac-histogram.png](images/glimmer-dsl-libui-mac-histogram.png)
|
3683
|
+
|
3684
|
+
Linux
|
3685
|
+
|
3686
|
+
![glimmer-dsl-libui-linux-histogram.png](images/glimmer-dsl-libui-linux-histogram.png)
|
3687
|
+
|
3688
|
+
[LibUI](https://github.com/kojix2/LibUI) Original Version:
|
3689
|
+
|
3690
|
+
```ruby
|
3691
|
+
# https://github.com/jamescook/libui-ruby/blob/master/example/histogram.rb
|
3692
|
+
|
3693
|
+
require 'libui'
|
3694
|
+
|
3695
|
+
UI = LibUI
|
3696
|
+
|
3697
|
+
X_OFF_LEFT = 20
|
3698
|
+
Y_OFF_TOP = 20
|
3699
|
+
X_OFF_RIGHT = 20
|
3700
|
+
Y_OFF_BOTTOM = 20
|
3701
|
+
POINT_RADIUS = 5
|
3702
|
+
|
3703
|
+
init = UI.init
|
3704
|
+
handler = UI::FFI::AreaHandler.malloc
|
3705
|
+
histogram = UI.new_area(handler)
|
3706
|
+
brush = UI::FFI::DrawBrush.malloc
|
3707
|
+
color_button = UI.new_color_button
|
3708
|
+
blue = 0x1E90FF
|
3709
|
+
datapoints = []
|
3710
|
+
|
3711
|
+
def graph_size(area_width, area_height)
|
3712
|
+
graph_width = area_width - X_OFF_LEFT - X_OFF_RIGHT
|
3713
|
+
graph_height = area_height - Y_OFF_TOP - Y_OFF_BOTTOM
|
3714
|
+
[graph_width, graph_height]
|
3715
|
+
end
|
3716
|
+
|
3717
|
+
matrix = UI::FFI::DrawMatrix.malloc
|
3718
|
+
|
3719
|
+
def point_locations(datapoints, width, height)
|
3720
|
+
xincr = width / 9.0 # 10 - 1 to make the last point be at the end
|
3721
|
+
yincr = height / 100.0
|
3722
|
+
|
3723
|
+
data = []
|
3724
|
+
datapoints.each_with_index do |dp, i|
|
3725
|
+
val = 100 - UI.spinbox_value(dp)
|
3726
|
+
data << [xincr * i, yincr * val]
|
3727
|
+
i += 1
|
3728
|
+
end
|
3729
|
+
|
3730
|
+
data
|
3731
|
+
end
|
3732
|
+
|
3733
|
+
def construct_graph(datapoints, width, height, should_extend)
|
3734
|
+
locations = point_locations(datapoints, width, height)
|
3735
|
+
path = UI.draw_new_path(0) # winding
|
3736
|
+
first_location = locations[0] # x and y
|
3737
|
+
UI.draw_path_new_figure(path, first_location[0], first_location[1])
|
3738
|
+
locations.each do |loc|
|
3739
|
+
UI.draw_path_line_to(path, loc[0], loc[1])
|
3740
|
+
end
|
3741
|
+
|
3742
|
+
if should_extend
|
3743
|
+
UI.draw_path_line_to(path, width, height)
|
3744
|
+
UI.draw_path_line_to(path, 0, height)
|
3745
|
+
UI.draw_path_close_figure(path)
|
3746
|
+
end
|
3747
|
+
|
3748
|
+
UI.draw_path_end(path)
|
3749
|
+
|
3750
|
+
path
|
3751
|
+
end
|
3752
|
+
|
3753
|
+
handler_draw_event = Fiddle::Closure::BlockCaller.new(
|
3754
|
+
0, [1, 1, 1]
|
3755
|
+
) do |_area_handler, _area, area_draw_params|
|
3756
|
+
area_draw_params = UI::FFI::AreaDrawParams.new(area_draw_params)
|
3757
|
+
path = UI.draw_new_path(0) # winding
|
3758
|
+
UI.draw_path_add_rectangle(path, 0, 0, area_draw_params.AreaWidth, area_draw_params.AreaHeight)
|
3759
|
+
UI.draw_path_end(path)
|
3760
|
+
set_solid_brush(brush, 0xFFFFFF, 1.0) # white
|
3761
|
+
UI.draw_fill(area_draw_params.Context, path, brush.to_ptr)
|
3762
|
+
UI.draw_free_path(path)
|
3763
|
+
dsp = UI::FFI::DrawStrokeParams.malloc
|
3764
|
+
dsp.Cap = 0 # flat
|
3765
|
+
dsp.Join = 0 # miter
|
3766
|
+
dsp.Thickness = 2
|
3767
|
+
dsp.MiterLimit = 10 # DEFAULT_MITER_LIMIT
|
3768
|
+
dashes = Fiddle::Pointer.malloc(8)
|
3769
|
+
dsp.Dashes = dashes
|
3770
|
+
dsp.NumDashes = 0
|
3771
|
+
dsp.DashPhase = 0
|
3772
|
+
|
3773
|
+
# draw axes
|
3774
|
+
set_solid_brush(brush, 0x000000, 1.0) # black
|
3775
|
+
graph_width, graph_height = *graph_size(area_draw_params.AreaWidth, area_draw_params.AreaHeight)
|
3776
|
+
|
3777
|
+
path = UI.draw_new_path(0) # winding
|
3778
|
+
UI.draw_path_new_figure(path, X_OFF_LEFT, Y_OFF_TOP)
|
3779
|
+
UI.draw_path_line_to(path, X_OFF_LEFT, Y_OFF_TOP + graph_height)
|
3780
|
+
UI.draw_path_line_to(path, X_OFF_LEFT + graph_width, Y_OFF_TOP + graph_height)
|
3781
|
+
UI.draw_path_end(path)
|
3782
|
+
UI.draw_stroke(area_draw_params.Context, path, brush, dsp)
|
3783
|
+
UI.draw_free_path(path)
|
3784
|
+
|
3785
|
+
# now transform the coordinate space so (0, 0) is the top-left corner of the graph
|
3786
|
+
UI.draw_matrix_set_identity(matrix)
|
3787
|
+
UI.draw_matrix_translate(matrix, X_OFF_LEFT, Y_OFF_TOP)
|
3788
|
+
UI.draw_transform(area_draw_params.Context, matrix)
|
3789
|
+
|
3790
|
+
# now get the color for the graph itself and set up the brush
|
3791
|
+
# uiColorButtonColor(colorButton, &graphR, &graphG, &graphB, &graphA)
|
3792
|
+
graph_r = Fiddle::Pointer.malloc(8) # double
|
3793
|
+
graph_g = Fiddle::Pointer.malloc(8) # double
|
3794
|
+
graph_b = Fiddle::Pointer.malloc(8) # double
|
3795
|
+
graph_a = Fiddle::Pointer.malloc(8) # double
|
3796
|
+
|
3797
|
+
UI.color_button_color(color_button, graph_r, graph_g, graph_b, graph_a)
|
3798
|
+
brush.Type = 0 # solid
|
3799
|
+
brush.R = graph_r[0, 8].unpack1('d')
|
3800
|
+
brush.G = graph_g[0, 8].unpack1('d')
|
3801
|
+
brush.B = graph_b[0, 8].unpack1('d')
|
3802
|
+
|
3803
|
+
# now create the fill for the graph below the graph line
|
3804
|
+
path = construct_graph(datapoints, graph_width, graph_height, true)
|
3805
|
+
brush.A = graph_a[0, 8].unpack1('d') / 2.0
|
3806
|
+
UI.draw_fill(area_draw_params.Context, path, brush)
|
3807
|
+
UI.draw_free_path(path)
|
3808
|
+
|
3809
|
+
# now draw the histogram line
|
3810
|
+
path = construct_graph(datapoints, graph_width, graph_height, false)
|
3811
|
+
brush.A = graph_a[0, 8].unpack1('d')
|
3812
|
+
UI.draw_stroke(area_draw_params.Context, path, brush, dsp)
|
3813
|
+
UI.draw_free_path(path)
|
3814
|
+
end
|
3815
|
+
|
3816
|
+
handler.Draw = handler_draw_event
|
3817
|
+
|
3818
|
+
# Assigning to local variables
|
3819
|
+
# This is intended to protect Fiddle::Closure from garbage collection.
|
3820
|
+
# See https://github.com/kojix2/LibUI/issues/8
|
3821
|
+
handler.MouseEvent = (c1 = Fiddle::Closure::BlockCaller.new(0, [0]) {})
|
3822
|
+
handler.MouseCrossed = (c2 = Fiddle::Closure::BlockCaller.new(0, [0]) {})
|
3823
|
+
handler.DragBroken = (c3 = Fiddle::Closure::BlockCaller.new(0, [0]) {})
|
3824
|
+
handler.KeyEvent = (c4 = Fiddle::Closure::BlockCaller.new(1, [0]) { 0 })
|
3825
|
+
|
3826
|
+
UI.freeInitError(init) unless init.nil?
|
3827
|
+
|
3828
|
+
hbox = UI.new_horizontal_box
|
3829
|
+
UI.box_set_padded(hbox, 1)
|
3830
|
+
|
3831
|
+
vbox = UI.new_vertical_box
|
3832
|
+
UI.box_set_padded(vbox, 1)
|
3833
|
+
UI.box_append(hbox, vbox, 0)
|
3834
|
+
UI.box_append(hbox, histogram, 1)
|
3835
|
+
|
3836
|
+
datapoints = Array.new(10) do
|
3837
|
+
UI.new_spinbox(0, 100).tap do |datapoint|
|
3838
|
+
UI.spinbox_set_value(datapoint, Random.new.rand(90))
|
3839
|
+
UI.spinbox_on_changed(datapoint) do
|
3840
|
+
UI.area_queue_redraw_all(histogram)
|
3841
|
+
end
|
3842
|
+
UI.box_append(vbox, datapoint, 0)
|
3843
|
+
end
|
3844
|
+
end
|
3845
|
+
|
3846
|
+
def set_solid_brush(brush, color, alpha)
|
3847
|
+
brush.Type = 0 # solid
|
3848
|
+
brush.R = ((color >> 16) & 0xFF) / 255.0
|
3849
|
+
brush.G = ((color >> 8) & 0xFF) / 255.0
|
3850
|
+
brush.B = (color & 0xFF) / 255.0
|
3851
|
+
brush.A = alpha
|
3852
|
+
brush
|
3853
|
+
end
|
3854
|
+
|
3855
|
+
set_solid_brush(brush, blue, 1.0)
|
3856
|
+
UI.color_button_set_color(color_button, brush.R, brush.G, brush.B, brush.A)
|
3857
|
+
|
3858
|
+
UI.color_button_on_changed(color_button) do
|
3859
|
+
UI.area_queue_redraw_all(histogram)
|
3860
|
+
end
|
3861
|
+
|
3862
|
+
UI.box_append(vbox, color_button, 0)
|
3863
|
+
|
3864
|
+
MAIN_WINDOW = UI.new_window('histogram example', 640, 480, 1)
|
3865
|
+
UI.window_set_margined(MAIN_WINDOW, 1)
|
3866
|
+
UI.window_set_child(MAIN_WINDOW, hbox)
|
3867
|
+
|
3868
|
+
should_quit = proc do |_ptr|
|
3869
|
+
UI.control_destroy(MAIN_WINDOW)
|
3870
|
+
UI.quit
|
3871
|
+
0
|
3872
|
+
end
|
3873
|
+
|
3874
|
+
UI.window_on_closing(MAIN_WINDOW, should_quit)
|
3875
|
+
UI.on_should_quit(should_quit)
|
3876
|
+
UI.control_show(MAIN_WINDOW)
|
3877
|
+
|
3878
|
+
UI.main
|
3879
|
+
UI.quit
|
3880
|
+
```
|
3881
|
+
|
3882
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
3883
|
+
|
3884
|
+
```ruby
|
3885
|
+
# https://github.com/jamescook/libui-ruby/blob/master/example/histogram.rb
|
3886
|
+
|
3887
|
+
require 'glimmer-dsl-libui'
|
3888
|
+
|
3889
|
+
include Glimmer
|
3890
|
+
|
3891
|
+
X_OFF_LEFT = 20
|
3892
|
+
Y_OFF_TOP = 20
|
3893
|
+
X_OFF_RIGHT = 20
|
3894
|
+
Y_OFF_BOTTOM = 20
|
3895
|
+
POINT_RADIUS = 5
|
3896
|
+
|
3897
|
+
COLOR_BLUE = 0x1E90FF
|
3898
|
+
|
3899
|
+
def graph_size(area_width, area_height)
|
3900
|
+
graph_width = area_width - X_OFF_LEFT - X_OFF_RIGHT
|
3901
|
+
graph_height = area_height - Y_OFF_TOP - Y_OFF_BOTTOM
|
3902
|
+
[graph_width, graph_height]
|
3903
|
+
end
|
3904
|
+
|
3905
|
+
def point_locations(datapoints, width, height)
|
3906
|
+
xincr = width / 9.0 # 10 - 1 to make the last point be at the end
|
3907
|
+
yincr = height / 100.0
|
3908
|
+
|
3909
|
+
data = []
|
3910
|
+
datapoints.each_with_index do |dp, i|
|
3911
|
+
val = 100 - dp.value
|
3912
|
+
data << [xincr * i, yincr * val]
|
3913
|
+
i += 1
|
3914
|
+
end
|
3915
|
+
|
3916
|
+
data
|
3917
|
+
end
|
3918
|
+
|
3919
|
+
def graph_path(datapoints, width, height, should_extend, &block)
|
3920
|
+
locations = point_locations(datapoints, width, height)
|
3921
|
+
path {
|
3922
|
+
first_location = locations[0] # x and y
|
3923
|
+
figure(first_location[0], first_location[1]) {
|
3924
|
+
locations.each do |loc|
|
3925
|
+
line(loc[0], loc[1])
|
3926
|
+
end
|
3927
|
+
if should_extend
|
3928
|
+
line(width, height)
|
3929
|
+
line(0, height)
|
3930
|
+
|
3931
|
+
closed true
|
3932
|
+
end
|
3933
|
+
}
|
3934
|
+
|
3935
|
+
# now transform the coordinate space so (0, 0) is the top-left corner of the graph
|
3936
|
+
transform {
|
3937
|
+
translate X_OFF_LEFT, Y_OFF_TOP
|
3938
|
+
}
|
3939
|
+
|
3940
|
+
block.call
|
3941
|
+
}
|
3942
|
+
end
|
3943
|
+
|
3944
|
+
window('histogram example', 640, 480) {
|
3945
|
+
margined true
|
3946
|
+
|
3947
|
+
horizontal_box {
|
3948
|
+
vertical_box {
|
3949
|
+
stretchy false
|
3950
|
+
|
3951
|
+
@datapoints = 10.times.map do
|
3952
|
+
spinbox(0, 100) { |datapoint|
|
3953
|
+
stretchy false
|
3954
|
+
value Random.new.rand(90)
|
3955
|
+
|
3956
|
+
on_changed do
|
3957
|
+
@area.queue_redraw_all
|
3958
|
+
end
|
3959
|
+
}
|
3960
|
+
end
|
3961
|
+
|
3962
|
+
@color_button = color_button {
|
3963
|
+
stretchy false
|
3964
|
+
color COLOR_BLUE
|
3965
|
+
|
3966
|
+
on_changed do
|
3967
|
+
@area.queue_redraw_all
|
3968
|
+
end
|
3969
|
+
}
|
3970
|
+
}
|
3971
|
+
|
3972
|
+
@area = area {
|
3973
|
+
on_draw do |area_draw_params|
|
3974
|
+
path {
|
3975
|
+
rectangle(0, 0, area_draw_params[:area_width], area_draw_params[:area_height])
|
3976
|
+
|
3977
|
+
fill color: 0xFFFFFF
|
3978
|
+
}
|
3979
|
+
|
3980
|
+
graph_width, graph_height = *graph_size(area_draw_params[:area_width], area_draw_params[:area_height])
|
3981
|
+
|
3982
|
+
path {
|
3983
|
+
figure(X_OFF_LEFT, Y_OFF_TOP) {
|
3984
|
+
line(X_OFF_LEFT, Y_OFF_TOP + graph_height)
|
3985
|
+
line(X_OFF_LEFT + graph_width, Y_OFF_TOP + graph_height)
|
3986
|
+
}
|
3987
|
+
|
3988
|
+
stroke color: 0x000000, thickness: 2, miter_limit: 10
|
3989
|
+
}
|
3990
|
+
|
3991
|
+
# now create the fill for the graph below the graph line
|
3992
|
+
graph_path(@datapoints, graph_width, graph_height, true) {
|
3993
|
+
fill @color_button.color.merge(a: 0.5)
|
3994
|
+
}
|
3995
|
+
|
3996
|
+
# now draw the histogram line
|
3997
|
+
graph_path(@datapoints, graph_width, graph_height, false) {
|
3998
|
+
stroke @color_button.color.merge(thickness: 2, miter_limit: 10)
|
3999
|
+
}
|
4000
|
+
end
|
4001
|
+
}
|
4002
|
+
}
|
4003
|
+
}.show
|
4004
|
+
```
|
4005
|
+
|
4006
|
+
### Basic Transform
|
4007
|
+
|
4008
|
+
[examples/basic_transform.rb](examples/basic_transform.rb)
|
4009
|
+
|
4010
|
+
Run with this command from the root of the project if you cloned the project:
|
4011
|
+
|
4012
|
+
```
|
4013
|
+
ruby -r './lib/glimmer-dsl-libui' examples/basic_transform.rb
|
4014
|
+
```
|
4015
|
+
|
4016
|
+
Run with this command if you installed the [Ruby gem](https://rubygems.org/gems/glimmer-dsl-libui):
|
4017
|
+
|
4018
|
+
```
|
4019
|
+
ruby -r glimmer-dsl-libui -e "require 'examples/basic_transform'"
|
4020
|
+
```
|
4021
|
+
|
4022
|
+
Mac
|
4023
|
+
|
4024
|
+
![glimmer-dsl-libui-mac-basic-transform.png](images/glimmer-dsl-libui-mac-basic-transform.png)
|
4025
|
+
|
4026
|
+
Linux
|
4027
|
+
|
4028
|
+
![glimmer-dsl-libui-linux-basic-transform.png](images/glimmer-dsl-libui-linux-basic-transform.png)
|
4029
|
+
|
4030
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
4031
|
+
|
4032
|
+
```ruby
|
4033
|
+
require 'glimmer-dsl-libui'
|
4034
|
+
|
4035
|
+
include Glimmer
|
4036
|
+
|
4037
|
+
window('Basic Transform', 350, 350) {
|
4038
|
+
area {
|
4039
|
+
path {
|
4040
|
+
square(0, 0, 350)
|
4041
|
+
|
4042
|
+
fill r: 255, g: 255, b: 0
|
4043
|
+
}
|
4044
|
+
40.times do |n|
|
4045
|
+
path {
|
4046
|
+
square(0, 0, 100)
|
4047
|
+
|
4048
|
+
fill r: [255 - n*5, 0].max, g: [n*5, 255].min, b: 0, a: 0.5
|
4049
|
+
stroke color: 0, thickness: 2
|
4050
|
+
transform {
|
4051
|
+
skew 0.15, 0.15
|
4052
|
+
translate 50, 50
|
4053
|
+
rotate 100, 100, -9 * n
|
4054
|
+
scale 1.1, 1.1
|
4055
|
+
}
|
4056
|
+
}
|
4057
|
+
end
|
4058
|
+
}
|
4059
|
+
}.show
|
4060
|
+
```
|
4061
|
+
|
2877
4062
|
## Contributing to glimmer-dsl-libui
|
2878
4063
|
|
2879
4064
|
- Check out the latest master to make sure the feature hasn't been
|