glimmer-dsl-libui 0.1.3 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +50 -0
- data/README.md +901 -104
- data/VERSION +1 -1
- data/examples/area_gallery.rb +36 -38
- 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 +0 -2
- data/lib/glimmer/dsl/libui/file_expression.rb +5 -1
- data/lib/glimmer/dsl/libui/shape_expression.rb +2 -4
- 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/{horizontal_box_proxy.rb → control_proxy/box/vertical_box_proxy.rb} +10 -6
- data/lib/glimmer/libui/{box.rb → control_proxy/box.rb} +31 -27
- 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/control_proxy/column/progress_bar_column_proxy.rb +44 -0
- data/lib/glimmer/libui/{checkbox_column_proxy.rb → control_proxy/column/text_column_proxy.rb} +17 -13
- data/lib/glimmer/libui/control_proxy/column.rb +55 -0
- data/lib/glimmer/libui/control_proxy/combobox_proxy.rb +45 -0
- 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/{date_picker_proxy.rb → control_proxy/menu_item_proxy/preferences_menu_item_proxy.rb} +10 -10
- data/lib/glimmer/libui/{quit_menu_item_proxy.rb → control_proxy/menu_item_proxy/quit_menu_item_proxy.rb} +33 -29
- 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/{vertical_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/{time_picker_proxy.rb → control_proxy/message_box.rb} +9 -10
- data/lib/glimmer/libui/{rectangle.rb → control_proxy/multiline_entry_proxy/non_wrapping_multiline_entry_proxy.rb} +6 -7
- data/lib/glimmer/libui/{progress_bar_column_proxy.rb → control_proxy/multiline_entry_proxy.rb} +10 -11
- data/lib/glimmer/libui/control_proxy/path_proxy.rb +190 -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 +39 -20
- data/lib/glimmer/libui/{enableable_column.rb → parent.rb} +7 -15
- data/lib/glimmer/libui/{arc.rb → shape/arc.rb} +13 -10
- data/lib/glimmer/libui/shape/bezier.rb +38 -0
- data/lib/glimmer/libui/{figure.rb → shape/figure.rb} +23 -20
- data/lib/glimmer/libui/{line.rb → shape/line.rb} +9 -6
- data/lib/glimmer/libui/{bezier.rb → shape/rectangle.rb} +9 -6
- data/lib/glimmer/libui/{square.rb → shape/square.rb} +9 -6
- data/lib/glimmer/libui/shape.rb +30 -14
- data/lib/glimmer/libui.rb +92 -0
- data/lib/glimmer-dsl-libui.rb +2 -0
- metadata +79 -53
- data/lib/glimmer/libui/about_menu_item_proxy.rb +0 -37
- data/lib/glimmer/libui/area_proxy.rb +0 -105
- data/lib/glimmer/libui/check_menu_item_proxy.rb +0 -37
- 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_column_proxy.rb +0 -40
- 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/non_wrapping_multiline_entry_proxy.rb +0 -32
- data/lib/glimmer/libui/path_proxy.rb +0 -169
- data/lib/glimmer/libui/preferences_menu_item_proxy.rb +0 -37
- 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.7
|
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)
|
@@ -47,13 +47,23 @@ data = [
|
|
47
47
|
['task 5', -1],
|
48
48
|
]
|
49
49
|
|
50
|
-
window('Task
|
51
|
-
|
50
|
+
window('Task Progress', 300, 200) {
|
51
|
+
vertical_box {
|
52
52
|
table {
|
53
53
|
text_column('Task')
|
54
54
|
progress_bar_column('Progress')
|
55
55
|
|
56
|
-
cell_rows data
|
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
|
57
67
|
}
|
58
68
|
}
|
59
69
|
}.show
|
@@ -70,50 +80,48 @@ require 'glimmer-dsl-libui'
|
|
70
80
|
include Glimmer
|
71
81
|
|
72
82
|
window('Area Gallery', 400, 400) {
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
line(400, 400)
|
92
|
-
|
93
|
-
closed true
|
94
|
-
}
|
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)
|
95
101
|
|
96
|
-
|
97
|
-
stroke thickness: 1, r: 0, g: 0, b: 0
|
102
|
+
closed true
|
98
103
|
}
|
99
|
-
path { # declarative stable path
|
100
|
-
figure(0, 0) {
|
101
|
-
bezier(200, 100, 100, 200, 400, 100)
|
102
|
-
bezier(300, 100, 100, 300, 100, 400)
|
103
|
-
bezier(100, 300, 300, 100, 400, 400)
|
104
104
|
|
105
|
-
|
106
|
-
|
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)
|
107
113
|
|
108
|
-
|
109
|
-
stroke thickness: 2, r: 0, g: 0, b: 0
|
114
|
+
closed true
|
110
115
|
}
|
111
|
-
path { # declarative stable path
|
112
|
-
arc(200, 200, 90, 0, 360, false)
|
113
116
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
118
|
+
stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.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 r: 0, g: 0, b: 0, thickness: 2
|
117
125
|
}
|
118
126
|
}
|
119
127
|
}.show
|
@@ -135,7 +143,7 @@ Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interes
|
|
135
143
|
|
136
144
|
## Table of Contents
|
137
145
|
|
138
|
-
- [Glimmer DSL for LibUI 0.1.
|
146
|
+
- [Glimmer DSL for LibUI 0.1.7](#-glimmer-dsl-for-libui-017)
|
139
147
|
- [Glimmer GUI DSL Concepts](#glimmer-gui-dsl-concepts)
|
140
148
|
- [Usage](#usage)
|
141
149
|
- [Girb (Glimmer IRB)](#girb-glimmer-irb)
|
@@ -176,6 +184,8 @@ Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interes
|
|
176
184
|
- [Basic Area](#basic-area)
|
177
185
|
- [Dynamic Area](#dynamic-area)
|
178
186
|
- [Area Gallery](#area-gallery)
|
187
|
+
- [Histogram](#histogram)
|
188
|
+
- [Basic Transform](#basic-transform)
|
179
189
|
- [Contributing to glimmer-dsl-libui](#contributing-to-glimmer-dsl-libui)
|
180
190
|
- [Help](#help)
|
181
191
|
- [Issues](#issues)
|
@@ -239,10 +249,10 @@ require 'glimmer-dsl-libui'
|
|
239
249
|
|
240
250
|
include Glimmer
|
241
251
|
|
242
|
-
window('hello world', 300, 200) {
|
252
|
+
window('hello world', 300, 200) {
|
243
253
|
button('Button') {
|
244
254
|
on_clicked do
|
245
|
-
msg_box(
|
255
|
+
msg_box('Information', 'You clicked the button')
|
246
256
|
end
|
247
257
|
}
|
248
258
|
|
@@ -263,7 +273,7 @@ gem install glimmer-dsl-libui
|
|
263
273
|
Or install via Bundler `Gemfile`:
|
264
274
|
|
265
275
|
```ruby
|
266
|
-
gem 'glimmer-dsl-libui', '~> 0.1.
|
276
|
+
gem 'glimmer-dsl-libui', '~> 0.1.7'
|
267
277
|
```
|
268
278
|
|
269
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.
|
@@ -351,7 +361,7 @@ Control(Args) | Properties | Listeners
|
|
351
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`
|
352
362
|
`editable_combobox` | `items` (`Array` of `String`), `text` (`String`) | `on_changed`
|
353
363
|
`entry` | `read_only` (Boolean), `text` (`String`) | `on_changed`
|
354
|
-
`figure(x as Numeric, y as Numeric)` | `x` (`Numeric`), `y` (`Numeric`), `closed` (Boolean) | None
|
364
|
+
`figure(x=nil as Numeric, y=nil as Numeric)` | `x` (`Numeric`), `y` (`Numeric`), `closed` (Boolean) | None
|
355
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`
|
356
366
|
`form` | `padded` (Boolean) | None
|
357
367
|
`grid` | `padded` (Boolean) | None
|
@@ -364,13 +374,14 @@ Control(Args) | Properties | Listeners
|
|
364
374
|
`image_text_column(name as String)` | None | None
|
365
375
|
`label(text as String)` | `text` (`String`) | None
|
366
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
|
367
378
|
`menu(text as String)` | None | None
|
368
379
|
`menu_item(text as String)` | `checked` (Boolean) | `on_clicked`
|
369
380
|
`multiline_entry` | `read_only` (Boolean), `text` (`String`) | `on_changed`
|
370
|
-
`msg_box(window as Glimmer::LibUI::WindowProxy, title as String, description as String)` | None | None
|
371
|
-
`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
|
372
383
|
`non_wrapping_multiline_entry` | `read_only` (Boolean), `text` (`String`) | `on_changed`
|
373
|
-
`path` | `fill` (`Hash` of `:r` as `0`-`255`, `:g` as `0`-`255`, `:b` as `0`-`255`, `:a` as `0.0`-`1.0`), `stroke` (`Hash` of `:r` as `0`-`255`, `:g` as `0`-`255`, `:b` as `0`-`255`, `:a` as `0.0`-`1.0`, `:cap` as
|
384
|
+
`path(draw_fill_mode = :winding)` | `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 (`:round`, `:square`, `:flat`), `:join` as (`:miter`, `:round`, `:bevel`), `:thickness` as `Numeric`, `:miter_limit` as `Numeric`, `:dashes` as `Array` of `Numeric` ) | None
|
374
385
|
`preferences_menu_item` | None | `on_clicked`
|
375
386
|
`progress_bar` | `value` (`Numeric`) | None
|
376
387
|
`progress_bar_column(name as String)` | None | None
|
@@ -384,7 +395,7 @@ Control(Args) | Properties | Listeners
|
|
384
395
|
`tab_item(name as String)` | `index` [read-only] (`Integer`), `margined` (Boolean), `name` [read-only] (`String`) | None
|
385
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
|
386
397
|
`text_column(name as String)` | `editable` (Boolean) | None
|
387
|
-
`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`
|
388
399
|
`vertical_box` | `padded` (Boolean) | None
|
389
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`
|
390
401
|
|
@@ -520,9 +531,9 @@ Learn more by checking out [examples](#examples).
|
|
520
531
|
|
521
532
|
### Area API
|
522
533
|
|
523
|
-
The `area` control can be used in one of two ways:
|
524
|
-
- Declaratively via stable paths: useful for stable paths that will not change later on. Simply nest `path` and figures like `rectangle` and all drawing logic is generated automatically.
|
525
|
-
- Semi-declaratively via on_draw listener dynamic paths: useful for more dynamic paths that will definitely change. Open an `on_draw` listener block and nest `path
|
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.
|
526
537
|
|
527
538
|
Here is an example of a declarative `area` with a stable path (you may copy/paste in [`girb`](#girb-glimmer-irb)):
|
528
539
|
|
@@ -548,7 +559,7 @@ window('Basic Area', 400, 400) {
|
|
548
559
|
|
549
560
|
![glimmer-dsl-libui-mac-basic-area.png](images/glimmer-dsl-libui-mac-basic-area.png)
|
550
561
|
|
551
|
-
Here is the same example using a semi-declarative `area` with `on_draw` listener and a dynamic path (you may copy/paste in [`girb`](#girb-glimmer-irb)):
|
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)):
|
552
563
|
|
553
564
|
```ruby
|
554
565
|
require 'glimmer-dsl-libui'
|
@@ -561,7 +572,7 @@ window('Basic Area', 400, 400) {
|
|
561
572
|
vertical_box {
|
562
573
|
area {
|
563
574
|
on_draw do |area_draw_params|
|
564
|
-
path
|
575
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
565
576
|
rectangle(0, 0, 400, 400)
|
566
577
|
|
567
578
|
fill r: 102, g: 102, b: 204, a: 1.0
|
@@ -574,24 +585,110 @@ window('Basic Area', 400, 400) {
|
|
574
585
|
|
575
586
|
Check [examples/dynamic_area.rb](#dynamic-area) for a more detailed semi-declarative example.
|
576
587
|
|
588
|
+
`path` can receive a `draw_fill_mode` argument that can accept values `:winding` or `:alternate` and defaults to `:winding`.
|
589
|
+
|
577
590
|
Available nested `path` shapes:
|
578
591
|
- `rectangle(x as Numeric, y as Numeric, width as Numeric, height as Numeric)`
|
579
592
|
- `square(x as Numeric, y as Numeric, length as Numeric)`
|
580
593
|
- `arc(x_center as Numeric, y_center as Numeric, radius as Numeric, start_angle as Numeric, sweep as Numeric, is_negative as Boolean)`
|
581
594
|
- `line(x as Numeric, y as Numeric)`
|
582
595
|
- `bezier(c1_x as Numeric, c1_y as Numeric, c2_x as Numeric, c2_y as Numeric, end_x as Numeric, end_y as Numeric)`
|
583
|
-
- `figure(x as Numeric, y as Numeric)` (composite that can contain other shapes) (can set `closed true` to connect last point to first point automatically)
|
596
|
+
- `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)
|
597
|
+
|
598
|
+
Check [examples/area_gallery.rb](#area-gallery) for an overiew of all `path` shapes.
|
584
599
|
|
585
|
-
|
600
|
+
The `area_draw_params` argument for `on_draw` block is a hash consisting of the following keys:
|
601
|
+
- `:context`: the drawing context object
|
602
|
+
- `:area_width`: area width
|
603
|
+
- `:area_height`: area height
|
604
|
+
- `:clip_x`: clip region top-left x coordinate
|
605
|
+
- `:clip_y`: clip region top-left y coordinate
|
606
|
+
- `:clip_width`: clip region width
|
607
|
+
- `:clip_height`: clip region height
|
586
608
|
|
587
|
-
|
609
|
+
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.
|
610
|
+
|
611
|
+
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.
|
612
|
+
|
613
|
+
To redraw an `area`, you may call the `#queue_redraw_all` method, or simply `#redraw`.
|
614
|
+
|
615
|
+
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.
|
616
|
+
|
617
|
+
When instantiating a `matrix` object, it always starts with identity matrix.
|
618
|
+
|
619
|
+
Here are the following operations that can be performed in a `matrix` body:
|
620
|
+
- `identity` [alias: `set_identity`]: resets matrix to identity matrix
|
621
|
+
- `translate(x as Numeric, y as Numeric)`
|
622
|
+
- `scale(x_center = 0 as Numeric, y_center = 0 as Numeric, x as Numeric, y as Numeric)`
|
623
|
+
- `skew(x = 0 as Numeric, y = 0 as Numeric, x_amount as Numeric, y_amount as Numeric)`
|
624
|
+
- `rotate(x = 0 as Numeric, y = 0 as Numeric, degrees as Numeric)`
|
625
|
+
|
626
|
+
Example of using transform matrix (you may copy/paste in [`girb`](#girb-glimmer-irb)):
|
627
|
+
|
628
|
+
```ruby
|
629
|
+
require 'glimmer-dsl-libui'
|
630
|
+
|
631
|
+
include Glimmer
|
632
|
+
|
633
|
+
window('Basic Transform', 350, 350) {
|
634
|
+
area {
|
635
|
+
path {
|
636
|
+
square(0, 0, 350)
|
637
|
+
|
638
|
+
fill r: 255, g: 255, b: 0
|
639
|
+
}
|
640
|
+
40.times do |n|
|
641
|
+
path {
|
642
|
+
square(0, 0, 100)
|
643
|
+
|
644
|
+
fill r: [255 - n*5, 0].max, g: [n*5, 255].min, b: 0, a: 0.5
|
645
|
+
stroke :black, thickness: 2
|
646
|
+
transform {
|
647
|
+
skew 0.15, 0.15
|
648
|
+
translate 50, 50
|
649
|
+
rotate 100, 100, -9 * n
|
650
|
+
scale 1.1, 1.1
|
651
|
+
}
|
652
|
+
}
|
653
|
+
end
|
654
|
+
}
|
655
|
+
}.show
|
656
|
+
```
|
657
|
+
|
658
|
+
Keep in mind that this part could be written differently when there is a need to reuse the matrix:
|
659
|
+
|
660
|
+
```ruby
|
661
|
+
transform {
|
662
|
+
translate 100, 100
|
663
|
+
rotate 100, 100, -9 * n
|
664
|
+
}
|
665
|
+
```
|
666
|
+
|
667
|
+
Alternatively:
|
668
|
+
|
669
|
+
```ruby
|
670
|
+
m1 = matrix {
|
671
|
+
translate 100, 100
|
672
|
+
rotate 100, 100, -9 * n
|
673
|
+
}
|
674
|
+
transform m1
|
675
|
+
# and then reuse m1 elsewhere too
|
676
|
+
```
|
677
|
+
|
678
|
+
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.
|
679
|
+
|
680
|
+
`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)
|
681
|
+
|
682
|
+
Check [Basic Transform](#basic-transform) example for use of [X11](https://en.wikipedia.org/wiki/X11_color_names) colors.
|
683
|
+
|
684
|
+
Check [Histogram](#histogram) example for use of hex colors.
|
588
685
|
|
589
686
|
### Smart Defaults and Conventions
|
590
687
|
|
591
688
|
- `horizontal_box`, `vertical_box`, `grid`, and `form` controls have `padded` as `true` upon instantiation to ensure more user-friendly GUI by default
|
592
689
|
- `group` controls have `margined` as `true` upon instantiation to ensure more user-friendly GUI by default
|
593
690
|
- 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)
|
594
|
-
- `window` instatiation args can be left off, having the following defaults when unspecified: `title` as `''`, `width` as `
|
691
|
+
- `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`)
|
595
692
|
- `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)
|
596
693
|
- `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'; ...}`)
|
597
694
|
- `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'}}`)
|
@@ -617,11 +714,17 @@ To redraw an `area`, you may call `#queue_redraw_all` method.
|
|
617
714
|
- `area` paths are specified declaratively with figures underneath (e.g. `rectangle`) and `area` draw listener is automatically generated
|
618
715
|
- Observe figure properties (e.g. `rectangle` `width`) for changes and automatically redraw containing area accordingly
|
619
716
|
- Observe `path` `fill` and `stroke` hashes for changes and automatically redraw containing area accordingly
|
717
|
+
- All controls are protected from garbage collection until no longer needed (explicitly destroyed), so there is no need to worry about surprises.
|
718
|
+
- All resources are freed automatically once no longer needed or left to garbage collection.
|
719
|
+
- 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.
|
720
|
+
- 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)
|
721
|
+
- Color alpha value defaults to `1.0` when not specified.
|
620
722
|
|
621
723
|
### API Gotchas
|
622
724
|
|
623
725
|
- 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`).
|
624
726
|
- `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).
|
727
|
+
- 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.
|
625
728
|
|
626
729
|
### Original API
|
627
730
|
|
@@ -693,7 +796,7 @@ class MetaExample
|
|
693
796
|
end
|
694
797
|
|
695
798
|
def launch
|
696
|
-
window('Meta-Example', 700, 500) {
|
799
|
+
window('Meta-Example', 700, 500) {
|
697
800
|
margined true
|
698
801
|
|
699
802
|
horizontal_box {
|
@@ -715,7 +818,7 @@ class MetaExample
|
|
715
818
|
meta_example_file = File.join(Dir.home, '.meta_example.rb')
|
716
819
|
File.write(meta_example_file, @nwme.text)
|
717
820
|
result = `ruby -r #{glimmer_dsl_libui_file} #{meta_example_file} 2>&1`
|
718
|
-
msg_box(
|
821
|
+
msg_box('Error Running Example', result) if result.include?('error')
|
719
822
|
rescue => e
|
720
823
|
puts 'Unable to write code changes! Running original example...'
|
721
824
|
system "ruby -r #{glimmer_dsl_libui_file} #{file_path_for(@examples[@rbs.selected])}"
|
@@ -799,7 +902,7 @@ window('hello world', 300, 200, true) {
|
|
799
902
|
}.show
|
800
903
|
```
|
801
904
|
|
802
|
-
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2:
|
905
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (setting `window` properties instead of arguments):
|
803
906
|
|
804
907
|
```ruby
|
805
908
|
require 'glimmer-dsl-libui'
|
@@ -880,10 +983,10 @@ require 'glimmer-dsl-libui'
|
|
880
983
|
|
881
984
|
include Glimmer
|
882
985
|
|
883
|
-
window('hello world', 300, 200) {
|
986
|
+
window('hello world', 300, 200) {
|
884
987
|
button('Button') {
|
885
988
|
on_clicked do
|
886
|
-
msg_box(
|
989
|
+
msg_box('Information', 'You clicked the button')
|
887
990
|
end
|
888
991
|
}
|
889
992
|
|
@@ -967,7 +1070,7 @@ require 'glimmer-dsl-libui'
|
|
967
1070
|
|
968
1071
|
include Glimmer
|
969
1072
|
|
970
|
-
window('Basic Entry', 300, 50) {
|
1073
|
+
window('Basic Entry', 300, 50) {
|
971
1074
|
horizontal_box {
|
972
1075
|
e = entry {
|
973
1076
|
# stretchy true # Smart default option for appending to horizontal_box
|
@@ -983,7 +1086,7 @@ window('Basic Entry', 300, 50) { |w|
|
|
983
1086
|
|
984
1087
|
on_clicked do
|
985
1088
|
text = e.text
|
986
|
-
msg_box(
|
1089
|
+
msg_box('You entered', text)
|
987
1090
|
end
|
988
1091
|
}
|
989
1092
|
}
|
@@ -1087,12 +1190,12 @@ ruby -r glimmer-dsl-libui -e "require 'examples/midi_player'"
|
|
1087
1190
|
Mac
|
1088
1191
|
|
1089
1192
|
![glimmer-dsl-libui-mac-midi-player.png](images/glimmer-dsl-libui-mac-midi-player.png)
|
1090
|
-
![glimmer-dsl-libui-mac-midi-player-
|
1193
|
+
![glimmer-dsl-libui-mac-midi-player-msg-box.png](images/glimmer-dsl-libui-mac-midi-player-msg-box.png)
|
1091
1194
|
|
1092
1195
|
Linux
|
1093
1196
|
|
1094
1197
|
![glimmer-dsl-libui-linux-midi-player.png](images/glimmer-dsl-libui-linux-midi-player.png)
|
1095
|
-
![glimmer-dsl-libui-linux-midi-player-
|
1198
|
+
![glimmer-dsl-libui-linux-midi-player-msg-box.png](images/glimmer-dsl-libui-linux-midi-player-msg-box.png)
|
1096
1199
|
|
1097
1200
|
[LibUI](https://github.com/kojix2/LibUI) Original Version:
|
1098
1201
|
|
@@ -1238,23 +1341,22 @@ class TinyMidiPlayer
|
|
1238
1341
|
end
|
1239
1342
|
end
|
1240
1343
|
|
1241
|
-
def show_version
|
1242
|
-
msg_box(
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1246
|
-
"Version #{VERSION}")
|
1344
|
+
def show_version
|
1345
|
+
msg_box('Tiny Midi Player',
|
1346
|
+
"Written in Ruby\n" \
|
1347
|
+
"https://github.com/kojix2/libui\n" \
|
1348
|
+
"Version #{VERSION}")
|
1247
1349
|
end
|
1248
1350
|
|
1249
1351
|
def create_gui
|
1250
1352
|
menu('Help') { |m|
|
1251
1353
|
menu_item('Version') {
|
1252
1354
|
on_clicked do
|
1253
|
-
show_version
|
1355
|
+
show_version
|
1254
1356
|
end
|
1255
1357
|
}
|
1256
1358
|
}
|
1257
|
-
|
1359
|
+
window('Tiny Midi Player', 200, 50) {
|
1258
1360
|
horizontal_box {
|
1259
1361
|
vertical_box {
|
1260
1362
|
stretchy false
|
@@ -1270,7 +1372,7 @@ class TinyMidiPlayer
|
|
1270
1372
|
end
|
1271
1373
|
}
|
1272
1374
|
}
|
1273
|
-
|
1375
|
+
|
1274
1376
|
combobox { |c|
|
1275
1377
|
items @midi_files.map { |path| File.basename(path) }
|
1276
1378
|
|
@@ -1280,8 +1382,7 @@ class TinyMidiPlayer
|
|
1280
1382
|
end
|
1281
1383
|
}
|
1282
1384
|
}
|
1283
|
-
}
|
1284
|
-
@main_window.show
|
1385
|
+
}.show
|
1285
1386
|
end
|
1286
1387
|
end
|
1287
1388
|
|
@@ -1517,14 +1618,14 @@ include Glimmer
|
|
1517
1618
|
menu('File') {
|
1518
1619
|
menu_item('Open') {
|
1519
1620
|
on_clicked do
|
1520
|
-
file = open_file
|
1621
|
+
file = open_file
|
1521
1622
|
puts file unless file.nil?
|
1522
1623
|
end
|
1523
1624
|
}
|
1524
1625
|
|
1525
1626
|
menu_item('Save') {
|
1526
1627
|
on_clicked do
|
1527
|
-
file = save_file
|
1628
|
+
file = save_file
|
1528
1629
|
puts file unless file.nil?
|
1529
1630
|
end
|
1530
1631
|
}
|
@@ -1567,7 +1668,7 @@ MAIN_WINDOW = window('Control Gallery', 600, 500) {
|
|
1567
1668
|
stretchy false
|
1568
1669
|
|
1569
1670
|
on_clicked do
|
1570
|
-
msg_box(
|
1671
|
+
msg_box('Information', 'You clicked the button')
|
1571
1672
|
end
|
1572
1673
|
}
|
1573
1674
|
|
@@ -1575,7 +1676,7 @@ MAIN_WINDOW = window('Control Gallery', 600, 500) {
|
|
1575
1676
|
stretchy false
|
1576
1677
|
|
1577
1678
|
on_toggled do |c|
|
1578
|
-
checked = c.checked
|
1679
|
+
checked = c.checked?
|
1579
1680
|
MAIN_WINDOW.title = "Checkbox is #{checked}"
|
1580
1681
|
c.text = "I am the checkbox (#{checked})"
|
1581
1682
|
end
|
@@ -2029,7 +2130,7 @@ require 'glimmer-dsl-libui'
|
|
2029
2130
|
|
2030
2131
|
include Glimmer
|
2031
2132
|
|
2032
|
-
window('Form') {
|
2133
|
+
window('Form') {
|
2033
2134
|
margined true
|
2034
2135
|
|
2035
2136
|
vertical_box {
|
@@ -2045,7 +2146,7 @@ window('Form') { |w|
|
|
2045
2146
|
|
2046
2147
|
button('Display Name') {
|
2047
2148
|
on_clicked do
|
2048
|
-
msg_box(
|
2149
|
+
msg_box('Name', "#{@first_name_entry.text} #{@last_name_entry.text}")
|
2049
2150
|
end
|
2050
2151
|
}
|
2051
2152
|
}
|
@@ -2729,13 +2830,23 @@ data = [
|
|
2729
2830
|
['task 5', -1],
|
2730
2831
|
]
|
2731
2832
|
|
2732
|
-
window('Task
|
2733
|
-
|
2833
|
+
window('Task Progress', 300, 200) {
|
2834
|
+
vertical_box {
|
2734
2835
|
table {
|
2735
2836
|
text_column('Task')
|
2736
2837
|
progress_bar_column('Progress')
|
2737
2838
|
|
2738
|
-
cell_rows data
|
2839
|
+
cell_rows data # implicit data-binding
|
2840
|
+
}
|
2841
|
+
|
2842
|
+
button('Mark All As Done') {
|
2843
|
+
stretchy false
|
2844
|
+
|
2845
|
+
on_clicked do
|
2846
|
+
data.each_with_index do |row_data, row|
|
2847
|
+
data[row] = [row_data[0], 100] # automatically updates table due to implicit data-binding
|
2848
|
+
end
|
2849
|
+
end
|
2739
2850
|
}
|
2740
2851
|
}
|
2741
2852
|
}.show
|
@@ -2935,7 +3046,7 @@ window('Basic Area', 400, 400) {
|
|
2935
3046
|
}.show
|
2936
3047
|
```
|
2937
3048
|
|
2938
|
-
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2:
|
3049
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (semi-declarative `on_draw` dynamic `path` approach):
|
2939
3050
|
|
2940
3051
|
```ruby
|
2941
3052
|
require 'glimmer-dsl-libui'
|
@@ -2948,7 +3059,7 @@ window('Basic Area', 400, 400) {
|
|
2948
3059
|
vertical_box {
|
2949
3060
|
area {
|
2950
3061
|
on_draw do |area_draw_params|
|
2951
|
-
path
|
3062
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
2952
3063
|
rectangle(0, 0, 400, 400)
|
2953
3064
|
|
2954
3065
|
fill r: 102, g: 102, b: 204, a: 1.0
|
@@ -3078,7 +3189,7 @@ window('Dynamic Area', 240, 500) {
|
|
3078
3189
|
|
3079
3190
|
@area = area {
|
3080
3191
|
on_draw do |area_draw_params|
|
3081
|
-
path
|
3192
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3082
3193
|
rectangle(@x_spinbox.value, @y_spinbox.value, @width_spinbox.value, @height_spinbox.value)
|
3083
3194
|
|
3084
3195
|
fill r: @red_spinbox.value, g: @green_spinbox.value, b: @blue_spinbox.value, a: @alpha_spinbox.value / 100.0
|
@@ -3089,7 +3200,7 @@ window('Dynamic Area', 240, 500) {
|
|
3089
3200
|
}.show
|
3090
3201
|
```
|
3091
3202
|
|
3092
|
-
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2:
|
3203
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (declarative stable `path` approach):
|
3093
3204
|
|
3094
3205
|
```ruby
|
3095
3206
|
require 'glimmer-dsl-libui'
|
@@ -3223,21 +3334,192 @@ require 'glimmer-dsl-libui'
|
|
3223
3334
|
include Glimmer
|
3224
3335
|
|
3225
3336
|
window('Area Gallery', 400, 400) {
|
3226
|
-
|
3227
|
-
|
3228
|
-
|
3337
|
+
area {
|
3338
|
+
path { # declarative stable path
|
3339
|
+
square(0, 0, 100)
|
3340
|
+
square(100, 100, 400)
|
3341
|
+
|
3342
|
+
fill r: 102, g: 102, b: 204
|
3343
|
+
}
|
3344
|
+
path { # declarative stable path
|
3345
|
+
rectangle(0, 100, 100, 400)
|
3346
|
+
rectangle(100, 0, 400, 100)
|
3347
|
+
|
3348
|
+
fill r: 204, g: 102, b: 204
|
3349
|
+
}
|
3350
|
+
path { # declarative stable path
|
3351
|
+
figure(100, 100) {
|
3352
|
+
line(100, 400)
|
3353
|
+
line(400, 100)
|
3354
|
+
line(400, 400)
|
3355
|
+
|
3356
|
+
closed true
|
3357
|
+
}
|
3358
|
+
|
3359
|
+
fill r: 202, g: 102, b: 104, a: 0.5
|
3360
|
+
stroke r: 0, g: 0, b: 0
|
3361
|
+
}
|
3362
|
+
path { # declarative stable path
|
3363
|
+
figure(0, 0) {
|
3364
|
+
bezier(200, 100, 100, 200, 400, 100)
|
3365
|
+
bezier(300, 100, 100, 300, 100, 400)
|
3366
|
+
bezier(100, 300, 300, 100, 400, 400)
|
3367
|
+
|
3368
|
+
closed true
|
3369
|
+
}
|
3370
|
+
|
3371
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
3372
|
+
stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
|
3373
|
+
}
|
3374
|
+
path { # declarative stable path
|
3375
|
+
arc(200, 200, 90, 0, 360, false)
|
3376
|
+
|
3377
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
3378
|
+
stroke r: 0, g: 0, b: 0, thickness: 2
|
3379
|
+
}
|
3380
|
+
}
|
3381
|
+
}.show
|
3382
|
+
```
|
3383
|
+
|
3384
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (setting shape properties instead of arguments):
|
3385
|
+
|
3386
|
+
```ruby
|
3387
|
+
require 'glimmer-dsl-libui'
|
3388
|
+
|
3389
|
+
include Glimmer
|
3390
|
+
|
3391
|
+
window('Area Gallery', 400, 400) {
|
3392
|
+
area {
|
3393
|
+
path { # declarative stable path
|
3394
|
+
square {
|
3395
|
+
x 0
|
3396
|
+
y 0
|
3397
|
+
length 100
|
3398
|
+
}
|
3399
|
+
square {
|
3400
|
+
x 100
|
3401
|
+
y 100
|
3402
|
+
length 400
|
3403
|
+
}
|
3404
|
+
|
3405
|
+
fill r: 102, g: 102, b: 204
|
3406
|
+
}
|
3407
|
+
path { # declarative stable path
|
3408
|
+
rectangle {
|
3409
|
+
x 0
|
3410
|
+
y 100
|
3411
|
+
width 100
|
3412
|
+
height 400
|
3413
|
+
}
|
3414
|
+
rectangle {
|
3415
|
+
x 100
|
3416
|
+
y 0
|
3417
|
+
width 400
|
3418
|
+
height 100
|
3419
|
+
}
|
3420
|
+
|
3421
|
+
fill r: 204, g: 102, b: 204
|
3422
|
+
}
|
3423
|
+
path { # declarative stable path
|
3424
|
+
figure {
|
3425
|
+
x 100
|
3426
|
+
y 100
|
3427
|
+
|
3428
|
+
line {
|
3429
|
+
x 100
|
3430
|
+
y 400
|
3431
|
+
}
|
3432
|
+
line {
|
3433
|
+
x 400
|
3434
|
+
y 100
|
3435
|
+
}
|
3436
|
+
line {
|
3437
|
+
x 400
|
3438
|
+
y 400
|
3439
|
+
}
|
3440
|
+
|
3441
|
+
closed true
|
3442
|
+
}
|
3443
|
+
|
3444
|
+
fill r: 202, g: 102, b: 104, a: 0.5
|
3445
|
+
stroke r: 0, g: 0, b: 0
|
3446
|
+
}
|
3447
|
+
path { # declarative stable path
|
3448
|
+
figure {
|
3449
|
+
x 0
|
3450
|
+
y 0
|
3451
|
+
|
3452
|
+
bezier {
|
3453
|
+
c1_x 200
|
3454
|
+
c1_y 100
|
3455
|
+
c2_x 100
|
3456
|
+
c2_y 200
|
3457
|
+
end_x 400
|
3458
|
+
end_y 100
|
3459
|
+
}
|
3460
|
+
bezier {
|
3461
|
+
c1_x 300
|
3462
|
+
c1_y 100
|
3463
|
+
c2_x 100
|
3464
|
+
c2_y 300
|
3465
|
+
end_x 100
|
3466
|
+
end_y 400
|
3467
|
+
}
|
3468
|
+
bezier {
|
3469
|
+
c1_x 100
|
3470
|
+
c1_y 300
|
3471
|
+
c2_x 300
|
3472
|
+
c2_y 100
|
3473
|
+
end_x 400
|
3474
|
+
end_y 400
|
3475
|
+
}
|
3476
|
+
|
3477
|
+
closed true
|
3478
|
+
}
|
3479
|
+
|
3480
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
3481
|
+
stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
|
3482
|
+
}
|
3483
|
+
path { # declarative stable path
|
3484
|
+
arc {
|
3485
|
+
x_center 200
|
3486
|
+
y_center 200
|
3487
|
+
radius 90
|
3488
|
+
start_angle 0
|
3489
|
+
sweep 360
|
3490
|
+
is_negative false
|
3491
|
+
}
|
3492
|
+
|
3493
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
3494
|
+
stroke r: 0, g: 0, b: 0, thickness: 2
|
3495
|
+
}
|
3496
|
+
}
|
3497
|
+
}.show
|
3498
|
+
```
|
3499
|
+
|
3500
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 3 (semi-declarative `on_draw` dynamic `path` approach):
|
3501
|
+
|
3502
|
+
```ruby
|
3503
|
+
require 'glimmer-dsl-libui'
|
3504
|
+
|
3505
|
+
include Glimmer
|
3506
|
+
|
3507
|
+
window('Area Gallery', 400, 400) {
|
3508
|
+
area {
|
3509
|
+
on_draw do |area_draw_params|
|
3510
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3229
3511
|
square(0, 0, 100)
|
3230
3512
|
square(100, 100, 400)
|
3231
3513
|
|
3232
3514
|
fill r: 102, g: 102, b: 204
|
3233
3515
|
}
|
3234
|
-
path { #
|
3516
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3235
3517
|
rectangle(0, 100, 100, 400)
|
3236
3518
|
rectangle(100, 0, 400, 100)
|
3237
|
-
|
3519
|
+
|
3238
3520
|
fill r: 204, g: 102, b: 204
|
3239
3521
|
}
|
3240
|
-
path { #
|
3522
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3241
3523
|
figure(100, 100) {
|
3242
3524
|
line(100, 400)
|
3243
3525
|
line(400, 100)
|
@@ -3247,9 +3529,9 @@ window('Area Gallery', 400, 400) {
|
|
3247
3529
|
}
|
3248
3530
|
|
3249
3531
|
fill r: 202, g: 102, b: 104, a: 0.5
|
3250
|
-
stroke
|
3532
|
+
stroke r: 0, g: 0, b: 0
|
3251
3533
|
}
|
3252
|
-
path { #
|
3534
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3253
3535
|
figure(0, 0) {
|
3254
3536
|
bezier(200, 100, 100, 200, 400, 100)
|
3255
3537
|
bezier(300, 100, 100, 300, 100, 400)
|
@@ -3259,15 +3541,530 @@ window('Area Gallery', 400, 400) {
|
|
3259
3541
|
}
|
3260
3542
|
|
3261
3543
|
fill r: 202, g: 102, b: 204, a: 0.5
|
3262
|
-
stroke
|
3544
|
+
stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
|
3263
3545
|
}
|
3264
|
-
path { #
|
3546
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3265
3547
|
arc(200, 200, 90, 0, 360, false)
|
3266
3548
|
|
3267
3549
|
fill r: 202, g: 102, b: 204, a: 0.5
|
3268
|
-
stroke
|
3550
|
+
stroke r: 0, g: 0, b: 0, thickness: 2
|
3551
|
+
}
|
3552
|
+
end
|
3553
|
+
}
|
3554
|
+
}.show
|
3555
|
+
```
|
3556
|
+
|
3557
|
+
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):
|
3558
|
+
|
3559
|
+
```ruby
|
3560
|
+
require 'glimmer-dsl-libui'
|
3561
|
+
|
3562
|
+
include Glimmer
|
3563
|
+
|
3564
|
+
window('Area Gallery', 400, 400) {
|
3565
|
+
area {
|
3566
|
+
on_draw do |area_draw_params|
|
3567
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3568
|
+
square {
|
3569
|
+
x 0
|
3570
|
+
y 0
|
3571
|
+
length 100
|
3572
|
+
}
|
3573
|
+
square {
|
3574
|
+
x 100
|
3575
|
+
y 100
|
3576
|
+
length 400
|
3577
|
+
}
|
3578
|
+
|
3579
|
+
fill r: 102, g: 102, b: 204
|
3580
|
+
}
|
3581
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3582
|
+
rectangle {
|
3583
|
+
x 0
|
3584
|
+
y 100
|
3585
|
+
width 100
|
3586
|
+
height 400
|
3587
|
+
}
|
3588
|
+
rectangle {
|
3589
|
+
x 100
|
3590
|
+
y 0
|
3591
|
+
width 400
|
3592
|
+
height 100
|
3593
|
+
}
|
3594
|
+
|
3595
|
+
fill r: 204, g: 102, b: 204
|
3596
|
+
}
|
3597
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3598
|
+
figure {
|
3599
|
+
x 100
|
3600
|
+
y 100
|
3601
|
+
|
3602
|
+
line {
|
3603
|
+
x 100
|
3604
|
+
y 400
|
3605
|
+
}
|
3606
|
+
line {
|
3607
|
+
x 400
|
3608
|
+
y 100
|
3609
|
+
}
|
3610
|
+
line {
|
3611
|
+
x 400
|
3612
|
+
y 400
|
3613
|
+
}
|
3614
|
+
|
3615
|
+
closed true
|
3616
|
+
}
|
3617
|
+
|
3618
|
+
fill r: 202, g: 102, b: 104, a: 0.5
|
3619
|
+
stroke r: 0, g: 0, b: 0
|
3620
|
+
}
|
3621
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3622
|
+
figure {
|
3623
|
+
x 0
|
3624
|
+
y 0
|
3625
|
+
|
3626
|
+
bezier {
|
3627
|
+
c1_x 200
|
3628
|
+
c1_y 100
|
3629
|
+
c2_x 100
|
3630
|
+
c2_y 200
|
3631
|
+
end_x 400
|
3632
|
+
end_y 100
|
3633
|
+
}
|
3634
|
+
bezier {
|
3635
|
+
c1_x 300
|
3636
|
+
c1_y 100
|
3637
|
+
c2_x 100
|
3638
|
+
c2_y 300
|
3639
|
+
end_x 100
|
3640
|
+
end_y 400
|
3641
|
+
}
|
3642
|
+
bezier {
|
3643
|
+
c1_x 100
|
3644
|
+
c1_y 300
|
3645
|
+
c2_x 300
|
3646
|
+
c2_y 100
|
3647
|
+
end_x 400
|
3648
|
+
end_y 400
|
3649
|
+
}
|
3650
|
+
|
3651
|
+
closed true
|
3652
|
+
}
|
3653
|
+
|
3654
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
3655
|
+
stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
|
3656
|
+
}
|
3657
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3658
|
+
arc {
|
3659
|
+
x_center 200
|
3660
|
+
y_center 200
|
3661
|
+
radius 90
|
3662
|
+
start_angle 0
|
3663
|
+
sweep 360
|
3664
|
+
is_negative false
|
3665
|
+
}
|
3666
|
+
|
3667
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
3668
|
+
stroke r: 0, g: 0, b: 0, thickness: 2
|
3669
|
+
}
|
3670
|
+
end
|
3671
|
+
}
|
3672
|
+
}.show
|
3673
|
+
```
|
3674
|
+
|
3675
|
+
### Histogram
|
3676
|
+
|
3677
|
+
[examples/histogram.rb](examples/histogram.rb)
|
3678
|
+
|
3679
|
+
Run with this command from the root of the project if you cloned the project:
|
3680
|
+
|
3681
|
+
```
|
3682
|
+
ruby -r './lib/glimmer-dsl-libui' examples/histogram.rb
|
3683
|
+
```
|
3684
|
+
|
3685
|
+
Run with this command if you installed the [Ruby gem](https://rubygems.org/gems/glimmer-dsl-libui):
|
3686
|
+
|
3687
|
+
```
|
3688
|
+
ruby -r glimmer-dsl-libui -e "require 'examples/histogram'"
|
3689
|
+
```
|
3690
|
+
|
3691
|
+
Mac
|
3692
|
+
|
3693
|
+
![glimmer-dsl-libui-mac-histogram.png](images/glimmer-dsl-libui-mac-histogram.png)
|
3694
|
+
|
3695
|
+
Linux
|
3696
|
+
|
3697
|
+
![glimmer-dsl-libui-linux-histogram.png](images/glimmer-dsl-libui-linux-histogram.png)
|
3698
|
+
|
3699
|
+
[LibUI](https://github.com/kojix2/LibUI) Original Version:
|
3700
|
+
|
3701
|
+
```ruby
|
3702
|
+
# https://github.com/jamescook/libui-ruby/blob/master/example/histogram.rb
|
3703
|
+
|
3704
|
+
require 'libui'
|
3705
|
+
|
3706
|
+
UI = LibUI
|
3707
|
+
|
3708
|
+
X_OFF_LEFT = 20
|
3709
|
+
Y_OFF_TOP = 20
|
3710
|
+
X_OFF_RIGHT = 20
|
3711
|
+
Y_OFF_BOTTOM = 20
|
3712
|
+
POINT_RADIUS = 5
|
3713
|
+
|
3714
|
+
init = UI.init
|
3715
|
+
handler = UI::FFI::AreaHandler.malloc
|
3716
|
+
histogram = UI.new_area(handler)
|
3717
|
+
brush = UI::FFI::DrawBrush.malloc
|
3718
|
+
color_button = UI.new_color_button
|
3719
|
+
blue = 0x1E90FF
|
3720
|
+
datapoints = []
|
3721
|
+
|
3722
|
+
def graph_size(area_width, area_height)
|
3723
|
+
graph_width = area_width - X_OFF_LEFT - X_OFF_RIGHT
|
3724
|
+
graph_height = area_height - Y_OFF_TOP - Y_OFF_BOTTOM
|
3725
|
+
[graph_width, graph_height]
|
3726
|
+
end
|
3727
|
+
|
3728
|
+
matrix = UI::FFI::DrawMatrix.malloc
|
3729
|
+
|
3730
|
+
def point_locations(datapoints, width, height)
|
3731
|
+
xincr = width / 9.0 # 10 - 1 to make the last point be at the end
|
3732
|
+
yincr = height / 100.0
|
3733
|
+
|
3734
|
+
data = []
|
3735
|
+
datapoints.each_with_index do |dp, i|
|
3736
|
+
val = 100 - UI.spinbox_value(dp)
|
3737
|
+
data << [xincr * i, yincr * val]
|
3738
|
+
i += 1
|
3739
|
+
end
|
3740
|
+
|
3741
|
+
data
|
3742
|
+
end
|
3743
|
+
|
3744
|
+
def construct_graph(datapoints, width, height, should_extend)
|
3745
|
+
locations = point_locations(datapoints, width, height)
|
3746
|
+
path = UI.draw_new_path(0) # winding
|
3747
|
+
first_location = locations[0] # x and y
|
3748
|
+
UI.draw_path_new_figure(path, first_location[0], first_location[1])
|
3749
|
+
locations.each do |loc|
|
3750
|
+
UI.draw_path_line_to(path, loc[0], loc[1])
|
3751
|
+
end
|
3752
|
+
|
3753
|
+
if should_extend
|
3754
|
+
UI.draw_path_line_to(path, width, height)
|
3755
|
+
UI.draw_path_line_to(path, 0, height)
|
3756
|
+
UI.draw_path_close_figure(path)
|
3757
|
+
end
|
3758
|
+
|
3759
|
+
UI.draw_path_end(path)
|
3760
|
+
|
3761
|
+
path
|
3762
|
+
end
|
3763
|
+
|
3764
|
+
handler_draw_event = Fiddle::Closure::BlockCaller.new(
|
3765
|
+
0, [1, 1, 1]
|
3766
|
+
) do |_area_handler, _area, area_draw_params|
|
3767
|
+
area_draw_params = UI::FFI::AreaDrawParams.new(area_draw_params)
|
3768
|
+
path = UI.draw_new_path(0) # winding
|
3769
|
+
UI.draw_path_add_rectangle(path, 0, 0, area_draw_params.AreaWidth, area_draw_params.AreaHeight)
|
3770
|
+
UI.draw_path_end(path)
|
3771
|
+
set_solid_brush(brush, 0xFFFFFF, 1.0) # white
|
3772
|
+
UI.draw_fill(area_draw_params.Context, path, brush.to_ptr)
|
3773
|
+
UI.draw_free_path(path)
|
3774
|
+
dsp = UI::FFI::DrawStrokeParams.malloc
|
3775
|
+
dsp.Cap = 0 # flat
|
3776
|
+
dsp.Join = 0 # miter
|
3777
|
+
dsp.Thickness = 2
|
3778
|
+
dsp.MiterLimit = 10 # DEFAULT_MITER_LIMIT
|
3779
|
+
dashes = Fiddle::Pointer.malloc(8)
|
3780
|
+
dsp.Dashes = dashes
|
3781
|
+
dsp.NumDashes = 0
|
3782
|
+
dsp.DashPhase = 0
|
3783
|
+
|
3784
|
+
# draw axes
|
3785
|
+
set_solid_brush(brush, 0x000000, 1.0) # black
|
3786
|
+
graph_width, graph_height = *graph_size(area_draw_params.AreaWidth, area_draw_params.AreaHeight)
|
3787
|
+
|
3788
|
+
path = UI.draw_new_path(0) # winding
|
3789
|
+
UI.draw_path_new_figure(path, X_OFF_LEFT, Y_OFF_TOP)
|
3790
|
+
UI.draw_path_line_to(path, X_OFF_LEFT, Y_OFF_TOP + graph_height)
|
3791
|
+
UI.draw_path_line_to(path, X_OFF_LEFT + graph_width, Y_OFF_TOP + graph_height)
|
3792
|
+
UI.draw_path_end(path)
|
3793
|
+
UI.draw_stroke(area_draw_params.Context, path, brush, dsp)
|
3794
|
+
UI.draw_free_path(path)
|
3795
|
+
|
3796
|
+
# now transform the coordinate space so (0, 0) is the top-left corner of the graph
|
3797
|
+
UI.draw_matrix_set_identity(matrix)
|
3798
|
+
UI.draw_matrix_translate(matrix, X_OFF_LEFT, Y_OFF_TOP)
|
3799
|
+
UI.draw_transform(area_draw_params.Context, matrix)
|
3800
|
+
|
3801
|
+
# now get the color for the graph itself and set up the brush
|
3802
|
+
# uiColorButtonColor(colorButton, &graphR, &graphG, &graphB, &graphA)
|
3803
|
+
graph_r = Fiddle::Pointer.malloc(8) # double
|
3804
|
+
graph_g = Fiddle::Pointer.malloc(8) # double
|
3805
|
+
graph_b = Fiddle::Pointer.malloc(8) # double
|
3806
|
+
graph_a = Fiddle::Pointer.malloc(8) # double
|
3807
|
+
|
3808
|
+
UI.color_button_color(color_button, graph_r, graph_g, graph_b, graph_a)
|
3809
|
+
brush.Type = 0 # solid
|
3810
|
+
brush.R = graph_r[0, 8].unpack1('d')
|
3811
|
+
brush.G = graph_g[0, 8].unpack1('d')
|
3812
|
+
brush.B = graph_b[0, 8].unpack1('d')
|
3813
|
+
|
3814
|
+
# now create the fill for the graph below the graph line
|
3815
|
+
path = construct_graph(datapoints, graph_width, graph_height, true)
|
3816
|
+
brush.A = graph_a[0, 8].unpack1('d') / 2.0
|
3817
|
+
UI.draw_fill(area_draw_params.Context, path, brush)
|
3818
|
+
UI.draw_free_path(path)
|
3819
|
+
|
3820
|
+
# now draw the histogram line
|
3821
|
+
path = construct_graph(datapoints, graph_width, graph_height, false)
|
3822
|
+
brush.A = graph_a[0, 8].unpack1('d')
|
3823
|
+
UI.draw_stroke(area_draw_params.Context, path, brush, dsp)
|
3824
|
+
UI.draw_free_path(path)
|
3825
|
+
end
|
3826
|
+
|
3827
|
+
handler.Draw = handler_draw_event
|
3828
|
+
|
3829
|
+
# Assigning to local variables
|
3830
|
+
# This is intended to protect Fiddle::Closure from garbage collection.
|
3831
|
+
# See https://github.com/kojix2/LibUI/issues/8
|
3832
|
+
handler.MouseEvent = (c1 = Fiddle::Closure::BlockCaller.new(0, [0]) {})
|
3833
|
+
handler.MouseCrossed = (c2 = Fiddle::Closure::BlockCaller.new(0, [0]) {})
|
3834
|
+
handler.DragBroken = (c3 = Fiddle::Closure::BlockCaller.new(0, [0]) {})
|
3835
|
+
handler.KeyEvent = (c4 = Fiddle::Closure::BlockCaller.new(1, [0]) { 0 })
|
3836
|
+
|
3837
|
+
UI.freeInitError(init) unless init.nil?
|
3838
|
+
|
3839
|
+
hbox = UI.new_horizontal_box
|
3840
|
+
UI.box_set_padded(hbox, 1)
|
3841
|
+
|
3842
|
+
vbox = UI.new_vertical_box
|
3843
|
+
UI.box_set_padded(vbox, 1)
|
3844
|
+
UI.box_append(hbox, vbox, 0)
|
3845
|
+
UI.box_append(hbox, histogram, 1)
|
3846
|
+
|
3847
|
+
datapoints = Array.new(10) do
|
3848
|
+
UI.new_spinbox(0, 100).tap do |datapoint|
|
3849
|
+
UI.spinbox_set_value(datapoint, Random.new.rand(90))
|
3850
|
+
UI.spinbox_on_changed(datapoint) do
|
3851
|
+
UI.area_queue_redraw_all(histogram)
|
3852
|
+
end
|
3853
|
+
UI.box_append(vbox, datapoint, 0)
|
3854
|
+
end
|
3855
|
+
end
|
3856
|
+
|
3857
|
+
def set_solid_brush(brush, color, alpha)
|
3858
|
+
brush.Type = 0 # solid
|
3859
|
+
brush.R = ((color >> 16) & 0xFF) / 255.0
|
3860
|
+
brush.G = ((color >> 8) & 0xFF) / 255.0
|
3861
|
+
brush.B = (color & 0xFF) / 255.0
|
3862
|
+
brush.A = alpha
|
3863
|
+
brush
|
3864
|
+
end
|
3865
|
+
|
3866
|
+
set_solid_brush(brush, blue, 1.0)
|
3867
|
+
UI.color_button_set_color(color_button, brush.R, brush.G, brush.B, brush.A)
|
3868
|
+
|
3869
|
+
UI.color_button_on_changed(color_button) do
|
3870
|
+
UI.area_queue_redraw_all(histogram)
|
3871
|
+
end
|
3872
|
+
|
3873
|
+
UI.box_append(vbox, color_button, 0)
|
3874
|
+
|
3875
|
+
MAIN_WINDOW = UI.new_window('histogram example', 640, 480, 1)
|
3876
|
+
UI.window_set_margined(MAIN_WINDOW, 1)
|
3877
|
+
UI.window_set_child(MAIN_WINDOW, hbox)
|
3878
|
+
|
3879
|
+
should_quit = proc do |_ptr|
|
3880
|
+
UI.control_destroy(MAIN_WINDOW)
|
3881
|
+
UI.quit
|
3882
|
+
0
|
3883
|
+
end
|
3884
|
+
|
3885
|
+
UI.window_on_closing(MAIN_WINDOW, should_quit)
|
3886
|
+
UI.on_should_quit(should_quit)
|
3887
|
+
UI.control_show(MAIN_WINDOW)
|
3888
|
+
|
3889
|
+
UI.main
|
3890
|
+
UI.quit
|
3891
|
+
```
|
3892
|
+
|
3893
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
3894
|
+
|
3895
|
+
```ruby
|
3896
|
+
# https://github.com/jamescook/libui-ruby/blob/master/example/histogram.rb
|
3897
|
+
|
3898
|
+
require 'glimmer-dsl-libui'
|
3899
|
+
|
3900
|
+
include Glimmer
|
3901
|
+
|
3902
|
+
X_OFF_LEFT = 20
|
3903
|
+
Y_OFF_TOP = 20
|
3904
|
+
X_OFF_RIGHT = 20
|
3905
|
+
Y_OFF_BOTTOM = 20
|
3906
|
+
POINT_RADIUS = 5
|
3907
|
+
COLOR_BLUE = 0x1E90FF
|
3908
|
+
|
3909
|
+
@datapoints = 10.times.map {Random.new.rand(90)}
|
3910
|
+
|
3911
|
+
def graph_size(area_width, area_height)
|
3912
|
+
graph_width = area_width - X_OFF_LEFT - X_OFF_RIGHT
|
3913
|
+
graph_height = area_height - Y_OFF_TOP - Y_OFF_BOTTOM
|
3914
|
+
[graph_width, graph_height]
|
3915
|
+
end
|
3916
|
+
|
3917
|
+
def point_locations(width, height)
|
3918
|
+
xincr = width / 9.0 # 10 - 1 to make the last point be at the end
|
3919
|
+
yincr = height / 100.0
|
3920
|
+
|
3921
|
+
@datapoints.each_with_index.map do |value, i|
|
3922
|
+
val = 100 - value
|
3923
|
+
[xincr * i, yincr * val]
|
3924
|
+
end
|
3925
|
+
end
|
3926
|
+
|
3927
|
+
# method-based custom control representing a graph path
|
3928
|
+
def graph_path(width, height, should_extend, &block)
|
3929
|
+
locations = point_locations(width, height)
|
3930
|
+
path {
|
3931
|
+
first_location = locations[0] # x and y
|
3932
|
+
figure(first_location[0], first_location[1]) {
|
3933
|
+
locations.each do |loc|
|
3934
|
+
line(loc[0], loc[1])
|
3935
|
+
end
|
3936
|
+
if should_extend
|
3937
|
+
line(width, height)
|
3938
|
+
line(0, height)
|
3939
|
+
|
3940
|
+
closed true
|
3941
|
+
end
|
3942
|
+
}
|
3943
|
+
|
3944
|
+
# apply a transform to the coordinate space for this path so (0, 0) is the top-left corner of the graph
|
3945
|
+
transform {
|
3946
|
+
translate X_OFF_LEFT, Y_OFF_TOP
|
3947
|
+
}
|
3948
|
+
|
3949
|
+
block.call
|
3950
|
+
}
|
3951
|
+
end
|
3952
|
+
|
3953
|
+
window('histogram example', 640, 480) {
|
3954
|
+
margined true
|
3955
|
+
|
3956
|
+
horizontal_box {
|
3957
|
+
vertical_box {
|
3958
|
+
stretchy false
|
3959
|
+
|
3960
|
+
10.times do |i|
|
3961
|
+
spinbox(0, 100) { |sb|
|
3962
|
+
stretchy false
|
3963
|
+
value @datapoints[i]
|
3964
|
+
|
3965
|
+
on_changed do
|
3966
|
+
@datapoints[i] = sb.value
|
3967
|
+
@area.queue_redraw_all
|
3968
|
+
end
|
3969
|
+
}
|
3970
|
+
end
|
3971
|
+
|
3972
|
+
@color_button = color_button {
|
3973
|
+
stretchy false
|
3974
|
+
color COLOR_BLUE
|
3975
|
+
|
3976
|
+
on_changed do
|
3977
|
+
@area.queue_redraw_all
|
3978
|
+
end
|
3269
3979
|
}
|
3270
3980
|
}
|
3981
|
+
|
3982
|
+
@area = area {
|
3983
|
+
on_draw do |area_draw_params|
|
3984
|
+
path {
|
3985
|
+
rectangle(0, 0, area_draw_params[:area_width], area_draw_params[:area_height])
|
3986
|
+
|
3987
|
+
fill 0xFFFFFF
|
3988
|
+
}
|
3989
|
+
|
3990
|
+
graph_width, graph_height = *graph_size(area_draw_params[:area_width], area_draw_params[:area_height])
|
3991
|
+
|
3992
|
+
path {
|
3993
|
+
figure(X_OFF_LEFT, Y_OFF_TOP) {
|
3994
|
+
line(X_OFF_LEFT, Y_OFF_TOP + graph_height)
|
3995
|
+
line(X_OFF_LEFT + graph_width, Y_OFF_TOP + graph_height)
|
3996
|
+
}
|
3997
|
+
|
3998
|
+
stroke 0x000000, thickness: 2, miter_limit: 10
|
3999
|
+
}
|
4000
|
+
|
4001
|
+
# now create the fill for the graph below the graph line
|
4002
|
+
graph_path(graph_width, graph_height, true) {
|
4003
|
+
fill @color_button.color.merge(a: 0.5)
|
4004
|
+
}
|
4005
|
+
|
4006
|
+
# now draw the histogram line
|
4007
|
+
graph_path(graph_width, graph_height, false) {
|
4008
|
+
stroke @color_button.color.merge(thickness: 2, miter_limit: 10)
|
4009
|
+
}
|
4010
|
+
end
|
4011
|
+
}
|
4012
|
+
}
|
4013
|
+
}.show
|
4014
|
+
```
|
4015
|
+
|
4016
|
+
### Basic Transform
|
4017
|
+
|
4018
|
+
[examples/basic_transform.rb](examples/basic_transform.rb)
|
4019
|
+
|
4020
|
+
Run with this command from the root of the project if you cloned the project:
|
4021
|
+
|
4022
|
+
```
|
4023
|
+
ruby -r './lib/glimmer-dsl-libui' examples/basic_transform.rb
|
4024
|
+
```
|
4025
|
+
|
4026
|
+
Run with this command if you installed the [Ruby gem](https://rubygems.org/gems/glimmer-dsl-libui):
|
4027
|
+
|
4028
|
+
```
|
4029
|
+
ruby -r glimmer-dsl-libui -e "require 'examples/basic_transform'"
|
4030
|
+
```
|
4031
|
+
|
4032
|
+
Mac
|
4033
|
+
|
4034
|
+
![glimmer-dsl-libui-mac-basic-transform.png](images/glimmer-dsl-libui-mac-basic-transform.png)
|
4035
|
+
|
4036
|
+
Linux
|
4037
|
+
|
4038
|
+
![glimmer-dsl-libui-linux-basic-transform.png](images/glimmer-dsl-libui-linux-basic-transform.png)
|
4039
|
+
|
4040
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
4041
|
+
|
4042
|
+
```ruby
|
4043
|
+
require 'glimmer-dsl-libui'
|
4044
|
+
|
4045
|
+
include Glimmer
|
4046
|
+
|
4047
|
+
window('Basic Transform', 350, 350) {
|
4048
|
+
area {
|
4049
|
+
path {
|
4050
|
+
square(0, 0, 350)
|
4051
|
+
|
4052
|
+
fill r: 255, g: 255, b: 0
|
4053
|
+
}
|
4054
|
+
40.times do |n|
|
4055
|
+
path {
|
4056
|
+
square(0, 0, 100)
|
4057
|
+
|
4058
|
+
fill r: [255 - n*5, 0].max, g: [n*5, 255].min, b: 0, a: 0.5
|
4059
|
+
stroke :black, thickness: 2
|
4060
|
+
transform {
|
4061
|
+
skew 0.15, 0.15
|
4062
|
+
translate 50, 50
|
4063
|
+
rotate 100, 100, -9 * n
|
4064
|
+
scale 1.1, 1.1
|
4065
|
+
}
|
4066
|
+
}
|
4067
|
+
end
|
3271
4068
|
}
|
3272
4069
|
}.show
|
3273
4070
|
```
|