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
@@ -52,12 +52,14 @@ module Glimmer
52
52
 
53
53
  include Parent
54
54
  prepend Transformable
55
+ include Equalizer.new(:options, :data)
55
56
 
56
- attr_reader :data, :pixels, :shapes
57
+ attr_reader :data, :pixels, :shapes, :options
57
58
 
58
59
  def initialize(keyword, parent, args, &block)
59
60
  @keyword = keyword
60
61
  @parent_proxy = parent
62
+ @options = args.last.is_a?(Hash) ? args.pop : {}
61
63
  @args = args
62
64
  @block = block
63
65
  @enabled = true
@@ -92,11 +94,47 @@ module Glimmer
92
94
  alias file= file
93
95
  alias set_file file
94
96
 
97
+ def x(value = nil)
98
+ if value.nil?
99
+ @args.size > 3 ? @args[1] : (@options[:x] || 0)
100
+ else
101
+ if @args.size > 3
102
+ @args[1] = value
103
+ else
104
+ @options[:x] = value
105
+ end
106
+ if area_image? && @content_added
107
+ post_add_content
108
+ request_auto_redraw
109
+ end
110
+ end
111
+ end
112
+ alias x= x
113
+ alias set_x x
114
+
115
+ def y(value = nil)
116
+ if value.nil?
117
+ @args.size > 3 ? @args[2] : (@options[:y] || 0)
118
+ else
119
+ if @args.size > 3
120
+ @args[2] = value
121
+ else
122
+ @options[:y] = value
123
+ end
124
+ if area_image? && @content_added
125
+ post_add_content
126
+ request_auto_redraw
127
+ end
128
+ end
129
+ end
130
+ alias y= y
131
+ alias set_y y
132
+
95
133
  def width(value = nil)
96
134
  if value.nil?
97
- @args[1]
135
+ @args.size > 3 ? @args[3] : (@options[:width] || @args[1])
98
136
  else
99
- @args[1] = value
137
+ set_width_variable(value)
100
138
  if area_image? && @content_added
101
139
  post_add_content
102
140
  request_auto_redraw
@@ -108,9 +146,9 @@ module Glimmer
108
146
 
109
147
  def height(value = nil)
110
148
  if value.nil?
111
- @args[2]
149
+ @args.size > 3 ? @args[4] : (@options[:height] || @args[2])
112
150
  else
113
- @args[2] = value
151
+ set_height_variable(value)
114
152
  if area_image? && @content_added
115
153
  post_add_content
116
154
  request_auto_redraw
@@ -142,12 +180,34 @@ module Glimmer
142
180
  end
143
181
 
144
182
  def destroy
183
+ return if ControlProxy.main_window_proxy&.destroying?
184
+ deregister_all_custom_listeners
145
185
  @parent_proxy&.children&.delete(self)
146
186
  ControlProxy.control_proxies.delete(self)
147
187
  end
148
188
 
149
189
  private
150
190
 
191
+ def set_width_variable(value)
192
+ if @args.size > 3
193
+ @args[3] = value
194
+ elsif @options[:width]
195
+ @options[:width] = value
196
+ else
197
+ @args[1] = value
198
+ end
199
+ end
200
+
201
+ def set_height_variable(value)
202
+ if @args.size > 3
203
+ @args[4] = value
204
+ elsif @options[:height]
205
+ @options[:height] = value
206
+ else
207
+ @args[2] = value
208
+ end
209
+ end
210
+
151
211
  def build_control
152
212
  unless area_image? # image object
153
213
  if file
@@ -180,10 +240,15 @@ module Glimmer
180
240
  canvas = ChunkyPNG::Canvas.from_io(f)
181
241
  f.close
182
242
  end
183
- canvas.resample_nearest_neighbor!(width, height) if width && height
243
+ original_width = canvas.width
244
+ original_height = canvas.height
245
+ require 'bigdecimal'
246
+ calculated_width = ((BigDecimal(height)/BigDecimal(original_height))*original_width).to_i if height && !width
247
+ calculated_height = ((BigDecimal(width)/BigDecimal(original_width))*original_height).to_i if width && !height
248
+ canvas.resample_nearest_neighbor!(calculated_width || width, calculated_height || height) if width || height
184
249
  @data = canvas.to_rgba_stream
185
- @args[1] = canvas.width
186
- @args[2] = canvas.height
250
+ set_width_variable(canvas.width) unless width
251
+ set_height_variable(canvas.height) unless height
187
252
  [@data, width, height]
188
253
  end
189
254
 
@@ -203,6 +268,8 @@ module Glimmer
203
268
  @shapes = []
204
269
  original_pixels = @pixels.dup
205
270
  indexed_original_pixels = Hash[original_pixels.each_with_index.to_a]
271
+ x_offset = x
272
+ y_offset = y
206
273
  @pixels.each do |pixel|
207
274
  index = indexed_original_pixels[pixel]
208
275
  @rectangle_start_x ||= pixel[:x]
@@ -211,9 +278,9 @@ module Glimmer
211
278
  @rectangle_width += 1
212
279
  else
213
280
  if pixel[:x] > 0 && pixel[:color] == original_pixels[index - 1][:color]
214
- @shapes << {x: @rectangle_start_x, y: pixel[:y], width: @rectangle_width, height: 1, color: pixel[:color]}
281
+ @shapes << {x: x_offset + @rectangle_start_x, y: y_offset + pixel[:y], width: @rectangle_width, height: 1, color: pixel[:color]}
215
282
  else
216
- @shapes << {x: pixel[:x], y: pixel[:y], width: 1, height: 1, color: pixel[:color]}
283
+ @shapes << {x: x_offset + pixel[:x], y: y_offset + pixel[:y], width: 1, height: 1, color: pixel[:color]}
217
284
  end
218
285
  @rectangle_width = 1
219
286
  @rectangle_start_x = pixel[:x] == width - 1 ? 0 : pixel[:x] + 1
@@ -35,29 +35,39 @@ module Glimmer
35
35
 
36
36
  def handle_listener(listener_name, &listener)
37
37
  if listener_name == 'on_clicked'
38
- @default_behavior_listener = Proc.new do
39
- return_value = listener.call(self)
38
+ @on_clicked_listeners ||= []
39
+ @on_clicked_listeners << listener
40
+ @default_behavior_listener ||= Proc.new do
41
+ return_value = nil
42
+ @on_clicked_listeners.each do |l|
43
+ return_value = l.call(self)
44
+ break if return_value.is_a?(Numeric)
45
+ end
40
46
  if return_value.is_a?(Numeric)
41
47
  return_value
42
48
  else
43
49
  destroy
50
+ ControlProxy.main_window_proxy&.destroy
44
51
  ::LibUI.quit
45
52
  0
46
53
  end
54
+ end.tap do |default_behavior_listener|
55
+ ::LibUI.on_should_quit(&default_behavior_listener)
47
56
  end
48
- ::LibUI.on_should_quit(&@default_behavior_listener)
49
57
  end
50
58
  end
59
+
60
+ def destroy
61
+ @on_clicked_listeners&.clear
62
+ super
63
+ end
51
64
 
52
65
  private
53
66
 
54
67
  def build_control
55
68
  @libui = @parent_proxy.append_quit_item(*@args)
56
- handle_listener('on_clicked') do
57
- ControlProxy.main_window_proxy&.destroy
58
- ::LibUI.quit
59
- 0
60
- end
69
+ # setup default on_clicked listener if no on_clicked listeners are setup
70
+ handle_listener('on_clicked') {} if @on_clicked_listeners.nil? || @on_clicked_listeners.empty?
61
71
  end
62
72
  end
63
73
  end
@@ -33,15 +33,24 @@ module Glimmer
33
33
  include Parent
34
34
 
35
35
  def destroy
36
+ return if ControlProxy.main_window_proxy&.destroying?
37
+ return if @destroying
38
+ @destroying = true
39
+ deregister_all_custom_listeners
36
40
  ::LibUI.free_open_type_features(@libui)
37
- @parent_proxy&.children&.delete(self)
41
+ @parent_proxy&.remove_open_type_features
38
42
  ControlProxy.control_proxies.delete(self)
43
+ @destroying = false
39
44
  end
40
45
 
41
46
  def redraw
42
- @parent_proxy.redraw
47
+ @parent_proxy&.redraw
43
48
  end
44
49
 
50
+ def request_auto_redraw
51
+ @parent_proxy&.request_auto_redraw
52
+ end
53
+
45
54
  private
46
55
 
47
56
  def build_control
@@ -31,6 +31,8 @@ module Glimmer
31
31
  # Follows the Proxy Design Pattern
32
32
  class OpenTypeTagProxy < ControlProxy
33
33
  def destroy
34
+ return if ControlProxy.main_window_proxy&.destroying?
35
+ deregister_all_custom_listeners
34
36
  @parent_proxy&.children&.delete(self)
35
37
  ControlProxy.control_proxies.delete(self)
36
38
  end
@@ -140,6 +140,8 @@ module Glimmer
140
140
  end
141
141
 
142
142
  def destroy
143
+ return if ControlProxy.main_window_proxy&.destroying?
144
+ deregister_all_custom_listeners
143
145
  @parent_proxy&.children&.delete(self)
144
146
  ControlProxy.control_proxies.delete(self)
145
147
  end
@@ -36,7 +36,7 @@ module Glimmer
36
36
  class TableProxy < ControlProxy
37
37
  include Glimmer::FiddleConsumer
38
38
 
39
- LISTENERS = ['on_changed', 'on_edited']
39
+ CUSTOM_LISTENER_NAMES = ['on_changed', 'on_edited']
40
40
 
41
41
  attr_reader :model_handler, :model, :table_params, :columns, :column_attributes
42
42
 
@@ -90,26 +90,26 @@ module Glimmer
90
90
  @cell_rows_observer ||= Glimmer::DataBinding::Observer.proc do |new_cell_rows|
91
91
  if @cell_rows.size < @last_cell_rows.size && @last_cell_rows.include_all?(*@cell_rows)
92
92
  @last_cell_rows.array_diff_indexes(@cell_rows).reverse.each do |row|
93
- ::LibUI.table_model_row_deleted(model, row)
94
- on_changed.each {|listener| listener.call(row, :deleted, @last_cell_rows[row])}
93
+ ::LibUI.table_model_row_deleted(model, row) if model && row
94
+ notify_custom_listeners('on_changed', row, :deleted, @last_cell_rows[row])
95
95
  end
96
96
  elsif @cell_rows.size > @last_cell_rows.size && @cell_rows.include_all?(*@last_cell_rows)
97
97
  @cell_rows.array_diff_indexes(@last_cell_rows).each do |row|
98
- ::LibUI.table_model_row_inserted(model, row)
99
- on_changed.each {|listener| listener.call(row, :inserted, @cell_rows[row])}
98
+ ::LibUI.table_model_row_inserted(model, row) if model && row
99
+ notify_custom_listeners('on_changed', row, :inserted, @cell_rows[row])
100
100
  end
101
101
  else
102
102
  @cell_rows.each_with_index do |new_row_data, row|
103
103
  if new_row_data != @last_cell_rows[row]
104
- ::LibUI.table_model_row_changed(model, row)
105
- on_changed.each {|listener| listener.call(row, :changed, @cell_rows[row])}
104
+ ::LibUI.table_model_row_changed(model, row) if model && row
105
+ notify_custom_listeners('on_changed', row, :changed, @cell_rows[row])
106
106
  end
107
107
  end
108
108
  end
109
109
  @last_last_cell_rows = array_deep_clone(@last_cell_rows)
110
110
  @last_cell_rows = array_deep_clone(@cell_rows)
111
111
  end.tap do |cell_rows_observer|
112
- cell_rows_observer.observe(self, :cell_rows, recursive: true)
112
+ cell_rows_observer.observe(self, :cell_rows, recursive: true, ignore_frozen: true)
113
113
  end
114
114
  end
115
115
  @cell_rows
@@ -153,7 +153,7 @@ module Glimmer
153
153
  new_value = new_value.to_a if new_value.is_a?(Enumerator)
154
154
  if model_binding.binding_options[:column_attributes] || (!new_value.empty? && !new_value.first.is_a?(Array))
155
155
  @model_attribute_array_observer_registration&.deregister
156
- @model_attribute_array_observer_registration = model_attribute_observer.observe(new_value, @column_attributes)
156
+ @model_attribute_array_observer_registration = model_attribute_observer.observe(new_value, @column_attributes, ignore_frozen: true)
157
157
  model_attribute_observer.add_dependent(model_attribute_observer_registration => @model_attribute_array_observer_registration)
158
158
  end
159
159
  # TODO look if multiple notifications are happening as a result of observing array and observing model binding
@@ -208,9 +208,11 @@ module Glimmer
208
208
  when Column::TextColumnProxy, Column::ButtonColumnProxy, Column::TextColorColumnProxy, :text
209
209
  ::LibUI.new_table_value_string((expanded_cell_rows[row] && expanded_cell_rows[row][column]).to_s)
210
210
  when Column::ImageColumnProxy, Column::ImageTextColumnProxy, Column::ImageTextColorColumnProxy
211
- # TODO refactor to eliminate redundancy and share similar code
212
- row = row - 1 if OS.windows? && row == cell_rows.count
213
- img = expanded_cell_rows[row][column]
211
+ if OS.windows? && row == cell_rows.count
212
+ img = Glimmer::LibUI::ICON
213
+ else
214
+ img = expanded_cell_rows[row][column]
215
+ end
214
216
  img = ControlProxy::ImageProxy.create('image', nil, img) if img.is_a?(Array)
215
217
  img = ControlProxy::ImageProxy.create('image', nil, [img]) if img.is_a?(String)
216
218
  img = img.respond_to?(:libui) ? img.libui : img
@@ -270,7 +272,7 @@ module Glimmer
270
272
  @cell_rows[row].send(attribute)[1] = ::LibUI.table_value_string(val).to_s
271
273
  end
272
274
  when Column::ButtonColumnProxy
273
- @columns[column].notify_listeners(:on_clicked, row)
275
+ @columns[column].notify_custom_listeners('on_clicked', row)
274
276
  when Column::CheckboxColumnProxy
275
277
  column = @columns[column].index
276
278
  @cell_rows[row] ||= []
@@ -292,7 +294,7 @@ module Glimmer
292
294
  @cell_rows[row].send(attribute)[0] = ::LibUI.table_value_int(val).to_i == 1
293
295
  end
294
296
  end
295
- on_edited.each {|listener| listener.call(row, @cell_rows[row])}
297
+ notify_custom_listeners('on_edited', row, @cell_rows[row])
296
298
  end
297
299
 
298
300
  @model = ::LibUI.new_table_model(@model_handler)
@@ -308,6 +310,15 @@ module Glimmer
308
310
  @libui.tap do
309
311
  @columns.each {|column| column.respond_to?(:build_control, true) && column.send(:build_control) }
310
312
  end
313
+
314
+ if !@applied_windows_fix && OS.windows?
315
+ @applied_windows_fix = true
316
+ new_row = @columns&.select {|column| column.is_a?(Column)}&.map {|column| column.class.default_value}
317
+ if new_row
318
+ @cell_rows << new_row
319
+ @cell_rows.pop
320
+ end
321
+ end
311
322
  end
312
323
 
313
324
  def next_column_index
@@ -60,6 +60,8 @@ module Glimmer
60
60
  end
61
61
 
62
62
  def destroy
63
+ return if ControlProxy.main_window_proxy&.destroying?
64
+ deregister_all_custom_listeners
63
65
  @parent_proxy&.children&.delete(self)
64
66
  ControlProxy.control_proxies.delete(self)
65
67
  end
@@ -29,6 +29,10 @@ module Glimmer
29
29
  #
30
30
  # Follows the Proxy Design Pattern
31
31
  class WindowProxy < ControlProxy
32
+ CUSTOM_LISTENER_NAMES = ['on_destroy']
33
+ CUSTOM_LISTENER_NAME_ALIASES = {
34
+ on_destroyed: 'on_destroy',
35
+ }
32
36
  DEFAULT_TITLE = ''
33
37
  DEFAULT_WIDTH = 190
34
38
  DEFAULT_HEIGHT = 150
@@ -44,22 +48,20 @@ module Glimmer
44
48
  end
45
49
 
46
50
  def destroy
51
+ return if @destroying
52
+ @destroying = true
53
+ @on_closing_listeners&.clear
47
54
  super
48
55
  ControlProxy.image_proxies.each { |image_proxy| ::LibUI.free_image(image_proxy.libui) unless image_proxy.area_image? }
49
- @on_destroy_procs&.each { |on_destroy_proc| on_destroy_proc.call(self)}
56
+ notify_custom_listeners('on_destroy', self)
57
+ deregister_custom_listeners('on_destroy')
58
+ @destroying = false
50
59
  end
51
60
 
52
- def on_destroy(&block)
53
- # TODO look into a way to generalize this logic for multiple listeners
54
- @on_destroy_procs ||= []
55
- if block.nil?
56
- @on_destroy_procs
57
- else
58
- @on_destroy_procs << block
59
- block
60
- end
61
+ def destroying?
62
+ @destroying
61
63
  end
62
-
64
+
63
65
  def show
64
66
  super
65
67
  unless @shown_at_least_once
@@ -69,29 +71,29 @@ module Glimmer
69
71
  end
70
72
  end
71
73
 
72
- def can_handle_listener?(listener_name)
73
- listener_name == 'on_destroy' || super
74
- end
75
-
76
74
  def handle_listener(listener_name, &listener)
77
75
  case listener_name
78
- when 'on_destroy'
79
- on_destroy(&listener)
80
- else
81
- default_behavior_listener = nil
82
- if listener_name == 'on_closing'
83
- default_behavior_listener = Proc.new do
84
- return_value = listener.call(self)
85
- if return_value.is_a?(Numeric)
86
- return_value
87
- else
88
- destroy
89
- ::LibUI.quit
90
- 0
91
- end
76
+ when 'on_closing'
77
+ @on_closing_listeners ||= []
78
+ @on_closing_listeners << listener
79
+ @default_behavior_listener ||= Proc.new do
80
+ return_value = nil
81
+ @on_closing_listeners.each do |l|
82
+ return_value = l.call(self)
83
+ break if return_value.is_a?(Numeric)
84
+ end
85
+ if return_value.is_a?(Numeric)
86
+ return_value
87
+ else
88
+ destroy
89
+ ::LibUI.quit
90
+ 0
92
91
  end
92
+ end.tap do |default_behavior_listener|
93
+ super(listener_name, &default_behavior_listener)
93
94
  end
94
- super(listener_name, &(default_behavior_listener || listener))
95
+ else
96
+ super
95
97
  end
96
98
  end
97
99
 
@@ -168,11 +170,8 @@ module Glimmer
168
170
  @height = construction_args[2]
169
171
  @libui = ControlProxy.new_control(@keyword, construction_args)
170
172
  @libui.tap do
171
- handle_listener('on_closing') do
172
- destroy
173
- ::LibUI.quit
174
- 0
175
- end
173
+ # setup default on_closing listener if no on_closing listeners are setup
174
+ handle_listener('on_closing') {} if @on_closing_listeners.nil? || @on_closing_listeners.empty?
176
175
  end
177
176
  end
178
177
  end
@@ -169,31 +169,49 @@ module Glimmer
169
169
  def handle_listener(listener_name, &listener)
170
170
  safe_listener = Proc.new { listener.call(self) }
171
171
  if ::LibUI.respond_to?("#{libui_api_keyword}_#{listener_name}")
172
- ::LibUI.send("#{libui_api_keyword}_#{listener_name}", @libui, &safe_listener)
172
+ if listeners[listener_name].nil?
173
+ ::LibUI.send("#{libui_api_keyword}_#{listener_name}", @libui) do
174
+ listeners_for(listener_name).map { |listener| listener.call }.last
175
+ end
176
+ end
177
+ listeners_for(listener_name) << safe_listener
173
178
  elsif ::LibUI.respond_to?("control_#{listener_name}")
174
- ::LibUI.send("control_#{listener_name}", @libui, &safe_listener)
179
+ if listeners[listener_name].nil?
180
+ ::LibUI.send("control_#{listener_name}", @libui) do
181
+ listeners_for(listener_name).map { |listener| listener.call }.last
182
+ end
183
+ end
184
+ listeners_for(listener_name) << safe_listener
175
185
  elsif has_custom_listener?(listener_name)
176
186
  handle_custom_listener(listener_name, &listener)
177
187
  end
178
188
  end
179
189
 
190
+ def listeners
191
+ @listeners ||= {}
192
+ end
193
+
194
+ def listeners_for(listener_name)
195
+ listeners[listener_name] ||= []
196
+ end
197
+
180
198
  def has_custom_listener?(listener_name)
181
199
  listener_name = listener_name.to_s
182
- custom_listeners.include?(listener_name) || custom_listener_aliases.stringify_keys.keys.include?(listener_name)
200
+ custom_listener_names.include?(listener_name) || custom_listener_name_aliases.stringify_keys.keys.include?(listener_name)
183
201
  end
184
202
 
185
- def custom_listeners
186
- self.class.constants.include?(:LISTENERS) ? self.class::LISTENERS : []
203
+ def custom_listener_names
204
+ self.class.constants.include?(:CUSTOM_LISTENER_NAMES) ? self.class::CUSTOM_LISTENER_NAMES : []
187
205
  end
188
206
 
189
- def custom_listener_aliases
190
- self.class.constants.include?(:LISTENER_ALIASES) ? self.class::LISTENER_ALIASES : {}
207
+ def custom_listener_name_aliases
208
+ self.class.constants.include?(:CUSTOM_LISTENER_NAME_ALIASES) ? self.class::CUSTOM_LISTENER_NAME_ALIASES : {}
191
209
  end
192
210
 
193
211
  def handle_custom_listener(listener_name, &listener)
194
212
  listener_name = listener_name.to_s
195
- listener_name = custom_listener_aliases.stringify_keys[listener_name] || listener_name
196
- instance_variable_name = "@#{listener_name}_procs"
213
+ listener_name = custom_listener_name_aliases.stringify_keys[listener_name] || listener_name
214
+ instance_variable_name = "@#{listener_name}_procs" # TODO ensure clearing custom listeners on destroy of a control
197
215
  instance_variable_set(instance_variable_name, []) if instance_variable_get(instance_variable_name).nil?
198
216
  if listener.nil?
199
217
  instance_variable_get(instance_variable_name)
@@ -203,6 +221,21 @@ module Glimmer
203
221
  end
204
222
  end
205
223
 
224
+ def notify_custom_listeners(listener_name, *args)
225
+ handle_custom_listener(listener_name).each do |listener|
226
+ listener.call(*args)
227
+ end
228
+ end
229
+
230
+ def deregister_custom_listeners(listener_name)
231
+ handle_custom_listener(listener_name).clear
232
+ end
233
+
234
+ # deregisters all custom listeners except on_destroy, which can only be deregistered after destruction of a control, using deregister_custom_listeners
235
+ def deregister_all_custom_listeners
236
+ (custom_listener_names - ['on_destroy']).each { |listener_name| deregister_custom_listeners(listener_name) }
237
+ end
238
+
206
239
  def respond_to?(method_name, *args, &block)
207
240
  respond_to_libui?(method_name, *args, &block) ||
208
241
  (
@@ -289,6 +322,8 @@ module Glimmer
289
322
  end
290
323
 
291
324
  def destroy
325
+ # TODO exclude menus from this initial return
326
+ return if !is_a?(ControlProxy::WindowProxy) && ControlProxy.main_window_proxy&.destroying?
292
327
  data_binding_model_attribute_observer_registrations.each(&:deregister)
293
328
  if parent_proxy.nil?
294
329
  default_destroy
@@ -302,6 +337,7 @@ module Glimmer
302
337
  end
303
338
 
304
339
  def default_destroy
340
+ deregister_all_custom_listeners
305
341
  send_to_libui('destroy')
306
342
  ControlProxy.control_proxies.delete(self)
307
343
  end
@@ -116,6 +116,7 @@ module Glimmer
116
116
  end
117
117
 
118
118
  def destroy
119
+ return if ControlProxy.main_window_proxy&.destroying?
119
120
  @parent.children.delete(self)
120
121
  end
121
122
 
data/lib/glimmer/libui.rb CHANGED
@@ -23,6 +23,7 @@ require 'glimmer/fiddle_consumer'
23
23
 
24
24
  module Glimmer
25
25
  module LibUI
26
+ ICON = File.expand_path('../../icons/blank.png', __dir__)
26
27
  class << self
27
28
  include Glimmer::FiddleConsumer
28
29
 
@@ -28,6 +28,7 @@ require 'glimmer'
28
28
  # require 'super_module'
29
29
  require 'color'
30
30
  require 'os'
31
+ require 'equalizer'
31
32
  require 'array_include_methods'
32
33
  require 'facets/hash/stringify_keys'
33
34
  require 'facets/string/underscore'
@@ -46,3 +47,8 @@ Glimmer::Config.excluded_keyword_checkers << lambda do |method_symbol, *args|
46
47
  end
47
48
 
48
49
  ::LibUI.init
50
+ # begin
51
+ # PutsDebuggerer.printer = lambda { |m| puts m; $stdout.flush}
52
+ # rescue
53
+ ## No Op if puts_debuggerer is not loaded
54
+ # 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.4.13
4
+ version: 0.4.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Maleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-03 00:00:00.000000000 Z
11
+ date: 2021-12-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: glimmer
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 2.5.0
19
+ version: 2.5.3
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 2.5.0
26
+ version: 2.5.3
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: os
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -86,6 +86,20 @@ dependencies:
86
86
  - - "~>"
87
87
  - !ruby/object:Gem::Version
88
88
  version: 1.4.0
89
+ - !ruby/object:Gem::Dependency
90
+ name: equalizer
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - '='
94
+ - !ruby/object:Gem::Version
95
+ version: 0.0.11
96
+ type: :runtime
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - '='
101
+ - !ruby/object:Gem::Version
102
+ version: 0.0.11
89
103
  - !ruby/object:Gem::Dependency
90
104
  name: juwelier
91
105
  requirement: !ruby/object:Gem::Requirement
@@ -309,6 +323,7 @@ files:
309
323
  - examples/timer.rb
310
324
  - examples/timer2.rb
311
325
  - glimmer-dsl-libui.gemspec
326
+ - icons/blank.png
312
327
  - icons/glimmer.png
313
328
  - lib/glimmer-dsl-libui.rb
314
329
  - lib/glimmer/dsl/libui/bind_expression.rb
@@ -433,7 +448,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
433
448
  - !ruby/object:Gem::Version
434
449
  version: '0'
435
450
  requirements: []
436
- rubygems_version: 3.2.31
451
+ rubygems_version: 3.2.22
437
452
  signing_key:
438
453
  specification_version: 4
439
454
  summary: Glimmer DSL for LibUI