#------------------------------------------------------
# Script for generating the "library manager" window.
#
# Written by Tim Edwards, July 2017
#------------------------------------------------------

global Opts

if {$::tk_version >= 8.5} {

set Opts(libmgr) 0

magic::tag addpath "magic::libmanager"
magic::tag path    "magic::libmanager"

# Callback to the library manager

proc magic::libcallback {command} {
   global Opts

   set rpath [ split [.libmgr.box.view focus] "/"]
   set rootdef [lindex $rpath 0]
   set cellpath [lrange $rpath 1 end]
   set celldef [lrange $rpath end end]

   if { $Opts(target) == "default" } {
      set winlist [magic::windownames layout]
      set winname [lindex $winlist 0]
   } else {
      set winname $Opts(target)
   }

   switch $command {
      load {$winname load $celldef}
      place {$winname getcell $celldef}
      pick {
	magic::tool pick
	$winname getcell $celldef
	magic::startselect $winname pick
      }
   }
}

#----------------------------------------------
# Create the library manager window
#----------------------------------------------

proc magic::makelibmanager { mgrpath } {
   global filtered

   set filtered 1
   toplevel ${mgrpath}
   wm withdraw ${mgrpath}
   frame ${mgrpath}.actionbar
   frame ${mgrpath}.box
   frame ${mgrpath}.target

   ttk::treeview ${mgrpath}.box.view -selectmode browse \
		-yscrollcommand "${mgrpath}.box.vert set" \
		-xscrollcommand "${mgrpath}.box.vert set" \
		-columns 0
   scrollbar ${mgrpath}.box.vert -orient vertical -command "${mgrpath}.box.view yview"
   ${mgrpath}.box.view heading #0 -text Cell
   ${mgrpath}.box.view heading 0 -text Technology
   ${mgrpath}.box.view column #0 -stretch true -anchor w -minwidth 300
   ${mgrpath}.box.view column 0 -stretch false -anchor center -minwidth 100

   grid columnconfigure ${mgrpath}.box 0 -weight 1 -minsize 500
   grid columnconfigure ${mgrpath}.box 1 -weight 0
   grid rowconfigure ${mgrpath}.box 0 -weight 1
   grid ${mgrpath}.box.view -row 0 -column 0 -sticky news
   grid ${mgrpath}.box.vert -row 0 -column 1 -sticky news

   grid rowconfigure ${mgrpath} 0 -weight 0
   grid rowconfigure ${mgrpath} 1 -weight 1
   grid rowconfigure ${mgrpath} 2 -weight 0
   grid columnconfigure ${mgrpath} 0 -weight 1
   grid ${mgrpath}.actionbar -row 0 -column 0 -sticky news
   grid ${mgrpath}.box -row 1 -column 0 -sticky news
   grid ${mgrpath}.target -row 2 -column 0 -sticky news

   button ${mgrpath}.actionbar.load  -text "Load" -command {magic::libcallback load}
   button ${mgrpath}.actionbar.place -text "Place" -command {magic::libcallback place}
   button ${mgrpath}.actionbar.pick  -text "Pick" -command {magic::libcallback pick}
   checkbutton ${mgrpath}.actionbar.filter -text "Filter" -variable filtered \
	-command {magic::libmanager update}

   pack ${mgrpath}.actionbar.load -side left
   pack ${mgrpath}.actionbar.place -side left
   pack ${mgrpath}.actionbar.pick -side left
   pack ${mgrpath}.actionbar.filter -side right

   label ${mgrpath}.target.name -text "Target window:"
   menubutton ${mgrpath}.target.list -text "default" \
 	   -menu ${mgrpath}.target.list.winmenu

   pack ${mgrpath}.target.name -side left -padx 2
   pack ${mgrpath}.target.list -side left

   #.winmenu clone ${mgrpath}.target.list.winmenu

   #Withdraw the window when the close button is pressed
   wm protocol ${mgrpath} WM_DELETE_WINDOW  "set Opts(libmgr) 0 ; \
		wm withdraw ${mgrpath}"

   #-------------------------------------------------
   # Callback when a treeview item is opened
   #-------------------------------------------------

   bind .libmgr <<TreeviewOpen>> {
      set s [.libmgr.box.view selection]
      # puts stdout "open $s"
      foreach i [.libmgr.box.view children $s] {
         # This is NOT hierarchical like the cell manager!
         .libmgr.box.view item $i -open false
      }
   }

   bind .libmgr <<TreeviewClose>> {
      set s [.libmgr.box.view selection]
      # puts stdout "close $s"
      foreach i [.libmgr.box.view children $s] {
         foreach j [.libmgr.box.view children $i] {
	    .libmgr.box.view delete $j
         }
      }
   }
}

proc magic::addlibentry {parent child name tech} {
   if {$child != 0} {
      set hiername ${parent}${child}
      # puts stdout "libentry $hiername"
      if {[.libmgr.box.view exists $hiername] == 0} {
         .libmgr.box.view insert $parent end -id $hiername -text "$name"
         .libmgr.box.view set $hiername 0 "$tech"
      }
   }
}

#
proc magic::addtolibset {item} {
   global filtered

   set pathname [.libmgr.box.view item $item -text]
   set pathfiles [glob -nocomplain -directory $pathname *.mag]
   # puts stdout "addtolibset $item"

   # Sort files alphabetically

   foreach f [lsort $pathfiles] {
      set tailname [file tail $f]
      set rootname [file root $tailname]
      if {![catch {open $f r} fin]} {
         # Read first two lines, break on error
         if {[gets $fin line] < 0} {continue}	;# empty file error
         if {$line != "magic"} {continue}	;# not a magic file
         if {[gets $fin line] < 0} {continue}	;# truncated file
         set tokens [split $line]
         if {[llength $tokens] != 2} {continue}
         set keyword [lindex $tokens 0]
         if {$keyword != "tech"} {continue}
         set tech [lindex $tokens 1]
         close $fin

	 # filter here for compatible technology
	 if {($filtered == 0) || ($tech == [tech name])} {
            magic::addlibentry $item $tailname $rootname $tech
	 }
      }
   }
}

#--------------------------------------------------------------
# The cell manager window main callback function
#--------------------------------------------------------------

proc magic::libmanager {{option "update"}} {
   global editstack
   global CAD_ROOT

   # Use of command "path" is recursive, so break if level > 0
   if {[info level] > 1} {return}

   # Check for existence of the manager widget
   if {[catch {wm state .libmgr}]} {
      if {$option == "create"} {
	 magic::makelibmanager .libmgr
      } else {
	 return
      }
   } elseif { $option == "create"} {
      return
   }

   magic::suspendall

   # Get existing list of paths
   set curpaths [.libmgr.box.view children {}]

   # Find all library paths for cell searches
   # (Separated so that system default path can be viewed or ignored
   # by option selection (to be done).)
   set spath1 [magic::path search]	;# Rank 1 search
   set spath2 [magic::path cell]	;# Rank 2 search

   # If any component of curpaths is not in spath1 or spath2, remove it.
   set allpaths [concat $spath1 $spath2]
   foreach path $curpaths {
      if {[lsearch $allpaths $path] == -1} {
	  .libmgr.box.view delete ${path}
      }
   }

   set first true
   foreach i $spath1 {
      if {[.libmgr.box.view exists ${i}/] == 0} {
 	 .libmgr.box.view insert {} end -id ${i}/ -text ${i}/
      }
      magic::addtolibset ${i}/
      .libmgr.box.view item ${i}/ -open $first
      set first false
   }
   foreach i $spath2 {
      set expandname [subst $i]
      if {[.libmgr.box.view exists ${expandname}/] == 0} {
 	 .libmgr.box.view insert {} end -id ${expandname}/ -text ${expandname}/
      }
      magic::addtolibset ${expandname}/
      .libmgr.box.view item ${expandname}/ -open $first
      set first false
   }
   magic::resumeall
}

}	;# (if Tk version 8.5)

