glimmer-dsl-libui 0.2.6 → 0.2.10
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 +30 -0
- data/README.md +530 -92
- data/VERSION +1 -1
- data/examples/area_gallery.rb +18 -8
- data/examples/area_gallery2.rb +26 -12
- data/examples/area_gallery3.rb +16 -6
- data/examples/area_gallery4.rb +26 -12
- data/examples/basic_table_button.rb +4 -0
- data/examples/basic_table_color.rb +39 -0
- data/examples/basic_table_progress_bar.rb +1 -1
- data/examples/color_button.rb +2 -0
- data/examples/custom_draw_text.rb +1 -1
- data/examples/custom_draw_text2.rb +1 -1
- data/examples/editable_table.rb +8 -0
- data/examples/form.rb +12 -2
- data/examples/form_table.rb +4 -0
- data/examples/meta_example.rb +27 -17
- data/examples/method_based_custom_keyword.rb +87 -0
- data/glimmer-dsl-libui.gemspec +0 -0
- data/icons/glimmer.png +0 -0
- data/lib/glimmer/libui/control_proxy/column/background_color_column_proxy.rb +38 -0
- data/lib/glimmer/libui/control_proxy/column/checkbox_text_color_column_proxy.rb +82 -0
- data/lib/glimmer/libui/control_proxy/column/image_text_color_column_proxy.rb +50 -0
- data/lib/glimmer/libui/control_proxy/column/text_color_column_proxy.rb +50 -0
- data/lib/glimmer/libui/control_proxy/editable_column.rb +1 -0
- data/lib/glimmer/libui/control_proxy/path_proxy.rb +31 -6
- data/lib/glimmer/libui/control_proxy/table_proxy.rb +53 -14
- data/lib/glimmer/libui/control_proxy/text_proxy.rb +1 -1
- data/lib/glimmer/libui/control_proxy/triple_column.rb +45 -0
- data/lib/glimmer/libui.rb +1 -1
- metadata +12 -4
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.2.
|
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.2.10
|
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)
|
@@ -14,10 +14,10 @@ The main trade-off in using [Glimmer DSL for LibUI](https://rubygems.org/gems/gl
|
|
14
14
|
- Declarative DSL syntax that visually maps to the GUI control hierarchy
|
15
15
|
- Convention over configuration via smart defaults and automation of low-level details
|
16
16
|
- Requiring the least amount of syntax possible to build GUI
|
17
|
-
- Bidirectional Data-Binding to declaratively wire and automatically synchronize GUI with Business Models
|
18
17
|
- Custom Control support
|
19
|
-
-
|
20
|
-
-
|
18
|
+
- [Far Future Plan] Bidirectional Data-Binding to declaratively wire and automatically synchronize GUI with Business Models
|
19
|
+
- [Far Future Plan] Scaffolding for new custom controls, apps, and gems
|
20
|
+
- [Far Future Plan] Native-Executable packaging on Mac, Windows, and Linux.
|
21
21
|
|
22
22
|
Hello, World!
|
23
23
|
|
@@ -61,7 +61,7 @@ window('Task Progress', 300, 200) {
|
|
61
61
|
|
62
62
|
on_clicked do
|
63
63
|
data.each_with_index do |row_data, row|
|
64
|
-
data[row] =
|
64
|
+
data[row][1] = 100 # automatically updates table due to implicit data-binding
|
65
65
|
end
|
66
66
|
end
|
67
67
|
}
|
@@ -84,14 +84,15 @@ window('Area Gallery', 400, 400) {
|
|
84
84
|
path { # declarative stable path
|
85
85
|
square(0, 0, 100)
|
86
86
|
square(100, 100, 400)
|
87
|
-
|
87
|
+
|
88
88
|
fill r: 102, g: 102, b: 204
|
89
89
|
}
|
90
90
|
path { # declarative stable path
|
91
91
|
rectangle(0, 100, 100, 400)
|
92
92
|
rectangle(100, 0, 400, 100)
|
93
|
-
|
94
|
-
|
93
|
+
|
94
|
+
# linear gradient (has x0, y0, x1, y1, and stops)
|
95
|
+
fill x0: 10, y0: 10, x1: 350, y1: 350, stops: [{pos: 0.25, r: 204, g: 102, b: 204}, {pos: 0.75, r: 102, g: 102, b: 204}]
|
95
96
|
}
|
96
97
|
path { # declarative stable path
|
97
98
|
figure(100, 100) {
|
@@ -117,17 +118,26 @@ window('Area Gallery', 400, 400) {
|
|
117
118
|
fill r: 202, g: 102, b: 204, a: 0.5
|
118
119
|
stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
|
119
120
|
}
|
121
|
+
path { # declarative stable path
|
122
|
+
arc(400, 220, 180, 90, 90, false)
|
123
|
+
|
124
|
+
# radial gradient (has an outer_radius in addition to x0, y0, x1, y1, and stops)
|
125
|
+
fill outer_radius: 90, x0: 0, y0: 0, x1: 500, y1: 500, stops: [{pos: 0.25, r: 102, g: 102, b: 204, a: 0.5}, {pos: 0.75, r: 204, g: 102, b: 204}]
|
126
|
+
stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
|
127
|
+
}
|
120
128
|
path { # declarative stable path
|
121
129
|
circle(200, 200, 90)
|
122
130
|
|
123
131
|
fill r: 202, g: 102, b: 204, a: 0.5
|
124
132
|
stroke r: 0, g: 0, b: 0, thickness: 2
|
125
133
|
}
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
134
|
+
text(160, 40, 100) { # x, y, width
|
135
|
+
string {
|
136
|
+
font family: 'Times', size: 14
|
137
|
+
color :black
|
138
|
+
|
139
|
+
'Area Gallery'
|
140
|
+
}
|
131
141
|
}
|
132
142
|
|
133
143
|
on_mouse_event do |area_mouse_event|
|
@@ -186,7 +196,7 @@ window('Area Gallery', 400, 400) {
|
|
186
196
|
|
187
197
|
[Check Out Many More Examples Over Here!](#examples)
|
188
198
|
|
189
|
-
NOTE: [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) is in
|
199
|
+
NOTE: [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) is feature-complete and in beta mode (though the C [libui](https://github.com/andlabs/libui) is still mid-alpha). Please help make better by contributing, adopting for small or low risk projects, and providing feedback. The more feedback and issues you report the better.
|
190
200
|
|
191
201
|
Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interested in:
|
192
202
|
- [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt): Glimmer DSL for SWT (JRuby Desktop Development GUI Framework)
|
@@ -197,7 +207,7 @@ Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interes
|
|
197
207
|
|
198
208
|
## Table of Contents
|
199
209
|
|
200
|
-
- [Glimmer DSL for LibUI 0.2.
|
210
|
+
- [Glimmer DSL for LibUI 0.2.10](#-glimmer-dsl-for-libui-0210)
|
201
211
|
- [Glimmer GUI DSL Concepts](#glimmer-gui-dsl-concepts)
|
202
212
|
- [Usage](#usage)
|
203
213
|
- [Girb (Glimmer IRB)](#girb-glimmer-irb)
|
@@ -211,8 +221,10 @@ Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interes
|
|
211
221
|
- [Table API](#table-api)
|
212
222
|
- [Area API](#area-api)
|
213
223
|
- [Smart Defaults and Conventions](#smart-defaults-and-conventions)
|
224
|
+
- [Custom Keywords](#custom-keywords)
|
214
225
|
- [API Gotchas](#api-gotchas)
|
215
226
|
- [Original API](#original-api)
|
227
|
+
- [Packaging](#packaging)
|
216
228
|
- [Glimmer Style Guide](#glimmer-style-guide)
|
217
229
|
- [Examples](#examples)
|
218
230
|
- [Basic Window](#basic-window)
|
@@ -235,6 +247,7 @@ Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interes
|
|
235
247
|
- [Basic Table Checkbox](#basic-table-checkbox)
|
236
248
|
- [Basic Table Checkbox Text](#basic-table-checkbox-text)
|
237
249
|
- [Basic Table Progress Bar](#basic-table-progress-bar)
|
250
|
+
- [Basic Table Color](#basic-table-color)
|
238
251
|
- [Form Table](#form-table)
|
239
252
|
- [Basic Area](#basic-area)
|
240
253
|
- [Dynamic Area](#dynamic-area)
|
@@ -246,6 +259,7 @@ Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interes
|
|
246
259
|
- [Color The Circles](#color-the-circles)
|
247
260
|
- [Basic Draw Text](#basic-draw-text)
|
248
261
|
- [Custom Draw Text](#custom-draw-text)
|
262
|
+
- [Method-Based Custom Keyword](#method-based-custom-keyword)
|
249
263
|
- [Contributing to glimmer-dsl-libui](#contributing-to-glimmer-dsl-libui)
|
250
264
|
- [Help](#help)
|
251
265
|
- [Issues](#issues)
|
@@ -333,7 +347,7 @@ gem install glimmer-dsl-libui
|
|
333
347
|
Or install via Bundler `Gemfile`:
|
334
348
|
|
335
349
|
```ruby
|
336
|
-
gem 'glimmer-dsl-libui', '~> 0.2.
|
350
|
+
gem 'glimmer-dsl-libui', '~> 0.2.10'
|
337
351
|
```
|
338
352
|
|
339
353
|
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.
|
@@ -409,12 +423,14 @@ Control(Args) | Properties | Listeners
|
|
409
423
|
`about_menu_item` | None | `on_clicked`
|
410
424
|
`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`, `on_key_event(area_key_event)`, `on_key_down(area_key_event)`, `on_key_up(area_key_event)`
|
411
425
|
`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
|
426
|
+
`background_color_column(name as String)` | None | None
|
412
427
|
`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
|
413
428
|
`button(text as String)` | `text` (`String`) | `on_clicked`
|
414
429
|
`button_column(name as String)` | `enabled` (Boolean) | None
|
415
430
|
`checkbox(text as String)` | `checked` (Boolean), `text` (`String`) | `on_toggled`
|
416
431
|
`checkbox_column(name as String)` | `editable` (Boolean) | None
|
417
432
|
`checkbox_text_column(name as String)` | `editable` (Boolean), `editable_checkbox` (Boolean), `editable_text` (Boolean) | None
|
433
|
+
`checkbox_text_color_column(name as String)` | `editable` (Boolean), `editable_checkbox` (Boolean), `editable_text` (Boolean) | None
|
418
434
|
`combobox` | `items` (`Array` of `String`), `selected` (`Integer`) | `on_selected`
|
419
435
|
`color_button` | `color` (Array of `red` as `Float`, `green` as `Float`, `blue` as `Float`, `alpha` as `Float`), `red` as `Float`, `green` as `Float`, `blue` as `Float`, `alpha` as `Float` | `on_changed`
|
420
436
|
`date_picker` | `time` (`Hash` of keys: `sec` as `Integer`, `min` as `Integer`, `hour` as `Integer`, `mday` as `Integer`, `mon` as `Integer`, `year` as `Integer`, `wday` as `Integer`, `yday` as `Integer`, `dst` as Boolean) | `on_changed`
|
@@ -432,6 +448,7 @@ Control(Args) | Properties | Listeners
|
|
432
448
|
`image_part(pixels as String [encoded image rgba byte array], width as Numeric, height as Numeric, byte_stride as Numeric [usually width*4])` | None | None
|
433
449
|
`image_column(name as String)` | None | None
|
434
450
|
`image_text_column(name as String)` | None | None
|
451
|
+
`image_text_color_column(name as String)` | None | None
|
435
452
|
`label(text as String)` | `text` (`String`) | None
|
436
453
|
`line(x as Numeric, y as Numeric)` | `x` (`Numeric`), `y` (`Numeric`) | None
|
437
454
|
`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
|
@@ -442,7 +459,7 @@ Control(Args) | Properties | Listeners
|
|
442
459
|
`msg_box_error(window = main_window as Glimmer::LibUI::WindowProxy, title as String, description as String)` | None | None
|
443
460
|
`non_wrapping_multiline_entry` | `read_only` (Boolean), `text` (`String`) | `on_changed`
|
444
461
|
`password_entry` | `read_only` (Boolean), `text` (`String`) | `on_changed`
|
445
|
-
`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
|
462
|
+
`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`, hex, or [X11](https://en.wikipedia.org/wiki/X11_color_names) color), `stroke` (`Hash` of `:r` as `0`-`255`, `:g` as `0`-`255`, `:b` as `0`-`255`, `:a` as `0.0`-`1.0`, hex, or [X11](https://en.wikipedia.org/wiki/X11_color_names) color), `:cap` as (`:round`, `:square`, `:flat`), `:join` as (`:miter`, `:round`, `:bevel`), `:thickness` as `Numeric`, `:miter_limit` as `Numeric`, `:dashes` as `Array` of `Numeric` ) | None
|
446
463
|
`preferences_menu_item` | None | `on_clicked`
|
447
464
|
`progress_bar` | `value` (`Numeric`) | None
|
448
465
|
`progress_bar_column(name as String)` | None | None
|
@@ -453,10 +470,13 @@ Control(Args) | Properties | Listeners
|
|
453
470
|
`slider(min as Numeric, max as Numeric)` | `value` (`Numeric`) | `on_changed`
|
454
471
|
`spinbox(min as Numeric, max as Numeric)` | `value` (`Numeric`) | `on_changed`
|
455
472
|
`square(x as Numeric, y as Numeric, length as Numeric)` | `x` (`Numeric`), `y` (`Numeric`), `length` (`Numeric`) | None
|
473
|
+
`string` | `font`, `color` (`Hash` of `:r` as `0`-`255`, `:g` as `0`-`255`, `:b` as `0`-`255`, `:a` as `0.0`-`1.0`, hex, or [X11](https://en.wikipedia.org/wiki/X11_color_names) color), `background` (`Hash` of `:r` as `0`-`255`, `:g` as `0`-`255`, `:b` as `0`-`255`, `:a` as `0.0`-`1.0`, hex, or [X11](https://en.wikipedia.org/wiki/X11_color_names) color), `underline`, `underline_color` (`Hash` of `:r` as `0`-`255`, `:g` as `0`-`255`, `:b` as `0`-`255`, `:a` as `0.0`-`1.0`, hex, or [X11](https://en.wikipedia.org/wiki/X11_color_names) color), `open_type_features` | None
|
456
474
|
`tab` | `margined` (Boolean), `num_pages` (`Integer`) | None
|
457
475
|
`tab_item(name as String)` | `index` [read-only] (`Integer`), `margined` (Boolean), `name` [read-only] (`String`) | None
|
458
|
-
`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 |
|
476
|
+
`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 | `on_changed {|row, type, row_data| ...}`, `on_edited {|row, row_data| ...}`
|
477
|
+
`text(x = 0 as Numeric, y = 0 as Numeric, width = area_width as Numeric)` | `align`, `default_font` | None
|
459
478
|
`text_column(name as String)` | `editable` (Boolean) | None
|
479
|
+
`text_color_column(name as String)` | `editable` (Boolean) | None
|
460
480
|
`time_picker` | `time` (`Hash` of keys: `sec` as `Integer`, `min` as `Integer`, `hour` as `Integer`) | `on_changed`
|
461
481
|
`vertical_box` | `padded` (Boolean) | None
|
462
482
|
`vertical_separator` | None | None
|
@@ -510,12 +530,16 @@ All operations that could normally be called on `LibUI` can also be called on `G
|
|
510
530
|
### Table API
|
511
531
|
|
512
532
|
The `table` control must first declare its columns via one of these column keywords (mentioned in [Supported Controls](#supported-controls)):
|
533
|
+
- `background_color_column`: expects color cell values
|
513
534
|
- `button_column`: expects `String` cell values
|
514
535
|
- `checkbox_column`: expects Boolean cell values
|
515
536
|
- `checkbox_text_column`: expects dual-element `Array` of Boolean and `String` cell values
|
537
|
+
- `checkbox_text_color_column`: expects triple-element `Array` of Boolean, `String`, and color cell values
|
516
538
|
- `image_column`: expects `image` cell values (produced by `image` and `image_part` keywords as per [Supported Controls](#supported-controls))
|
517
539
|
- `image_text_column`: expects dual-element `Array` of `image` and `String` cell values
|
540
|
+
- `image_text_color_column`: expects triple-element `Array` of `image`, `String`, and color cell values
|
518
541
|
- `text_column`: expects `String` cell values
|
542
|
+
- `text_color_column`: expects dual-element `Array` of `String` and color cell values
|
519
543
|
- `progress_bar_column`: expects `Integer` cell values
|
520
544
|
|
521
545
|
Afterwards, it must declare its `cell_rows` array (`Array` of `Array`s of column cell values) and whether it is `editable` (Boolean) for all its columns.
|
@@ -798,11 +822,11 @@ To draw `text` in an `area`, you simply nest a `text(x, y, width)` control direc
|
|
798
822
|
|
799
823
|
`string` can have the following properties:
|
800
824
|
- `font`: font descriptor hash consisting of `:family`, `:size`, `:weight` (`[:minimum, :thin, :ultra_light, :light, :book, :normal, :medium, :semi_bold, :bold, :ultra_bold, :heavy, :ultra_heavy, :maximum]`), `:italic` (`[:normal, :oblique, :italic]`), and `:stretch` (`[:ultra_condensed, :extra_condensed, :condensed, :semi_condensed, :normal, :semi_expanded, :expanded, :extra_expanded, :ultra_expanded]`) key values
|
801
|
-
- `color`: rgba, hex, or
|
802
|
-
- `background`: rgba, hex, or
|
825
|
+
- `color`: rgba, hex, or [X11](https://en.wikipedia.org/wiki/X11_color_names) color
|
826
|
+
- `background`: rgba, hex, or [X11](https://en.wikipedia.org/wiki/X11_color_names) color
|
803
827
|
- `underline`: one of `:none`, `:single`, `:double`, `:suggestion`, `:color_custom`, `:color_spelling`, `:color_grammar`, `:color_auxiliary`
|
804
|
-
- `underline_color`: one of `:spelling`, `:grammar`, `:auxiliary`, rgba, hex, or
|
805
|
-
- `open_type_features`:
|
828
|
+
- `underline_color`: one of `:spelling`, `:grammar`, `:auxiliary`, rgba, hex, or [X11](https://en.wikipedia.org/wiki/X11_color_names) color
|
829
|
+
- `open_type_features`: Open Type Features (https://www.microsoft.com/typography/otspec/featuretags.htm) consist of `open_type_tag`s nested in content block, which accept (`a`, `b`, `c`, `d`, `Integer`) arguments.
|
806
830
|
|
807
831
|
Example (you may copy/paste in [`girb`](#girb-glimmer-irb)):
|
808
832
|
|
@@ -871,16 +895,126 @@ window('area text drawing') {
|
|
871
895
|
- 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)
|
872
896
|
- Color alpha value defaults to `1.0` when not specified.
|
873
897
|
|
898
|
+
### Custom Keywords
|
899
|
+
|
900
|
+
To define custom keywords, simply define a method representing the custom control you want. To make reusable, you can define in modules and simply include the modules in the view classes that need them.
|
901
|
+
|
902
|
+
Example that defines `field`, `address_form`, `label_pair`, and `address` keywords (you may copy/paste in [`girb`](#girb-glimmer-irb)):
|
903
|
+
|
904
|
+
```ruby
|
905
|
+
require 'glimmer-dsl-libui'
|
906
|
+
require 'facets'
|
907
|
+
|
908
|
+
include Glimmer
|
909
|
+
|
910
|
+
Address = Struct.new(:street, :p_o_box, :city, :state, :zip_code)
|
911
|
+
|
912
|
+
def field(model, property)
|
913
|
+
property = property.to_s
|
914
|
+
entry { |e|
|
915
|
+
label property.underscore.split('_').map(&:capitalize).join(' ')
|
916
|
+
text model.send(property).to_s
|
917
|
+
|
918
|
+
on_changed do
|
919
|
+
model.send("#{property}=", e.text)
|
920
|
+
end
|
921
|
+
}
|
922
|
+
end
|
923
|
+
|
924
|
+
def address_form(address)
|
925
|
+
form {
|
926
|
+
field(address, :street)
|
927
|
+
field(address, :p_o_box)
|
928
|
+
field(address, :city)
|
929
|
+
field(address, :state)
|
930
|
+
field(address, :zip_code)
|
931
|
+
}
|
932
|
+
end
|
933
|
+
|
934
|
+
def label_pair(model, attribute, value)
|
935
|
+
name_label = nil
|
936
|
+
value_label = nil
|
937
|
+
horizontal_box {
|
938
|
+
name_label = label(attribute.to_s.underscore.split('_').map(&:capitalize).join(' '))
|
939
|
+
value_label = label(value.to_s)
|
940
|
+
}
|
941
|
+
Glimmer::DataBinding::Observer.proc do
|
942
|
+
value_label.text = model.send(attribute)
|
943
|
+
end.observe(model, attribute)
|
944
|
+
end
|
945
|
+
|
946
|
+
def address(address)
|
947
|
+
vertical_box {
|
948
|
+
address.each_pair do |attribute, value|
|
949
|
+
label_pair(address, attribute, value)
|
950
|
+
end
|
951
|
+
}
|
952
|
+
end
|
953
|
+
|
954
|
+
address1 = Address.new('123 Main St', '23923', 'Denver', 'Colorado', '80014')
|
955
|
+
address2 = Address.new('2038 Park Ave', '83272', 'Boston', 'Massachusetts', '02101')
|
956
|
+
|
957
|
+
window('Method-Based Custom Keyword') {
|
958
|
+
margined true
|
959
|
+
|
960
|
+
horizontal_box {
|
961
|
+
vertical_box {
|
962
|
+
label('Address 1') {
|
963
|
+
stretchy false
|
964
|
+
}
|
965
|
+
address_form(address1)
|
966
|
+
horizontal_separator {
|
967
|
+
stretchy false
|
968
|
+
}
|
969
|
+
label('Address 1 (Saved)') {
|
970
|
+
stretchy false
|
971
|
+
}
|
972
|
+
address(address1)
|
973
|
+
}
|
974
|
+
vertical_separator {
|
975
|
+
stretchy false
|
976
|
+
}
|
977
|
+
vertical_box {
|
978
|
+
label('Address 2') {
|
979
|
+
stretchy false
|
980
|
+
}
|
981
|
+
address_form(address2)
|
982
|
+
horizontal_separator {
|
983
|
+
stretchy false
|
984
|
+
}
|
985
|
+
label('Address 2 (Saved)') {
|
986
|
+
stretchy false
|
987
|
+
}
|
988
|
+
address(address2)
|
989
|
+
}
|
990
|
+
}
|
991
|
+
}.show
|
992
|
+
```
|
993
|
+
|
994
|
+

|
995
|
+
|
874
996
|
### API Gotchas
|
875
997
|
|
876
998
|
- There is no proper way to destroy `grid` children due to [libui](https://github.com/andlabs/libui) not offering any API for deleting them from `grid` (no `grid_delete` similar to `box_delete` for `horizontal_box` and `vertical_box`).
|
877
999
|
- `table` `checkbox_column` and `checkbox_text_column` checkbox editing only works on Windows and Linux (not Mac) due to a current limitation in [libui](https://github.com/andlabs/ui/issues/357).
|
878
|
-
-
|
1000
|
+
- `text` `align` property seems not to work on the Mac ([libui](https://github.com/andlabs/libui) has an [issue](https://github.com/andlabs/libui/pull/407) about it)
|
879
1001
|
|
880
1002
|
### Original API
|
881
1003
|
|
882
|
-
To learn more about the [LibUI](https://github.com/kojix2/LibUI) API exposed through [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui)
|
883
|
-
|
1004
|
+
To learn more about the [LibUI](https://github.com/kojix2/LibUI) API exposed through [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui):
|
1005
|
+
- Check out [LibUI ffi.rb](https://github.com/kojix2/LibUI/blob/main/lib/libui/ffi.rb)
|
1006
|
+
- Check out the [libui C headers](https://github.com/andlabs/libui/blob/master/ui.h)
|
1007
|
+
- Check out the [Go UI (Golang LibUI) documentation](https://pkg.go.dev/github.com/andlabs/ui) for an alternative well-documented [libui](https://github.com/andlabs/libui) reference.
|
1008
|
+
|
1009
|
+
## Packaging
|
1010
|
+
|
1011
|
+
I am documenting options for packaging, which I have not tried myself, but figured they would still be useful to add to the README.md until I can expand further effort into supporting packaging.
|
1012
|
+
|
1013
|
+
For Windows, the [LibUI](https://github.com/kojix2/LibUI) project recommends [OCRA](https://github.com/larsch/ocra) (One-Click Ruby Application), which builds Windows executables from Ruby source.
|
1014
|
+
|
1015
|
+
For Mac, consider [Platybus](https://github.com/sveinbjornt/Platypus) (builds a native Mac app from a Ruby script)
|
1016
|
+
|
1017
|
+
For Linux, simply package your app as a [Ruby Gem](https://guides.rubygems.org/what-is-a-gem/) and [build rpm package from Ruby Gem](https://www.redpill-linpro.com/sysadvent/2015/12/07/building-rpms-from-gems.html) or [build deb package from Ruby Gem](https://openpreservation.org/blogs/building-debian-package-ruby-program/).
|
884
1018
|
|
885
1019
|
## Glimmer Style Guide
|
886
1020
|
|
@@ -897,8 +1031,6 @@ The following examples include reimplementions of the examples in the [LibUI](ht
|
|
897
1031
|
|
898
1032
|
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.
|
899
1033
|
|
900
|
-
(note that for examples that emit output to terminal/command-line via `p` or `puts`, you must run them directly to see output)
|
901
|
-
|
902
1034
|
[examples/meta_example.rb](examples/meta_example.rb)
|
903
1035
|
|
904
1036
|
Run with this command from the root of the project if you cloned the project:
|
@@ -924,65 +1056,118 @@ Linux
|
|
924
1056
|
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
925
1057
|
|
926
1058
|
```ruby
|
1059
|
+
# frozen_string_literal: true
|
1060
|
+
|
927
1061
|
require 'glimmer-dsl-libui'
|
928
1062
|
require 'facets'
|
929
1063
|
|
930
1064
|
class MetaExample
|
931
1065
|
include Glimmer
|
932
1066
|
|
1067
|
+
def initialize
|
1068
|
+
@selected_example_index = 0
|
1069
|
+
end
|
1070
|
+
|
933
1071
|
def examples
|
934
1072
|
if @examples.nil?
|
935
1073
|
example_files = Dir.glob(File.join(File.expand_path('.', __dir__), '**', '*.rb'))
|
936
1074
|
example_file_names = example_files.map { |f| File.basename(f, '.rb') }
|
937
|
-
example_file_names = example_file_names.reject { |f| f == 'meta_example' }
|
1075
|
+
example_file_names = example_file_names.reject { |f| f == 'meta_example' || f.match(/\d$/) }
|
938
1076
|
@examples = example_file_names.map { |f| f.underscore.titlecase }
|
939
1077
|
end
|
940
1078
|
@examples
|
941
1079
|
end
|
942
1080
|
|
1081
|
+
def examples_with_versions
|
1082
|
+
examples.map do |example|
|
1083
|
+
version_count_for(example) > 1 ? "#{example} (#{version_count_for(example)} versions)" : example
|
1084
|
+
end
|
1085
|
+
end
|
1086
|
+
|
943
1087
|
def file_path_for(example)
|
944
1088
|
File.join(File.expand_path('.', __dir__), "#{example.underscore}.rb")
|
945
1089
|
end
|
946
1090
|
|
1091
|
+
def version_count_for(example)
|
1092
|
+
Dir.glob(File.join(File.expand_path('.', __dir__), "#{example.underscore}*.rb")).select {|file| file.match(/\d\.rb$/)}.count + 1
|
1093
|
+
end
|
1094
|
+
|
947
1095
|
def glimmer_dsl_libui_file
|
948
1096
|
File.expand_path('../lib/glimmer-dsl-libui', __dir__)
|
949
1097
|
end
|
950
1098
|
|
1099
|
+
def selected_example
|
1100
|
+
examples[@selected_example_index]
|
1101
|
+
end
|
1102
|
+
|
951
1103
|
def launch
|
952
1104
|
window('Meta-Example', 700, 500) {
|
953
1105
|
margined true
|
954
1106
|
|
955
1107
|
horizontal_box {
|
956
1108
|
vertical_box {
|
957
|
-
|
1109
|
+
stretchy false
|
1110
|
+
|
1111
|
+
@example_radio_buttons = radio_buttons {
|
958
1112
|
stretchy false
|
959
|
-
items
|
960
|
-
selected
|
1113
|
+
items examples_with_versions
|
1114
|
+
selected @selected_example_index
|
961
1115
|
|
962
1116
|
on_selected do
|
963
|
-
@
|
1117
|
+
@selected_example_index = @example_radio_buttons.selected
|
1118
|
+
example = selected_example
|
1119
|
+
@code_entry.text = File.read(file_path_for(example))
|
1120
|
+
@version_spinbox.value = 1
|
964
1121
|
end
|
965
1122
|
}
|
966
|
-
|
1123
|
+
|
1124
|
+
horizontal_box {
|
1125
|
+
label('Version') {
|
1126
|
+
stretchy false
|
1127
|
+
}
|
1128
|
+
|
1129
|
+
@version_spinbox = spinbox(1, 100) {
|
1130
|
+
value 1
|
1131
|
+
|
1132
|
+
on_changed do
|
1133
|
+
example = selected_example
|
1134
|
+
if @version_spinbox.value > version_count_for(example)
|
1135
|
+
@version_spinbox.value -= 1
|
1136
|
+
else
|
1137
|
+
version_number = @version_spinbox.value == 1 ? '' : @version_spinbox.value
|
1138
|
+
example = "#{selected_example}#{version_number}"
|
1139
|
+
@code_entry.text = File.read(file_path_for(example))
|
1140
|
+
end
|
1141
|
+
end
|
1142
|
+
}
|
1143
|
+
}
|
1144
|
+
|
1145
|
+
horizontal_box {
|
967
1146
|
stretchy false
|
968
1147
|
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
|
1148
|
+
button('Launch') {
|
1149
|
+
on_clicked do
|
1150
|
+
begin
|
1151
|
+
meta_example_file = File.join(Dir.home, '.meta_example.rb')
|
1152
|
+
File.write(meta_example_file, @code_entry.text)
|
1153
|
+
result = `ruby -r #{glimmer_dsl_libui_file} #{meta_example_file} 2>&1`
|
1154
|
+
msg_box('Error Running Example', result) if result.include?('error')
|
1155
|
+
rescue => e
|
1156
|
+
puts 'Unable to write code changes! Running original example...'
|
1157
|
+
system "ruby -r #{glimmer_dsl_libui_file} #{file_path_for(selected_example)}"
|
1158
|
+
end
|
978
1159
|
end
|
979
|
-
|
1160
|
+
}
|
1161
|
+
button('Reset') {
|
1162
|
+
on_clicked do
|
1163
|
+
@code_entry.text = File.read(file_path_for(selected_example))
|
1164
|
+
end
|
1165
|
+
}
|
980
1166
|
}
|
981
1167
|
}
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
}
|
1168
|
+
|
1169
|
+
@code_entry = non_wrapping_multiline_entry {
|
1170
|
+
text File.read(file_path_for(selected_example))
|
986
1171
|
}
|
987
1172
|
}
|
988
1173
|
}.show
|
@@ -2049,6 +2234,8 @@ include Glimmer
|
|
2049
2234
|
|
2050
2235
|
window('color button', 230) {
|
2051
2236
|
color_button { |cb|
|
2237
|
+
color :blue
|
2238
|
+
|
2052
2239
|
on_changed do
|
2053
2240
|
rgba = cb.color
|
2054
2241
|
p rgba
|
@@ -2513,6 +2700,14 @@ window('Editable animal sounds', 300, 200) {
|
|
2513
2700
|
|
2514
2701
|
cell_rows data
|
2515
2702
|
editable true
|
2703
|
+
|
2704
|
+
on_changed do |row, type, row_data| # fires on all changes (even ones happening through data array)
|
2705
|
+
puts "Row #{row} #{type}: #{row_data}"
|
2706
|
+
end
|
2707
|
+
|
2708
|
+
on_edited do |row, row_data| # only fires on direct table editing
|
2709
|
+
puts "Row #{row} edited: #{row_data}"
|
2710
|
+
end
|
2516
2711
|
}
|
2517
2712
|
}
|
2518
2713
|
|
@@ -2584,7 +2779,7 @@ window('Editable column animal sounds', 400, 200) {
|
|
2584
2779
|
|
2585
2780
|
### Basic Table Image
|
2586
2781
|
|
2587
|
-
This example
|
2782
|
+
This example requires pre-installing `chunky_png` Ruby gem:
|
2588
2783
|
|
2589
2784
|
```
|
2590
2785
|
gem install chunky_png -v1.4.0
|
@@ -2871,6 +3066,10 @@ window('Animal sounds', 300, 200) {
|
|
2871
3066
|
}
|
2872
3067
|
|
2873
3068
|
cell_rows data # implicit data-binding
|
3069
|
+
|
3070
|
+
on_changed do |row, type, row_data|
|
3071
|
+
puts "Row #{row} #{type}: #{row_data}"
|
3072
|
+
end
|
2874
3073
|
}
|
2875
3074
|
}
|
2876
3075
|
}.show
|
@@ -3033,7 +3232,7 @@ window('Task Progress', 300, 200) {
|
|
3033
3232
|
|
3034
3233
|
on_clicked do
|
3035
3234
|
data.each_with_index do |row_data, row|
|
3036
|
-
data[row] =
|
3235
|
+
data[row][1] = 100 # automatically updates table due to implicit data-binding
|
3037
3236
|
end
|
3038
3237
|
end
|
3039
3238
|
}
|
@@ -3041,6 +3240,78 @@ window('Task Progress', 300, 200) {
|
|
3041
3240
|
}.show
|
3042
3241
|
```
|
3043
3242
|
|
3243
|
+
### Basic Table Color
|
3244
|
+
|
3245
|
+
This example requires pre-installing `chunky_png` Ruby gem:
|
3246
|
+
|
3247
|
+
```
|
3248
|
+
gem install chunky_png -v1.4.0
|
3249
|
+
```
|
3250
|
+
|
3251
|
+
[examples/basic_table_color.rb](examples/basic_table_color.rb)
|
3252
|
+
|
3253
|
+
Run with this command from the root of the project if you cloned the project:
|
3254
|
+
|
3255
|
+
```
|
3256
|
+
ruby -r './lib/glimmer-dsl-libui' examples/basic_table_color.rb
|
3257
|
+
```
|
3258
|
+
|
3259
|
+
Run with this command if you installed the [Ruby gem](https://rubygems.org/gems/glimmer-dsl-libui):
|
3260
|
+
|
3261
|
+
```
|
3262
|
+
ruby -r glimmer-dsl-libui -e "require 'examples/basic_table_color'"
|
3263
|
+
```
|
3264
|
+
|
3265
|
+
Mac
|
3266
|
+
|
3267
|
+

|
3268
|
+
|
3269
|
+
Linux
|
3270
|
+
|
3271
|
+

|
3272
|
+
|
3273
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
3274
|
+
|
3275
|
+
```ruby
|
3276
|
+
require 'glimmer-dsl-libui'
|
3277
|
+
require 'chunky_png'
|
3278
|
+
|
3279
|
+
include Glimmer
|
3280
|
+
|
3281
|
+
f = File.open(File.expand_path('../icons/glimmer.png', __dir__))
|
3282
|
+
canvas = ChunkyPNG::Canvas.from_io(f)
|
3283
|
+
f.close
|
3284
|
+
canvas.resample_nearest_neighbor!(24, 24)
|
3285
|
+
data = canvas.to_rgba_stream
|
3286
|
+
width = canvas.width
|
3287
|
+
height = canvas.height
|
3288
|
+
img = image {
|
3289
|
+
image_part(data, width, height, width * 4)
|
3290
|
+
}
|
3291
|
+
|
3292
|
+
data = [
|
3293
|
+
[['cat', :red] , ['meow', :blue] , [true, 'mammal', :green], [img, 'Glimmer', :dark_blue], {r: 255, g: 120, b: 0, a: 0.5}],
|
3294
|
+
[['dog', :yellow] , ['woof', {r: 240, g: 32, b: 32}] , [true, 'mammal', :green], [img, 'Glimmer', :dark_blue], :skyblue],
|
3295
|
+
[['chicken', :beige], ['cock-a-doodle-doo', :blue] , [false, 'mammal', :red] , [img, 'Glimmer', :beige], {r: 5, g: 120, b: 110}],
|
3296
|
+
[['horse', :purple] , ['neigh', {r: 240, g: 32, b: 32}], [true, 'mammal', :green], [img, 'Glimmer', :dark_blue], '13a1fb'],
|
3297
|
+
[['cow', :gray] , ['moo', :blue] , [true, 'mammal', :green], [img, 'Glimmer', :brown], 0x12ff02]
|
3298
|
+
]
|
3299
|
+
|
3300
|
+
window('Animals', 500, 200) {
|
3301
|
+
horizontal_box {
|
3302
|
+
table {
|
3303
|
+
text_color_column('Animal')
|
3304
|
+
text_color_column('Sound')
|
3305
|
+
checkbox_text_color_column('Description')
|
3306
|
+
image_text_color_column('GUI')
|
3307
|
+
background_color_column('Mammal')
|
3308
|
+
|
3309
|
+
cell_rows data
|
3310
|
+
}
|
3311
|
+
}
|
3312
|
+
}.show
|
3313
|
+
```
|
3314
|
+
|
3044
3315
|
### Form Table
|
3045
3316
|
|
3046
3317
|
[examples/form_table.rb](examples/form_table.rb)
|
@@ -3156,6 +3427,10 @@ window('Contacts', 600, 600) { |w|
|
|
3156
3427
|
text_column('State')
|
3157
3428
|
|
3158
3429
|
cell_rows data # implicit data-binding
|
3430
|
+
|
3431
|
+
on_changed do |row, type, row_data|
|
3432
|
+
puts "Row #{row} #{type}: #{row_data}"
|
3433
|
+
end
|
3159
3434
|
}
|
3160
3435
|
}
|
3161
3436
|
}.show
|
@@ -3551,14 +3826,15 @@ window('Area Gallery', 400, 400) {
|
|
3551
3826
|
path { # declarative stable path
|
3552
3827
|
square(0, 0, 100)
|
3553
3828
|
square(100, 100, 400)
|
3554
|
-
|
3829
|
+
|
3555
3830
|
fill r: 102, g: 102, b: 204
|
3556
3831
|
}
|
3557
3832
|
path { # declarative stable path
|
3558
3833
|
rectangle(0, 100, 100, 400)
|
3559
3834
|
rectangle(100, 0, 400, 100)
|
3560
|
-
|
3561
|
-
|
3835
|
+
|
3836
|
+
# linear gradient (has x0, y0, x1, y1, and stops)
|
3837
|
+
fill x0: 10, y0: 10, x1: 350, y1: 350, stops: [{pos: 0.25, r: 204, g: 102, b: 204}, {pos: 0.75, r: 102, g: 102, b: 204}]
|
3562
3838
|
}
|
3563
3839
|
path { # declarative stable path
|
3564
3840
|
figure(100, 100) {
|
@@ -3584,17 +3860,26 @@ window('Area Gallery', 400, 400) {
|
|
3584
3860
|
fill r: 202, g: 102, b: 204, a: 0.5
|
3585
3861
|
stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
|
3586
3862
|
}
|
3863
|
+
path { # declarative stable path
|
3864
|
+
arc(400, 220, 180, 90, 90, false)
|
3865
|
+
|
3866
|
+
# radial gradient (has an outer_radius in addition to x0, y0, x1, y1, and stops)
|
3867
|
+
fill outer_radius: 90, x0: 0, y0: 0, x1: 500, y1: 500, stops: [{pos: 0.25, r: 102, g: 102, b: 204, a: 0.5}, {pos: 0.75, r: 204, g: 102, b: 204}]
|
3868
|
+
stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
|
3869
|
+
}
|
3587
3870
|
path { # declarative stable path
|
3588
3871
|
circle(200, 200, 90)
|
3589
3872
|
|
3590
3873
|
fill r: 202, g: 102, b: 204, a: 0.5
|
3591
3874
|
stroke r: 0, g: 0, b: 0, thickness: 2
|
3592
3875
|
}
|
3593
|
-
|
3594
|
-
|
3595
|
-
|
3596
|
-
|
3597
|
-
|
3876
|
+
text(160, 40, 100) { # x, y, width
|
3877
|
+
string {
|
3878
|
+
font family: 'Times', size: 14
|
3879
|
+
color :black
|
3880
|
+
|
3881
|
+
'Area Gallery'
|
3882
|
+
}
|
3598
3883
|
}
|
3599
3884
|
|
3600
3885
|
on_mouse_event do |area_mouse_event|
|
@@ -3685,7 +3970,8 @@ window('Area Gallery', 400, 400) {
|
|
3685
3970
|
height 100
|
3686
3971
|
}
|
3687
3972
|
|
3688
|
-
|
3973
|
+
# linear gradient (has x0, y0, x1, y1, and stops)
|
3974
|
+
fill x0: 10, y0: 10, x1: 350, y1: 350, stops: [{pos: 0.25, r: 204, g: 102, b: 204}, {pos: 0.75, r: 102, g: 102, b: 204}]
|
3689
3975
|
}
|
3690
3976
|
path { # declarative stable path
|
3691
3977
|
figure {
|
@@ -3747,16 +4033,6 @@ window('Area Gallery', 400, 400) {
|
|
3747
4033
|
fill r: 202, g: 102, b: 204, a: 0.5
|
3748
4034
|
stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
|
3749
4035
|
}
|
3750
|
-
path { # declarative stable path
|
3751
|
-
circle {
|
3752
|
-
x_center 200
|
3753
|
-
y_center 200
|
3754
|
-
radius 90
|
3755
|
-
}
|
3756
|
-
|
3757
|
-
fill r: 202, g: 102, b: 204, a: 0.5
|
3758
|
-
stroke r: 0, g: 0, b: 0, thickness: 2
|
3759
|
-
}
|
3760
4036
|
path { # declarative stable path
|
3761
4037
|
arc {
|
3762
4038
|
x_center 400
|
@@ -3767,9 +4043,32 @@ window('Area Gallery', 400, 400) {
|
|
3767
4043
|
is_negative false
|
3768
4044
|
}
|
3769
4045
|
|
3770
|
-
|
4046
|
+
# radial gradient (has an outer_radius in addition to x0, y0, x1, y1, and stops)
|
4047
|
+
fill outer_radius: 90, x0: 0, y0: 0, x1: 500, y1: 500, stops: [{pos: 0.25, r: 102, g: 102, b: 204, a: 0.5}, {pos: 0.75, r: 204, g: 102, b: 204}]
|
3771
4048
|
stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
|
3772
4049
|
}
|
4050
|
+
path { # declarative stable path
|
4051
|
+
circle {
|
4052
|
+
x_center 200
|
4053
|
+
y_center 200
|
4054
|
+
radius 90
|
4055
|
+
}
|
4056
|
+
|
4057
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
4058
|
+
stroke r: 0, g: 0, b: 0, thickness: 2
|
4059
|
+
}
|
4060
|
+
text {
|
4061
|
+
x 160
|
4062
|
+
y 40
|
4063
|
+
width 100
|
4064
|
+
|
4065
|
+
string {
|
4066
|
+
font family: 'Times', size: 14
|
4067
|
+
color :black
|
4068
|
+
|
4069
|
+
'Area Gallery'
|
4070
|
+
}
|
4071
|
+
}
|
3773
4072
|
|
3774
4073
|
on_mouse_event do |area_mouse_event|
|
3775
4074
|
p area_mouse_event
|
@@ -3842,7 +4141,8 @@ window('Area Gallery', 400, 400) {
|
|
3842
4141
|
rectangle(0, 100, 100, 400)
|
3843
4142
|
rectangle(100, 0, 400, 100)
|
3844
4143
|
|
3845
|
-
|
4144
|
+
# linear gradient (has x0, y0, x1, y1, and stops)
|
4145
|
+
fill x0: 10, y0: 10, x1: 350, y1: 350, stops: [{pos: 0.25, r: 204, g: 102, b: 204}, {pos: 0.75, r: 102, g: 102, b: 204}]
|
3846
4146
|
}
|
3847
4147
|
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3848
4148
|
figure(100, 100) {
|
@@ -3868,17 +4168,26 @@ window('Area Gallery', 400, 400) {
|
|
3868
4168
|
fill r: 202, g: 102, b: 204, a: 0.5
|
3869
4169
|
stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
|
3870
4170
|
}
|
4171
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
4172
|
+
arc(400, 220, 180, 90, 90, false)
|
4173
|
+
|
4174
|
+
# radial gradient (has an outer_radius in addition to x0, y0, x1, y1, and stops)
|
4175
|
+
fill outer_radius: 90, x0: 0, y0: 0, x1: 500, y1: 500, stops: [{pos: 0.25, r: 102, g: 102, b: 204, a: 0.5}, {pos: 0.75, r: 204, g: 102, b: 204}]
|
4176
|
+
stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
|
4177
|
+
}
|
3871
4178
|
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3872
4179
|
circle(200, 200, 90)
|
3873
4180
|
|
3874
4181
|
fill r: 202, g: 102, b: 204, a: 0.5
|
3875
4182
|
stroke r: 0, g: 0, b: 0, thickness: 2
|
3876
4183
|
}
|
3877
|
-
|
3878
|
-
|
3879
|
-
|
3880
|
-
|
3881
|
-
|
4184
|
+
text(160, 40, 100) { # x, y, width
|
4185
|
+
string {
|
4186
|
+
font family: 'Times', size: 14
|
4187
|
+
color :black
|
4188
|
+
|
4189
|
+
'Area Gallery'
|
4190
|
+
}
|
3882
4191
|
}
|
3883
4192
|
end
|
3884
4193
|
|
@@ -3971,7 +4280,8 @@ window('Area Gallery', 400, 400) {
|
|
3971
4280
|
height 100
|
3972
4281
|
}
|
3973
4282
|
|
3974
|
-
|
4283
|
+
# linear gradient (has x0, y0, x1, y1, and stops)
|
4284
|
+
fill x0: 10, y0: 10, x1: 350, y1: 350, stops: [{pos: 0.25, r: 204, g: 102, b: 204}, {pos: 0.75, r: 102, g: 102, b: 204}]
|
3975
4285
|
}
|
3976
4286
|
path { # a dynamic path is added semi-declaratively inside on_draw block
|
3977
4287
|
figure {
|
@@ -4033,16 +4343,6 @@ window('Area Gallery', 400, 400) {
|
|
4033
4343
|
fill r: 202, g: 102, b: 204, a: 0.5
|
4034
4344
|
stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
|
4035
4345
|
}
|
4036
|
-
path { # a dynamic path is added semi-declaratively inside on_draw block
|
4037
|
-
circle {
|
4038
|
-
x_center 200
|
4039
|
-
y_center 200
|
4040
|
-
radius 90
|
4041
|
-
}
|
4042
|
-
|
4043
|
-
fill r: 202, g: 102, b: 204, a: 0.5
|
4044
|
-
stroke r: 0, g: 0, b: 0, thickness: 2
|
4045
|
-
}
|
4046
4346
|
path { # a dynamic path is added semi-declaratively inside on_draw block
|
4047
4347
|
arc {
|
4048
4348
|
x_center 400
|
@@ -4053,9 +4353,32 @@ window('Area Gallery', 400, 400) {
|
|
4053
4353
|
is_negative false
|
4054
4354
|
}
|
4055
4355
|
|
4056
|
-
|
4356
|
+
# radial gradient (has an outer_radius in addition to x0, y0, x1, y1, and stops)
|
4357
|
+
fill outer_radius: 90, x0: 0, y0: 0, x1: 500, y1: 500, stops: [{pos: 0.25, r: 102, g: 102, b: 204, a: 0.5}, {pos: 0.75, r: 204, g: 102, b: 204}]
|
4057
4358
|
stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
|
4058
4359
|
}
|
4360
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
4361
|
+
circle {
|
4362
|
+
x_center 200
|
4363
|
+
y_center 200
|
4364
|
+
radius 90
|
4365
|
+
}
|
4366
|
+
|
4367
|
+
fill r: 202, g: 102, b: 204, a: 0.5
|
4368
|
+
stroke r: 0, g: 0, b: 0, thickness: 2
|
4369
|
+
}
|
4370
|
+
text {
|
4371
|
+
x 160
|
4372
|
+
y 40
|
4373
|
+
width 100
|
4374
|
+
|
4375
|
+
string {
|
4376
|
+
font family: 'Times', size: 14
|
4377
|
+
color :black
|
4378
|
+
|
4379
|
+
'Area Gallery'
|
4380
|
+
}
|
4381
|
+
}
|
4059
4382
|
end
|
4060
4383
|
|
4061
4384
|
on_mouse_event do |area_mouse_event|
|
@@ -5441,11 +5764,11 @@ class CustomDrawText
|
|
5441
5764
|
text { # default arguments for x, y, and width are (0, 0, area_draw_params[:area_width])
|
5442
5765
|
# align :left # default alignment
|
5443
5766
|
|
5444
|
-
|
5445
|
-
font @font
|
5446
|
-
color @color
|
5447
|
-
background @background
|
5448
|
-
underline @underline
|
5767
|
+
string {
|
5768
|
+
font @font
|
5769
|
+
color @color
|
5770
|
+
background @background
|
5771
|
+
underline @underline
|
5449
5772
|
|
5450
5773
|
' At last Ygramul sensed that something was coming toward ' \
|
5451
5774
|
'her. With the speed of lightning, she turned about, confronting ' \
|
@@ -5479,7 +5802,122 @@ class CustomDrawText
|
|
5479
5802
|
end
|
5480
5803
|
|
5481
5804
|
CustomDrawText.new.launch
|
5805
|
+
```
|
5806
|
+
|
5807
|
+
### Method-Based Custom Keyword
|
5808
|
+
|
5809
|
+
[examples/method_based_custom_keyword.rb](examples/method_based_custom_keyword.rb)
|
5810
|
+
|
5811
|
+
Run with this command from the root of the project if you cloned the project:
|
5812
|
+
|
5813
|
+
```
|
5814
|
+
ruby -r './lib/glimmer-dsl-libui' examples/method_based_custom_keyword.rb
|
5815
|
+
```
|
5816
|
+
|
5817
|
+
Run with this command if you installed the [Ruby gem](https://rubygems.org/gems/glimmer-dsl-libui):
|
5818
|
+
|
5819
|
+
```
|
5820
|
+
ruby -r glimmer-dsl-libui -e "require 'examples/method_based_custom_keyword'"
|
5821
|
+
```
|
5822
|
+
|
5823
|
+
Mac
|
5824
|
+
|
5825
|
+

|
5826
|
+
|
5827
|
+
Linux
|
5828
|
+
|
5829
|
+

|
5830
|
+
|
5831
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
5482
5832
|
|
5833
|
+
```ruby
|
5834
|
+
require 'glimmer-dsl-libui'
|
5835
|
+
require 'facets'
|
5836
|
+
|
5837
|
+
include Glimmer
|
5838
|
+
|
5839
|
+
Address = Struct.new(:street, :p_o_box, :city, :state, :zip_code)
|
5840
|
+
|
5841
|
+
def field(model, property)
|
5842
|
+
property = property.to_s
|
5843
|
+
entry { |e|
|
5844
|
+
label property.underscore.split('_').map(&:capitalize).join(' ')
|
5845
|
+
text model.send(property).to_s
|
5846
|
+
|
5847
|
+
on_changed do
|
5848
|
+
model.send("#{property}=", e.text)
|
5849
|
+
end
|
5850
|
+
}
|
5851
|
+
end
|
5852
|
+
|
5853
|
+
def address_form(address)
|
5854
|
+
form {
|
5855
|
+
field(address, :street)
|
5856
|
+
field(address, :p_o_box)
|
5857
|
+
field(address, :city)
|
5858
|
+
field(address, :state)
|
5859
|
+
field(address, :zip_code)
|
5860
|
+
}
|
5861
|
+
end
|
5862
|
+
|
5863
|
+
def label_pair(model, attribute, value)
|
5864
|
+
name_label = nil
|
5865
|
+
value_label = nil
|
5866
|
+
horizontal_box {
|
5867
|
+
name_label = label(attribute.to_s.underscore.split('_').map(&:capitalize).join(' '))
|
5868
|
+
value_label = label(value.to_s)
|
5869
|
+
}
|
5870
|
+
Glimmer::DataBinding::Observer.proc do
|
5871
|
+
value_label.text = model.send(attribute)
|
5872
|
+
end.observe(model, attribute)
|
5873
|
+
end
|
5874
|
+
|
5875
|
+
def address(address)
|
5876
|
+
vertical_box {
|
5877
|
+
address.each_pair do |attribute, value|
|
5878
|
+
label_pair(address, attribute, value)
|
5879
|
+
end
|
5880
|
+
}
|
5881
|
+
end
|
5882
|
+
|
5883
|
+
address1 = Address.new('123 Main St', '23923', 'Denver', 'Colorado', '80014')
|
5884
|
+
address2 = Address.new('2038 Park Ave', '83272', 'Boston', 'Massachusetts', '02101')
|
5885
|
+
|
5886
|
+
window('Method-Based Custom Keyword') {
|
5887
|
+
margined true
|
5888
|
+
|
5889
|
+
horizontal_box {
|
5890
|
+
vertical_box {
|
5891
|
+
label('Address 1') {
|
5892
|
+
stretchy false
|
5893
|
+
}
|
5894
|
+
address_form(address1)
|
5895
|
+
horizontal_separator {
|
5896
|
+
stretchy false
|
5897
|
+
}
|
5898
|
+
label('Address 1 (Saved)') {
|
5899
|
+
stretchy false
|
5900
|
+
}
|
5901
|
+
address(address1)
|
5902
|
+
}
|
5903
|
+
vertical_separator {
|
5904
|
+
stretchy false
|
5905
|
+
}
|
5906
|
+
vertical_box {
|
5907
|
+
label('Address 2') {
|
5908
|
+
stretchy false
|
5909
|
+
}
|
5910
|
+
address_form(address2)
|
5911
|
+
horizontal_separator {
|
5912
|
+
stretchy false
|
5913
|
+
}
|
5914
|
+
label('Address 2 (Saved)') {
|
5915
|
+
stretchy false
|
5916
|
+
}
|
5917
|
+
address(address2)
|
5918
|
+
}
|
5919
|
+
}
|
5920
|
+
}.show
|
5483
5921
|
```
|
5484
5922
|
|
5485
5923
|
## Contributing to glimmer-dsl-libui
|