
array set ::grid {}

#
# The parent size
#
set pwidth 336
set pheight 400

array set ::requests {
 .w1,width 40
 .w1,height 20

 .w2,width 60
 .w2,height 30

 .w3,width 100
 .w3,height 100

 .wb4,width 50
 .wb4,height 50
}

proc _grid.insert {path column row _sticky_ sticky} {
 global grid

 #TODO use info exists to see if we should remove $path from grid(list)
 catch {unset grid($path)}

 lappend grid(list) $path
 set grid($path,column) $column
 set grid($path,row) $row
 set grid($path,columnratio) 0
 set grid($path,rowratio) 0
 set grid($path,sticky) $sticky

 _grid.layout
}


#key is generally column or row
proc _grid.layout.insert {p list key} {
 global grid

 set inserted 0

 #insert the item in a sorted fashion into the list
 for {set i 0} {$i < [llength $list]} {incr i} {
  set e [lindex $list $i]
  set ca $grid($e,$key)
  set cb $grid($p,$key)

  #puts "$e:$ca $p:$cb"

  if {$cb < $ca} {
   set list [linsert $list $i $p]
   set inserted 1
   break
  } elseif {$cb == $ca} {
   #THIS IS INVALID
   return -code error "2 widgets are in the same grid $key $ca.  These widgets are $e and $p."
  }
 }

 if {!$inserted} {
  lappend list $p
 }
 return $list
}

proc _grid.layout {} {
 global grid requests pwidth pheight

 array set rows {}
 array set columns {}

#XXX we can cache this between calls
 foreach p $grid(list) {
  set column $grid($p,column)
  set row $grid($p,row)

  if {![info exists rows($row,list)]} {
   lappend rows($row,list) $p
  } else {
   set rows($row,list) [_grid.layout.insert $p $rows($row,list) column]
  }

  if {![info exists colums($column,list)]} {
   lappend columns($column,list) $p
  } else {
   set columns($column,list) [_grid.layout.insert $p $columns($column,list) row]
  }
 }

 #
 # Set the width for the grid widgets.
 #
 foreach {key rowlist} [array get rows *,list] { 
  #puts $rowlist

  set totalwidth $pwidth
  set numwidgets [llength $rowlist]

  #
  # Make the first pass, and set the initial widths.
  #
  foreach p $rowlist {
   catch {unset grid($p,widthset)}
   set reqw $requests($p,width) 
   set w [expr {$totalwidth / $numwidgets}]

   if {[lsearch -exact $grid($p,sticky) width] < 0} {
    if {$reqw < $w} {
     set w $reqw
     set grid($p,widthset) 1
    }
   }

   set grid($p,width) $w
   set totalwidth [expr {$totalwidth - $w}]
   incr numwidgets -1
  }


  #
  # Make a 2nd pass, and set the growable regions to a larger size.
  #
  set totalwidth $pwidth
  set numwidgets [llength $rowlist]

  set growable [list]

  foreach p $rowlist {
   if {[info exists grid($p,widthset)]} {
    incr numwidgets -1
    set totalwidth [expr {$totalwidth - $grid($p,width)}]
   } else {
    lappend growable $p
   }
  }

#puts "NUMWIDGETS:$numwidgets GROWABLE:$growable"

  if {$numwidgets > 0} {
   #
   # We have at least 1 widget that is growable, 
   # due to the constrained size of others.
   #
   set w [expr {$totalwidth / $numwidgets}]
   foreach p $growable {
    set grid($p,width) $w
   }
  }
 }

# parray grid
}

if 0 {
 Rules:

  when -sticky [list width] use the maximum space for the slot according to the space ratio
  when -sticky {} use the request unless request > maximium space for the slot
  when -row is equal to another widget's -row and -column is equal to another widget's -column then go by the order of processing

}


#scrollbar (4 is also a test, instead of 3)
_grid.insert .w1 4 0 -sticky [list height]
_grid.insert .w2 1 0 -sticky [list width height]
puts 3:[time {_grid.insert .w3 2 0 -sticky [list width height]}]
_grid.insert .wb4 1 1 -sticky [list width height]
