glimmer-dsl-libui 0.11.10 → 0.12.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9dc986b55cf3a2e7709de2312a9c1c347d46ab164f4fcb9b7d9ffb4f03f938b7
4
- data.tar.gz: 16788eb79d6c697856296ffccd60e430a2068208ee2b4f43850183eee56dc9e6
3
+ metadata.gz: e5f1ed415725c882407b3aa780a19d0a1d7f21ad388e1aec0f98119e781b802c
4
+ data.tar.gz: 7f5a04c65e07437ab3cc86c82187cd5840ae265d72ecb46745f1e9cc7230cf96
5
5
  SHA512:
6
- metadata.gz: 2ad2265f1cefe53aa1d23157c33c0e8126738943ddcd735e0d3da24fcf9afa3ae1e467b66bdae204c0e0474d926938bcf693ab9c8510495521595a994a493d05
7
- data.tar.gz: 8de4c0931c5a47d052eb4818512f6a0149a7c634c6375c79307695a3eef075eac8043d2a2eb38758f8d0fcc7c72fdac11fb19bb635ccf5cef6e592fbcd7b313a
6
+ metadata.gz: 6fe322ae6ee6772be7d8a01d24dfce89ee3c6e5296dbef1c5084c3a55b0299219dd99b33e6652ec36d49f6154422e61c21090f3bce66d74acc4c62697d9356f4
7
+ data.tar.gz: b5512ffaa585b5be77738abbe75436ad573925196180bbe40d437ae9253439de5141290bf92cb4fef4ec30880d4ed4f1c086099ff41d162e761dca6739fe5e4d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.12.0
4
+
5
+ - Custom Control Component Slots (containers that could accept content within different parts of a Custom Component)
6
+
3
7
  ## 0.11.10
4
8
 
5
9
  - Fix issue with not being able to add content to the body root of a custom control by opening a block when invoking the custom control keyword
data/README.md CHANGED
@@ -1,4 +1,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.11.10
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.12.0
2
2
  ## Prerequisite-Free Ruby Desktop Development Cross-Platform Native GUI Library ([Fukuoka Award Winning](http://www.digitalfukuoka.jp/topics/187?locale=ja))
3
3
  ### The Quickest Way From Zero To GUI
4
4
  [![Gem Version](https://badge.fury.io/rb/glimmer-dsl-libui.svg)](http://badge.fury.io/rb/glimmer-dsl-libui)
@@ -28,7 +28,7 @@ The main trade-off in using [Glimmer DSL for LibUI](https://rubygems.org/gems/gl
28
28
  - [Declarative DSL syntax](#glimmer-gui-dsl-concepts) that visually maps to the GUI control hierarchy
29
29
  - [Convention over configuration](#smart-defaults-and-conventions) via smart defaults and automation of low-level details
30
30
  - Requiring the [least amount of syntax](#glimmer-gui-dsl-concepts) possible to build GUI
31
- - [Custom Component](#custom-components) support (Custom Controls, Custom Windows, and Custom Shapes), including external Ruby gems (e.g. [Graphs and Charts](https://github.com/AndyObtiva/glimmer-libui-cc-graphs_and_charts))
31
+ - [Custom Component](#custom-components) support (Custom Controls, Custom Windows, and Custom Shapes), including [Component Slots](#class-based-custom-control-slots) and external Ruby gems (e.g. [Graphs and Charts](https://github.com/AndyObtiva/glimmer-libui-cc-graphs_and_charts))
32
32
  - [Bidirectional/Unidirectional Data-Binding](#data-binding) to declaratively wire and automatically synchronize GUI Views with Models
33
33
  - [Scaffolding](#scaffold-application) for new custom windows/controls, apps, and gems
34
34
  - [Far Future Plan] Native-Executable [packaging](#packaging) on Mac, Windows, and Linux.
@@ -456,7 +456,7 @@ gem install glimmer-dsl-libui
456
456
  Or install via Bundler `Gemfile`:
457
457
 
458
458
  ```ruby
459
- gem 'glimmer-dsl-libui', '~> 0.11.10'
459
+ gem 'glimmer-dsl-libui', '~> 0.12.0'
460
460
  ```
461
461
 
462
462
  Test that installation worked by running the [Glimmer Meta-Example](#examples):
@@ -3073,9 +3073,11 @@ Custom components like custom controls, custom windows, and custom shapes can be
3073
3073
 
3074
3074
  For example, you can define a custom `address_view` control as an aggregate of multiple `label` controls to reuse multiple times as a standard address View, displaying street, city, state, and zip code.
3075
3075
 
3076
+ Component slots are also supported, meaning containers that could accept content within different parts of a component (e.g. `address_form` can have a `header` slot and a `footer` slot to display extra information about the address being entered).
3077
+
3076
3078
  There are two ways to define custom components:
3077
3079
  - Method-Based: simply define a method representing the custom component you want (e.g. `address_view`) with any options needed (e.g. `address(address_model: some_model)`).
3078
- - Class-Based: define a class matching the camelcased name of the custom component by convention (e.g. the `address_view` custom component keyword would have a class called `AddressView`) and `include Glimmer::LibUI::CustomControl`, `include Glimmer::LibUI::CustomWindow`, or `include Glimmer::LibUI::CustomShape` depending on if the component represents a standard control, a whole window, or an [area canvas graphics shape](#area-path-shapes). Classes add the benefit of being able to distribute the custom components into a separate file for external reuse from multiple views or for sharing as a Ruby gem (e.g. [Graphs and Charts Ruby gem](https://github.com/AndyObtiva/glimmer-libui-cc-graphs_and_charts)).
3080
+ - Class-Based: define a class matching the camelcased name of the custom component by convention (e.g. the `address_view` custom component keyword would have a class called `AddressView`) and `include Glimmer::LibUI::CustomControl`, `include Glimmer::LibUI::CustomWindow`, or `include Glimmer::LibUI::CustomShape` depending on if the component represents a standard control, a whole window, or an [area canvas graphics shape](#area-path-shapes). Classes add the benefit of being able to distribute the custom components into a separate file for external reuse from multiple views or for sharing as a Ruby gem (e.g. [Graphs and Charts Ruby gem](https://github.com/AndyObtiva/glimmer-libui-cc-graphs_and_charts)). They also support Component Slots.
3079
3081
 
3080
3082
  It is OK to use the terms "custom control", "custom component", and "custom keyword" synonymously though "custom component" is a broader term that covers things other than controls too like custom shapes (e.g. `cube`), custom attributed strings (e.g. `alternating_color_string`), and custom transforms (`isometric_transform`).
3081
3083
 
@@ -3182,6 +3184,8 @@ window('Method-Based Custom Keyword') {
3182
3184
 
3183
3185
  #### Class-Based Custom Components
3184
3186
 
3187
+ ##### Class-Based Custom Controls
3188
+
3185
3189
  Define a class matching the camelcased name of the [custom control](#custom-components) by convention (e.g. the `address_view` [custom control](#custom-components) keyword would have a class called `AddressView`) and `include Glimmer::LibUI::CustomControl`. Classes add the benefit of being able to distribute the [custom control](#custom-components)s into separate files and reuse externally from multiple places or share via Ruby gems.
3186
3190
 
3187
3191
  Example (you may copy/paste in [`girb`](#girb-glimmer-irb)):
@@ -3312,6 +3316,212 @@ ClassBasedCustomControls.launch
3312
3316
 
3313
3317
  ![glimmer-dsl-libui-mac-method-based-custom-keyword.png](images/glimmer-dsl-libui-mac-method-based-custom-keyword.png)
3314
3318
 
3319
+ ##### Class-Based Custom Control Slots
3320
+
3321
+ Component can have Component Slots inside layout container controls: `vertical_box`, `horizontal_box`, `form`, and `grid`.
3322
+
3323
+ Simply pass a `slot: slot_name` option to the layout container control to designate it as a Component Slot inside a Custom Control class (in the example below, we have a `:header` slot and a `:footer` slot):
3324
+
3325
+ ```ruby
3326
+ body {
3327
+ vertical_box {
3328
+ vertical_box(slot: :header) {
3329
+ stretchy false
3330
+ }
3331
+ form {
3332
+ form_field(model: address, attribute: :street)
3333
+ form_field(model: address, attribute: :p_o_box)
3334
+ form_field(model: address, attribute: :city)
3335
+ form_field(model: address, attribute: :state)
3336
+ form_field(model: address, attribute: :zip_code)
3337
+ }
3338
+ vertical_box(slot: :footer) {
3339
+ stretchy false
3340
+ }
3341
+ }
3342
+ }
3343
+ ```
3344
+
3345
+ Next, in the Custom Control consuming code, open a block matching the name of the Component Slot (e.g. `header {}` and `footer {}`):
3346
+
3347
+ ```ruby
3348
+ address_form(address: @address) {
3349
+ header {
3350
+ label('Billing Address') {
3351
+ stretchy false
3352
+ }
3353
+ }
3354
+ footer {
3355
+ label('Billing address is used for online payments') {
3356
+ stretchy false
3357
+ }
3358
+ }
3359
+ }
3360
+ ```
3361
+
3362
+ Note that the slotted labels can include properties that apply to their Component Slot container like `stretchy false`.
3363
+
3364
+ ![glimmer-dsl-libui-mac-class-based-custom-control-slots.png](/images/glimmer-dsl-libui-mac-class-based-custom-control-slots.png)
3365
+
3366
+ Example ([Class-Based Custom Control Slots](/docs/examples/GLIMMER-DSL-LIBUI-ADVANCED-EXAMPLES.md#class-based-custom-control-slots)):
3367
+
3368
+ ```ruby
3369
+ require 'glimmer-dsl-libui'
3370
+ require 'facets'
3371
+
3372
+ Address = Struct.new(:street, :p_o_box, :city, :state, :zip_code)
3373
+
3374
+ class FormField
3375
+ include Glimmer::LibUI::CustomControl
3376
+
3377
+ options :model, :attribute
3378
+
3379
+ body {
3380
+ entry { |e|
3381
+ label attribute.to_s.underscore.split('_').map(&:capitalize).join(' ')
3382
+ text <=> [model, attribute]
3383
+ }
3384
+ }
3385
+ end
3386
+
3387
+ class AddressForm
3388
+ include Glimmer::LibUI::CustomControl
3389
+
3390
+ option :address
3391
+
3392
+ body {
3393
+ vertical_box {
3394
+ vertical_box(slot: :header) {
3395
+ stretchy false
3396
+ }
3397
+ form {
3398
+ form_field(model: address, attribute: :street)
3399
+ form_field(model: address, attribute: :p_o_box)
3400
+ form_field(model: address, attribute: :city)
3401
+ form_field(model: address, attribute: :state)
3402
+ form_field(model: address, attribute: :zip_code)
3403
+ }
3404
+ vertical_box(slot: :footer) {
3405
+ stretchy false
3406
+ }
3407
+ }
3408
+ }
3409
+ end
3410
+
3411
+ class LabelPair
3412
+ include Glimmer::LibUI::CustomControl
3413
+
3414
+ options :model, :attribute, :value
3415
+
3416
+ body {
3417
+ horizontal_box {
3418
+ label(attribute.to_s.underscore.split('_').map(&:capitalize).join(' '))
3419
+ label(value.to_s) {
3420
+ text <= [model, attribute]
3421
+ }
3422
+ }
3423
+ }
3424
+ end
3425
+
3426
+ class AddressView
3427
+ include Glimmer::LibUI::CustomControl
3428
+
3429
+ options :address
3430
+
3431
+ body {
3432
+ vertical_box {
3433
+ vertical_box(slot: :header) {
3434
+ stretchy false
3435
+ }
3436
+ address.each_pair do |attribute, value|
3437
+ label_pair(model: address, attribute: attribute, value: value)
3438
+ end
3439
+ }
3440
+ }
3441
+ end
3442
+
3443
+ class ClassBasedCustomControlSlots
3444
+ include Glimmer::LibUI::Application # alias: Glimmer::LibUI::CustomWindow
3445
+
3446
+ before_body do
3447
+ @address1 = Address.new('123 Main St', '23923', 'Denver', 'Colorado', '80014')
3448
+ @address2 = Address.new('2038 Park Ave', '83272', 'Boston', 'Massachusetts', '02101')
3449
+ end
3450
+
3451
+ body {
3452
+ window('Class-Based Custom Control Slots') {
3453
+ margined true
3454
+
3455
+ horizontal_box {
3456
+ vertical_box {
3457
+ address_form(address: @address1) {
3458
+ header {
3459
+ label('Shipping Address') {
3460
+ stretchy false
3461
+ }
3462
+ }
3463
+ footer {
3464
+ label('Shipping address is used for mailing purchases') {
3465
+ stretchy false
3466
+ }
3467
+ }
3468
+ }
3469
+
3470
+ horizontal_separator {
3471
+ stretchy false
3472
+ }
3473
+
3474
+ address_view(address: @address1) {
3475
+ header {
3476
+ label('Shipping Address (Saved)') {
3477
+ stretchy false
3478
+ }
3479
+ }
3480
+ }
3481
+ }
3482
+
3483
+ vertical_separator {
3484
+ stretchy false
3485
+ }
3486
+
3487
+ vertical_box {
3488
+ address_form(address: @address2) {
3489
+ header {
3490
+ label('Billing Address') {
3491
+ stretchy false
3492
+ }
3493
+ }
3494
+ footer {
3495
+ label('Billing address is used for online payments') {
3496
+ stretchy false
3497
+ }
3498
+ }
3499
+ }
3500
+
3501
+ horizontal_separator {
3502
+ stretchy false
3503
+ }
3504
+
3505
+ address_view(address: @address2) {
3506
+ header {
3507
+ label('Billing Address (Saved)') {
3508
+ stretchy false
3509
+ }
3510
+ }
3511
+ }
3512
+ }
3513
+ }
3514
+ }
3515
+ }
3516
+ end
3517
+
3518
+ ClassBasedCustomControlSlots.launch
3519
+ ```
3520
+
3521
+ ![glimmer-dsl-libui-mac-class-based-custom-control-slots.png](/images/glimmer-dsl-libui-mac-class-based-custom-control-slots.png)
3522
+
3523
+ ##### Class-Based Custom Shapes
3524
+
3315
3525
  Example of a `cube` custom shape (you may copy/paste in [`girb`](#girb-glimmer-irb)):
3316
3526
 
3317
3527
  ```ruby
@@ -3484,13 +3694,15 @@ BasicCustomShape.launch
3484
3694
 
3485
3695
  ![glimmer-dsl-libui-mac-basic-custom-shape.gif](/images/glimmer-dsl-libui-mac-basic-composite-shape.gif)
3486
3696
 
3697
+ ##### Class-Based Custom Windows (Applications)
3698
+
3487
3699
  You can also define Custom Window keywords, that is [custom control](#custom-components)s with `window` being the body root. These are also known as Applications. To define a Custom Window, you `include Glimmer::LibUI::CustomWindow` or `include Glimmer:LibUI::Application` and then you can invoke the `::launch` method on the class.
3488
3700
 
3489
3701
  The [`area`](#area-api) control can be utilized to build non-native custom controls from scratch by leveraging vector graphics, formattable text, keyboard events, and mouse events. This is demonstrated in the [Area-Based Custom Controls](/docs/examples/GLIMMER-DSL-LIBUI-ADVANCED-EXAMPLES.md#area-based-custom-controls) example.
3490
3702
 
3491
3703
  Defining custom controls enables unlimited extension of the [Glimmer GUI DSL](#glimmer-gui-dsl). The sky is the limit on what can be done with custom controls as a result. You can compose new visual vocabulary to build applications in any domain from higher concepts rather than [mere standard controls](#supported-keywords). For example, in a traffic signaling app, you could define `street`, `light_signal`, `traffic_sign`, and `car` as custom keywords and build your application from these concepts directly, saving enormous time and achieving much higher productivity.
3492
3704
 
3493
- Learn more from custom control usage in [Method-Based Custom Controls](/docs/examples/GLIMMER-DSL-LIBUI-ADVANCED-EXAMPLES.md#method--based-custom-controls), [Class-Based Custom Controls](/docs/examples/GLIMMER-DSL-LIBUI-ADVANCED-EXAMPLES.md#class-based-custom-controls), [Area-Based Custom Controls](/docs/examples/GLIMMER-DSL-LIBUI-ADVANCED-EXAMPLES.md#area-based-custom-controls), [Basic Composite Shape](), [Basic Custom Shape](), [Basic Scrolling Area](/docs/examples/GLIMMER-DSL-LIBUI-BASIC-EXAMPLES.md#basic-scrolling-area), [Histogram](/docs/examples/GLIMMER-DSL-LIBUI-ADVANCED-EXAMPLES.md#histogram), and [Tetris](/docs/examples/GLIMMER-DSL-LIBUI-ADVANCED-EXAMPLES.md#tetris) examples.
3705
+ Learn more from custom control usage in [Method-Based Custom Controls](/docs/examples/GLIMMER-DSL-LIBUI-ADVANCED-EXAMPLES.md#method--based-custom-controls), [Class-Based Custom Controls](/docs/examples/GLIMMER-DSL-LIBUI-ADVANCED-EXAMPLES.md#class-based-custom-controls), [Class-Based Custom Control Slots](/docs/examples/GLIMMER-DSL-LIBUI-ADVANCED-EXAMPLES.md#class-based-custom-control-slots), [Area-Based Custom Controls](/docs/examples/GLIMMER-DSL-LIBUI-ADVANCED-EXAMPLES.md#area-based-custom-controls), [Basic Composite Shape](), [Basic Custom Shape](), [Basic Scrolling Area](/docs/examples/GLIMMER-DSL-LIBUI-BASIC-EXAMPLES.md#basic-scrolling-area), [Histogram](/docs/examples/GLIMMER-DSL-LIBUI-ADVANCED-EXAMPLES.md#histogram), and [Tetris](/docs/examples/GLIMMER-DSL-LIBUI-ADVANCED-EXAMPLES.md#tetris) examples.
3494
3706
 
3495
3707
  ### Observer Pattern
3496
3708
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.11.10
1
+ 0.12.0
@@ -20,6 +20,7 @@
20
20
  - [Login](#login)
21
21
  - [Method-Based Custom Controls](#method-based-custom-controls)
22
22
  - [Class-Based Custom Controls](#class-based-custom-controls)
23
+ - [Class-Based Custom Control Slots](#class-based-custom-control-slots)
23
24
  - [Area-Based Custom Controls](#area-based-custom-controls)
24
25
  - [Midi Player](#midi-player)
25
26
  - [Snake](#snake)
@@ -1546,131 +1547,31 @@ Mac | Windows | Linux
1546
1547
  ----|---------|------
1547
1548
  ![glimmer-dsl-libui-mac-method-based-custom-keyword.png](/images/glimmer-dsl-libui-mac-method-based-custom-keyword.png) | ![glimmer-dsl-libui-windows-method-based-custom-keyword.png](/images/glimmer-dsl-libui-windows-method-based-custom-keyword.png) | ![glimmer-dsl-libui-linux-method-based-custom-keyword.png](/images/glimmer-dsl-libui-linux-method-based-custom-keyword.png)
1548
1549
 
1549
- New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version (with [data-binding](#data-binding)):
1550
+ ## Class-Based Custom Control Slots
1550
1551
 
1551
- ```ruby
1552
- require 'glimmer-dsl-libui'
1553
- require 'facets'
1552
+ Class-Based Custom Controls support slots, which enable adding content to various parts of a custom control, like a header, a footer, etc...
1554
1553
 
1555
- Address = Struct.new(:street, :p_o_box, :city, :state, :zip_code)
1554
+ Code: [examples/class_based_custom_control_slots.rb](/examples/class_based_custom_control_slots.rb)
1556
1555
 
1557
- class FormField
1558
- include Glimmer::LibUI::CustomControl
1559
-
1560
- options :model, :attribute
1561
-
1562
- body {
1563
- entry { |e|
1564
- label attribute.to_s.underscore.split('_').map(&:capitalize).join(' ')
1565
- text <=> [model, attribute]
1566
- }
1567
- }
1568
- end
1556
+ Run with `glimmer examples` command if you installed the [glimmer-dsl-libui Ruby gem](https://rubygems.org/gems/glimmer-dsl-libui):
1569
1557
 
1570
- class AddressForm
1571
- include Glimmer::LibUI::CustomControl
1572
-
1573
- options :address
1574
-
1575
- body {
1576
- form {
1577
- form_field(model: address, attribute: :street)
1578
- form_field(model: address, attribute: :p_o_box)
1579
- form_field(model: address, attribute: :city)
1580
- form_field(model: address, attribute: :state)
1581
- form_field(model: address, attribute: :zip_code)
1582
- }
1583
- }
1584
- end
1558
+ ```
1559
+ glimmer examples
1560
+ ```
1585
1561
 
1586
- class LabelPair
1587
- include Glimmer::LibUI::CustomControl
1588
-
1589
- options :model, :attribute, :value
1590
-
1591
- body {
1592
- horizontal_box {
1593
- label(attribute.to_s.underscore.split('_').map(&:capitalize).join(' '))
1594
- label(value.to_s) {
1595
- text <= [model, attribute]
1596
- }
1597
- }
1598
- }
1599
- end
1562
+ Run directly with this command if you installed the [glimmer-dsl-libui Ruby gem](https://rubygems.org/gems/glimmer-dsl-libui):
1600
1563
 
1601
- class AddressView
1602
- include Glimmer::LibUI::CustomControl
1603
-
1604
- options :address
1605
-
1606
- body {
1607
- vertical_box {
1608
- address.each_pair do |attribute, value|
1609
- label_pair(model: address, attribute: attribute, value: value)
1610
- end
1611
- }
1612
- }
1613
- end
1564
+ ```
1565
+ ruby -r glimmer-dsl-libui -e "require 'examples/class_based_custom_control_slots'"
1566
+ ```
1614
1567
 
1615
- class ClassBasedCustomControls
1616
- include Glimmer::LibUI::Application # alias: Glimmer::LibUI::CustomWindow
1617
-
1618
- before_body do
1619
- @address1 = Address.new('123 Main St', '23923', 'Denver', 'Colorado', '80014')
1620
- @address2 = Address.new('2038 Park Ave', '83272', 'Boston', 'Massachusetts', '02101')
1621
- end
1622
-
1623
- body {
1624
- window('Class-Based Custom Keyword') {
1625
- margined true
1626
-
1627
- horizontal_box {
1628
- vertical_box {
1629
- label('Address 1') {
1630
- stretchy false
1631
- }
1632
-
1633
- address_form(address: @address1)
1634
-
1635
- horizontal_separator {
1636
- stretchy false
1637
- }
1638
-
1639
- label('Address 1 (Saved)') {
1640
- stretchy false
1641
- }
1642
-
1643
- address_view(address: @address1)
1644
- }
1645
-
1646
- vertical_separator {
1647
- stretchy false
1648
- }
1649
-
1650
- vertical_box {
1651
- label('Address 2') {
1652
- stretchy false
1653
- }
1654
-
1655
- address_form(address: @address2)
1656
-
1657
- horizontal_separator {
1658
- stretchy false
1659
- }
1660
-
1661
- label('Address 2 (Saved)') {
1662
- stretchy false
1663
- }
1664
-
1665
- address_view(address: @address2)
1666
- }
1667
- }
1668
- }
1669
- }
1670
- end
1568
+ Run with this command from the root of the project if you cloned the project:
1671
1569
 
1672
- ClassBasedCustomControls.launch
1673
1570
  ```
1571
+ bin/glimmer examples/class_based_custom_control_slots.rb
1572
+ ```
1573
+
1574
+ ![glimmer-dsl-libui-mac-class-based-custom-control-slots.png](/images/glimmer-dsl-libui-mac-class-based-custom-control-slots.png)
1674
1575
 
1675
1576
  ## Area-Based Custom Controls
1676
1577
 
@@ -0,0 +1,150 @@
1
+ require 'glimmer-dsl-libui'
2
+ require 'facets'
3
+
4
+ Address = Struct.new(:street, :p_o_box, :city, :state, :zip_code)
5
+
6
+ class FormField
7
+ include Glimmer::LibUI::CustomControl
8
+
9
+ options :model, :attribute
10
+
11
+ body {
12
+ entry { |e|
13
+ label attribute.to_s.underscore.split('_').map(&:capitalize).join(' ')
14
+ text <=> [model, attribute]
15
+ }
16
+ }
17
+ end
18
+
19
+ class AddressForm
20
+ include Glimmer::LibUI::CustomControl
21
+
22
+ option :address
23
+
24
+ body {
25
+ vertical_box {
26
+ vertical_box(slot: :header) {
27
+ stretchy false
28
+ }
29
+ form {
30
+ form_field(model: address, attribute: :street)
31
+ form_field(model: address, attribute: :p_o_box)
32
+ form_field(model: address, attribute: :city)
33
+ form_field(model: address, attribute: :state)
34
+ form_field(model: address, attribute: :zip_code)
35
+ }
36
+ vertical_box(slot: :footer) {
37
+ stretchy false
38
+ }
39
+ }
40
+ }
41
+ end
42
+
43
+ class LabelPair
44
+ include Glimmer::LibUI::CustomControl
45
+
46
+ options :model, :attribute, :value
47
+
48
+ body {
49
+ horizontal_box {
50
+ label(attribute.to_s.underscore.split('_').map(&:capitalize).join(' '))
51
+ label(value.to_s) {
52
+ text <= [model, attribute]
53
+ }
54
+ }
55
+ }
56
+ end
57
+
58
+ class AddressView
59
+ include Glimmer::LibUI::CustomControl
60
+
61
+ options :address
62
+
63
+ body {
64
+ vertical_box {
65
+ vertical_box(slot: :header) {
66
+ stretchy false
67
+ }
68
+ address.each_pair do |attribute, value|
69
+ label_pair(model: address, attribute: attribute, value: value)
70
+ end
71
+ }
72
+ }
73
+ end
74
+
75
+ class ClassBasedCustomControlSlots
76
+ include Glimmer::LibUI::Application # alias: Glimmer::LibUI::CustomWindow
77
+
78
+ before_body do
79
+ @address1 = Address.new('123 Main St', '23923', 'Denver', 'Colorado', '80014')
80
+ @address2 = Address.new('2038 Park Ave', '83272', 'Boston', 'Massachusetts', '02101')
81
+ end
82
+
83
+ body {
84
+ window('Class-Based Custom Control Slots') {
85
+ margined true
86
+
87
+ horizontal_box {
88
+ vertical_box {
89
+ address_form(address: @address1) {
90
+ header {
91
+ label('Shipping Address') {
92
+ stretchy false
93
+ }
94
+ }
95
+ footer {
96
+ label('Shipping address is used for mailing purchases') {
97
+ stretchy false
98
+ }
99
+ }
100
+ }
101
+
102
+ horizontal_separator {
103
+ stretchy false
104
+ }
105
+
106
+ address_view(address: @address1) {
107
+ header {
108
+ label('Shipping Address (Saved)') {
109
+ stretchy false
110
+ }
111
+ }
112
+ }
113
+ }
114
+
115
+ vertical_separator {
116
+ stretchy false
117
+ }
118
+
119
+ vertical_box {
120
+ address_form(address: @address2) {
121
+ header {
122
+ label('Billing Address') {
123
+ stretchy false
124
+ }
125
+ }
126
+ footer {
127
+ label('Billing address is used for online payments') {
128
+ stretchy false
129
+ }
130
+ }
131
+ }
132
+
133
+ horizontal_separator {
134
+ stretchy false
135
+ }
136
+
137
+ address_view(address: @address2) {
138
+ header {
139
+ label('Billing Address (Saved)') {
140
+ stretchy false
141
+ }
142
+ }
143
+ }
144
+ }
145
+ }
146
+ }
147
+ }
148
+ end
149
+
150
+ ClassBasedCustomControlSlots.launch
Binary file
@@ -0,0 +1,44 @@
1
+ # Copyright (c) 2021-2024 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ require 'glimmer'
23
+ require 'glimmer/dsl/expression'
24
+ require 'glimmer/libui/custom_control'
25
+
26
+ module Glimmer
27
+ module DSL
28
+ module Libui
29
+ class CustomControlSlotContentExpression < Expression
30
+ def can_interpret?(parent, keyword, *args, &block)
31
+ slot = keyword.to_s.to_sym
32
+ block_given? &&
33
+ parent.is_a?(Glimmer::LibUI::CustomControl) &&
34
+ parent.slot_controls.keys.include?(slot)
35
+ end
36
+
37
+ def interpret(parent, keyword, *args, &block)
38
+ slot = keyword.to_s.to_sym
39
+ parent.slot_controls[slot]&.content(&block)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -44,6 +44,7 @@ module Glimmer
44
44
  string
45
45
  operation
46
46
  control
47
+ custom_control_slot_content
47
48
  custom_control
48
49
  shape
49
50
  custom_shape
@@ -126,14 +126,18 @@ module Glimmer
126
126
  ]
127
127
 
128
128
  # libui returns the contained LibUI object
129
- attr_reader :parent_proxy, :parent_custom_control, :libui, :args, :keyword, :block, :content_added
129
+ attr_reader :parent_proxy, :parent_custom_control, :custom_control, :libui, :args, :options, :slot, :keyword, :block, :content_added
130
130
  alias content_added? content_added
131
131
 
132
132
  def initialize(keyword, parent, args, &block)
133
133
  @keyword = keyword
134
+ @custom_control = CustomControl.custom_controls_being_interpreted.last
134
135
  @parent_custom_control = parent if parent.is_a?(CustomControl)
135
136
  @parent_proxy = parent.is_a?(CustomControl) ? parent.body_root : parent
136
137
  @args = args
138
+ @options = args.last.is_a?(Hash) ? args.pop : {}
139
+ @slot = options[:slot]
140
+ custom_control.slot_controls[@slot] = self if @slot && custom_control
137
141
  @block = block
138
142
  @enabled = true
139
143
  build_control
@@ -171,7 +171,7 @@ module Glimmer
171
171
  end_eval
172
172
  end
173
173
  end
174
-
174
+
175
175
  def before_body(&block)
176
176
  @before_body_block = block
177
177
  end
@@ -189,13 +189,14 @@ module Glimmer
189
189
  end
190
190
  end
191
191
 
192
- attr_reader :body_root, :libui, :parent, :parent_proxy, :args, :keyword, :content, :options
192
+ attr_reader :body_root, :libui, :parent, :parent_proxy, :args, :keyword, :content, :options, :slot_controls
193
193
 
194
194
  def initialize(keyword, parent, args, options, &content)
195
195
  CustomControl.custom_controls_being_interpreted << self
196
196
  @parent_proxy = @parent = parent
197
197
  options ||= {}
198
198
  @options = self.class.options.merge(options)
199
+ @slot_controls = {}
199
200
  @content = ProcTracker.new(content) if content
200
201
  execute_hook('before_body')
201
202
  body_block = self.class.instance_variable_get("@body_block")
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glimmer-dsl-libui
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.10
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Maleh
@@ -58,7 +58,7 @@ dependencies:
58
58
  requirements:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: 0.13.5
61
+ version: 1.0.0
62
62
  - - "<"
63
63
  - !ruby/object:Gem::Version
64
64
  version: 2.0.0
@@ -68,7 +68,7 @@ dependencies:
68
68
  requirements:
69
69
  - - ">="
70
70
  - !ruby/object:Gem::Version
71
- version: 0.13.5
71
+ version: 1.0.0
72
72
  - - "<"
73
73
  - !ruby/object:Gem::Version
74
74
  version: 2.0.0
@@ -423,6 +423,7 @@ files:
423
423
  - examples/basic_window.rb
424
424
  - examples/basic_window2.rb
425
425
  - examples/button_counter.rb
426
+ - examples/class_based_custom_control_slots.rb
426
427
  - examples/class_based_custom_controls.rb
427
428
  - examples/color_button.rb
428
429
  - examples/color_button2.rb
@@ -504,6 +505,7 @@ files:
504
505
  - lib/glimmer/dsl/libui/content_expression.rb
505
506
  - lib/glimmer/dsl/libui/control_expression.rb
506
507
  - lib/glimmer/dsl/libui/custom_control_expression.rb
508
+ - lib/glimmer/dsl/libui/custom_control_slot_content_expression.rb
507
509
  - lib/glimmer/dsl/libui/custom_shape_expression.rb
508
510
  - lib/glimmer/dsl/libui/data_binding_expression.rb
509
511
  - lib/glimmer/dsl/libui/dsl.rb