glimmer-dsl-libui 0.11.10 → 0.12.1

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: 9dc091cfefc95ef7b7f93457fc609a3ee852912d5c72fb79a363c9dd96787865
4
+ data.tar.gz: d6547ce1dae1fa9abb73bdcf7b441b087f0bc7ab66dd0d8eedeed724e82c810f
5
5
  SHA512:
6
- metadata.gz: 2ad2265f1cefe53aa1d23157c33c0e8126738943ddcd735e0d3da24fcf9afa3ae1e467b66bdae204c0e0474d926938bcf693ab9c8510495521595a994a493d05
7
- data.tar.gz: 8de4c0931c5a47d052eb4818512f6a0149a7c634c6375c79307695a3eef075eac8043d2a2eb38758f8d0fcc7c72fdac11fb19bb635ccf5cef6e592fbcd7b313a
6
+ metadata.gz: 352489b82a6706cbc9232f21be57a1e236efc4b08d76653b4b2fce73b0e931c6d3c7e10207f14f2f2417336f6f54bcdb03b52aa84ec55e8c9849be2bf2bfb361
7
+ data.tar.gz: 23587a71abcecc6d95bdc471b3fb907928abb028f439aaf22542fc2c19bf26916944e35770e36f1600765e04c767c0a512d5626cfbf2a0ebe007286a5516b733
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.12.1
4
+
5
+ - Fix issue with getting error "superclass mismatch for class Array" when `concurrent-ruby` is included in a desktop applications as it is required to load `concurrent-ruby` before `glimmer`, so now `glimmer-dsl-libui` will attempt loading `concurrent-ruby` if available or default to old behavior otherwise.
6
+
7
+ ## 0.12.0
8
+
9
+ - Custom Control Component Slots (containers that could accept content within different parts of a Custom Component)
10
+
3
11
  ## 0.11.10
4
12
 
5
13
  - 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.1
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.1'
460
460
  ```
461
461
 
462
462
  Test that installation worked by running the [Glimmer Meta-Example](#examples):
@@ -492,6 +492,8 @@ If you are new to [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-
492
492
 
493
493
  If you encounter any issues with the documentation, get stuck with code you do not understand, or notice some out-of-date information, you may contact the project maintainers on the [Glimmer Gitter Chat](https://app.gitter.im/#/room/#AndyObtiva_glimmer:gitter.im). Also, this could be your opportunity to be a good steward of Open-Source Software by contributing a documentation fix in a GitHub Pull Request or reporting a GitHub Issue at least.
494
494
 
495
+ For integration with a Relational Database (SQL) via ActiveRecord, you may refer to the blog post that was written about [using ActiveRecord with SQLite DB and Glimmer DSL for SWT](https://andymaleh.blogspot.com/2022/06/using-activerecord-with-sqlite-db-in.html) (altering to fit CRuby and Glimmer DSL for LibUI). Also, [@chip](https://github.com/chip) created a prototype Git repo for starting a Glimmer DSL for LibUI project with SQLite DB and ActiveRecord: https://github.com/chip/glimmer_dsl_with_active_record
496
+
495
497
  ### Experimentation Usage
496
498
 
497
499
  For experimenting and learning, add `include Glimmer` into the top-level main object and start using the Glimmer GUI DSL directly.
@@ -3073,9 +3075,11 @@ Custom components like custom controls, custom windows, and custom shapes can be
3073
3075
 
3074
3076
  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
3077
 
3078
+ 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).
3079
+
3076
3080
  There are two ways to define custom components:
3077
3081
  - 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)).
3082
+ - 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
3083
 
3080
3084
  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
3085
 
@@ -3182,6 +3186,8 @@ window('Method-Based Custom Keyword') {
3182
3186
 
3183
3187
  #### Class-Based Custom Components
3184
3188
 
3189
+ ##### Class-Based Custom Controls
3190
+
3185
3191
  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
3192
 
3187
3193
  Example (you may copy/paste in [`girb`](#girb-glimmer-irb)):
@@ -3312,6 +3318,212 @@ ClassBasedCustomControls.launch
3312
3318
 
3313
3319
  ![glimmer-dsl-libui-mac-method-based-custom-keyword.png](images/glimmer-dsl-libui-mac-method-based-custom-keyword.png)
3314
3320
 
3321
+ ##### Class-Based Custom Control Slots
3322
+
3323
+ Component can have Component Slots inside layout container controls: `vertical_box`, `horizontal_box`, `form`, and `grid`.
3324
+
3325
+ Simply designate a layout container control as a Component Slot inside a Custom Control class body block by passing it a `slot: slot_name` option (in the example below, we have a `:header` slot and a `:footer` slot):
3326
+
3327
+ ```ruby
3328
+ body {
3329
+ vertical_box {
3330
+ vertical_box(slot: :header) {
3331
+ stretchy false
3332
+ }
3333
+ form {
3334
+ form_field(model: address, attribute: :street)
3335
+ form_field(model: address, attribute: :p_o_box)
3336
+ form_field(model: address, attribute: :city)
3337
+ form_field(model: address, attribute: :state)
3338
+ form_field(model: address, attribute: :zip_code)
3339
+ }
3340
+ vertical_box(slot: :footer) {
3341
+ stretchy false
3342
+ }
3343
+ }
3344
+ }
3345
+ ```
3346
+
3347
+ Next, in the Custom Control consuming code, open a block matching the name of the Component Slot (e.g. `header {}` and `footer {}`):
3348
+
3349
+ ```ruby
3350
+ address_form(address: @address) {
3351
+ header {
3352
+ label('Billing Address') {
3353
+ stretchy false
3354
+ }
3355
+ }
3356
+ footer {
3357
+ label('Billing address is used for online payments') {
3358
+ stretchy false
3359
+ }
3360
+ }
3361
+ }
3362
+ ```
3363
+
3364
+ Note that the slotted labels can include properties that apply to their Component Slot container like `stretchy false`.
3365
+
3366
+ ![glimmer-dsl-libui-mac-class-based-custom-control-slots.png](/images/glimmer-dsl-libui-mac-class-based-custom-control-slots.png)
3367
+
3368
+ Example ([Class-Based Custom Control Slots](/docs/examples/GLIMMER-DSL-LIBUI-ADVANCED-EXAMPLES.md#class-based-custom-control-slots)):
3369
+
3370
+ ```ruby
3371
+ require 'glimmer-dsl-libui'
3372
+ require 'facets'
3373
+
3374
+ Address = Struct.new(:street, :p_o_box, :city, :state, :zip_code)
3375
+
3376
+ class FormField
3377
+ include Glimmer::LibUI::CustomControl
3378
+
3379
+ options :model, :attribute
3380
+
3381
+ body {
3382
+ entry { |e|
3383
+ label attribute.to_s.underscore.split('_').map(&:capitalize).join(' ')
3384
+ text <=> [model, attribute]
3385
+ }
3386
+ }
3387
+ end
3388
+
3389
+ class AddressForm
3390
+ include Glimmer::LibUI::CustomControl
3391
+
3392
+ option :address
3393
+
3394
+ body {
3395
+ vertical_box {
3396
+ vertical_box(slot: :header) {
3397
+ stretchy false
3398
+ }
3399
+ form {
3400
+ form_field(model: address, attribute: :street)
3401
+ form_field(model: address, attribute: :p_o_box)
3402
+ form_field(model: address, attribute: :city)
3403
+ form_field(model: address, attribute: :state)
3404
+ form_field(model: address, attribute: :zip_code)
3405
+ }
3406
+ vertical_box(slot: :footer) {
3407
+ stretchy false
3408
+ }
3409
+ }
3410
+ }
3411
+ end
3412
+
3413
+ class LabelPair
3414
+ include Glimmer::LibUI::CustomControl
3415
+
3416
+ options :model, :attribute, :value
3417
+
3418
+ body {
3419
+ horizontal_box {
3420
+ label(attribute.to_s.underscore.split('_').map(&:capitalize).join(' '))
3421
+ label(value.to_s) {
3422
+ text <= [model, attribute]
3423
+ }
3424
+ }
3425
+ }
3426
+ end
3427
+
3428
+ class AddressView
3429
+ include Glimmer::LibUI::CustomControl
3430
+
3431
+ options :address
3432
+
3433
+ body {
3434
+ vertical_box {
3435
+ vertical_box(slot: :header) {
3436
+ stretchy false
3437
+ }
3438
+ address.each_pair do |attribute, value|
3439
+ label_pair(model: address, attribute: attribute, value: value)
3440
+ end
3441
+ }
3442
+ }
3443
+ end
3444
+
3445
+ class ClassBasedCustomControlSlots
3446
+ include Glimmer::LibUI::Application # alias: Glimmer::LibUI::CustomWindow
3447
+
3448
+ before_body do
3449
+ @address1 = Address.new('123 Main St', '23923', 'Denver', 'Colorado', '80014')
3450
+ @address2 = Address.new('2038 Park Ave', '83272', 'Boston', 'Massachusetts', '02101')
3451
+ end
3452
+
3453
+ body {
3454
+ window('Class-Based Custom Control Slots') {
3455
+ margined true
3456
+
3457
+ horizontal_box {
3458
+ vertical_box {
3459
+ address_form(address: @address1) {
3460
+ header {
3461
+ label('Shipping Address') {
3462
+ stretchy false
3463
+ }
3464
+ }
3465
+ footer {
3466
+ label('Shipping address is used for mailing purchases') {
3467
+ stretchy false
3468
+ }
3469
+ }
3470
+ }
3471
+
3472
+ horizontal_separator {
3473
+ stretchy false
3474
+ }
3475
+
3476
+ address_view(address: @address1) {
3477
+ header {
3478
+ label('Shipping Address (Saved)') {
3479
+ stretchy false
3480
+ }
3481
+ }
3482
+ }
3483
+ }
3484
+
3485
+ vertical_separator {
3486
+ stretchy false
3487
+ }
3488
+
3489
+ vertical_box {
3490
+ address_form(address: @address2) {
3491
+ header {
3492
+ label('Billing Address') {
3493
+ stretchy false
3494
+ }
3495
+ }
3496
+ footer {
3497
+ label('Billing address is used for online payments') {
3498
+ stretchy false
3499
+ }
3500
+ }
3501
+ }
3502
+
3503
+ horizontal_separator {
3504
+ stretchy false
3505
+ }
3506
+
3507
+ address_view(address: @address2) {
3508
+ header {
3509
+ label('Billing Address (Saved)') {
3510
+ stretchy false
3511
+ }
3512
+ }
3513
+ }
3514
+ }
3515
+ }
3516
+ }
3517
+ }
3518
+ end
3519
+
3520
+ ClassBasedCustomControlSlots.launch
3521
+ ```
3522
+
3523
+ ![glimmer-dsl-libui-mac-class-based-custom-control-slots.png](/images/glimmer-dsl-libui-mac-class-based-custom-control-slots.png)
3524
+
3525
+ ##### Class-Based Custom Shapes
3526
+
3315
3527
  Example of a `cube` custom shape (you may copy/paste in [`girb`](#girb-glimmer-irb)):
3316
3528
 
3317
3529
  ```ruby
@@ -3484,13 +3696,15 @@ BasicCustomShape.launch
3484
3696
 
3485
3697
  ![glimmer-dsl-libui-mac-basic-custom-shape.gif](/images/glimmer-dsl-libui-mac-basic-composite-shape.gif)
3486
3698
 
3699
+ ##### Class-Based Custom Windows (Applications)
3700
+
3487
3701
  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
3702
 
3489
3703
  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
3704
 
3491
3705
  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
3706
 
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.
3707
+ 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
3708
 
3495
3709
  ### Observer Pattern
3496
3710
 
@@ -4287,6 +4501,14 @@ https://rubygems.org/gems/adamantite
4287
4501
 
4288
4502
  ![Adamantite password manager](/images/glimmer-dsl-libui-mac-application-adamantite.png)
4289
4503
 
4504
+ ### Ruby Go
4505
+
4506
+ A simple app for playing Go games with a friend, built by [Tim Standen](https://github.com/timbot1789).
4507
+
4508
+ https://github.com/timbot1789/rubygo
4509
+
4510
+ ![Ruby Go](/images/glimmer-dsl-libui-mac-application-ruby-go.png)
4511
+
4290
4512
  ## Design Principles
4291
4513
 
4292
4514
  - The Ruby Way (including TIMTOWTDI: There Is More Than One Way To Do It)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.11.10
1
+ 0.12.1
@@ -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")
@@ -21,8 +21,17 @@
21
21
 
22
22
  $LOAD_PATH.unshift(File.expand_path('..', __FILE__))
23
23
 
24
- # External requires
24
+ # concurrent-ruby gem ensures glimmer relies on Concurrent data-structure classes
25
+ # Load if available only to ensure loading at the right time before loading glimmer
26
+ begin
27
+ require 'concurrent/array'
28
+ require 'concurrent/hash'
29
+ require 'concurrent/set'
30
+ rescue LoadError
31
+ # No Op
32
+ end
25
33
  require 'glimmer'
34
+ # External requires
26
35
  # require 'logging'
27
36
  require 'puts_debuggerer' if (ENV['PD'] || ENV['pd']).to_s.downcase == 'true'
28
37
  # require 'super_module'
metadata CHANGED
@@ -1,14 +1,14 @@
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.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Maleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-06-22 00:00:00.000000000 Z
11
+ date: 2024-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: glimmer
@@ -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