# frozen_string_literal: false
#
#  templdlg demo  ---  called from demo.rb
#
unless Object.const_defined?('DemoVar')
  fail RuntimeError, "This is NOT a stand alone script. This script is called from 'demo.rb'. "
end

module DemoTree
  @@count = 0
  @@dblclick = false
  @@top = nil

  def self.create(nb)
    frame = nb.insert('end', 'demoTree', :text=>'Tree')
    pw = Tk::BWidget::PanedWindow.new(frame, :side=>:top)

    pane = pw.add(:weight=>1)
    title = Tk::BWidget::TitleFrame.new(pane, :text=>'Directory tree')
    sw = Tk::BWidget::ScrolledWindow.new(title.get_frame,
                                         :relief=>:sunken, :borderwidth=>2)
    tree = Tk::BWidget::Tree.new(sw, :relief=>:flat, :borderwidth=>0,
                                 :width=>15, :highlightthickness=>0,
                                 :redraw=>false, :dropenabled=>true,
                                 :dragenabled=>true, :dragevent=>3,
                                 :droptypes=>[
                                   'TREE_NODE', [
                                     :copy, [],
                                     :move, [],
                                     :link, []
                                   ],
                                   'LISTBOX_ITEM', [
                                     :copy, [],
                                     :move, [],
                                     :link, []
                                   ]
                                 ],
                                 :opencmd=>proc{|node|
                                   moddir(1, tree, node)
                                 },
                                 :closecmd=>proc{|node|
                                   moddir(0, tree, node)
                                 })
    sw.set_widget(tree)

    sw.pack(:side=>:top, :expand=>true, :fill=>:both)
    title.pack(:fill=>:both, :expand=>true)

    pane = pw.add(:weight=>2)
    lf = Tk::BWidget::TitleFrame.new(pane, :text=>'Content')
    sw = Tk::BWidget::ScrolledWindow.new(lf.get_frame,
                                         :scrollbar=>:horizontal,
                                         :auto=>:none, :relief=>:sunken,
                                         :borderwidth=>2)

    list = Tk::BWidget::ListBox.new(sw, :relief=>:flat, :borderwidth=>0,
                                    :highlightthickness=>0, :width=>20,
                                    :multicolumn=>true, :redraw=>false,
                                    :dragevent=>3, :dropenabled=>true,
                                    :dragenabled=>true,
                                 :droptypes=>[
                                      'TREE_NODE', [
                                        :copy, [],
                                        :move, [],
                                        :link, []
                                      ],
                                      'LISTBOX_ITEM', [
                                        :copy, [],
                                        :move, [],
                                        :link, []
                                      ]
                                    ])
    sw.set_widget(list)

    Tk.pack(sw, lf, :fill=>:both, :expand=>true)

    pw.pack(:fill=>:both, :expand=>true)

    tree.textbind('ButtonPress-1',
                  proc{|node, ev| select('tree', 1, tree, list, node)})
    tree.textbind('Double-ButtonPress-1',
                  proc{|node, ev| select('tree', 2, tree, list, node)})

    list.textbind('ButtonPress-1',
                  proc{|node, ev| select('list', 1, tree, list, node)})
    list.textbind('Double-ButtonPress-1',
                  proc{|node, ev| select('list', 2, tree, list, node)})

    list.imagebind('Double-ButtonPress-1',
                   proc{|node, ev| select('list', 2, tree, list, node)})

    nb.itemconfigure('demoTree',
                     :createcmd=>proc{|*args| init(tree, list, *args)},
                     :raisecmd=>proc{
                       Tk.root.geometry =~
                         /\d+x\d+([+-]{1,2}\d+)([+-]{1,2}\d+)/
                       global_w = ($1 || 0).to_i
                       global_h = ($2 || 0).to_i
                       if @@top
                         Tk::BWidget.place(@@top, 0, 0, :at,
                            global_w - Tk.root.winfo_screenwidth, global_h)
                         @@top.deiconify
                         Tk.root.bind('Unmap', proc{@@top.withdraw})
                         Tk.root.bind('Map',   proc{@@top.deiconify})
                         Tk.root.bind('Configure', proc{|w|
                                if w == Tk.root
                                  Tk.root.geometry =~
                                    /\d+x\d+([+-]{1,2}\d+)([+-]{1,2}\d+)/
                                  global_w = ($1 || 0).to_i
                                  global_h = ($2 || 0).to_i
                                  Tk::BWidget.place(@@top, 0, 0, :at,
                                       global_w - Tk.root.winfo_screenwidth,
                                       global_h)
                                end
                         }, '%W')
                       end
                     },
                     :leavecmd=>proc{
                       @@top.withdraw if @@top
                       Tk.root.bind_remove('Unmap')
                       Tk.root.bind_remove('Map')
                       Tk.root.bind_remove('Configure')
                       true
                     })
  end

  def self.init(tree, list, *args)
    @@count = 0
    if Tk::PLATFORM['platform'] == 'unix'
      rootdir = File.expand_path('~')
    else
      rootdir = 'c:'
    end

    tree.insert('end', 'root', 'home',
                :text=>rootdir, :data=>rootdir, :open=>true,
                :image=>Tk::BWidget::Bitmap.new('openfold'))
    getdir(tree, 'home', rootdir)
    select('tree', 1, tree, list, 'home')
    tree.redraw(true)
    list.redraw(true)

    @@top = TkToplevel.new
    @@top.withdraw
    @@top.protocol('WM_DELETE_WINDOW'){
      # don't kill me
    }
    @@top.resizable(false, false)
    @@top.title('Drag rectangle to scroll directory tree')
    @@top.transient(Tk.root)
    Tk::BWidget::ScrollView.new(@@top, :window=>tree, :fill=>'white',
                                :width=>300, :height=>300, :relief=>:sunken,
                                :bd=>1).pack(:fill=>:both, :expand=>true)
  end

  def self.getdir(tree, node, path)
    lentries = Dir.glob(File.join(path, '*')).sort
    lfiles = []
    lentries.each{|f|
      basename = File.basename(f)
      if File.directory?(f)
        Tk::BWidget::Tree::Node.new(tree, node,
                                    :index=>'end', :text=>basename,
                                    :image=>Tk::BWidget::Bitmap.new('folder'),
                                    :drawcross=>:always, :data=>f)
        @@count += 1
      else
        lfiles << basename
      end
    }
    tree.itemconfigure(node, :drawcross=>:auto, :data=>lfiles)
  end

  def self.moddir(idx, tree, node)
    if (idx != 0 && tree.itemcget(node, :drawcross).to_s == 'always')
      getdir(tree, node, tree.itemcget(node, :data))
      if tree.nodes(node).empty?
        tree.itemconfigure(node, :image=>Tk::BWidget::Bitmap.new('folder'))
      else
        tree.itemconfigure(node, :image=>Tk::BWidget::Bitmap.new('openfold'))
      end
    else
      img = %w(folder openfold)[idx] || 'openfold'
      tree.itemconfigure(node, :image=>Tk::BWidget::Bitmap.new(img))
    end
  end

  def self.select(where, num, tree, list, node)
    @@dblclick = true
    if num == 1
      if (where == 'tree' &&
          tree.selection_get.find{|x|
            TkUtil._get_eval_string(x) == TkUtil._get_eval_string(node)
          })
        @@dblclick = false
        Tk.after(500, proc{edit('tree', tree, list, node)})
        return
      end
      if (where == 'list' &&
          list.selection_get.find{|x|
            TkUtil._get_eval_string(x) == TkUtil._get_eval_string(node)
          })
        @@dblclick = false
        Tk.after(500, proc{edit('list', tree, list, node)})
        return
      end
      if where == 'tree'
        select_node(tree, list, node)
      else
        list.selection_set(node)
      end
    elsif (where == 'list' && tree.exist?(node))
      parent = tree.parent(node)
      while TkUtil._get_eval_string(parent) != 'root'
        tree.itemconfigure(parent, :open=>true)
        parent = tree.parent(parent)
      end
      select_node(tree, list, node)
    end
  end

  def self.select_node(tree, list, node)
    tree.selection_set(node)
    Tk.update
    list.delete(*(list.items(0, 'end')))

    dir = tree.itemcget(node, :data)
    if tree.itemcget(node, :drawcross).to_s == 'always'
      getdir(tree, node, dir)
      dir = tree.itemcget(node, :data)
    end

    tree.nodes(node).each{|subnode|
      list.insert('end', subnode,
                  :text=>tree.itemcget(subnode, :text),
                  :image=>Tk::BWidget::Bitmap.new('folder'))
    }

    TkComm.simplelist(dir).each{|f|
      Tk::BWidget::ListBox::Item.new(list, 'end', :text=>f,
                                     :image=>Tk::BWidget::Bitmap.new('file'))
    }
  end

  def self.edit(where, tree, list, node)
    return if @@dblclick

    if (where == 'tree' &&
        tree.selection_get.find{|x|
          TkUtil._get_eval_string(x) == TkUtil._get_eval_string(node)
        })
      res = tree.edit(node, tree.itemcget(node, :text))
      if res != ''
        tree.itemconfigure(node, :text=>res)
        if list.exist?(node)
          list.itemconfigure(node, :text=>res)
        end
        tree.selection_set(node)
      end
      return
    end

    if (where == 'list')
      res = list.edit(node, list.igemcget(node, :text))
      if res != ''
        list.itemconfigure(node, :text=>res)
        if tree.exist?(node)
          tree.itemconfigure(node, :text=>res)
        else
          cursel = tree.selection_get[0]
          index  = list.index(node) - tree.nodes(cursel).size
          data   = TkComm.simplelist(tree.itemcget(cursel, :data))
          data[index] = res
          tree.itemconfigure(cursel, :date=>data)
        end
        list.selection_set(node)
      end
    end
  end

  def self.expand(tree, but)
    unless (cur = tree.selection_get).empty?
      if TkComm.bool(but)
        tree.opentree(cur)
      else
        tree.closetree(cur)
      end
    end
  end
end
