glimmer-dsl-libui 0.2.11 → 0.2.15
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 +40 -0
- data/README.md +192 -110
- data/VERSION +1 -1
- data/bin/girb +0 -0
- data/bin/girb_runner.rb +1 -1
- data/examples/area_gallery.rb +1 -3
- data/examples/area_gallery3.rb +1 -3
- data/examples/basic_draw_text2.rb +0 -1
- data/examples/basic_table_button.rb +1 -1
- data/examples/basic_table_checkbox.rb +1 -1
- data/examples/basic_table_image.rb +1 -0
- data/examples/basic_table_image_text.rb +1 -0
- data/examples/color_the_circles.rb +24 -22
- data/examples/control_gallery.rb +6 -0
- data/examples/meta_example.rb +12 -7
- data/glimmer-dsl-libui.gemspec +0 -0
- data/lib/glimmer/dsl/libui/control_expression.rb +2 -0
- data/lib/glimmer/dsl/libui/string_expression.rb +9 -2
- data/lib/glimmer/libui/attributed_string.rb +32 -12
- data/lib/glimmer/libui/control_proxy/area_proxy.rb +37 -4
- data/lib/glimmer/libui/control_proxy/table_proxy.rb +30 -10
- data/lib/glimmer/libui/control_proxy.rb +17 -2
- data/lib/glimmer/libui/shape/arc.rb +5 -1
- data/lib/glimmer/libui/shape/circle.rb +5 -1
- data/lib/glimmer/libui.rb +2 -2
- metadata +13 -10
data/README.md
CHANGED
@@ -1,7 +1,6 @@
|
|
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.15
|
2
2
|
## Prerequisite-Free Ruby Desktop Development GUI Library
|
3
3
|
[](http://badge.fury.io/rb/glimmer-dsl-libui)
|
4
|
-
[](https://codeclimate.com/github/AndyObtiva/glimmer-dsl-libui/maintainability)
|
5
4
|
[](https://gitter.im/AndyObtiva/glimmer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
6
5
|
|
7
6
|
[Glimmer](https://github.com/AndyObtiva/glimmer) DSL for [LibUI](https://github.com/kojix2/LibUI) is a prerequisite-free Ruby desktop development GUI library. No need to pre-install any prerequisites. Just install the gem and have platform-independent native GUI that just works!
|
@@ -10,13 +9,11 @@
|
|
10
9
|
|
11
10
|
The main trade-off in using [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) as opposed to [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt) or [Glimmer DSL for Tk](https://github.com/AndyObtiva/glimmer-dsl-tk) is the fact that [SWT](https://www.eclipse.org/swt/) and [Tk](https://www.tcl.tk/) are more mature than mid-alpha [libui](https://github.com/andlabs/libui) as GUI toolkits. Still, if there is only a need to build a small simple application, [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) could be a good convenient choice due to having zero prerequisites beyond the dependencies included in the [Ruby gem](https://rubygems.org/gems/glimmer-dsl-libui). Also, just like [Glimmer DSL for Tk](https://github.com/AndyObtiva/glimmer-dsl-tk), its apps start instantly and have a small memory footprint. [LibUI](https://github.com/kojix2/LibUI) is a promising new GUI toolkit that might prove quite worthy in the future.
|
12
11
|
|
13
|
-
**(Note: although LibUI works on Windows, this project has not been tested on Windows yet. It has only been verified on Mac x64 and Linux x64)**
|
14
|
-
|
15
12
|
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) aims to provide a DSL similar to the [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt) to enable more productive desktop development in Ruby with:
|
16
13
|
- Declarative DSL syntax that visually maps to the GUI control hierarchy
|
17
14
|
- Convention over configuration via smart defaults and automation of low-level details
|
18
15
|
- Requiring the least amount of syntax possible to build GUI
|
19
|
-
- Custom
|
16
|
+
- Custom Keyword support
|
20
17
|
- [Far Future Plan] Bidirectional Data-Binding to declaratively wire and automatically synchronize GUI with Business Models
|
21
18
|
- [Far Future Plan] Scaffolding for new custom controls, apps, and gems
|
22
19
|
- [Far Future Plan] Native-Executable packaging on Mac, Windows, and Linux.
|
@@ -134,11 +131,9 @@ window('Area Gallery', 400, 400) {
|
|
134
131
|
stroke r: 0, g: 0, b: 0, thickness: 2
|
135
132
|
}
|
136
133
|
text(160, 40, 100) { # x, y, width
|
137
|
-
string {
|
134
|
+
string('Area Gallery') {
|
138
135
|
font family: 'Times', size: 14
|
139
136
|
color :black
|
140
|
-
|
141
|
-
'Area Gallery'
|
142
137
|
}
|
143
138
|
}
|
144
139
|
|
@@ -214,7 +209,7 @@ Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interes
|
|
214
209
|
- [Usage](#usage)
|
215
210
|
- [Girb (Glimmer IRB)](#girb-glimmer-irb)
|
216
211
|
- [API](#api)
|
217
|
-
- [Supported
|
212
|
+
- [Supported Keywords](#supported-keywords)
|
218
213
|
- [Common Control Properties](#common-control-properties)
|
219
214
|
- [Common Control Operations](#common-control-operations)
|
220
215
|
- [LibUI Operations](#libui-operations)
|
@@ -262,13 +257,18 @@ Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interes
|
|
262
257
|
- [Basic Draw Text](#basic-draw-text)
|
263
258
|
- [Custom Draw Text](#custom-draw-text)
|
264
259
|
- [Method-Based Custom Keyword](#method-based-custom-keyword)
|
265
|
-
- [
|
260
|
+
- [Applications](#applications)
|
261
|
+
- [Manga2PDF](#manga2pdf)
|
262
|
+
- [Befunge98 GUI](#befunge98-gui)
|
263
|
+
- [i3off Gtk Ruby](#i3off-gtk-ruby)
|
264
|
+
- [Process](#process)
|
265
|
+
- [Resources](#resources)
|
266
266
|
- [Help](#help)
|
267
267
|
- [Issues](#issues)
|
268
268
|
- [Chat](#chat)
|
269
|
-
- [Process](#process)
|
270
269
|
- [Planned Features and Feature Suggestions](#planned-features-and-feature-suggestions)
|
271
270
|
- [Change Log](#change-log)
|
271
|
+
- [Contributing](#contributing)
|
272
272
|
- [Contributors](#contributors)
|
273
273
|
- [License](#license)
|
274
274
|
|
@@ -282,10 +282,10 @@ The Glimmer GUI DSL provides object-oriented declarative hierarchical syntax for
|
|
282
282
|
- Requires the minimum amount of syntax needed to describe an app's GUI
|
283
283
|
|
284
284
|
The Glimmer GUI DSL follows these simple concepts in mapping from [LibUI](https://github.com/kojix2/LibUI) syntax:
|
285
|
-
- **
|
286
|
-
- **Content
|
287
|
-
- **Property**: Control properties may be declared inside keyword blocks with lower-case underscored name followed by property value args (e.g. `title "hello world"` inside `group`). Behind the scenes, properties correspond to `control_set_property` methods.
|
288
|
-
- **Listener**: Control listeners may be declared inside keyword blocks with listener lower-case underscored name beginning with `on_` and receiving required block handler (e.g. `on_clicked {puts 'clicked'}` inside `button`). Behind the scenes, listeners correspond to `control_on_event` methods.
|
285
|
+
- **Keyword(args)**: [LibUI](https://github.com/kojix2/LibUI) controls may be declared by lower-case underscored name (aka keyword) (e.g. `window` or `button`). Behind the scenes, they are represented by keyword methods that map to corresponding `LibUI.new_keyword` methods receiving args (e.g. `window('hello world', 300, 200, true)`).
|
286
|
+
- **Content Block** (Properties/Listeners/Controls): Any keyword may be optionally followed by a Ruby curly-brace multi-line content block containing properties (attributes), listeners, and/or nested controls (e.g. `window {title 'hello world'; on_closing {puts 'Bye'}; button('greet')}`). Content block optionally receives one arg representing the control (e.g. `button('greet') {|b| on_clicked { puts b.text}}`)
|
287
|
+
- **Property**: Control properties may be declared inside keyword blocks with lower-case underscored name followed by property value args (e.g. `title "hello world"` inside `group`). Behind the scenes, properties correspond to `LibUI.control_set_property` methods.
|
288
|
+
- **Listener**: Control listeners may be declared inside keyword blocks with listener lower-case underscored name beginning with `on_` and receiving required block handler (e.g. `on_clicked {puts 'clicked'}` inside `button`). Optionally, the listener block can receive an arg representing the control (e.g. `on_clicked {|btn| puts btn.text}`). Behind the scenes, listeners correspond to `LibUI.control_on_event` methods.
|
289
289
|
|
290
290
|
Example of an app written in [LibUI](https://github.com/kojix2/LibUI)'s procedural imperative syntax:
|
291
291
|
|
@@ -349,7 +349,7 @@ gem install glimmer-dsl-libui
|
|
349
349
|
Or install via Bundler `Gemfile`:
|
350
350
|
|
351
351
|
```ruby
|
352
|
-
gem 'glimmer-dsl-libui', '~> 0.2.
|
352
|
+
gem 'glimmer-dsl-libui', '~> 0.2.15'
|
353
353
|
```
|
354
354
|
|
355
355
|
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,7 +409,7 @@ w.set_title 'aloha'
|
|
409
409
|
puts w.title # => aloha
|
410
410
|
```
|
411
411
|
|
412
|
-
Controls are wrapped as Ruby proxy objects, having a `#libui` method to obtain the wrapped Fiddle pointer object. Ruby proxy objects rely on composition (via [Proxy Design Pattern](https://en.wikipedia.org/wiki/Proxy_pattern)) instead of inheritance to shield consumers from having to deal with lower-level details unless absolutely needed.
|
412
|
+
Controls are wrapped as Ruby proxy objects, having a `#libui` method to obtain the wrapped [LibUI](https://github.com/kojix2/LibUI) Fiddle pointer object. Ruby proxy objects rely on composition (via [Proxy Design Pattern](https://en.wikipedia.org/wiki/Proxy_pattern)) instead of inheritance to shield consumers from having to deal with lower-level details unless absolutely needed.
|
413
413
|
|
414
414
|
Example (you may copy/paste in [`girb`](#girb-glimmer-irb)):
|
415
415
|
|
@@ -418,9 +418,11 @@ w = window('hello world') # => #<Glimmer::LibUI::WindowProxy:0x00007fde4ea39fb0
|
|
418
418
|
w.libui # => #<Fiddle::Pointer:0x00007fde53997980 ptr=0x00007fde51352a60 size=0 free=0x0000000000000000>
|
419
419
|
```
|
420
420
|
|
421
|
-
### Supported
|
421
|
+
### Supported Keywords
|
422
422
|
|
423
|
-
|
423
|
+
These are all the supported keywords. Note that some keywords do not represent controls, but produce objects that are used as the property values of controls (e.g. `image` builds objects to use in `cell_rows` for a `table` with an image column)
|
424
|
+
|
425
|
+
Keyword(Args) | Properties | Listeners
|
424
426
|
------------- | ---------- | ---------
|
425
427
|
`about_menu_item` | None | `on_clicked`
|
426
428
|
`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)`
|
@@ -456,6 +458,8 @@ Control(Args) | Properties | Listeners
|
|
456
458
|
`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
|
457
459
|
`menu(text as String)` | None | None
|
458
460
|
`menu_item(text as String)` | `checked` (Boolean) | `on_clicked`
|
461
|
+
`message_box` (alias for `msg_box`; see for arguments) | None | None
|
462
|
+
`message_box_error` (alias for `msg_box_error`; see for arguments) | None | None
|
459
463
|
`multiline_entry` | `read_only` (Boolean), `text` (`String`) | `on_changed`
|
460
464
|
`msg_box(window = main_window as Glimmer::LibUI::WindowProxy, title as String, description as String)` | None | None
|
461
465
|
`msg_box_error(window = main_window as Glimmer::LibUI::WindowProxy, title as String, description as String)` | None | None
|
@@ -472,7 +476,7 @@ Control(Args) | Properties | Listeners
|
|
472
476
|
`slider(min as Numeric, max as Numeric)` | `value` (`Numeric`) | `on_changed`
|
473
477
|
`spinbox(min as Numeric, max as Numeric)` | `value` (`Numeric`) | `on_changed`
|
474
478
|
`square(x as Numeric, y as Numeric, length as Numeric)` | `x` (`Numeric`), `y` (`Numeric`), `length` (`Numeric`) | None
|
475
|
-
`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
|
479
|
+
`string(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`, `string` (`String`) | None
|
476
480
|
`tab` | `margined` (Boolean), `num_pages` (`Integer`) | None
|
477
481
|
`tab_item(name as String)` | `index` [read-only] (`Integer`), `margined` (Boolean), `name` [read-only] (`String`) | None
|
478
482
|
`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| ...}`
|
@@ -517,8 +521,8 @@ All operations that could normally be called on `LibUI` can also be called on `G
|
|
517
521
|
|
518
522
|
### Extra Dialogs
|
519
523
|
|
520
|
-
- `open_file(window as Glimmer::LibUI::WindowProxy)`: returns selected file (`String`) or `nil` if cancelled
|
521
|
-
- `save_file(window as Glimmer::LibUI::WindowProxy)`: returns selected file (`String`) or `nil` if cancelled
|
524
|
+
- `open_file(window as Glimmer::LibUI::WindowProxy = ControlProxy::main_window_proxy)`: returns selected file (`String`) or `nil` if cancelled
|
525
|
+
- `save_file(window as Glimmer::LibUI::WindowProxy = ControlProxy::main_window_proxy)`: returns selected file (`String`) or `nil` if cancelled
|
522
526
|
|
523
527
|
### Extra Operations
|
524
528
|
|
@@ -531,13 +535,13 @@ All operations that could normally be called on `LibUI` can also be called on `G
|
|
531
535
|
|
532
536
|
### Table API
|
533
537
|
|
534
|
-
The `table` control must first declare its columns via one of these column keywords (mentioned in [Supported
|
538
|
+
The `table` control must first declare its columns via one of these column keywords (mentioned in [Supported Keywords](#supported-keywords)):
|
535
539
|
- `background_color_column`: expects color cell values
|
536
540
|
- `button_column`: expects `String` cell values
|
537
541
|
- `checkbox_column`: expects Boolean cell values
|
538
542
|
- `checkbox_text_column`: expects dual-element `Array` of Boolean and `String` cell values
|
539
543
|
- `checkbox_text_color_column`: expects triple-element `Array` of Boolean, `String`, and color cell values
|
540
|
-
- `image_column`: expects `image` cell values (produced by `image` and `image_part` keywords as per [Supported
|
544
|
+
- `image_column`: expects `image` cell values (produced by `image` and `image_part` keywords as per [Supported Keywords](#supported-keywords))
|
541
545
|
- `image_text_column`: expects dual-element `Array` of `image` and `String` cell values
|
542
546
|
- `image_text_color_column`: expects triple-element `Array` of `image`, `String`, and color cell values
|
543
547
|
- `text_column`: expects `String` cell values
|
@@ -599,6 +603,7 @@ window('Contacts', 600, 600) { |w|
|
|
599
603
|
msg_box_error(w, 'Validation Error!', 'All fields are required! Please make sure to enter a value for all fields.')
|
600
604
|
else
|
601
605
|
data << new_row # automatically inserts a row into the table due to implicit data-binding
|
606
|
+
@unfiltered_data = data.dup
|
602
607
|
@name_entry.text = ''
|
603
608
|
@email_entry.text = ''
|
604
609
|
@phone_entry.text = ''
|
@@ -608,6 +613,25 @@ window('Contacts', 600, 600) { |w|
|
|
608
613
|
end
|
609
614
|
}
|
610
615
|
|
616
|
+
search_entry { |se|
|
617
|
+
stretchy false
|
618
|
+
|
619
|
+
on_changed do
|
620
|
+
filter_value = se.text
|
621
|
+
@unfiltered_data ||= data.dup
|
622
|
+
# Unfilter first to remove any previous filters
|
623
|
+
data.replace(@unfiltered_data) # affects table indirectly through implicit data-binding
|
624
|
+
# Now, apply filter if entered
|
625
|
+
unless filter_value.empty?
|
626
|
+
data.filter! do |row_data| # affects table indirectly through implicit data-binding
|
627
|
+
row_data.any? do |cell|
|
628
|
+
cell.to_s.downcase.include?(filter_value.downcase)
|
629
|
+
end
|
630
|
+
end
|
631
|
+
end
|
632
|
+
end
|
633
|
+
}
|
634
|
+
|
611
635
|
table {
|
612
636
|
text_column('Name')
|
613
637
|
text_column('Email')
|
@@ -616,6 +640,10 @@ window('Contacts', 600, 600) { |w|
|
|
616
640
|
text_column('State')
|
617
641
|
|
618
642
|
cell_rows data # implicit data-binding
|
643
|
+
|
644
|
+
on_changed do |row, type, row_data|
|
645
|
+
puts "Row #{row} #{type}: #{row_data}"
|
646
|
+
end
|
619
647
|
}
|
620
648
|
}
|
621
649
|
}.show
|
@@ -628,8 +656,8 @@ Learn more by checking out [examples](#examples).
|
|
628
656
|
### Area API
|
629
657
|
|
630
658
|
The `area` control is a canvas-like control for drawing paths that can be used in one of two ways:
|
631
|
-
- 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).
|
632
|
-
- 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.
|
659
|
+
- Declaratively via stable paths: useful for stable paths that will not change often 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 relatively few stable paths (mostly for decorative reasons).
|
660
|
+
- Semi-declaratively via on_draw listener dynamic paths: useful for more dynamic paths that will definitely change very often. 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.
|
633
661
|
|
634
662
|
Here is an example of a declarative `area` with a stable path (you may copy/paste in [`girb`](#girb-glimmer-irb)):
|
635
663
|
|
@@ -816,19 +844,23 @@ Check [Basic Transform](#basic-transform) example for use of [X11](https://en.wi
|
|
816
844
|
|
817
845
|
Check [Histogram](#histogram) example for use of hex colors.
|
818
846
|
|
819
|
-
To draw `text` in an `area`, you simply nest a `text(x, y, width)` control directly under `area` or inside a `on_draw` listener, and then nest attributed `string {string_value}` controls underneath it returning an actual `String` (think of them as the `<span>` element in html, which contains a string of text).
|
847
|
+
To draw `text` in an `area`, you simply nest a `text(x, y, width)` control directly under `area` or inside a `on_draw` listener, and then nest attributed `string {[attributes]; string_value}` controls underneath it returning an actual `String` (think of them as the `<span>` or `<p>` element in html, which contains a string of text). Alternatively, you can nest attributed `string(string_value) {[attributes]}` if `string_value` is a short single-line string. An attributed `string` value can be changed dynamically via its `string` property.
|
820
848
|
|
821
|
-
`text`
|
849
|
+
`text` has the following properties:
|
822
850
|
- `default_font`:
|
823
851
|
- `align`: `:left` (default), `:center`, or `:right` (`align` currently seems not to work on the Mac)
|
852
|
+
- `x`: x coordinate in relation to parent `area` top-left corner
|
853
|
+
- `y`: y coordinate in relation to parent `area` top-left corner
|
854
|
+
- `width` (default: area width - x*2): width of text to display
|
824
855
|
|
825
|
-
`string`
|
856
|
+
`string` has the following properties:
|
826
857
|
- `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
|
827
858
|
- `color`: rgba, hex, or [X11](https://en.wikipedia.org/wiki/X11_color_names) color
|
828
859
|
- `background`: rgba, hex, or [X11](https://en.wikipedia.org/wiki/X11_color_names) color
|
829
860
|
- `underline`: one of `:none`, `:single`, `:double`, `:suggestion`, `:color_custom`, `:color_spelling`, `:color_grammar`, `:color_auxiliary`
|
830
861
|
- `underline_color`: one of `:spelling`, `:grammar`, `:auxiliary`, rgba, hex, or [X11](https://en.wikipedia.org/wiki/X11_color_names) color
|
831
862
|
- `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.
|
863
|
+
- `string`: string value (`String`)
|
832
864
|
|
833
865
|
Example (you may copy/paste in [`girb`](#girb-glimmer-irb)):
|
834
866
|
|
@@ -849,12 +881,13 @@ window('area text drawing') {
|
|
849
881
|
open_type_tag 'l', 'i', 'g', 'a', 1
|
850
882
|
}
|
851
883
|
|
852
|
-
"This is a
|
884
|
+
"This is a demonstration\n" \
|
885
|
+
"of a very long\n" \
|
886
|
+
"attributed string\n" \
|
887
|
+
"spanning multiple lines\n\n"
|
853
888
|
}
|
854
889
|
|
855
|
-
string
|
856
|
-
'This is another test'
|
857
|
-
}
|
890
|
+
string('This is a short unattributed string')
|
858
891
|
}
|
859
892
|
}
|
860
893
|
}.show
|
@@ -888,9 +921,11 @@ window('area text drawing') {
|
|
888
921
|
- Table `cell_rows` data has implicit data-binding to table cell values for deletion, insertion, and change (done by diffing `cell_rows` value before and after change and auto-informing `table` of deletions [`LibUI.table_model_row_deleted`], insertions [`LibUI.table_model_row_deleted`], and changes [`LibUI.table_model_row_changed`]). When deleting data rows from `cell_rows` array, then actual rows from the `table` are automatically deleted. When inserting data rows into `cell_rows` array, then actual `table` rows are automatically inserted. When updating data rows in `cell_rows` array, then actual `table` rows are automatically updated.
|
889
922
|
- `image` instances are automatically freed from memory after `window` is destroyed.
|
890
923
|
- `image` `width` and `height` can be left off if it has one `image_part` only as they default to the same `width` and `height` of the `image_part`
|
924
|
+
- Automatically provide shifted `:key` characters in `area_key_event` provided in `area` key listeners `on_key_event`, `on_key_down`, and `on_key_up`
|
891
925
|
- `area` paths are specified declaratively with figures underneath (e.g. `rectangle`) and `area` draw listener is automatically generated
|
892
926
|
- Observe figure properties (e.g. `rectangle` `width`) for changes and automatically redraw containing area accordingly
|
893
927
|
- Observe `path` `fill` and `stroke` hashes for changes and automatically redraw containing area accordingly
|
928
|
+
- Observe `text` and `string` properties for changes and automatically redraw containing area accordingly
|
894
929
|
- All controls are protected from garbage collection until no longer needed (explicitly destroyed), so there is no need to worry about surprises.
|
895
930
|
- All resources are freed automatically once no longer needed or left to garbage collection.
|
896
931
|
- 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.
|
@@ -1008,8 +1043,13 @@ window('Method-Based Custom Keyword') {
|
|
1008
1043
|
### API Gotchas
|
1009
1044
|
|
1010
1045
|
- 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`).
|
1011
|
-
- `table` `checkbox_column` and `checkbox_text_column` checkbox editing only works on
|
1046
|
+
- `table` `checkbox_column` and `checkbox_text_column` checkbox editing only works on Linux and Windows (not Mac) due to a current limitation in [libui](https://github.com/andlabs/ui/issues/357).
|
1012
1047
|
- `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)
|
1048
|
+
- `text` `string` `background` does not work on Windows due to an [issue in libui](https://github.com/andlabs/libui/issues/347).
|
1049
|
+
- `arc` shape does not work on Windows unless a figure is started due to implementation of [libui](https://github.com/andlabs/libui).
|
1050
|
+
- `table` controls on Windows intentionally get an extra empty row at the end because if any row were to be deleted for the first time, double-deletion happens due to an issue in [libui](https://github.com/andlabs/libui) on Windows.
|
1051
|
+
- `table` `progress_bar` column on Windows cannot be updated with a positive value if it started initially with `-1` (it ignores update to avoid crashing due to an issue in [libui](https://github.com/andlabs/libui) on Windows.
|
1052
|
+
- It seems that [libui](https://github.com/andlabs/libui) does not support nesting multiple `area` controls under a `grid` as only the first one shows up in that scenario. To workaround that limitation, use a `vertical_box` with nested `horizontal_box`s instead to include multiple `area`s in a GUI.
|
1013
1053
|
|
1014
1054
|
### Original API
|
1015
1055
|
|
@@ -1024,7 +1064,7 @@ I am documenting options for packaging, which I have not tried myself, but figur
|
|
1024
1064
|
|
1025
1065
|
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.
|
1026
1066
|
|
1027
|
-
For Mac, consider [
|
1067
|
+
For Mac, consider [Platypus](https://github.com/sveinbjornt/Platypus) (builds a native Mac app from a Ruby script)
|
1028
1068
|
|
1029
1069
|
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/).
|
1030
1070
|
|
@@ -1111,15 +1151,20 @@ class MetaExample
|
|
1111
1151
|
end
|
1112
1152
|
|
1113
1153
|
def run_example(example)
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1154
|
+
Thread.new do
|
1155
|
+
command = "ruby -r #{glimmer_dsl_libui_file} #{example} 2>&1"
|
1156
|
+
result = ''
|
1157
|
+
IO.popen(command) do |f|
|
1158
|
+
sleep(0.0001) # yield to main thread
|
1159
|
+
f.each_line do |line|
|
1160
|
+
result << line
|
1161
|
+
puts line
|
1162
|
+
$stdout.flush # for Windows
|
1163
|
+
sleep(0.0001) # yield to main thread
|
1164
|
+
end
|
1120
1165
|
end
|
1166
|
+
Glimmer::LibUI.queue_main { msg_box('Error Running Example', result) } if result.downcase.include?('error')
|
1121
1167
|
end
|
1122
|
-
msg_box('Error Running Example', result) if result.downcase.include?('error')
|
1123
1168
|
end
|
1124
1169
|
|
1125
1170
|
def launch
|
@@ -3375,8 +3420,6 @@ Linux
|
|
3375
3420
|
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
3376
3421
|
|
3377
3422
|
```ruby
|
3378
|
-
# frozen_string_literal: true
|
3379
|
-
|
3380
3423
|
require 'glimmer-dsl-libui'
|
3381
3424
|
|
3382
3425
|
include Glimmer
|
@@ -3906,11 +3949,9 @@ window('Area Gallery', 400, 400) {
|
|
3906
3949
|
stroke r: 0, g: 0, b: 0, thickness: 2
|
3907
3950
|
}
|
3908
3951
|
text(160, 40, 100) { # x, y, width
|
3909
|
-
string {
|
3952
|
+
string('Area Gallery') {
|
3910
3953
|
font family: 'Times', size: 14
|
3911
3954
|
color :black
|
3912
|
-
|
3913
|
-
'Area Gallery'
|
3914
3955
|
}
|
3915
3956
|
}
|
3916
3957
|
|
@@ -4214,11 +4255,9 @@ window('Area Gallery', 400, 400) {
|
|
4214
4255
|
stroke r: 0, g: 0, b: 0, thickness: 2
|
4215
4256
|
}
|
4216
4257
|
text(160, 40, 100) { # x, y, width
|
4217
|
-
string {
|
4258
|
+
string('Area Gallery') {
|
4218
4259
|
font family: 'Times', size: 14
|
4219
4260
|
color :black
|
4220
|
-
|
4221
|
-
'Area Gallery'
|
4222
4261
|
}
|
4223
4262
|
}
|
4224
4263
|
end
|
@@ -5139,8 +5178,8 @@ class ColorTheCircles
|
|
5139
5178
|
|
5140
5179
|
WINDOW_WIDTH = 800
|
5141
5180
|
WINDOW_HEIGHT = 600
|
5142
|
-
|
5143
|
-
|
5181
|
+
SHAPE_MIN_SIZE = 15
|
5182
|
+
SHAPE_MAX_SIZE = 75
|
5144
5183
|
MARGIN_WIDTH = 55
|
5145
5184
|
MARGIN_HEIGHT = 155
|
5146
5185
|
TIME_MAX_EASY = 4
|
@@ -5154,6 +5193,7 @@ class ColorTheCircles
|
|
5154
5193
|
@circles_data = []
|
5155
5194
|
@score = 0
|
5156
5195
|
@time_max = TIME_MAX_HARD
|
5196
|
+
@game_over = false
|
5157
5197
|
register_observers
|
5158
5198
|
setup_circle_factory
|
5159
5199
|
end
|
@@ -5162,9 +5202,11 @@ class ColorTheCircles
|
|
5162
5202
|
observer = Glimmer::DataBinding::Observer.proc do |new_score|
|
5163
5203
|
@score_label.text = new_score.to_s
|
5164
5204
|
if new_score == -20
|
5205
|
+
@game_over = true
|
5165
5206
|
msg_box('You Lost!', 'Sorry! Your score reached -20')
|
5166
5207
|
restart_game
|
5167
5208
|
elsif new_score == 0
|
5209
|
+
@game_over = true
|
5168
5210
|
msg_box('You Won!', 'Congratulations! Your score reached 0')
|
5169
5211
|
restart_game
|
5170
5212
|
end
|
@@ -5174,11 +5216,13 @@ class ColorTheCircles
|
|
5174
5216
|
|
5175
5217
|
def setup_circle_factory
|
5176
5218
|
consumer = Proc.new do
|
5177
|
-
|
5178
|
-
|
5179
|
-
|
5180
|
-
|
5181
|
-
|
5219
|
+
unless @game_over
|
5220
|
+
if @circles_data.empty?
|
5221
|
+
# start with 3 circles to make more challenging
|
5222
|
+
add_circle until @circles_data.size > 3
|
5223
|
+
else
|
5224
|
+
add_circle
|
5225
|
+
end
|
5182
5226
|
end
|
5183
5227
|
delay = rand * @time_max
|
5184
5228
|
Glimmer::LibUI.timer(delay, repeat: false, &consumer)
|
@@ -5187,12 +5231,12 @@ class ColorTheCircles
|
|
5187
5231
|
end
|
5188
5232
|
|
5189
5233
|
def add_circle
|
5190
|
-
|
5191
|
-
|
5192
|
-
|
5234
|
+
circle_x = rand * (WINDOW_WIDTH - MARGIN_WIDTH - SHAPE_MAX_SIZE) + SHAPE_MAX_SIZE
|
5235
|
+
circle_y = rand * (WINDOW_HEIGHT - MARGIN_HEIGHT - SHAPE_MAX_SIZE) + SHAPE_MAX_SIZE
|
5236
|
+
circle_size = rand * (SHAPE_MAX_SIZE - SHAPE_MIN_SIZE) + SHAPE_MIN_SIZE
|
5193
5237
|
stroke_color = Glimmer::LibUI.x11_colors.sample
|
5194
5238
|
@circles_data << {
|
5195
|
-
args: [
|
5239
|
+
args: [circle_x, circle_y, circle_size],
|
5196
5240
|
fill: nil,
|
5197
5241
|
stroke: stroke_color
|
5198
5242
|
}
|
@@ -5203,8 +5247,28 @@ class ColorTheCircles
|
|
5203
5247
|
def restart_game
|
5204
5248
|
@score = 0 # update variable directly to avoid notifying observers
|
5205
5249
|
@circles_data.clear
|
5250
|
+
@game_over = false
|
5206
5251
|
end
|
5207
5252
|
|
5253
|
+
def color_circle(x, y)
|
5254
|
+
clicked_circle_data = @circles_data.find do |circle_data|
|
5255
|
+
circle_data[:fill].nil? && circle_data[:circle]&.include?(x, y)
|
5256
|
+
end
|
5257
|
+
if clicked_circle_data
|
5258
|
+
clicked_circle_data[:fill] = clicked_circle_data[:stroke]
|
5259
|
+
push_colored_circle_behind_uncolored_circles(clicked_circle_data)
|
5260
|
+
@area.queue_redraw_all
|
5261
|
+
self.score += 1 # notifies score observers automatically of change
|
5262
|
+
end
|
5263
|
+
end
|
5264
|
+
|
5265
|
+
def push_colored_circle_behind_uncolored_circles(colored_circle_data)
|
5266
|
+
removed_colored_circle_data = @circles_data.delete(colored_circle_data)
|
5267
|
+
last_colored_circle_data = @circles_data.select {|cd| cd[:fill]}.last
|
5268
|
+
last_colored_circle_data_index = @circles_data.index(last_colored_circle_data) || -1
|
5269
|
+
@circles_data.insert(last_colored_circle_data_index + 1, removed_colored_circle_data)
|
5270
|
+
end
|
5271
|
+
|
5208
5272
|
def launch
|
5209
5273
|
menu('Actions') {
|
5210
5274
|
menu_item('Restart') {
|
@@ -5292,45 +5356,35 @@ class ColorTheCircles
|
|
5292
5356
|
}
|
5293
5357
|
}
|
5294
5358
|
|
5295
|
-
|
5359
|
+
@area = area {
|
5296
5360
|
left 0
|
5297
5361
|
top 4
|
5298
5362
|
hexpand true
|
5299
5363
|
vexpand true
|
5300
5364
|
halign :fill
|
5301
5365
|
valign :fill
|
5302
|
-
|
5303
|
-
|
5304
|
-
|
5366
|
+
|
5367
|
+
on_draw do |area_draw_params|
|
5368
|
+
path {
|
5369
|
+
rectangle(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT)
|
5370
|
+
|
5371
|
+
fill :white
|
5372
|
+
}
|
5373
|
+
|
5374
|
+
@circles_data.each do |circle_data|
|
5305
5375
|
path {
|
5306
|
-
|
5307
|
-
|
5308
|
-
fill :
|
5376
|
+
circle_data[:circle] = circle(*circle_data[:args])
|
5377
|
+
|
5378
|
+
fill circle_data[:fill]
|
5379
|
+
stroke circle_data[:stroke]
|
5309
5380
|
}
|
5310
|
-
|
5311
|
-
@circles_data.each do |circle_data|
|
5312
|
-
path {
|
5313
|
-
circle_data[:circle] = circle(*circle_data[:args])
|
5314
|
-
|
5315
|
-
fill circle_data[:fill]
|
5316
|
-
stroke circle_data[:stroke]
|
5317
|
-
}
|
5318
|
-
end
|
5319
|
-
end
|
5320
|
-
|
5321
|
-
on_mouse_down do |area_mouse_event|
|
5322
|
-
clicked_circle_data = @circles_data.find do |circle_data|
|
5323
|
-
circle_data[:fill].nil? && circle_data[:circle].include?(area_mouse_event[:x], area_mouse_event[:y])
|
5324
|
-
end
|
5325
|
-
if clicked_circle_data
|
5326
|
-
clicked_circle_data[:fill] = clicked_circle_data[:stroke]
|
5327
|
-
@area.queue_redraw_all
|
5328
|
-
self.score += 1 # notifies score observers automatically of change
|
5329
|
-
end
|
5330
5381
|
end
|
5331
|
-
|
5382
|
+
end
|
5383
|
+
|
5384
|
+
on_mouse_down do |area_mouse_event|
|
5385
|
+
color_circle(area_mouse_event[:x], area_mouse_event[:y])
|
5386
|
+
end
|
5332
5387
|
}
|
5333
|
-
|
5334
5388
|
}
|
5335
5389
|
}.show
|
5336
5390
|
end
|
@@ -5962,38 +6016,50 @@ window('Method-Based Custom Keyword') {
|
|
5962
6016
|
}.show
|
5963
6017
|
```
|
5964
6018
|
|
5965
|
-
##
|
6019
|
+
## Applications
|
5966
6020
|
|
5967
|
-
|
5968
|
-
implemented or the bug hasn't been fixed yet.
|
5969
|
-
- Check out the issue tracker to make sure someone already hasn't
|
5970
|
-
requested it and/or contributed it.
|
5971
|
-
- Fork the project.
|
5972
|
-
- Start a feature/bugfix branch.
|
5973
|
-
- Commit and push until you are happy with your contribution.
|
5974
|
-
- Make sure to add tests for it. This is important so I don't break it
|
5975
|
-
in a future version unintentionally.
|
5976
|
-
- Please try not to mess with the Rakefile, version, or history. If
|
5977
|
-
you want to have your own version, or is otherwise necessary, that
|
5978
|
-
is fine, but please isolate to its own commit so I can cherry-pick
|
5979
|
-
around it.
|
6021
|
+
Here are some applications built with [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui)
|
5980
6022
|
|
5981
|
-
|
6023
|
+
### Manga2PDF
|
5982
6024
|
|
5983
|
-
|
6025
|
+
Download and merge manga images into a single pdf file.
|
5984
6026
|
|
5985
|
-
|
6027
|
+
https://github.com/PinGunter/manga2pdf
|
5986
6028
|
|
5987
|
-
[
|
6029
|
+

|
5988
6030
|
|
5989
|
-
###
|
6031
|
+
### Befunge98 GUI
|
5990
6032
|
|
5991
|
-
|
6033
|
+
Ruby implementation of the Befunge-98 programmming language.
|
6034
|
+
|
6035
|
+
https://github.com/AndyObtiva/befunge98/tree/gui
|
6036
|
+
|
6037
|
+

|
6038
|
+
|
6039
|
+
### i3off Gtk Ruby
|
6040
|
+
|
6041
|
+
https://github.com/iraamaro/i3off-gtk-ruby
|
5992
6042
|
|
5993
6043
|
## Process
|
5994
6044
|
|
5995
6045
|
[Glimmer Process](https://github.com/AndyObtiva/glimmer/blob/master/PROCESS.md)
|
5996
6046
|
|
6047
|
+
## Resources
|
6048
|
+
|
6049
|
+
- [libui C Library](https://github.com/andlabs/libui)
|
6050
|
+
- [LibUI Ruby Bindings](https://github.com/kojix2/LibUI)
|
6051
|
+
- [Code Master Blog](https://andymaleh.blogspot.com/search/label/LibUI)
|
6052
|
+
|
6053
|
+
## Help
|
6054
|
+
|
6055
|
+
### Issues
|
6056
|
+
|
6057
|
+
If you encounter [issues](https://github.com/AndyObtiva/glimmer-dsl-libui/issues) that are not reported, discover missing features that are not mentioned in [TODO.md](TODO.md), or think up better ways to use [libui](https://github.com/andlabs/libui) than what is possible with [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui), you may submit an [issue](https://github.com/AndyObtiva/glimmer-dsl-libui/issues/new) or [pull request](https://github.com/AndyObtiva/glimmer-dsl-libui/compare) on [GitHub](https://github.com).
|
6058
|
+
|
6059
|
+
### Chat
|
6060
|
+
|
6061
|
+
If you need live help, try to [](https://gitter.im/AndyObtiva/glimmer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
6062
|
+
|
5997
6063
|
## Planned Features and Feature Suggestions
|
5998
6064
|
|
5999
6065
|
These features have been planned or suggested. You might see them in a future version of [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui). You are welcome to contribute more feature suggestions.
|
@@ -6004,6 +6070,22 @@ These features have been planned or suggested. You might see them in a future ve
|
|
6004
6070
|
|
6005
6071
|
[CHANGELOG.md](CHANGELOG.md)
|
6006
6072
|
|
6073
|
+
## Contributing
|
6074
|
+
|
6075
|
+
- Check out the latest master to make sure the feature hasn't been
|
6076
|
+
implemented or the bug hasn't been fixed yet.
|
6077
|
+
- Check out the issue tracker to make sure someone already hasn't
|
6078
|
+
requested it and/or contributed it.
|
6079
|
+
- Fork the project.
|
6080
|
+
- Start a feature/bugfix branch.
|
6081
|
+
- Commit and push until you are happy with your contribution.
|
6082
|
+
- Make sure to add tests for it. This is important so I don't break it
|
6083
|
+
in a future version unintentionally.
|
6084
|
+
- Please try not to mess with the Rakefile, version, or history. If
|
6085
|
+
you want to have your own version, or is otherwise necessary, that
|
6086
|
+
is fine, but please isolate to its own commit so I can cherry-pick
|
6087
|
+
around it.
|
6088
|
+
|
6007
6089
|
## Contributors
|
6008
6090
|
|
6009
6091
|
* [Andy Maleh](https://github.com/AndyObtiva) (Founder)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.15
|
data/bin/girb
CHANGED
File without changes
|
data/bin/girb_runner.rb
CHANGED
@@ -27,7 +27,7 @@ require_relative '../lib/glimmer-dsl-libui'
|
|
27
27
|
|
28
28
|
include Glimmer
|
29
29
|
|
30
|
-
GIRB_RUNNER_EXIT_FILE = "#{
|
30
|
+
GIRB_RUNNER_EXIT_FILE = "#{Dir.home}/.girb_runner_exit"
|
31
31
|
FileUtils.rm_rf GIRB_RUNNER_EXIT_FILE
|
32
32
|
|
33
33
|
@exit_method = method(:exit)
|
data/examples/area_gallery.rb
CHANGED