glimmer-dsl-libui 0.1.2 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +55 -0
- data/README.md +1127 -65
- 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_button.rb +2 -2
- data/examples/basic_entry.rb +2 -2
- data/examples/basic_table_progress_bar.rb +13 -3
- data/examples/basic_transform.rb +27 -0
- data/examples/control_gallery.rb +3 -3
- data/examples/dynamic_area.rb +1 -1
- data/examples/form.rb +2 -2
- data/examples/histogram.rb +118 -0
- data/examples/meta_example.rb +71 -20
- data/examples/midi_player.rb +8 -10
- data/glimmer-dsl-libui.gemspec +0 -0
- data/lib/glimmer/dsl/libui/control_expression.rb +1 -3
- data/lib/glimmer/dsl/libui/dsl.rb +1 -0
- data/lib/glimmer/dsl/libui/file_expression.rb +5 -1
- data/lib/glimmer/dsl/libui/property_expression.rb +5 -1
- data/lib/glimmer/{libui/box.rb → dsl/libui/shape_expression.rb} +26 -29
- data/lib/glimmer/dsl/libui/tab_item_expression.rb +2 -2
- data/lib/glimmer/libui/control_proxy/area_proxy.rb +117 -0
- data/lib/glimmer/libui/{menu_item_proxy.rb → control_proxy/box/horizontal_box_proxy.rb} +9 -12
- data/lib/glimmer/libui/{vertical_box_proxy.rb → control_proxy/box/vertical_box_proxy.rb} +10 -6
- data/lib/glimmer/libui/control_proxy/box.rb +61 -0
- data/lib/glimmer/libui/{button_proxy.rb → control_proxy/button_proxy.rb} +14 -12
- data/lib/glimmer/libui/{checkbox_proxy.rb → control_proxy/checkbox_proxy.rb} +14 -12
- data/lib/glimmer/libui/control_proxy/color_button_proxy.rb +118 -0
- data/lib/glimmer/libui/control_proxy/column/button_column_proxy.rb +76 -0
- data/lib/glimmer/libui/control_proxy/column/checkbox_column_proxy.rb +46 -0
- data/lib/glimmer/libui/control_proxy/column/checkbox_text_column_proxy.rb +80 -0
- data/lib/glimmer/libui/{radio_buttons_proxy.rb → control_proxy/column/image_column_proxy.rb} +14 -13
- data/lib/glimmer/libui/control_proxy/column/image_text_column_proxy.rb +48 -0
- data/lib/glimmer/libui/{progress_bar_column_proxy.rb → control_proxy/column/progress_bar_column_proxy.rb} +14 -10
- data/lib/glimmer/libui/control_proxy/column/text_column_proxy.rb +46 -0
- data/lib/glimmer/libui/control_proxy/column.rb +55 -0
- data/lib/glimmer/libui/{checkbox_column_proxy.rb → control_proxy/combobox_proxy.rb} +16 -13
- data/lib/glimmer/libui/control_proxy/date_time_picker_proxy/date_picker_proxy.rb +43 -0
- data/lib/glimmer/libui/control_proxy/date_time_picker_proxy/time_picker_proxy.rb +43 -0
- data/lib/glimmer/libui/control_proxy/date_time_picker_proxy.rb +72 -0
- data/lib/glimmer/libui/control_proxy/dual_column.rb +40 -0
- data/lib/glimmer/libui/control_proxy/editable_column.rb +46 -0
- data/lib/glimmer/libui/control_proxy/editable_combobox_proxy.rb +45 -0
- data/lib/glimmer/libui/{dual_column.rb → control_proxy/enableable_column.rb} +18 -10
- data/lib/glimmer/libui/control_proxy/font_button_proxy.rb +70 -0
- data/lib/glimmer/libui/{form_proxy.rb → control_proxy/form_proxy.rb} +26 -24
- data/lib/glimmer/libui/{grid_proxy.rb → control_proxy/grid_proxy.rb} +29 -27
- data/lib/glimmer/libui/{group_proxy.rb → control_proxy/group_proxy.rb} +24 -22
- data/lib/glimmer/libui/{image_part_proxy.rb → control_proxy/image_part_proxy.rb} +20 -18
- data/lib/glimmer/libui/{image_proxy.rb → control_proxy/image_proxy.rb} +32 -30
- data/lib/glimmer/libui/{combobox_proxy.rb → control_proxy/label_proxy.rb} +13 -13
- data/lib/glimmer/libui/control_proxy/matrix_proxy.rb +147 -0
- data/lib/glimmer/libui/{editable_column.rb → control_proxy/menu_item_proxy/about_menu_item_proxy.rb} +13 -16
- data/lib/glimmer/libui/control_proxy/menu_item_proxy/check_menu_item_proxy.rb +41 -0
- data/lib/glimmer/libui/{preferences_menu_item_proxy.rb → control_proxy/menu_item_proxy/preferences_menu_item_proxy.rb} +11 -9
- data/lib/glimmer/libui/control_proxy/menu_item_proxy/quit_menu_item_proxy.rb +66 -0
- data/lib/glimmer/libui/control_proxy/menu_item_proxy/separator_menu_item_proxy.rb +41 -0
- data/lib/glimmer/libui/control_proxy/menu_item_proxy.rb +45 -0
- data/lib/glimmer/libui/{editable_combobox_proxy.rb → control_proxy/menu_proxy.rb} +13 -13
- data/lib/glimmer/libui/{horizontal_box_proxy.rb → control_proxy/message_box/msg_box_error_proxy.rb} +9 -6
- data/lib/glimmer/libui/{multiline_entry_proxy.rb → control_proxy/message_box/msg_box_proxy.rb} +8 -6
- data/lib/glimmer/libui/{check_menu_item_proxy.rb → control_proxy/message_box.rb} +11 -10
- data/lib/glimmer/libui/control_proxy/multiline_entry_proxy/non_wrapping_multiline_entry_proxy.rb +34 -0
- data/lib/glimmer/libui/{image_column_proxy.rb → control_proxy/multiline_entry_proxy.rb} +10 -11
- data/lib/glimmer/libui/control_proxy/path_proxy.rb +169 -0
- data/lib/glimmer/libui/control_proxy/radio_buttons_proxy.rb +45 -0
- data/lib/glimmer/libui/{button_column_proxy.rb → control_proxy/tab_item_proxy.rb} +37 -40
- data/lib/glimmer/libui/control_proxy/table_proxy.rb +182 -0
- data/lib/glimmer/libui/control_proxy/transformable.rb +74 -0
- data/lib/glimmer/libui/control_proxy/window_proxy.rb +128 -0
- data/lib/glimmer/libui/control_proxy.rb +41 -22
- data/lib/glimmer/libui/{enableable_column.rb → parent.rb} +7 -15
- data/lib/glimmer/libui/shape/arc.rb +43 -0
- data/lib/glimmer/libui/{date_picker_proxy.rb → shape/bezier.rb} +8 -9
- data/lib/glimmer/libui/{quit_menu_item_proxy.rb → shape/figure.rb} +24 -32
- data/lib/glimmer/libui/{non_wrapping_multiline_entry_proxy.rb → shape/line.rb} +11 -5
- data/lib/glimmer/libui/{time_picker_proxy.rb → shape/rectangle.rb} +8 -9
- data/lib/glimmer/libui/{about_menu_item_proxy.rb → shape/square.rb} +9 -8
- data/lib/glimmer/libui/shape.rb +145 -0
- data/lib/glimmer/libui.rb +92 -0
- data/lib/glimmer-dsl-libui.rb +2 -0
- metadata +82 -48
- data/lib/glimmer/libui/area_proxy.rb +0 -105
- data/lib/glimmer/libui/checkbox_text_column_proxy.rb +0 -76
- data/lib/glimmer/libui/color_button_proxy.rb +0 -64
- data/lib/glimmer/libui/column.rb +0 -51
- data/lib/glimmer/libui/date_time_picker_proxy.rb +0 -68
- data/lib/glimmer/libui/font_button_proxy.rb +0 -68
- data/lib/glimmer/libui/image_text_column_proxy.rb +0 -44
- data/lib/glimmer/libui/label_proxy.rb +0 -41
- data/lib/glimmer/libui/menu_proxy.rb +0 -41
- data/lib/glimmer/libui/path_proxy.rb +0 -167
- data/lib/glimmer/libui/rectangle_proxy.rb +0 -100
- data/lib/glimmer/libui/separator_menu_item_proxy.rb +0 -37
- data/lib/glimmer/libui/tab_item_proxy.rb +0 -67
- data/lib/glimmer/libui/table_proxy.rb +0 -180
- data/lib/glimmer/libui/text_column_proxy.rb +0 -42
- data/lib/glimmer/libui/window_proxy.rb +0 -119
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.6
|
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.6](#-glimmer-dsl-for-libui-016)
|
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)
|
@@ -146,10 +249,10 @@ require 'glimmer-dsl-libui'
|
|
146
249
|
|
147
250
|
include Glimmer
|
148
251
|
|
149
|
-
window('hello world', 300, 200) {
|
252
|
+
window('hello world', 300, 200) {
|
150
253
|
button('Button') {
|
151
254
|
on_clicked do
|
152
|
-
msg_box(
|
255
|
+
msg_box('Information', 'You clicked the button')
|
153
256
|
end
|
154
257
|
}
|
155
258
|
|
@@ -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.6'
|
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,11 +373,13 @@ 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`
|
255
|
-
`msg_box(window as Glimmer::LibUI::WindowProxy, title as String, description as String)` | None | None
|
256
|
-
`msg_box_error(window as Glimmer::LibUI::WindowProxy, title as String, description as String)` | None | None
|
381
|
+
`msg_box(window = main_window as Glimmer::LibUI::WindowProxy, title as String, description as String)` | None | None
|
382
|
+
`msg_box_error(window = main_window as Glimmer::LibUI::WindowProxy, title as String, description as String)` | None | None
|
257
383
|
`non_wrapping_multiline_entry` | `read_only` (Boolean), `text` (`String`) | `on_changed`
|
258
384
|
`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
|
259
385
|
`preferences_menu_item` | None | `on_clicked`
|
@@ -261,14 +387,15 @@ 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
|
270
397
|
`text_column(name as String)` | `editable` (Boolean) | None
|
271
|
-
`time_picker` | `time` (`Hash` of keys: `sec` as `Integer`, `min` as `Integer`, `hour` as `Integer
|
398
|
+
`time_picker` | `time` (`Hash` of keys: `sec` as `Integer`, `min` as `Integer`, `hour` as `Integer`) | `on_changed`
|
272
399
|
`vertical_box` | `padded` (Boolean) | None
|
273
400
|
`window(title as String, width as Integer, height as Integer, has_menubar as Boolean)` | `borderless` (Boolean), `content_size` (width `Numeric`, height `Numeric`), `fullscreen` (Boolean), `margined` (Boolean), `title` (`String`) | `on_closing`, `on_content_size_changed`, `on_destroy`
|
274
401
|
|
@@ -328,11 +455,85 @@ Note that the `cell_rows` property declaration results in "implicit data-binding
|
|
328
455
|
- Inserting cell rows: Calling `Array#<<`, `Array#push`, `Array#prepend`, or any insertion/addition `Array` method automatically inserts rows in actual `table` control
|
329
456
|
- Changing cell rows: Calling `Array#[]=`, `Array#map!`, or any update `Array` method automatically updates rows in actual `table` control
|
330
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
|
+
|
331
532
|
### Area API
|
332
533
|
|
333
|
-
The `area` control can be used in one of two ways:
|
334
|
-
- 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.
|
335
|
-
- 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.
|
336
537
|
|
337
538
|
Here is an example of a declarative `area` with a stable path (you may copy/paste in [`girb`](#girb-glimmer-irb)):
|
338
539
|
|
@@ -358,7 +559,7 @@ window('Basic Area', 400, 400) {
|
|
358
559
|
|
359
560
|
![glimmer-dsl-libui-mac-basic-area.png](images/glimmer-dsl-libui-mac-basic-area.png)
|
360
561
|
|
361
|
-
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)):
|
362
563
|
|
363
564
|
```ruby
|
364
565
|
require 'glimmer-dsl-libui'
|
@@ -371,7 +572,7 @@ window('Basic Area', 400, 400) {
|
|
371
572
|
vertical_box {
|
372
573
|
area {
|
373
574
|
on_draw do |area_draw_params|
|
374
|
-
path
|
575
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
375
576
|
rectangle(0, 0, 400, 400)
|
376
577
|
|
377
578
|
fill r: 102, g: 102, b: 204, a: 1.0
|
@@ -384,16 +585,108 @@ window('Basic Area', 400, 400) {
|
|
384
585
|
|
385
586
|
Check [examples/dynamic_area.rb](#dynamic-area) for a more detailed semi-declarative example.
|
386
587
|
|
387
|
-
|
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
|
+
Note that when nesting an `area` directly underneath `window` (without a layout control like `vertical_box`), it is automatically reparented with `vertical_box` in between the `window` and `area` since it would not show up on Linux otherwise.
|
610
|
+
|
611
|
+
To redraw an `area`, you may call the `#queue_redraw_all` method, or simply `#redraw`.
|
612
|
+
|
613
|
+
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.
|
614
|
+
|
615
|
+
When instantiating a `matrix` object, it always starts with identity matrix.
|
616
|
+
|
617
|
+
Here are the following operations that can be performed in a `matrix` body:
|
618
|
+
- `identity` [alias: `set_identity`]: resets matrix to identity matrix
|
619
|
+
- `translate(x as Numeric, y as Numeric)`
|
620
|
+
- `scale(x_center = 0 as Numeric, y_center = 0 as Numeric, x as Numeric, y as Numeric)`
|
621
|
+
- `skew(x = 0 as Numeric, y = 0 as Numeric, x_amount as Numeric, y_amount as Numeric)`
|
622
|
+
- `rotate(x = 0 as Numeric, y = 0 as Numeric, degrees as Numeric)`
|
623
|
+
|
624
|
+
Example of using transform matrix (you may copy/paste in [`girb`](#girb-glimmer-irb)):
|
388
625
|
|
389
|
-
|
626
|
+
```ruby
|
627
|
+
require 'glimmer-dsl-libui'
|
628
|
+
|
629
|
+
include Glimmer
|
630
|
+
|
631
|
+
window('Basic Transform', 350, 350) {
|
632
|
+
area {
|
633
|
+
path {
|
634
|
+
square(0, 0, 350)
|
635
|
+
|
636
|
+
fill r: 255, g: 255, b: 0
|
637
|
+
}
|
638
|
+
40.times do |n|
|
639
|
+
path {
|
640
|
+
square(0, 0, 100)
|
641
|
+
|
642
|
+
fill r: [255 - n*5, 0].max, g: [n*5, 255].min, b: 0, a: 0.5
|
643
|
+
stroke :black, thickness: 2
|
644
|
+
transform {
|
645
|
+
skew 0.15, 0.15
|
646
|
+
translate 50, 50
|
647
|
+
rotate 100, 100, -9 * n
|
648
|
+
scale 1.1, 1.1
|
649
|
+
}
|
650
|
+
}
|
651
|
+
end
|
652
|
+
}
|
653
|
+
}.show
|
654
|
+
```
|
655
|
+
|
656
|
+
Keep in mind that this part could be written differently when there is a need to reuse the matrix:
|
657
|
+
|
658
|
+
```ruby
|
659
|
+
transform {
|
660
|
+
translate 100, 100
|
661
|
+
rotate 100, 100, -9 * n
|
662
|
+
}
|
663
|
+
```
|
664
|
+
|
665
|
+
Alternatively:
|
666
|
+
|
667
|
+
```ruby
|
668
|
+
m1 = matrix {
|
669
|
+
translate 100, 100
|
670
|
+
rotate 100, 100, -9 * n
|
671
|
+
}
|
672
|
+
transform m1
|
673
|
+
# and then reuse m1 elsewhere too
|
674
|
+
```
|
675
|
+
|
676
|
+
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.
|
677
|
+
|
678
|
+
`fill` and `stroke` accept [X11](https://en.wikipedia.org/wiki/X11_color_names) color `Symbol`s/`String`s like `:skyblue` and `'sandybrown'` or 6-number hex or 3-number hex-shorthand (as `Integer` or `String` with or without `0x` prefix)
|
679
|
+
|
680
|
+
Check [Basic Transform](#basic-transform) example for use of [X11](https://en.wikipedia.org/wiki/X11_color_names) colors.
|
681
|
+
|
682
|
+
Check [Histogram](#histogram) example for use of hex colors.
|
390
683
|
|
391
684
|
### Smart Defaults and Conventions
|
392
685
|
|
393
686
|
- `horizontal_box`, `vertical_box`, `grid`, and `form` controls have `padded` as `true` upon instantiation to ensure more user-friendly GUI by default
|
394
687
|
- `group` controls have `margined` as `true` upon instantiation to ensure more user-friendly GUI by default
|
395
688
|
- All controls nested under a `horizontal_box`, `vertical_box`, and `form` have `stretchy` property (fill maximum space) as `true` by default (passed to `box_append`/`form_append` method)
|
396
|
-
- `window` instatiation args can be left off, having the following defaults when unspecified: `title` as `''`, `width` as `
|
689
|
+
- `window` instatiation args can be left off, having the following defaults when unspecified: `title` as `''`, `width` as `190`, `height` as `150`, and `has_menubar` as `true`)
|
397
690
|
- `window` has an `on_closing` listener by default that quits application upon hitting the close button (can be overridden with a manual `on_closing` implementation that returns integer `0` for success)
|
398
691
|
- `group` has `title` property default to `''` if not specified in instantiation args, so it can be instantiated without args with `title` property specified in nested block (e.g. `group {title 'Address'; ...}`)
|
399
692
|
- `button`, `checkbox`, and `label` have `text` default to `''` if not specified in instantiation args, so they can be instantiated without args with `text` property specified in nested block (e.g. `button {text 'Greet'; on_clicked {puts 'Hello'}}`)
|
@@ -419,11 +712,17 @@ To redraw an `area`, you may call `#queue_redraw_all` method.
|
|
419
712
|
- `area` paths are specified declaratively with figures underneath (e.g. `rectangle`) and `area` draw listener is automatically generated
|
420
713
|
- Observe figure properties (e.g. `rectangle` `width`) for changes and automatically redraw containing area accordingly
|
421
714
|
- Observe `path` `fill` and `stroke` hashes for changes and automatically redraw containing area accordingly
|
715
|
+
- All controls are protected from garbage collection until no longer needed (explicitly destroyed), so there is no need to worry about surprises.
|
716
|
+
- All resources are freed automatically once no longer needed or left to garbage collection.
|
717
|
+
- When nesting an `area` directly underneath `window` (without a layout control like `vertical_box`), it is automatically reparented with `vertical_box` in between the `window` and `area` since it would not show up on Linux otherwise.
|
718
|
+
- Colors may be passed in as a hash of `:r`, `:g`, `:b`, `:a`, or `:red`, `:green`, `:blue`, `:alpha`, or [X11](https://en.wikipedia.org/wiki/X11_color_names) color like `:skyblue`, or 6-number hex or 3-number hex (as `Integer` or `String` with or without `0x` prefix)
|
719
|
+
- Color alpha value defaults to `1.0` when not specified.
|
422
720
|
|
423
721
|
### API Gotchas
|
424
722
|
|
425
723
|
- 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`).
|
426
724
|
- `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).
|
725
|
+
- 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.
|
427
726
|
|
428
727
|
### Original API
|
429
728
|
|
@@ -439,21 +738,9 @@ check out the [libui C headers](https://github.com/andlabs/libui/blob/master/ui.
|
|
439
738
|
- 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.
|
440
739
|
- 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.
|
441
740
|
|
442
|
-
## Girb (Glimmer IRB)
|
443
|
-
|
444
|
-
You can run the `girb` command (`bin/girb` if you cloned the project locally):
|
445
|
-
|
446
|
-
```
|
447
|
-
girb
|
448
|
-
```
|
449
|
-
|
450
|
-
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.
|
451
|
-
|
452
|
-
Gotcha: On the Mac, when you close a window opened in `girb`, it remains open until you enter `exit` or open another GUI window.
|
453
|
-
|
454
741
|
## Examples
|
455
742
|
|
456
|
-
|
743
|
+
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.
|
457
744
|
|
458
745
|
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.
|
459
746
|
|
@@ -507,7 +794,7 @@ class MetaExample
|
|
507
794
|
end
|
508
795
|
|
509
796
|
def launch
|
510
|
-
window('Meta-Example', 700, 500) {
|
797
|
+
window('Meta-Example', 700, 500) {
|
511
798
|
margined true
|
512
799
|
|
513
800
|
horizontal_box {
|
@@ -529,7 +816,7 @@ class MetaExample
|
|
529
816
|
meta_example_file = File.join(Dir.home, '.meta_example.rb')
|
530
817
|
File.write(meta_example_file, @nwme.text)
|
531
818
|
result = `ruby -r #{glimmer_dsl_libui_file} #{meta_example_file} 2>&1`
|
532
|
-
msg_box(
|
819
|
+
msg_box('Error Running Example', result) if result.include?('error')
|
533
820
|
rescue => e
|
534
821
|
puts 'Unable to write code changes! Running original example...'
|
535
822
|
system "ruby -r #{glimmer_dsl_libui_file} #{file_path_for(@examples[@rbs.selected])}"
|
@@ -613,7 +900,7 @@ window('hello world', 300, 200, true) {
|
|
613
900
|
}.show
|
614
901
|
```
|
615
902
|
|
616
|
-
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2:
|
903
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (setting `window` properties instead of arguments):
|
617
904
|
|
618
905
|
```ruby
|
619
906
|
require 'glimmer-dsl-libui'
|
@@ -694,10 +981,10 @@ require 'glimmer-dsl-libui'
|
|
694
981
|
|
695
982
|
include Glimmer
|
696
983
|
|
697
|
-
window('hello world', 300, 200) {
|
984
|
+
window('hello world', 300, 200) {
|
698
985
|
button('Button') {
|
699
986
|
on_clicked do
|
700
|
-
msg_box(
|
987
|
+
msg_box('Information', 'You clicked the button')
|
701
988
|
end
|
702
989
|
}
|
703
990
|
|
@@ -781,7 +1068,7 @@ require 'glimmer-dsl-libui'
|
|
781
1068
|
|
782
1069
|
include Glimmer
|
783
1070
|
|
784
|
-
window('Basic Entry', 300, 50) {
|
1071
|
+
window('Basic Entry', 300, 50) {
|
785
1072
|
horizontal_box {
|
786
1073
|
e = entry {
|
787
1074
|
# stretchy true # Smart default option for appending to horizontal_box
|
@@ -797,7 +1084,7 @@ window('Basic Entry', 300, 50) { |w|
|
|
797
1084
|
|
798
1085
|
on_clicked do
|
799
1086
|
text = e.text
|
800
|
-
msg_box(
|
1087
|
+
msg_box('You entered', text)
|
801
1088
|
end
|
802
1089
|
}
|
803
1090
|
}
|
@@ -901,12 +1188,12 @@ ruby -r glimmer-dsl-libui -e "require 'examples/midi_player'"
|
|
901
1188
|
Mac
|
902
1189
|
|
903
1190
|
![glimmer-dsl-libui-mac-midi-player.png](images/glimmer-dsl-libui-mac-midi-player.png)
|
904
|
-
![glimmer-dsl-libui-mac-midi-player-
|
1191
|
+
![glimmer-dsl-libui-mac-midi-player-msg-box.png](images/glimmer-dsl-libui-mac-midi-player-msg-box.png)
|
905
1192
|
|
906
1193
|
Linux
|
907
1194
|
|
908
1195
|
![glimmer-dsl-libui-linux-midi-player.png](images/glimmer-dsl-libui-linux-midi-player.png)
|
909
|
-
![glimmer-dsl-libui-linux-midi-player-
|
1196
|
+
![glimmer-dsl-libui-linux-midi-player-msg-box.png](images/glimmer-dsl-libui-linux-midi-player-msg-box.png)
|
910
1197
|
|
911
1198
|
[LibUI](https://github.com/kojix2/LibUI) Original Version:
|
912
1199
|
|
@@ -1052,23 +1339,22 @@ class TinyMidiPlayer
|
|
1052
1339
|
end
|
1053
1340
|
end
|
1054
1341
|
|
1055
|
-
def show_version
|
1056
|
-
msg_box(
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
"Version #{VERSION}")
|
1342
|
+
def show_version
|
1343
|
+
msg_box('Tiny Midi Player',
|
1344
|
+
"Written in Ruby\n" \
|
1345
|
+
"https://github.com/kojix2/libui\n" \
|
1346
|
+
"Version #{VERSION}")
|
1061
1347
|
end
|
1062
1348
|
|
1063
1349
|
def create_gui
|
1064
1350
|
menu('Help') { |m|
|
1065
1351
|
menu_item('Version') {
|
1066
1352
|
on_clicked do
|
1067
|
-
show_version
|
1353
|
+
show_version
|
1068
1354
|
end
|
1069
1355
|
}
|
1070
1356
|
}
|
1071
|
-
|
1357
|
+
window('Tiny Midi Player', 200, 50) {
|
1072
1358
|
horizontal_box {
|
1073
1359
|
vertical_box {
|
1074
1360
|
stretchy false
|
@@ -1084,7 +1370,7 @@ class TinyMidiPlayer
|
|
1084
1370
|
end
|
1085
1371
|
}
|
1086
1372
|
}
|
1087
|
-
|
1373
|
+
|
1088
1374
|
combobox { |c|
|
1089
1375
|
items @midi_files.map { |path| File.basename(path) }
|
1090
1376
|
|
@@ -1094,8 +1380,7 @@ class TinyMidiPlayer
|
|
1094
1380
|
end
|
1095
1381
|
}
|
1096
1382
|
}
|
1097
|
-
}
|
1098
|
-
@main_window.show
|
1383
|
+
}.show
|
1099
1384
|
end
|
1100
1385
|
end
|
1101
1386
|
|
@@ -1331,14 +1616,14 @@ include Glimmer
|
|
1331
1616
|
menu('File') {
|
1332
1617
|
menu_item('Open') {
|
1333
1618
|
on_clicked do
|
1334
|
-
file = open_file
|
1619
|
+
file = open_file
|
1335
1620
|
puts file unless file.nil?
|
1336
1621
|
end
|
1337
1622
|
}
|
1338
1623
|
|
1339
1624
|
menu_item('Save') {
|
1340
1625
|
on_clicked do
|
1341
|
-
file = save_file
|
1626
|
+
file = save_file
|
1342
1627
|
puts file unless file.nil?
|
1343
1628
|
end
|
1344
1629
|
}
|
@@ -1381,7 +1666,7 @@ MAIN_WINDOW = window('Control Gallery', 600, 500) {
|
|
1381
1666
|
stretchy false
|
1382
1667
|
|
1383
1668
|
on_clicked do
|
1384
|
-
msg_box(
|
1669
|
+
msg_box('Information', 'You clicked the button')
|
1385
1670
|
end
|
1386
1671
|
}
|
1387
1672
|
|
@@ -1389,7 +1674,7 @@ MAIN_WINDOW = window('Control Gallery', 600, 500) {
|
|
1389
1674
|
stretchy false
|
1390
1675
|
|
1391
1676
|
on_toggled do |c|
|
1392
|
-
checked = c.checked
|
1677
|
+
checked = c.checked?
|
1393
1678
|
MAIN_WINDOW.title = "Checkbox is #{checked}"
|
1394
1679
|
c.text = "I am the checkbox (#{checked})"
|
1395
1680
|
end
|
@@ -1843,7 +2128,7 @@ require 'glimmer-dsl-libui'
|
|
1843
2128
|
|
1844
2129
|
include Glimmer
|
1845
2130
|
|
1846
|
-
window('Form') {
|
2131
|
+
window('Form') {
|
1847
2132
|
margined true
|
1848
2133
|
|
1849
2134
|
vertical_box {
|
@@ -1859,7 +2144,7 @@ window('Form') { |w|
|
|
1859
2144
|
|
1860
2145
|
button('Display Name') {
|
1861
2146
|
on_clicked do
|
1862
|
-
msg_box(
|
2147
|
+
msg_box('Name', "#{@first_name_entry.text} #{@last_name_entry.text}")
|
1863
2148
|
end
|
1864
2149
|
}
|
1865
2150
|
}
|
@@ -2543,13 +2828,23 @@ data = [
|
|
2543
2828
|
['task 5', -1],
|
2544
2829
|
]
|
2545
2830
|
|
2546
|
-
window('Task
|
2547
|
-
|
2831
|
+
window('Task Progress', 300, 200) {
|
2832
|
+
vertical_box {
|
2548
2833
|
table {
|
2549
2834
|
text_column('Task')
|
2550
2835
|
progress_bar_column('Progress')
|
2551
2836
|
|
2552
|
-
cell_rows data
|
2837
|
+
cell_rows data # implicit data-binding
|
2838
|
+
}
|
2839
|
+
|
2840
|
+
button('Mark All As Done') {
|
2841
|
+
stretchy false
|
2842
|
+
|
2843
|
+
on_clicked do
|
2844
|
+
data.each_with_index do |row_data, row|
|
2845
|
+
data[row] = [row_data[0], 100] # automatically updates table due to implicit data-binding
|
2846
|
+
end
|
2847
|
+
end
|
2553
2848
|
}
|
2554
2849
|
}
|
2555
2850
|
}.show
|
@@ -2749,7 +3044,7 @@ window('Basic Area', 400, 400) {
|
|
2749
3044
|
}.show
|
2750
3045
|
```
|
2751
3046
|
|
2752
|
-
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2:
|
3047
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (semi-declarative `on_draw` dynamic `path` approach):
|
2753
3048
|
|
2754
3049
|
```ruby
|
2755
3050
|
require 'glimmer-dsl-libui'
|
@@ -2762,7 +3057,7 @@ window('Basic Area', 400, 400) {
|
|
2762
3057
|
vertical_box {
|
2763
3058
|
area {
|
2764
3059
|
on_draw do |area_draw_params|
|
2765
|
-
path
|
3060
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
2766
3061
|
rectangle(0, 0, 400, 400)
|
2767
3062
|
|
2768
3063
|
fill r: 102, g: 102, b: 204, a: 1.0
|
@@ -2892,7 +3187,7 @@ window('Dynamic Area', 240, 500) {
|
|
2892
3187
|
|
2893
3188
|
@area = area {
|
2894
3189
|
on_draw do |area_draw_params|
|
2895
|
-
path
|
3190
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
2896
3191
|
rectangle(@x_spinbox.value, @y_spinbox.value, @width_spinbox.value, @height_spinbox.value)
|
2897
3192
|
|
2898
3193
|
fill r: @red_spinbox.value, g: @green_spinbox.value, b: @blue_spinbox.value, a: @alpha_spinbox.value / 100.0
|
@@ -2903,7 +3198,7 @@ window('Dynamic Area', 240, 500) {
|
|
2903
3198
|
}.show
|
2904
3199
|
```
|
2905
3200
|
|
2906
|
-
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2:
|
3201
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (declarative stable `path` approach):
|
2907
3202
|
|
2908
3203
|
```ruby
|
2909
3204
|
require 'glimmer-dsl-libui'
|
@@ -3005,6 +3300,773 @@ window('Dynamic Area', 240, 600) {
|
|
3005
3300
|
}.show
|
3006
3301
|
```
|
3007
3302
|
|
3303
|
+
### Area Gallery
|
3304
|
+
|
3305
|
+
[examples/area_gallery.rb](examples/area_gallery.rb)
|
3306
|
+
|
3307
|
+
Run with this command from the root of the project if you cloned the project:
|
3308
|
+
|
3309
|
+
```
|
3310
|
+
ruby -r './lib/glimmer-dsl-libui' examples/area_gallery.rb
|
3311
|
+
```
|
3312
|
+
|
3313
|
+
Run with this command if you installed the [Ruby gem](https://rubygems.org/gems/glimmer-dsl-libui):
|
3314
|
+
|
3315
|
+
```
|
3316
|
+
ruby -r glimmer-dsl-libui -e "require 'examples/area_gallery'"
|
3317
|
+
```
|
3318
|
+
|
3319
|
+
Mac
|
3320
|
+
|
3321
|
+
![glimmer-dsl-libui-mac-area-gallery.png](images/glimmer-dsl-libui-mac-area-gallery.png)
|
3322
|
+
|
3323
|
+
Linux
|
3324
|
+
|
3325
|
+
![glimmer-dsl-libui-linux-area-gallery.png](images/glimmer-dsl-libui-linux-area-gallery.png)
|
3326
|
+
|
3327
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
3328
|
+
|
3329
|
+
```ruby
|
3330
|
+
require 'glimmer-dsl-libui'
|
3331
|
+
|
3332
|
+
include Glimmer
|
3333
|
+
|
3334
|
+
window('Area Gallery', 400, 400) {
|
3335
|
+
area {
|
3336
|
+
path { # declarative stable path
|
3337
|
+
square(0, 0, 100)
|
3338
|
+
square(100, 100, 400)
|
3339
|
+
|
3340
|
+
fill r: 102, g: 102, b: 204
|
3341
|
+
}
|
3342
|
+
path { # declarative stable path
|
3343
|
+
rectangle(0, 100, 100, 400)
|
3344
|
+
rectangle(100, 0, 400, 100)
|
3345
|
+
|
3346
|
+
fill r: 204, g: 102, b: 204
|
3347
|
+
}
|
3348
|
+
path { # declarative stable path
|
3349
|
+
figure(100, 100) {
|
3350
|
+
line(100, 400)
|
3351
|
+
line(400, 100)
|
3352
|
+
line(400, 400)
|
3353
|
+
|
3354
|
+
closed true
|
3355
|
+
}
|
3356
|
+
|
3357
|
+
fill r: 202, g: 102, b: 104, a: 0.5
|
3358
|
+
stroke r: 0, g: 0, b: 0
|
3359
|
+
}
|
3360
|
+
path { # declarative stable path
|
3361
|
+
figure(0, 0) {
|
3362
|
+
bezier(200, 100, 100, 200, 400, 100)
|
3363
|
+
bezier(300, 100, 100, 300, 100, 400)
|
3364
|
+
bezier(100, 300, 300, 100, 400, 400)
|
3365
|
+
|
3366
|
+
closed true
|
3367
|
+
}
|
3368
|
+
|
3369
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
3370
|
+
stroke thickness: 2, r: 0, g: 0, b: 0
|
3371
|
+
}
|
3372
|
+
path { # declarative stable path
|
3373
|
+
arc(200, 200, 90, 0, 360, false)
|
3374
|
+
|
3375
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
3376
|
+
stroke thickness: 2, r: 0, g: 0, b: 0
|
3377
|
+
}
|
3378
|
+
}
|
3379
|
+
}.show
|
3380
|
+
```
|
3381
|
+
|
3382
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (setting shape properties instead of arguments):
|
3383
|
+
|
3384
|
+
```ruby
|
3385
|
+
require 'glimmer-dsl-libui'
|
3386
|
+
|
3387
|
+
include Glimmer
|
3388
|
+
|
3389
|
+
window('Area Gallery', 400, 400) {
|
3390
|
+
area {
|
3391
|
+
path { # declarative stable path
|
3392
|
+
square {
|
3393
|
+
x 0
|
3394
|
+
y 0
|
3395
|
+
length 100
|
3396
|
+
}
|
3397
|
+
square {
|
3398
|
+
x 100
|
3399
|
+
y 100
|
3400
|
+
length 400
|
3401
|
+
}
|
3402
|
+
|
3403
|
+
fill r: 102, g: 102, b: 204
|
3404
|
+
}
|
3405
|
+
path { # declarative stable path
|
3406
|
+
rectangle {
|
3407
|
+
x 0
|
3408
|
+
y 100
|
3409
|
+
width 100
|
3410
|
+
height 400
|
3411
|
+
}
|
3412
|
+
rectangle {
|
3413
|
+
x 100
|
3414
|
+
y 0
|
3415
|
+
width 400
|
3416
|
+
height 100
|
3417
|
+
}
|
3418
|
+
|
3419
|
+
fill r: 204, g: 102, b: 204
|
3420
|
+
}
|
3421
|
+
path { # declarative stable path
|
3422
|
+
figure {
|
3423
|
+
x 100
|
3424
|
+
y 100
|
3425
|
+
|
3426
|
+
line {
|
3427
|
+
x 100
|
3428
|
+
y 400
|
3429
|
+
}
|
3430
|
+
line {
|
3431
|
+
x 400
|
3432
|
+
y 100
|
3433
|
+
}
|
3434
|
+
line {
|
3435
|
+
x 400
|
3436
|
+
y 400
|
3437
|
+
}
|
3438
|
+
|
3439
|
+
closed true
|
3440
|
+
}
|
3441
|
+
|
3442
|
+
fill r: 202, g: 102, b: 104, a: 0.5
|
3443
|
+
stroke r: 0, g: 0, b: 0
|
3444
|
+
}
|
3445
|
+
path { # declarative stable path
|
3446
|
+
figure {
|
3447
|
+
x 0
|
3448
|
+
y 0
|
3449
|
+
|
3450
|
+
bezier {
|
3451
|
+
c1_x 200
|
3452
|
+
c1_y 100
|
3453
|
+
c2_x 100
|
3454
|
+
c2_y 200
|
3455
|
+
end_x 400
|
3456
|
+
end_y 100
|
3457
|
+
}
|
3458
|
+
bezier {
|
3459
|
+
c1_x 300
|
3460
|
+
c1_y 100
|
3461
|
+
c2_x 100
|
3462
|
+
c2_y 300
|
3463
|
+
end_x 100
|
3464
|
+
end_y 400
|
3465
|
+
}
|
3466
|
+
bezier {
|
3467
|
+
c1_x 100
|
3468
|
+
c1_y 300
|
3469
|
+
c2_x 300
|
3470
|
+
c2_y 100
|
3471
|
+
end_x 400
|
3472
|
+
end_y 400
|
3473
|
+
}
|
3474
|
+
|
3475
|
+
closed true
|
3476
|
+
}
|
3477
|
+
|
3478
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
3479
|
+
stroke thickness: 2, r: 0, g: 0, b: 0
|
3480
|
+
}
|
3481
|
+
path { # declarative stable path
|
3482
|
+
arc {
|
3483
|
+
x_center 200
|
3484
|
+
y_center 200
|
3485
|
+
radius 90
|
3486
|
+
start_angle 0
|
3487
|
+
sweep 360
|
3488
|
+
is_negative false
|
3489
|
+
}
|
3490
|
+
|
3491
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
3492
|
+
stroke thickness: 2, r: 0, g: 0, b: 0
|
3493
|
+
}
|
3494
|
+
}
|
3495
|
+
}.show
|
3496
|
+
```
|
3497
|
+
|
3498
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 3 (semi-declarative `on_draw` dynamic `path` approach):
|
3499
|
+
|
3500
|
+
```ruby
|
3501
|
+
require 'glimmer-dsl-libui'
|
3502
|
+
|
3503
|
+
include Glimmer
|
3504
|
+
|
3505
|
+
window('Area Gallery', 400, 400) {
|
3506
|
+
area {
|
3507
|
+
on_draw do |area_draw_params|
|
3508
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3509
|
+
square(0, 0, 100)
|
3510
|
+
square(100, 100, 400)
|
3511
|
+
|
3512
|
+
fill r: 102, g: 102, b: 204
|
3513
|
+
}
|
3514
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3515
|
+
rectangle(0, 100, 100, 400)
|
3516
|
+
rectangle(100, 0, 400, 100)
|
3517
|
+
|
3518
|
+
fill r: 204, g: 102, b: 204
|
3519
|
+
}
|
3520
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3521
|
+
figure(100, 100) {
|
3522
|
+
line(100, 400)
|
3523
|
+
line(400, 100)
|
3524
|
+
line(400, 400)
|
3525
|
+
|
3526
|
+
closed true
|
3527
|
+
}
|
3528
|
+
|
3529
|
+
fill r: 202, g: 102, b: 104, a: 0.5
|
3530
|
+
stroke r: 0, g: 0, b: 0
|
3531
|
+
}
|
3532
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3533
|
+
figure(0, 0) {
|
3534
|
+
bezier(200, 100, 100, 200, 400, 100)
|
3535
|
+
bezier(300, 100, 100, 300, 100, 400)
|
3536
|
+
bezier(100, 300, 300, 100, 400, 400)
|
3537
|
+
|
3538
|
+
closed true
|
3539
|
+
}
|
3540
|
+
|
3541
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
3542
|
+
stroke thickness: 2, r: 0, g: 0, b: 0
|
3543
|
+
}
|
3544
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3545
|
+
arc(200, 200, 90, 0, 360, false)
|
3546
|
+
|
3547
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
3548
|
+
stroke thickness: 2, r: 0, g: 0, b: 0
|
3549
|
+
}
|
3550
|
+
end
|
3551
|
+
}
|
3552
|
+
}.show
|
3553
|
+
```
|
3554
|
+
|
3555
|
+
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):
|
3556
|
+
|
3557
|
+
```ruby
|
3558
|
+
require 'glimmer-dsl-libui'
|
3559
|
+
|
3560
|
+
include Glimmer
|
3561
|
+
|
3562
|
+
window('Area Gallery', 400, 400) {
|
3563
|
+
area {
|
3564
|
+
on_draw do |area_draw_params|
|
3565
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3566
|
+
square {
|
3567
|
+
x 0
|
3568
|
+
y 0
|
3569
|
+
length 100
|
3570
|
+
}
|
3571
|
+
square {
|
3572
|
+
x 100
|
3573
|
+
y 100
|
3574
|
+
length 400
|
3575
|
+
}
|
3576
|
+
|
3577
|
+
fill r: 102, g: 102, b: 204
|
3578
|
+
}
|
3579
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3580
|
+
rectangle {
|
3581
|
+
x 0
|
3582
|
+
y 100
|
3583
|
+
width 100
|
3584
|
+
height 400
|
3585
|
+
}
|
3586
|
+
rectangle {
|
3587
|
+
x 100
|
3588
|
+
y 0
|
3589
|
+
width 400
|
3590
|
+
height 100
|
3591
|
+
}
|
3592
|
+
|
3593
|
+
fill r: 204, g: 102, b: 204
|
3594
|
+
}
|
3595
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3596
|
+
figure {
|
3597
|
+
x 100
|
3598
|
+
y 100
|
3599
|
+
|
3600
|
+
line {
|
3601
|
+
x 100
|
3602
|
+
y 400
|
3603
|
+
}
|
3604
|
+
line {
|
3605
|
+
x 400
|
3606
|
+
y 100
|
3607
|
+
}
|
3608
|
+
line {
|
3609
|
+
x 400
|
3610
|
+
y 400
|
3611
|
+
}
|
3612
|
+
|
3613
|
+
closed true
|
3614
|
+
}
|
3615
|
+
|
3616
|
+
fill r: 202, g: 102, b: 104, a: 0.5
|
3617
|
+
stroke r: 0, g: 0, b: 0
|
3618
|
+
}
|
3619
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3620
|
+
figure {
|
3621
|
+
x 0
|
3622
|
+
y 0
|
3623
|
+
|
3624
|
+
bezier {
|
3625
|
+
c1_x 200
|
3626
|
+
c1_y 100
|
3627
|
+
c2_x 100
|
3628
|
+
c2_y 200
|
3629
|
+
end_x 400
|
3630
|
+
end_y 100
|
3631
|
+
}
|
3632
|
+
bezier {
|
3633
|
+
c1_x 300
|
3634
|
+
c1_y 100
|
3635
|
+
c2_x 100
|
3636
|
+
c2_y 300
|
3637
|
+
end_x 100
|
3638
|
+
end_y 400
|
3639
|
+
}
|
3640
|
+
bezier {
|
3641
|
+
c1_x 100
|
3642
|
+
c1_y 300
|
3643
|
+
c2_x 300
|
3644
|
+
c2_y 100
|
3645
|
+
end_x 400
|
3646
|
+
end_y 400
|
3647
|
+
}
|
3648
|
+
|
3649
|
+
closed true
|
3650
|
+
}
|
3651
|
+
|
3652
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
3653
|
+
stroke thickness: 2, r: 0, g: 0, b: 0
|
3654
|
+
}
|
3655
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3656
|
+
arc {
|
3657
|
+
x_center 200
|
3658
|
+
y_center 200
|
3659
|
+
radius 90
|
3660
|
+
start_angle 0
|
3661
|
+
sweep 360
|
3662
|
+
is_negative false
|
3663
|
+
}
|
3664
|
+
|
3665
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
3666
|
+
stroke thickness: 2, r: 0, g: 0, b: 0
|
3667
|
+
}
|
3668
|
+
end
|
3669
|
+
}
|
3670
|
+
}.show
|
3671
|
+
```
|
3672
|
+
|
3673
|
+
### Histogram
|
3674
|
+
|
3675
|
+
[examples/histogram.rb](examples/histogram.rb)
|
3676
|
+
|
3677
|
+
Run with this command from the root of the project if you cloned the project:
|
3678
|
+
|
3679
|
+
```
|
3680
|
+
ruby -r './lib/glimmer-dsl-libui' examples/histogram.rb
|
3681
|
+
```
|
3682
|
+
|
3683
|
+
Run with this command if you installed the [Ruby gem](https://rubygems.org/gems/glimmer-dsl-libui):
|
3684
|
+
|
3685
|
+
```
|
3686
|
+
ruby -r glimmer-dsl-libui -e "require 'examples/histogram'"
|
3687
|
+
```
|
3688
|
+
|
3689
|
+
Mac
|
3690
|
+
|
3691
|
+
![glimmer-dsl-libui-mac-histogram.png](images/glimmer-dsl-libui-mac-histogram.png)
|
3692
|
+
|
3693
|
+
Linux
|
3694
|
+
|
3695
|
+
![glimmer-dsl-libui-linux-histogram.png](images/glimmer-dsl-libui-linux-histogram.png)
|
3696
|
+
|
3697
|
+
[LibUI](https://github.com/kojix2/LibUI) Original Version:
|
3698
|
+
|
3699
|
+
```ruby
|
3700
|
+
# https://github.com/jamescook/libui-ruby/blob/master/example/histogram.rb
|
3701
|
+
|
3702
|
+
require 'libui'
|
3703
|
+
|
3704
|
+
UI = LibUI
|
3705
|
+
|
3706
|
+
X_OFF_LEFT = 20
|
3707
|
+
Y_OFF_TOP = 20
|
3708
|
+
X_OFF_RIGHT = 20
|
3709
|
+
Y_OFF_BOTTOM = 20
|
3710
|
+
POINT_RADIUS = 5
|
3711
|
+
|
3712
|
+
init = UI.init
|
3713
|
+
handler = UI::FFI::AreaHandler.malloc
|
3714
|
+
histogram = UI.new_area(handler)
|
3715
|
+
brush = UI::FFI::DrawBrush.malloc
|
3716
|
+
color_button = UI.new_color_button
|
3717
|
+
blue = 0x1E90FF
|
3718
|
+
datapoints = []
|
3719
|
+
|
3720
|
+
def graph_size(area_width, area_height)
|
3721
|
+
graph_width = area_width - X_OFF_LEFT - X_OFF_RIGHT
|
3722
|
+
graph_height = area_height - Y_OFF_TOP - Y_OFF_BOTTOM
|
3723
|
+
[graph_width, graph_height]
|
3724
|
+
end
|
3725
|
+
|
3726
|
+
matrix = UI::FFI::DrawMatrix.malloc
|
3727
|
+
|
3728
|
+
def point_locations(datapoints, width, height)
|
3729
|
+
xincr = width / 9.0 # 10 - 1 to make the last point be at the end
|
3730
|
+
yincr = height / 100.0
|
3731
|
+
|
3732
|
+
data = []
|
3733
|
+
datapoints.each_with_index do |dp, i|
|
3734
|
+
val = 100 - UI.spinbox_value(dp)
|
3735
|
+
data << [xincr * i, yincr * val]
|
3736
|
+
i += 1
|
3737
|
+
end
|
3738
|
+
|
3739
|
+
data
|
3740
|
+
end
|
3741
|
+
|
3742
|
+
def construct_graph(datapoints, width, height, should_extend)
|
3743
|
+
locations = point_locations(datapoints, width, height)
|
3744
|
+
path = UI.draw_new_path(0) # winding
|
3745
|
+
first_location = locations[0] # x and y
|
3746
|
+
UI.draw_path_new_figure(path, first_location[0], first_location[1])
|
3747
|
+
locations.each do |loc|
|
3748
|
+
UI.draw_path_line_to(path, loc[0], loc[1])
|
3749
|
+
end
|
3750
|
+
|
3751
|
+
if should_extend
|
3752
|
+
UI.draw_path_line_to(path, width, height)
|
3753
|
+
UI.draw_path_line_to(path, 0, height)
|
3754
|
+
UI.draw_path_close_figure(path)
|
3755
|
+
end
|
3756
|
+
|
3757
|
+
UI.draw_path_end(path)
|
3758
|
+
|
3759
|
+
path
|
3760
|
+
end
|
3761
|
+
|
3762
|
+
handler_draw_event = Fiddle::Closure::BlockCaller.new(
|
3763
|
+
0, [1, 1, 1]
|
3764
|
+
) do |_area_handler, _area, area_draw_params|
|
3765
|
+
area_draw_params = UI::FFI::AreaDrawParams.new(area_draw_params)
|
3766
|
+
path = UI.draw_new_path(0) # winding
|
3767
|
+
UI.draw_path_add_rectangle(path, 0, 0, area_draw_params.AreaWidth, area_draw_params.AreaHeight)
|
3768
|
+
UI.draw_path_end(path)
|
3769
|
+
set_solid_brush(brush, 0xFFFFFF, 1.0) # white
|
3770
|
+
UI.draw_fill(area_draw_params.Context, path, brush.to_ptr)
|
3771
|
+
UI.draw_free_path(path)
|
3772
|
+
dsp = UI::FFI::DrawStrokeParams.malloc
|
3773
|
+
dsp.Cap = 0 # flat
|
3774
|
+
dsp.Join = 0 # miter
|
3775
|
+
dsp.Thickness = 2
|
3776
|
+
dsp.MiterLimit = 10 # DEFAULT_MITER_LIMIT
|
3777
|
+
dashes = Fiddle::Pointer.malloc(8)
|
3778
|
+
dsp.Dashes = dashes
|
3779
|
+
dsp.NumDashes = 0
|
3780
|
+
dsp.DashPhase = 0
|
3781
|
+
|
3782
|
+
# draw axes
|
3783
|
+
set_solid_brush(brush, 0x000000, 1.0) # black
|
3784
|
+
graph_width, graph_height = *graph_size(area_draw_params.AreaWidth, area_draw_params.AreaHeight)
|
3785
|
+
|
3786
|
+
path = UI.draw_new_path(0) # winding
|
3787
|
+
UI.draw_path_new_figure(path, X_OFF_LEFT, Y_OFF_TOP)
|
3788
|
+
UI.draw_path_line_to(path, X_OFF_LEFT, Y_OFF_TOP + graph_height)
|
3789
|
+
UI.draw_path_line_to(path, X_OFF_LEFT + graph_width, Y_OFF_TOP + graph_height)
|
3790
|
+
UI.draw_path_end(path)
|
3791
|
+
UI.draw_stroke(area_draw_params.Context, path, brush, dsp)
|
3792
|
+
UI.draw_free_path(path)
|
3793
|
+
|
3794
|
+
# now transform the coordinate space so (0, 0) is the top-left corner of the graph
|
3795
|
+
UI.draw_matrix_set_identity(matrix)
|
3796
|
+
UI.draw_matrix_translate(matrix, X_OFF_LEFT, Y_OFF_TOP)
|
3797
|
+
UI.draw_transform(area_draw_params.Context, matrix)
|
3798
|
+
|
3799
|
+
# now get the color for the graph itself and set up the brush
|
3800
|
+
# uiColorButtonColor(colorButton, &graphR, &graphG, &graphB, &graphA)
|
3801
|
+
graph_r = Fiddle::Pointer.malloc(8) # double
|
3802
|
+
graph_g = Fiddle::Pointer.malloc(8) # double
|
3803
|
+
graph_b = Fiddle::Pointer.malloc(8) # double
|
3804
|
+
graph_a = Fiddle::Pointer.malloc(8) # double
|
3805
|
+
|
3806
|
+
UI.color_button_color(color_button, graph_r, graph_g, graph_b, graph_a)
|
3807
|
+
brush.Type = 0 # solid
|
3808
|
+
brush.R = graph_r[0, 8].unpack1('d')
|
3809
|
+
brush.G = graph_g[0, 8].unpack1('d')
|
3810
|
+
brush.B = graph_b[0, 8].unpack1('d')
|
3811
|
+
|
3812
|
+
# now create the fill for the graph below the graph line
|
3813
|
+
path = construct_graph(datapoints, graph_width, graph_height, true)
|
3814
|
+
brush.A = graph_a[0, 8].unpack1('d') / 2.0
|
3815
|
+
UI.draw_fill(area_draw_params.Context, path, brush)
|
3816
|
+
UI.draw_free_path(path)
|
3817
|
+
|
3818
|
+
# now draw the histogram line
|
3819
|
+
path = construct_graph(datapoints, graph_width, graph_height, false)
|
3820
|
+
brush.A = graph_a[0, 8].unpack1('d')
|
3821
|
+
UI.draw_stroke(area_draw_params.Context, path, brush, dsp)
|
3822
|
+
UI.draw_free_path(path)
|
3823
|
+
end
|
3824
|
+
|
3825
|
+
handler.Draw = handler_draw_event
|
3826
|
+
|
3827
|
+
# Assigning to local variables
|
3828
|
+
# This is intended to protect Fiddle::Closure from garbage collection.
|
3829
|
+
# See https://github.com/kojix2/LibUI/issues/8
|
3830
|
+
handler.MouseEvent = (c1 = Fiddle::Closure::BlockCaller.new(0, [0]) {})
|
3831
|
+
handler.MouseCrossed = (c2 = Fiddle::Closure::BlockCaller.new(0, [0]) {})
|
3832
|
+
handler.DragBroken = (c3 = Fiddle::Closure::BlockCaller.new(0, [0]) {})
|
3833
|
+
handler.KeyEvent = (c4 = Fiddle::Closure::BlockCaller.new(1, [0]) { 0 })
|
3834
|
+
|
3835
|
+
UI.freeInitError(init) unless init.nil?
|
3836
|
+
|
3837
|
+
hbox = UI.new_horizontal_box
|
3838
|
+
UI.box_set_padded(hbox, 1)
|
3839
|
+
|
3840
|
+
vbox = UI.new_vertical_box
|
3841
|
+
UI.box_set_padded(vbox, 1)
|
3842
|
+
UI.box_append(hbox, vbox, 0)
|
3843
|
+
UI.box_append(hbox, histogram, 1)
|
3844
|
+
|
3845
|
+
datapoints = Array.new(10) do
|
3846
|
+
UI.new_spinbox(0, 100).tap do |datapoint|
|
3847
|
+
UI.spinbox_set_value(datapoint, Random.new.rand(90))
|
3848
|
+
UI.spinbox_on_changed(datapoint) do
|
3849
|
+
UI.area_queue_redraw_all(histogram)
|
3850
|
+
end
|
3851
|
+
UI.box_append(vbox, datapoint, 0)
|
3852
|
+
end
|
3853
|
+
end
|
3854
|
+
|
3855
|
+
def set_solid_brush(brush, color, alpha)
|
3856
|
+
brush.Type = 0 # solid
|
3857
|
+
brush.R = ((color >> 16) & 0xFF) / 255.0
|
3858
|
+
brush.G = ((color >> 8) & 0xFF) / 255.0
|
3859
|
+
brush.B = (color & 0xFF) / 255.0
|
3860
|
+
brush.A = alpha
|
3861
|
+
brush
|
3862
|
+
end
|
3863
|
+
|
3864
|
+
set_solid_brush(brush, blue, 1.0)
|
3865
|
+
UI.color_button_set_color(color_button, brush.R, brush.G, brush.B, brush.A)
|
3866
|
+
|
3867
|
+
UI.color_button_on_changed(color_button) do
|
3868
|
+
UI.area_queue_redraw_all(histogram)
|
3869
|
+
end
|
3870
|
+
|
3871
|
+
UI.box_append(vbox, color_button, 0)
|
3872
|
+
|
3873
|
+
MAIN_WINDOW = UI.new_window('histogram example', 640, 480, 1)
|
3874
|
+
UI.window_set_margined(MAIN_WINDOW, 1)
|
3875
|
+
UI.window_set_child(MAIN_WINDOW, hbox)
|
3876
|
+
|
3877
|
+
should_quit = proc do |_ptr|
|
3878
|
+
UI.control_destroy(MAIN_WINDOW)
|
3879
|
+
UI.quit
|
3880
|
+
0
|
3881
|
+
end
|
3882
|
+
|
3883
|
+
UI.window_on_closing(MAIN_WINDOW, should_quit)
|
3884
|
+
UI.on_should_quit(should_quit)
|
3885
|
+
UI.control_show(MAIN_WINDOW)
|
3886
|
+
|
3887
|
+
UI.main
|
3888
|
+
UI.quit
|
3889
|
+
```
|
3890
|
+
|
3891
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
3892
|
+
|
3893
|
+
```ruby
|
3894
|
+
# https://github.com/jamescook/libui-ruby/blob/master/example/histogram.rb
|
3895
|
+
|
3896
|
+
require 'glimmer-dsl-libui'
|
3897
|
+
|
3898
|
+
include Glimmer
|
3899
|
+
|
3900
|
+
X_OFF_LEFT = 20
|
3901
|
+
Y_OFF_TOP = 20
|
3902
|
+
X_OFF_RIGHT = 20
|
3903
|
+
Y_OFF_BOTTOM = 20
|
3904
|
+
POINT_RADIUS = 5
|
3905
|
+
COLOR_BLUE = 0x1E90FF
|
3906
|
+
|
3907
|
+
@datapoints = 10.times.map {Random.new.rand(90)}
|
3908
|
+
|
3909
|
+
def graph_size(area_width, area_height)
|
3910
|
+
graph_width = area_width - X_OFF_LEFT - X_OFF_RIGHT
|
3911
|
+
graph_height = area_height - Y_OFF_TOP - Y_OFF_BOTTOM
|
3912
|
+
[graph_width, graph_height]
|
3913
|
+
end
|
3914
|
+
|
3915
|
+
def point_locations(width, height)
|
3916
|
+
xincr = width / 9.0 # 10 - 1 to make the last point be at the end
|
3917
|
+
yincr = height / 100.0
|
3918
|
+
|
3919
|
+
@datapoints.each_with_index.map do |value, i|
|
3920
|
+
val = 100 - value
|
3921
|
+
[xincr * i, yincr * val]
|
3922
|
+
end
|
3923
|
+
end
|
3924
|
+
|
3925
|
+
# method-based custom control representing a graph path
|
3926
|
+
def graph_path(width, height, should_extend, &block)
|
3927
|
+
locations = point_locations(width, height)
|
3928
|
+
path {
|
3929
|
+
first_location = locations[0] # x and y
|
3930
|
+
figure(first_location[0], first_location[1]) {
|
3931
|
+
locations.each do |loc|
|
3932
|
+
line(loc[0], loc[1])
|
3933
|
+
end
|
3934
|
+
if should_extend
|
3935
|
+
line(width, height)
|
3936
|
+
line(0, height)
|
3937
|
+
|
3938
|
+
closed true
|
3939
|
+
end
|
3940
|
+
}
|
3941
|
+
|
3942
|
+
# apply a transform to the coordinate space for this path so (0, 0) is the top-left corner of the graph
|
3943
|
+
transform {
|
3944
|
+
translate X_OFF_LEFT, Y_OFF_TOP
|
3945
|
+
}
|
3946
|
+
|
3947
|
+
block.call
|
3948
|
+
}
|
3949
|
+
end
|
3950
|
+
|
3951
|
+
window('histogram example', 640, 480) {
|
3952
|
+
margined true
|
3953
|
+
|
3954
|
+
horizontal_box {
|
3955
|
+
vertical_box {
|
3956
|
+
stretchy false
|
3957
|
+
|
3958
|
+
10.times do |i|
|
3959
|
+
spinbox(0, 100) { |sb|
|
3960
|
+
stretchy false
|
3961
|
+
value @datapoints[i]
|
3962
|
+
|
3963
|
+
on_changed do
|
3964
|
+
@datapoints[i] = sb.value
|
3965
|
+
@area.queue_redraw_all
|
3966
|
+
end
|
3967
|
+
}
|
3968
|
+
end
|
3969
|
+
|
3970
|
+
@color_button = color_button {
|
3971
|
+
stretchy false
|
3972
|
+
color COLOR_BLUE
|
3973
|
+
|
3974
|
+
on_changed do
|
3975
|
+
@area.queue_redraw_all
|
3976
|
+
end
|
3977
|
+
}
|
3978
|
+
}
|
3979
|
+
|
3980
|
+
@area = area {
|
3981
|
+
on_draw do |area_draw_params|
|
3982
|
+
path {
|
3983
|
+
rectangle(0, 0, area_draw_params[:area_width], area_draw_params[:area_height])
|
3984
|
+
|
3985
|
+
fill 0xFFFFFF
|
3986
|
+
}
|
3987
|
+
|
3988
|
+
graph_width, graph_height = *graph_size(area_draw_params[:area_width], area_draw_params[:area_height])
|
3989
|
+
|
3990
|
+
path {
|
3991
|
+
figure(X_OFF_LEFT, Y_OFF_TOP) {
|
3992
|
+
line(X_OFF_LEFT, Y_OFF_TOP + graph_height)
|
3993
|
+
line(X_OFF_LEFT + graph_width, Y_OFF_TOP + graph_height)
|
3994
|
+
}
|
3995
|
+
|
3996
|
+
stroke 0x000000, thickness: 2, miter_limit: 10
|
3997
|
+
}
|
3998
|
+
|
3999
|
+
# now create the fill for the graph below the graph line
|
4000
|
+
graph_path(graph_width, graph_height, true) {
|
4001
|
+
fill @color_button.color.merge(a: 0.5)
|
4002
|
+
}
|
4003
|
+
|
4004
|
+
# now draw the histogram line
|
4005
|
+
graph_path(graph_width, graph_height, false) {
|
4006
|
+
stroke @color_button.color.merge(thickness: 2, miter_limit: 10)
|
4007
|
+
}
|
4008
|
+
end
|
4009
|
+
}
|
4010
|
+
}
|
4011
|
+
}.show
|
4012
|
+
```
|
4013
|
+
|
4014
|
+
### Basic Transform
|
4015
|
+
|
4016
|
+
[examples/basic_transform.rb](examples/basic_transform.rb)
|
4017
|
+
|
4018
|
+
Run with this command from the root of the project if you cloned the project:
|
4019
|
+
|
4020
|
+
```
|
4021
|
+
ruby -r './lib/glimmer-dsl-libui' examples/basic_transform.rb
|
4022
|
+
```
|
4023
|
+
|
4024
|
+
Run with this command if you installed the [Ruby gem](https://rubygems.org/gems/glimmer-dsl-libui):
|
4025
|
+
|
4026
|
+
```
|
4027
|
+
ruby -r glimmer-dsl-libui -e "require 'examples/basic_transform'"
|
4028
|
+
```
|
4029
|
+
|
4030
|
+
Mac
|
4031
|
+
|
4032
|
+
![glimmer-dsl-libui-mac-basic-transform.png](images/glimmer-dsl-libui-mac-basic-transform.png)
|
4033
|
+
|
4034
|
+
Linux
|
4035
|
+
|
4036
|
+
![glimmer-dsl-libui-linux-basic-transform.png](images/glimmer-dsl-libui-linux-basic-transform.png)
|
4037
|
+
|
4038
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
4039
|
+
|
4040
|
+
```ruby
|
4041
|
+
require 'glimmer-dsl-libui'
|
4042
|
+
|
4043
|
+
include Glimmer
|
4044
|
+
|
4045
|
+
window('Basic Transform', 350, 350) {
|
4046
|
+
area {
|
4047
|
+
path {
|
4048
|
+
square(0, 0, 350)
|
4049
|
+
|
4050
|
+
fill r: 255, g: 255, b: 0
|
4051
|
+
}
|
4052
|
+
40.times do |n|
|
4053
|
+
path {
|
4054
|
+
square(0, 0, 100)
|
4055
|
+
|
4056
|
+
fill r: [255 - n*5, 0].max, g: [n*5, 255].min, b: 0, a: 0.5
|
4057
|
+
stroke :black, thickness: 2
|
4058
|
+
transform {
|
4059
|
+
skew 0.15, 0.15
|
4060
|
+
translate 50, 50
|
4061
|
+
rotate 100, 100, -9 * n
|
4062
|
+
scale 1.1, 1.1
|
4063
|
+
}
|
4064
|
+
}
|
4065
|
+
end
|
4066
|
+
}
|
4067
|
+
}.show
|
4068
|
+
```
|
4069
|
+
|
3008
4070
|
## Contributing to glimmer-dsl-libui
|
3009
4071
|
|
3010
4072
|
- Check out the latest master to make sure the feature hasn't been
|