glimmer-dsl-libui 0.4.5 → 0.4.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +33 -0
- data/README.md +388 -57
- data/VERSION +1 -1
- data/examples/button_counter.rb +2 -1
- data/examples/color_button.rb +18 -13
- data/examples/color_button2.rb +14 -0
- data/examples/date_time_picker.rb +19 -14
- data/examples/date_time_picker2.rb +20 -0
- data/examples/font_button.rb +17 -12
- data/examples/font_button2.rb +18 -0
- data/examples/histogram.rb +1 -6
- data/examples/meta_example.rb +17 -6
- data/examples/midi_player.rb +5 -6
- data/examples/midi_player2.rb +83 -0
- data/examples/midi_player3.rb +84 -0
- data/examples/snake.rb +19 -10
- data/examples/tetris.rb +15 -18
- data/glimmer-dsl-libui.gemspec +0 -0
- data/lib/glimmer/libui/control_proxy/checkbox_proxy.rb +4 -0
- data/lib/glimmer/libui/control_proxy/color_button_proxy.rb +4 -0
- data/lib/glimmer/libui/control_proxy/combobox_proxy.rb +17 -2
- data/lib/glimmer/libui/control_proxy/date_time_picker_proxy.rb +4 -0
- data/lib/glimmer/libui/control_proxy/editable_combobox_proxy.rb +4 -0
- data/lib/glimmer/libui/control_proxy/entry_proxy.rb +1 -2
- data/lib/glimmer/libui/control_proxy/font_button_proxy.rb +8 -0
- data/lib/glimmer/libui/control_proxy/menu_item_proxy/check_menu_item_proxy.rb +4 -0
- data/lib/glimmer/libui/control_proxy/menu_item_proxy/radio_menu_item_proxy.rb +16 -4
- data/lib/glimmer/libui/control_proxy/multiline_entry_proxy.rb +1 -2
- data/lib/glimmer/libui/control_proxy/radio_buttons_proxy.rb +19 -0
- data/lib/glimmer/libui/control_proxy/slider_proxy.rb +37 -0
- data/lib/glimmer/libui/control_proxy/spinbox_proxy.rb +1 -2
- data/lib/glimmer/libui/control_proxy.rb +2 -2
- data/lib/glimmer/libui/data_bindable.rb +27 -2
- metadata +8 -2
data/README.md
CHANGED
@@ -1,9 +1,9 @@
|
|
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.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.4.9
|
2
2
|
## Prerequisite-Free Ruby Desktop Development GUI Library
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/glimmer-dsl-libui.svg)](http://badge.fury.io/rb/glimmer-dsl-libui)
|
4
4
|
[![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)
|
5
5
|
|
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!
|
6
|
+
[Glimmer](https://github.com/AndyObtiva/glimmer) DSL for [LibUI](https://github.com/kojix2/LibUI) is a prerequisite-free Ruby desktop development GUI (Graphical User Interface) library. No need to pre-install any prerequisites. Just install the [gem](https://rubygems.org/gems/glimmer-dsl-libui) and have platform-independent native GUI that just works!
|
7
7
|
|
8
8
|
Mac | Windows | Linux
|
9
9
|
----|---------|------
|
@@ -373,7 +373,7 @@ gem install glimmer-dsl-libui
|
|
373
373
|
Or install via Bundler `Gemfile`:
|
374
374
|
|
375
375
|
```ruby
|
376
|
-
gem 'glimmer-dsl-libui', '~> 0.4.
|
376
|
+
gem 'glimmer-dsl-libui', '~> 0.4.9'
|
377
377
|
```
|
378
378
|
|
379
379
|
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.
|
@@ -460,7 +460,7 @@ Keyword(Args) | Properties | Listeners
|
|
460
460
|
`checkbox_text_column(name as String)` | `editable` (Boolean), `editable_checkbox` (Boolean), `editable_text` (Boolean) | None
|
461
461
|
`checkbox_text_color_column(name as String)` | `editable` (Boolean), `editable_checkbox` (Boolean), `editable_text` (Boolean) | None
|
462
462
|
`check_menu_item(text as String)` | `checked` (Boolean) | `on_clicked`
|
463
|
-
`combobox` | `items` (`Array` of `String`), `selected` (`Integer`) | `on_selected`
|
463
|
+
`combobox` | `items` (`Array` of `String`), `selected` (`Integer`), `selected_item` (`String`) | `on_selected`
|
464
464
|
`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`
|
465
465
|
`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`
|
466
466
|
`date_time_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`
|
@@ -1382,11 +1382,24 @@ Data-binding supports utilizing the [MVP (Model View Presenter)](https://en.wiki
|
|
1382
1382
|
![MVP](https://www.researchgate.net/profile/Gilles-Perrouin/publication/320249584/figure/fig8/AS:668260987068418@1536337243385/Model-view-presenter-architecture.png)
|
1383
1383
|
|
1384
1384
|
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) supports bidirectional (two-way) data-binding of the following controls/properties via the `<=>` operator (indicating data is moving in both directions between View and Model):
|
1385
|
-
- `
|
1386
|
-
- `
|
1387
|
-
- `
|
1388
|
-
- `
|
1389
|
-
- `
|
1385
|
+
- `checkbox`: `checked`
|
1386
|
+
- `check_menu_item`: `checked`
|
1387
|
+
- `color_button`: `color`
|
1388
|
+
- `combobox`: `selected`, `selected_item`
|
1389
|
+
- `date_picker`: `time`
|
1390
|
+
- `date_time_picker`: `time`
|
1391
|
+
- `editable_combobox`: `text`
|
1392
|
+
- `entry`: `text`
|
1393
|
+
- `font_button`: `font`
|
1394
|
+
- `multiline_entry`: `text`
|
1395
|
+
- `non_wrapping_multiline_entry`: `text`
|
1396
|
+
- `radio_buttons`: `selected`
|
1397
|
+
- `radio_menu_item`: `checked`
|
1398
|
+
- `search_entry`: `text`
|
1399
|
+
- `slider`: `value`
|
1400
|
+
- `spinbox`: `value`
|
1401
|
+
- `table`: `cell_rows` (explicit data-binding using `<=>` and [implicit data-binding](#table-api) by assigning value directly)
|
1402
|
+
- `time_picker`: `time`
|
1390
1403
|
|
1391
1404
|
Example of bidirectional data-binding:
|
1392
1405
|
|
@@ -1436,6 +1449,11 @@ To summarize the data-binding API:
|
|
1436
1449
|
|
1437
1450
|
This is also known as the [Glimmer Shine](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#shine) syntax for data-binding, a [Glimmer](https://github.com/AndyObtiva/glimmer)-only unique innovation that takes advantage of [Ruby](https://www.ruby-lang.org/en/)'s highly expressive syntax and malleable DSL support.
|
1438
1451
|
|
1452
|
+
Data-bound model attribute can be:
|
1453
|
+
- **Direct:** `Symbol` representing attribute reader/writer (e.g. `[person, :name`])
|
1454
|
+
- **Nested:** `String` representing nested attribute path (e.g. `[company, 'address.street']`). That results in "nested data-binding"
|
1455
|
+
- **Indexed:** `String` containing array attribute index (e.g. `[customer, 'addresses[0].street']`). That results in "indexed data-binding"
|
1456
|
+
|
1439
1457
|
Data-binding options include:
|
1440
1458
|
- `before_read {|value| ...}`: performs an operation before reading data from Model to update the View.
|
1441
1459
|
- `on_read {|value| ...}`: converts value read from Model to update the View.
|
@@ -1443,7 +1461,7 @@ Data-binding options include:
|
|
1443
1461
|
- `before_write {|value| ...}`: performs an operation before writing data to Model from View.
|
1444
1462
|
- `on_write {|value| ...}`: converts value read from View to update the Model.
|
1445
1463
|
- `after_write {|converted_value| ...}`: performs an operation after writing to Model from View.
|
1446
|
-
- `computed_by attribute` or `computed_by [attribute1, attribute2, ...]`: indicates model attribute is computed from specified attribute(s), thus updated when they are updated (see in [Login example version 2](/examples/login2.rb))
|
1464
|
+
- `computed_by attribute` or `computed_by [attribute1, attribute2, ...]`: indicates model attribute is computed from specified attribute(s), thus updated when they are updated (see in [Login example version 2](/examples/login2.rb)). That is known as "computed data-binding".
|
1447
1465
|
|
1448
1466
|
Note that with both `on_read` and `on_write` converters, you could pass a `Symbol` representing the name of a method on the value object to invoke.
|
1449
1467
|
|
@@ -1875,7 +1893,7 @@ Example:
|
|
1875
1893
|
|
1876
1894
|
## Examples
|
1877
1895
|
|
1878
|
-
The following examples include reimplementions of the examples in the [LibUI](https://github.com/kojix2/LibUI) project utilizing the [Glimmer GUI DSL](#glimmer-gui-dsl-concepts) as well as brand new examples.
|
1896
|
+
The following examples include reimplementions of the examples in the [LibUI](https://github.com/kojix2/LibUI) project utilizing the [Glimmer GUI DSL](#glimmer-gui-dsl-concepts) (with and without [data-binding](#data-binding)) as well as brand new examples.
|
1879
1897
|
|
1880
1898
|
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.
|
1881
1899
|
|
@@ -2490,7 +2508,33 @@ UI.quit
|
|
2490
2508
|
|
2491
2509
|
```
|
2492
2510
|
|
2493
|
-
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
2511
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version (with [data-binding](#data-binding)):
|
2512
|
+
|
2513
|
+
```ruby
|
2514
|
+
require 'glimmer-dsl-libui'
|
2515
|
+
|
2516
|
+
class FontButton
|
2517
|
+
include Glimmer
|
2518
|
+
|
2519
|
+
attr_accessor :font_descriptor
|
2520
|
+
|
2521
|
+
def launch
|
2522
|
+
window('hello world', 300, 200) {
|
2523
|
+
font_button {
|
2524
|
+
font <=> [self, :font_descriptor, after_write: -> { p font_descriptor }]
|
2525
|
+
}
|
2526
|
+
|
2527
|
+
on_closing do
|
2528
|
+
puts 'Bye Bye'
|
2529
|
+
end
|
2530
|
+
}.show
|
2531
|
+
end
|
2532
|
+
end
|
2533
|
+
|
2534
|
+
FontButton.new.launch
|
2535
|
+
```
|
2536
|
+
|
2537
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (without [data-binding](#data-binding)):
|
2494
2538
|
|
2495
2539
|
```ruby
|
2496
2540
|
require 'glimmer-dsl-libui'
|
@@ -2531,7 +2575,33 @@ Mac | Windows | Linux
|
|
2531
2575
|
----|---------|------
|
2532
2576
|
![glimmer-dsl-libui-mac-color-button.png](images/glimmer-dsl-libui-mac-color-button.png) ![glimmer-dsl-libui-mac-color-button-selection.png](images/glimmer-dsl-libui-mac-color-button-selection.png) | ![glimmer-dsl-libui-windows-color-button.png](images/glimmer-dsl-libui-windows-color-button.png) ![glimmer-dsl-libui-windows-color-button-selection.png](images/glimmer-dsl-libui-windows-color-button-selection.png) | ![glimmer-dsl-libui-linux-color-button.png](images/glimmer-dsl-libui-linux-color-button.png) ![glimmer-dsl-libui-linux-color-button-selection.png](images/glimmer-dsl-libui-linux-color-button-selection.png)
|
2533
2577
|
|
2534
|
-
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
2578
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version (with [data-binding](#data-binding)):
|
2579
|
+
|
2580
|
+
```ruby
|
2581
|
+
require 'glimmer-dsl-libui'
|
2582
|
+
|
2583
|
+
class ColorButton
|
2584
|
+
include Glimmer
|
2585
|
+
|
2586
|
+
attr_accessor :selected_color
|
2587
|
+
|
2588
|
+
def initialize
|
2589
|
+
@selected_color = :blue
|
2590
|
+
end
|
2591
|
+
|
2592
|
+
def launch
|
2593
|
+
window('color button', 240) {
|
2594
|
+
color_button {
|
2595
|
+
color <=> [self, :selected_color, after_write: ->(color) {p color}]
|
2596
|
+
}
|
2597
|
+
}.show
|
2598
|
+
end
|
2599
|
+
end
|
2600
|
+
|
2601
|
+
ColorButton.new.launch
|
2602
|
+
```
|
2603
|
+
|
2604
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (without [data-binding](#data-binding)):
|
2535
2605
|
|
2536
2606
|
```ruby
|
2537
2607
|
require 'glimmer-dsl-libui'
|
@@ -2613,7 +2683,35 @@ UI.main
|
|
2613
2683
|
UI.quit
|
2614
2684
|
```
|
2615
2685
|
|
2616
|
-
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
2686
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version (with [data-binding](#data-binding)):
|
2687
|
+
|
2688
|
+
```ruby
|
2689
|
+
require 'glimmer-dsl-libui'
|
2690
|
+
|
2691
|
+
class DateTimePicker
|
2692
|
+
include Glimmer
|
2693
|
+
|
2694
|
+
attr_accessor :picked_time
|
2695
|
+
|
2696
|
+
def launch
|
2697
|
+
window('Date Time Pickers', 300, 200) {
|
2698
|
+
vertical_box {
|
2699
|
+
date_time_picker {
|
2700
|
+
time <=> [self, :picked_time, after_write: ->(time) { p time }]
|
2701
|
+
}
|
2702
|
+
}
|
2703
|
+
|
2704
|
+
on_closing do
|
2705
|
+
puts 'Bye Bye'
|
2706
|
+
end
|
2707
|
+
}.show
|
2708
|
+
end
|
2709
|
+
end
|
2710
|
+
|
2711
|
+
DateTimePicker.new.launch
|
2712
|
+
```
|
2713
|
+
|
2714
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (without [data-binding](#data-binding)):
|
2617
2715
|
|
2618
2716
|
```ruby
|
2619
2717
|
require 'glimmer-dsl-libui'
|
@@ -3171,7 +3269,62 @@ Mac | Windows | Linux
|
|
3171
3269
|
----|---------|------
|
3172
3270
|
![glimmer-dsl-libui-mac-basic-table-button.png](images/glimmer-dsl-libui-mac-basic-table-button.png) ![glimmer-dsl-libui-mac-basic-table-button-deleted.png](images/glimmer-dsl-libui-mac-basic-table-button-deleted.png) | ![glimmer-dsl-libui-windows-basic-table-button.png](images/glimmer-dsl-libui-windows-basic-table-button.png) ![glimmer-dsl-libui-windows-basic-table-button-deleted.png](images/glimmer-dsl-libui-windows-basic-table-button-deleted.png) | ![glimmer-dsl-libui-linux-basic-table-button.png](images/glimmer-dsl-libui-linux-basic-table-button.png) ![glimmer-dsl-libui-linux-basic-table-button-deleted.png](images/glimmer-dsl-libui-linux-basic-table-button-deleted.png)
|
3173
3271
|
|
3174
|
-
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
3272
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version (with explicit [data-binding](#data-binding)):
|
3273
|
+
|
3274
|
+
```ruby
|
3275
|
+
# frozen_string_literal: true
|
3276
|
+
|
3277
|
+
require 'glimmer-dsl-libui'
|
3278
|
+
|
3279
|
+
class BasicTableButton
|
3280
|
+
include Glimmer
|
3281
|
+
|
3282
|
+
attr_accessor :data
|
3283
|
+
|
3284
|
+
def initialize
|
3285
|
+
@data = [
|
3286
|
+
%w[cat meow delete],
|
3287
|
+
%w[dog woof delete],
|
3288
|
+
%w[chicken cock-a-doodle-doo delete],
|
3289
|
+
%w[horse neigh delete],
|
3290
|
+
%w[cow moo delete]
|
3291
|
+
]
|
3292
|
+
end
|
3293
|
+
|
3294
|
+
def launch
|
3295
|
+
window('Animal sounds', 400, 200) {
|
3296
|
+
horizontal_box {
|
3297
|
+
table {
|
3298
|
+
text_column('Animal')
|
3299
|
+
text_column('Description')
|
3300
|
+
button_column('Action') {
|
3301
|
+
on_clicked do |row|
|
3302
|
+
# Option 1: direct data deletion is the simpler solution
|
3303
|
+
# @data.delete_at(row) # automatically deletes actual table row due to explicit data-binding
|
3304
|
+
|
3305
|
+
# Option 2: cloning only to demonstrate table row deletion upon explicit setting of data attribute (cloning is not recommended beyond demonstrating this point)
|
3306
|
+
new_data = @data.clone
|
3307
|
+
new_data.delete_at(row)
|
3308
|
+
self.data = new_data # automatically loses deleted table row due to explicit data-binding
|
3309
|
+
end
|
3310
|
+
}
|
3311
|
+
|
3312
|
+
cell_rows <=> [self, :data] # explicit data-binding of table cell_rows to self.data
|
3313
|
+
|
3314
|
+
on_changed do |row, type, row_data|
|
3315
|
+
puts "Row #{row} #{type}: #{row_data}"
|
3316
|
+
$stdout.flush
|
3317
|
+
end
|
3318
|
+
}
|
3319
|
+
}
|
3320
|
+
}.show
|
3321
|
+
end
|
3322
|
+
end
|
3323
|
+
|
3324
|
+
BasicTableButton.new.launch
|
3325
|
+
```
|
3326
|
+
|
3327
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (with implicit [data-binding](#data-binding)):
|
3175
3328
|
|
3176
3329
|
```ruby
|
3177
3330
|
require 'glimmer-dsl-libui'
|
@@ -4950,7 +5103,8 @@ class ButtonCounter
|
|
4950
5103
|
def launch
|
4951
5104
|
window('Hello, Button!') {
|
4952
5105
|
button {
|
4953
|
-
|
5106
|
+
# data-bind button text to self count, converting to string on read.
|
5107
|
+
text <= [self, :count, on_read: ->(count) {"Count: #{count}"}]
|
4954
5108
|
|
4955
5109
|
on_clicked do
|
4956
5110
|
self.count += 1
|
@@ -6351,7 +6505,7 @@ require 'glimmer-dsl-libui'
|
|
6351
6505
|
class FormTable
|
6352
6506
|
include Glimmer
|
6353
6507
|
|
6354
|
-
attr_accessor :name, :email, :phone, :city, :state, :filter_value
|
6508
|
+
attr_accessor :data, :name, :email, :phone, :city, :state, :filter_value
|
6355
6509
|
|
6356
6510
|
def initialize
|
6357
6511
|
@data = [
|
@@ -6422,10 +6576,10 @@ class FormTable
|
|
6422
6576
|
after_write: ->(filter_value) { # execute after write to self.filter_value
|
6423
6577
|
@unfiltered_data ||= @data.dup
|
6424
6578
|
# Unfilter first to remove any previous filters
|
6425
|
-
|
6579
|
+
self.data = @unfiltered_data # affects table indirectly through explicit data-binding
|
6426
6580
|
# Now, apply filter if entered
|
6427
6581
|
unless filter_value.empty?
|
6428
|
-
@data.filter
|
6582
|
+
self.data = @data.filter do |row_data| # affects table indirectly through explicit data-binding
|
6429
6583
|
row_data.any? do |cell|
|
6430
6584
|
cell.to_s.downcase.include?(filter_value.downcase)
|
6431
6585
|
end
|
@@ -6442,7 +6596,7 @@ class FormTable
|
|
6442
6596
|
text_column('City')
|
6443
6597
|
text_column('State')
|
6444
6598
|
|
6445
|
-
cell_rows
|
6599
|
+
cell_rows <=> [self, :data] # explicit data-binding
|
6446
6600
|
|
6447
6601
|
on_changed do |row, type, row_data|
|
6448
6602
|
puts "Row #{row} #{type}: #{row_data}"
|
@@ -6975,12 +7129,7 @@ class Histogram
|
|
6975
7129
|
|
6976
7130
|
color_button { |cb|
|
6977
7131
|
stretchy false
|
6978
|
-
color
|
6979
|
-
|
6980
|
-
on_changed do
|
6981
|
-
@histogram_color = cb.color
|
6982
|
-
@area.queue_redraw_all
|
6983
|
-
end
|
7132
|
+
color <=> [self, :histogram_color, after_write: -> { @area.queue_redraw_all }]
|
6984
7133
|
}
|
6985
7134
|
}
|
6986
7135
|
|
@@ -7802,7 +7951,181 @@ end
|
|
7802
7951
|
TinyMidiPlayer.new
|
7803
7952
|
```
|
7804
7953
|
|
7805
|
-
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
7954
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version (with [data-binding](#data-binding)):
|
7955
|
+
|
7956
|
+
```ruby
|
7957
|
+
# frozen_string_literal: true
|
7958
|
+
|
7959
|
+
require 'glimmer-dsl-libui'
|
7960
|
+
|
7961
|
+
class TinyMidiPlayer
|
7962
|
+
include Glimmer
|
7963
|
+
|
7964
|
+
VERSION = '0.0.1'
|
7965
|
+
|
7966
|
+
attr_accessor :selected_file
|
7967
|
+
|
7968
|
+
def initialize
|
7969
|
+
@pid = nil
|
7970
|
+
@music_directory = File.expand_path('../sounds', __dir__)
|
7971
|
+
@midi_files = Dir.glob(File.join(@music_directory, '**/*.mid'))
|
7972
|
+
.sort_by { |path| File.basename(path) }
|
7973
|
+
at_exit { stop_midi }
|
7974
|
+
create_gui
|
7975
|
+
end
|
7976
|
+
|
7977
|
+
def stop_midi
|
7978
|
+
if @pid
|
7979
|
+
Process.kill(:SIGKILL, @pid) if @th.alive?
|
7980
|
+
@pid = nil
|
7981
|
+
end
|
7982
|
+
end
|
7983
|
+
|
7984
|
+
def play_midi
|
7985
|
+
stop_midi
|
7986
|
+
if @pid.nil? && @selected_file
|
7987
|
+
begin
|
7988
|
+
@pid = spawn "timidity #{@selected_file}"
|
7989
|
+
@th = Process.detach @pid
|
7990
|
+
rescue Errno::ENOENT
|
7991
|
+
warn 'Timidty++ not found. Please install Timidity++.'
|
7992
|
+
warn 'https://sourceforge.net/projects/timidity/'
|
7993
|
+
end
|
7994
|
+
end
|
7995
|
+
end
|
7996
|
+
|
7997
|
+
def show_version
|
7998
|
+
msg_box('Tiny Midi Player',
|
7999
|
+
"Written in Ruby\n" \
|
8000
|
+
"https://github.com/kojix2/libui\n" \
|
8001
|
+
"Version #{VERSION}")
|
8002
|
+
end
|
8003
|
+
|
8004
|
+
def create_gui
|
8005
|
+
menu('Help') {
|
8006
|
+
menu_item('Version') {
|
8007
|
+
on_clicked do
|
8008
|
+
show_version
|
8009
|
+
end
|
8010
|
+
}
|
8011
|
+
}
|
8012
|
+
window('Tiny Midi Player', 200, 50) {
|
8013
|
+
horizontal_box {
|
8014
|
+
vertical_box {
|
8015
|
+
stretchy false
|
8016
|
+
|
8017
|
+
button('▶') {
|
8018
|
+
on_clicked do
|
8019
|
+
play_midi
|
8020
|
+
end
|
8021
|
+
}
|
8022
|
+
button('■') {
|
8023
|
+
on_clicked do
|
8024
|
+
stop_midi
|
8025
|
+
end
|
8026
|
+
}
|
8027
|
+
}
|
8028
|
+
|
8029
|
+
combobox {
|
8030
|
+
items @midi_files.map { |path| File.basename(path) }
|
8031
|
+
# data-bind selected item (String) to self.selected_file with on-read/on-write converters and after_write operation
|
8032
|
+
selected_item <=> [self, :selected_file, on_read: ->(f) {File.basename(f.to_s)}, on_write: ->(f) {File.join(@music_directory, f)}, after_write: -> { play_midi if @th&.alive? }]
|
8033
|
+
}
|
8034
|
+
}
|
8035
|
+
}.show
|
8036
|
+
end
|
8037
|
+
end
|
8038
|
+
|
8039
|
+
TinyMidiPlayer.new
|
8040
|
+
```
|
8041
|
+
|
8042
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (with [data-binding](#data-binding)):
|
8043
|
+
|
8044
|
+
```ruby
|
8045
|
+
require 'glimmer-dsl-libui'
|
8046
|
+
|
8047
|
+
class TinyMidiPlayer
|
8048
|
+
include Glimmer
|
8049
|
+
|
8050
|
+
VERSION = '0.0.1'
|
8051
|
+
|
8052
|
+
attr_accessor :selected_file
|
8053
|
+
|
8054
|
+
def initialize
|
8055
|
+
@pid = nil
|
8056
|
+
@music_directory = File.expand_path('../sounds', __dir__)
|
8057
|
+
@midi_files = Dir.glob(File.join(@music_directory, '**/*.mid'))
|
8058
|
+
.sort_by { |path| File.basename(path) }
|
8059
|
+
at_exit { stop_midi }
|
8060
|
+
create_gui
|
8061
|
+
end
|
8062
|
+
|
8063
|
+
def stop_midi
|
8064
|
+
if @pid
|
8065
|
+
Process.kill(:SIGKILL, @pid) if @th.alive?
|
8066
|
+
@pid = nil
|
8067
|
+
end
|
8068
|
+
end
|
8069
|
+
|
8070
|
+
def play_midi
|
8071
|
+
stop_midi
|
8072
|
+
if @pid.nil? && @selected_file
|
8073
|
+
begin
|
8074
|
+
@pid = spawn "timidity #{@selected_file}"
|
8075
|
+
@th = Process.detach @pid
|
8076
|
+
rescue Errno::ENOENT
|
8077
|
+
warn 'Timidty++ not found. Please install Timidity++.'
|
8078
|
+
warn 'https://sourceforge.net/projects/timidity/'
|
8079
|
+
end
|
8080
|
+
end
|
8081
|
+
end
|
8082
|
+
|
8083
|
+
def show_version
|
8084
|
+
msg_box('Tiny Midi Player',
|
8085
|
+
"Written in Ruby\n" \
|
8086
|
+
"https://github.com/kojix2/libui\n" \
|
8087
|
+
"Version #{VERSION}")
|
8088
|
+
end
|
8089
|
+
|
8090
|
+
def create_gui
|
8091
|
+
menu('Help') {
|
8092
|
+
menu_item('Version') {
|
8093
|
+
on_clicked do
|
8094
|
+
show_version
|
8095
|
+
end
|
8096
|
+
}
|
8097
|
+
}
|
8098
|
+
window('Tiny Midi Player', 200, 50) {
|
8099
|
+
horizontal_box {
|
8100
|
+
vertical_box {
|
8101
|
+
stretchy false
|
8102
|
+
|
8103
|
+
button('▶') {
|
8104
|
+
on_clicked do
|
8105
|
+
play_midi
|
8106
|
+
end
|
8107
|
+
}
|
8108
|
+
button('■') {
|
8109
|
+
on_clicked do
|
8110
|
+
stop_midi
|
8111
|
+
end
|
8112
|
+
}
|
8113
|
+
}
|
8114
|
+
|
8115
|
+
combobox {
|
8116
|
+
items @midi_files.map { |path| File.basename(path) }
|
8117
|
+
# data-bind selected index (Integer) to self.selected_file with on-read/on-write converters and after_write operation
|
8118
|
+
selected <=> [self, :selected_file, on_read: ->(f) {@midi_files.index(f)}, on_write: ->(i) {@midi_files[i]}, after_write: -> { play_midi if @th&.alive? }]
|
8119
|
+
}
|
8120
|
+
}
|
8121
|
+
}.show
|
8122
|
+
end
|
8123
|
+
end
|
8124
|
+
|
8125
|
+
TinyMidiPlayer.new
|
8126
|
+
```
|
8127
|
+
|
8128
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 3 (without [data-binding](#data-binding)):
|
7806
8129
|
|
7807
8130
|
```ruby
|
7808
8131
|
require 'glimmer-dsl-libui'
|
@@ -7928,6 +8251,7 @@ class Snake
|
|
7928
8251
|
@game = Model::Game.new
|
7929
8252
|
@grid = Presenter::Grid.new(@game)
|
7930
8253
|
@game.start
|
8254
|
+
@keypress_queue = []
|
7931
8255
|
create_gui
|
7932
8256
|
register_observers
|
7933
8257
|
end
|
@@ -7947,14 +8271,30 @@ class Snake
|
|
7947
8271
|
end
|
7948
8272
|
|
7949
8273
|
Glimmer::LibUI.timer(SNAKE_MOVE_DELAY) do
|
7950
|
-
|
8274
|
+
unless @game.over?
|
8275
|
+
process_queued_keypress
|
8276
|
+
@game.snake.move
|
8277
|
+
end
|
8278
|
+
end
|
8279
|
+
end
|
8280
|
+
|
8281
|
+
def process_queued_keypress
|
8282
|
+
# key press queue ensures one turn per snake move to avoid a double-turn resulting in instant death (due to snake illogically going back against itself)
|
8283
|
+
key = @keypress_queue.shift
|
8284
|
+
case [@game.snake.head.orientation, key]
|
8285
|
+
in [:north, :right] | [:east, :down] | [:south, :left] | [:west, :up]
|
8286
|
+
@game.snake.turn_right
|
8287
|
+
in [:north, :left] | [:west, :down] | [:south, :right] | [:east, :up]
|
8288
|
+
@game.snake.turn_left
|
8289
|
+
else
|
8290
|
+
# No Op
|
7951
8291
|
end
|
7952
8292
|
end
|
7953
8293
|
|
7954
8294
|
def create_gui
|
7955
8295
|
@main_window = window {
|
7956
8296
|
# data-bind window title to game score, converting it to a title string on read from the model
|
7957
|
-
title <= [@game, :score, on_read: -> (score) {"
|
8297
|
+
title <= [@game, :score, on_read: -> (score) {"Snake (Score: #{@game.score})"}]
|
7958
8298
|
content_size @game.width * CELL_SIZE, @game.height * CELL_SIZE
|
7959
8299
|
resizable false
|
7960
8300
|
|
@@ -7972,15 +8312,7 @@ class Snake
|
|
7972
8312
|
}
|
7973
8313
|
|
7974
8314
|
on_key_up do |area_key_event|
|
7975
|
-
|
7976
|
-
case orientation_and_key
|
7977
|
-
in [:north, :right] | [:east, :down] | [:south, :left] | [:west, :up]
|
7978
|
-
@game.snake.turn_right
|
7979
|
-
in [:north, :left] | [:west, :down] | [:south, :right] | [:east, :up]
|
7980
|
-
@game.snake.turn_left
|
7981
|
-
else
|
7982
|
-
# No Op
|
7983
|
-
end
|
8315
|
+
@keypress_queue << area_key_event[:ext_key]
|
7984
8316
|
end
|
7985
8317
|
}
|
7986
8318
|
end
|
@@ -8130,22 +8462,23 @@ class Tetris
|
|
8130
8462
|
menu('Game') {
|
8131
8463
|
@pause_menu_item = check_menu_item('Pause') {
|
8132
8464
|
enabled false
|
8133
|
-
|
8134
|
-
on_clicked do
|
8135
|
-
@game.paused = @pause_menu_item.checked?
|
8136
|
-
end
|
8465
|
+
checked <=> [@game, :paused]
|
8137
8466
|
}
|
8467
|
+
|
8138
8468
|
menu_item('Restart') {
|
8139
8469
|
on_clicked do
|
8140
8470
|
@game.restart!
|
8141
8471
|
end
|
8142
8472
|
}
|
8473
|
+
|
8143
8474
|
separator_menu_item
|
8475
|
+
|
8144
8476
|
menu_item('Exit') {
|
8145
8477
|
on_clicked do
|
8146
8478
|
exit(0)
|
8147
8479
|
end
|
8148
8480
|
}
|
8481
|
+
|
8149
8482
|
quit_menu_item if OS.mac?
|
8150
8483
|
}
|
8151
8484
|
|
@@ -8155,6 +8488,7 @@ class Tetris
|
|
8155
8488
|
show_high_scores
|
8156
8489
|
end
|
8157
8490
|
}
|
8491
|
+
|
8158
8492
|
menu_item('Clear High Scores') {
|
8159
8493
|
on_clicked {
|
8160
8494
|
@game.clear_high_scores!
|
@@ -8163,22 +8497,16 @@ class Tetris
|
|
8163
8497
|
}
|
8164
8498
|
|
8165
8499
|
menu('Options') {
|
8166
|
-
radio_menu_item('Instant Down on Up Arrow') {
|
8167
|
-
|
8168
|
-
@game.instant_down_on_up = true
|
8169
|
-
end
|
8500
|
+
radio_menu_item('Instant Down on Up Arrow') { |r|
|
8501
|
+
checked <=> [@game, :instant_down_on_up]
|
8170
8502
|
}
|
8171
|
-
|
8172
|
-
|
8173
|
-
|
8174
|
-
end
|
8503
|
+
|
8504
|
+
radio_menu_item('Rotate Right on Up Arrow') { |r|
|
8505
|
+
checked <=> [@game, :rotate_right_on_up]
|
8175
8506
|
}
|
8176
|
-
|
8177
|
-
|
8178
|
-
|
8179
|
-
on_clicked do
|
8180
|
-
@game.rotate_left_on_up = true
|
8181
|
-
end
|
8507
|
+
|
8508
|
+
radio_menu_item('Rotate Left on Up Arrow') { |r|
|
8509
|
+
checked <=> [@game, :rotate_left_on_up]
|
8182
8510
|
}
|
8183
8511
|
}
|
8184
8512
|
|
@@ -8190,6 +8518,7 @@ class Tetris
|
|
8190
8518
|
end
|
8191
8519
|
}
|
8192
8520
|
end
|
8521
|
+
|
8193
8522
|
menu_item('About') {
|
8194
8523
|
on_clicked do
|
8195
8524
|
show_about_dialog
|
@@ -8819,7 +9148,7 @@ https://github.com/iraamaro/i3off-gtk-ruby
|
|
8819
9148
|
|
8820
9149
|
### Issues
|
8821
9150
|
|
8822
|
-
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).
|
9151
|
+
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). In the meantime, you may try older gem versions of [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) till you find one that works until issues are resolved.
|
8823
9152
|
|
8824
9153
|
### Chat
|
8825
9154
|
|
@@ -8851,6 +9180,8 @@ These features have been planned or suggested. You might see them in a future ve
|
|
8851
9180
|
is fine, but please isolate to its own commit so I can cherry-pick
|
8852
9181
|
around it.
|
8853
9182
|
|
9183
|
+
Note that the latest development sometimes takes place in the [development](https://github.com/AndyObtiva/glimmer-dsl-libui/tree/development) branch (usually deleted once merged back to [master](https://github.com/AndyObtiva/glimmer-dsl-libui)).
|
9184
|
+
|
8854
9185
|
## Contributors
|
8855
9186
|
|
8856
9187
|
* [Andy Maleh](https://github.com/AndyObtiva) (Founder)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.4.
|
1
|
+
0.4.9
|
data/examples/button_counter.rb
CHANGED
@@ -13,7 +13,8 @@ class ButtonCounter
|
|
13
13
|
window('Hello, Button!', 190, 20) {
|
14
14
|
vertical_box {
|
15
15
|
button {
|
16
|
-
|
16
|
+
# data-bind button text to self count, converting to string on read.
|
17
|
+
text <= [self, :count, on_read: ->(count) {"Count: #{count}"}]
|
17
18
|
|
18
19
|
on_clicked do
|
19
20
|
self.count += 1
|
data/examples/color_button.rb
CHANGED
@@ -1,16 +1,21 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
require 'glimmer-dsl-libui'
|
4
2
|
|
5
|
-
|
3
|
+
class ColorButton
|
4
|
+
include Glimmer
|
5
|
+
|
6
|
+
attr_accessor :selected_color
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@selected_color = :blue
|
10
|
+
end
|
11
|
+
|
12
|
+
def launch
|
13
|
+
window('color button', 240) {
|
14
|
+
color_button {
|
15
|
+
color <=> [self, :selected_color, after_write: ->(color) {p color}]
|
16
|
+
}
|
17
|
+
}.show
|
18
|
+
end
|
19
|
+
end
|
6
20
|
|
7
|
-
|
8
|
-
color_button { |cb|
|
9
|
-
color :blue
|
10
|
-
|
11
|
-
on_changed do
|
12
|
-
rgba = cb.color
|
13
|
-
p rgba
|
14
|
-
end
|
15
|
-
}
|
16
|
-
}.show
|
21
|
+
ColorButton.new.launch
|