class Glimmer::SWT::TableProxy
Constants
- STYLE
Attributes
additional_sort_properties[R]
column_properties[RW]
columns[R]
data[RW]
editor[R]
item_count[RW]
model_binding[RW]
selection[R]
sort_block[R]
sort_by_block[R]
sort_column[R]
sort_property[R]
sort_type[R]
table_editor[R]
Public Class Methods
editors()
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 50 def editors @editors ||= { # ensure editor can work with string keys not just symbols (leave one string in for testing) text: { widget_value_property: :text, editor_gui: lambda do |args, model, property, table_proxy| table_proxy.table_editor.minimumWidth = 90 table_proxy.table_editor.minimumHeight = 10 table_editor_widget_proxy = text(*args) { text model.send(property) focus true on_focus_lost { table_proxy.finish_edit! } on_modify_text do |event| # No Op, just record @text changes on key up # TODO find a better solution than this in the future end 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 # TODO select all 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.minimumWidth = 90 table_proxy.table_editor.minimumHeight = 18 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.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, }, date: { widget_value_property: :date_time, editor_gui: lambda do |args, model, property, table_proxy| first_time = true table_proxy.table_editor.minimumWidth = 90 table_proxy.table_editor.minimumHeight = 15 date(*args) { date_time model.send(property) focus true on_widget_selected { 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, }, date_drop_down: { widget_value_property: :date_time, editor_gui: lambda do |args, model, property, table_proxy| first_time = true table_proxy.table_editor.minimumWidth = 80 table_proxy.table_editor.minimumHeight = 15 date_drop_down(*args) { date_time model.send(property) focus true on_widget_selected { 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, }, time: { widget_value_property: :date_time, editor_gui: lambda do |args, model, property, table_proxy| first_time = true table_proxy.table_editor.minimumWidth = 80 table_proxy.table_editor.minimumHeight = 15 time(*args) { date_time 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, }, spinner: { widget_value_property: :selection, editor_gui: lambda do |args, model, property, table_proxy| first_time = true table_proxy.table_editor.minimumHeight = 25 table_editor_widget_proxy = spinner(*args) { selection 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 end, }, } end
new(parent, args, block)
click to toggle source
Calls superclass method
Glimmer::SWT::CompositeProxy::new
# File lib/glimmer/swt/table_proxy.rb, line 252 def initialize(parent, args, block) super(parent, args, block) @columns = [] @children = [] @editors = [] @selection = [] @table_editor = TableEditor.new(self) @table_editor.horizontalAlignment = SWTProxy[:left] @table_editor.grabHorizontal = true @table_editor.minimumWidth = 90 @table_editor.minimumHeight = 20 if editable? add_editable_event_listener end end
Public Instance Methods
add_editable_event_listener()
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 328 def add_editable_event_listener @editable_on_mouse_up_event_listener = on_mouse_up { |event| edit_table_item(event.table_item, event.column_index) if editable? } end
add_listener(underscored_listener_name, &block)
click to toggle source
Calls superclass method
# File lib/glimmer/swt/table_proxy.rb, line 606 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
additional_sort_properties=(*args)
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 498 def additional_sort_properties=(*args) @additional_sort_properties = args unless args.empty? end
cancel_edit!()
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 511 def cancel_edit! @cancel_edit&.call if @edit_mode end
cells_for(model)
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 356 def cells_for(model) column_properties.map {|property| model.send(property)} end
column_sort_properties()
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 408 def column_sort_properties column_properties.zip(columns.map(&:sort_property)).map do |pair| pair.compact.last.to_collection end end
columns_dom()
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 703 def columns_dom tr { } end
columns_dom_element()
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 691 def columns_dom_element Document.find(columns_path) end
columns_path()
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 687 def columns_path path + ' thead tr' end
default_layout()
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 298 def default_layout nil end
detect_sort_type()
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 392 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
dom()
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 723 def dom table_id = id table_id_style = css table_id_css_classes = css_classes table_id_css_classes << 'table' unless table_id_css_classes.include?('table') table_id_css_classes << 'editable' if editable? && !table_id_css_classes.include?('editable') table_id_css_classes_string = table_id_css_classes.to_a.join(' ') @dom ||= html { table(id: table_id, style: table_id_style, class: table_id_css_classes_string) { thead_dom items_dom } }.to_s end
edit_in_progress?()
click to toggle source
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
# File lib/glimmer/swt/table_proxy.rb, line 521 def edit_in_progress? !!@edit_in_progress end
edit_mode?()
click to toggle source
Indicates if table is in edit mode, thus displaying a text widget for a table item cell
# File lib/glimmer/swt/table_proxy.rb, line 507 def edit_mode? !!@edit_mode end
edit_selected_table_item(column_index, before_write: nil, after_write: nil, after_cancel: nil)
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 525 def edit_selected_table_item(column_index, before_write: nil, after_write: nil, after_cancel: nil) edit_table_item(selection.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)
click to toggle source
TODO migrate the following to the next method
def edit_table_item(table_item, column_index) table_item&.edit(column_index) unless column_index.nil? end
# File lib/glimmer/swt/table_proxy.rb, line 534 def edit_table_item(table_item, column_index, before_write: nil, after_write: nil, after_cancel: nil) return if table_item.nil? || (@edit_mode && @edit_table_item == table_item && @edit_column_index == column_index) @edit_column_index = column_index @edit_table_item = table_item column_index = column_index.to_i model = table_item.data property = column_properties[column_index] cancel_edit! return unless columns[column_index].editable? action_taken = false @edit_mode = true editor_config = columns[column_index].editor || editor editor_config = editor_config.to_collection 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).to_sym editor_widget_args = editor_config[1..editor_widget_arg_last_index] model_editing_property = editor_widget_options[:property] || property widget_value_property = TableProxy::editors.symbolize_keys[editor_widget][:widget_value_property] @cancel_edit = lambda do |event=nil| @cancel_in_progress = true @table_editor.cancel! @table_editor_widget_proxy&.dispose @table_editor_widget_proxy = nil after_cancel&.call @edit_in_progress = false @cancel_in_progress = false @cancel_edit = nil @edit_table_item = @edit_column_index = nil if (@edit_mode && @edit_table_item == table_item && @edit_column_index == column_index) @edit_mode = false end @finish_edit = lambda do |event=nil| new_value = @table_editor_widget_proxy&.send(widget_value_property) if table_item.disposed? @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 @table_editor.save!(widget_value_property: widget_value_property) 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.data == model }.first show_item(edited_table_item) @table_editor_widget_proxy&.dispose @table_editor_widget_proxy = nil after_write&.call(edited_table_item) @edit_in_progress = false @edit_table_item = @edit_column_index = nil end end end content { @table_editor_widget_proxy = TableProxy::editors.symbolize_keys[editor_widget][:editor_gui].call(editor_widget_args, model, model_editing_property, self) } @table_editor.set_editor(@table_editor_widget_proxy, table_item, column_index) rescue => e Glimmer::Config.logger.error {e.full_message} raise e end
editable=(value)
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 316 def editable=(value) if value args.push(:editable) dom_element.addClass('editable') add_editable_event_listener else args.delete(:editable) dom_element.removeClass('editable') @editable_on_mouse_up_event_listener.deregister # TODO see why table event listener deregistration is not working end end
editable?()
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 311 def editable? args.include?(:editable) end
Also aliased as: editable
editor=(args)
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 502 def editor=(args) @editor = args end
element()
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 683 def element 'table' end
finish_edit!()
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 515 def finish_edit! @finish_edit&.call if @edit_mode end
get_data(key=nil)
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 302 def get_data(key=nil) data end
header_visible()
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 624 def header_visible @header_visible end
header_visible=(value)
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 615 def header_visible=(value) @header_visible = value if @header_visible thead_dom_element.remove_class('hide') else thead_dom_element.add_class('hide') end end
index_of(item)
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 364 def index_of(item) items.index(item) end
initial_sort!()
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 465 def initial_sort! sort_by_column! end
item_count=(value)
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 351 def item_count=(value) @item_count = value redraw_empty_items end
items=(new_items)
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 345 def items=(new_items) @children = new_items # TODO optimize in the future by sorting elements in DOM directly when no change to elements occur other than sort redraw end
items_dom()
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 718 def items_dom tbody { } end
items_dom_element()
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 699 def items_dom_element Document.find(items_path) end
items_path()
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 695 def items_path path + ' tbody' end
observation_request_to_event_mapping()
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 632 def observation_request_to_event_mapping mouse_handler = -> (event_listener) { -> (event) { event.singleton_class.send(:define_method, :table_item=) do |item| @table_item = item end event.singleton_class.send(:define_method, :table_item) do @table_item end table_row = event.target.parents('tr').first table_data = event.target.parents('td').first event.table_item = items.detect {|item| item.id == table_row.attr('id')} event.singleton_class.send(:define_method, :column_index) do (table_data || event.target).attr('data-column-index') end event_listener.call(event) unless event.table_item.nil? && event.column_index.nil? } } { 'on_mouse_down' => { event: 'mousedown', event_handler: mouse_handler, }, 'on_mouse_up' => { event: 'mouseup', event_handler: mouse_handler, }, 'on_widget_selected' => { event: 'mouseup', event_handler: mouse_handler, }, } end
post_add_content()
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 292 def post_add_content return if @initially_sorted initial_sort! @initially_sorted = true end
post_dispose_child(child)
click to toggle source
Executes for the parent of a child that just got disposed
# File lib/glimmer/swt/table_proxy.rb, line 282 def post_dispose_child(child) if child.is_a?(TableColumnProxy) @columns&.delete(child) elsif child.is_a?(TableItemProxy) @children&.delete(child) else @editors&.delete(child) end end
post_initialize_child(child)
click to toggle source
Only table_columns may be added as children
# File lib/glimmer/swt/table_proxy.rb, line 269 def post_initialize_child(child) if child.is_a?(TableColumnProxy) @columns << child child.render elsif child.is_a?(TableItemProxy) @children << child child.render else @editors << child end end
redraw()
click to toggle source
Calls superclass method
# File lib/glimmer/swt/table_proxy.rb, line 668 def redraw super() @columns.to_a.each(&:redraw) redraw_empty_items end
redraw_empty_items()
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 674 def redraw_empty_items if @children&.size.to_i < item_count.to_i item_count.to_i.times do empty_columns = column_properties&.size.to_i.times.map { |i| "<td data-column-index='#{i}'></td>" } items_dom_element.append("<tr class='table-item empty-table-item'>#{empty_columns}</tr>") end end end
remove_all()
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 306 def remove_all items.clear redraw end
search(&condition)
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 360 def search(&condition) items.select {|item| condition.nil? || condition.call(item)} end
select(index, meta = false)
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 368 def select(index, meta = false) new_selection = @selection.clone selected_item = items[index] if @selection.include?(selected_item) new_selection.delete(selected_item) if meta else new_selection = [] if !meta || (!has_style?(:multi) && @selection.to_a.size >= 1) new_selection << selected_item end self.selection = new_selection end
selection=(new_selection)
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 338 def selection=(new_selection) new_selection = new_selection.to_a changed = (selection + new_selection) - (selection & new_selection) @selection = new_selection changed.each(&:redraw_selection) end
selector()
click to toggle source
Calls superclass method
# File lib/glimmer/swt/table_proxy.rb, line 628 def selector super + ' tbody' end
show_item(table_item)
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 602 def show_item(table_item) table_item.dom_element.focus end
sort!()
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 469 def sort! return unless sort_property && (sort_type || sort_block || sort_by_block) array = model_binding.evaluate_property array = array.sort_by(&:hash) # this ensures consistent subsequent sorting in case there are equivalent sorts to avoid an infinite loop # 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_block=(comparator)
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 380 def sort_block=(comparator) @sort_block = comparator end
sort_by_block=(property_picker)
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 384 def sort_by_block=(property_picker) @sort_by_block = property_picker end
sort_by_column!(table_column_proxy=nil)
click to toggle source
Sorts by specified TableColumnProxy
object. If nil, it uses the table default sort instead.
# File lib/glimmer/swt/table_proxy.rb, line 423 def sort_by_column!(table_column_proxy=nil) index = columns.to_a.index(table_column_proxy) unless table_column_proxy.nil? new_sort_property = table_column_proxy.nil? ? @sort_property : table_column_proxy.sort_property || [column_properties[index]] return if table_column_proxy.nil? && new_sort_property.nil? && @sort_block.nil? && @sort_by_block.nil? if new_sort_property && table_column_proxy.nil? && new_sort_property.size == 1 && (index = column_sort_properties.index(new_sort_property)) table_column_proxy = columns[index] end if new_sort_property && 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 new_sort_property = new_sort_property.to_collection unless new_sort_property.is_a?(Array) @sort_direction = @sort_direction.nil? || @sort_property.first != new_sort_property.first || @sort_direction == :descending ? :ascending : :descending @sort_property = new_sort_property table_column_index = column_properties.index(new_sort_property.to_s.to_sym) table_column_proxy ||= columns[table_column_index] if table_column_index @sort_column = table_column_proxy if table_column_proxy if table_column_proxy @sort_by_block = nil @sort_block = nil end @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
sort_direction()
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 414 def sort_direction @sort_direction == :ascending ? SWTProxy[:up] : SWTProxy[:down] end
sort_direction=(value)
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 418 def sort_direction=(value) @sort_direction = value == SWTProxy[:up] ? :ascending : :descending end
sort_property=(new_sort_property)
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 388 def sort_property=(new_sort_property) @sort_property = new_sort_property.to_collection end
thead_dom()
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 708 def thead_dom thead { columns_dom } end
thead_dom_element()
click to toggle source
# File lib/glimmer/swt/table_proxy.rb, line 714 def thead_dom_element dom_element.find('thead') end
Private Instance Methods
property_type_converters()
click to toggle source
Calls superclass method
# File lib/glimmer/swt/table_proxy.rb, line 740 def property_type_converters super.merge({ selection: lambda do |value| if value.is_a?(Array) search {|ti| value.include?(ti.get_data) } else search {|ti| ti.get_data == value} end end, }) end