glimmer-dsl-libui 0.4.13 → 0.4.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +28 -0
  3. data/README.md +102 -47
  4. data/VERSION +1 -1
  5. data/bin/girb +0 -0
  6. data/examples/basic_image.rb +5 -3
  7. data/examples/basic_image2.rb +1 -3
  8. data/examples/basic_image3.rb +3 -3
  9. data/examples/basic_image4.rb +0 -3
  10. data/examples/basic_image5.rb +0 -2
  11. data/examples/basic_table_button.rb +0 -1
  12. data/examples/cpu_percentage.rb +1 -1
  13. data/examples/editable_column_table.rb +5 -0
  14. data/examples/form_table.rb +10 -4
  15. data/examples/form_table2.rb +12 -6
  16. data/examples/form_table3.rb +9 -3
  17. data/examples/form_table4.rb +9 -3
  18. data/examples/form_table5.rb +9 -3
  19. data/examples/meta_example.rb +3 -1
  20. data/glimmer-dsl-libui.gemspec +0 -0
  21. data/icons/blank.png +0 -0
  22. data/lib/glimmer/libui/attributed_string.rb +17 -8
  23. data/lib/glimmer/libui/control_proxy/area_proxy.rb +17 -17
  24. data/lib/glimmer/libui/control_proxy/box.rb +1 -0
  25. data/lib/glimmer/libui/control_proxy/column/background_color_column_proxy.rb +6 -0
  26. data/lib/glimmer/libui/control_proxy/column/button_column_proxy.rb +6 -28
  27. data/lib/glimmer/libui/control_proxy/column/checkbox_column_proxy.rb +6 -0
  28. data/lib/glimmer/libui/control_proxy/column/checkbox_text_color_column_proxy.rb +6 -0
  29. data/lib/glimmer/libui/control_proxy/column/checkbox_text_column_proxy.rb +6 -0
  30. data/lib/glimmer/libui/control_proxy/column/image_column_proxy.rb +6 -0
  31. data/lib/glimmer/libui/control_proxy/column/image_text_color_column_proxy.rb +6 -0
  32. data/lib/glimmer/libui/control_proxy/column/image_text_column_proxy.rb +6 -0
  33. data/lib/glimmer/libui/control_proxy/column/progress_bar_column_proxy.rb +6 -0
  34. data/lib/glimmer/libui/control_proxy/column/text_color_column_proxy.rb +6 -0
  35. data/lib/glimmer/libui/control_proxy/column/text_column_proxy.rb +6 -0
  36. data/lib/glimmer/libui/control_proxy/column.rb +7 -0
  37. data/lib/glimmer/libui/control_proxy/form_proxy.rb +1 -0
  38. data/lib/glimmer/libui/control_proxy/image_proxy.rb +77 -10
  39. data/lib/glimmer/libui/control_proxy/menu_item_proxy/quit_menu_item_proxy.rb +18 -8
  40. data/lib/glimmer/libui/control_proxy/open_type_features_proxy.rb +11 -2
  41. data/lib/glimmer/libui/control_proxy/open_type_tag_proxy.rb +2 -0
  42. data/lib/glimmer/libui/control_proxy/path_proxy.rb +2 -0
  43. data/lib/glimmer/libui/control_proxy/table_proxy.rb +25 -14
  44. data/lib/glimmer/libui/control_proxy/text_proxy.rb +2 -0
  45. data/lib/glimmer/libui/control_proxy/window_proxy.rb +34 -35
  46. data/lib/glimmer/libui/control_proxy.rb +45 -9
  47. data/lib/glimmer/libui/shape.rb +1 -0
  48. data/lib/glimmer/libui.rb +1 -0
  49. data/lib/glimmer-dsl-libui.rb +6 -0
  50. metadata +20 -5
@@ -1,7 +1,7 @@
1
1
  require 'glimmer-dsl-libui'
2
2
 
3
3
  class FormTable
4
- Contact = Struct.new(:name, :email, :phone, :city, :state)
4
+ Contact = Struct.new(:name, :email, :phone, :city, :state_province)
5
5
 
6
6
  include Glimmer
7
7
 
@@ -18,7 +18,7 @@ class FormTable
18
18
  end
19
19
 
20
20
  def launch
21
- window('Contacts', 600, 600) { |w|
21
+ window('Contacts', 600, 600) {
22
22
  margined true
23
23
 
24
24
  vertical_box {
@@ -56,8 +56,8 @@ class FormTable
56
56
 
57
57
  on_clicked do
58
58
  new_row = [name, email, phone, city, state]
59
- if new_row.include?('')
60
- msg_box_error(w, 'Validation Error!', 'All fields are required! Please make sure to enter a value for all fields.')
59
+ if new_row.map(&:to_s).include?('')
60
+ msg_box_error('Validation Error!', 'All fields are required! Please make sure to enter a value for all fields.')
61
61
  else
62
62
  @contacts << Contact.new(*new_row) # automatically inserts a row into the table due to implicit data-binding
63
63
  @unfiltered_contacts = @contacts.dup
@@ -95,13 +95,19 @@ class FormTable
95
95
  text_column('Email')
96
96
  text_column('Phone')
97
97
  text_column('City')
98
- text_column('State/Province')
98
+ text_column('State')
99
99
 
100
100
  editable true
101
- cell_rows <=> [self, :contacts, column_attributes: {'State/Province' => :state}] # explicit data-binding to Model Array with column_attributes mapping for a specific column
101
+ cell_rows <=> [self, :contacts, column_attributes: {'State' => :state_province}] # explicit data-binding to Model Array with column_attributes mapping for a specific column
102
102
 
103
103
  on_changed do |row, type, row_data|
104
104
  puts "Row #{row} #{type}: #{row_data}"
105
+ $stdout.flush # for Windows
106
+ end
107
+
108
+ on_edited do |row, row_data| # only fires on direct table editing
109
+ puts "Row #{row} edited: #{row_data}"
110
+ $stdout.flush # for Windows
105
111
  end
106
112
  }
107
113
  }
@@ -19,7 +19,7 @@ class FormTable
19
19
  end
20
20
 
21
21
  def launch
22
- window('Contacts', 600, 600) { |w|
22
+ window('Contacts', 600, 600) {
23
23
  margined true
24
24
 
25
25
  vertical_box {
@@ -57,8 +57,8 @@ class FormTable
57
57
 
58
58
  on_clicked do
59
59
  new_row = [name, email, phone, city, state]
60
- if new_row.include?('')
61
- msg_box_error(w, 'Validation Error!', 'All fields are required! Please make sure to enter a value for all fields.')
60
+ if new_row.map(&:to_s).include?('')
61
+ msg_box_error('Validation Error!', 'All fields are required! Please make sure to enter a value for all fields.')
62
62
  else
63
63
  @contacts << Contact.new(*new_row) # automatically inserts a row into the table due to implicit data-binding
64
64
  @unfiltered_contacts = @contacts.dup
@@ -103,6 +103,12 @@ class FormTable
103
103
 
104
104
  on_changed do |row, type, row_data|
105
105
  puts "Row #{row} #{type}: #{row_data}"
106
+ $stdout.flush # for Windows
107
+ end
108
+
109
+ on_edited do |row, row_data| # only fires on direct table editing
110
+ puts "Row #{row} edited: #{row_data}"
111
+ $stdout.flush # for Windows
106
112
  end
107
113
  }
108
114
  }
@@ -16,7 +16,7 @@ class FormTable
16
16
  end
17
17
 
18
18
  def launch
19
- window('Contacts', 600, 600) { |w|
19
+ window('Contacts', 600, 600) {
20
20
  margined true
21
21
 
22
22
  vertical_box {
@@ -54,8 +54,8 @@ class FormTable
54
54
 
55
55
  on_clicked do
56
56
  new_row = [name, email, phone, city, state]
57
- if new_row.include?('')
58
- msg_box_error(w, 'Validation Error!', 'All fields are required! Please make sure to enter a value for all fields.')
57
+ if new_row.map(&:to_s).include?('')
58
+ msg_box_error('Validation Error!', 'All fields are required! Please make sure to enter a value for all fields.')
59
59
  else
60
60
  data << new_row # automatically inserts a row into the table due to implicit data-binding
61
61
  @unfiltered_data = data.dup
@@ -100,6 +100,12 @@ class FormTable
100
100
 
101
101
  on_changed do |row, type, row_data|
102
102
  puts "Row #{row} #{type}: #{row_data}"
103
+ $stdout.flush # for Windows
104
+ end
105
+
106
+ on_edited do |row, row_data| # only fires on direct table editing
107
+ puts "Row #{row} edited: #{row_data}"
108
+ $stdout.flush # for Windows
103
109
  end
104
110
  }
105
111
  }
@@ -10,7 +10,7 @@ data = [
10
10
  ['Melody Hanheimer', 'melody@hanheimer.com', '213-493-8274', 'Los Angeles', 'CA'],
11
11
  ]
12
12
 
13
- window('Contacts', 600, 600) { |w|
13
+ window('Contacts', 600, 600) {
14
14
  margined true
15
15
 
16
16
  vertical_box {
@@ -43,8 +43,8 @@ window('Contacts', 600, 600) { |w|
43
43
 
44
44
  on_clicked do
45
45
  new_row = [@name_entry.text, @email_entry.text, @phone_entry.text, @city_entry.text, @state_entry.text]
46
- if new_row.include?('')
47
- msg_box_error(w, 'Validation Error!', 'All fields are required! Please make sure to enter a value for all fields.')
46
+ if new_row.map(&:to_s).include?('')
47
+ msg_box_error('Validation Error!', 'All fields are required! Please make sure to enter a value for all fields.')
48
48
  else
49
49
  data << new_row # automatically inserts a row into the table due to implicit data-binding
50
50
  @unfiltered_data = data.dup
@@ -88,6 +88,12 @@ window('Contacts', 600, 600) { |w|
88
88
 
89
89
  on_changed do |row, type, row_data|
90
90
  puts "Row #{row} #{type}: #{row_data}"
91
+ $stdout.flush # for Windows
92
+ end
93
+
94
+ on_edited do |row, row_data| # only fires on direct table editing
95
+ puts "Row #{row} edited: #{row_data}"
96
+ $stdout.flush # for Windows
91
97
  end
92
98
  }
93
99
  }
@@ -180,7 +180,9 @@ class MetaExample
180
180
  }
181
181
  button('Reset') {
182
182
  on_clicked do
183
- self.code_text = File.read(file_path_for(selected_example))
183
+ version_number = @version_spinbox.value == 1 ? '' : @version_spinbox.value
184
+ example = "#{selected_example}#{version_number}"
185
+ self.code_text = File.read(file_path_for(example))
184
186
  end
185
187
  }
186
188
  }
Binary file
data/icons/blank.png ADDED
Binary file
@@ -22,7 +22,6 @@
22
22
  require 'glimmer/libui/control_proxy'
23
23
  require 'glimmer/libui/control_proxy/area_proxy'
24
24
  require 'glimmer/libui/parent'
25
- require 'glimmer/libui/control_proxy/transformable'
26
25
  require 'glimmer/libui/data_bindable'
27
26
 
28
27
  module Glimmer
@@ -48,7 +47,7 @@ module Glimmer
48
47
  @string
49
48
  else
50
49
  @string = value
51
- redraw
50
+ request_auto_redraw
52
51
  end
53
52
  end
54
53
  alias string= string
@@ -59,7 +58,7 @@ module Glimmer
59
58
  @font
60
59
  else
61
60
  @font = value
62
- redraw
61
+ request_auto_redraw
63
62
  end
64
63
  end
65
64
  alias font= font
@@ -70,7 +69,7 @@ module Glimmer
70
69
  @color
71
70
  else
72
71
  @color = Glimmer::LibUI.interpret_color(value)
73
- redraw
72
+ request_auto_redraw
74
73
  end
75
74
  end
76
75
  alias color= color
@@ -81,7 +80,7 @@ module Glimmer
81
80
  @background
82
81
  else
83
82
  @background = Glimmer::LibUI.interpret_color(value)
84
- redraw
83
+ request_auto_redraw
85
84
  end
86
85
  end
87
86
  alias background= background
@@ -92,7 +91,7 @@ module Glimmer
92
91
  @underline
93
92
  else
94
93
  @underline = value
95
- redraw
94
+ request_auto_redraw
96
95
  end
97
96
  end
98
97
  alias underline= underline
@@ -103,7 +102,7 @@ module Glimmer
103
102
  @underline_color
104
103
  else
105
104
  @underline_color = value
106
- redraw
105
+ request_auto_redraw
107
106
  end
108
107
  end
109
108
  alias underline_color= underline_color
@@ -114,12 +113,21 @@ module Glimmer
114
113
  @open_type_features
115
114
  else
116
115
  @open_type_features = value
117
- redraw
116
+ request_auto_redraw
118
117
  end
119
118
  end
120
119
  alias open_type_features= open_type_features
121
120
  alias set_open_type_features open_type_features
122
121
 
122
+ def remove_open_type_features
123
+ return if @removing_open_type_features
124
+ @removing_open_type_features = true
125
+ @open_type_features&.destroy
126
+ @open_type_features = nil
127
+ request_auto_redraw
128
+ @removing_open_type_features = false
129
+ end
130
+
123
131
  def post_add_content(block = nil)
124
132
  block ||= @block
125
133
  block_result = block&.call
@@ -189,6 +197,7 @@ module Glimmer
189
197
  end
190
198
 
191
199
  def destroy
200
+ return if ControlProxy.main_window_proxy&.destroying?
192
201
  open_type_features.destroy unless open_type_features.nil?
193
202
  @parent_proxy&.children&.delete(self)
194
203
  end
@@ -36,9 +36,9 @@ module Glimmer
36
36
  attr_accessor :current_area_draw_params
37
37
  end
38
38
 
39
- LISTENERS = ['on_draw', 'on_mouse_event', 'on_mouse_move', 'on_mouse_down', 'on_mouse_up', 'on_mouse_drag_start', 'on_mouse_drag', 'on_mouse_drop', 'on_mouse_crossed', 'on_mouse_enter', 'on_mouse_exit', 'on_drag_broken', 'on_key_event', 'on_key_down', 'on_key_up']
39
+ CUSTOM_LISTENER_NAMES = ['on_draw', 'on_mouse_event', 'on_mouse_move', 'on_mouse_down', 'on_mouse_up', 'on_mouse_drag_start', 'on_mouse_drag', 'on_mouse_drop', 'on_mouse_crossed', 'on_mouse_enter', 'on_mouse_exit', 'on_drag_broken', 'on_key_event', 'on_key_down', 'on_key_up']
40
40
 
41
- LISTENER_ALIASES = {
41
+ CUSTOM_LISTENER_NAME_ALIASES = {
42
42
  on_drawn: 'on_draw',
43
43
  on_mouse_moved: 'on_mouse_move',
44
44
  on_mouse_drag_started: 'on_mouse_drag_start',
@@ -105,7 +105,7 @@ module Glimmer
105
105
 
106
106
  def draw(area_draw_params)
107
107
  children.dup.each {|child| child.draw(area_draw_params)}
108
- on_draw.each {|listener| listener.call(area_draw_params)}
108
+ notify_custom_listeners('on_draw', area_draw_params)
109
109
  end
110
110
 
111
111
  def redraw
@@ -156,37 +156,37 @@ module Glimmer
156
156
  @area_handler.MouseEvent = fiddle_closure_block_caller(0, [1, 1, 1]) do |_, _, area_mouse_event|
157
157
  area_mouse_event = ::LibUI::FFI::AreaMouseEvent.new(area_mouse_event)
158
158
  area_mouse_event = area_mouse_event_hash(area_mouse_event)
159
- on_mouse_event.each { |listener| listener.call(area_mouse_event)}
160
- on_mouse_move.each { |listener| listener.call(area_mouse_event)} if area_mouse_event[:x].between?(0, area_mouse_event[:area_width]) && area_mouse_event[:y].between?(0, area_mouse_event[:area_height])
159
+ notify_custom_listeners('on_mouse_event', area_mouse_event)
160
+ notify_custom_listeners('on_mouse_move', area_mouse_event) if area_mouse_event[:x].between?(0, area_mouse_event[:area_width]) && area_mouse_event[:y].between?(0, area_mouse_event[:area_height])
161
161
  unless @last_area_mouse_event.nil?
162
- on_mouse_down.each { |listener| listener.call(area_mouse_event)} if area_mouse_event[:down] > 0 && @last_area_mouse_event[:down] == 0
163
- on_mouse_up.each { |listener| listener.call(area_mouse_event)} if area_mouse_event[:up] > 0 && @last_area_mouse_event[:up] == 0
164
- on_mouse_drag_start.each { |listener| listener.call(area_mouse_event)} if area_mouse_event[:held] > 0 && @last_area_mouse_event[:held] == 0
165
- on_mouse_drag.each { |listener| listener.call(area_mouse_event)} if area_mouse_event[:held] > 0
166
- on_mouse_drop.each { |listener| listener.call(area_mouse_event)} if area_mouse_event[:held] == 0 && @last_area_mouse_event[:held] > 0
162
+ notify_custom_listeners('on_mouse_down', area_mouse_event) if area_mouse_event[:down] > 0 && @last_area_mouse_event[:down] == 0
163
+ notify_custom_listeners('on_mouse_up', area_mouse_event) if area_mouse_event[:up] > 0 && @last_area_mouse_event[:up] == 0
164
+ notify_custom_listeners('on_mouse_drag_start', area_mouse_event) if area_mouse_event[:held] > 0 && @last_area_mouse_event[:held] == 0
165
+ notify_custom_listeners('on_mouse_drag', area_mouse_event) if area_mouse_event[:held] > 0
166
+ notify_custom_listeners('on_mouse_drop', area_mouse_event) if area_mouse_event[:held] == 0 && @last_area_mouse_event[:held] > 0
167
167
  end
168
168
  @last_area_mouse_event = area_mouse_event
169
169
  end
170
170
  @area_handler.MouseCrossed = fiddle_closure_block_caller(0, [1, 1, 4]) do |_, _, left|
171
171
  left = Glimmer::LibUI.integer_to_boolean(left)
172
- on_mouse_crossed.each { |listener| listener.call(left) }
172
+ notify_custom_listeners('on_mouse_crossed', left)
173
173
  if left
174
- on_mouse_exit.each { |listener| listener.call(left) }
174
+ notify_custom_listeners('on_mouse_exit', left)
175
175
  else
176
- on_mouse_enter.each { |listener| listener.call(left) }
176
+ notify_custom_listeners('on_mouse_enter', left)
177
177
  end
178
178
  end
179
179
  @area_handler.DragBroken = fiddle_closure_block_caller(0, [1, 1]) do |_, _|
180
- on_drag_broken.each { |listener| listener.call }
180
+ notify_custom_listeners('on_drag_broken')
181
181
  end
182
182
  @area_handler.KeyEvent = fiddle_closure_block_caller(0, [1, 1, 1]) do |_, _, area_key_event|
183
183
  area_key_event = ::LibUI::FFI::AreaKeyEvent.new(area_key_event)
184
184
  area_key_event = area_key_event_hash(area_key_event)
185
- on_key_event.each { |listener| listener.call(area_key_event) }
185
+ notify_custom_listeners('on_key_event', area_key_event)
186
186
  if area_key_event[:up]
187
- on_key_up.each { |listener| listener.call(area_key_event) }
187
+ notify_custom_listeners('on_key_up', area_key_event)
188
188
  else
189
- on_key_down.each { |listener| listener.call(area_key_event) }
189
+ notify_custom_listeners('on_key_down', area_key_event)
190
190
  end
191
191
  end
192
192
  @listeners_installed = true
@@ -42,6 +42,7 @@ module Glimmer
42
42
  end
43
43
 
44
44
  def destroy_child(child)
45
+ child.deregister_all_custom_listeners
45
46
  ::LibUI.send("box_delete", @libui, children.index(child))
46
47
  ControlProxy.control_proxies.delete(child)
47
48
  end
@@ -30,6 +30,12 @@ module Glimmer
30
30
  #
31
31
  # Follows the Proxy Design Pattern
32
32
  class BackgroundColorColumnProxy < ControlProxy
33
+ class << self
34
+ def default_value
35
+ :white
36
+ end
37
+ end
38
+
33
39
  include Column
34
40
 
35
41
  def name
@@ -31,39 +31,17 @@ module Glimmer
31
31
  #
32
32
  # Follows the Proxy Design Pattern
33
33
  class ButtonColumnProxy < ControlProxy
34
- include Column
35
- include EnableableColumn
36
-
37
- def on_clicked(&block)
38
- # TODO consider generalizing into custom listeners and moving to ControlProxy
39
- @on_clicked_procs ||= []
40
- if block.nil?
41
- @on_clicked_procs
42
- else
43
- @on_clicked_procs << block
44
- block
34
+ class << self
35
+ def default_value
36
+ ''
45
37
  end
46
38
  end
47
39
 
48
- def can_handle_listener?(listener_name)
49
- listener_name == 'on_clicked' || super
50
- end
40
+ include Column
41
+ include EnableableColumn
51
42
 
52
- def handle_listener(listener_name, &listener)
53
- case listener_name
54
- when 'on_clicked'
55
- on_clicked(&listener)
56
- else
57
- super
58
- end
59
- end
43
+ CUSTOM_LISTENER_NAMES = ['on_clicked']
60
44
 
61
- def notify_listeners(listener_name, *args)
62
- @on_clicked_procs&.each do |on_clicked_proc|
63
- on_clicked_proc.call(*args)
64
- end
65
- end
66
-
67
45
  private
68
46
 
69
47
  def build_control
@@ -31,6 +31,12 @@ module Glimmer
31
31
  #
32
32
  # Follows the Proxy Design Pattern
33
33
  class CheckboxColumnProxy < ControlProxy
34
+ class << self
35
+ def default_value
36
+ false
37
+ end
38
+ end
39
+
34
40
  include Column
35
41
  include EditableColumn
36
42
 
@@ -32,6 +32,12 @@ module Glimmer
32
32
  #
33
33
  # Follows the Proxy Design Pattern
34
34
  class CheckboxTextColorColumnProxy < ControlProxy
35
+ class << self
36
+ def default_value
37
+ [false, '', :black]
38
+ end
39
+ end
40
+
35
41
  include Column
36
42
  include TripleColumn
37
43
  include EditableColumn
@@ -32,6 +32,12 @@ module Glimmer
32
32
  #
33
33
  # Follows the Proxy Design Pattern
34
34
  class CheckboxTextColumnProxy < ControlProxy
35
+ class << self
36
+ def default_value
37
+ [false, '']
38
+ end
39
+ end
40
+
35
41
  include Column
36
42
  include DualColumn
37
43
  include EditableColumn
@@ -30,6 +30,12 @@ module Glimmer
30
30
  #
31
31
  # Follows the Proxy Design Pattern
32
32
  class ImageColumnProxy < ControlProxy
33
+ class << self
34
+ def default_value
35
+ Glimmer::LibUI::ICON
36
+ end
37
+ end
38
+
33
39
  include Column
34
40
 
35
41
  private
@@ -32,6 +32,12 @@ module Glimmer
32
32
  #
33
33
  # Follows the Proxy Design Pattern
34
34
  class ImageTextColorColumnProxy < ControlProxy
35
+ class << self
36
+ def default_value
37
+ [Glimmer::LibUI::ICON, '', :black]
38
+ end
39
+ end
40
+
35
41
  include Column
36
42
  include TripleColumn
37
43
  include EditableColumn
@@ -32,6 +32,12 @@ module Glimmer
32
32
  #
33
33
  # Follows the Proxy Design Pattern
34
34
  class ImageTextColumnProxy < ControlProxy
35
+ class << self
36
+ def default_value
37
+ [Glimmer::LibUI::ICON, '']
38
+ end
39
+ end
40
+
35
41
  include Column
36
42
  include DualColumn
37
43
  include EditableColumn
@@ -30,6 +30,12 @@ module Glimmer
30
30
  #
31
31
  # Follows the Proxy Design Pattern
32
32
  class ProgressBarColumnProxy < ControlProxy
33
+ class << self
34
+ def default_value
35
+ 0
36
+ end
37
+ end
38
+
33
39
  include Column
34
40
 
35
41
  private
@@ -32,6 +32,12 @@ module Glimmer
32
32
  #
33
33
  # Follows the Proxy Design Pattern
34
34
  class TextColorColumnProxy < ControlProxy
35
+ class << self
36
+ def default_value
37
+ ['', :black]
38
+ end
39
+ end
40
+
35
41
  include Column
36
42
  include DualColumn
37
43
  include EditableColumn
@@ -31,6 +31,12 @@ module Glimmer
31
31
  #
32
32
  # Follows the Proxy Design Pattern
33
33
  class TextColumnProxy < ControlProxy
34
+ class << self
35
+ def default_value
36
+ ''
37
+ end
38
+ end
39
+
34
40
  include Column
35
41
  include EditableColumn
36
42
 
@@ -24,6 +24,13 @@ module Glimmer
24
24
  class ControlProxy
25
25
  # Common logic for all column proxy objects
26
26
  module Column
27
+ class << self
28
+ # subclasses may override to provide a valid default value like a blank image for image columns and false for checkbox
29
+ def default_value
30
+ nil
31
+ end
32
+ end
33
+
27
34
  def initialize(keyword, parent, args, &block)
28
35
  @keyword = keyword
29
36
  @parent_proxy = parent
@@ -39,6 +39,7 @@ module Glimmer
39
39
  end
40
40
 
41
41
  def destroy_child(child)
42
+ child.deregister_all_custom_listeners
42
43
  ::LibUI.send("form_delete", @libui, children.index(child))
43
44
  ControlProxy.control_proxies.delete(child)
44
45
  end