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 +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +217 -5
- data/VERSION +1 -1
- data/docs/examples/GLIMMER-DSL-LIBUI-ADVANCED-EXAMPLES.md +17 -116
- data/examples/class_based_custom_control_slots.rb +150 -0
- data/glimmer-dsl-libui.gemspec +0 -0
- data/lib/glimmer/dsl/libui/custom_control_slot_content_expression.rb +44 -0
- data/lib/glimmer/dsl/libui/dsl.rb +1 -0
- data/lib/glimmer/libui/control_proxy.rb +5 -1
- data/lib/glimmer/libui/custom_control.rb +3 -2
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e5f1ed415725c882407b3aa780a19d0a1d7f21ad388e1aec0f98119e781b802c
|
4
|
+
data.tar.gz: 7f5a04c65e07437ab3cc86c82187cd5840ae265d72ecb46745f1e9cc7230cf96
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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
|
[](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.
|
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
|

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

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

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

|
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.
|
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
|
 |  | 
|
1548
1549
|
|
1549
|
-
|
1550
|
+
## Class-Based Custom Control Slots
|
1550
1551
|
|
1551
|
-
|
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
|
-
|
1554
|
+
Code: [examples/class_based_custom_control_slots.rb](/examples/class_based_custom_control_slots.rb)
|
1556
1555
|
|
1557
|
-
|
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
|
-
|
1571
|
-
|
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
|
-
|
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
|
-
|
1602
|
-
|
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
|
-
|
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
|
+

|
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
|
data/glimmer-dsl-libui.gemspec
CHANGED
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
|
@@ -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.
|
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.
|
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.
|
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
|