glimmer-dsl-libui 0.4.5 → 0.4.9
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 +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
|
[](http://badge.fury.io/rb/glimmer-dsl-libui)
|
4
4
|
[](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
|

|
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
|
  |   |  
|
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
|
  |   |  
|
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
|