Class: Glimmer::SWT::TableProxy

Inherits:
WidgetProxy show all
Includes:
Glimmer
Defined in:
lib/glimmer/swt/table_proxy.rb

Defined Under Namespace

Modules: TableListenerEvent

Constant Summary

Constants inherited from WidgetProxy

WidgetProxy::DEFAULT_INITIALIZERS, WidgetProxy::DEFAULT_STYLES

Instance Attribute Summary collapse

Attributes inherited from WidgetProxy

#drag_source_proxy, #drag_source_style, #drag_source_transfer, #drop_target_proxy, #drop_target_transfer, #parent_proxy, #swt_widget

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Glimmer

included

Methods inherited from WidgetProxy

#add_observer, #async_exec, #can_add_observer?, #can_handle_drag_observation_request?, #can_handle_drop_observation_request?, #can_handle_observation_request?, #content, create, #dispose, #ensure_drag_source_proxy, #ensure_drop_target_proxy, #extract_args, #get_attribute, #handle_observation_request, #has_attribute?, #has_style?, #method_missing, #pack_same_size, #post_add_content, #remove_observer, #respond_to?, #set_attribute, swt_widget_class_for, #sync_exec, underscored_widget_name, widget_exists?, widget_proxy_class

Methods included from Packages

included

Constructor Details

#initialize(underscored_widget_name, parent, args) ⇒ TableProxy

Returns a new instance of TableProxy.



144
145
146
147
148
149
150
# File 'lib/glimmer/swt/table_proxy.rb', line 144

def initialize(underscored_widget_name, parent, args)
  super
  @table_editor = TableEditor.new(swt_widget)
  @table_editor.horizontalAlignment = SWTProxy[:left]
  @table_editor.grabHorizontal = true
  @table_editor.minimumHeight = 20
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Glimmer::SWT::WidgetProxy

Instance Attribute Details

#additional_sort_propertiesObject

Returns the value of attribute additional_sort_properties.



141
142
143
# File 'lib/glimmer/swt/table_proxy.rb', line 141

def additional_sort_properties
  @additional_sort_properties
end

#column_propertiesObject

Returns the value of attribute column_properties.



142
143
144
# File 'lib/glimmer/swt/table_proxy.rb', line 142

def column_properties
  @column_properties
end

#editorObject

Returns the value of attribute editor.



141
142
143
# File 'lib/glimmer/swt/table_proxy.rb', line 141

def editor
  @editor
end

#sort_blockObject (readonly)

Returns the value of attribute sort_block.



141
142
143
# File 'lib/glimmer/swt/table_proxy.rb', line 141

def sort_block
  @sort_block
end

#sort_by_blockObject (readonly)

Returns the value of attribute sort_by_block.



141
142
143
# File 'lib/glimmer/swt/table_proxy.rb', line 141

def sort_by_block
  @sort_by_block
end

#sort_directionObject (readonly)

Returns the value of attribute sort_direction.



141
142
143
# File 'lib/glimmer/swt/table_proxy.rb', line 141

def sort_direction
  @sort_direction
end

#sort_propertyObject (readonly)

Returns the value of attribute sort_property.



141
142
143
# File 'lib/glimmer/swt/table_proxy.rb', line 141

def sort_property
  @sort_property
end

#sort_typeObject (readonly)

Returns the value of attribute sort_type.



141
142
143
# File 'lib/glimmer/swt/table_proxy.rb', line 141

def sort_type
  @sort_type
end

#table_editorObject (readonly)

Returns the value of attribute table_editor.



141
142
143
# File 'lib/glimmer/swt/table_proxy.rb', line 141

def table_editor
  @table_editor
end

#table_editor_widget_proxyObject (readonly)

Returns the value of attribute table_editor_widget_proxy.



141
142
143
# File 'lib/glimmer/swt/table_proxy.rb', line 141

def table_editor_widget_proxy
  @table_editor_widget_proxy
end

Class Method Details

.editorsObject



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/glimmer/swt/table_proxy.rb', line 37

def editors
  @editors ||= {
    text: {
      widget_value_property: :text,
      editor_gui: lambda do |args, model, property, table_proxy|
        table_proxy.table_editor.minimumHeight = 20
        table_editor_widget_proxy = text(*args) {
          text model.send(property)
          focus true
          on_focus_lost {
            table_proxy.finish_edit!
          }
          on_key_pressed { |key_event|
            if key_event.keyCode == swt(:cr)
              table_proxy.finish_edit!
            elsif key_event.keyCode == swt(:esc)
              table_proxy.cancel_edit!
            end
          }              
        }
        table_editor_widget_proxy.swt_widget.selectAll          
        table_editor_widget_proxy
      end,
    },
    combo: {
      widget_value_property: :text,
      editor_gui: lambda do |args, model, property, table_proxy|
        first_time = true
        table_proxy.table_editor.minimumHeight = 25
        table_editor_widget_proxy = combo(*args) {
          items model.send("#{property}_options")
          text model.send(property)
          focus true
          on_focus_lost {
            table_proxy.finish_edit!
          }
          on_key_pressed { |key_event|
            if key_event.keyCode == swt(:cr)
              table_proxy.finish_edit!
            elsif key_event.keyCode == swt(:esc)
              table_proxy.cancel_edit!
            end
          }
          on_widget_selected {
            if !OS.windows? || !first_time || first_time && model.send(property) != table_editor_widget_proxy.swt_widget.text
              table_proxy.finish_edit! 
            end 
          }
        }
        table_editor_widget_proxy
      end,
    },
    checkbox: {
      widget_value_property: :selection,
      editor_gui: lambda do |args, model, property, table_proxy|
        first_time = true
        table_proxy.table_editor.minimumHeight = 25
        checkbox(*args) {
          selection model.send(property)
          focus true
          on_widget_selected {
            table_proxy.finish_edit! 
          }
          on_focus_lost {
            table_proxy.finish_edit! 
          }
          on_key_pressed { |key_event|
            if key_event.keyCode == swt(:cr)
              table_proxy.finish_edit!
            elsif key_event.keyCode == swt(:esc)
              table_proxy.cancel_edit!
            end
          }              
        }
      end,
    },
    radio: {
      widget_value_property: :selection,
      editor_gui: lambda do |args, model, property, table_proxy|
        first_time = true
        table_proxy.table_editor.minimumHeight = 25
        radio(*args) {
          selection model.send(property)
          focus true
          on_widget_selected {
            table_proxy.finish_edit! 
          }
          on_focus_lost {
            table_proxy.finish_edit! 
          }
          on_key_pressed { |key_event|
            if key_event.keyCode == swt(:cr)
              table_proxy.finish_edit!
            elsif key_event.keyCode == swt(:esc)
              table_proxy.cancel_edit!
            end
          }              
        }
      end,
    }            
  }      
end

Instance Method Details

#add_listener(underscored_listener_name, &block) ⇒ Object



355
356
357
358
359
360
361
# File 'lib/glimmer/swt/table_proxy.rb', line 355

def add_listener(underscored_listener_name, &block)
  enhanced_block = lambda do |event|
    event.extend(TableListenerEvent)
    block.call(event)
  end
  super(underscored_listener_name, &enhanced_block)
end

#all_table_itemsObject

Returns all table items including descendants



248
249
250
# File 'lib/glimmer/swt/table_proxy.rb', line 248

def all_table_items
  search
end

#cancel_edit!Object



277
278
279
# File 'lib/glimmer/swt/table_proxy.rb', line 277

def cancel_edit!
  @cancel_edit&.call if @edit_mode
end

#detect_sort_typeObject



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/glimmer/swt/table_proxy.rb', line 188

def detect_sort_type
  @sort_type = sort_property.size.times.map { String }
  array = model_binding.evaluate_property
  sort_property.each_with_index do |a_sort_property, i|
    values = array.map { |object| object.send(a_sort_property) }
    value_classes = values.map(&:class).uniq
    if value_classes.size == 1
      @sort_type[i] = value_classes.first
    elsif value_classes.include?(Integer)
      @sort_type[i] = Integer
    elsif value_classes.include?(Float)
      @sort_type[i] = Float
    end
  end
end

#edit_in_progress?Boolean

Indicates if table is editing a table item because the user hit ENTER or focused out after making a change in edit mode to a table item cell. It is set to false once change is saved to model

Returns:

  • (Boolean)


287
288
289
# File 'lib/glimmer/swt/table_proxy.rb', line 287

def edit_in_progress?
  !!@edit_in_progress
end

#edit_mode?Boolean

Indicates if table is in edit mode, thus displaying a text widget for a table item cell

Returns:

  • (Boolean)


273
274
275
# File 'lib/glimmer/swt/table_proxy.rb', line 273

def edit_mode?
  !!@edit_mode
end

#edit_selected_table_item(column_index, before_write: nil, after_write: nil, after_cancel: nil) ⇒ Object



291
292
293
# File 'lib/glimmer/swt/table_proxy.rb', line 291

def edit_selected_table_item(column_index, before_write: nil, after_write: nil, after_cancel: nil)
  edit_table_item(swt_widget.getSelection.first, column_index, before_write: before_write, after_write: after_write, after_cancel: after_cancel)
end

#edit_table_item(table_item, column_index, before_write: nil, after_write: nil, after_cancel: nil) ⇒ Object



295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
# File 'lib/glimmer/swt/table_proxy.rb', line 295

def edit_table_item(table_item, column_index, before_write: nil, after_write: nil, after_cancel: nil)
  return if table_item.nil?
  model = table_item.data
  property = column_properties[column_index]
  @cancel_edit&.call if @edit_mode
  action_taken = false
  @edit_mode = true
  
  editor_config = table_column_proxies[column_index].editor || editor
  editor_config = editor_config.to_a
  editor_widget_options = editor_config.last.is_a?(Hash) ? editor_config.last : {}
  editor_widget_arg_last_index = editor_config.last.is_a?(Hash) ? -2 : -1
  editor_widget = editor_config[0] || :text
  editor_widget_args = editor_config[1..editor_widget_arg_last_index]
  model_editing_property = editor_widget_options[:property] || property
  widget_value_property = TableProxy::editors[editor_widget][:widget_value_property]
  
  @cancel_edit = lambda do |event=nil|
    @cancel_in_progress = true
    @table_editor_widget_proxy&.swt_widget&.dispose
    @table_editor_widget_proxy = nil
    after_cancel&.call
    @edit_in_progress = false
    @cancel_in_progress = false
    @cancel_edit = nil
    @edit_mode = false
  end
  
  @finish_edit = lambda do |event=nil|
    new_value = @table_editor_widget_proxy&.swt_widget&.send(widget_value_property)
    if table_item.isDisposed
      @cancel_edit.call
    elsif !new_value.nil? && !action_taken && !@edit_in_progress && !@cancel_in_progress
      action_taken = true
      @edit_in_progress = true
      if new_value == model.send(model_editing_property)
        @cancel_edit.call
      else
        before_write&.call
        model.send("#{model_editing_property}=", new_value) # makes table update itself, so must search for selected table item again
        # Table refresh happens here because of model update triggering observers, so must retrieve table item again
        edited_table_item = search { |ti| ti.getData == model }.first
        swt_widget.showItem(edited_table_item)
        @table_editor_widget_proxy&.swt_widget&.dispose
        @table_editor_widget_proxy = nil
        after_write&.call(edited_table_item)              
        @edit_in_progress = false
      end
    end
  end

  content { 
    @table_editor_widget_proxy = TableProxy::editors[editor_widget][:editor_gui].call(editor_widget_args, model, model_editing_property, self)
  }
  @table_editor.setEditor(@table_editor_widget_proxy.swt_widget, table_item, column_index)
rescue => e
  Glimmer::Config.logger.error {e.full_message}
  raise e
end

#finish_edit!Object



281
282
283
# File 'lib/glimmer/swt/table_proxy.rb', line 281

def finish_edit!
  @finish_edit&.call if @edit_mode
end

#model_bindingObject



152
153
154
# File 'lib/glimmer/swt/table_proxy.rb', line 152

def model_binding
  swt_widget.data
end

#post_initialize_child(table_column_proxy) ⇒ Object



264
265
266
# File 'lib/glimmer/swt/table_proxy.rb', line 264

def post_initialize_child(table_column_proxy)
  table_column_proxies << table_column_proxy
end

#search(&condition) ⇒ Object

Performs a search for table items matching block condition If no condition block is passed, returns all table items Returns a Java TableItem array to easily set as selection on org.eclipse.swt.Table if needed



243
244
245
# File 'lib/glimmer/swt/table_proxy.rb', line 243

def search(&condition)
  swt_widget.getItems.select {|item| condition.nil? || condition.call(item)}.to_java(TableItem)
end

#sortObject



212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/glimmer/swt/table_proxy.rb', line 212

def sort
  return unless sort_property && (sort_type || sort_block || sort_by_block)
  array = model_binding.evaluate_property
  # Converting value to_s first to handle nil cases. Should work with numeric, boolean, and date fields
  if sort_block
    sorted_array = array.sort(&sort_block)
  elsif sort_by_block
    sorted_array = array.sort_by(&sort_by_block)          
  else
    sorted_array = array.sort_by do |object|
      sort_property.each_with_index.map do |a_sort_property, i|
        value = object.send(a_sort_property)
        # handle nil and difficult to compare types gracefully
        if sort_type[i] == Integer
          value = value.to_i
        elsif sort_type[i] == Float
          value = value.to_f
        elsif sort_type[i] == String
          value = value.to_s
        end
        value
      end
    end
  end
  sorted_array = sorted_array.reverse if sort_direction == :descending
  model_binding.call(sorted_array)
end

#sort_by_column(table_column_proxy) ⇒ Object



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/glimmer/swt/table_proxy.rb', line 156

def sort_by_column(table_column_proxy)
  index = swt_widget.columns.to_a.index(table_column_proxy.swt_widget)
  new_sort_property = table_column_proxy.sort_property || [column_properties[index]]
  if new_sort_property.size == 1 && !additional_sort_properties.to_a.empty?
    selected_additional_sort_properties = additional_sort_properties.clone
    if selected_additional_sort_properties.include?(new_sort_property.first)
      selected_additional_sort_properties.delete(new_sort_property.first)
      new_sort_property += selected_additional_sort_properties
    else
      new_sort_property += additional_sort_properties
    end
  end
  
  @sort_direction = @sort_direction.nil? || @sort_property != new_sort_property || @sort_direction == :descending ? :ascending : :descending        
  swt_widget.sort_direction = @sort_direction == :ascending ? SWTProxy[:up] : SWTProxy[:down]
  
  @sort_property = new_sort_property
  swt_widget.sort_column = table_column_proxy.swt_widget
  
  @sort_by_block = nil
  @sort_block = nil
  @sort_type = nil
  if table_column_proxy.sort_by_block
    @sort_by_block = table_column_proxy.sort_by_block
  elsif table_column_proxy.sort_block
    @sort_block = table_column_proxy.sort_block
  else
    detect_sort_type        
  end
  sort
end

#table_column_proxiesObject



268
269
270
# File 'lib/glimmer/swt/table_proxy.rb', line 268

def table_column_proxies
  @table_column_proxies ||= []
end

#widget_property_listener_installersObject



252
253
254
255
256
257
258
259
260
261
262
# File 'lib/glimmer/swt/table_proxy.rb', line 252

def widget_property_listener_installers
  super.merge({
    Java::OrgEclipseSwtWidgets::Table => {
      selection: lambda do |observer|
        on_widget_selected { |selection_event|
          observer.call(@swt_widget.getSelection)
        }
      end
    },        
  })
end