glimmer-dsl-libui 0.0.26 → 0.1.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: 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