glimmer-dsl-libui 0.11.10 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
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