#!/usr/bin/ruby -w
# Encoding: UTF-8
# frozen_string_literal: true
# =========================================================================== #
# === Gtk::TreeView
# =========================================================================== #
# require 'gtk_paradise/core_classes/tree_view.rb'
# =========================================================================== #
module Gtk

class TreeView # === Gtk::TreeView

  # ========================================================================= #
  # === do_not_allow_editing
  # ========================================================================= #
  def do_not_allow_editing
  end

  # ========================================================================= #
  # == deselect_on_right_click_event
  # ========================================================================= #
  def deselect_on_right_click_event
    on_button_press_event { |widget, event|
      case event.button
      when 3 # Right-mouse button was clicked here.
        self.deselect
      end
    }
  end

  # ========================================================================= #
  # === rubber_banding
  # ========================================================================= #
  def rubber_banding
    set_rubber_banding(true)
  end

  # ========================================================================= #
  # === do_use_clickable_headers
  # ========================================================================= #
  def do_use_clickable_headers
    self.headers_clickable = true
  end; alias use_clickable_headers     do_use_clickable_headers # === use_clickable_headers
       alias clickable_headers         do_use_clickable_headers # === clickable_headers
       alias the_headers_are_clickable do_use_clickable_headers # === the_headers_are_clickable

  # ========================================================================= #
  # === deselect
  # ========================================================================= #
  def deselect
    selection.unselect_all
  end; alias deselect_everything deselect # === deselect_everything

  # ========================================================================= #
  # === all_are_sortable
  #
  # This method can be used to make all columns sortable, by the proper 
  # entry. This is not flexible, so only use it when you need nothing
  # more complex than the iterated column to be sorted by its own
  # dataset.
  #
  # It will be applied onto ALL columns, so only call the method if you
  # really want that.
  #
  # Note that this is NOT the same as calling .sortable_based_on() -
  # the latter implements the actual arrow-down interface that the
  # user can then use, by clicking on it. The method here does NOT
  # do so.
  # ========================================================================= #
  def all_are_sortable(
      columns = columns?
    )
    columns.each_with_index {|content, index|
      content.set_sort_column_id(index)
    }
  end; alias make_sortable         all_are_sortable # === make_sortable
       alias make_resizable        all_are_sortable # === make_resizable
       alias is_sortable           all_are_sortable # === is_sortable
       alias linear_sorting        all_are_sortable # === linear_sorting
       alias the_rows_are_sortable all_are_sortable # === the_rows_are_sortable

  # ========================================================================= #
  # === allow_resizing
  #
  # Note that for the default-input to this method to work, the columns
  # must have been added already. So you may have to invoke
  # .allow_resizing() only after the columns were already defined.
  # ========================================================================= #
  def allow_resizing(
      modify_these_columns = columns?
    )
    modify_these_columns.each {|this_column|
      this_column.set_resizable(true)
    }
  end; alias can_be_resized             allow_resizing # === can_be_resized
       alias resizable_headers          allow_resizing # === resizable_headers
       alias headers_can_be_moved       allow_resizing # === headers_can_be_moved
       alias the_headers_can_be_dragged allow_resizing # === the_headers_can_be_dragged
       alias the_headers_can_be_moved   allow_resizing # === the_headers_can_be_moved
       alias the_header_can_be_dragged  allow_resizing # === the_header_can_be_dragged
       alias the_header_can_be_resized  allow_resizing # === the_header_can_be_resized
       alias the_headers_are_resizable  allow_resizing # === the_headers_are_resizable
       alias the_headers_can_be_resized allow_resizing # === the_headers_can_be_resized
       alias the_header_are_clickable   allow_resizing # === the_headers_are_clickable

  # ========================================================================= #
  # === clear
  #
  # Remove the associated list-store. This currently does not work
  # very well.
  # ========================================================================= #
  def clear
    self.model = nil # Or list_store.clear
  end

  # ========================================================================= #
  # === enable_drag_and_drop
  #
  # Simplified method to enable drag-and-drop.
  # ========================================================================= #
  def enable_drag_and_drop
    # ===================================================================== #
    # === GTK3
    # ===================================================================== #
    target_table = [['GTK_TREE_MODEL_ROW', 0, 0]]
    enable_model_drag_source(:button1_mask, 
      target_table,
      Gdk::DragAction::COPY|Gdk::DragAction::MOVE
    )
    enable_model_drag_dest(
      target_table,
      Gdk::DragAction::COPY|Gdk::DragAction::MOVE
    )
  end; alias enable_dragging                  enable_drag_and_drop # === enable_dragging
       alias make_reorderable                 enable_drag_and_drop # === make_reorderable
       alias is_reorderable                   enable_drag_and_drop # === is_reorderable
       alias the_columns_can_be_rearranged    enable_drag_and_drop # === the_columns_can_be_rearranged
       alias drag_action_copy_and_action_move enable_drag_and_drop # === drag_action_copy_and_action_move

  # ========================================================================= #
  # === enable_search
  # ========================================================================= #
  def enable_search
    set_enable_search(true)
  end

  # ========================================================================= #
  # === disable_search
  # ========================================================================= #
  def disable_search
    set_enable_search(false)
  end; alias no_search disable_search # === no_search

  # ========================================================================= #
  # === remove_the_columns
  # ========================================================================= #
  def remove_the_columns
    columns.each {|this_column|
      remove_column(this_column)
    }
  end; alias remove_all_columns remove_the_columns # === remove_all_columns

  # ========================================================================= #
  # === use_these_headers
  #
  # The last element to this method must be the cell-renderer. If it
  # is not provided then the method will automatically use a new
  # cell-renderer (Gtk::CellRendererText to be precise).
  #
  # Usage example:
  #
  #   @tree_view.use_these_headers('#', 'Name of the course', 'Exam Date')
  #
  # ========================================================================= #
  def use_these_headers(*i)
    i.flatten!
    last_element = i.last
    if last_element.is_a? ::Gtk::CellRendererText
      renderer = i.pop # Remove the last element.
    else
      renderer = ::Gtk::CellRendererText.new
    end
    i.each_with_index {|entry, index|
      append(entry.to_s, renderer, text: index)
    }
  end; alias add_these_headers  use_these_headers # === add_these_headers
       alias use_these_headers= use_these_headers # === use_these_headers=
       alias headers=           use_these_headers # === headers=
       alias headers            use_these_headers # === headers

  # ========================================================================= #
  # === on_left_mouse_button_double_click_event
  #
  # This method currently does not work; unsure how to make this work,
  # either. (October 2020)
  # ========================================================================= #
  def on_left_mouse_button_double_click_event(&block)
    signal_connect(:button_press_event) { |widget, event|
      if event.event_type == Gdk::Event::BUTTON2_PRESS and event.button == 1 # event.event_type.name
        if block_given?
          yield
        end
      end
    }
  end

  # ========================================================================= #
  # === model?
  # ========================================================================= #
  def model?
    model
  end

  # ========================================================================= #
  # === second_entry?
  # ========================================================================= #
  def second_entry?
    return selection.selected[1].to_s
  end

  # ========================================================================= #
  # === second_selection
  # ========================================================================= #
  def second_selection
    selection.selected[1]
  end

  # ========================================================================= #
  # === columns?
  #
  # This is not an alias anymore, as the method called .columns() may not
  # always be available.
  # ========================================================================= #
  def columns?
    columns
  end

  # ========================================================================= #
  # === append_columns
  # ========================================================================= #
  def append_columns(*i)
    i.flatten.compact.each {|this_column|
      append_column(this_column)
    }
  end

  # ========================================================================= #
  # === return_the_selection
  #
  # This method will return the first selection in a given Gtk::TreeView.
  # ========================================================================= #
  def return_the_selection
    this_selection = selection.selected
    if this_selection # Protect against nil values.
      return this_selection[0].to_s
    end
    this_selection
  end; alias selection? return_the_selection # === selection?
       alias selected?  return_the_selection # === selected?

  # ========================================================================= #
  # === second_column?
  # ========================================================================= #
  def second_column?
    columns?[1]
  end

  # ========================================================================= #
  # === first_column?
  # ========================================================================= #
  def first_column?
    columns?[0]
  end

  # ========================================================================= #
  # === append
  #
  # This variant can be used as a simplified alternative to insert_column().
  #
  # Usage example:
  #
  #   @tree_view.append('n ECTS', @renderer, text: 2)
  #
  # ========================================================================= #
  def append(
      string_to_add   = '',
      renderer_to_use = ::Gtk::CellRendererText.new, 
      array_or_hash
    )
    if array_or_hash.is_a? Array
      # ===================================================================== #
      # Must have three elements in that case.
      # ===================================================================== #
      string_to_add   = array_or_hash.shift
      renderer_to_use = array_or_hash.shift
      array_or_hash   = array_or_hash.shift
    end
    insert_column(
      -1,
      string_to_add,
      renderer_to_use,
      array_or_hash
    )
  end; alias <<                 append # === <<
       alias append_this_column append # === append_this_column
       alias quick_append       append # === quick_append

  # ========================================================================= #
  # === enable_selection_single
  #
  # This method enables single-selection.
  # ========================================================================= #
  def enable_selection_single(
      selection_single = :single
    )
    selection.mode = selection_single
  end; alias enable_single_selection enable_selection_single # === enable_single_selection

  # ========================================================================= #
  # === enable_selection_multiple
  #
  # This method enables multiple-selection.
  # ========================================================================= #
  def enable_selection_multiple
    selection.mode = :multiple # For ruby-gtk3.
  end; alias do_select_multiple enable_selection_multiple # === do_select_multiple

end

# =========================================================================== #
# === Gtk.tree_view
# =========================================================================== #
def self.tree_view(optional_argument = nil)
  if Gtk.do_we_use_gtk2?
    ::Gtk::TreeView.new
  else
    ::Gtk::TreeView.new(optional_argument)
  end
end; self.instance_eval { alias gtk_tree_view tree_view } # === Gtk.gtk_tree_view
     self.instance_eval { alias treeview      tree_view } # === Gtk.treeview

end