examples/basic_table_selection2.rb
require 'glimmer-dsl-libui'
class BasicTableSelection
TableColumnPresenter = Struct.new(:name,
:column,
:sort_indicator,
:table_presenter,
keyword_init: true) do
def toggle_sort_indicator
self.sort_indicator = self.sort_indicator != :ascending ? :ascending : :descending
end
def sort
selected_data = table_presenter.selection_mode == :zero_or_many ? table_presenter.selected_rows : table_presenter.selected_row
toggle_sort_indicator
table_presenter.data.sort_by! { |row_data| row_data[column] }
table_presenter.data.reverse! if sort_indicator == :descending
table_presenter.selection = table_presenter.selection_mode == :zero_or_many ? selected_data&.map { |selected_row| table_presenter.data.index(selected_row) } : table_presenter.data.index(selected_data)
end
end
TablePresenter = Struct.new(:data,
:column_names,
:selection_mode,
:selection,
:header_visible,
keyword_init: true) do
def selection_items
data.size.times.map { |row| "Row #{row} Selection" }
end
def toggle_header_visible
self.header_visible = !(header_visible.nil? || header_visible)
end
def column_presenters
@column_presenters ||= column_names.each_with_index.map do |column_name, column|
TableColumnPresenter.new(name: column_name, column: column, table_presenter: self)
end
end
def selected_row
selection && data[selection]
end
def selected_rows
selection && selection.is_a?(Array) && selection.map { |row| data[row] }
end
end
include Glimmer::LibUI::Application
before_body do
data = [
%w[cat meow],
%w[dog woof],
%w[chicken cock-a-doodle-doo],
%w[horse neigh],
%w[cow moo]
]
@one_table_presenter = TablePresenter.new(
data: data.dup,
column_names: ['Name', 'Description'],
selection_mode: :one, # other values are :zero_or_many , :zero_or_one, :none (default is :zero_or_one if not specified)
selection: 2, # initial selection row index (could be nil too or just left off, defaulting to 0)
header_visible: nil, # defaults to true
)
@zero_or_one_table_presenter = TablePresenter.new(
data: data.dup,
column_names: ['Name', 'Description'],
selection_mode: :zero_or_one, # other values are :zero_or_many , :one, :none (default is :zero_or_one if not specified)
selection: nil, # initial selection row index (could be an integer too or just left off, defaulting to nil)
header_visible: nil, # defaults to true
)
@zero_or_many_table_presenter = TablePresenter.new(
data: data.dup,
column_names: ['Name', 'Description'],
selection_mode: :zero_or_many, # other values are :zero_or_many , :one, :none (default is :zero_or_one if not specified)
selection: [0, 2, 4], # initial selection row index (could be an integer too or just left off, defaulting to nil)
header_visible: nil, # defaults to true
)
@none_table_presenter = TablePresenter.new(
data: data.dup,
column_names: ['Name', 'Description'],
selection_mode: :none, # other values are :zero_or_many , :zero_or_one, :one (default is :zero_or_one if not specified)
selection: nil, # defaults to nil
header_visible: nil, # defaults to true
)
end
body {
window('Basic Table Selection', 400, 300) {
tab {
tab_item('One') {
vertical_box {
vertical_box {
stretchy false
@one_table_selection_radio_buttons = radio_buttons {
items @one_table_presenter.selection_items
selected <=> [@one_table_presenter, :selection]
}
}
button('Toggle Table Header Visibility') {
stretchy false
on_clicked do
@one_table_presenter.toggle_header_visible
end
}
@one_table = table {
@one_table_presenter.column_presenters.each do |column_presenter|
text_column(column_presenter.name) {
sort_indicator <=> [column_presenter, :sort_indicator]
on_clicked do |tc, column|
puts "Clicked column #{column}: #{tc.name}"
column_presenter.sort
end
}
end
cell_rows @one_table_presenter.data
selection_mode <= [@one_table_presenter, :selection_mode]
selection <=> [@one_table_presenter, :selection]
header_visible <= [@one_table_presenter, :header_visible]
sortable false # disable default sorting behavior to demonstrate manual sorting
on_row_clicked do |t, row|
puts "Row Clicked: #{row}"
end
on_row_double_clicked do |t, row|
puts "Row Double Clicked: #{row}"
end
on_selection_changed do |t, selection, added_selection, removed_selection|
# selection is an array or nil if selection mode is zero_or_many
# otherwise, selection is a single index integer or nil when not selected
puts "Selection Changed: #{selection.inspect}"
puts "Added Selection: #{added_selection.inspect}"
puts "Removed Selection: #{removed_selection.inspect}"
end
}
}
}
tab_item('Zero-Or-One') {
vertical_box {
vertical_box {
stretchy false
@zero_or_one_table_selection_radio_buttons = radio_buttons {
items @zero_or_one_table_presenter.selection_items
selected <=> [@zero_or_one_table_presenter, :selection]
}
}
button('Toggle Table Header Visibility') {
stretchy false
on_clicked do
@zero_or_one_table_presenter.toggle_header_visible
end
}
@zero_or_one_table = table {
@zero_or_one_table_presenter.column_presenters.each do |column_presenter|
text_column(column_presenter.name) {
sort_indicator <=> [column_presenter, :sort_indicator]
on_clicked do |tc, column|
puts "Clicked column #{column}: #{tc.name}"
column_presenter.sort
end
}
end
cell_rows @zero_or_one_table_presenter.data
selection_mode <= [@zero_or_one_table_presenter, :selection_mode]
selection <=> [@zero_or_one_table_presenter, :selection]
header_visible <= [@zero_or_one_table_presenter, :header_visible]
sortable false # disable default sorting behavior to demonstrate manual sorting
on_row_clicked do |t, row|
puts "Row Clicked: #{row}"
end
on_row_double_clicked do |t, row|
puts "Row Double Clicked: #{row}"
end
on_selection_changed do |t, selection, added_selection, removed_selection|
# selection is an array or nil if selection mode is zero_or_many
# otherwise, selection is a single index integer or nil when not selected
puts "Selection Changed: #{selection.inspect}"
puts "Added Selection: #{added_selection.inspect}"
puts "Removed Selection: #{removed_selection.inspect}"
end
}
}
}
tab_item('Zero-Or-Many') {
vertical_box {
vertical_box {
stretchy false
@zero_or_many_table_selection_checkboxes = @zero_or_many_table_presenter.data.size.times.map do |row|
checkbox("Row #{row} Selection") {
checked <=> [@zero_or_many_table_presenter, :selection,
on_read: ->(selection_rows) {selection_rows.to_a.include?(row)},
on_write: ->(checked_value) {
checked_value ?
(@zero_or_many_table_presenter.selection.to_a + [row]).uniq :
@zero_or_many_table_presenter.selection.to_a.reject {|v| v == row }
},
]
}
end
}
button('Toggle Table Header Visibility') {
stretchy false
on_clicked do
@zero_or_many_table_presenter.toggle_header_visible
end
}
@zero_or_many_table = table {
@zero_or_many_table_presenter.column_presenters.each do |column_presenter|
text_column(column_presenter.name) {
sort_indicator <=> [column_presenter, :sort_indicator]
on_clicked do |tc, column|
puts "Clicked column #{column}: #{tc.name}"
column_presenter.sort
end
}
end
cell_rows @zero_or_many_table_presenter.data
selection_mode <= [@zero_or_many_table_presenter, :selection_mode]
selection <=> [@zero_or_many_table_presenter, :selection]
header_visible <= [@zero_or_many_table_presenter, :header_visible]
sortable false # disable default sorting behavior to demonstrate manual sorting
on_row_clicked do |t, row|
puts "Row Clicked: #{row}"
end
on_row_double_clicked do |t, row|
puts "Row Double Clicked: #{row}"
end
on_selection_changed do |t, selection, added_selection, removed_selection|
# selection is an array or nil if selection mode is zero_or_many
# otherwise, selection is a single index integer or nil when not selected
puts "Selection Changed: #{selection.inspect}"
puts "Added Selection: #{added_selection.inspect}"
puts "Removed Selection: #{removed_selection.inspect}"
end
}
}
}
tab_item('None') {
vertical_box {
button('Toggle Table Header Visibility') {
stretchy false
on_clicked do
@none_table_presenter.toggle_header_visible
end
}
@none_table = table {
@none_table_presenter.column_presenters.each do |column_presenter|
text_column(column_presenter.name) {
sort_indicator <=> [column_presenter, :sort_indicator]
on_clicked do |tc, column|
puts "Clicked column #{column}: #{tc.name}"
column_presenter.sort
end
}
end
cell_rows @none_table_presenter.data
selection_mode <= [@none_table_presenter, :selection_mode]
selection <=> [@none_table_presenter, :selection]
header_visible <= [@none_table_presenter, :header_visible]
sortable false # disable default sorting behavior to demonstrate manual sorting
on_row_clicked do |t, row|
puts "Row Clicked: #{row}"
end
on_row_double_clicked do |t, row|
puts "Row Double Clicked: #{row}"
end
}
}
}
}
}
}
end
BasicTableSelection.launch