glimmer-dsl-libui 0.4.13 → 0.4.17

Sign up to get free protection for your applications and to get access to all the features.
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