glimmer-dsl-libui 0.4.4 → 0.4.8
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 +36 -1
- data/README.md +932 -160
- 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/dynamic_area.rb +77 -90
- data/examples/dynamic_area2.rb +14 -12
- data/examples/dynamic_area3.rb +90 -0
- data/examples/dynamic_area4.rb +95 -0
- data/examples/font_button.rb +17 -12
- data/examples/font_button2.rb +18 -0
- data/examples/form_table.rb +0 -2
- data/examples/form_table2.rb +0 -2
- data/examples/histogram.rb +93 -91
- data/examples/histogram2.rb +109 -0
- 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/tetris.rb +15 -18
- data/examples/timer.rb +28 -31
- data/examples/timer2.rb +129 -0
- data/glimmer-dsl-libui.gemspec +0 -0
- data/lib/glimmer/libui/control_proxy/checkbox_proxy.rb +5 -0
- data/lib/glimmer/libui/control_proxy/color_button_proxy.rb +5 -0
- data/lib/glimmer/libui/control_proxy/combobox_proxy.rb +18 -2
- data/lib/glimmer/libui/control_proxy/date_time_picker_proxy.rb +5 -0
- data/lib/glimmer/libui/control_proxy/editable_combobox_proxy.rb +5 -0
- data/lib/glimmer/libui/control_proxy/font_button_proxy.rb +4 -0
- data/lib/glimmer/libui/control_proxy/menu_item_proxy/check_menu_item_proxy.rb +5 -0
- data/lib/glimmer/libui/control_proxy/menu_item_proxy/radio_menu_item_proxy.rb +17 -4
- data/lib/glimmer/libui/control_proxy/radio_buttons_proxy.rb +20 -0
- data/lib/glimmer/libui/control_proxy/slider_proxy.rb +38 -0
- data/lib/glimmer/libui/control_proxy/spinbox_proxy.rb +38 -0
- data/lib/glimmer/libui/control_proxy.rb +2 -2
- metadata +13 -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.8
|
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.8'
|
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`
|
@@ -620,93 +620,112 @@ Example (you may copy/paste in [`girb`](#girb-glimmer-irb)):
|
|
620
620
|
```ruby
|
621
621
|
require 'glimmer-dsl-libui'
|
622
622
|
|
623
|
-
|
624
|
-
|
625
|
-
data = [
|
626
|
-
['Lisa Sky', 'lisa@sky.com', '720-523-4329', 'Denver', 'CO', '80014'],
|
627
|
-
['Jordan Biggins', 'jordan@biggins.com', '617-528-5399', 'Boston', 'MA', '02101'],
|
628
|
-
['Mary Glass', 'mary@glass.com', '847-589-8788', 'Elk Grove Village', 'IL', '60007'],
|
629
|
-
['Darren McGrath', 'darren@mcgrath.com', '206-539-9283', 'Seattle', 'WA', '98101'],
|
630
|
-
['Melody Hanheimer', 'melody@hanheimer.com', '213-493-8274', 'Los Angeles', 'CA', '90001'],
|
631
|
-
]
|
632
|
-
|
633
|
-
window('Contacts', 600, 600) { |w|
|
634
|
-
margined true
|
623
|
+
class FormTable
|
624
|
+
include Glimmer
|
635
625
|
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
@
|
641
|
-
|
642
|
-
|
643
|
-
@
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
}
|
652
|
-
@state_entry = entry {
|
653
|
-
label 'State'
|
654
|
-
}
|
655
|
-
}
|
656
|
-
|
657
|
-
button('Save Contact') {
|
658
|
-
stretchy false
|
659
|
-
|
660
|
-
on_clicked do
|
661
|
-
new_row = [@name_entry.text, @email_entry.text, @phone_entry.text, @city_entry.text, @state_entry.text]
|
662
|
-
if new_row.include?('')
|
663
|
-
msg_box_error(w, 'Validation Error!', 'All fields are required! Please make sure to enter a value for all fields.')
|
664
|
-
else
|
665
|
-
data << new_row # automatically inserts a row into the table due to implicit data-binding
|
666
|
-
@unfiltered_data = data.dup
|
667
|
-
@name_entry.text = ''
|
668
|
-
@email_entry.text = ''
|
669
|
-
@phone_entry.text = ''
|
670
|
-
@city_entry.text = ''
|
671
|
-
@state_entry.text = ''
|
672
|
-
end
|
673
|
-
end
|
674
|
-
}
|
675
|
-
|
676
|
-
search_entry { |se|
|
677
|
-
stretchy false
|
626
|
+
attr_accessor :name, :email, :phone, :city, :state, :filter_value
|
627
|
+
|
628
|
+
def initialize
|
629
|
+
@data = [
|
630
|
+
['Lisa Sky', 'lisa@sky.com', '720-523-4329', 'Denver', 'CO', '80014'],
|
631
|
+
['Jordan Biggins', 'jordan@biggins.com', '617-528-5399', 'Boston', 'MA', '02101'],
|
632
|
+
['Mary Glass', 'mary@glass.com', '847-589-8788', 'Elk Grove Village', 'IL', '60007'],
|
633
|
+
['Darren McGrath', 'darren@mcgrath.com', '206-539-9283', 'Seattle', 'WA', '98101'],
|
634
|
+
['Melody Hanheimer', 'melody@hanheimer.com', '213-493-8274', 'Los Angeles', 'CA', '90001'],
|
635
|
+
]
|
636
|
+
end
|
637
|
+
|
638
|
+
def launch
|
639
|
+
window('Contacts', 600, 600) { |w|
|
640
|
+
margined true
|
678
641
|
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
642
|
+
vertical_box {
|
643
|
+
form {
|
644
|
+
stretchy false
|
645
|
+
|
646
|
+
entry {
|
647
|
+
label 'Name'
|
648
|
+
text <=> [self, :name]
|
649
|
+
}
|
650
|
+
|
651
|
+
entry {
|
652
|
+
label 'Email'
|
653
|
+
text <=> [self, :email]
|
654
|
+
}
|
655
|
+
|
656
|
+
entry {
|
657
|
+
label 'Phone'
|
658
|
+
text <=> [self, :phone]
|
659
|
+
}
|
660
|
+
|
661
|
+
entry {
|
662
|
+
label 'City'
|
663
|
+
text <=> [self, :city]
|
664
|
+
}
|
665
|
+
|
666
|
+
entry {
|
667
|
+
label 'State'
|
668
|
+
text <=> [self, :state]
|
669
|
+
}
|
670
|
+
}
|
671
|
+
|
672
|
+
button('Save Contact') {
|
673
|
+
stretchy false
|
674
|
+
|
675
|
+
on_clicked do
|
676
|
+
new_row = [name, email, phone, city, state]
|
677
|
+
if new_row.include?('')
|
678
|
+
msg_box_error(w, 'Validation Error!', 'All fields are required! Please make sure to enter a value for all fields.')
|
679
|
+
else
|
680
|
+
@data << new_row # automatically inserts a row into the table due to implicit data-binding
|
681
|
+
@unfiltered_data = @data.dup
|
682
|
+
self.name = '' # automatically clears name entry through explicit data-binding
|
683
|
+
self.email = ''
|
684
|
+
self.phone = ''
|
685
|
+
self.city = ''
|
686
|
+
self.state = ''
|
689
687
|
end
|
690
688
|
end
|
691
|
-
|
692
|
-
|
693
|
-
|
689
|
+
}
|
690
|
+
|
691
|
+
search_entry {
|
692
|
+
stretchy false
|
693
|
+
text <=> [self, :filter_value, # bidirectional data-binding of text to self.filter_value with after_write option
|
694
|
+
after_write: ->(filter_value) { # execute after write to self.filter_value
|
695
|
+
@unfiltered_data ||= @data.dup
|
696
|
+
# Unfilter first to remove any previous filters
|
697
|
+
@data.replace(@unfiltered_data) # affects table indirectly through implicit data-binding
|
698
|
+
# Now, apply filter if entered
|
699
|
+
unless filter_value.empty?
|
700
|
+
@data.filter! do |row_data| # affects table indirectly through implicit data-binding
|
701
|
+
row_data.any? do |cell|
|
702
|
+
cell.to_s.downcase.include?(filter_value.downcase)
|
703
|
+
end
|
704
|
+
end
|
705
|
+
end
|
706
|
+
}
|
707
|
+
]
|
708
|
+
}
|
709
|
+
|
710
|
+
table {
|
711
|
+
text_column('Name')
|
712
|
+
text_column('Email')
|
713
|
+
text_column('Phone')
|
714
|
+
text_column('City')
|
715
|
+
text_column('State')
|
694
716
|
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
717
|
+
cell_rows @data # implicit data-binding
|
718
|
+
|
719
|
+
on_changed do |row, type, row_data|
|
720
|
+
puts "Row #{row} #{type}: #{row_data}"
|
721
|
+
end
|
722
|
+
}
|
723
|
+
}
|
724
|
+
}.show
|
725
|
+
end
|
726
|
+
end
|
701
727
|
|
702
|
-
|
703
|
-
|
704
|
-
on_changed do |row, type, row_data|
|
705
|
-
puts "Row #{row} #{type}: #{row_data}"
|
706
|
-
end
|
707
|
-
}
|
708
|
-
}
|
709
|
-
}.show
|
728
|
+
FormTable.new.launch
|
710
729
|
```
|
711
730
|
|
712
731
|

|
@@ -1363,10 +1382,23 @@ Data-binding supports utilizing the [MVP (Model View Presenter)](https://en.wiki
|
|
1363
1382
|

|
1364
1383
|
|
1365
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):
|
1366
|
-
- `
|
1367
|
-
- `
|
1368
|
-
- `
|
1369
|
-
- `
|
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
|
+
- `time_picker`: `time`
|
1370
1402
|
|
1371
1403
|
Example of bidirectional data-binding:
|
1372
1404
|
|
@@ -1416,6 +1448,11 @@ To summarize the data-binding API:
|
|
1416
1448
|
|
1417
1449
|
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.
|
1418
1450
|
|
1451
|
+
Data-bound model attribute can be:
|
1452
|
+
- **Direct:** `Symbol` representing attribute reader/writer (e.g. `[person, :name`])
|
1453
|
+
- **Nested:** `String` representing nested attribute path (e.g. `[company, 'address.street']`). That results in "nested data-binding"
|
1454
|
+
- **Indexed:** `String` containing array attribute index (e.g. `[customer, 'addresses[0].street']`). That results in "indexed data-binding"
|
1455
|
+
|
1419
1456
|
Data-binding options include:
|
1420
1457
|
- `before_read {|value| ...}`: performs an operation before reading data from Model to update the View.
|
1421
1458
|
- `on_read {|value| ...}`: converts value read from Model to update the View.
|
@@ -1423,7 +1460,7 @@ Data-binding options include:
|
|
1423
1460
|
- `before_write {|value| ...}`: performs an operation before writing data to Model from View.
|
1424
1461
|
- `on_write {|value| ...}`: converts value read from View to update the Model.
|
1425
1462
|
- `after_write {|converted_value| ...}`: performs an operation after writing to Model from View.
|
1426
|
-
- `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))
|
1463
|
+
- `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".
|
1427
1464
|
|
1428
1465
|
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.
|
1429
1466
|
|
@@ -1435,7 +1472,9 @@ entry {
|
|
1435
1472
|
}
|
1436
1473
|
```
|
1437
1474
|
|
1438
|
-
|
1475
|
+
Data-binding gotchas:
|
1476
|
+
- Never data-bind a control property to an attribute on the same view object with the same exact name (e.g. binding `entry` `text` property to `self` `text` attribute) as it would conflict with it. Instead, data-bind view property to an attribute with a different name on the view object or with the same name, but on a presenter or model object (e.g. data-bind `entry` `text` to `self` `legal_text` attribute or to `contract` model `text` attribute)
|
1477
|
+
- Data-binding a property utilizes the control's listener associated with the property (e.g. `on_changed` for `entry` `text`), so you cannot hook into the listener directly anymore as that would negate data-binding. Instead, you can add an `after_write: ->(val) {}` option to perform something on trigger of the control listener instead.
|
1439
1478
|
|
1440
1479
|
Learn more from data-binding usage in [Login](#login) (4 data-binding versions), [Basic Entry](#basic-entry), [Form](#form), [Form Table](#form-table), [Method-Based Custom Keyword](#method-based-custom-keyword), [Snake](#snake) and [Tic Tac Toe](#tic_tac_toe) examples.
|
1441
1480
|
|
@@ -1853,7 +1892,7 @@ Example:
|
|
1853
1892
|
|
1854
1893
|
## Examples
|
1855
1894
|
|
1856
|
-
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.
|
1895
|
+
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.
|
1857
1896
|
|
1858
1897
|
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.
|
1859
1898
|
|
@@ -1880,17 +1919,23 @@ New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version
|
|
1880
1919
|
```ruby
|
1881
1920
|
require 'glimmer-dsl-libui'
|
1882
1921
|
require 'facets'
|
1922
|
+
require 'fileutils'
|
1883
1923
|
|
1884
1924
|
class MetaExample
|
1885
1925
|
include Glimmer
|
1886
1926
|
|
1927
|
+
ADDITIONAL_BASIC_EXAMPLES = ['Color Button', 'Font Button', 'Form', 'Date Time Picker', 'Simple Notepad']
|
1928
|
+
|
1929
|
+
attr_accessor :code_text
|
1930
|
+
|
1887
1931
|
def initialize
|
1888
|
-
@selected_example_index =
|
1932
|
+
@selected_example_index = examples_with_versions.index(basic_examples_with_versions.first)
|
1933
|
+
@code_text = File.read(file_path_for(selected_example))
|
1889
1934
|
end
|
1890
1935
|
|
1891
1936
|
def examples
|
1892
1937
|
if @examples.nil?
|
1893
|
-
example_files = Dir.glob(File.join(File.expand_path('.', __dir__), '
|
1938
|
+
example_files = Dir.glob(File.join(File.expand_path('.', __dir__), '*.rb'))
|
1894
1939
|
example_file_names = example_files.map { |f| File.basename(f, '.rb') }
|
1895
1940
|
example_file_names = example_file_names.reject { |f| f == 'meta_example' || f.match(/\d$/) }
|
1896
1941
|
@examples = example_file_names.map { |f| f.underscore.titlecase }
|
@@ -1904,12 +1949,20 @@ class MetaExample
|
|
1904
1949
|
end
|
1905
1950
|
end
|
1906
1951
|
|
1952
|
+
def basic_examples_with_versions
|
1953
|
+
examples_with_versions.select {|example| example.start_with?('Basic') || ADDITIONAL_BASIC_EXAMPLES.include?(example) }
|
1954
|
+
end
|
1955
|
+
|
1956
|
+
def advanced_examples_with_versions
|
1957
|
+
examples_with_versions - basic_examples_with_versions
|
1958
|
+
end
|
1959
|
+
|
1907
1960
|
def file_path_for(example)
|
1908
1961
|
File.join(File.expand_path('.', __dir__), "#{example.underscore}.rb")
|
1909
1962
|
end
|
1910
1963
|
|
1911
1964
|
def version_count_for(example)
|
1912
|
-
Dir.glob(File.join(File.expand_path('.', __dir__), "#{example.underscore}*.rb")).select {|file| file.match(
|
1965
|
+
Dir.glob(File.join(File.expand_path('.', __dir__), "#{example.underscore}*.rb")).select {|file| file.match(/#{example.underscore}\d\.rb$/)}.count + 1
|
1913
1966
|
end
|
1914
1967
|
|
1915
1968
|
def glimmer_dsl_libui_file
|
@@ -1945,17 +1998,47 @@ class MetaExample
|
|
1945
1998
|
vertical_box {
|
1946
1999
|
stretchy false
|
1947
2000
|
|
1948
|
-
|
2001
|
+
tab {
|
1949
2002
|
stretchy false
|
1950
|
-
items examples_with_versions
|
1951
|
-
selected @selected_example_index
|
1952
2003
|
|
1953
|
-
|
1954
|
-
|
1955
|
-
|
1956
|
-
|
1957
|
-
|
1958
|
-
|
2004
|
+
tab_item('Basic') {
|
2005
|
+
vertical_box {
|
2006
|
+
@basic_example_radio_buttons = radio_buttons {
|
2007
|
+
stretchy false
|
2008
|
+
items basic_examples_with_versions
|
2009
|
+
selected basic_examples_with_versions.index(examples_with_versions[@selected_example_index])
|
2010
|
+
|
2011
|
+
on_selected do
|
2012
|
+
@selected_example_index = examples_with_versions.index(basic_examples_with_versions[@basic_example_radio_buttons.selected])
|
2013
|
+
example = selected_example
|
2014
|
+
self.code_text = File.read(file_path_for(example))
|
2015
|
+
@version_spinbox.value = 1
|
2016
|
+
end
|
2017
|
+
}
|
2018
|
+
|
2019
|
+
label # filler
|
2020
|
+
label # filler
|
2021
|
+
}
|
2022
|
+
}
|
2023
|
+
|
2024
|
+
tab_item('Advanced') {
|
2025
|
+
vertical_box {
|
2026
|
+
@advanced_example_radio_buttons = radio_buttons {
|
2027
|
+
stretchy false
|
2028
|
+
items advanced_examples_with_versions
|
2029
|
+
|
2030
|
+
on_selected do
|
2031
|
+
@selected_example_index = examples_with_versions.index(advanced_examples_with_versions[@advanced_example_radio_buttons.selected])
|
2032
|
+
example = selected_example
|
2033
|
+
self.code_text = File.read(file_path_for(example))
|
2034
|
+
@version_spinbox.value = 1
|
2035
|
+
end
|
2036
|
+
}
|
2037
|
+
|
2038
|
+
label # filler
|
2039
|
+
label # filler
|
2040
|
+
}
|
2041
|
+
}
|
1959
2042
|
}
|
1960
2043
|
|
1961
2044
|
horizontal_box {
|
@@ -1973,7 +2056,7 @@ class MetaExample
|
|
1973
2056
|
else
|
1974
2057
|
version_number = @version_spinbox.value == 1 ? '' : @version_spinbox.value
|
1975
2058
|
example = "#{selected_example}#{version_number}"
|
1976
|
-
|
2059
|
+
self.code_text = File.read(file_path_for(example))
|
1977
2060
|
end
|
1978
2061
|
end
|
1979
2062
|
}
|
@@ -1985,9 +2068,15 @@ class MetaExample
|
|
1985
2068
|
button('Launch') {
|
1986
2069
|
on_clicked do
|
1987
2070
|
begin
|
1988
|
-
|
1989
|
-
|
1990
|
-
|
2071
|
+
parent_dir = File.join(Dir.home, '.glimmer-dsl-libui', 'examples')
|
2072
|
+
FileUtils.mkdir_p(parent_dir)
|
2073
|
+
example_file = File.join(parent_dir, "#{selected_example.underscore}.rb")
|
2074
|
+
File.write(example_file, code_text)
|
2075
|
+
example_supporting_directory = File.expand_path(selected_example.underscore, __dir__)
|
2076
|
+
FileUtils.cp_r(example_supporting_directory, parent_dir) if Dir.exist?(example_supporting_directory)
|
2077
|
+
FileUtils.cp_r(File.expand_path('../icons', __dir__), File.dirname(parent_dir))
|
2078
|
+
FileUtils.cp_r(File.expand_path('../sounds', __dir__), File.dirname(parent_dir))
|
2079
|
+
run_example(example_file)
|
1991
2080
|
rescue => e
|
1992
2081
|
puts e.full_message
|
1993
2082
|
puts 'Unable to write code changes! Running original example...'
|
@@ -1997,14 +2086,14 @@ class MetaExample
|
|
1997
2086
|
}
|
1998
2087
|
button('Reset') {
|
1999
2088
|
on_clicked do
|
2000
|
-
|
2089
|
+
self.code_text = File.read(file_path_for(selected_example))
|
2001
2090
|
end
|
2002
2091
|
}
|
2003
2092
|
}
|
2004
2093
|
}
|
2005
2094
|
|
2006
2095
|
@code_entry = non_wrapping_multiline_entry {
|
2007
|
-
text
|
2096
|
+
text <=> [self, :code_text]
|
2008
2097
|
}
|
2009
2098
|
}
|
2010
2099
|
}.show
|
@@ -2418,7 +2507,33 @@ UI.quit
|
|
2418
2507
|
|
2419
2508
|
```
|
2420
2509
|
|
2421
|
-
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
2510
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version (with [data-binding](#data-binding)):
|
2511
|
+
|
2512
|
+
```ruby
|
2513
|
+
require 'glimmer-dsl-libui'
|
2514
|
+
|
2515
|
+
class FontButton
|
2516
|
+
include Glimmer
|
2517
|
+
|
2518
|
+
attr_accessor :font_descriptor
|
2519
|
+
|
2520
|
+
def launch
|
2521
|
+
window('hello world', 300, 200) {
|
2522
|
+
font_button {
|
2523
|
+
font <=> [self, :font_descriptor, after_write: -> { p font_descriptor }]
|
2524
|
+
}
|
2525
|
+
|
2526
|
+
on_closing do
|
2527
|
+
puts 'Bye Bye'
|
2528
|
+
end
|
2529
|
+
}.show
|
2530
|
+
end
|
2531
|
+
end
|
2532
|
+
|
2533
|
+
FontButton.new.launch
|
2534
|
+
```
|
2535
|
+
|
2536
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (without [data-binding](#data-binding)):
|
2422
2537
|
|
2423
2538
|
```ruby
|
2424
2539
|
require 'glimmer-dsl-libui'
|
@@ -2459,7 +2574,33 @@ Mac | Windows | Linux
|
|
2459
2574
|
----|---------|------
|
2460
2575
|
  |   |  
|
2461
2576
|
|
2462
|
-
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
2577
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version (with [data-binding](#data-binding)):
|
2578
|
+
|
2579
|
+
```ruby
|
2580
|
+
require 'glimmer-dsl-libui'
|
2581
|
+
|
2582
|
+
class ColorButton
|
2583
|
+
include Glimmer
|
2584
|
+
|
2585
|
+
attr_accessor :selected_color
|
2586
|
+
|
2587
|
+
def initialize
|
2588
|
+
@selected_color = :blue
|
2589
|
+
end
|
2590
|
+
|
2591
|
+
def launch
|
2592
|
+
window('color button', 240) {
|
2593
|
+
color_button {
|
2594
|
+
color <=> [self, :selected_color, after_write: ->(color) {p color}]
|
2595
|
+
}
|
2596
|
+
}.show
|
2597
|
+
end
|
2598
|
+
end
|
2599
|
+
|
2600
|
+
ColorButton.new.launch
|
2601
|
+
```
|
2602
|
+
|
2603
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (without [data-binding](#data-binding)):
|
2463
2604
|
|
2464
2605
|
```ruby
|
2465
2606
|
require 'glimmer-dsl-libui'
|
@@ -2541,20 +2682,48 @@ UI.main
|
|
2541
2682
|
UI.quit
|
2542
2683
|
```
|
2543
2684
|
|
2544
|
-
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
2685
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version (with [data-binding](#data-binding)):
|
2545
2686
|
|
2546
2687
|
```ruby
|
2547
2688
|
require 'glimmer-dsl-libui'
|
2548
2689
|
|
2549
|
-
|
2550
|
-
|
2551
|
-
|
2552
|
-
|
2553
|
-
|
2554
|
-
|
2555
|
-
|
2556
|
-
|
2557
|
-
|
2690
|
+
class DateTimePicker
|
2691
|
+
include Glimmer
|
2692
|
+
|
2693
|
+
attr_accessor :picked_time
|
2694
|
+
|
2695
|
+
def launch
|
2696
|
+
window('Date Time Pickers', 300, 200) {
|
2697
|
+
vertical_box {
|
2698
|
+
date_time_picker {
|
2699
|
+
time <=> [self, :picked_time, after_write: ->(time) { p time }]
|
2700
|
+
}
|
2701
|
+
}
|
2702
|
+
|
2703
|
+
on_closing do
|
2704
|
+
puts 'Bye Bye'
|
2705
|
+
end
|
2706
|
+
}.show
|
2707
|
+
end
|
2708
|
+
end
|
2709
|
+
|
2710
|
+
DateTimePicker.new.launch
|
2711
|
+
```
|
2712
|
+
|
2713
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (without [data-binding](#data-binding)):
|
2714
|
+
|
2715
|
+
```ruby
|
2716
|
+
require 'glimmer-dsl-libui'
|
2717
|
+
|
2718
|
+
include Glimmer
|
2719
|
+
|
2720
|
+
window('Date Time Pickers', 300, 200) {
|
2721
|
+
vertical_box {
|
2722
|
+
date_time_picker { |dtp|
|
2723
|
+
on_changed do
|
2724
|
+
time = dtp.time
|
2725
|
+
p time
|
2726
|
+
end
|
2558
2727
|
}
|
2559
2728
|
}
|
2560
2729
|
|
@@ -4878,7 +5047,8 @@ class ButtonCounter
|
|
4878
5047
|
def launch
|
4879
5048
|
window('Hello, Button!') {
|
4880
5049
|
button {
|
4881
|
-
|
5050
|
+
# data-bind button text to self count, converting to string on read.
|
5051
|
+
text <= [self, :count, on_read: ->(count) {"Count: #{count}"}]
|
4882
5052
|
|
4883
5053
|
on_clicked do
|
4884
5054
|
self.count += 1
|
@@ -5751,7 +5921,96 @@ Mac | Windows | Linux
|
|
5751
5921
|
----|---------|------
|
5752
5922
|
  |   |  
|
5753
5923
|
|
5754
|
-
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
5924
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version (with [data-binding](#data-binding)):
|
5925
|
+
|
5926
|
+
```ruby
|
5927
|
+
require 'glimmer-dsl-libui'
|
5928
|
+
|
5929
|
+
class DynamicArea
|
5930
|
+
include Glimmer
|
5931
|
+
|
5932
|
+
attr_accessor :rectangle_x, :rectangle_y, :rectangle_width, :rectangle_height, :rectangle_red, :rectangle_green, :rectangle_blue, :rectangle_alpha
|
5933
|
+
|
5934
|
+
def initialize
|
5935
|
+
@rectangle_x = 25
|
5936
|
+
@rectangle_y = 25
|
5937
|
+
@rectangle_width = 150
|
5938
|
+
@rectangle_height = 150
|
5939
|
+
@rectangle_red = 102
|
5940
|
+
@rectangle_green = 102
|
5941
|
+
@rectangle_blue = 204
|
5942
|
+
@rectangle_alpha = 100
|
5943
|
+
end
|
5944
|
+
|
5945
|
+
def launch
|
5946
|
+
window('Dynamic Area', 240, 600) {
|
5947
|
+
margined true
|
5948
|
+
|
5949
|
+
vertical_box {
|
5950
|
+
label('Rectangle Properties') {
|
5951
|
+
stretchy false
|
5952
|
+
}
|
5953
|
+
|
5954
|
+
form {
|
5955
|
+
stretchy false
|
5956
|
+
|
5957
|
+
spinbox(0, 1000) {
|
5958
|
+
label 'x'
|
5959
|
+
value <=> [self, :rectangle_x, after_write: -> {@area.queue_redraw_all}]
|
5960
|
+
}
|
5961
|
+
|
5962
|
+
spinbox(0, 1000) {
|
5963
|
+
label 'y'
|
5964
|
+
value <=> [self, :rectangle_y, after_write: -> {@area.queue_redraw_all}]
|
5965
|
+
}
|
5966
|
+
|
5967
|
+
spinbox(0, 1000) {
|
5968
|
+
label 'width'
|
5969
|
+
value <=> [self, :rectangle_width, after_write: -> {@area.queue_redraw_all}]
|
5970
|
+
}
|
5971
|
+
|
5972
|
+
spinbox(0, 1000) {
|
5973
|
+
label 'height'
|
5974
|
+
value <=> [self, :rectangle_height, after_write: -> {@area.queue_redraw_all}]
|
5975
|
+
}
|
5976
|
+
|
5977
|
+
spinbox(0, 255) {
|
5978
|
+
label 'red'
|
5979
|
+
value <=> [self, :rectangle_red, after_write: -> {@area.queue_redraw_all}]
|
5980
|
+
}
|
5981
|
+
|
5982
|
+
spinbox(0, 255) {
|
5983
|
+
label 'green'
|
5984
|
+
value <=> [self, :rectangle_green, after_write: -> {@area.queue_redraw_all}]
|
5985
|
+
}
|
5986
|
+
|
5987
|
+
spinbox(0, 255) {
|
5988
|
+
label 'blue'
|
5989
|
+
value <=> [self, :rectangle_blue, after_write: -> {@area.queue_redraw_all}]
|
5990
|
+
}
|
5991
|
+
|
5992
|
+
spinbox(0, 100) {
|
5993
|
+
label 'alpha'
|
5994
|
+
value <=> [self, :rectangle_alpha, after_write: -> {@area.queue_redraw_all}]
|
5995
|
+
}
|
5996
|
+
}
|
5997
|
+
|
5998
|
+
@area = area {
|
5999
|
+
on_draw do |area_draw_params|
|
6000
|
+
rectangle(rectangle_x, rectangle_y, rectangle_width, rectangle_height) { # a dynamic path is added semi-declaratively inside on_draw block
|
6001
|
+
fill r: rectangle_red, g: rectangle_green, b: rectangle_blue, a: rectangle_alpha / 100.0
|
6002
|
+
}
|
6003
|
+
end
|
6004
|
+
}
|
6005
|
+
}
|
6006
|
+
}.show
|
6007
|
+
end
|
6008
|
+
end
|
6009
|
+
|
6010
|
+
DynamicArea.new.launch
|
6011
|
+
```
|
6012
|
+
|
6013
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (without [data-binding](#data-binding)):
|
5755
6014
|
|
5756
6015
|
```ruby
|
5757
6016
|
require 'glimmer-dsl-libui'
|
@@ -5853,7 +6112,102 @@ window('Dynamic Area', 240, 600) {
|
|
5853
6112
|
}.show
|
5854
6113
|
```
|
5855
6114
|
|
5856
|
-
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version
|
6115
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 3 (declarative stable `path` approach with [data-binding](#data-binding)):
|
6116
|
+
|
6117
|
+
```ruby
|
6118
|
+
require 'glimmer-dsl-libui'
|
6119
|
+
|
6120
|
+
class DynamicArea
|
6121
|
+
include Glimmer
|
6122
|
+
|
6123
|
+
attr_accessor :rectangle_x, :rectangle_y, :rectangle_width, :rectangle_height, :rectangle_red, :rectangle_green, :rectangle_blue, :rectangle_alpha
|
6124
|
+
|
6125
|
+
def initialize
|
6126
|
+
@rectangle_x = 25
|
6127
|
+
@rectangle_y = 25
|
6128
|
+
@rectangle_width = 150
|
6129
|
+
@rectangle_height = 150
|
6130
|
+
@rectangle_red = 102
|
6131
|
+
@rectangle_green = 102
|
6132
|
+
@rectangle_blue = 204
|
6133
|
+
@rectangle_alpha = 100
|
6134
|
+
end
|
6135
|
+
|
6136
|
+
def rectangle_fill
|
6137
|
+
{ r: rectangle_red, g: rectangle_green, b: rectangle_blue, a: rectangle_alpha / 100.0 }
|
6138
|
+
end
|
6139
|
+
|
6140
|
+
def launch
|
6141
|
+
window('Dynamic Area', 240, 600) {
|
6142
|
+
margined true
|
6143
|
+
|
6144
|
+
vertical_box {
|
6145
|
+
label('Rectangle Properties') {
|
6146
|
+
stretchy false
|
6147
|
+
}
|
6148
|
+
|
6149
|
+
form {
|
6150
|
+
stretchy false
|
6151
|
+
|
6152
|
+
@x_spinbox = spinbox(0, 1000) {
|
6153
|
+
label 'x'
|
6154
|
+
value <=> [self, :rectangle_x]
|
6155
|
+
}
|
6156
|
+
|
6157
|
+
@y_spinbox = spinbox(0, 1000) {
|
6158
|
+
label 'y'
|
6159
|
+
value <=> [self, :rectangle_y]
|
6160
|
+
}
|
6161
|
+
|
6162
|
+
@width_spinbox = spinbox(0, 1000) {
|
6163
|
+
label 'width'
|
6164
|
+
value <=> [self, :rectangle_width]
|
6165
|
+
}
|
6166
|
+
|
6167
|
+
@height_spinbox = spinbox(0, 1000) {
|
6168
|
+
label 'height'
|
6169
|
+
value <=> [self, :rectangle_height]
|
6170
|
+
}
|
6171
|
+
|
6172
|
+
@red_spinbox = spinbox(0, 255) {
|
6173
|
+
label 'red'
|
6174
|
+
value <=> [self, :rectangle_red]
|
6175
|
+
}
|
6176
|
+
|
6177
|
+
@green_spinbox = spinbox(0, 255) {
|
6178
|
+
label 'green'
|
6179
|
+
value <=> [self, :rectangle_green]
|
6180
|
+
}
|
6181
|
+
|
6182
|
+
@blue_spinbox = spinbox(0, 255) {
|
6183
|
+
label 'blue'
|
6184
|
+
value <=> [self, :rectangle_blue]
|
6185
|
+
}
|
6186
|
+
|
6187
|
+
@alpha_spinbox = spinbox(0, 100) {
|
6188
|
+
label 'alpha'
|
6189
|
+
value <=> [self, :rectangle_alpha]
|
6190
|
+
}
|
6191
|
+
}
|
6192
|
+
|
6193
|
+
area {
|
6194
|
+
@rectangle = rectangle { # stable implicit path shape
|
6195
|
+
x <= [self, :rectangle_x]
|
6196
|
+
y <= [self, :rectangle_y]
|
6197
|
+
width <= [self, :rectangle_width]
|
6198
|
+
height <= [self, :rectangle_height]
|
6199
|
+
fill <= [self, :rectangle_fill, computed_by: [:rectangle_red, :rectangle_green, :rectangle_blue, :rectangle_alpha]]
|
6200
|
+
}
|
6201
|
+
}
|
6202
|
+
}
|
6203
|
+
}.show
|
6204
|
+
end
|
6205
|
+
end
|
6206
|
+
|
6207
|
+
DynamicArea.new.launch
|
6208
|
+
```
|
6209
|
+
|
6210
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 4 (declarative stable `path` approach without [data-binding](#data-binding)):
|
5857
6211
|
|
5858
6212
|
```ruby
|
5859
6213
|
require 'glimmer-dsl-libui'
|
@@ -5945,7 +6299,7 @@ window('Dynamic Area', 240, 600) {
|
|
5945
6299
|
}
|
5946
6300
|
|
5947
6301
|
area {
|
5948
|
-
@rectangle = rectangle(@x_spinbox.value, @y_spinbox.value, @width_spinbox.value, @height_spinbox.value) { # stable path
|
6302
|
+
@rectangle = rectangle(@x_spinbox.value, @y_spinbox.value, @width_spinbox.value, @height_spinbox.value) { # stable implicit path shape
|
5949
6303
|
fill r: @red_spinbox.value, g: @green_spinbox.value, b: @blue_spinbox.value, a: @alpha_spinbox.value / 100.0
|
5950
6304
|
}
|
5951
6305
|
}
|
@@ -6643,7 +6997,121 @@ UI.main
|
|
6643
6997
|
UI.quit
|
6644
6998
|
```
|
6645
6999
|
|
6646
|
-
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
7000
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version (with [data-binding](#data-binding)):
|
7001
|
+
|
7002
|
+
```ruby
|
7003
|
+
# https://github.com/jamescook/libui-ruby/blob/master/example/histogram.rb
|
7004
|
+
|
7005
|
+
require 'glimmer-dsl-libui'
|
7006
|
+
|
7007
|
+
class Histogram
|
7008
|
+
include Glimmer
|
7009
|
+
|
7010
|
+
X_OFF_LEFT = 20
|
7011
|
+
Y_OFF_TOP = 20
|
7012
|
+
X_OFF_RIGHT = 20
|
7013
|
+
Y_OFF_BOTTOM = 20
|
7014
|
+
POINT_RADIUS = 5
|
7015
|
+
COLOR_BLUE = Glimmer::LibUI.interpret_color(0x1E90FF)
|
7016
|
+
|
7017
|
+
attr_accessor :datapoints, :histogram_color
|
7018
|
+
|
7019
|
+
def initialize
|
7020
|
+
@datapoints = 10.times.map {Random.new.rand(90)}
|
7021
|
+
@histogram_color = COLOR_BLUE
|
7022
|
+
end
|
7023
|
+
|
7024
|
+
def graph_size(area_width, area_height)
|
7025
|
+
graph_width = area_width - X_OFF_LEFT - X_OFF_RIGHT
|
7026
|
+
graph_height = area_height - Y_OFF_TOP - Y_OFF_BOTTOM
|
7027
|
+
[graph_width, graph_height]
|
7028
|
+
end
|
7029
|
+
|
7030
|
+
def point_locations(width, height)
|
7031
|
+
xincr = width / 9.0 # 10 - 1 to make the last point be at the end
|
7032
|
+
yincr = height / 100.0
|
7033
|
+
|
7034
|
+
@datapoints.each_with_index.map do |value, i|
|
7035
|
+
val = 100 - value
|
7036
|
+
[xincr * i, yincr * val]
|
7037
|
+
end
|
7038
|
+
end
|
7039
|
+
|
7040
|
+
# method-based custom control representing a graph path
|
7041
|
+
def graph_path(width, height, should_extend, &block)
|
7042
|
+
locations = point_locations(width, height).flatten
|
7043
|
+
path {
|
7044
|
+
if should_extend
|
7045
|
+
polygon(locations + [width, height, 0, height])
|
7046
|
+
else
|
7047
|
+
polyline(locations)
|
7048
|
+
end
|
7049
|
+
|
7050
|
+
# apply a transform to the coordinate space for this path so (0, 0) is the top-left corner of the graph
|
7051
|
+
transform {
|
7052
|
+
translate X_OFF_LEFT, Y_OFF_TOP
|
7053
|
+
}
|
7054
|
+
|
7055
|
+
block.call
|
7056
|
+
}
|
7057
|
+
end
|
7058
|
+
|
7059
|
+
def launch
|
7060
|
+
window('histogram example', 640, 480) {
|
7061
|
+
margined true
|
7062
|
+
|
7063
|
+
horizontal_box {
|
7064
|
+
vertical_box {
|
7065
|
+
stretchy false
|
7066
|
+
|
7067
|
+
10.times do |i|
|
7068
|
+
spinbox(0, 100) { |sb|
|
7069
|
+
stretchy false
|
7070
|
+
value <=> [self, "datapoints[#{i}]", after_write: -> { @area.queue_redraw_all }]
|
7071
|
+
}
|
7072
|
+
end
|
7073
|
+
|
7074
|
+
color_button { |cb|
|
7075
|
+
stretchy false
|
7076
|
+
color <=> [self, :histogram_color, after_write: -> { @area.queue_redraw_all }]
|
7077
|
+
}
|
7078
|
+
}
|
7079
|
+
|
7080
|
+
@area = area {
|
7081
|
+
on_draw do |area_draw_params|
|
7082
|
+
rectangle(0, 0, area_draw_params[:area_width], area_draw_params[:area_height]) {
|
7083
|
+
fill 0xFFFFFF
|
7084
|
+
}
|
7085
|
+
|
7086
|
+
graph_width, graph_height = *graph_size(area_draw_params[:area_width], area_draw_params[:area_height])
|
7087
|
+
|
7088
|
+
figure(X_OFF_LEFT, Y_OFF_TOP) {
|
7089
|
+
line(X_OFF_LEFT, Y_OFF_TOP + graph_height)
|
7090
|
+
line(X_OFF_LEFT + graph_width, Y_OFF_TOP + graph_height)
|
7091
|
+
|
7092
|
+
stroke 0x000000, thickness: 2, miter_limit: 10
|
7093
|
+
}
|
7094
|
+
|
7095
|
+
# now create the fill for the graph below the graph line
|
7096
|
+
graph_path(graph_width, graph_height, true) {
|
7097
|
+
fill @histogram_color.merge(a: 0.5)
|
7098
|
+
}
|
7099
|
+
|
7100
|
+
# now draw the histogram line
|
7101
|
+
graph_path(graph_width, graph_height, false) {
|
7102
|
+
stroke @histogram_color.merge(thickness: 2, miter_limit: 10)
|
7103
|
+
}
|
7104
|
+
end
|
7105
|
+
}
|
7106
|
+
}
|
7107
|
+
}.show
|
7108
|
+
end
|
7109
|
+
end
|
7110
|
+
|
7111
|
+
Histogram.new.launch
|
7112
|
+
```
|
7113
|
+
|
7114
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (without [data-binding](#data-binding)):
|
6647
7115
|
|
6648
7116
|
```ruby
|
6649
7117
|
# https://github.com/jamescook/libui-ruby/blob/master/example/histogram.rb
|
@@ -6657,9 +7125,10 @@ Y_OFF_TOP = 20
|
|
6657
7125
|
X_OFF_RIGHT = 20
|
6658
7126
|
Y_OFF_BOTTOM = 20
|
6659
7127
|
POINT_RADIUS = 5
|
6660
|
-
COLOR_BLUE = 0x1E90FF
|
7128
|
+
COLOR_BLUE = Glimmer::LibUI.interpret_color(0x1E90FF)
|
6661
7129
|
|
6662
7130
|
@datapoints = 10.times.map {Random.new.rand(90)}
|
7131
|
+
@color = COLOR_BLUE
|
6663
7132
|
|
6664
7133
|
def graph_size(area_width, area_height)
|
6665
7134
|
graph_width = area_width - X_OFF_LEFT - X_OFF_RIGHT
|
@@ -6715,11 +7184,12 @@ window('histogram example', 640, 480) {
|
|
6715
7184
|
}
|
6716
7185
|
end
|
6717
7186
|
|
6718
|
-
|
7187
|
+
color_button { |cb|
|
6719
7188
|
stretchy false
|
6720
7189
|
color COLOR_BLUE
|
6721
7190
|
|
6722
7191
|
on_changed do
|
7192
|
+
@color = cb.color
|
6723
7193
|
@area.queue_redraw_all
|
6724
7194
|
end
|
6725
7195
|
}
|
@@ -6727,31 +7197,27 @@ window('histogram example', 640, 480) {
|
|
6727
7197
|
|
6728
7198
|
@area = area {
|
6729
7199
|
on_draw do |area_draw_params|
|
6730
|
-
|
6731
|
-
rectangle(0, 0, area_draw_params[:area_width], area_draw_params[:area_height])
|
6732
|
-
|
7200
|
+
rectangle(0, 0, area_draw_params[:area_width], area_draw_params[:area_height]) {
|
6733
7201
|
fill 0xFFFFFF
|
6734
7202
|
}
|
6735
7203
|
|
6736
7204
|
graph_width, graph_height = *graph_size(area_draw_params[:area_width], area_draw_params[:area_height])
|
6737
7205
|
|
6738
|
-
|
6739
|
-
|
6740
|
-
|
6741
|
-
line(X_OFF_LEFT + graph_width, Y_OFF_TOP + graph_height)
|
6742
|
-
}
|
7206
|
+
figure(X_OFF_LEFT, Y_OFF_TOP) {
|
7207
|
+
line(X_OFF_LEFT, Y_OFF_TOP + graph_height)
|
7208
|
+
line(X_OFF_LEFT + graph_width, Y_OFF_TOP + graph_height)
|
6743
7209
|
|
6744
7210
|
stroke 0x000000, thickness: 2, miter_limit: 10
|
6745
7211
|
}
|
6746
7212
|
|
6747
7213
|
# now create the fill for the graph below the graph line
|
6748
7214
|
graph_path(graph_width, graph_height, true) {
|
6749
|
-
fill @
|
7215
|
+
fill @color.merge(a: 0.5)
|
6750
7216
|
}
|
6751
7217
|
|
6752
7218
|
# now draw the histogram line
|
6753
7219
|
graph_path(graph_width, graph_height, false) {
|
6754
|
-
stroke @
|
7220
|
+
stroke @color.merge(thickness: 2, miter_limit: 10)
|
6755
7221
|
}
|
6756
7222
|
end
|
6757
7223
|
}
|
@@ -7429,7 +7895,181 @@ end
|
|
7429
7895
|
TinyMidiPlayer.new
|
7430
7896
|
```
|
7431
7897
|
|
7432
|
-
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
7898
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version (with [data-binding](#data-binding)):
|
7899
|
+
|
7900
|
+
```ruby
|
7901
|
+
# frozen_string_literal: true
|
7902
|
+
|
7903
|
+
require 'glimmer-dsl-libui'
|
7904
|
+
|
7905
|
+
class TinyMidiPlayer
|
7906
|
+
include Glimmer
|
7907
|
+
|
7908
|
+
VERSION = '0.0.1'
|
7909
|
+
|
7910
|
+
attr_accessor :selected_file
|
7911
|
+
|
7912
|
+
def initialize
|
7913
|
+
@pid = nil
|
7914
|
+
@music_directory = File.expand_path('../sounds', __dir__)
|
7915
|
+
@midi_files = Dir.glob(File.join(@music_directory, '**/*.mid'))
|
7916
|
+
.sort_by { |path| File.basename(path) }
|
7917
|
+
at_exit { stop_midi }
|
7918
|
+
create_gui
|
7919
|
+
end
|
7920
|
+
|
7921
|
+
def stop_midi
|
7922
|
+
if @pid
|
7923
|
+
Process.kill(:SIGKILL, @pid) if @th.alive?
|
7924
|
+
@pid = nil
|
7925
|
+
end
|
7926
|
+
end
|
7927
|
+
|
7928
|
+
def play_midi
|
7929
|
+
stop_midi
|
7930
|
+
if @pid.nil? && @selected_file
|
7931
|
+
begin
|
7932
|
+
@pid = spawn "timidity #{@selected_file}"
|
7933
|
+
@th = Process.detach @pid
|
7934
|
+
rescue Errno::ENOENT
|
7935
|
+
warn 'Timidty++ not found. Please install Timidity++.'
|
7936
|
+
warn 'https://sourceforge.net/projects/timidity/'
|
7937
|
+
end
|
7938
|
+
end
|
7939
|
+
end
|
7940
|
+
|
7941
|
+
def show_version
|
7942
|
+
msg_box('Tiny Midi Player',
|
7943
|
+
"Written in Ruby\n" \
|
7944
|
+
"https://github.com/kojix2/libui\n" \
|
7945
|
+
"Version #{VERSION}")
|
7946
|
+
end
|
7947
|
+
|
7948
|
+
def create_gui
|
7949
|
+
menu('Help') {
|
7950
|
+
menu_item('Version') {
|
7951
|
+
on_clicked do
|
7952
|
+
show_version
|
7953
|
+
end
|
7954
|
+
}
|
7955
|
+
}
|
7956
|
+
window('Tiny Midi Player', 200, 50) {
|
7957
|
+
horizontal_box {
|
7958
|
+
vertical_box {
|
7959
|
+
stretchy false
|
7960
|
+
|
7961
|
+
button('▶') {
|
7962
|
+
on_clicked do
|
7963
|
+
play_midi
|
7964
|
+
end
|
7965
|
+
}
|
7966
|
+
button('■') {
|
7967
|
+
on_clicked do
|
7968
|
+
stop_midi
|
7969
|
+
end
|
7970
|
+
}
|
7971
|
+
}
|
7972
|
+
|
7973
|
+
combobox {
|
7974
|
+
items @midi_files.map { |path| File.basename(path) }
|
7975
|
+
# data-bind selected item (String) to self.selected_file with on-read/on-write converters and after_write operation
|
7976
|
+
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? }]
|
7977
|
+
}
|
7978
|
+
}
|
7979
|
+
}.show
|
7980
|
+
end
|
7981
|
+
end
|
7982
|
+
|
7983
|
+
TinyMidiPlayer.new
|
7984
|
+
```
|
7985
|
+
|
7986
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (with [data-binding](#data-binding)):
|
7987
|
+
|
7988
|
+
```ruby
|
7989
|
+
require 'glimmer-dsl-libui'
|
7990
|
+
|
7991
|
+
class TinyMidiPlayer
|
7992
|
+
include Glimmer
|
7993
|
+
|
7994
|
+
VERSION = '0.0.1'
|
7995
|
+
|
7996
|
+
attr_accessor :selected_file
|
7997
|
+
|
7998
|
+
def initialize
|
7999
|
+
@pid = nil
|
8000
|
+
@music_directory = File.expand_path('../sounds', __dir__)
|
8001
|
+
@midi_files = Dir.glob(File.join(@music_directory, '**/*.mid'))
|
8002
|
+
.sort_by { |path| File.basename(path) }
|
8003
|
+
at_exit { stop_midi }
|
8004
|
+
create_gui
|
8005
|
+
end
|
8006
|
+
|
8007
|
+
def stop_midi
|
8008
|
+
if @pid
|
8009
|
+
Process.kill(:SIGKILL, @pid) if @th.alive?
|
8010
|
+
@pid = nil
|
8011
|
+
end
|
8012
|
+
end
|
8013
|
+
|
8014
|
+
def play_midi
|
8015
|
+
stop_midi
|
8016
|
+
if @pid.nil? && @selected_file
|
8017
|
+
begin
|
8018
|
+
@pid = spawn "timidity #{@selected_file}"
|
8019
|
+
@th = Process.detach @pid
|
8020
|
+
rescue Errno::ENOENT
|
8021
|
+
warn 'Timidty++ not found. Please install Timidity++.'
|
8022
|
+
warn 'https://sourceforge.net/projects/timidity/'
|
8023
|
+
end
|
8024
|
+
end
|
8025
|
+
end
|
8026
|
+
|
8027
|
+
def show_version
|
8028
|
+
msg_box('Tiny Midi Player',
|
8029
|
+
"Written in Ruby\n" \
|
8030
|
+
"https://github.com/kojix2/libui\n" \
|
8031
|
+
"Version #{VERSION}")
|
8032
|
+
end
|
8033
|
+
|
8034
|
+
def create_gui
|
8035
|
+
menu('Help') {
|
8036
|
+
menu_item('Version') {
|
8037
|
+
on_clicked do
|
8038
|
+
show_version
|
8039
|
+
end
|
8040
|
+
}
|
8041
|
+
}
|
8042
|
+
window('Tiny Midi Player', 200, 50) {
|
8043
|
+
horizontal_box {
|
8044
|
+
vertical_box {
|
8045
|
+
stretchy false
|
8046
|
+
|
8047
|
+
button('▶') {
|
8048
|
+
on_clicked do
|
8049
|
+
play_midi
|
8050
|
+
end
|
8051
|
+
}
|
8052
|
+
button('■') {
|
8053
|
+
on_clicked do
|
8054
|
+
stop_midi
|
8055
|
+
end
|
8056
|
+
}
|
8057
|
+
}
|
8058
|
+
|
8059
|
+
combobox {
|
8060
|
+
items @midi_files.map { |path| File.basename(path) }
|
8061
|
+
# data-bind selected index (Integer) to self.selected_file with on-read/on-write converters and after_write operation
|
8062
|
+
selected <=> [self, :selected_file, on_read: ->(f) {@midi_files.index(f)}, on_write: ->(i) {@midi_files[i]}, after_write: -> { play_midi if @th&.alive? }]
|
8063
|
+
}
|
8064
|
+
}
|
8065
|
+
}.show
|
8066
|
+
end
|
8067
|
+
end
|
8068
|
+
|
8069
|
+
TinyMidiPlayer.new
|
8070
|
+
```
|
8071
|
+
|
8072
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 3 (without [data-binding](#data-binding)):
|
7433
8073
|
|
7434
8074
|
```ruby
|
7435
8075
|
require 'glimmer-dsl-libui'
|
@@ -7757,22 +8397,23 @@ class Tetris
|
|
7757
8397
|
menu('Game') {
|
7758
8398
|
@pause_menu_item = check_menu_item('Pause') {
|
7759
8399
|
enabled false
|
7760
|
-
|
7761
|
-
on_clicked do
|
7762
|
-
@game.paused = @pause_menu_item.checked?
|
7763
|
-
end
|
8400
|
+
checked <=> [@game, :paused]
|
7764
8401
|
}
|
8402
|
+
|
7765
8403
|
menu_item('Restart') {
|
7766
8404
|
on_clicked do
|
7767
8405
|
@game.restart!
|
7768
8406
|
end
|
7769
8407
|
}
|
8408
|
+
|
7770
8409
|
separator_menu_item
|
8410
|
+
|
7771
8411
|
menu_item('Exit') {
|
7772
8412
|
on_clicked do
|
7773
8413
|
exit(0)
|
7774
8414
|
end
|
7775
8415
|
}
|
8416
|
+
|
7776
8417
|
quit_menu_item if OS.mac?
|
7777
8418
|
}
|
7778
8419
|
|
@@ -7782,6 +8423,7 @@ class Tetris
|
|
7782
8423
|
show_high_scores
|
7783
8424
|
end
|
7784
8425
|
}
|
8426
|
+
|
7785
8427
|
menu_item('Clear High Scores') {
|
7786
8428
|
on_clicked {
|
7787
8429
|
@game.clear_high_scores!
|
@@ -7790,22 +8432,16 @@ class Tetris
|
|
7790
8432
|
}
|
7791
8433
|
|
7792
8434
|
menu('Options') {
|
7793
|
-
radio_menu_item('Instant Down on Up Arrow') {
|
7794
|
-
|
7795
|
-
@game.instant_down_on_up = true
|
7796
|
-
end
|
8435
|
+
radio_menu_item('Instant Down on Up Arrow') { |r|
|
8436
|
+
checked <=> [@game, :instant_down_on_up]
|
7797
8437
|
}
|
7798
|
-
|
7799
|
-
|
7800
|
-
|
7801
|
-
end
|
8438
|
+
|
8439
|
+
radio_menu_item('Rotate Right on Up Arrow') { |r|
|
8440
|
+
checked <=> [@game, :rotate_right_on_up]
|
7802
8441
|
}
|
7803
|
-
|
7804
|
-
|
7805
|
-
|
7806
|
-
on_clicked do
|
7807
|
-
@game.rotate_left_on_up = true
|
7808
|
-
end
|
8442
|
+
|
8443
|
+
radio_menu_item('Rotate Left on Up Arrow') { |r|
|
8444
|
+
checked <=> [@game, :rotate_left_on_up]
|
7809
8445
|
}
|
7810
8446
|
}
|
7811
8447
|
|
@@ -7817,6 +8453,7 @@ class Tetris
|
|
7817
8453
|
end
|
7818
8454
|
}
|
7819
8455
|
end
|
8456
|
+
|
7820
8457
|
menu_item('About') {
|
7821
8458
|
on_clicked do
|
7822
8459
|
show_about_dialog
|
@@ -8140,7 +8777,140 @@ Mac | Windows | Linux
|
|
8140
8777
|
----|---------|------
|
8141
8778
|
  |   |  
|
8142
8779
|
|
8143
|
-
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
8780
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version (with [data-binding](#data-binding)):
|
8781
|
+
|
8782
|
+
```ruby
|
8783
|
+
require 'glimmer-dsl-libui'
|
8784
|
+
|
8785
|
+
class Timer
|
8786
|
+
include Glimmer
|
8787
|
+
|
8788
|
+
SECOND_MAX = 59
|
8789
|
+
MINUTE_MAX = 59
|
8790
|
+
HOUR_MAX = 23
|
8791
|
+
|
8792
|
+
attr_accessor :hour, :min, :sec, :started, :played
|
8793
|
+
|
8794
|
+
def initialize
|
8795
|
+
@pid = nil
|
8796
|
+
@alarm_file = File.expand_path('../sounds/AlanWalker-Faded.mid', __dir__)
|
8797
|
+
@hour = @min = @sec = 0
|
8798
|
+
at_exit { stop_alarm }
|
8799
|
+
setup_timer
|
8800
|
+
create_gui
|
8801
|
+
end
|
8802
|
+
|
8803
|
+
def stop_alarm
|
8804
|
+
if @pid
|
8805
|
+
Process.kill(:SIGKILL, @pid) if @th.alive?
|
8806
|
+
@pid = nil
|
8807
|
+
end
|
8808
|
+
end
|
8809
|
+
|
8810
|
+
def play_alarm
|
8811
|
+
stop_alarm
|
8812
|
+
if @pid.nil?
|
8813
|
+
begin
|
8814
|
+
@pid = spawn "timidity -G 0.0-10.0 #{@alarm_file}"
|
8815
|
+
@th = Process.detach @pid
|
8816
|
+
rescue Errno::ENOENT
|
8817
|
+
warn 'Timidty++ not found. Please install Timidity++.'
|
8818
|
+
warn 'https://sourceforge.net/projects/timidity/'
|
8819
|
+
end
|
8820
|
+
end
|
8821
|
+
end
|
8822
|
+
|
8823
|
+
def setup_timer
|
8824
|
+
unless @setup_timer
|
8825
|
+
Glimmer::LibUI.timer(1) do
|
8826
|
+
if @started
|
8827
|
+
seconds = @sec
|
8828
|
+
minutes = @min
|
8829
|
+
hours = @hour
|
8830
|
+
if seconds > 0
|
8831
|
+
self.sec = seconds -= 1
|
8832
|
+
end
|
8833
|
+
if seconds == 0
|
8834
|
+
if minutes > 0
|
8835
|
+
self.min = minutes -= 1
|
8836
|
+
self.sec = seconds = SECOND_MAX
|
8837
|
+
end
|
8838
|
+
if minutes == 0
|
8839
|
+
if hours > 0
|
8840
|
+
self.hour = hours -= 1
|
8841
|
+
self.min = minutes = MINUTE_MAX
|
8842
|
+
self.sec = seconds = SECOND_MAX
|
8843
|
+
end
|
8844
|
+
if hours == 0 && minutes == 0 && seconds == 0
|
8845
|
+
self.started = false
|
8846
|
+
unless @played
|
8847
|
+
play_alarm
|
8848
|
+
msg_box('Alarm', 'Countdown Is Finished!')
|
8849
|
+
self.played = true
|
8850
|
+
end
|
8851
|
+
end
|
8852
|
+
end
|
8853
|
+
end
|
8854
|
+
end
|
8855
|
+
end
|
8856
|
+
@setup_timer = true
|
8857
|
+
end
|
8858
|
+
end
|
8859
|
+
|
8860
|
+
def create_gui
|
8861
|
+
window('Timer') {
|
8862
|
+
margined true
|
8863
|
+
|
8864
|
+
group('Countdown') {
|
8865
|
+
vertical_box {
|
8866
|
+
horizontal_box {
|
8867
|
+
spinbox(0, HOUR_MAX) {
|
8868
|
+
stretchy false
|
8869
|
+
value <=> [self, :hour]
|
8870
|
+
}
|
8871
|
+
label(':') {
|
8872
|
+
stretchy false
|
8873
|
+
}
|
8874
|
+
spinbox(0, MINUTE_MAX) {
|
8875
|
+
stretchy false
|
8876
|
+
value <=> [self, :min]
|
8877
|
+
}
|
8878
|
+
label(':') {
|
8879
|
+
stretchy false
|
8880
|
+
}
|
8881
|
+
spinbox(0, SECOND_MAX) {
|
8882
|
+
stretchy false
|
8883
|
+
value <=> [self, :sec]
|
8884
|
+
}
|
8885
|
+
}
|
8886
|
+
horizontal_box {
|
8887
|
+
button('Start') {
|
8888
|
+
enabled <= [self, :started, on_read: :!]
|
8889
|
+
|
8890
|
+
on_clicked do
|
8891
|
+
self.started = true
|
8892
|
+
self.played = false
|
8893
|
+
end
|
8894
|
+
}
|
8895
|
+
|
8896
|
+
button('Stop') {
|
8897
|
+
enabled <= [self, :started]
|
8898
|
+
|
8899
|
+
on_clicked do
|
8900
|
+
self.started = false
|
8901
|
+
end
|
8902
|
+
}
|
8903
|
+
}
|
8904
|
+
}
|
8905
|
+
}
|
8906
|
+
}.show
|
8907
|
+
end
|
8908
|
+
end
|
8909
|
+
|
8910
|
+
Timer.new
|
8911
|
+
```
|
8912
|
+
|
8913
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (without [data-binding](#data-binding)):
|
8144
8914
|
|
8145
8915
|
```ruby
|
8146
8916
|
require 'glimmer-dsl-libui'
|
@@ -8313,7 +9083,7 @@ https://github.com/iraamaro/i3off-gtk-ruby
|
|
8313
9083
|
|
8314
9084
|
### Issues
|
8315
9085
|
|
8316
|
-
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).
|
9086
|
+
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.
|
8317
9087
|
|
8318
9088
|
### Chat
|
8319
9089
|
|
@@ -8345,6 +9115,8 @@ These features have been planned or suggested. You might see them in a future ve
|
|
8345
9115
|
is fine, but please isolate to its own commit so I can cherry-pick
|
8346
9116
|
around it.
|
8347
9117
|
|
9118
|
+
Note that the latest development sometimes takes place in [development](https://github.com/AndyObtiva/glimmer-dsl-libui/tree/development) branch (which is deleted once merged back to [master](https://github.com/AndyObtiva/glimmer-dsl-libui)).
|
9119
|
+
|
8348
9120
|
## Contributors
|
8349
9121
|
|
8350
9122
|
* [Andy Maleh](https://github.com/AndyObtiva) (Founder)
|