glimmer-dsl-libui 0.6.0 → 0.6.2

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: cd6518993a36f3108798c6e510e7e8b4cf948738106d78320e3c50a0537d6046
4
- data.tar.gz: a06bd741f0900f8311a771cd5acdabefa22e7f7d07f7a2878cc85e03a086c916
3
+ metadata.gz: 8b428873ab2c165da4aa71fb0f0b22496f02c6dc88a94e22368e398d7f5482b7
4
+ data.tar.gz: 8f4e813a4a99a91434ff0ae9fa72db2b7cbacf9df77ba195bb21dedd5f3a7536
5
5
  SHA512:
6
- metadata.gz: b42863592aeff2f871c596bbe8e43fd74646d4a3b7b413ead62bd07f8baf1a40f3109a73e23709441eb32403edac51088211c0c373ea0fa5c29c1f97c6581ff3
7
- data.tar.gz: cb642dc20da632413d2fc7a29900158120d9d4146401c334a8681044a048e7a925ed05d7f845ecaf6e75f05a5fbdabc055c5bac28c7713228c466ef116f9db01
6
+ metadata.gz: 6b164fe869a9668d90820d3a47d998ef3e212339346bf7ec4c830b8ebbf9a4ce791b8e7ab2f353bcffc58a65ac1f62f20a762d1b75b414167ea780aa7fb7566f
7
+ data.tar.gz: 0fffb26e375d7b7cbdf683ae1a844ac67df154ef3626ab407a1af198658d9e0448674d21c517045e5f045cd4983d193d04a32ff2146958d4d1598cb6c899620a
data/CHANGELOG.md CHANGED
@@ -1,9 +1,18 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.6.2
4
+
5
+ - Fix issue with `examples/lazy_table.rb` not working in Windows due to error: block in `apply_windows_fix`: undefined method `<<` for `#:each`> (`NoMethodError`) `@cell_rows << new_row`
6
+
7
+ ## 0.6.1
8
+
9
+ - `examples/lazy_table.rb` (4 versions) table lazy loading with a million rows via `Enumerator` or `Enumerator::Lazy` to enable instant app startup time
10
+ - Support `table` `cell_rows` implicit data-binding to a collection of models (only supported an array of arrays before in implicit data-binding)
11
+
3
12
  ## 0.6.0
4
13
 
5
14
  - Upgrade to `libui` Ruby gem version 0.1.0.pre.0, which includes a newer C libui alpha release (libui-ng Nov 13, 2022)
6
- - Support table `cell_rows` `Enumerator` value to do lazy loading of data upon display of rows instead of immediate loading of all table data, thus improving performance of table initial render for very large datasets
15
+ - Support table `cell_rows` `Enumerator` or `Enumerator::Lazy` value to do lazy loading of data upon display of rows instead of immediate loading of all table data, thus improving performance of table initial render for very large datasets
7
16
  - Fix issue with `table` `progress_bar_column` not getting updated successfully on Windows if there were dual or triple columns before it.
8
17
  - Fix issue with `table` `progress_bar_column` not getting updated successfully on Windows if data-binding table to an array of models instead of an array of arrays
9
18
  - Fix issue with `table` `checkbox_column` checkbox editing not working in Mac by including a new C libui-ng release
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.6.0
1
+ # [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for LibUI 0.6.2
2
2
  ## Prerequisite-Free Ruby Desktop Development GUI Library
3
3
  ### The Quickest Way From Zero To GUI
4
4
  [![Gem Version](https://badge.fury.io/rb/glimmer-dsl-libui.svg)](http://badge.fury.io/rb/glimmer-dsl-libui)
@@ -542,7 +542,7 @@ gem install glimmer-dsl-libui
542
542
  Or install via Bundler `Gemfile`:
543
543
 
544
544
  ```ruby
545
- gem 'glimmer-dsl-libui', '~> 0.6.0'
545
+ gem 'glimmer-dsl-libui', '~> 0.6.2'
546
546
  ```
547
547
 
548
548
  Test that installation worked by running the [Meta-Example](#examples):
@@ -2000,8 +2000,10 @@ That is data-binding `entered_text` attribute on `self` to `entry` `text` proper
2000
2000
  ##### Table Data-Binding
2001
2001
 
2002
2002
  One note about `table` `cell_rows` data-binding is that it works with either:
2003
- - Raw data `Array` (rows) of `Array`s (column cells)
2004
- - Model `Array` (rows) of objects having attributes (column cells) matching the underscored names of `table` columns by convention. Model attribute names can be overridden when needed by passing an `Array` enumerating all mapped model attributes in the order of `table` columns or alternatively a `Hash` mapping only the column names that have model attribute names different from their table column underscored version.
2003
+ - Raw data `Array` (rows) of `Array`s (column cells) (see [Form Table example versions 4-5](https://github.com/AndyObtiva/glimmer-dsl-libui/blob/master/docs/examples/GLIMMER-DSL-LIBUI-ADVANCED-EXAMPLES.md#form-table)).
2004
+ - Model `Array` (rows) of objects having attributes (column cells) matching the underscored names of `table` columns by convention. Model attribute names can be overridden when needed by passing an `Array` enumerating all mapped model attributes in the order of `table` columns or alternatively a `Hash` mapping only the column names that have model attribute names different from their table column underscored version (see [Form Table example versions 1-3](https://github.com/AndyObtiva/glimmer-dsl-libui/blob/master/docs/examples/GLIMMER-DSL-LIBUI-ADVANCED-EXAMPLES.md#form-table)).
2005
+ - Raw data `Enumerator` or `Enumerator::Lazy` that generates `Array`s (column cells). This option enables rendering a table instantly even if it contained millions of rows, before all its rows have been generated. Rows are gradually generated as the user scrolls through the table.
2006
+ - Model `Enumerator` or `Enumerator::Lazy` that generates objects having attributes (column cells) matching the underscored names of `table` columns. This option enables rendering a table instantly even if it contained millions of rows, before all its rows have been generated. Rows are gradually generated as the user scrolls through the table (see [Lazy Table](https://github.com/AndyObtiva/glimmer-dsl-libui/blob/master/docs/examples/GLIMMER-DSL-LIBUI-ADVANCED-EXAMPLES.md#lazy-table) example).
2005
2007
 
2006
2008
  Example of `table` implicit data-binding of `cell_rows` to raw data `Array` of `Array`s (you may copy/paste in [`girb`](#girb-glimmer-irb)):
2007
2009
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.6.0
1
+ 0.6.2
@@ -13,6 +13,7 @@
13
13
  - [Form Table](#form-table)
14
14
  - [GPT2 Notepad](#gpt2-notepad)
15
15
  - [Paginated Refined Table](#paginated-refined-table)
16
+ - [Lazy Table](#lazy-table)
16
17
  - [Grid](#grid)
17
18
  - [Histogram](#histogram)
18
19
  - [Login](#login)
@@ -337,126 +338,44 @@ Mac | Windows | Linux
337
338
 
338
339
  New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
339
340
 
340
- ```ruby
341
- require 'glimmer-dsl-libui'
341
+ [examples/paginated_refined_table.rb](/examples/paginated_refined_table.rb)
342
342
 
343
- class PaginatedRefinedTable
344
- Contact = Struct.new(:name, :email, :phone, :city, :state)
345
-
346
- include Glimmer::LibUI::Application
347
-
348
- NAMES_FIRST = %w[
349
- Liam Noah William James Oliver Benjamin Elijah Lucas Mason Logan Alexander Ethan Jacob Michael Daniel Henry Jackson Sebastian
350
- Aiden Matthew Samuel David Joseph Carter Owen Wyatt John Jack Luke Jayden Dylan Grayson Levi Isaac Gabriel Julian Mateo
351
- Anthony Jaxon Lincoln Joshua Christopher Andrew Theodore Caleb Ryan Asher Nathan Thomas Leo Isaiah Charles Josiah Hudson
352
- Christian Hunter Connor Eli Ezra Aaron Landon Adrian Jonathan Nolan Jeremiah Easton Elias Colton Cameron Carson Robert Angel
353
- Maverick Nicholas Dominic Jaxson Greyson Adam Ian Austin Santiago Jordan Cooper Brayden Roman Evan Ezekiel Xaviar Jose Jace
354
- Jameson Leonardo Axel Everett Kayden Miles Sawyer Jason Emma Olivia Bartholomew Corey Danielle Eva Felicity
355
- ]
356
-
357
- NAMES_LAST = %w[
358
- Smith Johnson Williams Brown Jones Miller Davis Wilson Anderson Taylor George Harrington Iverson Jackson Korby Levinson
359
- ]
360
-
361
- CITIES = [
362
- 'Bellesville', 'Lombardia', 'Steepleton', 'Deerenstein', 'Schwartz', 'Hollandia', 'Saint Pete', 'Grandville', 'London',
363
- 'Berlin', 'Elktown', 'Paris', 'Garrison', 'Muncy', 'St Louis',
364
- ]
365
-
366
- STATES = [ 'AK', 'AL', 'AR', 'AZ', 'CA', 'CO', 'CT', 'DC', 'DE', 'FL', 'GA',
367
- 'HI', 'IA', 'ID', 'IL', 'IN', 'KS', 'KY', 'LA', 'MA', 'MD', 'ME',
368
- 'MI', 'MN', 'MO', 'MS', 'MT', 'NC', 'ND', 'NE', 'NH', 'NJ', 'NM',
369
- 'NV', 'NY', 'OH', 'OK', 'OR', 'PA', 'RI', 'SC', 'SD', 'TN', 'TX',
370
- 'UT', 'VA', 'VT', 'WA', 'WI', 'WV', 'WY']
371
-
372
- attr_accessor :contacts, :name, :email, :phone, :city, :state, :filter_value, :index
373
-
374
- before_body do
375
- @contacts = 50_000.times.map do |n|
376
- n += 1
377
- first_name = NAMES_FIRST.sample
378
- last_name = NAMES_LAST.sample
379
- city = CITIES.sample
380
- state = STATES.sample
381
- Contact.new("#{first_name} #{last_name}", "#{first_name.downcase}#{n}@#{last_name.downcase}.com", '555-555-5555', city, state)
382
- end
383
- end
384
-
385
- body {
386
- window("50,000 Paginated Contacts", 600, 700) {
387
- margined true
388
-
389
- vertical_box {
390
- form {
391
- stretchy false
392
-
393
- entry {
394
- label 'Name'
395
- text <=> [self, :name] # bidirectional data-binding between entry text and self.name
396
- }
397
-
398
- entry {
399
- label 'Email'
400
- text <=> [self, :email]
401
- }
402
-
403
- entry {
404
- label 'Phone'
405
- text <=> [self, :phone]
406
- }
407
-
408
- entry {
409
- label 'City'
410
- text <=> [self, :city]
411
- }
412
-
413
- entry {
414
- label 'State'
415
- text <=> [self, :state]
416
- }
417
- }
418
-
419
- button('Save Contact') {
420
- stretchy false
421
-
422
- on_clicked do
423
- new_row = [name, email, phone, city, state]
424
- if new_row.map(&:to_s).include?('')
425
- msg_box_error('Validation Error!', 'All fields are required! Please make sure to enter a value for all fields.')
426
- else
427
- @contacts << Contact.new(*new_row) # automatically inserts a row into the table due to explicit data-binding
428
- @unfiltered_contacts = @contacts.dup
429
- self.name = '' # automatically clears name entry through explicit data-binding
430
- self.email = ''
431
- self.phone = ''
432
- self.city = ''
433
- self.state = ''
434
- end
435
- end
436
- }
437
-
438
- refined_table(
439
- model_array: contacts,
440
- table_columns: {
441
- 'Name' => {text: {editable: false}},
442
- 'Email' => :text,
443
- 'Phone' => :text,
444
- 'City' => :text,
445
- 'State' => :text,
446
- },
447
- table_editable: true,
448
- per_page: 20,
449
- # page: 1, # initial page is 1
450
- # visible_page_count: true, # page count can be shown if preferred
451
- )
452
- }
453
- }
454
- }
455
- end
343
+ ## Lazy Table
344
+
345
+ A lazy table is loaded with row data lazily via Ruby `Enumerator` or `Enumerator::Lazy`.
346
+ That enables starting the app and rendering the table instantly before generating/loading all data,
347
+ even if the table was to contain millions of rows.
348
+
349
+ [examples/lazy_table.rb](/examples/lazy_table.rb)
456
350
 
457
- PaginatedRefinedTable.launch
351
+ Run with this command from the root of the project if you cloned the project:
352
+
353
+ ```
354
+ ruby -r './lib/glimmer-dsl-libui' examples/lazy_table.rb
355
+ ```
356
+
357
+ Run with this command if you installed the [Ruby gem](https://rubygems.org/gems/glimmer-dsl-libui):
358
+
359
+ ```
360
+ ruby -r glimmer-dsl-libui -e "require 'examples/lazy_table'"
458
361
  ```
459
362
 
363
+ [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version (using a well encapsulated `Enumerator` Subclass):
364
+
365
+ [examples/lazy_table.rb](/examples/lazy_table.rb)
366
+
367
+ [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (using `Enumerator` directly):
368
+
369
+ [examples/lazy_table2.rb](/examples/lazy_table2.rb)
370
+
371
+ [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 3 (using a well encapsulated `Enumerator::Lazy` Subclass):
372
+
373
+ [examples/lazy_table3.rb](/examples/lazy_table3.rb)
374
+
375
+ [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 4 (using `Enumerator::Lazy` directly):
376
+
377
+ [examples/lazy_table4.rb](/examples/lazy_table4.rb)
378
+
460
379
  ## Grid
461
380
 
462
381
  [examples/grid.rb](/examples/grid.rb)
@@ -0,0 +1,76 @@
1
+ require 'glimmer-dsl-libui'
2
+
3
+ class LazyTable
4
+ Contact = Struct.new(:name, :email, :phone, :city, :state)
5
+
6
+ # Extending Enumerator enables building a collection generator in an encapsulated maintainable fashion
7
+ class ContactGenerator < Enumerator
8
+ NAMES_FIRST = %w[
9
+ Liam Noah William James Oliver Benjamin Elijah Lucas Mason Logan Alexander Ethan Jacob Michael Daniel Henry Jackson Sebastian
10
+ Aiden Matthew Samuel David Joseph Carter Owen Wyatt John Jack Luke Jayden Dylan Grayson Levi Isaac Gabriel Julian Mateo
11
+ Anthony Jaxon Lincoln Joshua Christopher Andrew Theodore Caleb Ryan Asher Nathan Thomas Leo Isaiah Charles Josiah Hudson
12
+ Christian Hunter Connor Eli Ezra Aaron Landon Adrian Jonathan Nolan Jeremiah Easton Elias Colton Cameron Carson Robert Angel
13
+ Maverick Nicholas Dominic Jaxson Greyson Adam Ian Austin Santiago Jordan Cooper Brayden Roman Evan Ezekiel Xaviar Jose Jace
14
+ Jameson Leonardo Axel Everett Kayden Miles Sawyer Jason Emma Olivia Bartholomew Corey Danielle Eva Felicity
15
+ ]
16
+
17
+ NAMES_LAST = %w[
18
+ Smith Johnson Williams Brown Jones Miller Davis Wilson Anderson Taylor George Harrington Iverson Jackson Korby Levinson
19
+ ]
20
+
21
+ CITIES = [
22
+ 'Bellesville', 'Lombardia', 'Steepleton', 'Deerenstein', 'Schwartz', 'Hollandia', 'Saint Pete', 'Grandville', 'London',
23
+ 'Berlin', 'Elktown', 'Paris', 'Garrison', 'Muncy', 'St Louis',
24
+ ]
25
+
26
+ STATES = [ 'AK', 'AL', 'AR', 'AZ', 'CA', 'CO', 'CT', 'DC', 'DE', 'FL', 'GA',
27
+ 'HI', 'IA', 'ID', 'IL', 'IN', 'KS', 'KY', 'LA', 'MA', 'MD', 'ME',
28
+ 'MI', 'MN', 'MO', 'MS', 'MT', 'NC', 'ND', 'NE', 'NH', 'NJ', 'NM',
29
+ 'NV', 'NY', 'OH', 'OK', 'OR', 'PA', 'RI', 'SC', 'SD', 'TN', 'TX',
30
+ 'UT', 'VA', 'VT', 'WA', 'WI', 'WV', 'WY']
31
+
32
+ def initialize(contact_count)
33
+ # Make sure to pass super constructor size argument as it gets used by Glimmer DSL for LibUI
34
+ # to determine the number of rows in the table before generating all its data
35
+ super(contact_count) do |yielder|
36
+ contact_count.times do |index|
37
+ # Data will get lazy loaded into the table as the user scrolls through.
38
+ # After data is built, it is cached long-term, till updating table `cell_rows`.
39
+ yielder << contact_for(index)
40
+ end
41
+ end
42
+ end
43
+
44
+ def contact_for(index)
45
+ number = index + 1
46
+ first_name = NAMES_FIRST.sample
47
+ last_name = NAMES_LAST.sample
48
+ phone = 10.times.map { rand(10) }.yield_self { |numbers| [numbers[0..2], numbers[3..5], numbers[6..9]].map(&:join).join('-') }
49
+ city = CITIES.sample
50
+ state = STATES.sample
51
+ Contact.new("#{first_name} #{last_name}", "#{first_name.downcase}#{number}@#{last_name.downcase}.com", phone, city, state)
52
+ end
53
+ end
54
+
55
+ include Glimmer::LibUI::Application
56
+
57
+ body {
58
+ window("1,000,000 Lazy Loaded Contacts", 600, 700) {
59
+ margined true
60
+
61
+ vertical_box {
62
+ table {
63
+ text_column('Name')
64
+ text_column('Email')
65
+ text_column('Phone')
66
+ text_column('City')
67
+ text_column('State')
68
+
69
+ cell_rows ContactGenerator.new(1_000_000)
70
+ }
71
+ }
72
+ }
73
+ }
74
+ end
75
+
76
+ LazyTable.launch
@@ -0,0 +1,71 @@
1
+ require 'glimmer-dsl-libui'
2
+
3
+ class LazyTable
4
+ Contact = Struct.new(:name, :email, :phone, :city, :state)
5
+
6
+ include Glimmer::LibUI::Application
7
+
8
+ NAMES_FIRST = %w[
9
+ Liam Noah William James Oliver Benjamin Elijah Lucas Mason Logan Alexander Ethan Jacob Michael Daniel Henry Jackson Sebastian
10
+ Aiden Matthew Samuel David Joseph Carter Owen Wyatt John Jack Luke Jayden Dylan Grayson Levi Isaac Gabriel Julian Mateo
11
+ Anthony Jaxon Lincoln Joshua Christopher Andrew Theodore Caleb Ryan Asher Nathan Thomas Leo Isaiah Charles Josiah Hudson
12
+ Christian Hunter Connor Eli Ezra Aaron Landon Adrian Jonathan Nolan Jeremiah Easton Elias Colton Cameron Carson Robert Angel
13
+ Maverick Nicholas Dominic Jaxson Greyson Adam Ian Austin Santiago Jordan Cooper Brayden Roman Evan Ezekiel Xaviar Jose Jace
14
+ Jameson Leonardo Axel Everett Kayden Miles Sawyer Jason Emma Olivia Bartholomew Corey Danielle Eva Felicity
15
+ ]
16
+
17
+ NAMES_LAST = %w[
18
+ Smith Johnson Williams Brown Jones Miller Davis Wilson Anderson Taylor George Harrington Iverson Jackson Korby Levinson
19
+ ]
20
+
21
+ CITIES = [
22
+ 'Bellesville', 'Lombardia', 'Steepleton', 'Deerenstein', 'Schwartz', 'Hollandia', 'Saint Pete', 'Grandville', 'London',
23
+ 'Berlin', 'Elktown', 'Paris', 'Garrison', 'Muncy', 'St Louis',
24
+ ]
25
+
26
+ STATES = [ 'AK', 'AL', 'AR', 'AZ', 'CA', 'CO', 'CT', 'DC', 'DE', 'FL', 'GA',
27
+ 'HI', 'IA', 'ID', 'IL', 'IN', 'KS', 'KY', 'LA', 'MA', 'MD', 'ME',
28
+ 'MI', 'MN', 'MO', 'MS', 'MT', 'NC', 'ND', 'NE', 'NH', 'NJ', 'NM',
29
+ 'NV', 'NY', 'OH', 'OK', 'OR', 'PA', 'RI', 'SC', 'SD', 'TN', 'TX',
30
+ 'UT', 'VA', 'VT', 'WA', 'WI', 'WV', 'WY']
31
+
32
+ before_body do
33
+ contact_count = 1_000_000
34
+ # Make sure to pass Enumerator constructor size argument as it gets used by Glimmer DSL for LibUI
35
+ # to determine the number of rows in the table before generating all its data
36
+ @contacts = Enumerator.new(contact_count) do |yielder|
37
+ contact_count.times do |index|
38
+ number = index + 1
39
+ first_name = NAMES_FIRST.sample
40
+ last_name = NAMES_LAST.sample
41
+ phone = 10.times.map { rand(10) }.yield_self { |numbers| [numbers[0..2], numbers[3..5], numbers[6..9]].map(&:join).join('-') }
42
+ city = CITIES.sample
43
+ state = STATES.sample
44
+
45
+ # Data will get lazy loaded into the table as the user scrolls through.
46
+ # After data is built, it is cached long-term, till updating table `cell_rows`.
47
+ yielder << Contact.new("#{first_name} #{last_name}", "#{first_name.downcase}#{number}@#{last_name.downcase}.com", phone, city, state)
48
+ end
49
+ end
50
+ end
51
+
52
+ body {
53
+ window("1,000,000 Lazy Loaded Contacts", 600, 700) {
54
+ margined true
55
+
56
+ vertical_box {
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 @contacts
65
+ }
66
+ }
67
+ }
68
+ }
69
+ end
70
+
71
+ LazyTable.launch
@@ -0,0 +1,74 @@
1
+ require 'glimmer-dsl-libui'
2
+
3
+ class LazyTable
4
+ Contact = Struct.new(:name, :email, :phone, :city, :state)
5
+
6
+ # Extending Enumerator::Lazy enables building a collection generator in an encapsulated maintainable fashion
7
+ class ContactGenerator < Enumerator::Lazy
8
+ NAMES_FIRST = %w[
9
+ Liam Noah William James Oliver Benjamin Elijah Lucas Mason Logan Alexander Ethan Jacob Michael Daniel Henry Jackson Sebastian
10
+ Aiden Matthew Samuel David Joseph Carter Owen Wyatt John Jack Luke Jayden Dylan Grayson Levi Isaac Gabriel Julian Mateo
11
+ Anthony Jaxon Lincoln Joshua Christopher Andrew Theodore Caleb Ryan Asher Nathan Thomas Leo Isaiah Charles Josiah Hudson
12
+ Christian Hunter Connor Eli Ezra Aaron Landon Adrian Jonathan Nolan Jeremiah Easton Elias Colton Cameron Carson Robert Angel
13
+ Maverick Nicholas Dominic Jaxson Greyson Adam Ian Austin Santiago Jordan Cooper Brayden Roman Evan Ezekiel Xaviar Jose Jace
14
+ Jameson Leonardo Axel Everett Kayden Miles Sawyer Jason Emma Olivia Bartholomew Corey Danielle Eva Felicity
15
+ ]
16
+
17
+ NAMES_LAST = %w[
18
+ Smith Johnson Williams Brown Jones Miller Davis Wilson Anderson Taylor George Harrington Iverson Jackson Korby Levinson
19
+ ]
20
+
21
+ CITIES = [
22
+ 'Bellesville', 'Lombardia', 'Steepleton', 'Deerenstein', 'Schwartz', 'Hollandia', 'Saint Pete', 'Grandville', 'London',
23
+ 'Berlin', 'Elktown', 'Paris', 'Garrison', 'Muncy', 'St Louis',
24
+ ]
25
+
26
+ STATES = [ 'AK', 'AL', 'AR', 'AZ', 'CA', 'CO', 'CT', 'DC', 'DE', 'FL', 'GA',
27
+ 'HI', 'IA', 'ID', 'IL', 'IN', 'KS', 'KY', 'LA', 'MA', 'MD', 'ME',
28
+ 'MI', 'MN', 'MO', 'MS', 'MT', 'NC', 'ND', 'NE', 'NH', 'NJ', 'NM',
29
+ 'NV', 'NY', 'OH', 'OK', 'OR', 'PA', 'RI', 'SC', 'SD', 'TN', 'TX',
30
+ 'UT', 'VA', 'VT', 'WA', 'WI', 'WV', 'WY']
31
+
32
+ def initialize(contact_count)
33
+ # Make sure to pass super constructor size (2nd) argument as it gets used by Glimmer DSL for LibUI
34
+ # to determine the number of rows in the table before generating all its data
35
+ super(contact_count.times, contact_count) do |yielder, index|
36
+ # Data will get lazy loaded into the table as the user scrolls through.
37
+ # After data is built, it is cached long-term, till updating table `cell_rows`.
38
+ yielder << contact_for(index)
39
+ end
40
+ end
41
+
42
+ def contact_for(index)
43
+ number = index + 1
44
+ first_name = NAMES_FIRST.sample
45
+ last_name = NAMES_LAST.sample
46
+ phone = 10.times.map { rand(10) }.yield_self { |numbers| [numbers[0..2], numbers[3..5], numbers[6..9]].map(&:join).join('-') }
47
+ city = CITIES.sample
48
+ state = STATES.sample
49
+ Contact.new("#{first_name} #{last_name}", "#{first_name.downcase}#{number}@#{last_name.downcase}.com", phone, city, state)
50
+ end
51
+ end
52
+
53
+ include Glimmer::LibUI::Application
54
+
55
+ body {
56
+ window("1,000,000 Lazy Loaded Contacts", 600, 700) {
57
+ margined true
58
+
59
+ vertical_box {
60
+ table {
61
+ text_column('Name')
62
+ text_column('Email')
63
+ text_column('Phone')
64
+ text_column('City')
65
+ text_column('State')
66
+
67
+ cell_rows ContactGenerator.new(1_000_000)
68
+ }
69
+ }
70
+ }
71
+ }
72
+ end
73
+
74
+ LazyTable.launch
@@ -0,0 +1,69 @@
1
+ require 'glimmer-dsl-libui'
2
+
3
+ class LazyTable
4
+ Contact = Struct.new(:name, :email, :phone, :city, :state)
5
+
6
+ include Glimmer::LibUI::Application
7
+
8
+ NAMES_FIRST = %w[
9
+ Liam Noah William James Oliver Benjamin Elijah Lucas Mason Logan Alexander Ethan Jacob Michael Daniel Henry Jackson Sebastian
10
+ Aiden Matthew Samuel David Joseph Carter Owen Wyatt John Jack Luke Jayden Dylan Grayson Levi Isaac Gabriel Julian Mateo
11
+ Anthony Jaxon Lincoln Joshua Christopher Andrew Theodore Caleb Ryan Asher Nathan Thomas Leo Isaiah Charles Josiah Hudson
12
+ Christian Hunter Connor Eli Ezra Aaron Landon Adrian Jonathan Nolan Jeremiah Easton Elias Colton Cameron Carson Robert Angel
13
+ Maverick Nicholas Dominic Jaxson Greyson Adam Ian Austin Santiago Jordan Cooper Brayden Roman Evan Ezekiel Xaviar Jose Jace
14
+ Jameson Leonardo Axel Everett Kayden Miles Sawyer Jason Emma Olivia Bartholomew Corey Danielle Eva Felicity
15
+ ]
16
+
17
+ NAMES_LAST = %w[
18
+ Smith Johnson Williams Brown Jones Miller Davis Wilson Anderson Taylor George Harrington Iverson Jackson Korby Levinson
19
+ ]
20
+
21
+ CITIES = [
22
+ 'Bellesville', 'Lombardia', 'Steepleton', 'Deerenstein', 'Schwartz', 'Hollandia', 'Saint Pete', 'Grandville', 'London',
23
+ 'Berlin', 'Elktown', 'Paris', 'Garrison', 'Muncy', 'St Louis',
24
+ ]
25
+
26
+ STATES = [ 'AK', 'AL', 'AR', 'AZ', 'CA', 'CO', 'CT', 'DC', 'DE', 'FL', 'GA',
27
+ 'HI', 'IA', 'ID', 'IL', 'IN', 'KS', 'KY', 'LA', 'MA', 'MD', 'ME',
28
+ 'MI', 'MN', 'MO', 'MS', 'MT', 'NC', 'ND', 'NE', 'NH', 'NJ', 'NM',
29
+ 'NV', 'NY', 'OH', 'OK', 'OR', 'PA', 'RI', 'SC', 'SD', 'TN', 'TX',
30
+ 'UT', 'VA', 'VT', 'WA', 'WI', 'WV', 'WY']
31
+
32
+ before_body do
33
+ contact_count = 1_000_000
34
+ # Make sure to pass Enumerator::Lazy constructor size (2nd) argument as it gets used by Glimmer DSL for LibUI
35
+ # to determine the number of rows in the table before generating all its data
36
+ @contacts = Enumerator::Lazy.new(contact_count.times, contact_count) do |yielder, index|
37
+ number = index + 1
38
+ first_name = NAMES_FIRST.sample
39
+ last_name = NAMES_LAST.sample
40
+ phone = 10.times.map { rand(10) }.yield_self { |numbers| [numbers[0..2], numbers[3..5], numbers[6..9]].map(&:join).join('-') }
41
+ city = CITIES.sample
42
+ state = STATES.sample
43
+
44
+ # Data will get lazy loaded into the table as the user scrolls through.
45
+ # After data is built, it is cached long-term, till updating table `cell_rows`.
46
+ yielder << Contact.new("#{first_name} #{last_name}", "#{first_name.downcase}#{number}@#{last_name.downcase}.com", phone, city, state)
47
+ end
48
+ end
49
+
50
+ body {
51
+ window("1,000,000 Lazy Loaded Contacts", 600, 700) {
52
+ margined true
53
+
54
+ vertical_box {
55
+ table {
56
+ text_column('Name')
57
+ text_column('Email')
58
+ text_column('Phone')
59
+ text_column('City')
60
+ text_column('State')
61
+
62
+ cell_rows @contacts
63
+ }
64
+ }
65
+ }
66
+ }
67
+ end
68
+
69
+ LazyTable.launch
Binary file
@@ -38,7 +38,7 @@ module Glimmer
38
38
 
39
39
  CUSTOM_LISTENER_NAMES = ['on_changed', 'on_edited']
40
40
 
41
- attr_reader :model_handler, :model, :table_params, :columns, :column_attributes
41
+ attr_reader :model_handler, :model, :table_params, :columns
42
42
 
43
43
  def initialize(keyword, parent, args, &block)
44
44
  @keyword = keyword
@@ -110,12 +110,12 @@ module Glimmer
110
110
 
111
111
  def expand_cell_row(cell_row)
112
112
  return cell_row if cell_row.nil?
113
- cell_row = expand_cell_row_from_model(cell_row) if !cell_row.is_a?(Array) && @column_attributes&.any?
113
+ cell_row = expand_cell_row_from_model(cell_row) if !cell_row.is_a?(Array) && column_attributes.any?
114
114
  cell_row.flatten(1)
115
115
  end
116
116
 
117
117
  def expand_cell_row_from_model(cell_row)
118
- @column_attributes.to_a.map {|attribute| cell_row.send(attribute) }
118
+ column_attributes.to_a.map {|attribute| cell_row.send(attribute) }
119
119
  end
120
120
 
121
121
  def editable(value = nil)
@@ -129,6 +129,10 @@ module Glimmer
129
129
  alias set_editable editable
130
130
  alias editable? editable
131
131
 
132
+ def column_attributes
133
+ @column_attributes ||= columns.select {|column| column.is_a?(Column)}.map(&:name).map(&:underscore)
134
+ end
135
+
132
136
  def data_bind_read(property, model_binding)
133
137
  if model_binding.binding_options[:column_attributes].is_a?(Array)
134
138
  @column_attributes = model_binding.binding_options[:column_attributes]
@@ -141,7 +145,7 @@ module Glimmer
141
145
  new_value = model_binding.evaluate_property
142
146
  if model_binding.binding_options[:column_attributes] || (!new_value.nil? && (!new_value.is_a?(String) || !new_value.empty?) && (!new_value.is_a?(Array) || !new_value.first.is_a?(Array)))
143
147
  @model_attribute_array_observer_registration&.deregister
144
- @model_attribute_array_observer_registration = model_attribute_observer.observe(new_value, @column_attributes, ignore_frozen: true, attribute_writer_type: [:attribute=, :set_attribute])
148
+ @model_attribute_array_observer_registration = model_attribute_observer.observe(new_value, column_attributes, ignore_frozen: true, attribute_writer_type: [:attribute=, :set_attribute])
145
149
  model_attribute_observer.add_dependent(model_attribute_observer_registration => @model_attribute_array_observer_registration)
146
150
  end
147
151
  # TODO look if multiple notifications are happening as a result of observing array and observing model binding
@@ -326,7 +330,7 @@ module Glimmer
326
330
  if cell_row.is_a?(Array)
327
331
  cell_row[compound_column_index_for(column)] = -1
328
332
  else
329
- attribute = @column_attributes[column]
333
+ attribute = column_attributes[column]
330
334
  cell_row.send("#{attribute}=", -1)
331
335
  end
332
336
  ::LibUI.new_table_value_int(old_value)
@@ -349,7 +353,7 @@ module Glimmer
349
353
  if table_cell_row.is_a?(Array)
350
354
  table_cell_row[column] = ::LibUI.table_value_string(val).to_s
351
355
  else
352
- attribute = @column_attributes[column]
356
+ attribute = column_attributes[column]
353
357
  table_cell_row.send("#{attribute}=", ::LibUI.table_value_string(val).to_s)
354
358
  end
355
359
  when Column::TextColorColumnProxy
@@ -358,7 +362,7 @@ module Glimmer
358
362
  table_cell_row[column] ||= []
359
363
  table_cell_row[column][0] = ::LibUI.table_value_string(val).to_s
360
364
  else
361
- attribute = @column_attributes[column]
365
+ attribute = column_attributes[column]
362
366
  table_cell_row.send("#{attribute}=", []) unless table_cell_row.send(attribute)
363
367
  table_cell_row.send(attribute)[0] = ::LibUI.table_value_string(val).to_s
364
368
  end
@@ -368,7 +372,7 @@ module Glimmer
368
372
  table_cell_row[column] ||= []
369
373
  table_cell_row[column][1] = ::LibUI.table_value_string(val).to_s
370
374
  else
371
- attribute = @column_attributes[column]
375
+ attribute = column_attributes[column]
372
376
  table_cell_row.send("#{attribute}=", []) unless table_cell_row.send(attribute)
373
377
  table_cell_row.send(attribute)[1] = ::LibUI.table_value_string(val).to_s
374
378
  end
@@ -379,7 +383,7 @@ module Glimmer
379
383
  if table_cell_row.is_a?(Array)
380
384
  table_cell_row[column] = ::LibUI.table_value_int(val).to_i == 1
381
385
  else
382
- attribute = @column_attributes[column]
386
+ attribute = column_attributes[column]
383
387
  table_cell_row.send("#{attribute}=", ::LibUI.table_value_int(val).to_i == 1)
384
388
  end
385
389
  when Column::CheckboxTextColumnProxy
@@ -388,7 +392,7 @@ module Glimmer
388
392
  table_cell_row[column] ||= []
389
393
  table_cell_row[column][0] = ::LibUI.table_value_int(val).to_i == 1
390
394
  else
391
- attribute = @column_attributes[column]
395
+ attribute = column_attributes[column]
392
396
  table_cell_row.send("#{attribute}=", []) unless table_cell_row.send(attribute)
393
397
  table_cell_row.send(attribute)[0] = ::LibUI.table_value_int(val).to_i == 1
394
398
  end
@@ -507,7 +511,7 @@ module Glimmer
507
511
  # TODO will this require that @cell_rows_observer is called with queue_main too to avoid issue with multiple immediate model updates breaking this?
508
512
  Glimmer::LibUI.queue_main do
509
513
  new_row = @columns&.select {|column| column.is_a?(Column)}&.map {|column| column.class.default_value}
510
- if new_row
514
+ if new_row && !@cell_rows.is_a?(Enumerator)
511
515
  @cell_rows << new_row
512
516
  @cell_rows.pop
513
517
  end
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.6.0
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Maleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-09 00:00:00.000000000 Z
11
+ date: 2023-01-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: glimmer
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 1.0.5
33
+ version: 1.0.7
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 1.0.5
40
+ version: 1.0.7
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: super_module
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -168,6 +168,48 @@ dependencies:
168
168
  - - "<"
169
169
  - !ruby/object:Gem::Version
170
170
  version: 3.0.0
171
+ - !ruby/object:Gem::Dependency
172
+ name: stringio
173
+ requirement: !ruby/object:Gem::Requirement
174
+ requirements:
175
+ - - '='
176
+ - !ruby/object:Gem::Version
177
+ version: 3.0.1
178
+ type: :development
179
+ prerelease: false
180
+ version_requirements: !ruby/object:Gem::Requirement
181
+ requirements:
182
+ - - '='
183
+ - !ruby/object:Gem::Version
184
+ version: 3.0.1
185
+ - !ruby/object:Gem::Dependency
186
+ name: psych
187
+ requirement: !ruby/object:Gem::Requirement
188
+ requirements:
189
+ - - '='
190
+ - !ruby/object:Gem::Version
191
+ version: 4.0.3
192
+ type: :development
193
+ prerelease: false
194
+ version_requirements: !ruby/object:Gem::Requirement
195
+ requirements:
196
+ - - '='
197
+ - !ruby/object:Gem::Version
198
+ version: 4.0.3
199
+ - !ruby/object:Gem::Dependency
200
+ name: json
201
+ requirement: !ruby/object:Gem::Requirement
202
+ requirements:
203
+ - - '='
204
+ - !ruby/object:Gem::Version
205
+ version: 2.6.1
206
+ type: :development
207
+ prerelease: false
208
+ version_requirements: !ruby/object:Gem::Requirement
209
+ requirements:
210
+ - - '='
211
+ - !ruby/object:Gem::Version
212
+ version: 2.6.1
171
213
  - !ruby/object:Gem::Dependency
172
214
  name: rspec
173
215
  requirement: !ruby/object:Gem::Requirement
@@ -348,6 +390,10 @@ files:
348
390
  - examples/grid.rb
349
391
  - examples/histogram.rb
350
392
  - examples/histogram2.rb
393
+ - examples/lazy_table.rb
394
+ - examples/lazy_table2.rb
395
+ - examples/lazy_table3.rb
396
+ - examples/lazy_table4.rb
351
397
  - examples/login.rb
352
398
  - examples/login2.rb
353
399
  - examples/login3.rb