glimmer-dsl-libui 0.2.11 → 0.2.15
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Gem Version](https://badge.fury.io/rb/glimmer-dsl-libui.svg)](http://badge.fury.io/rb/glimmer-dsl-libui)
|
4
|
-
[![Maintainability](https://api.codeclimate.com/v1/badges/ce2853efdbecf6ebdc73/maintainability)](https://codeclimate.com/github/AndyObtiva/glimmer-dsl-libui/maintainability)
|
5
4
|
[![Join the chat at https://gitter.im/AndyObtiva/glimmer](https://badges.gitter.im/AndyObtiva/glimmer.svg)](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
|
+
![manga2pdf screenshot](https://raw.githubusercontent.com/PinGunter/manga2pdf/master/screenshots/manga2pdf-gui.png)
|
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
|
+
![befunge98 gui screenshot](https://raw.githubusercontent.com/AndyObtiva/befunge98/master/gui/glimmer-dsl-libui/befunge98_gui_glimmer_dsl_libui/screenshots/befunge98_gui_glimmer_dsl_libui_example.png)
|
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 [![Join the chat at https://gitter.im/AndyObtiva/glimmer](https://badges.gitter.im/AndyObtiva/glimmer.svg)](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