#---------------------------------------------------------
# Ptk (Parenthesized tk)
#---------------------------------------------------------
# Internal stuff + basic container and leaves
#---------------------------------------------------------
package require Tk
package provide Ptk 0.1

# return ithe full name of 'standard' widget
proc STDW { w } {
	#return [join [list "$TKLIB" "::" $w ] ""]
	return [join [list "::" $w ] ""]
}

namespace eval ptk {
# Public interface:
namespace export begin end
namespace export add
namespace export store
namespace export showif 
namespace export reopen reclose
namespace export packreq
namespace export configure
namespace export debug
namespace export confirm_quit
}
# USAGE
#
#  begin *kind* ?params? ?opts?
#  ....
#  end ?kind?
#
#  add *kind* ?params? ?opts?
#  
#  configure ?component? *opts*
#
#  store *var*
#
#  showif *var*
#   
#  reopen ?kind? *storedid*
#  reclose ?kind? ?storedid?
#
#  debug *bool*
#
# - 'params' are by-value, in order arguments, specific to 'kind'
# - 'opts' are regular tk options (-key val),  valid key's depend on 'kind'
# - end/reclose arguments are optional bur stongly recommanded for
#   tracking nesting errors

###### ERROR MANAGMENT
proc ptk::_error { msg } {
   puts -nonewline stderr "#Ptk error: "
   puts $msg
   flush stderr
	exit 1
}
proc ptk::ASSERT { args } {
	if { ! [eval {*}$args] } {
		ptk::_error "assertion '$args' violated"
	}
}

set ptk::dbg(on) 0
proc ptk::debug { v } {
	ptk::ASSERT string is  boolean $v
	set ptk::dbg(on) $v
}
set ptk::dbg(channel) stderr
proc ptk::DBG {msg} {
   if $ptk::dbg(on) then {
      puts -nonewline $ptk::dbg(channel) "#DBG: "
      puts $ptk::dbg(channel) "$msg"
      flush $ptk::dbg(channel)
   }
}

###### ptk ITEM managment
namespace eval ptk {
	variable item_cpt 0
	# current 'state' is determined by this single var:
	variable cur_node ""
	# these tabs are indexed by
 	variable node_cur_item
	variable kind_of_item
	# 
	variable root_stack {}
}

###### UTILS/INTERNAL
# returns a fresh slave NAME inside _cur_node
# must be used to create actual widget (frame, label etc)
# dont use directly, use push_node/new_leaf
proc ptk::_new_path { } {
   incr ptk::item_cpt
   set it $ptk::cur_node.w$ptk::item_cpt
	set ptk::node_cur_item($ptk::cur_node)  $it
	return $it
}

# add a "what" widget inside current node
# what is frame, a label etc
# args not (yet?) used
proc ptk::_new_leaf { what args } {
	set it [ ptk::_new_path ]
	lappend ptk::node_sons($ptk::cur_node) $it
	#set ptk::cur_node $it
	[STDW $what] $it
	ptk::DBG "  ptk::_new_leaf $what $args -> $it (inside $ptk::cur_node)"
	return $it
}


##### PROPS MANAGEMENT
# containers have an 'inner'
namespace eval ptk {
	variable item_props
}

proc _def_props { plist } {
	set keys [lindex $plist 0]
	set dlst [lrange $plist 1 end]
#puts ptab=$plist
#puts keys=$keys
#puts dlst=$dlst
	foreach prop $dlst {
		#puts $prop
		set kind [lindex $prop 0]
		set ptk::item_props($kind) [dict create]
		foreach k $keys v $prop {
			#ptk::DBG "add node prop: $kind $k $v"
			dict append ptk::item_props($kind) $k $v
		}
	}
}

proc ptk::get_prop { kind key } {
#puts "    ptk::get_prop $kind $key"
#set dd $ptk::item_props($kind)
#puts "    dd=$dd"
	return [dict get $ptk::item_props($kind) $key]
}

## DEBUG check
# performs all checks stored in ptk::dbg_check_list
set ptk::dbg_check_list {}
proc ptk::dbg_check { } {
	foreach {ck} $ptk::dbg_check_list {
		$ck
	}
}

# Basic DEBUG checks
proc ptk::check_prop { kind prop } {
	if { [catch {ptk::get_prop $kind $prop} res] } {
		ptk::DBG "CHECK ERROR: prop '$prop' requieded for item '$kind'"
	}
#puts "   kind=$kind prop=$prop res=$res"
}
proc ptk::check_proc { kind _proc } {
	if { [info commands $_proc] == {} } then {
		ptk::DBG "CHECK ERROR: proc '$_proc' requiered for item '$kind'"
	}
}

##### ITEM CONFIG managment
# components MUST exist
proc ptk::dbg_check_configure { } {
	foreach {kind props} [array get ptk::item_props] {
#puts " ITER PROPS    kind=$kind props=$props"
		ptk::check_prop $kind components
#set ff [catch {ptk::get_prop $kind components} res]
#puts "   GET COMP flag=$ff res=$res"
		if { ![catch {ptk::get_prop $kind components} res] } {
#puts "    compo=$res"
			if { $res != {} } {
				ptk::check_proc $kind _configure_$kind
			} 
			foreach cc $res {
				ptk::check_proc $kind _configure_$kind\_$cc
			}
		}
	}
}
lappend ptk::dbg_check_list ptk::dbg_check_configure

proc ptk::configure { args } {
   ptk::DBG "ptk::configure args:$args"
	set it $ptk::node_cur_item($ptk::cur_node) 
	set kind $ptk::kind_of_item($it)
#puts "it:$it"
#puts "kind:$kind"
	set components [ptk::get_prop $kind components]
#puts "components:$components"
	if { "$components" == {} } then {
		ptk::_error "'$kind' cannot be configured"
	}
	# first arg starts with '-' ?
	set first [lindex $args 0]
#puts "first=$first"
	if {[string match "-*" $first]} {
		set suffix ""
		set opts $args
	} elseif { $first == [lindex $args 0] } {
		set suffix ""
		set opts [lrange $args 1 end]
	} else {
		set suffix "_[lindex $args 0]"
		set opts [lrange $args 1 end]
	}
   ptk::DBG "ptk::configure item:$it kind:$kind suffix: $suffix opts: $opts"
	ptk::_configure_$kind$suffix $it $opts
}

# basic configure: just call tk equivalent
proc ptk::_configure_basic { it opts } {
   eval "$it configure $opts"
}


##### CONTAINERS managment
namespace eval ptk {
	# arrays to store begin infos of current
	variable node_params 
	# list of items created within cur_node 
	variable node_sons 
}

# push a new current container
proc ptk::push_node { what args } {
   set it [ ptk::_new_path ]
   [STDW $what] $it
   lappend ptk::node_sons($ptk::cur_node) $it
   set ptk::cur_node $it
   set ptk::node_params($it) $args
   set ptk::node_sons($it) {}
	# set new node cur-item to empty to ease checks
	set ptk::node_cur_item($it)  {}
   ptk::DBG "   ptk::push_node $what $args -> $ptk::cur_node"
   return $it
}

proc ptk::pop { } {
	set father [ winfo parent $ptk::cur_node ]
	set ptk::cur_node $father
	ptk::DBG "   ptk::pop -> $ptk::cur_node"
}

# push an existing 'root'
proc ptk::push_root { new_root } {
# new_root MUST be a sub-node of cur_node
	set cn $ptk::cur_node
	if { [string match "$cn.*" $new_root] } {
		# push (save) cur node
		lappend ptk::root_stack $ptk::cur_node
		# push (save) new_root for later check
		lappend ptk::root_stack $new_root
		set ptk::cur_node $new_root
		return $new_root
	} else {
		return ""
	}
}
proc ptk::pop_root { } {
	# check coherency ...
	set pushed_root [lindex $ptk::root_stack end]
# useless check, all done in closetag
#puts "pushed_root=$pushed_root"
#puts "cur_node=$ptk::cur_node"
#	if { $ptk::cur_node eq $pushed_root } {
		set pushed_node [lindex $ptk::root_stack end-1]	
		set ptk::root_stack [lrange $ptk::root_stack 0 end-2]
		set ptk::cur_node $pushed_node
#		return $pushed_root
#	} else {
#		return ""
#	}
}


##### CUSTOMIZE PACKING
proc ptk::_last_created_item {  } {
	# last created item
	set cn $ptk::cur_node
	if { $ptk::node_cur_item($cn) eq "" } {
		# last created is $cn
		set zeitem $cn
	} else {
		# last created is $ptk::node_cur_item($cn)
		set zeitem $ptk::node_cur_item($cn) 
	}
	return $zeitem
}
proc ptk::packreq { args } {
	# last created item
	set zeitem [ptk::_last_created_item]
	# store $args in packer_request
	lappend ptk::packer_req($zeitem) {*}$args
}
proc ptk::showif { cond } {
	# last created item
	set zeitem [ptk::_last_created_item]
	ptk::DBG "ptk::showif $cond (item = $zeitem)"
	# store $cond in packer_cond
	set ptk::packer_cond($zeitem) $cond
}

##### CONTAINERS managment
# Each container 'kind' is implemented with 2 procs:
#   proc _begin_$kind ?param ...? opts
#   proc _end_$kind   ?param ...? opts
# where:
# - params are those declared in: item_props($kind)/params
# - opts are valid tk options for the main component of $kind
#   i.e. the first elt. item_props($kind)/components 
# and its 'configure item' proc (as described before)
#
# Expected props for nodes are:
#	{kind      outer   inner  nbsons   params    components}

proc ptk::dbg_check_node_props { } {
	foreach {kind props} [array get ptk::item_props] {
		# mandatory param 
		if { [dict exists $props "inner"] } {
			ptk::DBG "Checking item '$kind'"
			ptk::check_prop $kind params
			ptk::check_proc $kind _begin_$kind
			ptk::check_proc $kind _end_$kind
		} else {
			#puts "$kind is an item node"
		}
	}
}
lappend ptk::dbg_check_list ptk::dbg_check_node_props

proc ptk::begin { usrkind args } {
	# VERY FIRST: resolve overloading
	set kind [ptk::unalias $usrkind]
	#puts "kind=$kind"
	ptk::DBG "begin $kind $args"
	if { ! [info exists ptk::item_props($kind)] } {
		ptk::_error "ptk::begin: unknown widget '$kind'"
	}
	if { ! [dict exists $ptk::item_props($kind) "inner"] } {
		ptk::_error "ptk::begin: '$kind' is not a container"
	}
	set nbargs [llength $args]
	set nbp 	[llength [ptk::get_prop $kind params]]
	#ptk::DBG "nbp=$nbp"
	if { $nbargs < $nbp } {
		ptk::_error "$kind requires at least $nbp args"
	}
	set params {}
	#ptk::DBG "   params=$params"
	for {set ix 0} {$ix<$nbp} {incr ix} {
		lappend params [lindex $args $ix]
		#ptk::DBG "   params=$params"
	}
	lappend params [lrange $args $ix end]
	ptk::DBG "   params=$params"
	# call ad hoc creator, store params for end
	set it [ptk::_begin_$kind {*}$params]
	set ptk::node_params($it) $params
	set ptk::kind_of_item($it) $kind
#puts "      ptk::kind_of_item($it)=$ptk::kind_of_item($it)"
}

# util: check for opt 'kind' first arg
# store it, returns the rest
proc ptk::pop_opt_kind { kvar args } {
	upvar 1 $kvar zekvar
	set hd [lindex $args 0]
	if { $hd == "" } {
		set zekvar ""
		set res $args
	} else {
		set kind [ptk::unalias $hd]
		if { [info exists ptk::item_props($kind)] } {
			set zekvar $kind
			set res [lrange $args 1 end]
		} else {
			set zekvar ""
			set res $args
		}
	}
	return $res
}

proc ptk::end { args } {
	ptk::DBG "end $args"

	variable optk
	set others [pop_opt_kind optk {*}$args]
	if { [llength "$others"] != 0 } {
		ptk::_error "usage: end ?kind?"
	}
	
	# VERY FIRST: resolve overloading
	set cn $ptk::cur_node
	set kind $ptk::kind_of_item($cn)
	if { ($optk != "") && ($kind != $optk) } {
		ptk::_error "begin $kind ended with $optk"
	}
	set params $ptk::node_params($cn)
	ptk::_end_$kind {*}$params
}

# keep trace of stored items
# n.b. provide user a 'tag' not actual tk path
namespace eval ptk {
	variable store_cpt
	variable item2tag
	variable tag2item
}

# Add a tag (an id) to the last created item:
# - it must directly follow (and then refers to) a
#   'add' or a 'begin' command.
# - a leaf tag (after 'add') is immediately available
# - a node tab (after 'begin') will become available
#   only after the corresponding end command;
# - moreover, a node 'tag' can only be used within 
#   an ancestor of the node. 


# Implem problem: reopening a node
proc ptk::store { var } {
	# store the LAST created item in (up) var
	set zeitem [ptk::_last_created_item]
	# keep trace, only existance matters...
	if { ! [info exists ptk::item2tag($zeitem)] } {
   	incr ptk::store_cpt
		set ptk::item2tag($zeitem) $ptk::store_cpt
		set ptk::tag2item($ptk::store_cpt) $zeitem
	}
	upvar 1 $var zevar
	set zevar $ptk::item2tag($zeitem)
}

proc ptk::reopen { args } {
	ptk::DBG "reopen $args"

	variable optk
	set tag [pop_opt_kind optk {*}$args]
	if { [llength "$tag"] != 1 } {
		ptk::_error "usage: reopen ?kind? storedid" 
	}
	# Known tag ?
	if { ! [info exists  ptk::tag2item($tag)] } {
		ptk::_error "reopen: unknown tag '$tag'"
	}
	set it $ptk::tag2item($tag)
	set kind $ptk::kind_of_item($it)
	# Coherence of kinds ?
	if { ($optk != "") && ($optk != $kind) } {
		ptk::_error "can't re-open $itk as $kind"
	}
	# kind is container ?
	if { ! [dict exists $ptk::item_props($kind) "inner"] } {
		ptk::_error "ptk::opentag: '$kind' is not a container"
	}
	if { [push_root $it] ne $it } {
		ptk::_error "can't re-open $tag within current context"
	}
}

proc ptk::reclose { args } {
	ptk::DBG "reclose $args"

	variable optk
	set opttag [pop_opt_kind optk {*}$args]
	if { [llength "$opttag"] > 1 } {
		ptk::_error "usage: reclose ?kind? ?storedid?"
	}
	
	# cur node
	set cn $ptk::cur_node
	set kind $ptk::kind_of_item($cn)
	# last opened node tag
	set lp [lindex $ptk::root_stack end]

	# many checks ...
	if { $cn != $lp } {
		ptk::_error "reclose: unbalanced '$kind' content"
	}
	if { ! [info exists ptk::item2tag($cn)] } {
		ptk::_error "reclose: cur node not tagged"
	}
	set ctag $ptk::item2tag($cn)
	if { ($opttag != "") && ($ctag != $opttag) } {
		ptk::_error "reclose: open '$ctag' closed with '$ta'"
	}
	# everything's ok, end container as usual...
	ptk::end $kind
	# pop the root
	ptk::pop_root 
}


##### BASIC CONTAINERS (packers)
# 
# - wrappers basic tk (label)frame :
# - label or not depends on the opts (-text)
# - pack policy determined by the command name

set basic_nodes {
	{kind      outer   inner  nbsons   params    components}
	{col       packer  packer   any   {}         {frame}}
	{line      packer  packer   any   {}         {frame}}
	{hbar      packer  packer   any   {}         {frame}}
	{vbar      packer  packer   any   {}         {frame}}
}
_def_props $basic_nodes

# basic configure
foreach bnprop [lrange $basic_nodes 1 end] {
	set kind [lindex $bnprop 0]
#puts "     $kind"
	interp alias {} ptk::_configure_$kind {} ptk::_configure_basic
	interp alias {} ptk::_configure_$kind\_frame {} ptk::_configure_basic
}

namespace eval ptk {
	# how a container packs its sons
	variable packer_policy
	# how a container whant to be packed
	variable packer_req
	# dynamical conditional pack
	# TODO
	variable packer_cond 
}
proc ptk::_begin_packer { opts } {
	if { [lsearch $opts "-text"] != -1 } {
		set tk_kind labelframe
	} else {
		set tk_kind frame
	}
	# push a labelframe/frame
	set it [ ptk::push_node $tk_kind]
   eval "$it configure $opts"
   return $it
}
proc ptk::_cond_pack { var it son packopts args } {
	ptk::DBG "_cond_pack $var $it $son $packopts"
	# At this point, 4 levels away from where 'pack_cond' exists 
	upvar #0 $var cond
#puts " !!!! upvar $var exists = [info exists cond]" 
	if { $cond } {
		eval "pack $son -in $it $packopts"
	} else {
		pack unpack $son
	}
}
 
proc ptk::_end_packer { } {
   #sons are all nodes created with push_node
   set sons $ptk::node_sons($ptk::cur_node)
   set it $ptk::cur_node
   ptk::DBG "   _end_packer cont:$ptk::cur_node sons: $sons opts: $ptk::packer_policy($it)"
   foreach son $sons {
      # is there some packer_req ?
      set pack_req [lindex [array get ptk::packer_req $son] 1]
      set pack_cond [lindex [array get ptk::packer_cond $son] 1]
      ptk::DBG "  pack $son req='$pack_req' cond='$pack_cond'"
      if { "$pack_req" != "none" } {
			# full pack opts
			set packopts [concat $ptk::packer_policy($it) $pack_req]
      	eval "pack $son -in $it $packopts"
			# is the packing conditionnal ?
			if { $pack_cond != {} } {
            # At this point, 3 levels away from where 'pack_cond' exists 
				upvar 3 $pack_cond var
#puts " !!!! $pack_cond exists = [info exists $pack_cond]" 
#puts " !!!! upvar $pack_cond exists = [info exists var]" 
				upvar #0 $pack_cond cond
				trace variable var w "ptk::_cond_pack $pack_cond $it $son {$packopts}"
				ptk::_cond_pack $pack_cond $it $son $packopts
				#call it once in case ...
				
			}
      }
   }
   ptk::pop
}

proc ptk::_begin_line { opts } {
	set it [ptk::_begin_packer $opts]
	set ptk::packer_policy($it) { -side left -expand 1 -anchor center -fill both }
	set ptk::packer_req($it) { -expand 1 -fill both }
	return $it
}
proc ptk::_begin_col { opts } {
	set it [ptk::_begin_packer $opts]
	set ptk::packer_policy($it) { -side top -expand 1 -anchor center -fill both }
	set ptk::packer_req($it) { -expand 1 -fill both }
	return $it
}
proc ptk::_begin_hbar { opts } {
	set it [ptk::_begin_packer $opts]
	set ptk::packer_policy($it) { -side left -expand 0 -anchor center -fill y }
	set ptk::packer_req($it) { -expand 0 -fill x }
	return $it
}
proc ptk::_begin_vbar { opts } {
	set it [ptk::_begin_packer $opts]
	set ptk::packer_policy($it) { -side top -expand 0 -anchor center -fill x }
	set ptk::packer_req($it) { -expand 0 -fill y }
	return $it
}
# _ends_xxx must have EXACTLY the same profile as _begin_xxx
# (even if args are not used)
proc ptk::_end_col { opts } {
   ptk::_end_packer
}
proc ptk::_end_line { opts } {
   ptk::_end_packer
}
proc ptk::_end_hbar { opts } {
   ptk::_end_packer
}
proc ptk::_end_vbar { opts } {
   ptk::_end_packer
}

# _configure -> all basic
proc ptk::_configure_col { it opts } {
   ptk::_configure_basic $it $opts
}
proc ptk::_configure_line { it opts } {
   ptk::_configure_basic $it $opts
}
proc ptk::_configure_hbar { it opts } {
   ptk::_configure_basic $it $opts
}
proc ptk::_configure_vbar { it opts } {
   ptk::_configure_basic $it $opts
}

###### MAIN CONTAINER
# params are the title and opts to pass to main frame
namespace eval ptk {
	variable main_frame
}
# nothing to configure (components = {})
_def_props {
	{kind     outer   inner  nbsons   params    components}
	{main     none    packer   any   {title}    {}}
}
proc ptk::_begin_main { title opts } {
   ptk::DBG "   ptk::_begin_main $title $opts"
#puts "     ptk::cur_node=$ptk::cur_node"
   wm positionfrom . ""
   wm sizefrom . ""
   wm minsize . 600 300
   wm title . $title
	wm protocol . WM_DELETE_WINDOW { exit }
   #create new node/insert in master sons
	set ptk::main_frame [ptk::_begin_col $opts]
#puts "     ptk::cur_node=$ptk::cur_node"
   return $ptk::main_frame
}

proc ptk::_end_main { title opts } {
   #top is a col-frame by default
   ptk::DBG "   ptk::_end_main $title $opts"
#puts "     ptk::cur_node=$ptk::cur_node"
   ptk::_end_col $opts
#puts "     ptk::cur_node=$ptk::cur_node"
	pack $ptk::main_frame  -expand 1 -anchor center -fill both
}

proc ptk::_do_confirm_quit { msg } {
    if {[tk_messageBox -message $msg -type yesno] eq "yes"} {
     	exit
    }
}
proc ptk::confirm_quit { msg } {
	wm protocol . WM_DELETE_WINDOW "ptk::_do_confirm_quit \"$msg\""
}

##### LEAVES managment
# - A ptk widget has a unique internel 'kind' used
# for # indexing its props (e.g. button != menu_button)
# - However, to be closer to tk style, the external
# 'kind' used in ::add may be overloaded.
# e.g. user may use 'add button' to create a button
# or a menu_button, depending on the current context.
# - to implement that, a contextual alias must be declared: 
#   * usrkind = the alias
#   * kind = the actual unique 
#   * check = a arg-free proc checking if overload
#     applies in current context
#     (can only depend on cur node and last item 
# e.g. ptk::new_alias "button" "menu_button" "within_menu"	
# Expected props for leaves:
#	{kind      outer   inner  nbsons   params    components}

variable ptk::aliases
proc ptk::new_alias { usrkind kind check } {
	lappend ::ptk::aliases($usrkind) [list $kind $check] 
}
proc ptk::get_aliases { usrkind } {
	if { [info exists ptk::aliases($usrkind)] } {
		return $ptk::aliases($usrkind) 
	} else {
		return {}
	}
}
proc ptk::unalias { usrkind } {
	foreach aa [ptk::get_aliases $usrkind] {
		if { [eval [lindex $aa 1]] } {
			set res [lindex $aa 0]
			ptk::DBG "ptk::unalias '$usrkind' -> '$res'"
			return [ptk::unalias $res]
		}
	}
	return $usrkind
}
#ICI
ptk::new_alias "lbl" "label" "expr 1"

proc ptk::add { usrkind args } {
	# VERY FIRST: resolve overloading
	set kind [ptk::unalias $usrkind]
	#check exists
	if { ! [info exists ptk::item_props($kind)] } {
		ptk::_error "ptk::add: unknown widget '$kind'"
	}
	if { [dict exists $ptk::item_props($kind) "inner"] } {
		ptk::_error "ptk::add:  '$kind' is not a leaf"
	}
	#check args
	set nbargs [llength $args]
	ptk::DBG "add $kind args=$args ln=$nbargs"
	set nbp 	[llength [ptk::get_prop $kind params]]
	#ptk::DBG "nbp=$nbp"
	if { $nbargs < $nbp } {
		ptk::_error "$kind requires at least $nbp args"
	}
	# kind is ALWAYS passed as first arg
	# -> allows to define aliases 
	set params {}
	lappend params $kind
	for {set ix 0} {$ix<$nbp} {incr ix} {
		lappend params [lindex $args $ix]
	}
	lappend params [lrange $args $ix end]
	#ptk::DBG "   params=$params"
	#TODO check outer
	# call ad hoc creator, store params for end
	set it [ptk::_add_$kind {*}$params]
	set ptk::kind_of_item($it) $kind
#puts "      ptk::add end it=$it kind=$ptk::kind_of_item($it)"
}

###### BASIC LEAVES
# valid for all basic tk widget within a packer


set basic_leaves {
	{kind          outer  params    components}
	{label        packer   {}       {label}}
	{button       packer   {}       {button}}
	{checkbutton  packer   {}       {checkbutton}}
	{radiobutton  packer   {}       {radiobutton}}
	{scale        packer   {}       {scale}}
	{entry        packer   {}       {entry}}
	{frame        packer   {}       {frame}}
}
_def_props $basic_leaves

proc ptk::_add_basic_in_packer { kind opts } {
   #new slave 
   set it [ ptk::_new_leaf $kind ]
   eval "$it configure $opts"
	return $it
}
foreach bfprop [lrange $basic_leaves 1 end] {
	set kind [lindex $bfprop 0]
#	puts "     $kind"
	interp alias {} ptk::_configure_$kind {} ptk::_configure_basic
	interp alias {} ptk::_configure_$kind\_$kind {} ptk::_configure_basic
	interp alias {} ptk::_add_$kind {} ptk::_add_basic_in_packer
}

###### EMPTY LEAVES
# just for customize layout 
# box: usefull within line/col to add space
#      actually: empty label
ptk::new_alias "box" "label"   "expr 1"

# fill: usefull within hbar/vbar to add expandable space
#       actually: empty frame 
#       eq. to 'begin line; end (or 'begin col; end')
_def_props {
	{kind          outer  params    components}
	{fill          packer   {}       {frame}}
}

proc ptk::_add_fill { kind opts } {
   set it [ ptk::_new_leaf frame ]
   eval "$it configure $opts"
	set ptk::packer_req($it) { -expand 1 -fill both }
	return $it
}
interp alias {} ptk::_configure_fill {} ptk::_configure_basic
interp alias {} ptk::_configure_fill_frame {} ptk::_configure_basic

