glimmer-dsl-libui 0.4.8 → 0.4.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +32 -0
  3. data/README.md +1361 -461
  4. data/VERSION +1 -1
  5. data/examples/basic_table_button.rb +54 -30
  6. data/examples/basic_table_button2.rb +34 -0
  7. data/examples/basic_table_color.rb +104 -26
  8. data/examples/basic_table_color2.rb +2 -14
  9. data/examples/basic_table_color3.rb +37 -0
  10. data/examples/basic_table_image.rb +1 -1
  11. data/examples/basic_table_image2.rb +2 -14
  12. data/examples/basic_table_image3.rb +44 -0
  13. data/examples/basic_table_image_text.rb +1 -2
  14. data/examples/basic_table_image_text2.rb +2 -13
  15. data/examples/basic_table_image_text3.rb +44 -0
  16. data/examples/cpu_percentage.rb +36 -0
  17. data/examples/editable_table.rb +1 -1
  18. data/examples/form_table.rb +21 -17
  19. data/examples/form_table2.rb +104 -85
  20. data/examples/form_table3.rb +113 -0
  21. data/examples/form_table4.rb +110 -0
  22. data/examples/form_table5.rb +94 -0
  23. data/examples/meta_example.rb +6 -4
  24. data/examples/snake.rb +19 -10
  25. data/examples/snake2.rb +97 -0
  26. data/examples/tic_tac_toe.rb +1 -0
  27. data/examples/tic_tac_toe2.rb +84 -0
  28. data/glimmer-dsl-libui.gemspec +0 -0
  29. data/lib/glimmer/dsl/libui/control_expression.rb +2 -1
  30. data/lib/glimmer/dsl/libui/shape_expression.rb +2 -2
  31. data/lib/glimmer/dsl/libui/string_expression.rb +2 -1
  32. data/lib/glimmer/libui/attributed_string.rb +3 -2
  33. data/lib/glimmer/libui/control_proxy/checkbox_proxy.rb +1 -2
  34. data/lib/glimmer/libui/control_proxy/color_button_proxy.rb +1 -2
  35. data/lib/glimmer/libui/control_proxy/column/background_color_column_proxy.rb +4 -0
  36. data/lib/glimmer/libui/control_proxy/combobox_proxy.rb +1 -2
  37. data/lib/glimmer/libui/control_proxy/date_time_picker_proxy.rb +1 -2
  38. data/lib/glimmer/libui/control_proxy/editable_combobox_proxy.rb +1 -2
  39. data/lib/glimmer/libui/control_proxy/entry_proxy.rb +1 -2
  40. data/lib/glimmer/libui/control_proxy/font_button_proxy.rb +5 -1
  41. data/lib/glimmer/libui/control_proxy/menu_item_proxy/check_menu_item_proxy.rb +1 -2
  42. data/lib/glimmer/libui/control_proxy/menu_item_proxy/radio_menu_item_proxy.rb +1 -2
  43. data/lib/glimmer/libui/control_proxy/multiline_entry_proxy.rb +1 -2
  44. data/lib/glimmer/libui/control_proxy/radio_buttons_proxy.rb +1 -2
  45. data/lib/glimmer/libui/control_proxy/slider_proxy.rb +1 -2
  46. data/lib/glimmer/libui/control_proxy/spinbox_proxy.rb +1 -2
  47. data/lib/glimmer/libui/control_proxy/table_proxy.rb +95 -29
  48. data/lib/glimmer/libui/control_proxy.rb +4 -2
  49. data/lib/glimmer/libui/data_bindable.rb +34 -4
  50. data/lib/glimmer/libui/shape.rb +3 -2
  51. data/lib/glimmer/libui.rb +2 -2
  52. data/lib/glimmer-dsl-libui.rb +1 -0
  53. metadata +12 -2
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.8
1
+ 0.4.12
@@ -1,34 +1,58 @@
1
- # frozen_string_literal: true
2
-
3
1
  require 'glimmer-dsl-libui'
4
2
 
5
- include Glimmer
6
-
7
- data = [
8
- %w[cat meow delete],
9
- %w[dog woof delete],
10
- %w[chicken cock-a-doodle-doo delete],
11
- %w[horse neigh delete],
12
- %w[cow moo delete]
13
- ]
14
-
15
- window('Animal sounds', 400, 200) {
16
- horizontal_box {
17
- table {
18
- text_column('Animal')
19
- text_column('Description')
20
- button_column('Action') {
21
- on_clicked do |row|
22
- data.delete_at(row) # automatically deletes actual table row due to implicit data-binding
23
- end
3
+ class BasicTableButton
4
+ BasicAnimal = Struct.new(:name, :sound)
5
+
6
+ class Animal < BasicAnimal
7
+ def action
8
+ 'delete'
9
+ end
10
+ end
11
+
12
+ include Glimmer
13
+
14
+ attr_accessor :animals
15
+
16
+ def initialize
17
+ @animals = [
18
+ Animal.new('cat', 'meow'),
19
+ Animal.new('dog', 'woof'),
20
+ Animal.new('chicken', 'cock-a-doodle-doo'),
21
+ Animal.new('horse', 'neigh'),
22
+ Animal.new('cow', 'moo'),
23
+ ]
24
+ end
25
+
26
+ def launch
27
+ window('Animal sounds', 400, 200) {
28
+ horizontal_box {
29
+ table {
30
+ text_column('Animal')
31
+ text_column('Description')
32
+ button_column('Action') {
33
+ on_clicked do |row|
34
+ # Option 1: direct data deletion is the simpler solution
35
+ # @animals.delete_at(row) # automatically deletes actual table row due to explicit data-binding
36
+
37
+ # Option 2: cloning only to demonstrate table row deletion upon explicit setting of animals attribute (cloning is not recommended beyond demonstrating this point)
38
+ new_animals = @animals.clone
39
+ new_animals.delete_at(row)
40
+ self.animals = new_animals # automatically loses deleted table row due to explicit data-binding
41
+ end
42
+ }
43
+
44
+
45
+ cell_rows <= [self, :animals, column_attributes: {'Animal' => :name, 'Description' => :sound}]
46
+
47
+ # explicit unidirectional data-binding of table cell_rows to self.animals
48
+ on_changed do |row, type, row_data|
49
+ puts "Row #{row} #{type}: #{row_data}"
50
+ $stdout.flush
51
+ end
52
+ }
24
53
  }
54
+ }.show
55
+ end
56
+ end
25
57
 
26
- cell_rows data # implicit data-binding
27
-
28
- on_changed do |row, type, row_data|
29
- puts "Row #{row} #{type}: #{row_data}"
30
- $stdout.flush
31
- end
32
- }
33
- }
34
- }.show
58
+ BasicTableButton.new.launch
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'glimmer-dsl-libui'
4
+
5
+ include Glimmer
6
+
7
+ data = [
8
+ %w[cat meow delete],
9
+ %w[dog woof delete],
10
+ %w[chicken cock-a-doodle-doo delete],
11
+ %w[horse neigh delete],
12
+ %w[cow moo delete]
13
+ ]
14
+
15
+ window('Animal sounds', 400, 200) {
16
+ horizontal_box {
17
+ table {
18
+ text_column('Animal')
19
+ text_column('Description')
20
+ button_column('Action') {
21
+ on_clicked do |row|
22
+ data.delete_at(row) # automatically deletes actual table row due to implicit data-binding
23
+ end
24
+ }
25
+
26
+ cell_rows data # implicit data-binding
27
+
28
+ on_changed do |row, type, row_data|
29
+ puts "Row #{row} #{type}: #{row_data}"
30
+ $stdout.flush
31
+ end
32
+ }
33
+ }
34
+ }.show
@@ -1,29 +1,107 @@
1
- # frozen_string_literal: true
2
-
3
1
  require 'glimmer-dsl-libui'
4
2
 
5
- include Glimmer
6
-
7
- img = image(File.expand_path('../icons/glimmer.png', __dir__), 24, 24)
8
-
9
- data = [
10
- [['cat', :red] , ['meow', :blue] , [true, 'mammal', :green], [img, 'Glimmer', :dark_blue], {r: 255, g: 120, b: 0, a: 0.5}],
11
- [['dog', :yellow] , ['woof', {r: 240, g: 32, b: 32}] , [true, 'mammal', :green], [img, 'Glimmer', :dark_blue], :skyblue],
12
- [['chicken', :beige], ['cock-a-doodle-doo', :blue] , [false, 'mammal', :red] , [img, 'Glimmer', :beige], {r: 5, g: 120, b: 110}],
13
- [['horse', :purple] , ['neigh', {r: 240, g: 32, b: 32}], [true, 'mammal', :green], [img, 'Glimmer', :dark_blue], '13a1fb'],
14
- [['cow', :gray] , ['moo', :blue] , [true, 'mammal', :green], [img, 'Glimmer', :brown], 0x12ff02]
15
- ]
16
-
17
- window('Animals', 500, 200) {
18
- horizontal_box {
19
- table {
20
- text_color_column('Animal')
21
- text_color_column('Sound')
22
- checkbox_text_color_column('Description')
23
- image_text_color_column('GUI')
24
- background_color_column('Mammal')
3
+ class BasicTableColor
4
+ Animal = Struct.new(:name, :sound, :mammal)
5
+
6
+ class AnimalPresenter < Animal
7
+ def name_color
8
+ color = case name
9
+ when 'cat'
10
+ :red
11
+ when 'dog'
12
+ :yellow
13
+ when 'chicken'
14
+ :beige
15
+ when 'horse'
16
+ :purple
17
+ when 'cow'
18
+ :gray
19
+ end
20
+ [name, color]
21
+ end
22
+
23
+ def sound_color
24
+ color = case name
25
+ when 'cat', 'chicken', 'cow'
26
+ :blue
27
+ when 'dog', 'horse'
28
+ {r: 240, g: 32, b: 32}
29
+ end
30
+ [sound, color]
31
+ end
32
+
33
+ def mammal_description_color
34
+ color = case name
35
+ when 'cat', 'dog', 'horse', 'cow'
36
+ :green
37
+ when 'chicken'
38
+ :red
39
+ end
40
+ [mammal, 'mammal', color]
41
+ end
42
+
43
+ def image_description_color
44
+ color = case name
45
+ when 'cat', 'dog', 'horse'
46
+ :dark_blue
47
+ when 'chicken'
48
+ :beige
49
+ when 'cow'
50
+ :brown
51
+ end
52
+ [img, 'Glimmer', color]
53
+ end
54
+
55
+ def img
56
+ # scale image to 24x24 (can be passed as file path String only instead of Array to avoid scaling)
57
+ [File.expand_path('../icons/glimmer.png', __dir__), 24, 24]
58
+ end
59
+
60
+ def background_color
61
+ case name
62
+ when 'cat'
63
+ {r: 255, g: 120, b: 0, a: 0.5}
64
+ when 'dog'
65
+ :skyblue
66
+ when 'chicken'
67
+ {r: 5, g: 120, b: 110}
68
+ when 'horse'
69
+ '#13a1fb'
70
+ when 'cow'
71
+ 0x12ff02
72
+ end
73
+ end
74
+ end
75
+
76
+ include Glimmer
77
+
78
+ attr_accessor :animals
79
+
80
+ def initialize
81
+ @animals = [
82
+ AnimalPresenter.new('cat', 'meow', true),
83
+ AnimalPresenter.new('dog', 'woof', true),
84
+ AnimalPresenter.new('chicken', 'cock-a-doodle-doo', false),
85
+ AnimalPresenter.new('horse', 'neigh', true),
86
+ AnimalPresenter.new('cow', 'moo', true),
87
+ ]
88
+ end
89
+
90
+ def launch
91
+ window('Animals', 500, 200) {
92
+ horizontal_box {
93
+ table {
94
+ text_color_column('Animal')
95
+ text_color_column('Sound')
96
+ checkbox_text_color_column('Description')
97
+ image_text_color_column('GUI')
98
+ background_color_column # must always be the last column and always expects data-binding model attribute `background_color` when binding to Array of models
99
+
100
+ cell_rows <= [self, :animals, column_attributes: {'Animal' => :name_color, 'Sound' => :sound_color, 'Description' => :mammal_description_color, 'GUI' => :image_description_color}]
101
+ }
102
+ }
103
+ }.show
104
+ end
105
+ end
25
106
 
26
- cell_rows data
27
- }
28
- }
29
- }.show
107
+ BasicTableColor.new.launch
@@ -1,20 +1,8 @@
1
- # frozen_string_literal: true
2
-
3
1
  require 'glimmer-dsl-libui'
4
- require 'chunky_png'
5
2
 
6
3
  include Glimmer
7
4
 
8
- f = File.open(File.expand_path('../icons/glimmer.png', __dir__))
9
- canvas = ChunkyPNG::Canvas.from_io(f)
10
- f.close
11
- canvas.resample_nearest_neighbor!(24, 24)
12
- data = canvas.to_rgba_stream
13
- width = canvas.width
14
- height = canvas.height
15
- img = image {
16
- image_part(data, width, height, width * 4)
17
- }
5
+ img = [File.expand_path('../icons/glimmer.png', __dir__), 24, 24] # scales image to 24x24 (can be passed as file path String only instead of Array to avoid scaling)
18
6
 
19
7
  data = [
20
8
  [['cat', :red] , ['meow', :blue] , [true, 'mammal', :green], [img, 'Glimmer', :dark_blue], {r: 255, g: 120, b: 0, a: 0.5}],
@@ -31,7 +19,7 @@ window('Animals', 500, 200) {
31
19
  text_color_column('Sound')
32
20
  checkbox_text_color_column('Description')
33
21
  image_text_color_column('GUI')
34
- background_color_column('Mammal')
22
+ background_color_column # must be the last column
35
23
 
36
24
  cell_rows data
37
25
  }
@@ -0,0 +1,37 @@
1
+ require 'glimmer-dsl-libui'
2
+ require 'chunky_png'
3
+
4
+ include Glimmer
5
+
6
+ f = File.open(File.expand_path('../icons/glimmer.png', __dir__))
7
+ canvas = ChunkyPNG::Canvas.from_io(f)
8
+ f.close
9
+ canvas.resample_nearest_neighbor!(24, 24)
10
+ data = canvas.to_rgba_stream
11
+ width = canvas.width
12
+ height = canvas.height
13
+ img = image {
14
+ image_part(data, width, height, width * 4)
15
+ }
16
+
17
+ data = [
18
+ [['cat', :red] , ['meow', :blue] , [true, 'mammal', :green], [img, 'Glimmer', :dark_blue], {r: 255, g: 120, b: 0, a: 0.5}],
19
+ [['dog', :yellow] , ['woof', {r: 240, g: 32, b: 32}] , [true, 'mammal', :green], [img, 'Glimmer', :dark_blue], :skyblue],
20
+ [['chicken', :beige], ['cock-a-doodle-doo', :blue] , [false, 'mammal', :red] , [img, 'Glimmer', :beige], {r: 5, g: 120, b: 110}],
21
+ [['horse', :purple] , ['neigh', {r: 240, g: 32, b: 32}], [true, 'mammal', :green], [img, 'Glimmer', :dark_blue], '13a1fb'],
22
+ [['cow', :gray] , ['moo', :blue] , [true, 'mammal', :green], [img, 'Glimmer', :brown], 0x12ff02]
23
+ ]
24
+
25
+ window('Animals', 500, 200) {
26
+ horizontal_box {
27
+ table {
28
+ text_color_column('Animal')
29
+ text_color_column('Sound')
30
+ checkbox_text_color_column('Description')
31
+ image_text_color_column('GUI')
32
+ background_color_column('Mammal')
33
+
34
+ cell_rows data
35
+ }
36
+ }
37
+ }.show
@@ -12,7 +12,7 @@ IMAGE_ROWS = []
12
12
  50.times do |i|
13
13
  url = format('https://www.ghibli.jp/gallery/thumb-redturtle%03d.png', (i + 1))
14
14
  puts "Processing Image: #{url}"; $stdout.flush # for Windows
15
- IMAGE_ROWS << [image(url)] # array of one column cell
15
+ IMAGE_ROWS << [url] # array of one column cell
16
16
  rescue StandardError => e
17
17
  warn url, e.message
18
18
  end
@@ -4,8 +4,6 @@
4
4
  # This example displays images that can be freely downloaded from the Studio Ghibli website.
5
5
 
6
6
  require 'glimmer-dsl-libui'
7
- require 'chunky_png'
8
- require 'open-uri'
9
7
 
10
8
  include Glimmer
11
9
 
@@ -13,18 +11,8 @@ IMAGE_ROWS = []
13
11
 
14
12
  50.times do |i|
15
13
  url = format('https://www.ghibli.jp/gallery/thumb-redturtle%03d.png', (i + 1))
16
- puts "Processing Image: #{url}"
17
- $stdout.flush # for Windows
18
- f = URI.open(url)
19
- canvas = ChunkyPNG::Canvas.from_io(f)
20
- f.close
21
- data = canvas.to_rgba_stream
22
- width = canvas.width
23
- height = canvas.height
24
- img = image {
25
- image_part(data, width, height, width * 4)
26
- }
27
- IMAGE_ROWS << [img] # array of one column cell
14
+ puts "Processing Image: #{url}"; $stdout.flush # for Windows
15
+ IMAGE_ROWS << [image(url)] # array of one column cell
28
16
  rescue StandardError => e
29
17
  warn url, e.message
30
18
  end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ # NOTE:
4
+ # This example displays images that can be freely downloaded from the Studio Ghibli website.
5
+
6
+ require 'glimmer-dsl-libui'
7
+ require 'chunky_png'
8
+ require 'open-uri'
9
+
10
+ include Glimmer
11
+
12
+ IMAGE_ROWS = []
13
+
14
+ 50.times do |i|
15
+ url = format('https://www.ghibli.jp/gallery/thumb-redturtle%03d.png', (i + 1))
16
+ puts "Processing Image: #{url}"
17
+ $stdout.flush # for Windows
18
+ f = URI.open(url)
19
+ canvas = ChunkyPNG::Canvas.from_io(f)
20
+ f.close
21
+ data = canvas.to_rgba_stream
22
+ width = canvas.width
23
+ height = canvas.height
24
+ img = image {
25
+ image_part(data, width, height, width * 4)
26
+ }
27
+ IMAGE_ROWS << [img] # array of one column cell
28
+ rescue StandardError => e
29
+ warn url, e.message
30
+ end
31
+
32
+ window('The Red Turtle', 310, 350, false) {
33
+ horizontal_box {
34
+ table {
35
+ image_column('www.ghibli.jp/works/red-turtle')
36
+
37
+ cell_rows IMAGE_ROWS
38
+ }
39
+ }
40
+
41
+ on_closing do
42
+ puts 'Bye Bye'
43
+ end
44
+ }.show
@@ -13,8 +13,7 @@ IMAGE_ROWS = []
13
13
  url = format('https://www.ghibli.jp/gallery/thumb-redturtle%03d.png', (i + 1))
14
14
  puts "Processing Image: #{url}"; $stdout.flush # for Windows
15
15
  text = url.sub('https://www.ghibli.jp/gallery/thumb-redturtle', '').sub('.png', '')
16
- img = image(url)
17
- IMAGE_ROWS << [[img, text], [img, text]] # cell values are dual-element arrays
16
+ IMAGE_ROWS << [[url, text], [url, text]] # cell values are dual-element arrays
18
17
  rescue StandardError => e
19
18
  warn url, e.message
20
19
  end
@@ -4,8 +4,6 @@
4
4
  # This example displays images that can be freely downloaded from the Studio Ghibli website.
5
5
 
6
6
  require 'glimmer-dsl-libui'
7
- require 'chunky_png'
8
- require 'open-uri'
9
7
 
10
8
  include Glimmer
11
9
 
@@ -13,18 +11,9 @@ IMAGE_ROWS = []
13
11
 
14
12
  5.times do |i|
15
13
  url = format('https://www.ghibli.jp/gallery/thumb-redturtle%03d.png', (i + 1))
16
- puts "Processing Image: #{url}"
17
- $stdout.flush # for Windows
18
- f = URI.open(url)
19
- canvas = ChunkyPNG::Canvas.from_io(f)
20
- f.close
21
- data = canvas.to_rgba_stream
22
- width = canvas.width
23
- height = canvas.height
24
- img = image {
25
- image_part(data, width, height, width * 4)
26
- }
14
+ puts "Processing Image: #{url}"; $stdout.flush # for Windows
27
15
  text = url.sub('https://www.ghibli.jp/gallery/thumb-redturtle', '').sub('.png', '')
16
+ img = image(url)
28
17
  IMAGE_ROWS << [[img, text], [img, text]] # cell values are dual-element arrays
29
18
  rescue StandardError => e
30
19
  warn url, e.message
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ # NOTE:
4
+ # This example displays images that can be freely downloaded from the Studio Ghibli website.
5
+
6
+ require 'glimmer-dsl-libui'
7
+ require 'chunky_png'
8
+ require 'open-uri'
9
+
10
+ include Glimmer
11
+
12
+ IMAGE_ROWS = []
13
+
14
+ 5.times do |i|
15
+ url = format('https://www.ghibli.jp/gallery/thumb-redturtle%03d.png', (i + 1))
16
+ puts "Processing Image: #{url}"
17
+ $stdout.flush # for Windows
18
+ f = URI.open(url)
19
+ canvas = ChunkyPNG::Canvas.from_io(f)
20
+ f.close
21
+ data = canvas.to_rgba_stream
22
+ width = canvas.width
23
+ height = canvas.height
24
+ img = image {
25
+ image_part(data, width, height, width * 4)
26
+ }
27
+ text = url.sub('https://www.ghibli.jp/gallery/thumb-redturtle', '').sub('.png', '')
28
+ IMAGE_ROWS << [[img, text], [img, text]] # cell values are dual-element arrays
29
+ rescue StandardError => e
30
+ warn url, e.message
31
+ end
32
+
33
+ window('The Red Turtle', 670, 350) {
34
+ horizontal_box {
35
+ table {
36
+ image_text_column('image/number')
37
+ image_text_column('image/number (editable)') {
38
+ editable true
39
+ }
40
+
41
+ cell_rows IMAGE_ROWS
42
+ }
43
+ }
44
+ }.show
@@ -0,0 +1,36 @@
1
+ require 'glimmer-dsl-libui'
2
+ require 'bigdecimal'
3
+
4
+ include Glimmer
5
+
6
+ data = [
7
+ ['CPU', '0%', 0],
8
+ ]
9
+
10
+ Glimmer::LibUI.timer(1) do
11
+ cpu_percentage_value = nil
12
+ if OS.windows?
13
+ cpu_percentage_raw_value = `wmic cpu get loadpercentage`
14
+ cpu_percentage_value = cpu_percentage_raw_value.split("\n")[2].to_i
15
+ elsif OS.mac?
16
+ cpu_percentage_value = `ps -A -o %cpu | awk '{s+=$1} END {print s}'`.to_i
17
+ elsif OS.linux?
18
+ stats = `top -n 1`
19
+ idle_percentage = stats.split("\n")[2].match(/ni,.* (.*) .*id/)[1]
20
+ cpu_percentage_value = (BigDecimal(100) - BigDecimal(idle_percentage)).to_i
21
+ end
22
+ data[0][1] = "#{cpu_percentage_value}%"
23
+ data[0][2] = cpu_percentage_value
24
+ end
25
+
26
+ window('CPU Percentage', 400, 200) {
27
+ vertical_box {
28
+ table {
29
+ text_column('Name')
30
+ text_column('Value')
31
+ progress_bar_column('Percentage')
32
+
33
+ cell_rows data # implicit data-binding
34
+ }
35
+ }
36
+ }.show
@@ -18,8 +18,8 @@ window('Editable animal sounds', 300, 200) {
18
18
  text_column('Animal')
19
19
  text_column('Description')
20
20
 
21
- cell_rows data
22
21
  editable true
22
+ cell_rows data
23
23
 
24
24
  on_changed do |row, type, row_data| # fires on all changes (even ones happening through data array)
25
25
  puts "Row #{row} #{type}: #{row_data}"
@@ -1,17 +1,19 @@
1
1
  require 'glimmer-dsl-libui'
2
2
 
3
3
  class FormTable
4
+ Contact = Struct.new(:name, :email, :phone, :city, :state)
5
+
4
6
  include Glimmer
5
7
 
6
- attr_accessor :name, :email, :phone, :city, :state, :filter_value
8
+ attr_accessor :contacts, :name, :email, :phone, :city, :state, :filter_value
7
9
 
8
10
  def initialize
9
- @data = [
10
- ['Lisa Sky', 'lisa@sky.com', '720-523-4329', 'Denver', 'CO', '80014'],
11
- ['Jordan Biggins', 'jordan@biggins.com', '617-528-5399', 'Boston', 'MA', '02101'],
12
- ['Mary Glass', 'mary@glass.com', '847-589-8788', 'Elk Grove Village', 'IL', '60007'],
13
- ['Darren McGrath', 'darren@mcgrath.com', '206-539-9283', 'Seattle', 'WA', '98101'],
14
- ['Melody Hanheimer', 'melody@hanheimer.com', '213-493-8274', 'Los Angeles', 'CA', '90001'],
11
+ @contacts = [
12
+ Contact.new('Lisa Sky', 'lisa@sky.com', '720-523-4329', 'Denver', 'CO'),
13
+ Contact.new('Jordan Biggins', 'jordan@biggins.com', '617-528-5399', 'Boston', 'MA'),
14
+ Contact.new('Mary Glass', 'mary@glass.com', '847-589-8788', 'Elk Grove Village', 'IL'),
15
+ Contact.new('Darren McGrath', 'darren@mcgrath.com', '206-539-9283', 'Seattle', 'WA'),
16
+ Contact.new('Melody Hanheimer', 'melody@hanheimer.com', '213-493-8274', 'Los Angeles', 'CA'),
15
17
  ]
16
18
  end
17
19
 
@@ -25,7 +27,7 @@ class FormTable
25
27
 
26
28
  entry {
27
29
  label 'Name'
28
- text <=> [self, :name]
30
+ text <=> [self, :name] # bidirectional data-binding between entry text and self.name
29
31
  }
30
32
 
31
33
  entry {
@@ -57,8 +59,8 @@ class FormTable
57
59
  if new_row.include?('')
58
60
  msg_box_error(w, 'Validation Error!', 'All fields are required! Please make sure to enter a value for all fields.')
59
61
  else
60
- @data << new_row # automatically inserts a row into the table due to implicit data-binding
61
- @unfiltered_data = @data.dup
62
+ @contacts << Contact.new(*new_row) # automatically inserts a row into the table due to explicit data-binding
63
+ @unfiltered_contacts = @contacts.dup
62
64
  self.name = '' # automatically clears name entry through explicit data-binding
63
65
  self.email = ''
64
66
  self.phone = ''
@@ -70,16 +72,17 @@ class FormTable
70
72
 
71
73
  search_entry {
72
74
  stretchy false
73
- text <=> [self, :filter_value, # bidirectional data-binding of text to self.filter_value with after_write option
75
+ # bidirectional data-binding of text to self.filter_value with after_write option
76
+ text <=> [self, :filter_value,
74
77
  after_write: ->(filter_value) { # execute after write to self.filter_value
75
- @unfiltered_data ||= @data.dup
78
+ @unfiltered_contacts ||= @contacts.dup
76
79
  # Unfilter first to remove any previous filters
77
- @data.replace(@unfiltered_data) # affects table indirectly through implicit data-binding
80
+ self.contacts = @unfiltered_contacts.dup # affects table indirectly through explicit data-binding
78
81
  # Now, apply filter if entered
79
82
  unless filter_value.empty?
80
- @data.filter! do |row_data| # affects table indirectly through implicit data-binding
81
- row_data.any? do |cell|
82
- cell.to_s.downcase.include?(filter_value.downcase)
83
+ self.contacts = @contacts.filter do |contact| # affects table indirectly through explicit data-binding
84
+ contact.members.any? do |attribute|
85
+ contact[attribute].to_s.downcase.include?(filter_value.downcase)
83
86
  end
84
87
  end
85
88
  end
@@ -94,7 +97,8 @@ class FormTable
94
97
  text_column('City')
95
98
  text_column('State')
96
99
 
97
- cell_rows @data # implicit data-binding
100
+ editable true
101
+ cell_rows <=> [self, :contacts] # explicit data-binding to Model Array
98
102
 
99
103
  on_changed do |row, type, row_data|
100
104
  puts "Row #{row} #{type}: #{row_data}"