glimmer-dsl-libui 0.1.4 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +55 -0
- data/README.md +939 -255
- data/VERSION +1 -1
- data/examples/area_gallery.rb +72 -38
- data/examples/area_gallery2.rb +126 -92
- data/examples/area_gallery3.rb +74 -40
- data/examples/area_gallery4.rb +132 -98
- data/examples/basic_area2.rb +1 -1
- data/examples/basic_button.rb +2 -2
- data/examples/basic_entry.rb +2 -2
- 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 +166 -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 -8
- 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 +72 -21
- data/lib/glimmer/libui/{enableable_column.rb → parent.rb} +7 -15
- data/lib/glimmer/libui/{arc.rb → shape/arc.rb} +13 -11
- data/lib/glimmer/libui/shape/bezier.rb +38 -0
- data/lib/glimmer/libui/{figure.rb → shape/figure.rb} +23 -21
- data/lib/glimmer/libui/{line.rb → shape/line.rb} +9 -7
- data/lib/glimmer/libui/{bezier.rb → shape/rectangle.rb} +9 -7
- data/lib/glimmer/libui/{square.rb → shape/square.rb} +9 -7
- data/lib/glimmer/libui/shape.rb +16 -15
- data/lib/glimmer/libui.rb +92 -0
- data/lib/glimmer-dsl-libui.rb +3 -0
- metadata +76 -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.8
|
2
2
|
## Prerequisite-Free Ruby Desktop Development GUI Library
|
3
3
|
[](http://badge.fury.io/rb/glimmer-dsl-libui)
|
4
4
|
[](https://codeclimate.com/github/AndyObtiva/glimmer-dsl-libui/maintainability)
|
@@ -80,51 +80,85 @@ require 'glimmer-dsl-libui'
|
|
80
80
|
include Glimmer
|
81
81
|
|
82
82
|
window('Area Gallery', 400, 400) {
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
line(400, 400)
|
102
|
-
|
103
|
-
closed true
|
104
|
-
}
|
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)
|
105
101
|
|
106
|
-
|
107
|
-
stroke r: 0, g: 0, b: 0
|
102
|
+
closed true
|
108
103
|
}
|
109
|
-
path { # declarative stable path
|
110
|
-
figure(0, 0) {
|
111
|
-
bezier(200, 100, 100, 200, 400, 100)
|
112
|
-
bezier(300, 100, 100, 300, 100, 400)
|
113
|
-
bezier(100, 300, 300, 100, 400, 400)
|
114
104
|
|
115
|
-
|
116
|
-
|
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)
|
117
113
|
|
118
|
-
|
119
|
-
stroke thickness: 2, r: 0, g: 0, b: 0
|
114
|
+
closed true
|
120
115
|
}
|
121
|
-
path { # declarative stable path
|
122
|
-
arc(200, 200, 90, 0, 360, false)
|
123
116
|
|
124
|
-
|
125
|
-
|
126
|
-
|
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
|
127
125
|
}
|
126
|
+
|
127
|
+
on_mouse_event do |area_mouse_event|
|
128
|
+
p area_mouse_event
|
129
|
+
end
|
130
|
+
|
131
|
+
on_mouse_moved do |area_mouse_event|
|
132
|
+
puts 'moved'
|
133
|
+
end
|
134
|
+
|
135
|
+
on_mouse_down do |area_mouse_event|
|
136
|
+
puts 'mouse down'
|
137
|
+
end
|
138
|
+
|
139
|
+
on_mouse_up do |area_mouse_event|
|
140
|
+
puts 'mouse up'
|
141
|
+
end
|
142
|
+
|
143
|
+
on_mouse_drag_started do |area_mouse_event|
|
144
|
+
puts 'drag started'
|
145
|
+
end
|
146
|
+
|
147
|
+
on_mouse_dragged do |area_mouse_event|
|
148
|
+
puts 'dragged'
|
149
|
+
end
|
150
|
+
|
151
|
+
on_mouse_dropped do |area_mouse_event|
|
152
|
+
puts 'dropped'
|
153
|
+
end
|
154
|
+
|
155
|
+
on_mouse_entered do
|
156
|
+
puts 'entered'
|
157
|
+
end
|
158
|
+
|
159
|
+
on_mouse_exited do
|
160
|
+
puts 'exited'
|
161
|
+
end
|
128
162
|
}
|
129
163
|
}.show
|
130
164
|
```
|
@@ -145,7 +179,7 @@ Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interes
|
|
145
179
|
|
146
180
|
## Table of Contents
|
147
181
|
|
148
|
-
- [Glimmer DSL for LibUI 0.1.
|
182
|
+
- [Glimmer DSL for LibUI 0.1.8](#-glimmer-dsl-for-libui-018)
|
149
183
|
- [Glimmer GUI DSL Concepts](#glimmer-gui-dsl-concepts)
|
150
184
|
- [Usage](#usage)
|
151
185
|
- [Girb (Glimmer IRB)](#girb-glimmer-irb)
|
@@ -186,6 +220,8 @@ Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interes
|
|
186
220
|
- [Basic Area](#basic-area)
|
187
221
|
- [Dynamic Area](#dynamic-area)
|
188
222
|
- [Area Gallery](#area-gallery)
|
223
|
+
- [Histogram](#histogram)
|
224
|
+
- [Basic Transform](#basic-transform)
|
189
225
|
- [Contributing to glimmer-dsl-libui](#contributing-to-glimmer-dsl-libui)
|
190
226
|
- [Help](#help)
|
191
227
|
- [Issues](#issues)
|
@@ -249,10 +285,10 @@ require 'glimmer-dsl-libui'
|
|
249
285
|
|
250
286
|
include Glimmer
|
251
287
|
|
252
|
-
window('hello world', 300, 200) {
|
288
|
+
window('hello world', 300, 200) {
|
253
289
|
button('Button') {
|
254
290
|
on_clicked do
|
255
|
-
msg_box(
|
291
|
+
msg_box('Information', 'You clicked the button')
|
256
292
|
end
|
257
293
|
}
|
258
294
|
|
@@ -273,7 +309,7 @@ gem install glimmer-dsl-libui
|
|
273
309
|
Or install via Bundler `Gemfile`:
|
274
310
|
|
275
311
|
```ruby
|
276
|
-
gem 'glimmer-dsl-libui', '~> 0.1.
|
312
|
+
gem 'glimmer-dsl-libui', '~> 0.1.8'
|
277
313
|
```
|
278
314
|
|
279
315
|
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.
|
@@ -347,7 +383,7 @@ w.libui # => #<Fiddle::Pointer:0x00007fde53997980 ptr=0x00007fde51352a60 size=0
|
|
347
383
|
Control(Args) | Properties | Listeners
|
348
384
|
------------- | ---------- | ---------
|
349
385
|
`about_menu_item` | None | `on_clicked`
|
350
|
-
`area` | None | `on_draw`
|
386
|
+
`area` | None | `on_draw(area_draw_params)`, `on_mouse_event(area_mouse_event)`, `on_mouse_down(area_mouse_event)`, `on_mouse_up(area_mouse_event)`, `on_mouse_drag_started(area_mouse_event)`, `on_mouse_dragged(area_mouse_event)`, `on_mouse_dropped(area_mouse_event)`, `on_mouse_entered`, `on_mouse_exited`
|
351
387
|
`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
388
|
`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
|
353
389
|
`button(text as String)` | `text` (`String`) | `on_clicked`
|
@@ -374,13 +410,14 @@ Control(Args) | Properties | Listeners
|
|
374
410
|
`image_text_column(name as String)` | None | None
|
375
411
|
`label(text as String)` | `text` (`String`) | None
|
376
412
|
`line(x as Numeric, y as Numeric)` | `x` (`Numeric`), `y` (`Numeric`) | None
|
413
|
+
`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
|
377
414
|
`menu(text as String)` | None | None
|
378
415
|
`menu_item(text as String)` | `checked` (Boolean) | `on_clicked`
|
379
416
|
`multiline_entry` | `read_only` (Boolean), `text` (`String`) | `on_changed`
|
380
|
-
`msg_box(window as Glimmer::LibUI::WindowProxy, title as String, description as String)` | None | None
|
381
|
-
`msg_box_error(window as Glimmer::LibUI::WindowProxy, title as String, description as String)` | None | None
|
417
|
+
`msg_box(window = main_window as Glimmer::LibUI::WindowProxy, title as String, description as String)` | None | None
|
418
|
+
`msg_box_error(window = main_window as Glimmer::LibUI::WindowProxy, title as String, description as String)` | None | None
|
382
419
|
`non_wrapping_multiline_entry` | `read_only` (Boolean), `text` (`String`) | `on_changed`
|
383
|
-
`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
|
420
|
+
`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
|
384
421
|
`preferences_menu_item` | None | `on_clicked`
|
385
422
|
`progress_bar` | `value` (`Numeric`) | None
|
386
423
|
`progress_bar_column(name as String)` | None | None
|
@@ -394,7 +431,7 @@ Control(Args) | Properties | Listeners
|
|
394
431
|
`tab_item(name as String)` | `index` [read-only] (`Integer`), `margined` (Boolean), `name` [read-only] (`String`) | None
|
395
432
|
`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
|
396
433
|
`text_column(name as String)` | `editable` (Boolean) | None
|
397
|
-
`time_picker` | `time` (`Hash` of keys: `sec` as `Integer`, `min` as `Integer`, `hour` as `Integer
|
434
|
+
`time_picker` | `time` (`Hash` of keys: `sec` as `Integer`, `min` as `Integer`, `hour` as `Integer`) | `on_changed`
|
398
435
|
`vertical_box` | `padded` (Boolean) | None
|
399
436
|
`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`
|
400
437
|
|
@@ -530,9 +567,9 @@ Learn more by checking out [examples](#examples).
|
|
530
567
|
|
531
568
|
### Area API
|
532
569
|
|
533
|
-
The `area` control can be used in one of two ways:
|
534
|
-
- 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.
|
535
|
-
- 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
|
570
|
+
The `area` control is a canvas-like control for drawing paths that can be used in one of two ways:
|
571
|
+
- 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).
|
572
|
+
- 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.
|
536
573
|
|
537
574
|
Here is an example of a declarative `area` with a stable path (you may copy/paste in [`girb`](#girb-glimmer-irb)):
|
538
575
|
|
@@ -558,7 +595,7 @@ window('Basic Area', 400, 400) {
|
|
558
595
|
|
559
596
|

|
560
597
|
|
561
|
-
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)):
|
598
|
+
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)):
|
562
599
|
|
563
600
|
```ruby
|
564
601
|
require 'glimmer-dsl-libui'
|
@@ -571,7 +608,7 @@ window('Basic Area', 400, 400) {
|
|
571
608
|
vertical_box {
|
572
609
|
area {
|
573
610
|
on_draw do |area_draw_params|
|
574
|
-
path
|
611
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
575
612
|
rectangle(0, 0, 400, 400)
|
576
613
|
|
577
614
|
fill r: 102, g: 102, b: 204, a: 1.0
|
@@ -584,6 +621,8 @@ window('Basic Area', 400, 400) {
|
|
584
621
|
|
585
622
|
Check [examples/dynamic_area.rb](#dynamic-area) for a more detailed semi-declarative example.
|
586
623
|
|
624
|
+
`path` can receive a `draw_fill_mode` argument that can accept values `:winding` or `:alternate` and defaults to `:winding`.
|
625
|
+
|
587
626
|
Available nested `path` shapes:
|
588
627
|
- `rectangle(x as Numeric, y as Numeric, width as Numeric, height as Numeric)`
|
589
628
|
- `square(x as Numeric, y as Numeric, length as Numeric)`
|
@@ -592,16 +631,123 @@ Available nested `path` shapes:
|
|
592
631
|
- `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)`
|
593
632
|
- `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)
|
594
633
|
|
595
|
-
|
634
|
+
Check [examples/area_gallery.rb](#area-gallery) for an overiew of all `path` shapes.
|
635
|
+
|
636
|
+
The `area_draw_params` argument for `on_draw` block is a hash consisting of the following keys:
|
637
|
+
- `:context`: the drawing context object
|
638
|
+
- `:area_width`: area width
|
639
|
+
- `:area_height`: area height
|
640
|
+
- `:clip_x`: clip region top-left x coordinate
|
641
|
+
- `:clip_y`: clip region top-left y coordinate
|
642
|
+
- `:clip_width`: clip region width
|
643
|
+
- `:clip_height`: clip region height
|
644
|
+
|
645
|
+
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.
|
646
|
+
|
647
|
+
`area` supported mouse listeners are:
|
648
|
+
- `on_mouse_event {|area_mouse_event| ...}`: general catch-all mouse event (recommend use fine-grained event below instead)
|
649
|
+
- `on_mouse_down {|area_mouse_event)`
|
650
|
+
- `on_mouse_up {|area_mouse_event)`
|
651
|
+
- `on_mouse_drag_started {|area_mouse_event)`
|
652
|
+
- `on_mouse_dragged {|area_mouse_event)`
|
653
|
+
- `on_mouse_dropped {|area_mouse_event)`
|
654
|
+
- `on_mouse_entered {...}`
|
655
|
+
- `on_mouse_exited {...}`
|
656
|
+
- `on_mouse_crossed {|left| ...}` (NOT RECOMMENDED; it does what `on_mouse_entered` and `on_mouse_exited` do by returning a `left` argument indicating if mouse left `area`)
|
657
|
+
- `on_drag_broken {...}` (NOT RECOMMENDED; varies per platforms; use `on_mouse_dropped` instead)
|
658
|
+
|
659
|
+
The `area_mouse_event` argument for mouse events that receive it (e.g. `on_mouse_up`, `on_mouse_dragged`) consist of the following keys:
|
660
|
+
- `:x`: mouse x location in relation to area's top-left-corner
|
661
|
+
- `:y`: mouse y location in relation to area's top-left-corner
|
662
|
+
- `:area_width`: area current width
|
663
|
+
- `:area_height`: area current height
|
664
|
+
- `:down`: mouse pressed button (e.g. `1` is left button, `3` is right button)
|
665
|
+
- `:up`: mouse depressed button (e.g. `1` is left button, `3` is right button)
|
666
|
+
- `:count`: count of mouse clicks (e.g. `2` for double-click, `1` for single-click)
|
667
|
+
- `:modifers`: `Array` of `Symbol`s from one of the following: `[:command, :shift, :alt, :control]`
|
668
|
+
- `:held`: mouse held button during dragging (e.g. `1` is left button, `4` is right button)
|
669
|
+
|
670
|
+
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.
|
671
|
+
|
672
|
+
To redraw an `area`, you may call the `#queue_redraw_all` method, or simply `#redraw`.
|
673
|
+
|
674
|
+
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.
|
675
|
+
|
676
|
+
When instantiating a `matrix` object, it always starts with identity matrix.
|
677
|
+
|
678
|
+
Here are the following operations that can be performed in a `matrix` body:
|
679
|
+
- `identity` [alias: `set_identity`]: resets matrix to identity matrix
|
680
|
+
- `translate(x as Numeric, y as Numeric)`
|
681
|
+
- `scale(x_center = 0 as Numeric, y_center = 0 as Numeric, x as Numeric, y as Numeric)`
|
682
|
+
- `skew(x = 0 as Numeric, y = 0 as Numeric, x_amount as Numeric, y_amount as Numeric)`
|
683
|
+
- `rotate(x = 0 as Numeric, y = 0 as Numeric, degrees as Numeric)`
|
684
|
+
|
685
|
+
Example of using transform matrix (you may copy/paste in [`girb`](#girb-glimmer-irb)):
|
686
|
+
|
687
|
+
```ruby
|
688
|
+
require 'glimmer-dsl-libui'
|
689
|
+
|
690
|
+
include Glimmer
|
691
|
+
|
692
|
+
window('Basic Transform', 350, 350) {
|
693
|
+
area {
|
694
|
+
path {
|
695
|
+
square(0, 0, 350)
|
696
|
+
|
697
|
+
fill r: 255, g: 255, b: 0
|
698
|
+
}
|
699
|
+
40.times do |n|
|
700
|
+
path {
|
701
|
+
square(0, 0, 100)
|
702
|
+
|
703
|
+
fill r: [255 - n*5, 0].max, g: [n*5, 255].min, b: 0, a: 0.5
|
704
|
+
stroke :black, thickness: 2
|
705
|
+
transform {
|
706
|
+
skew 0.15, 0.15
|
707
|
+
translate 50, 50
|
708
|
+
rotate 100, 100, -9 * n
|
709
|
+
scale 1.1, 1.1
|
710
|
+
}
|
711
|
+
}
|
712
|
+
end
|
713
|
+
}
|
714
|
+
}.show
|
715
|
+
```
|
716
|
+
|
717
|
+
Keep in mind that this part could be written differently when there is a need to reuse the matrix:
|
718
|
+
|
719
|
+
```ruby
|
720
|
+
transform {
|
721
|
+
translate 100, 100
|
722
|
+
rotate 100, 100, -9 * n
|
723
|
+
}
|
724
|
+
```
|
725
|
+
|
726
|
+
Alternatively:
|
727
|
+
|
728
|
+
```ruby
|
729
|
+
m1 = matrix {
|
730
|
+
translate 100, 100
|
731
|
+
rotate 100, 100, -9 * n
|
732
|
+
}
|
733
|
+
transform m1
|
734
|
+
# and then reuse m1 elsewhere too
|
735
|
+
```
|
736
|
+
|
737
|
+
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.
|
738
|
+
|
739
|
+
`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)
|
596
740
|
|
597
|
-
|
741
|
+
Check [Basic Transform](#basic-transform) example for use of [X11](https://en.wikipedia.org/wiki/X11_color_names) colors.
|
742
|
+
|
743
|
+
Check [Histogram](#histogram) example for use of hex colors.
|
598
744
|
|
599
745
|
### Smart Defaults and Conventions
|
600
746
|
|
601
747
|
- `horizontal_box`, `vertical_box`, `grid`, and `form` controls have `padded` as `true` upon instantiation to ensure more user-friendly GUI by default
|
602
748
|
- `group` controls have `margined` as `true` upon instantiation to ensure more user-friendly GUI by default
|
603
749
|
- 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)
|
604
|
-
- `window` instatiation args can be left off, having the following defaults when unspecified: `title` as `''`, `width` as `
|
750
|
+
- `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`)
|
605
751
|
- `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)
|
606
752
|
- `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'; ...}`)
|
607
753
|
- `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'}}`)
|
@@ -627,6 +773,11 @@ To redraw an `area`, you may call `#queue_redraw_all` method.
|
|
627
773
|
- `area` paths are specified declaratively with figures underneath (e.g. `rectangle`) and `area` draw listener is automatically generated
|
628
774
|
- Observe figure properties (e.g. `rectangle` `width`) for changes and automatically redraw containing area accordingly
|
629
775
|
- Observe `path` `fill` and `stroke` hashes for changes and automatically redraw containing area accordingly
|
776
|
+
- All controls are protected from garbage collection until no longer needed (explicitly destroyed), so there is no need to worry about surprises.
|
777
|
+
- All resources are freed automatically once no longer needed or left to garbage collection.
|
778
|
+
- 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.
|
779
|
+
- 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)
|
780
|
+
- Color alpha value defaults to `1.0` when not specified.
|
630
781
|
|
631
782
|
### API Gotchas
|
632
783
|
|
@@ -654,6 +805,8 @@ The following examples include reimplementions of the examples in the [LibUI](ht
|
|
654
805
|
|
655
806
|
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.
|
656
807
|
|
808
|
+
(note that for examples that emit output to terminal/command-line via `p` or `puts`, you must run them directly to see output)
|
809
|
+
|
657
810
|
[examples/meta_example.rb](examples/meta_example.rb)
|
658
811
|
|
659
812
|
Run with this command from the root of the project if you cloned the project:
|
@@ -704,7 +857,7 @@ class MetaExample
|
|
704
857
|
end
|
705
858
|
|
706
859
|
def launch
|
707
|
-
window('Meta-Example', 700, 500) {
|
860
|
+
window('Meta-Example', 700, 500) {
|
708
861
|
margined true
|
709
862
|
|
710
863
|
horizontal_box {
|
@@ -726,7 +879,7 @@ class MetaExample
|
|
726
879
|
meta_example_file = File.join(Dir.home, '.meta_example.rb')
|
727
880
|
File.write(meta_example_file, @nwme.text)
|
728
881
|
result = `ruby -r #{glimmer_dsl_libui_file} #{meta_example_file} 2>&1`
|
729
|
-
msg_box(
|
882
|
+
msg_box('Error Running Example', result) if result.include?('error')
|
730
883
|
rescue => e
|
731
884
|
puts 'Unable to write code changes! Running original example...'
|
732
885
|
system "ruby -r #{glimmer_dsl_libui_file} #{file_path_for(@examples[@rbs.selected])}"
|
@@ -810,7 +963,7 @@ window('hello world', 300, 200, true) {
|
|
810
963
|
}.show
|
811
964
|
```
|
812
965
|
|
813
|
-
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2:
|
966
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (setting `window` properties instead of arguments):
|
814
967
|
|
815
968
|
```ruby
|
816
969
|
require 'glimmer-dsl-libui'
|
@@ -891,10 +1044,10 @@ require 'glimmer-dsl-libui'
|
|
891
1044
|
|
892
1045
|
include Glimmer
|
893
1046
|
|
894
|
-
window('hello world', 300, 200) {
|
1047
|
+
window('hello world', 300, 200) {
|
895
1048
|
button('Button') {
|
896
1049
|
on_clicked do
|
897
|
-
msg_box(
|
1050
|
+
msg_box('Information', 'You clicked the button')
|
898
1051
|
end
|
899
1052
|
}
|
900
1053
|
|
@@ -978,7 +1131,7 @@ require 'glimmer-dsl-libui'
|
|
978
1131
|
|
979
1132
|
include Glimmer
|
980
1133
|
|
981
|
-
window('Basic Entry', 300, 50) {
|
1134
|
+
window('Basic Entry', 300, 50) {
|
982
1135
|
horizontal_box {
|
983
1136
|
e = entry {
|
984
1137
|
# stretchy true # Smart default option for appending to horizontal_box
|
@@ -994,7 +1147,7 @@ window('Basic Entry', 300, 50) { |w|
|
|
994
1147
|
|
995
1148
|
on_clicked do
|
996
1149
|
text = e.text
|
997
|
-
msg_box(
|
1150
|
+
msg_box('You entered', text)
|
998
1151
|
end
|
999
1152
|
}
|
1000
1153
|
}
|
@@ -1098,12 +1251,12 @@ ruby -r glimmer-dsl-libui -e "require 'examples/midi_player'"
|
|
1098
1251
|
Mac
|
1099
1252
|
|
1100
1253
|

|
1101
|
-

|
1102
1255
|
|
1103
1256
|
Linux
|
1104
1257
|
|
1105
1258
|

|
1106
|
-

|
1107
1260
|
|
1108
1261
|
[LibUI](https://github.com/kojix2/LibUI) Original Version:
|
1109
1262
|
|
@@ -1249,23 +1402,22 @@ class TinyMidiPlayer
|
|
1249
1402
|
end
|
1250
1403
|
end
|
1251
1404
|
|
1252
|
-
def show_version
|
1253
|
-
msg_box(
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
"Version #{VERSION}")
|
1405
|
+
def show_version
|
1406
|
+
msg_box('Tiny Midi Player',
|
1407
|
+
"Written in Ruby\n" \
|
1408
|
+
"https://github.com/kojix2/libui\n" \
|
1409
|
+
"Version #{VERSION}")
|
1258
1410
|
end
|
1259
1411
|
|
1260
1412
|
def create_gui
|
1261
1413
|
menu('Help') { |m|
|
1262
1414
|
menu_item('Version') {
|
1263
1415
|
on_clicked do
|
1264
|
-
show_version
|
1416
|
+
show_version
|
1265
1417
|
end
|
1266
1418
|
}
|
1267
1419
|
}
|
1268
|
-
|
1420
|
+
window('Tiny Midi Player', 200, 50) {
|
1269
1421
|
horizontal_box {
|
1270
1422
|
vertical_box {
|
1271
1423
|
stretchy false
|
@@ -1281,7 +1433,7 @@ class TinyMidiPlayer
|
|
1281
1433
|
end
|
1282
1434
|
}
|
1283
1435
|
}
|
1284
|
-
|
1436
|
+
|
1285
1437
|
combobox { |c|
|
1286
1438
|
items @midi_files.map { |path| File.basename(path) }
|
1287
1439
|
|
@@ -1291,8 +1443,7 @@ class TinyMidiPlayer
|
|
1291
1443
|
end
|
1292
1444
|
}
|
1293
1445
|
}
|
1294
|
-
}
|
1295
|
-
@main_window.show
|
1446
|
+
}.show
|
1296
1447
|
end
|
1297
1448
|
end
|
1298
1449
|
|
@@ -1528,14 +1679,14 @@ include Glimmer
|
|
1528
1679
|
menu('File') {
|
1529
1680
|
menu_item('Open') {
|
1530
1681
|
on_clicked do
|
1531
|
-
file = open_file
|
1682
|
+
file = open_file
|
1532
1683
|
puts file unless file.nil?
|
1533
1684
|
end
|
1534
1685
|
}
|
1535
1686
|
|
1536
1687
|
menu_item('Save') {
|
1537
1688
|
on_clicked do
|
1538
|
-
file = save_file
|
1689
|
+
file = save_file
|
1539
1690
|
puts file unless file.nil?
|
1540
1691
|
end
|
1541
1692
|
}
|
@@ -1578,7 +1729,7 @@ MAIN_WINDOW = window('Control Gallery', 600, 500) {
|
|
1578
1729
|
stretchy false
|
1579
1730
|
|
1580
1731
|
on_clicked do
|
1581
|
-
msg_box(
|
1732
|
+
msg_box('Information', 'You clicked the button')
|
1582
1733
|
end
|
1583
1734
|
}
|
1584
1735
|
|
@@ -1586,7 +1737,7 @@ MAIN_WINDOW = window('Control Gallery', 600, 500) {
|
|
1586
1737
|
stretchy false
|
1587
1738
|
|
1588
1739
|
on_toggled do |c|
|
1589
|
-
checked = c.checked
|
1740
|
+
checked = c.checked?
|
1590
1741
|
MAIN_WINDOW.title = "Checkbox is #{checked}"
|
1591
1742
|
c.text = "I am the checkbox (#{checked})"
|
1592
1743
|
end
|
@@ -2040,7 +2191,7 @@ require 'glimmer-dsl-libui'
|
|
2040
2191
|
|
2041
2192
|
include Glimmer
|
2042
2193
|
|
2043
|
-
window('Form') {
|
2194
|
+
window('Form') {
|
2044
2195
|
margined true
|
2045
2196
|
|
2046
2197
|
vertical_box {
|
@@ -2056,7 +2207,7 @@ window('Form') { |w|
|
|
2056
2207
|
|
2057
2208
|
button('Display Name') {
|
2058
2209
|
on_clicked do
|
2059
|
-
msg_box(
|
2210
|
+
msg_box('Name', "#{@first_name_entry.text} #{@last_name_entry.text}")
|
2060
2211
|
end
|
2061
2212
|
}
|
2062
2213
|
}
|
@@ -2956,7 +3107,7 @@ window('Basic Area', 400, 400) {
|
|
2956
3107
|
}.show
|
2957
3108
|
```
|
2958
3109
|
|
2959
|
-
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2:
|
3110
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (semi-declarative `on_draw` dynamic `path` approach):
|
2960
3111
|
|
2961
3112
|
```ruby
|
2962
3113
|
require 'glimmer-dsl-libui'
|
@@ -2969,7 +3120,7 @@ window('Basic Area', 400, 400) {
|
|
2969
3120
|
vertical_box {
|
2970
3121
|
area {
|
2971
3122
|
on_draw do |area_draw_params|
|
2972
|
-
path
|
3123
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
2973
3124
|
rectangle(0, 0, 400, 400)
|
2974
3125
|
|
2975
3126
|
fill r: 102, g: 102, b: 204, a: 1.0
|
@@ -3099,7 +3250,7 @@ window('Dynamic Area', 240, 500) {
|
|
3099
3250
|
|
3100
3251
|
@area = area {
|
3101
3252
|
on_draw do |area_draw_params|
|
3102
|
-
path
|
3253
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3103
3254
|
rectangle(@x_spinbox.value, @y_spinbox.value, @width_spinbox.value, @height_spinbox.value)
|
3104
3255
|
|
3105
3256
|
fill r: @red_spinbox.value, g: @green_spinbox.value, b: @blue_spinbox.value, a: @alpha_spinbox.value / 100.0
|
@@ -3110,7 +3261,7 @@ window('Dynamic Area', 240, 500) {
|
|
3110
3261
|
}.show
|
3111
3262
|
```
|
3112
3263
|
|
3113
|
-
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2:
|
3264
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (declarative stable `path` approach):
|
3114
3265
|
|
3115
3266
|
```ruby
|
3116
3267
|
require 'glimmer-dsl-libui'
|
@@ -3244,21 +3395,264 @@ require 'glimmer-dsl-libui'
|
|
3244
3395
|
include Glimmer
|
3245
3396
|
|
3246
3397
|
window('Area Gallery', 400, 400) {
|
3247
|
-
|
3248
|
-
|
3249
|
-
|
3398
|
+
area {
|
3399
|
+
path { # declarative stable path
|
3400
|
+
square(0, 0, 100)
|
3401
|
+
square(100, 100, 400)
|
3402
|
+
|
3403
|
+
fill r: 102, g: 102, b: 204
|
3404
|
+
}
|
3405
|
+
path { # declarative stable path
|
3406
|
+
rectangle(0, 100, 100, 400)
|
3407
|
+
rectangle(100, 0, 400, 100)
|
3408
|
+
|
3409
|
+
fill r: 204, g: 102, b: 204
|
3410
|
+
}
|
3411
|
+
path { # declarative stable path
|
3412
|
+
figure(100, 100) {
|
3413
|
+
line(100, 400)
|
3414
|
+
line(400, 100)
|
3415
|
+
line(400, 400)
|
3416
|
+
|
3417
|
+
closed true
|
3418
|
+
}
|
3419
|
+
|
3420
|
+
fill r: 202, g: 102, b: 104, a: 0.5
|
3421
|
+
stroke r: 0, g: 0, b: 0
|
3422
|
+
}
|
3423
|
+
path { # declarative stable path
|
3424
|
+
figure(0, 0) {
|
3425
|
+
bezier(200, 100, 100, 200, 400, 100)
|
3426
|
+
bezier(300, 100, 100, 300, 100, 400)
|
3427
|
+
bezier(100, 300, 300, 100, 400, 400)
|
3428
|
+
|
3429
|
+
closed true
|
3430
|
+
}
|
3431
|
+
|
3432
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
3433
|
+
stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
|
3434
|
+
}
|
3435
|
+
path { # declarative stable path
|
3436
|
+
arc(200, 200, 90, 0, 360, false)
|
3437
|
+
|
3438
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
3439
|
+
stroke r: 0, g: 0, b: 0, thickness: 2
|
3440
|
+
}
|
3441
|
+
|
3442
|
+
on_mouse_event do |area_mouse_event|
|
3443
|
+
p area_mouse_event
|
3444
|
+
end
|
3445
|
+
|
3446
|
+
on_mouse_moved do |area_mouse_event|
|
3447
|
+
puts 'moved'
|
3448
|
+
end
|
3449
|
+
|
3450
|
+
on_mouse_down do |area_mouse_event|
|
3451
|
+
puts 'mouse down'
|
3452
|
+
end
|
3453
|
+
|
3454
|
+
on_mouse_up do |area_mouse_event|
|
3455
|
+
puts 'mouse up'
|
3456
|
+
end
|
3457
|
+
|
3458
|
+
on_mouse_drag_started do |area_mouse_event|
|
3459
|
+
puts 'drag started'
|
3460
|
+
end
|
3461
|
+
|
3462
|
+
on_mouse_dragged do |area_mouse_event|
|
3463
|
+
puts 'dragged'
|
3464
|
+
end
|
3465
|
+
|
3466
|
+
on_mouse_dropped do |area_mouse_event|
|
3467
|
+
puts 'dropped'
|
3468
|
+
end
|
3469
|
+
|
3470
|
+
on_mouse_entered do
|
3471
|
+
puts 'entered'
|
3472
|
+
end
|
3473
|
+
|
3474
|
+
on_mouse_exited do
|
3475
|
+
puts 'exited'
|
3476
|
+
end
|
3477
|
+
}
|
3478
|
+
}.show
|
3479
|
+
```
|
3480
|
+
|
3481
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (setting shape properties instead of arguments):
|
3482
|
+
|
3483
|
+
```ruby
|
3484
|
+
require 'glimmer-dsl-libui'
|
3485
|
+
|
3486
|
+
include Glimmer
|
3487
|
+
|
3488
|
+
window('Area Gallery', 400, 400) {
|
3489
|
+
area {
|
3490
|
+
path { # declarative stable path
|
3491
|
+
square {
|
3492
|
+
x 0
|
3493
|
+
y 0
|
3494
|
+
length 100
|
3495
|
+
}
|
3496
|
+
square {
|
3497
|
+
x 100
|
3498
|
+
y 100
|
3499
|
+
length 400
|
3500
|
+
}
|
3501
|
+
|
3502
|
+
fill r: 102, g: 102, b: 204
|
3503
|
+
}
|
3504
|
+
path { # declarative stable path
|
3505
|
+
rectangle {
|
3506
|
+
x 0
|
3507
|
+
y 100
|
3508
|
+
width 100
|
3509
|
+
height 400
|
3510
|
+
}
|
3511
|
+
rectangle {
|
3512
|
+
x 100
|
3513
|
+
y 0
|
3514
|
+
width 400
|
3515
|
+
height 100
|
3516
|
+
}
|
3517
|
+
|
3518
|
+
fill r: 204, g: 102, b: 204
|
3519
|
+
}
|
3520
|
+
path { # declarative stable path
|
3521
|
+
figure {
|
3522
|
+
x 100
|
3523
|
+
y 100
|
3524
|
+
|
3525
|
+
line {
|
3526
|
+
x 100
|
3527
|
+
y 400
|
3528
|
+
}
|
3529
|
+
line {
|
3530
|
+
x 400
|
3531
|
+
y 100
|
3532
|
+
}
|
3533
|
+
line {
|
3534
|
+
x 400
|
3535
|
+
y 400
|
3536
|
+
}
|
3537
|
+
|
3538
|
+
closed true
|
3539
|
+
}
|
3540
|
+
|
3541
|
+
fill r: 202, g: 102, b: 104, a: 0.5
|
3542
|
+
stroke r: 0, g: 0, b: 0
|
3543
|
+
}
|
3544
|
+
path { # declarative stable path
|
3545
|
+
figure {
|
3546
|
+
x 0
|
3547
|
+
y 0
|
3548
|
+
|
3549
|
+
bezier {
|
3550
|
+
c1_x 200
|
3551
|
+
c1_y 100
|
3552
|
+
c2_x 100
|
3553
|
+
c2_y 200
|
3554
|
+
end_x 400
|
3555
|
+
end_y 100
|
3556
|
+
}
|
3557
|
+
bezier {
|
3558
|
+
c1_x 300
|
3559
|
+
c1_y 100
|
3560
|
+
c2_x 100
|
3561
|
+
c2_y 300
|
3562
|
+
end_x 100
|
3563
|
+
end_y 400
|
3564
|
+
}
|
3565
|
+
bezier {
|
3566
|
+
c1_x 100
|
3567
|
+
c1_y 300
|
3568
|
+
c2_x 300
|
3569
|
+
c2_y 100
|
3570
|
+
end_x 400
|
3571
|
+
end_y 400
|
3572
|
+
}
|
3573
|
+
|
3574
|
+
closed true
|
3575
|
+
}
|
3576
|
+
|
3577
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
3578
|
+
stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
|
3579
|
+
}
|
3580
|
+
path { # declarative stable path
|
3581
|
+
arc {
|
3582
|
+
x_center 200
|
3583
|
+
y_center 200
|
3584
|
+
radius 90
|
3585
|
+
start_angle 0
|
3586
|
+
sweep 360
|
3587
|
+
is_negative false
|
3588
|
+
}
|
3589
|
+
|
3590
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
3591
|
+
stroke r: 0, g: 0, b: 0, thickness: 2
|
3592
|
+
}
|
3593
|
+
|
3594
|
+
on_mouse_event do |area_mouse_event|
|
3595
|
+
p area_mouse_event
|
3596
|
+
end
|
3597
|
+
|
3598
|
+
on_mouse_moved do |area_mouse_event|
|
3599
|
+
puts 'moved'
|
3600
|
+
end
|
3601
|
+
|
3602
|
+
on_mouse_down do |area_mouse_event|
|
3603
|
+
puts 'mouse down'
|
3604
|
+
end
|
3605
|
+
|
3606
|
+
on_mouse_up do |area_mouse_event|
|
3607
|
+
puts 'mouse up'
|
3608
|
+
end
|
3609
|
+
|
3610
|
+
on_mouse_drag_started do |area_mouse_event|
|
3611
|
+
puts 'drag started'
|
3612
|
+
end
|
3613
|
+
|
3614
|
+
on_mouse_dragged do |area_mouse_event|
|
3615
|
+
puts 'dragged'
|
3616
|
+
end
|
3617
|
+
|
3618
|
+
on_mouse_dropped do |area_mouse_event|
|
3619
|
+
puts 'dropped'
|
3620
|
+
end
|
3621
|
+
|
3622
|
+
on_mouse_entered do
|
3623
|
+
puts 'entered'
|
3624
|
+
end
|
3625
|
+
|
3626
|
+
on_mouse_exited do
|
3627
|
+
puts 'exited'
|
3628
|
+
end
|
3629
|
+
}
|
3630
|
+
}.show
|
3631
|
+
```
|
3632
|
+
|
3633
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 3 (semi-declarative `on_draw` dynamic `path` approach):
|
3634
|
+
|
3635
|
+
```ruby
|
3636
|
+
require 'glimmer-dsl-libui'
|
3637
|
+
|
3638
|
+
include Glimmer
|
3639
|
+
|
3640
|
+
window('Area Gallery', 400, 400) {
|
3641
|
+
area {
|
3642
|
+
on_draw do |area_draw_params|
|
3643
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3250
3644
|
square(0, 0, 100)
|
3251
3645
|
square(100, 100, 400)
|
3252
3646
|
|
3253
3647
|
fill r: 102, g: 102, b: 204
|
3254
3648
|
}
|
3255
|
-
path { #
|
3649
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3256
3650
|
rectangle(0, 100, 100, 400)
|
3257
3651
|
rectangle(100, 0, 400, 100)
|
3258
|
-
|
3652
|
+
|
3259
3653
|
fill r: 204, g: 102, b: 204
|
3260
3654
|
}
|
3261
|
-
path { #
|
3655
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3262
3656
|
figure(100, 100) {
|
3263
3657
|
line(100, 400)
|
3264
3658
|
line(400, 100)
|
@@ -3270,7 +3664,7 @@ window('Area Gallery', 400, 400) {
|
|
3270
3664
|
fill r: 202, g: 102, b: 104, a: 0.5
|
3271
3665
|
stroke r: 0, g: 0, b: 0
|
3272
3666
|
}
|
3273
|
-
path { #
|
3667
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3274
3668
|
figure(0, 0) {
|
3275
3669
|
bezier(200, 100, 100, 200, 400, 100)
|
3276
3670
|
bezier(300, 100, 100, 300, 100, 400)
|
@@ -3280,20 +3674,56 @@ window('Area Gallery', 400, 400) {
|
|
3280
3674
|
}
|
3281
3675
|
|
3282
3676
|
fill r: 202, g: 102, b: 204, a: 0.5
|
3283
|
-
stroke
|
3677
|
+
stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
|
3284
3678
|
}
|
3285
|
-
path { #
|
3679
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3286
3680
|
arc(200, 200, 90, 0, 360, false)
|
3287
3681
|
|
3288
3682
|
fill r: 202, g: 102, b: 204, a: 0.5
|
3289
|
-
stroke
|
3683
|
+
stroke r: 0, g: 0, b: 0, thickness: 2
|
3290
3684
|
}
|
3291
|
-
|
3685
|
+
end
|
3686
|
+
|
3687
|
+
on_mouse_event do |area_mouse_event|
|
3688
|
+
p area_mouse_event
|
3689
|
+
end
|
3690
|
+
|
3691
|
+
on_mouse_moved do |area_mouse_event|
|
3692
|
+
puts 'moved'
|
3693
|
+
end
|
3694
|
+
|
3695
|
+
on_mouse_down do |area_mouse_event|
|
3696
|
+
puts 'mouse down'
|
3697
|
+
end
|
3698
|
+
|
3699
|
+
on_mouse_up do |area_mouse_event|
|
3700
|
+
puts 'mouse up'
|
3701
|
+
end
|
3702
|
+
|
3703
|
+
on_mouse_drag_started do |area_mouse_event|
|
3704
|
+
puts 'drag started'
|
3705
|
+
end
|
3706
|
+
|
3707
|
+
on_mouse_dragged do |area_mouse_event|
|
3708
|
+
puts 'dragged'
|
3709
|
+
end
|
3710
|
+
|
3711
|
+
on_mouse_dropped do |area_mouse_event|
|
3712
|
+
puts 'dropped'
|
3713
|
+
end
|
3714
|
+
|
3715
|
+
on_mouse_entered do
|
3716
|
+
puts 'entered'
|
3717
|
+
end
|
3718
|
+
|
3719
|
+
on_mouse_exited do
|
3720
|
+
puts 'exited'
|
3721
|
+
end
|
3292
3722
|
}
|
3293
3723
|
}.show
|
3294
3724
|
```
|
3295
3725
|
|
3296
|
-
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version
|
3726
|
+
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):
|
3297
3727
|
|
3298
3728
|
```ruby
|
3299
3729
|
require 'glimmer-dsl-libui'
|
@@ -3301,9 +3731,9 @@ require 'glimmer-dsl-libui'
|
|
3301
3731
|
include Glimmer
|
3302
3732
|
|
3303
3733
|
window('Area Gallery', 400, 400) {
|
3304
|
-
|
3305
|
-
|
3306
|
-
path { #
|
3734
|
+
area {
|
3735
|
+
on_draw do |area_draw_params|
|
3736
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3307
3737
|
square {
|
3308
3738
|
x 0
|
3309
3739
|
y 0
|
@@ -3317,7 +3747,7 @@ window('Area Gallery', 400, 400) {
|
|
3317
3747
|
|
3318
3748
|
fill r: 102, g: 102, b: 204
|
3319
3749
|
}
|
3320
|
-
path { #
|
3750
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3321
3751
|
rectangle {
|
3322
3752
|
x 0
|
3323
3753
|
y 100
|
@@ -3333,7 +3763,7 @@ window('Area Gallery', 400, 400) {
|
|
3333
3763
|
|
3334
3764
|
fill r: 204, g: 102, b: 204
|
3335
3765
|
}
|
3336
|
-
path { #
|
3766
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3337
3767
|
figure {
|
3338
3768
|
x 100
|
3339
3769
|
y 100
|
@@ -3357,7 +3787,7 @@ window('Area Gallery', 400, 400) {
|
|
3357
3787
|
fill r: 202, g: 102, b: 104, a: 0.5
|
3358
3788
|
stroke r: 0, g: 0, b: 0
|
3359
3789
|
}
|
3360
|
-
path { #
|
3790
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3361
3791
|
figure {
|
3362
3792
|
x 0
|
3363
3793
|
y 0
|
@@ -3391,9 +3821,9 @@ window('Area Gallery', 400, 400) {
|
|
3391
3821
|
}
|
3392
3822
|
|
3393
3823
|
fill r: 202, g: 102, b: 204, a: 0.5
|
3394
|
-
stroke
|
3824
|
+
stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
|
3395
3825
|
}
|
3396
|
-
path { #
|
3826
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3397
3827
|
arc {
|
3398
3828
|
x_center 200
|
3399
3829
|
y_center 200
|
@@ -3404,185 +3834,383 @@ window('Area Gallery', 400, 400) {
|
|
3404
3834
|
}
|
3405
3835
|
|
3406
3836
|
fill r: 202, g: 102, b: 204, a: 0.5
|
3407
|
-
stroke
|
3837
|
+
stroke r: 0, g: 0, b: 0, thickness: 2
|
3408
3838
|
}
|
3409
|
-
|
3839
|
+
end
|
3840
|
+
|
3841
|
+
on_mouse_event do |area_mouse_event|
|
3842
|
+
p area_mouse_event
|
3843
|
+
end
|
3844
|
+
|
3845
|
+
on_mouse_moved do |area_mouse_event|
|
3846
|
+
puts 'moved'
|
3847
|
+
end
|
3848
|
+
|
3849
|
+
on_mouse_down do |area_mouse_event|
|
3850
|
+
puts 'mouse down'
|
3851
|
+
end
|
3852
|
+
|
3853
|
+
on_mouse_up do |area_mouse_event|
|
3854
|
+
puts 'mouse up'
|
3855
|
+
end
|
3856
|
+
|
3857
|
+
on_mouse_drag_started do |area_mouse_event|
|
3858
|
+
puts 'drag started'
|
3859
|
+
end
|
3860
|
+
|
3861
|
+
on_mouse_dragged do |area_mouse_event|
|
3862
|
+
puts 'dragged'
|
3863
|
+
end
|
3864
|
+
|
3865
|
+
on_mouse_dropped do |area_mouse_event|
|
3866
|
+
puts 'dropped'
|
3867
|
+
end
|
3868
|
+
|
3869
|
+
on_mouse_entered do
|
3870
|
+
puts 'entered'
|
3871
|
+
end
|
3872
|
+
|
3873
|
+
on_mouse_exited do
|
3874
|
+
puts 'exited'
|
3875
|
+
end
|
3410
3876
|
}
|
3411
3877
|
}.show
|
3412
3878
|
```
|
3413
3879
|
|
3414
|
-
|
3880
|
+
### Histogram
|
3881
|
+
|
3882
|
+
[examples/histogram.rb](examples/histogram.rb)
|
3883
|
+
|
3884
|
+
Run with this command from the root of the project if you cloned the project:
|
3885
|
+
|
3886
|
+
```
|
3887
|
+
ruby -r './lib/glimmer-dsl-libui' examples/histogram.rb
|
3888
|
+
```
|
3889
|
+
|
3890
|
+
Run with this command if you installed the [Ruby gem](https://rubygems.org/gems/glimmer-dsl-libui):
|
3891
|
+
|
3892
|
+
```
|
3893
|
+
ruby -r glimmer-dsl-libui -e "require 'examples/histogram'"
|
3894
|
+
```
|
3895
|
+
|
3896
|
+
Mac
|
3897
|
+
|
3898
|
+

|
3899
|
+
|
3900
|
+
Linux
|
3901
|
+
|
3902
|
+

|
3903
|
+
|
3904
|
+
[LibUI](https://github.com/kojix2/LibUI) Original Version:
|
3415
3905
|
|
3416
3906
|
```ruby
|
3417
|
-
|
3907
|
+
# https://github.com/jamescook/libui-ruby/blob/master/example/histogram.rb
|
3418
3908
|
|
3419
|
-
|
3909
|
+
require 'libui'
|
3420
3910
|
|
3421
|
-
|
3422
|
-
vertical_box {
|
3423
|
-
area {
|
3424
|
-
on_draw do |area_draw_params|
|
3425
|
-
path(area_draw_params) { # a dynamic path is added semi-declaratively inside on_draw block
|
3426
|
-
square(0, 0, 100)
|
3427
|
-
square(100, 100, 400)
|
3428
|
-
|
3429
|
-
fill r: 102, g: 102, b: 204
|
3430
|
-
}
|
3431
|
-
path(area_draw_params) { # a dynamic path is added semi-declaratively inside on_draw block
|
3432
|
-
rectangle(0, 100, 100, 400)
|
3433
|
-
rectangle(100, 0, 400, 100)
|
3911
|
+
UI = LibUI
|
3434
3912
|
|
3435
|
-
|
3436
|
-
|
3437
|
-
|
3438
|
-
|
3439
|
-
|
3440
|
-
|
3441
|
-
|
3913
|
+
X_OFF_LEFT = 20
|
3914
|
+
Y_OFF_TOP = 20
|
3915
|
+
X_OFF_RIGHT = 20
|
3916
|
+
Y_OFF_BOTTOM = 20
|
3917
|
+
POINT_RADIUS = 5
|
3918
|
+
|
3919
|
+
init = UI.init
|
3920
|
+
handler = UI::FFI::AreaHandler.malloc
|
3921
|
+
histogram = UI.new_area(handler)
|
3922
|
+
brush = UI::FFI::DrawBrush.malloc
|
3923
|
+
color_button = UI.new_color_button
|
3924
|
+
blue = 0x1E90FF
|
3925
|
+
datapoints = []
|
3926
|
+
|
3927
|
+
def graph_size(area_width, area_height)
|
3928
|
+
graph_width = area_width - X_OFF_LEFT - X_OFF_RIGHT
|
3929
|
+
graph_height = area_height - Y_OFF_TOP - Y_OFF_BOTTOM
|
3930
|
+
[graph_width, graph_height]
|
3931
|
+
end
|
3442
3932
|
|
3443
|
-
|
3444
|
-
}
|
3933
|
+
matrix = UI::FFI::DrawMatrix.malloc
|
3445
3934
|
|
3446
|
-
|
3447
|
-
|
3448
|
-
|
3449
|
-
path(area_draw_params) { # a dynamic path is added semi-declaratively inside on_draw block
|
3450
|
-
figure(0, 0) {
|
3451
|
-
bezier(200, 100, 100, 200, 400, 100)
|
3452
|
-
bezier(300, 100, 100, 300, 100, 400)
|
3453
|
-
bezier(100, 300, 300, 100, 400, 400)
|
3935
|
+
def point_locations(datapoints, width, height)
|
3936
|
+
xincr = width / 9.0 # 10 - 1 to make the last point be at the end
|
3937
|
+
yincr = height / 100.0
|
3454
3938
|
|
3455
|
-
|
3456
|
-
|
3939
|
+
data = []
|
3940
|
+
datapoints.each_with_index do |dp, i|
|
3941
|
+
val = 100 - UI.spinbox_value(dp)
|
3942
|
+
data << [xincr * i, yincr * val]
|
3943
|
+
i += 1
|
3944
|
+
end
|
3457
3945
|
|
3458
|
-
|
3459
|
-
|
3460
|
-
}
|
3461
|
-
path(area_draw_params) { # a dynamic path is added semi-declaratively inside on_draw block
|
3462
|
-
arc(200, 200, 90, 0, 360, false)
|
3946
|
+
data
|
3947
|
+
end
|
3463
3948
|
|
3464
|
-
|
3465
|
-
|
3466
|
-
|
3467
|
-
|
3468
|
-
|
3469
|
-
|
3470
|
-
|
3949
|
+
def construct_graph(datapoints, width, height, should_extend)
|
3950
|
+
locations = point_locations(datapoints, width, height)
|
3951
|
+
path = UI.draw_new_path(0) # winding
|
3952
|
+
first_location = locations[0] # x and y
|
3953
|
+
UI.draw_path_new_figure(path, first_location[0], first_location[1])
|
3954
|
+
locations.each do |loc|
|
3955
|
+
UI.draw_path_line_to(path, loc[0], loc[1])
|
3956
|
+
end
|
3957
|
+
|
3958
|
+
if should_extend
|
3959
|
+
UI.draw_path_line_to(path, width, height)
|
3960
|
+
UI.draw_path_line_to(path, 0, height)
|
3961
|
+
UI.draw_path_close_figure(path)
|
3962
|
+
end
|
3963
|
+
|
3964
|
+
UI.draw_path_end(path)
|
3965
|
+
|
3966
|
+
path
|
3967
|
+
end
|
3968
|
+
|
3969
|
+
handler_draw_event = Fiddle::Closure::BlockCaller.new(
|
3970
|
+
0, [1, 1, 1]
|
3971
|
+
) do |_area_handler, _area, area_draw_params|
|
3972
|
+
area_draw_params = UI::FFI::AreaDrawParams.new(area_draw_params)
|
3973
|
+
path = UI.draw_new_path(0) # winding
|
3974
|
+
UI.draw_path_add_rectangle(path, 0, 0, area_draw_params.AreaWidth, area_draw_params.AreaHeight)
|
3975
|
+
UI.draw_path_end(path)
|
3976
|
+
set_solid_brush(brush, 0xFFFFFF, 1.0) # white
|
3977
|
+
UI.draw_fill(area_draw_params.Context, path, brush.to_ptr)
|
3978
|
+
UI.draw_free_path(path)
|
3979
|
+
dsp = UI::FFI::DrawStrokeParams.malloc
|
3980
|
+
dsp.Cap = 0 # flat
|
3981
|
+
dsp.Join = 0 # miter
|
3982
|
+
dsp.Thickness = 2
|
3983
|
+
dsp.MiterLimit = 10 # DEFAULT_MITER_LIMIT
|
3984
|
+
dashes = Fiddle::Pointer.malloc(8)
|
3985
|
+
dsp.Dashes = dashes
|
3986
|
+
dsp.NumDashes = 0
|
3987
|
+
dsp.DashPhase = 0
|
3988
|
+
|
3989
|
+
# draw axes
|
3990
|
+
set_solid_brush(brush, 0x000000, 1.0) # black
|
3991
|
+
graph_width, graph_height = *graph_size(area_draw_params.AreaWidth, area_draw_params.AreaHeight)
|
3992
|
+
|
3993
|
+
path = UI.draw_new_path(0) # winding
|
3994
|
+
UI.draw_path_new_figure(path, X_OFF_LEFT, Y_OFF_TOP)
|
3995
|
+
UI.draw_path_line_to(path, X_OFF_LEFT, Y_OFF_TOP + graph_height)
|
3996
|
+
UI.draw_path_line_to(path, X_OFF_LEFT + graph_width, Y_OFF_TOP + graph_height)
|
3997
|
+
UI.draw_path_end(path)
|
3998
|
+
UI.draw_stroke(area_draw_params.Context, path, brush, dsp)
|
3999
|
+
UI.draw_free_path(path)
|
4000
|
+
|
4001
|
+
# now transform the coordinate space so (0, 0) is the top-left corner of the graph
|
4002
|
+
UI.draw_matrix_set_identity(matrix)
|
4003
|
+
UI.draw_matrix_translate(matrix, X_OFF_LEFT, Y_OFF_TOP)
|
4004
|
+
UI.draw_transform(area_draw_params.Context, matrix)
|
4005
|
+
|
4006
|
+
# now get the color for the graph itself and set up the brush
|
4007
|
+
# uiColorButtonColor(colorButton, &graphR, &graphG, &graphB, &graphA)
|
4008
|
+
graph_r = Fiddle::Pointer.malloc(8) # double
|
4009
|
+
graph_g = Fiddle::Pointer.malloc(8) # double
|
4010
|
+
graph_b = Fiddle::Pointer.malloc(8) # double
|
4011
|
+
graph_a = Fiddle::Pointer.malloc(8) # double
|
4012
|
+
|
4013
|
+
UI.color_button_color(color_button, graph_r, graph_g, graph_b, graph_a)
|
4014
|
+
brush.Type = 0 # solid
|
4015
|
+
brush.R = graph_r[0, 8].unpack1('d')
|
4016
|
+
brush.G = graph_g[0, 8].unpack1('d')
|
4017
|
+
brush.B = graph_b[0, 8].unpack1('d')
|
4018
|
+
|
4019
|
+
# now create the fill for the graph below the graph line
|
4020
|
+
path = construct_graph(datapoints, graph_width, graph_height, true)
|
4021
|
+
brush.A = graph_a[0, 8].unpack1('d') / 2.0
|
4022
|
+
UI.draw_fill(area_draw_params.Context, path, brush)
|
4023
|
+
UI.draw_free_path(path)
|
4024
|
+
|
4025
|
+
# now draw the histogram line
|
4026
|
+
path = construct_graph(datapoints, graph_width, graph_height, false)
|
4027
|
+
brush.A = graph_a[0, 8].unpack1('d')
|
4028
|
+
UI.draw_stroke(area_draw_params.Context, path, brush, dsp)
|
4029
|
+
UI.draw_free_path(path)
|
4030
|
+
end
|
4031
|
+
|
4032
|
+
handler.Draw = handler_draw_event
|
4033
|
+
|
4034
|
+
# Assigning to local variables
|
4035
|
+
# This is intended to protect Fiddle::Closure from garbage collection.
|
4036
|
+
# See https://github.com/kojix2/LibUI/issues/8
|
4037
|
+
handler.MouseEvent = (c1 = Fiddle::Closure::BlockCaller.new(0, [0]) {})
|
4038
|
+
handler.MouseCrossed = (c2 = Fiddle::Closure::BlockCaller.new(0, [0]) {})
|
4039
|
+
handler.DragBroken = (c3 = Fiddle::Closure::BlockCaller.new(0, [0]) {})
|
4040
|
+
handler.KeyEvent = (c4 = Fiddle::Closure::BlockCaller.new(1, [0]) { 0 })
|
4041
|
+
|
4042
|
+
UI.freeInitError(init) unless init.nil?
|
4043
|
+
|
4044
|
+
hbox = UI.new_horizontal_box
|
4045
|
+
UI.box_set_padded(hbox, 1)
|
4046
|
+
|
4047
|
+
vbox = UI.new_vertical_box
|
4048
|
+
UI.box_set_padded(vbox, 1)
|
4049
|
+
UI.box_append(hbox, vbox, 0)
|
4050
|
+
UI.box_append(hbox, histogram, 1)
|
4051
|
+
|
4052
|
+
datapoints = Array.new(10) do
|
4053
|
+
UI.new_spinbox(0, 100).tap do |datapoint|
|
4054
|
+
UI.spinbox_set_value(datapoint, Random.new.rand(90))
|
4055
|
+
UI.spinbox_on_changed(datapoint) do
|
4056
|
+
UI.area_queue_redraw_all(histogram)
|
4057
|
+
end
|
4058
|
+
UI.box_append(vbox, datapoint, 0)
|
4059
|
+
end
|
4060
|
+
end
|
4061
|
+
|
4062
|
+
def set_solid_brush(brush, color, alpha)
|
4063
|
+
brush.Type = 0 # solid
|
4064
|
+
brush.R = ((color >> 16) & 0xFF) / 255.0
|
4065
|
+
brush.G = ((color >> 8) & 0xFF) / 255.0
|
4066
|
+
brush.B = (color & 0xFF) / 255.0
|
4067
|
+
brush.A = alpha
|
4068
|
+
brush
|
4069
|
+
end
|
4070
|
+
|
4071
|
+
set_solid_brush(brush, blue, 1.0)
|
4072
|
+
UI.color_button_set_color(color_button, brush.R, brush.G, brush.B, brush.A)
|
4073
|
+
|
4074
|
+
UI.color_button_on_changed(color_button) do
|
4075
|
+
UI.area_queue_redraw_all(histogram)
|
4076
|
+
end
|
4077
|
+
|
4078
|
+
UI.box_append(vbox, color_button, 0)
|
4079
|
+
|
4080
|
+
MAIN_WINDOW = UI.new_window('histogram example', 640, 480, 1)
|
4081
|
+
UI.window_set_margined(MAIN_WINDOW, 1)
|
4082
|
+
UI.window_set_child(MAIN_WINDOW, hbox)
|
4083
|
+
|
4084
|
+
should_quit = proc do |_ptr|
|
4085
|
+
UI.control_destroy(MAIN_WINDOW)
|
4086
|
+
UI.quit
|
4087
|
+
0
|
4088
|
+
end
|
4089
|
+
|
4090
|
+
UI.window_on_closing(MAIN_WINDOW, should_quit)
|
4091
|
+
UI.on_should_quit(should_quit)
|
4092
|
+
UI.control_show(MAIN_WINDOW)
|
4093
|
+
|
4094
|
+
UI.main
|
4095
|
+
UI.quit
|
3471
4096
|
```
|
3472
4097
|
|
3473
|
-
|
4098
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
3474
4099
|
|
3475
4100
|
```ruby
|
4101
|
+
# https://github.com/jamescook/libui-ruby/blob/master/example/histogram.rb
|
4102
|
+
|
3476
4103
|
require 'glimmer-dsl-libui'
|
3477
4104
|
|
3478
4105
|
include Glimmer
|
3479
4106
|
|
3480
|
-
|
3481
|
-
|
3482
|
-
|
3483
|
-
|
3484
|
-
|
3485
|
-
|
3486
|
-
|
3487
|
-
|
3488
|
-
|
3489
|
-
|
3490
|
-
|
3491
|
-
|
3492
|
-
|
3493
|
-
|
3494
|
-
|
4107
|
+
X_OFF_LEFT = 20
|
4108
|
+
Y_OFF_TOP = 20
|
4109
|
+
X_OFF_RIGHT = 20
|
4110
|
+
Y_OFF_BOTTOM = 20
|
4111
|
+
POINT_RADIUS = 5
|
4112
|
+
COLOR_BLUE = 0x1E90FF
|
4113
|
+
|
4114
|
+
@datapoints = 10.times.map {Random.new.rand(90)}
|
4115
|
+
|
4116
|
+
def graph_size(area_width, area_height)
|
4117
|
+
graph_width = area_width - X_OFF_LEFT - X_OFF_RIGHT
|
4118
|
+
graph_height = area_height - Y_OFF_TOP - Y_OFF_BOTTOM
|
4119
|
+
[graph_width, graph_height]
|
4120
|
+
end
|
4121
|
+
|
4122
|
+
def point_locations(width, height)
|
4123
|
+
xincr = width / 9.0 # 10 - 1 to make the last point be at the end
|
4124
|
+
yincr = height / 100.0
|
4125
|
+
|
4126
|
+
@datapoints.each_with_index.map do |value, i|
|
4127
|
+
val = 100 - value
|
4128
|
+
[xincr * i, yincr * val]
|
4129
|
+
end
|
4130
|
+
end
|
4131
|
+
|
4132
|
+
# method-based custom control representing a graph path
|
4133
|
+
def graph_path(width, height, should_extend, &block)
|
4134
|
+
locations = point_locations(width, height)
|
4135
|
+
path {
|
4136
|
+
first_location = locations[0] # x and y
|
4137
|
+
figure(first_location[0], first_location[1]) {
|
4138
|
+
locations.each do |loc|
|
4139
|
+
line(loc[0], loc[1])
|
4140
|
+
end
|
4141
|
+
if should_extend
|
4142
|
+
line(width, height)
|
4143
|
+
line(0, height)
|
4144
|
+
|
4145
|
+
closed true
|
4146
|
+
end
|
4147
|
+
}
|
4148
|
+
|
4149
|
+
# apply a transform to the coordinate space for this path so (0, 0) is the top-left corner of the graph
|
4150
|
+
transform {
|
4151
|
+
translate X_OFF_LEFT, Y_OFF_TOP
|
4152
|
+
}
|
4153
|
+
|
4154
|
+
block.call
|
4155
|
+
}
|
4156
|
+
end
|
4157
|
+
|
4158
|
+
window('histogram example', 640, 480) {
|
4159
|
+
margined true
|
4160
|
+
|
4161
|
+
horizontal_box {
|
4162
|
+
vertical_box {
|
4163
|
+
stretchy false
|
4164
|
+
|
4165
|
+
10.times do |i|
|
4166
|
+
spinbox(0, 100) { |sb|
|
4167
|
+
stretchy false
|
4168
|
+
value @datapoints[i]
|
3495
4169
|
|
3496
|
-
|
4170
|
+
on_changed do
|
4171
|
+
@datapoints[i] = sb.value
|
4172
|
+
@area.queue_redraw_all
|
4173
|
+
end
|
3497
4174
|
}
|
3498
|
-
|
3499
|
-
|
3500
|
-
|
3501
|
-
|
3502
|
-
|
3503
|
-
|
3504
|
-
|
3505
|
-
|
3506
|
-
|
3507
|
-
|
3508
|
-
|
3509
|
-
|
3510
|
-
|
4175
|
+
end
|
4176
|
+
|
4177
|
+
@color_button = color_button {
|
4178
|
+
stretchy false
|
4179
|
+
color COLOR_BLUE
|
4180
|
+
|
4181
|
+
on_changed do
|
4182
|
+
@area.queue_redraw_all
|
4183
|
+
end
|
4184
|
+
}
|
4185
|
+
}
|
4186
|
+
|
4187
|
+
@area = area {
|
4188
|
+
on_draw do |area_draw_params|
|
4189
|
+
path {
|
4190
|
+
rectangle(0, 0, area_draw_params[:area_width], area_draw_params[:area_height])
|
3511
4191
|
|
3512
|
-
fill
|
4192
|
+
fill 0xFFFFFF
|
3513
4193
|
}
|
3514
|
-
|
3515
|
-
|
3516
|
-
|
3517
|
-
|
3518
|
-
|
3519
|
-
line
|
3520
|
-
|
3521
|
-
y 400
|
3522
|
-
}
|
3523
|
-
line {
|
3524
|
-
x 400
|
3525
|
-
y 100
|
3526
|
-
}
|
3527
|
-
line {
|
3528
|
-
x 400
|
3529
|
-
y 400
|
3530
|
-
}
|
3531
|
-
|
3532
|
-
closed true
|
4194
|
+
|
4195
|
+
graph_width, graph_height = *graph_size(area_draw_params[:area_width], area_draw_params[:area_height])
|
4196
|
+
|
4197
|
+
path {
|
4198
|
+
figure(X_OFF_LEFT, Y_OFF_TOP) {
|
4199
|
+
line(X_OFF_LEFT, Y_OFF_TOP + graph_height)
|
4200
|
+
line(X_OFF_LEFT + graph_width, Y_OFF_TOP + graph_height)
|
3533
4201
|
}
|
3534
|
-
|
3535
|
-
|
3536
|
-
stroke r: 0, g: 0, b: 0
|
4202
|
+
|
4203
|
+
stroke 0x000000, thickness: 2, miter_limit: 10
|
3537
4204
|
}
|
3538
|
-
|
3539
|
-
|
3540
|
-
|
3541
|
-
|
3542
|
-
|
3543
|
-
bezier {
|
3544
|
-
c1_x 200
|
3545
|
-
c1_y 100
|
3546
|
-
c2_x 100
|
3547
|
-
c2_y 200
|
3548
|
-
end_x 400
|
3549
|
-
end_y 100
|
3550
|
-
}
|
3551
|
-
bezier {
|
3552
|
-
c1_x 300
|
3553
|
-
c1_y 100
|
3554
|
-
c2_x 100
|
3555
|
-
c2_y 300
|
3556
|
-
end_x 100
|
3557
|
-
end_y 400
|
3558
|
-
}
|
3559
|
-
bezier {
|
3560
|
-
c1_x 100
|
3561
|
-
c1_y 300
|
3562
|
-
c2_x 300
|
3563
|
-
c2_y 100
|
3564
|
-
end_x 400
|
3565
|
-
end_y 400
|
3566
|
-
}
|
3567
|
-
|
3568
|
-
closed true
|
3569
|
-
}
|
3570
|
-
|
3571
|
-
fill r: 202, g: 102, b: 204, a: 0.5
|
3572
|
-
stroke thickness: 2, r: 0, g: 0, b: 0
|
4205
|
+
|
4206
|
+
# now create the fill for the graph below the graph line
|
4207
|
+
graph_path(graph_width, graph_height, true) {
|
4208
|
+
fill @color_button.color.merge(a: 0.5)
|
3573
4209
|
}
|
3574
|
-
|
3575
|
-
|
3576
|
-
|
3577
|
-
|
3578
|
-
radius 90
|
3579
|
-
start_angle 0
|
3580
|
-
sweep 360
|
3581
|
-
is_negative false
|
3582
|
-
}
|
3583
|
-
|
3584
|
-
fill r: 202, g: 102, b: 204, a: 0.5
|
3585
|
-
stroke thickness: 2, r: 0, g: 0, b: 0
|
4210
|
+
|
4211
|
+
# now draw the histogram line
|
4212
|
+
graph_path(graph_width, graph_height, false) {
|
4213
|
+
stroke @color_button.color.merge(thickness: 2, miter_limit: 10)
|
3586
4214
|
}
|
3587
4215
|
end
|
3588
4216
|
}
|
@@ -3590,6 +4218,62 @@ window('Area Gallery', 400, 400) {
|
|
3590
4218
|
}.show
|
3591
4219
|
```
|
3592
4220
|
|
4221
|
+
### Basic Transform
|
4222
|
+
|
4223
|
+
[examples/basic_transform.rb](examples/basic_transform.rb)
|
4224
|
+
|
4225
|
+
Run with this command from the root of the project if you cloned the project:
|
4226
|
+
|
4227
|
+
```
|
4228
|
+
ruby -r './lib/glimmer-dsl-libui' examples/basic_transform.rb
|
4229
|
+
```
|
4230
|
+
|
4231
|
+
Run with this command if you installed the [Ruby gem](https://rubygems.org/gems/glimmer-dsl-libui):
|
4232
|
+
|
4233
|
+
```
|
4234
|
+
ruby -r glimmer-dsl-libui -e "require 'examples/basic_transform'"
|
4235
|
+
```
|
4236
|
+
|
4237
|
+
Mac
|
4238
|
+
|
4239
|
+

|
4240
|
+
|
4241
|
+
Linux
|
4242
|
+
|
4243
|
+

|
4244
|
+
|
4245
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
4246
|
+
|
4247
|
+
```ruby
|
4248
|
+
require 'glimmer-dsl-libui'
|
4249
|
+
|
4250
|
+
include Glimmer
|
4251
|
+
|
4252
|
+
window('Basic Transform', 350, 350) {
|
4253
|
+
area {
|
4254
|
+
path {
|
4255
|
+
square(0, 0, 350)
|
4256
|
+
|
4257
|
+
fill r: 255, g: 255, b: 0
|
4258
|
+
}
|
4259
|
+
40.times do |n|
|
4260
|
+
path {
|
4261
|
+
square(0, 0, 100)
|
4262
|
+
|
4263
|
+
fill r: [255 - n*5, 0].max, g: [n*5, 255].min, b: 0, a: 0.5
|
4264
|
+
stroke :black, thickness: 2
|
4265
|
+
transform {
|
4266
|
+
skew 0.15, 0.15
|
4267
|
+
translate 50, 50
|
4268
|
+
rotate 100, 100, -9 * n
|
4269
|
+
scale 1.1, 1.1
|
4270
|
+
}
|
4271
|
+
}
|
4272
|
+
end
|
4273
|
+
}
|
4274
|
+
}.show
|
4275
|
+
```
|
4276
|
+
|
3593
4277
|
## Contributing to glimmer-dsl-libui
|
3594
4278
|
|
3595
4279
|
- Check out the latest master to make sure the feature hasn't been
|