class Sirens::TreeView

Public Class Methods

view_accepted_styles() click to toggle source

Answer the styles accepted by this view.

Calls superclass method
# File lib/views/tree_view.rb, line 10
def view_accepted_styles()
    super() + [:show_headers, :clickable_headers, :on_selection_action ].freeze
end

Public Instance Methods

add_column_with_props(props) click to toggle source
# File lib/views/tree_view.rb, line 74
def add_column_with_props(props)
    column_index = tree_view.columns.size

    col = nil

    column_label = props[:label]

    if props.has_image_block?
        renderer = Gtk::CellRendererPixbuf.new

        col = Gtk::TreeViewColumn.new(column_label, renderer, pixbuf: column_index)
    else
        renderer = Gtk::CellRendererText.new

        col = Gtk::TreeViewColumn.new(column_label, renderer, text: column_index)
    end

    tree_view.append_column(col)
end
add_item(item:, parent_iter:, index:) click to toggle source
# File lib/views/tree_view.rb, line 235
def add_item(item:, parent_iter:, index:)
    iter = tree_store.insert(parent_iter, index)

    set_item_column_values(item: item, iter: iter)

    if parent_iter.nil?
        indices_path = [index]
    else
        indices_path = parent_iter.path.indices + [index]
    end

    children_count = get_children_at(path: indices_path).size

    if children_count > 0
        tree_store.insert(iter, 0)
    end
end
add_items(items:, parent_iter:, index:) click to toggle source

Adding

# File lib/views/tree_view.rb, line 229
def add_items(items:, parent_iter:, index:)
    items.each_with_index do |each_item, i|
        add_item(item: each_item, parent_iter: parent_iter, index: index + i)
    end
end
clear_items() click to toggle source

Actions

# File lib/views/tree_view.rb, line 217
def clear_items()
    tree_store.clear
end
clickable_headers=(boolean) click to toggle source
# File lib/views/tree_view.rb, line 152
def clickable_headers=(boolean)
    tree_view.headers_clickable = boolean
end
clickable_headers?() click to toggle source
# File lib/views/tree_view.rb, line 156
def clickable_headers?()
    tree_view.headers_clickable?
end
define_columns(columns_props_array) click to toggle source
# File lib/views/tree_view.rb, line 62
def define_columns(columns_props_array)
    @columns_props = columns_props_array

    list_store_types = @columns_props.collect { |type| tree_store_type_for(type) }

    tree_view.set_model(Gtk::TreeStore.new(*list_store_types))

    @columns_props.each do |each_column_props|
        add_column_with_props(each_column_props)
    end
end
display_data_of(item, column, column_index) click to toggle source
# File lib/views/tree_view.rb, line 289
def display_data_of(item, column, column_index)
    if column.has_image_block?
        image_file = column.display_image_of(item).to_s

        return GdkPixbuf::Pixbuf.new(file: image_file, width: 16, height: 16)
    end

    column.display_text_of(item)
end
expand(path:) click to toggle source
# File lib/views/tree_view.rb, line 328
def expand(path:)
    tree_path = Gtk::TreePath.new(
            path.join(':')
        )

    tree_view.expand_row(tree_path, false)
end
get_children_at(path:) click to toggle source
# File lib/views/tree_view.rb, line 138
def get_children_at(path:)
    @get_children_block.call(path: path)
end
get_children_block(&block) click to toggle source
# File lib/views/tree_view.rb, line 48
def get_children_block(&block)
    @get_children_block = block

    self
end
get_item_at(path:) click to toggle source
# File lib/views/tree_view.rb, line 134
def get_item_at(path:)
    @get_item_block.call(path: path)
end
get_item_block(&block) click to toggle source
# File lib/views/tree_view.rb, line 42
def get_item_block(&block)
    @get_item_block = block

    self
end
initialize_handles() click to toggle source

Initializing

# File lib/views/tree_view.rb, line 17
def initialize_handles()
    @tree_view = Gtk::TreeView.new
    @tree_view.set_model(Gtk::TreeStore.new(String))

    @main_handle = Gtk::ScrolledWindow.new
    @main_handle.add(tree_view)
    @main_handle.set_policy(:automatic, :automatic)

    @current_selection_indices = []

    @columns_props = []

    @on_selection_changed_block = nil
    @get_item_block = nil
    @get_children_block = nil
end
on_row_expanded(iter:, tree_path:) click to toggle source

To emulate a virtual tree elements are added with a child placeholder, the class placeholder constant. The first time a node is expanded if it has the child placeholder it is replaced by the actual node children. The actual children are get using the get_children_block.

# File lib/views/tree_view.rb, line 199
def on_row_expanded(iter:, tree_path:)
    child_iter = iter.first_child

    return if ! tree_store.get_value(child_iter, 0).nil?

    indices_path = tree_path.indices

    children = get_children_at(path: indices_path)

    tree_store.remove(child_iter)

    add_items(items: children, parent_iter: iter, index: 0)

    tree_view.expand_row(tree_path, false)
end
on_selection_action(tree_path:, tree_column:) click to toggle source
# File lib/views/tree_view.rb, line 183
def on_selection_action(tree_path:, tree_column:)
    return if @on_selection_action_block.nil?

    index_path = tree_path.indices

    item = get_item_at(path: index_path)

    @on_selection_action_block.call(index_path: index_path, item: item)
end
on_selection_action=(block) click to toggle source
# File lib/views/tree_view.rb, line 160
def on_selection_action=(block)
    @on_selection_action_block = block
end
on_selection_changed(tree_selection) click to toggle source

Handlers

# File lib/views/tree_view.rb, line 166
def on_selection_changed(tree_selection)
    indices = []
    items = []

    tree_selection.each do |tree_store, tree_path, iter|
        indices_path = tree_path.indices

        indices << indices_path
        items << get_item_at(path: indices_path)
    end

    @on_selection_changed_block.call(
        selection_items: items,
        selection_paths: indices
    )
end
on_selection_changed_block(&block) click to toggle source

Configuring callbacks

# File lib/views/tree_view.rb, line 36
def on_selection_changed_block(&block)
    @on_selection_changed_block = block

    self
end
remove_item(item:, index:) click to toggle source
# File lib/views/tree_view.rb, line 275
def remove_item(item:, index:)
    iter = tree_store.get_iter(index.to_s)

    tree_store.remove(iter)
end
remove_items(items:, indices:) click to toggle source

Removing

# File lib/views/tree_view.rb, line 269
def remove_items(items:, indices:)
    items.each_with_index do |each_item, i|
        remove_item(item: each_item, index: indices[i])
    end
end
rows() click to toggle source

Returns the rows contents of the tree. For testing and debugging only.

# File lib/views/tree_view.rb, line 128
def rows()
    tree_store.collect { |store, path, iter|
        iter[0]
    }
end
selection_indices() click to toggle source

Querying

# File lib/views/tree_view.rb, line 301
def selection_indices()
    indices = []

    tree_view.selection.each { |tree, path, iter|
        indices << path.to_s.to_i
    }

    indices
end
set_item_column_values(item:, iter:) click to toggle source
# File lib/views/tree_view.rb, line 281
def set_item_column_values(item:, iter:)
    @columns_props.each_with_index { |column, column_index|
        colum_value = display_data_of(item, column, column_index)

        iter.set_value(column_index, colum_value)
    }
end
set_roots(root_items) click to toggle source
# File lib/views/tree_view.rb, line 221
def set_roots(root_items)
    clear_items

    add_items(parent_iter: nil, items: root_items, index: 0)
end
set_selection_indices(indices) click to toggle source
# File lib/views/tree_view.rb, line 311
def set_selection_indices(indices)
    if indices.empty?
        tree_view.unselect_all
        return
    end

    tree_path = Gtk::TreePath.new(
            indices.join(':')
        )

    expand(path: indices[0..-2]) if indices.size > 1

    tree_view.selection.select_path(tree_path)

    tree_view.scroll_to_cell(tree_path, nil, false, 0.0, 0.0)
end
show_headers=(boolean) click to toggle source

Styles

# File lib/views/tree_view.rb, line 144
def show_headers=(boolean)
    tree_view.headers_visible = boolean
end
show_headers?() click to toggle source
# File lib/views/tree_view.rb, line 148
def show_headers?()
    tree_view.headers_visible?
end
subscribe_to_ui_events() click to toggle source

Hooking GUI signals

# File lib/views/tree_view.rb, line 96
def subscribe_to_ui_events()
    tree_view.selection.signal_connect('changed') { |tree_selection|
        on_selection_changed(tree_selection)
    }

    tree_view.signal_connect('row-activated') { |tree_view, tree_path, tree_column|
        on_selection_action(tree_path: tree_path, tree_column: tree_column)
    }

    tree_view.signal_connect('row-expanded') { |tree_view, iter, tree_path|
        on_row_expanded(iter: iter, tree_path: tree_path)
    }

    tree_view.signal_connect('button_press_event') do |tree_view, event|
        show_popup_menu(button: event.button, time: event.time) if (event.button == 3)
    end
end
tree_store() click to toggle source

Accessing

# File lib/views/tree_view.rb, line 116
def tree_store()
    tree_view.model
end
tree_store_type_for(column_props) click to toggle source

Building columns

# File lib/views/tree_view.rb, line 56
def tree_store_type_for(column_props)
    return GdkPixbuf::Pixbuf if column_props.has_image_block?

    String
end
tree_view() click to toggle source
# File lib/views/tree_view.rb, line 120
def tree_view()
    @tree_view
end
update_item(item:, index:) click to toggle source
# File lib/views/tree_view.rb, line 261
def update_item(item:, index:)
    iter = tree_store.get_iter(index.to_s)

    set_item_column_values(item: item, iter: iter)
end
update_items(items:, indices:) click to toggle source

Updating

# File lib/views/tree_view.rb, line 255
def update_items(items:, indices:)
    items.each_with_index do |each_item, i|
        update_item(item: each_item, index: indices[i])
    end
end