glimmer-dsl-libui 0.1.4 → 0.1.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +55 -0
- data/README.md +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
|
[![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)
|
@@ -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
|
![glimmer-dsl-libui-mac-basic-area.png](images/glimmer-dsl-libui-mac-basic-area.png)
|
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
|
![glimmer-dsl-libui-mac-midi-player.png](images/glimmer-dsl-libui-mac-midi-player.png)
|
1101
|
-
![glimmer-dsl-libui-mac-midi-player-
|
1254
|
+
![glimmer-dsl-libui-mac-midi-player-msg-box.png](images/glimmer-dsl-libui-mac-midi-player-msg-box.png)
|
1102
1255
|
|
1103
1256
|
Linux
|
1104
1257
|
|
1105
1258
|
![glimmer-dsl-libui-linux-midi-player.png](images/glimmer-dsl-libui-linux-midi-player.png)
|
1106
|
-
![glimmer-dsl-libui-linux-midi-player-
|
1259
|
+
![glimmer-dsl-libui-linux-midi-player-msg-box.png](images/glimmer-dsl-libui-linux-midi-player-msg-box.png)
|
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
|
+
![glimmer-dsl-libui-mac-histogram.png](images/glimmer-dsl-libui-mac-histogram.png)
|
3899
|
+
|
3900
|
+
Linux
|
3901
|
+
|
3902
|
+
![glimmer-dsl-libui-linux-histogram.png](images/glimmer-dsl-libui-linux-histogram.png)
|
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
|
+
![glimmer-dsl-libui-mac-basic-transform.png](images/glimmer-dsl-libui-mac-basic-transform.png)
|
4240
|
+
|
4241
|
+
Linux
|
4242
|
+
|
4243
|
+
![glimmer-dsl-libui-linux-basic-transform.png](images/glimmer-dsl-libui-linux-basic-transform.png)
|
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
|