glimmer-dsl-libui 0.0.26 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3a22a20e6928aba5a45b52a05d55c4b6fc8fe33ff4e39c71701e4f3675c8c118
4
- data.tar.gz: 13549e3b443fcc717a8ebee91694568a868bb7f3a6a6028f063b063d79af2e79
3
+ metadata.gz: '0938fd7cd0d762ecf27c7897a6305ec9a1d8b447917c4612c864e87486e44241'
4
+ data.tar.gz: 7387d2a5d966bbf5f2e70184013cc8056023b94375b1ec1e9941bcdac0c8da27
5
5
  SHA512:
6
- metadata.gz: ce691f8f98fcae7063245d9a8cd14b61ed64f6207236a7b111de8a35c6e84225634faaf1968218567827b06cd2f4b1b20a664c013c85b1b761bcecd6fd87e095
7
- data.tar.gz: 662d181cac9f3d86996b85d0aa8b725e99c154502867cdb8e1814dfc452956864772e31e6cac1127acf5966c29fd5aa017aea1cb4a3ad11c8331b7e42b49d756
6
+ metadata.gz: c44c83599999686358def664edf39c9f4cdcac415fd608d3668109eaba098b296cd27ce33130d8b0318904f89b406a5bddc2df808233f85c5474dc1165bbbfd2
7
+ data.tar.gz: c9d69205562886250e16359b5db53d426d4cea2d96da8bdac34c41b1488f7cd74e9e3864fa82636cd351169fab60e945f56a19f5219fc59312b4fc5d11e63770
data/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.1.1
4
+
5
+ - Support `area` listener: `on_draw`
6
+ - New examples/basic_area2.rb
7
+
8
+ ## 0.1.0
9
+
10
+ - Support examples/basic_area.rb
11
+ - Support `area` control
12
+ - Support `path(fill_mode)` control
13
+ - Support `rectangle(x, y, width, height)` figure
14
+ - Support `path` `fill` property
15
+ - Support `path` `stroke` property
16
+
17
+ ## 0.0.28
18
+
19
+ - Support automatic table row change when updating a row in `cell_rows` (e.g. `data[3] = ['new', 'row', 'cell', 'values']`)
20
+ - Support `editable` property for `checkbox_column` (checkbox editing only works in Windows due to a [libui](https://github.com/andlabs/libui) limitation)
21
+ - Support `editable`, `editable_checkbox`, and `editable_text` properties for `checkbox_text_column` (checkbox editing only works in Windows due to a [libui](https://github.com/andlabs/libui) limitation)
22
+ - Fix examples/basic_table_checkbox_text.rb by removing `editable` property
23
+
24
+ ## 0.0.27
25
+
26
+ - New examples/form_table.rb
27
+ - Support automatic table row insertion upon inserting data rows into `cell_rows`
28
+
3
29
  ## 0.0.26
4
30
 
5
31
  - New examples/basic_table_progress_bar.rb
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.0.26
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.1
2
2
  ## Prerequisite-Free Ruby Desktop Development GUI Library
3
3
  [![Gem Version](https://badge.fury.io/rb/glimmer-dsl-libui.svg)](http://badge.fury.io/rb/glimmer-dsl-libui)
4
4
  [![Maintainability](https://api.codeclimate.com/v1/badges/ce2853efdbecf6ebdc73/maintainability)](https://codeclimate.com/github/AndyObtiva/glimmer-dsl-libui/maintainability)
@@ -43,7 +43,7 @@ Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interes
43
43
 
44
44
  ## Table of Contents
45
45
 
46
- - [Glimmer DSL for LibUI 0.0.26](#-glimmer-dsl-for-libui-0026)
46
+ - [Glimmer DSL for LibUI 0.1.1](#-glimmer-dsl-for-libui-011)
47
47
  - [Glimmer GUI DSL Concepts](#glimmer-gui-dsl-concepts)
48
48
  - [Usage](#usage)
49
49
  - [API](#api)
@@ -52,6 +52,8 @@ Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interes
52
52
  - [Common Control Operations](#common-control-operations)
53
53
  - [Extra Dialogs](#extra-dialogs)
54
54
  - [Extra Operations](#extra-operations)
55
+ - [Table API](#table-api)
56
+ - [Area API](#area-api)
55
57
  - [Smart Defaults and Conventions](#smart-defaults-and-conventions)
56
58
  - [API Gotchas](#api-gotchas)
57
59
  - [Original API](#original-api)
@@ -78,6 +80,9 @@ Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interes
78
80
  - [Basic Table Checkbox](#basic-table-checkbox)
79
81
  - [Basic Table Checkbox Text](#basic-table-checkbox-text)
80
82
  - [Basic Table Progress Bar](#basic-table-progress-bar)
83
+ - [Form Table](#form-table)
84
+ - [Basic Area](#basic-area)
85
+ - [Dynamic Area](#dynamic-area)
81
86
  - [Contributing to glimmer-dsl-libui](#contributing-to-glimmer-dsl-libui)
82
87
  - [Help](#help)
83
88
  - [Issues](#issues)
@@ -165,7 +170,7 @@ gem install glimmer-dsl-libui
165
170
  Or install via Bundler `Gemfile`:
166
171
 
167
172
  ```ruby
168
- gem 'glimmer-dsl-libui', '~> 0.0.26'
173
+ gem 'glimmer-dsl-libui', '~> 0.1.1'
169
174
  ```
170
175
 
171
176
  Add `require 'glimmer-dsl-libui'` at the top, and then `include Glimmer` into the top-level main object for testing or into an actual class for serious usage.
@@ -221,11 +226,12 @@ w.libui # => #<Fiddle::Pointer:0x00007fde53997980 ptr=0x00007fde51352a60 size=0
221
226
  Control(Args) | Properties | Listeners
222
227
  ------------- | ---------- | ---------
223
228
  `about_menu_item` | None | `on_clicked`
229
+ `area` | None | `on_draw`
224
230
  `button(text as String)` | `text` (`String`) | `on_clicked`
225
231
  `button_column(name as String)` | `enabled` (Boolean) | None
226
232
  `checkbox(text as String)` | `checked` (Boolean), `text` (`String`) | `on_toggled`
227
- `checkbox_column(name as String)` | None | None
228
- `checkbox_text_column(name as String)` | `editable` (Boolean) | None
233
+ `checkbox_column(name as String)` | `editable` (Boolean) | None
234
+ `checkbox_text_column(name as String)` | `editable` (Boolean), `editable_checkbox` (Boolean), `editable_text` (Boolean) | None
229
235
  `combobox` | `items` (`Array` of `String`), `selected` (`Integer`) | `on_selected`
230
236
  `color_button` | `color` (Array of `red` as `Float`, `green` as `Float`, `blue` as `Float`, `alpha` as `Float`), `red` as `Float`, `green` as `Float`, `blue` as `Float`, `alpha` as `Float` | `on_changed`
231
237
  `date_picker` | `time` (`Hash` of keys: `sec` as `Integer`, `min` as `Integer`, `hour` as `Integer`, `mday` as `Integer`, `mon` as `Integer`, `year` as `Integer`, `wday` as `Integer`, `yday` as `Integer`, `dst` as Boolean) | `on_changed`
@@ -249,11 +255,13 @@ Control(Args) | Properties | Listeners
249
255
  `msg_box(window as Glimmer::LibUI::WindowProxy, title as String, description as String)` | None | None
250
256
  `msg_box_error(window as Glimmer::LibUI::WindowProxy, title as String, description as String)` | None | None
251
257
  `non_wrapping_multiline_entry` | `read_only` (Boolean), `text` (`String`) | `on_changed`
258
+ `path` | `fill` (`Hash` of `:r` as `0`-`255`, `:g` as `0`-`255`, `:b` as `0`-`255`, `:a` as `0.0`-`1.0`), `stroke` (`Hash` of `:r` as `0`-`255`, `:g` as `0`-`255`, `:b` as `0`-`255`, `:a` as `0.0`-`1.0`, `:cap` as `Numeric`, `:join` as `Numeric`, `:thickness` as `Numeric`, `:miter_limit` as `Numeric` ) | None
252
259
  `preferences_menu_item` | None | `on_clicked`
253
260
  `progress_bar` | `value` (`Numeric`) | None
254
261
  `progress_bar_column(name as String)` | None | None
255
262
  `quit_menu_item` | None | `on_clicked`
256
263
  `radio_buttons` | `selected` (`Integer`) | `on_selected`
264
+ `rectangle(x as Numeric, y as Numeric, width as Numeric, height as Numeric)` | None | None
257
265
  `slider(min as Numeric, max as Numeric)` | `value` (`Numeric`) | `on_changed`
258
266
  `spinbox(min as Numeric, max as Numeric)` | `value` (`Numeric`) | `on_changed`
259
267
  `tab` | `margined` (Boolean), `num_pages` (`Integer`) | None
@@ -301,6 +309,82 @@ Control(Args) | Properties | Listeners
301
309
  - `ControlProxy::main_window_proxy`: returns the first window proxy instantiated in the application
302
310
  - `ControlProxy#window_proxy`: returns the window proxy parent for a control
303
311
 
312
+ ### Table API
313
+
314
+ The `table` control must first declare its columns via one of these column keywords (mentioned in [Supported Controls](#supported-controls)):
315
+ - `button_column`: expects `String` cell values
316
+ - `checkbox_column`: expects Boolean cell values
317
+ - `checkbox_text_column`: expects dual-element `Array` of Boolean and `String` cell values
318
+ - `image_column`: expects `image` cell values (produced by `image` and `image_part` keywords as per [Supported Controls](#supported-controls))
319
+ - `image_text_column`: expects dual-element `Array` of `image` and `String` cell values
320
+ - `text_column`: expects `String` cell values
321
+ - `progress_bar_column`: expects `Integer` cell values
322
+
323
+ Afterwards, it must declare its `cell_rows` array (`Array` of `Array`s of column cell values) and whether it is `editable` (Boolean) for all its columns.
324
+
325
+ Note that the `cell_rows` property declaration results in "implicit data-binding" between the `table` control and `Array` of `Arrays` (a new innovation) to provide convenience automatic support for:
326
+ - Deleting cell rows: Calling `Array#delete`, `Array#delete_at`, `Array#delete_if`, or any filtering/deletion `Array` method automatically deletes rows in actual `table` control
327
+ - Inserting cell rows: Calling `Array#<<`, `Array#push`, `Array#prepend`, or any insertion/addition `Array` method automatically inserts rows in actual `table` control
328
+ - Changing cell rows: Calling `Array#[]=`, `Array#map!`, or any update `Array` method automatically updates rows in actual `table` control
329
+
330
+ ### Area API
331
+
332
+ The `area` control can be used in one of two ways:
333
+ - Declaratively via stable paths: useful for stable paths that will not change later on. Simply nest `path` and figures like `rectangle` and all drawing logic is generated automatically.
334
+ - Semi-declaratively via on_draw listener dynamic paths: useful for more dynamic paths that will definitely change. Open an `on_draw` listener block and nest `path(area_draw_params)` and figures like `rectangle` and all drawing logic is generated automatically.
335
+
336
+ Here is an example of a declarative `area` with a stable path (you may copy/paste in [`girb`](#girb-glimmer-irb)):
337
+
338
+ ```ruby
339
+ require 'glimmer-dsl-libui'
340
+
341
+ include Glimmer
342
+
343
+ window('Basic Area', 400, 400) {
344
+ margined true
345
+
346
+ vertical_box {
347
+ area {
348
+ path { # a stable path is added declaratively
349
+ rectangle(0, 0, 400, 400)
350
+
351
+ fill r: 102, g: 102, b: 204, a: 1.0
352
+ }
353
+ }
354
+ }
355
+ }.show
356
+ ```
357
+
358
+ ![glimmer-dsl-libui-mac-basic-area.png](images/glimmer-dsl-libui-mac-basic-area.png)
359
+
360
+ Here is the same example using a semi-declarative `area` with `on_draw` listener and a dynamic path (you may copy/paste in [`girb`](#girb-glimmer-irb)):
361
+
362
+ ```ruby
363
+ require 'glimmer-dsl-libui'
364
+
365
+ include Glimmer
366
+
367
+ window('Basic Area', 400, 400) {
368
+ margined true
369
+
370
+ vertical_box {
371
+ area {
372
+ on_draw do |area_draw_params|
373
+ path(area_draw_params) { # a dynamic path is added semi-declaratively inside on_draw block
374
+ rectangle(0, 0, 400, 400)
375
+
376
+ fill r: 102, g: 102, b: 204, a: 1.0
377
+ }
378
+ end
379
+ }
380
+ }
381
+ }.show
382
+ ```
383
+
384
+ Check [examples/dynamic_area.rb](#dynamic-area) for a more detailed semi-declarative example.
385
+
386
+ To redraw an `area`, you may call `#queue_redraw_all` method.
387
+
304
388
  ### Smart Defaults and Conventions
305
389
 
306
390
  - `horizontal_box`, `vertical_box`, `grid`, and `form` controls have `padded` as `true` upon instantiation to ensure more user-friendly GUI by default
@@ -326,13 +410,15 @@ Control(Args) | Properties | Listeners
326
410
  - Smart defaults for `grid` child attributes are `left` (`0`), `top` (`0`), `xspan` (`1`), `yspan` (`1`), `hexpand` (`false`), `halign` (`0`), `vexpand` (`false`), and `valign` (`0`)
327
411
  - The `table` control automatically constructs required `TableModelHandler`, `TableModel`, and `TableParams`, calculating all their arguments from `cell_rows` and `editable` properties (e.g. `NumRows`) as well as nested columns (e.g. `text_column`)
328
412
  - Table model instances are automatically freed from memory after `window` is destroyed.
329
- - Table `cell_rows` data has implicit data-binding to table cell values. When deleting data from `cell_rows` array, then actual rows from the `table` are automatically deleted.
413
+ - Table `cell_rows` data has implicit data-binding to table cell values for deletion, insertion, and change (done by diffing `cell_rows` value before and after change and auto-informing `table` of deletions [`LibUI.table_model_row_deleted`], insertions [`LibUI.table_model_row_deleted`], and changes [`LibUI.table_model_row_changed`]). When deleting data rows from `cell_rows` array, then actual rows from the `table` are automatically deleted. When inserting data rows into `cell_rows` array, then actual `table` rows are automatically inserted. When updating data rows in `cell_rows` array, then actual `table` rows are automatically updated.
330
414
  - `image` instances are automatically freed from memory after `window` is destroyed.
331
415
  - `image` `width` and `height` can be left off if it has one `image_part` only as they default to the same `width` and `height` of the `image_part`
416
+ - `area` paths are specified declaratively with figures underneath (e.g. `rectangle`) and `area` draw listener is automatically generated
332
417
 
333
418
  ### API Gotchas
334
419
 
335
- There is no proper way to destroy `grid` children due to [libui](https://github.com/andlabs/libui) not offering any API for deleting them from `grid` (no `grid_delete` similar to `box_delete` for `horizontal_box` and `vertical_box`)
420
+ - There is no proper way to destroy `grid` children due to [libui](https://github.com/andlabs/libui) not offering any API for deleting them from `grid` (no `grid_delete` similar to `box_delete` for `horizontal_box` and `vertical_box`).
421
+ - `table` `checkbox_column` and `checkbox_text_column` checkbox editing only works on Windows and Linux (not Mac) due to a current limitation in [libui](https://github.com/andlabs/ui/issues/357).
336
422
 
337
423
  ### Original API
338
424
 
@@ -2464,6 +2550,330 @@ window('Task progress', 300, 200) {
2464
2550
  }.show
2465
2551
  ```
2466
2552
 
2553
+ ### Form Table
2554
+
2555
+ [examples/form_table.rb](examples/form_table.rb)
2556
+
2557
+ Run with this command from the root of the project if you cloned the project:
2558
+
2559
+ ```
2560
+ ruby -r './lib/glimmer-dsl-libui' examples/form_table.rb
2561
+ ```
2562
+
2563
+ Run with this command if you installed the [Ruby gem](https://rubygems.org/gems/glimmer-dsl-libui):
2564
+
2565
+ ```
2566
+ ruby -r glimmer-dsl-libui -e "require 'examples/form_table'"
2567
+ ```
2568
+
2569
+ Mac
2570
+
2571
+ ![glimmer-dsl-libui-mac-form-table.png](images/glimmer-dsl-libui-mac-form-table.png)
2572
+ ![glimmer-dsl-libui-mac-form-table-contact-entered.png](images/glimmer-dsl-libui-mac-form-table-contact-entered.png)
2573
+
2574
+ Linux
2575
+
2576
+ ![glimmer-dsl-libui-linux-form-table.png](images/glimmer-dsl-libui-linux-form-table.png)
2577
+ ![glimmer-dsl-libui-linux-form-table-contact-entered.png](images/glimmer-dsl-libui-linux-form-table-contact-entered.png)
2578
+
2579
+ New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
2580
+
2581
+ ```ruby
2582
+ require 'glimmer-dsl-libui'
2583
+
2584
+ include Glimmer
2585
+
2586
+ data = [
2587
+ ['Lisa Sky', 'lisa@sky.com', '720-523-4329', 'Denver', 'CO', '80014'],
2588
+ ['Jordan Biggins', 'jordan@biggins.com', '617-528-5399', 'Boston', 'MA', '02101'],
2589
+ ['Mary Glass', 'mary@glass.com', '847-589-8788', 'Elk Grove Village', 'IL', '60007'],
2590
+ ['Darren McGrath', 'darren@mcgrath.com', '206-539-9283', 'Seattle', 'WA', '98101'],
2591
+ ['Melody Hanheimer', 'melody@hanheimer.com', '213-493-8274', 'Los Angeles', 'CA', '90001'],
2592
+ ]
2593
+
2594
+ window('Contacts', 600, 600) { |w|
2595
+ margined true
2596
+
2597
+ vertical_box {
2598
+ form {
2599
+ stretchy false
2600
+
2601
+ @name_entry = entry {
2602
+ label 'Name'
2603
+ }
2604
+ @email_entry = entry {
2605
+ label 'Email'
2606
+ }
2607
+ @phone_entry = entry {
2608
+ label 'Phone'
2609
+ }
2610
+ @city_entry = entry {
2611
+ label 'City'
2612
+ }
2613
+ @state_entry = entry {
2614
+ label 'State'
2615
+ }
2616
+ }
2617
+
2618
+ button('Save Contact') {
2619
+ stretchy false
2620
+
2621
+ on_clicked do
2622
+ new_row = [@name_entry.text, @email_entry.text, @phone_entry.text, @city_entry.text, @state_entry.text]
2623
+ if new_row.include?('')
2624
+ msg_box_error(w, 'Validation Error!', 'All fields are required! Please make sure to enter a value for all fields.')
2625
+ else
2626
+ data << new_row # automatically inserts a row into the table due to implicit data-binding
2627
+ @name_entry.text = ''
2628
+ @email_entry.text = ''
2629
+ @phone_entry.text = ''
2630
+ @city_entry.text = ''
2631
+ @state_entry.text = ''
2632
+ end
2633
+ end
2634
+ }
2635
+
2636
+ table {
2637
+ text_column('Name')
2638
+ text_column('Email')
2639
+ text_column('Phone')
2640
+ text_column('City')
2641
+ text_column('State')
2642
+
2643
+ cell_rows data # implicit data-binding
2644
+ }
2645
+ }
2646
+ }.show
2647
+ ```
2648
+
2649
+ ### Basic Area
2650
+
2651
+ [examples/basic_area.rb](examples/basic_area.rb)
2652
+
2653
+ Run with this command from the root of the project if you cloned the project:
2654
+
2655
+ ```
2656
+ ruby -r './lib/glimmer-dsl-libui' examples/basic_area.rb
2657
+ ```
2658
+
2659
+ Run with this command if you installed the [Ruby gem](https://rubygems.org/gems/glimmer-dsl-libui):
2660
+
2661
+ ```
2662
+ ruby -r glimmer-dsl-libui -e "require 'examples/basic_area'"
2663
+ ```
2664
+
2665
+ Mac
2666
+
2667
+ ![glimmer-dsl-libui-mac-basic-area.png](images/glimmer-dsl-libui-mac-basic-area.png)
2668
+
2669
+ Linux
2670
+
2671
+ ![glimmer-dsl-libui-linux-basic-area.png](images/glimmer-dsl-libui-linux-basic-area.png)
2672
+
2673
+ [LibUI](https://github.com/kojix2/LibUI) Original Version:
2674
+
2675
+ ```ruby
2676
+ require 'libui'
2677
+
2678
+ UI = LibUI
2679
+
2680
+ UI.init
2681
+
2682
+ handler = UI::FFI::AreaHandler.malloc
2683
+ area = UI.new_area(handler)
2684
+ brush = UI::FFI::DrawBrush.malloc
2685
+
2686
+ handler_draw_event = Fiddle::Closure::BlockCaller.new(0, [1, 1, 1]) do |_, _, area_draw_params|
2687
+ path = UI.draw_new_path(0)
2688
+ UI.draw_path_add_rectangle(path, 0, 0, 400, 400)
2689
+ UI.draw_path_end(path)
2690
+ brush.Type = 0
2691
+ brush.R = 0.4
2692
+ brush.G = 0.4
2693
+ brush.B = 0.8
2694
+ brush.A = 1.0
2695
+ area_draw_params = UI::FFI::AreaDrawParams.new(area_draw_params)
2696
+ UI.draw_fill(area_draw_params.Context, path, brush.to_ptr)
2697
+ UI.draw_free_path(path)
2698
+ end
2699
+
2700
+ handler.Draw = handler_draw_event
2701
+ handler.MouseEvent = Fiddle::Closure::BlockCaller.new(0, [0]) {}
2702
+ handler.MouseCrossed = Fiddle::Closure::BlockCaller.new(0, [0]) {}
2703
+ handler.DragBroken = Fiddle::Closure::BlockCaller.new(0, [0]) {}
2704
+ handler.KeyEvent = Fiddle::Closure::BlockCaller.new(0, [0]) {}
2705
+
2706
+ box = UI.new_vertical_box
2707
+ UI.box_set_padded(box, 1)
2708
+ UI.box_append(box, area, 1)
2709
+
2710
+ main_window = UI.new_window('Basic Area', 400, 400, 1)
2711
+ UI.window_set_margined(main_window, 1)
2712
+ UI.window_set_child(main_window, box)
2713
+
2714
+ UI.window_on_closing(main_window) do
2715
+ UI.control_destroy(main_window)
2716
+ UI.quit
2717
+ 0
2718
+ end
2719
+ UI.control_show(main_window)
2720
+
2721
+ UI.main
2722
+ UI.quit
2723
+ ```
2724
+
2725
+ [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
2726
+
2727
+ ```ruby
2728
+ require 'glimmer-dsl-libui'
2729
+
2730
+ include Glimmer
2731
+
2732
+ window('Basic Area', 400, 400) {
2733
+ margined true
2734
+
2735
+ vertical_box {
2736
+ area {
2737
+ path { # a stable path is added declaratively
2738
+ rectangle(0, 0, 400, 400)
2739
+
2740
+ fill r: 102, g: 102, b: 204, a: 1.0
2741
+ }
2742
+ }
2743
+ }
2744
+ }.show
2745
+ ```
2746
+
2747
+ ### Dynamic Area
2748
+
2749
+ [examples/dynamic_area.rb](examples/dynamic_area.rb)
2750
+
2751
+ Run with this command from the root of the project if you cloned the project:
2752
+
2753
+ ```
2754
+ ruby -r './lib/glimmer-dsl-libui' examples/dynamic_area.rb
2755
+ ```
2756
+
2757
+ Run with this command if you installed the [Ruby gem](https://rubygems.org/gems/glimmer-dsl-libui):
2758
+
2759
+ ```
2760
+ ruby -r glimmer-dsl-libui -e "require 'examples/dynamic_area'"
2761
+ ```
2762
+
2763
+ Mac
2764
+
2765
+ ![glimmer-dsl-libui-mac-dynamic-area.png](images/glimmer-dsl-libui-mac-dynamic-area.png)
2766
+ ![glimmer-dsl-libui-mac-dynamic-area-updated.png](images/glimmer-dsl-libui-mac-dynamic-area-updated.png)
2767
+
2768
+ Linux
2769
+
2770
+ ![glimmer-dsl-libui-linux-dynamic-area.png](images/glimmer-dsl-libui-linux-dynamic-area.png)
2771
+ ![glimmer-dsl-libui-linux-dynamic-area-updated.png](images/glimmer-dsl-libui-linux-dynamic-area-updated.png)
2772
+
2773
+ New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
2774
+
2775
+ ```ruby
2776
+ require 'glimmer-dsl-libui'
2777
+
2778
+ include Glimmer
2779
+
2780
+ window('Dynamic Area', 240, 500) {
2781
+ margined true
2782
+
2783
+ vertical_box {
2784
+ label('Rectangle Properties') {
2785
+ stretchy false
2786
+ }
2787
+
2788
+ form {
2789
+ stretchy false
2790
+
2791
+ @x_spinbox = spinbox(0, 1000) {
2792
+ label 'x'
2793
+ value 25
2794
+
2795
+ on_changed do
2796
+ @area.queue_redraw_all
2797
+ end
2798
+ }
2799
+
2800
+ @y_spinbox = spinbox(0, 1000) {
2801
+ label 'y'
2802
+ value 25
2803
+
2804
+ on_changed do
2805
+ @area.queue_redraw_all
2806
+ end
2807
+ }
2808
+
2809
+ @width_spinbox = spinbox(0, 1000) {
2810
+ label 'width'
2811
+ value 150
2812
+
2813
+ on_changed do
2814
+ @area.queue_redraw_all
2815
+ end
2816
+ }
2817
+
2818
+ @height_spinbox = spinbox(0, 1000) {
2819
+ label 'height'
2820
+ value 150
2821
+
2822
+ on_changed do
2823
+ @area.queue_redraw_all
2824
+ end
2825
+ }
2826
+
2827
+ @red_spinbox = spinbox(0, 255) {
2828
+ label 'red'
2829
+ value 102
2830
+
2831
+ on_changed do
2832
+ @area.queue_redraw_all
2833
+ end
2834
+ }
2835
+
2836
+ @green_spinbox = spinbox(0, 255) {
2837
+ label 'green'
2838
+ value 102
2839
+
2840
+ on_changed do
2841
+ @area.queue_redraw_all
2842
+ end
2843
+ }
2844
+
2845
+ @blue_spinbox = spinbox(0, 255) {
2846
+ label 'blue'
2847
+ value 204
2848
+
2849
+ on_changed do
2850
+ @area.queue_redraw_all
2851
+ end
2852
+ }
2853
+
2854
+ @alpha_spinbox = spinbox(0, 100) {
2855
+ label 'alpha'
2856
+ value 100
2857
+
2858
+ on_changed do
2859
+ @area.queue_redraw_all
2860
+ end
2861
+ }
2862
+ }
2863
+
2864
+ @area = area {
2865
+ on_draw do |area_draw_params|
2866
+ path(area_draw_params) { # a dynamic path is added semi-declaratively inside on_draw block
2867
+ rectangle(@x_spinbox.value, @y_spinbox.value, @width_spinbox.value, @height_spinbox.value)
2868
+
2869
+ fill r: @red_spinbox.value, g: @green_spinbox.value, b: @blue_spinbox.value, a: @alpha_spinbox.value / 100.0
2870
+ }
2871
+ end
2872
+ }
2873
+ }
2874
+ }.show
2875
+ ```
2876
+
2467
2877
  ## Contributing to glimmer-dsl-libui
2468
2878
 
2469
2879
  - Check out the latest master to make sure the feature hasn't been
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.26
1
+ 0.1.1
@@ -0,0 +1,17 @@
1
+ require 'glimmer-dsl-libui'
2
+
3
+ include Glimmer
4
+
5
+ window('Basic Area', 400, 400) {
6
+ margined true
7
+
8
+ vertical_box {
9
+ area {
10
+ path { # a stable path is added declaratively
11
+ rectangle(0, 0, 400, 400)
12
+
13
+ fill r: 102, g: 102, b: 204, a: 1.0
14
+ }
15
+ }
16
+ }
17
+ }.show
@@ -0,0 +1,19 @@
1
+ require 'glimmer-dsl-libui'
2
+
3
+ include Glimmer
4
+
5
+ window('Basic Area', 400, 400) {
6
+ margined true
7
+
8
+ vertical_box {
9
+ area {
10
+ on_draw do |area_draw_params|
11
+ path(area_draw_params) { # a dynamic path is added semi-declaratively inside on_draw block
12
+ rectangle(0, 0, 400, 400)
13
+
14
+ fill r: 102, g: 102, b: 204, a: 1.0
15
+ }
16
+ end
17
+ }
18
+ }
19
+ }.show
@@ -17,9 +17,7 @@ window('Animal sounds', 400, 200) {
17
17
  table {
18
18
  text_column('Animal')
19
19
  text_column('Sound')
20
- checkbox_text_column('Description') {
21
- editable true
22
- }
20
+ checkbox_text_column('Description')
23
21
 
24
22
  cell_rows data
25
23
  }
@@ -0,0 +1,99 @@
1
+ require 'glimmer-dsl-libui'
2
+
3
+ include Glimmer
4
+
5
+ window('Dynamic Area', 240, 600) {
6
+ margined true
7
+
8
+ vertical_box {
9
+ label('Rectangle Properties') {
10
+ stretchy false
11
+ }
12
+
13
+ form {
14
+ stretchy false
15
+
16
+ @x_spinbox = spinbox(0, 1000) {
17
+ label 'x'
18
+ value 25
19
+
20
+ on_changed do
21
+ @area.queue_redraw_all
22
+ end
23
+ }
24
+
25
+ @y_spinbox = spinbox(0, 1000) {
26
+ label 'y'
27
+ value 25
28
+
29
+ on_changed do
30
+ @area.queue_redraw_all
31
+ end
32
+ }
33
+
34
+ @width_spinbox = spinbox(0, 1000) {
35
+ label 'width'
36
+ value 150
37
+
38
+ on_changed do
39
+ @area.queue_redraw_all
40
+ end
41
+ }
42
+
43
+ @height_spinbox = spinbox(0, 1000) {
44
+ label 'height'
45
+ value 150
46
+
47
+ on_changed do
48
+ @area.queue_redraw_all
49
+ end
50
+ }
51
+
52
+ @red_spinbox = spinbox(0, 255) {
53
+ label 'red'
54
+ value 102
55
+
56
+ on_changed do
57
+ @area.queue_redraw_all
58
+ end
59
+ }
60
+
61
+ @green_spinbox = spinbox(0, 255) {
62
+ label 'green'
63
+ value 102
64
+
65
+ on_changed do
66
+ @area.queue_redraw_all
67
+ end
68
+ }
69
+
70
+ @blue_spinbox = spinbox(0, 255) {
71
+ label 'blue'
72
+ value 204
73
+
74
+ on_changed do
75
+ @area.queue_redraw_all
76
+ end
77
+ }
78
+
79
+ @alpha_spinbox = spinbox(0, 100) {
80
+ label 'alpha'
81
+ value 100
82
+
83
+ on_changed do
84
+ @area.queue_redraw_all
85
+ end
86
+ }
87
+ }
88
+
89
+ @area = area {
90
+ on_draw do |area_draw_params|
91
+ path(area_draw_params) { # a dynamic path is added semi-declaratively inside on_draw block
92
+ rectangle(@x_spinbox.value, @y_spinbox.value, @width_spinbox.value, @height_spinbox.value)
93
+
94
+ fill r: @red_spinbox.value, g: @green_spinbox.value, b: @blue_spinbox.value, a: @alpha_spinbox.value / 100.0
95
+ }
96
+ end
97
+ }
98
+ }
99
+ }.show
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'glimmer-dsl-libui'
4
+
5
+ include Glimmer
6
+
7
+ data = [
8
+ ['Lisa Sky', 'lisa@sky.com', '720-523-4329', 'Denver', 'CO', '80014'],
9
+ ['Jordan Biggins', 'jordan@biggins.com', '617-528-5399', 'Boston', 'MA', '02101'],
10
+ ['Mary Glass', 'mary@glass.com', '847-589-8788', 'Elk Grove Village', 'IL', '60007'],
11
+ ['Darren McGrath', 'darren@mcgrath.com', '206-539-9283', 'Seattle', 'WA', '98101'],
12
+ ['Melody Hanheimer', 'melody@hanheimer.com', '213-493-8274', 'Los Angeles', 'CA', '90001'],
13
+ ]
14
+
15
+ window('Contacts', 600, 600) { |w|
16
+ margined true
17
+
18
+ vertical_box {
19
+ form {
20
+ stretchy false
21
+
22
+ @name_entry = entry {
23
+ label 'Name'
24
+ }
25
+ @email_entry = entry {
26
+ label 'Email'
27
+ }
28
+ @phone_entry = entry {
29
+ label 'Phone'
30
+ }
31
+ @city_entry = entry {
32
+ label 'City'
33
+ }
34
+ @state_entry = entry {
35
+ label 'State'
36
+ }
37
+ }
38
+
39
+ button('Save Contact') {
40
+ stretchy false
41
+
42
+ on_clicked do
43
+ new_row = [@name_entry.text, @email_entry.text, @phone_entry.text, @city_entry.text, @state_entry.text]
44
+ if new_row.include?('')
45
+ msg_box_error(w, 'Validation Error!', 'All fields are required! Please make sure to enter a value for all fields.')
46
+ else
47
+ data << new_row # automatically inserts a row into the table due to implicit data-binding
48
+ @name_entry.text = ''
49
+ @email_entry.text = ''
50
+ @phone_entry.text = ''
51
+ @city_entry.text = ''
52
+ @state_entry.text = ''
53
+ end
54
+ end
55
+ }
56
+
57
+ table {
58
+ text_column('Name')
59
+ text_column('Email')
60
+ text_column('Phone')
61
+ text_column('City')
62
+ text_column('State')
63
+
64
+ cell_rows data # implicit data-binding
65
+ }
66
+ }
67
+ }.show
Binary file
@@ -0,0 +1,33 @@
1
+ # Copyright (c) 2021 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
+ module Glimmer
23
+ module FiddleConsumer
24
+ # Protects Fiddle::Closure::BlockCaller objects from garbage collection.
25
+ def fiddle_closure_block_caller(*args, &block)
26
+ @blockcaller ||= []
27
+ args << [0] if args.size == 1 # Argument types are ommited
28
+ blockcaller = ::Fiddle::Closure::BlockCaller.new(*args, &block)
29
+ @blockcaller << blockcaller
30
+ blockcaller
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,105 @@
1
+ # Copyright (c) 2021 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/libui/control_proxy'
23
+ require 'glimmer/fiddle_consumer'
24
+
25
+ module Glimmer
26
+ module LibUI
27
+ # Proxy for LibUI area objects
28
+ #
29
+ # Follows the Proxy Design Pattern
30
+ class AreaProxy < ControlProxy
31
+ include Glimmer::FiddleConsumer
32
+
33
+ attr_reader :area_handler
34
+
35
+ def post_initialize_child(child)
36
+ super
37
+ children << child
38
+ end
39
+
40
+ def post_add_content
41
+ super
42
+ install_listeners
43
+ end
44
+
45
+ def children
46
+ @children ||= []
47
+ end
48
+
49
+ def on_draw(&block)
50
+ @on_draw_procs ||= []
51
+ if block.nil?
52
+ @on_draw_procs
53
+ else
54
+ @on_draw_procs << block
55
+ block
56
+ end
57
+ end
58
+
59
+ def can_handle_listener?(listener_name)
60
+ listener_name == 'on_draw' || super
61
+ end
62
+
63
+ def handle_listener(listener_name, &listener)
64
+ case listener_name
65
+ when 'on_draw'
66
+ on_draw(&listener)
67
+ else
68
+ super
69
+ end
70
+ end
71
+
72
+ private
73
+
74
+ def build_control
75
+ @area_handler = ::LibUI::FFI::AreaHandler.malloc
76
+ @libui = ::LibUI.new_area(@area_handler)
77
+ end
78
+
79
+ def install_listeners
80
+ @area_handler.Draw = fiddle_closure_block_caller(0, [1, 1, 1]) do |_, _, area_draw_params|
81
+ area_draw_params = ::LibUI::FFI::AreaDrawParams.new(area_draw_params)
82
+ area_draw_params = area_draw_params_hash(area_draw_params)
83
+ children.each {|child| child.draw(area_draw_params)}
84
+ on_draw.each {|listener| listener.call(area_draw_params) }
85
+ end
86
+ @area_handler.MouseEvent = fiddle_closure_block_caller(0, [0]) {}
87
+ @area_handler.MouseCrossed = fiddle_closure_block_caller(0, [0]) {}
88
+ @area_handler.DragBroken = fiddle_closure_block_caller(0, [0]) {}
89
+ @area_handler.KeyEvent = fiddle_closure_block_caller(0, [0]) {}
90
+ end
91
+
92
+ def area_draw_params_hash(area_draw_params)
93
+ {
94
+ context: area_draw_params.Context,
95
+ area_width: area_draw_params.AreaWidth,
96
+ area_height: area_draw_params.AreaHeight,
97
+ clip_x: area_draw_params.ClipX,
98
+ clip_y: area_draw_params.ClipY,
99
+ clip_width: area_draw_params.ClipWidth,
100
+ clip_height: area_draw_params.ClipHeight,
101
+ }
102
+ end
103
+ end
104
+ end
105
+ end
@@ -35,7 +35,12 @@ module Glimmer
35
35
  def on_clicked(&block)
36
36
  # TODO consider generalizing into custom listeners and moving to ControlProxy
37
37
  @on_clicked_procs ||= []
38
- @on_clicked_procs << block
38
+ if block.nil?
39
+ @on_clicked_procs
40
+ else
41
+ @on_clicked_procs << block
42
+ block
43
+ end
39
44
  end
40
45
 
41
46
  def can_handle_listener?(listener_name)
@@ -30,12 +30,12 @@ module Glimmer
30
30
  # Follows the Proxy Design Pattern
31
31
  class CheckboxColumnProxy < ControlProxy
32
32
  include Column
33
- # include EditableColumn # TODO enable this once checkbox column becomes editable on macosx in C libui (currently has a bug)
33
+ include EditableColumn
34
34
 
35
35
  private
36
36
 
37
37
  def build_control
38
- @parent_proxy.append_checkbox_column(name, column_index, -1)
38
+ @parent_proxy.append_checkbox_column(name, column_index, editable_value)
39
39
  end
40
40
  end
41
41
  end
@@ -32,12 +32,44 @@ module Glimmer
32
32
  class CheckboxTextColumnProxy < ControlProxy
33
33
  include Column
34
34
  include DualColumn
35
- include EditableColumn # TODO split into editable_checkbox and editable_text properties in the future given that checkbox and text can be edited separately
35
+ include EditableColumn
36
36
 
37
+ def editable_checkbox(value = nil)
38
+ if value.nil?
39
+ @editable_checkbox = false if @editable_checkbox.nil?
40
+ @editable_checkbox
41
+ else
42
+ @editable_checkbox = !!value
43
+ end
44
+ end
45
+ alias editable_checkbox= editable_checkbox
46
+ alias set_editable_checkbox editable_checkbox
47
+ alias editable_checkbox? editable_checkbox
48
+
49
+ def editable_text(value = nil)
50
+ if value.nil?
51
+ @editable_text = false if @editable_text.nil?
52
+ @editable_text
53
+ else
54
+ @editable_text = !!value
55
+ end
56
+ end
57
+ alias editable_text= editable_text
58
+ alias set_editable_text editable_text
59
+ alias editable_text? editable_text
60
+
37
61
  private
38
62
 
39
63
  def build_control
40
- @parent_proxy.append_checkbox_text_column(name, column_index, -1, second_column_index, editable_value)
64
+ @parent_proxy.append_checkbox_text_column(name, column_index, editable_checkbox_value, second_column_index, editable_text_value)
65
+ end
66
+
67
+ def editable_checkbox_value
68
+ (@parent_proxy.editable? || editable? || editable_checkbox?) ? -2 : -1
69
+ end
70
+
71
+ def editable_text_value
72
+ (@parent_proxy.editable? || editable? || editable_text?) ? -2 : -1
41
73
  end
42
74
  end
43
75
  end
@@ -0,0 +1,149 @@
1
+ # Copyright (c) 2021 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/libui/control_proxy'
23
+
24
+ module Glimmer
25
+ module LibUI
26
+ # Proxy for LibUI path objects
27
+ #
28
+ # Follows the Proxy Design Pattern
29
+ class PathProxy < ControlProxy
30
+ # TODO support mode without parent proxy
31
+ def initialize(keyword, parent, args, &block)
32
+ @keyword = keyword
33
+ @parent_proxy = parent
34
+ @args = args
35
+ @block = block
36
+ @enabled = true
37
+ post_add_content if @block.nil?
38
+ end
39
+
40
+ def post_initialize_child(child)
41
+ super
42
+ children << child
43
+ end
44
+
45
+ def post_add_content
46
+ super
47
+ draw(area_draw_params) if @parent_proxy.nil?
48
+ end
49
+
50
+ def children
51
+ @children ||= []
52
+ end
53
+
54
+ def draw(area_draw_params)
55
+ build_control
56
+ children.each {|child| child.draw(area_draw_params)}
57
+ ::LibUI.draw_path_end(@libui)
58
+ ::LibUI.draw_fill(area_draw_params[:context], @libui, fill_draw_brush.to_ptr) unless fill.empty?
59
+ ::LibUI.draw_stroke(area_draw_params[:context], @libui, stroke_draw_brush, draw_stroke_params) unless stroke.empty?
60
+ ::LibUI.draw_free_path(@libui)
61
+ end
62
+
63
+ def draw_fill_mode
64
+ @args[0].is_a?(Integer) ? @args[0] : @args[0].to_s == 'alternate' ? 1 : 0
65
+ end
66
+
67
+ def fill(args = nil)
68
+ if args.nil?
69
+ @fill ||= {}
70
+ else
71
+ @fill = args
72
+ end
73
+ end
74
+ alias fill= fill
75
+ alias set_fill fill
76
+
77
+ def fill_draw_brush
78
+ @fill_draw_brush ||= ::LibUI::FFI::DrawBrush.malloc
79
+ init_draw_brush(@fill_draw_brush, @fill)
80
+ @fill_draw_brush
81
+ end
82
+
83
+ def stroke(args = nil)
84
+ if args.nil?
85
+ @stroke ||= {}
86
+ else
87
+ @stroke = args
88
+ end
89
+ end
90
+ alias stroke= stroke
91
+ alias set_stroke stroke
92
+
93
+ def stroke_draw_brush
94
+ @stroke_draw_brush ||= ::LibUI::FFI::DrawBrush.malloc
95
+ init_draw_brush(@stroke_draw_brush, @stroke)
96
+ @stroke_draw_brush
97
+ end
98
+
99
+ def draw_stroke_params
100
+ @draw_stroke_params ||= ::LibUI::FFI::DrawStrokeParams.malloc
101
+ @draw_stroke_params.Cap = @stroke[:cap] || 0 # flat
102
+ @draw_stroke_params.Join = @stroke[:join] || 0 # miter
103
+ @draw_stroke_params.Thickness = @stroke[:thickness] || 1
104
+ @draw_stroke_params.MiterLimit = @stroke[:miter_limit] || 10 # DEFAULT_MITER_LIMIT
105
+ @draw_stroke_params_dashes ||= Fiddle::Pointer.malloc(8)
106
+ @draw_stroke_params.Dashes = @draw_stroke_params_dashes
107
+ @draw_stroke_params.NumDashes = @stroke[:num_dashes] || 0 # TODO reimplement this line correctly (perhaps no need to pass num dashes, yet dashes themselves and use their count here)
108
+ @draw_stroke_params.DashPhase = @stroke[:dash_phase] || 0
109
+ @draw_stroke_params
110
+ end
111
+
112
+ # returns area_draw_params if built inside on_draw listener (not needed if declared outside)
113
+ def area_draw_params
114
+ @args[0] if @parent_proxy.nil?
115
+ end
116
+
117
+ def destroy
118
+ @parent_proxy.children.delete(self) unless @parent_proxy.nil?
119
+ end
120
+
121
+ private
122
+
123
+ def build_control
124
+ @libui = ::LibUI.draw_new_path(draw_fill_mode)
125
+ end
126
+
127
+ def init_draw_brush(draw_brush, draw_brush_args)
128
+ case draw_brush_args[:type]
129
+ when Integer
130
+ draw_brush.Type = draw_brush_args[:type]
131
+ when :solid, 'solid'
132
+ draw_brush.Type = 0
133
+ when :linear_gradient, 'linear_gradient'
134
+ draw_brush.Type = 1
135
+ when :radial_gradient, 'radial_gradient'
136
+ draw_brush.Type = 2
137
+ when :image, 'image'
138
+ draw_brush.Type = 3
139
+ else
140
+ draw_brush.Type = 0
141
+ end
142
+ draw_brush.R = (draw_brush_args[:r] || draw_brush_args[:red]).to_f / 255.0
143
+ draw_brush.G = (draw_brush_args[:g] || draw_brush_args[:green]).to_f / 255.0
144
+ draw_brush.B = (draw_brush_args[:b] || draw_brush_args[:blue]).to_f / 255.0
145
+ draw_brush.A = (draw_brush_args[:a] || draw_brush_args[:alpha])
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,56 @@
1
+ # Copyright (c) 2021 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/libui/control_proxy'
23
+
24
+ module Glimmer
25
+ module LibUI
26
+ # Proxy for LibUI rectangle objects
27
+ #
28
+ # Follows the Proxy Design Pattern
29
+ class RectangleProxy < ControlProxy
30
+ def initialize(keyword, parent, args, &block)
31
+ @keyword = keyword
32
+ @parent_proxy = parent
33
+ @args = args
34
+ @block = block
35
+ @enabled = true
36
+ post_add_content if @block.nil?
37
+ end
38
+
39
+ def draw(area_draw_params)
40
+ ::LibUI.draw_path_add_rectangle(@parent_proxy.libui, *@args)
41
+ end
42
+
43
+ def destroy
44
+ if @parent_proxy
45
+ @parent_proxy.children.delete(self)
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ def build_control
52
+ # No Op
53
+ end
54
+ end
55
+ end
56
+ end
@@ -21,6 +21,7 @@
21
21
 
22
22
  require 'glimmer/libui/control_proxy'
23
23
  require 'glimmer/data_binding/observer'
24
+ require 'glimmer/fiddle_consumer'
24
25
 
25
26
  using ArrayIncludeMethods
26
27
 
@@ -30,6 +31,8 @@ module Glimmer
30
31
  #
31
32
  # Follows the Proxy Design Pattern
32
33
  class TableProxy < ControlProxy
34
+ include Glimmer::FiddleConsumer
35
+
33
36
  attr_reader :model_handler, :model, :table_params, :columns
34
37
 
35
38
  def initialize(keyword, parent, args, &block)
@@ -71,8 +74,16 @@ module Glimmer
71
74
  @last_cell_rows = @cell_rows.clone
72
75
  Glimmer::DataBinding::Observer.proc do
73
76
  if @cell_rows.size < @last_cell_rows.size && @last_cell_rows.include_all?(*@cell_rows)
74
- @last_cell_rows.array_diff_indexes(@cell_rows).reverse.each do |index|
75
- ::LibUI.table_model_row_deleted(model, index)
77
+ @last_cell_rows.array_diff_indexes(@cell_rows).reverse.each do |row|
78
+ ::LibUI.table_model_row_deleted(model, row)
79
+ end
80
+ elsif @cell_rows.size > @last_cell_rows.size && @cell_rows.include_all?(*@last_cell_rows)
81
+ @cell_rows.array_diff_indexes(@last_cell_rows).each do |row|
82
+ ::LibUI.table_model_row_inserted(model, row)
83
+ end
84
+ else
85
+ @cell_rows.each_with_index do |new_row_data, row|
86
+ ::LibUI.table_model_row_changed(model, row) if new_row_data != @last_cell_rows[row]
76
87
  end
77
88
  end
78
89
  @last_cell_rows = @cell_rows.clone
@@ -104,8 +115,8 @@ module Glimmer
104
115
 
105
116
  def build_control
106
117
  @model_handler = ::LibUI::FFI::TableModelHandler.malloc
107
- @model_handler.NumColumns = rbcallback(4) { @columns.map {|c| c.is_a?(DualColumn) ? 2 : 1}.sum }
108
- @model_handler.ColumnType = rbcallback(4, [1, 1, 4]) do |_, _, column|
118
+ @model_handler.NumColumns = fiddle_closure_block_caller(4) { @columns.map {|c| c.is_a?(DualColumn) ? 2 : 1}.sum }
119
+ @model_handler.ColumnType = fiddle_closure_block_caller(4, [1, 1, 4]) do |_, _, column|
109
120
  case @columns[column]
110
121
  when TextColumnProxy, ButtonColumnProxy, NilClass
111
122
  0
@@ -115,8 +126,8 @@ module Glimmer
115
126
  2
116
127
  end
117
128
  end
118
- @model_handler.NumRows = rbcallback(4) { cell_rows.count }
119
- @model_handler.CellValue = rbcallback(1, [1, 1, 4, 4]) do |_, _, row, column|
129
+ @model_handler.NumRows = fiddle_closure_block_caller(4) { cell_rows.count }
130
+ @model_handler.CellValue = fiddle_closure_block_caller(1, [1, 1, 4, 4]) do |_, _, row, column|
120
131
  the_cell_rows = expanded_cell_rows
121
132
  case @columns[column]
122
133
  when TextColumnProxy, ButtonColumnProxy, NilClass
@@ -129,7 +140,7 @@ module Glimmer
129
140
  ::LibUI.new_table_value_int((expanded_cell_rows[row] && (expanded_cell_rows[row][column].to_i)))
130
141
  end
131
142
  end
132
- @model_handler.SetCellValue = rbcallback(0, [1, 1, 4, 4, 1]) do |_, _, row, column, val|
143
+ @model_handler.SetCellValue = fiddle_closure_block_caller(0, [1, 1, 4, 4, 1]) do |_, _, row, column, val|
133
144
  case @columns[column]
134
145
  when TextColumnProxy
135
146
  column = @columns[column].index
@@ -159,16 +170,6 @@ module Glimmer
159
170
  end
160
171
  end
161
172
 
162
- def rbcallback(*args, &block)
163
- # TODO consider moving to a more general reusable location in the future (e.g. when used with `AreaProxy`)
164
- # Protects BlockCaller objects from garbage collection.
165
- @blockcaller ||= []
166
- args << [0] if args.size == 1 # Argument types are ommited
167
- blockcaller = Fiddle::Closure::BlockCaller.new(*args, &block)
168
- @blockcaller << blockcaller
169
- blockcaller
170
- end
171
-
172
173
  def next_column_index
173
174
  @next_column_index ||= -1
174
175
  @next_column_index += 1
@@ -48,8 +48,14 @@ module Glimmer
48
48
  end
49
49
 
50
50
  def on_destroy(&block)
51
+ # TODO look into a way to generalize this logic for multiple listeners
51
52
  @on_destroy_procs ||= []
52
- @on_destroy_procs << block
53
+ if block.nil?
54
+ @on_destroy_procs
55
+ else
56
+ @on_destroy_procs << block
57
+ block
58
+ end
53
59
  end
54
60
 
55
61
  def show
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.0.26
4
+ version: 0.1.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: 2021-09-27 00:00:00.000000000 Z
11
+ date: 2021-09-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: glimmer
@@ -194,6 +194,8 @@ files:
194
194
  - VERSION
195
195
  - bin/girb
196
196
  - bin/girb_runner.rb
197
+ - examples/basic_area.rb
198
+ - examples/basic_area2.rb
197
199
  - examples/basic_button.rb
198
200
  - examples/basic_entry.rb
199
201
  - examples/basic_table.rb
@@ -208,10 +210,12 @@ files:
208
210
  - examples/color_button.rb
209
211
  - examples/control_gallery.rb
210
212
  - examples/date_time_picker.rb
213
+ - examples/dynamic_area.rb
211
214
  - examples/editable_column_table.rb
212
215
  - examples/editable_table.rb
213
216
  - examples/font_button.rb
214
217
  - examples/form.rb
218
+ - examples/form_table.rb
215
219
  - examples/grid.rb
216
220
  - examples/meta_example.rb
217
221
  - examples/midi_player.rb
@@ -226,7 +230,9 @@ files:
226
230
  - lib/glimmer/dsl/libui/property_expression.rb
227
231
  - lib/glimmer/dsl/libui/save_file_expression.rb
228
232
  - lib/glimmer/dsl/libui/tab_item_expression.rb
233
+ - lib/glimmer/fiddle_consumer.rb
229
234
  - lib/glimmer/libui/about_menu_item_proxy.rb
235
+ - lib/glimmer/libui/area_proxy.rb
230
236
  - lib/glimmer/libui/box.rb
231
237
  - lib/glimmer/libui/button_column_proxy.rb
232
238
  - lib/glimmer/libui/button_proxy.rb
@@ -258,10 +264,12 @@ files:
258
264
  - lib/glimmer/libui/menu_proxy.rb
259
265
  - lib/glimmer/libui/multiline_entry_proxy.rb
260
266
  - lib/glimmer/libui/non_wrapping_multiline_entry_proxy.rb
267
+ - lib/glimmer/libui/path_proxy.rb
261
268
  - lib/glimmer/libui/preferences_menu_item_proxy.rb
262
269
  - lib/glimmer/libui/progress_bar_column_proxy.rb
263
270
  - lib/glimmer/libui/quit_menu_item_proxy.rb
264
271
  - lib/glimmer/libui/radio_buttons_proxy.rb
272
+ - lib/glimmer/libui/rectangle_proxy.rb
265
273
  - lib/glimmer/libui/separator_menu_item_proxy.rb
266
274
  - lib/glimmer/libui/tab_item_proxy.rb
267
275
  - lib/glimmer/libui/table_proxy.rb