#
# Copyright (c) 1993 Eric Schenk.
# All rights reserved.
#
# Permission is hereby granted, without written agreement and without
# license or royalty fees, to use, copy, modify, and distribute this
# software and its documentation for any purpose, provided that the
# above copyright notice and the following two paragraphs appear in
# all copies of this software.
# 
# IN NO EVENT SHALL ERIC SCHENK BE LIABLE TO ANY PARTY FOR
# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
# OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF ERIC
# SCHENK HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# ERIC SCHENK SPECIFICALLY DISCLAIMS ANY WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
# ON AN "AS IS" BASIS, AND ERIC SCHENK HAS NO OBLIGATION TO
# PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

# routines to do geometry management functions
# mostly these just deal with placements at the moment

set tkwm_priv(managers) {}

# The simpleManager just puts windows where they ask to be put
# and leaves them there. It doesn't need to keep a list of them
# or anything special, so most of the widget is just for show.

proc simpleManager {name} {
    global tkwm_priv
    lappend tkwm_priv(managers) $name
    proc $name {command win} {
	switch $command {
	    map {wm deiconify $win; restack $win Above None}
            unmap {wm withdraw $win}
            remove {}
	    refresh {}
	}
    }
}

proc packingManager {name region padx pady dir1 dir2} {
    global $name tkwm_priv
    lappend tkwm_priv(managers) $name
    set ${name}(y) 10
    set ${name}(list) {}
    set num [scan $region "%dx%d%c%d%c%d" ${name}(width) ${name}(height) \
	gx x gy y]
    if {$num!="6" || [set ${name}(width)] <= "0" || [set ${name}(height)] <= "0"
    || ($gx!="43" && $gx!="45") || ($gy!="43" && $gy!="45")
    } {
	error "bad region specifier: $region"
    }
    set ${name}(x) \
	[expr "($gx==45)?([winfo screenwidth .]-$x-[set ${name}(width)]):$x"]
    set ${name}(y) \
	[expr "($gy==45)?([winfo screenheight .]-$y-[set ${name}(height)]):$x"]
    set ${name}(padx) $padx
    set ${name}(pady) $pady
    set ${name}(dir1) $dir1
    set ${name}(dir2) $dir2
    proc $name {command win} "packingManager::command $name \$command \$win"
}

proc packingManager::command {name command win} {
    global $name

    switch $command {
        map {
            lappend ${name}(list) $win
	    packingManager::pack $name
            wm deiconify $win
        }
        unmap {
	    set_remove ${name}(list) $win
	    wm withdraw $win
	    packingManager::pack $name
        }
        remove {
	    set_remove ${name}(list) $win
	    packingManager::pack $name
        }
	refresh {
	    packingManager::pack $name
	}
    }
}

# The current overflow rule is if we can't fit the window into the
# region, we leave it where it is and go on to the next one.
# Anyone have any better ideas?

proc packingManager::pack {name} {
    upvar #0 $name data

    set dir1 $data(dir1)
    set dir2 $data(dir2)
    set padx $data(padx)
    set pady $data(pady)
    set sx   $data(x)
    set sy   $data(y)
    set swidth $data(width)
    set sheight $data(height)

    # repack the region
    if {$dir1=="east"||$dir2=="east"} {
    	set x [expr "[winfo screenwidth .]-$sx-$swidth"]
        set gx -
    } else {
	set x $sx
        set gx +
    }
    set ix $x
    if {$dir1=="south"||$dir2=="south"} {
    	set y [expr "[winfo screenheight .]-$sy-$sheight"]
        set gy -
    } else {
	set y $sy
        set gy +
    }
    set iy $y
    # set up avialable width and height counters
    set width $swidth
    set height $sheight
    set maxw 0
    set maxh 0

    foreach w $data(list) {
	set cw [winfo width $w]
	set ch [winfo height $w]
        if {($height<$ch || $width<$cw)
        && (  (($dir1=="south"||$dir1=="north")
	       && $sheight>=$ch && [expr $width-$maxw-$padx]>=$cw)
	   || (($dir1=="east"||$dir1=="west")
	       && [expr $height-$maxh-$pady]>=$ch && $swidth>=$cw))} {
	    # not enough room here, but there is in next column or row
	    if {$dir1=="south"||$dir1=="north"} {
		set y $iy
		set height $sheight
		incr x $maxw
		incr x $padx
		incr width -$maxw
		incr width -$padx
	    } else {
		set x $ix
		set width $swidth
		incr y $maxh
		incr y $pady
		incr height -$maxh
		incr height -$pady
	    }
	    set maxw 0
	    set maxh 0
	}
        if {$height>=$ch && $width>=$cw} {
	    wm geometry $w $gx$x$gy$y
            if {$dir1=="south"||$dir1=="north"} {
		set adv [expr "$ch+$pady"]
	        incr y $adv
		incr height -$adv
	    } else {
		set adv [expr "$cw+$padx"]
	        incr x $adv
		incr width -$adv
            }
	    if {$cw>$maxw} {set maxw $cw}
	    if {$ch>$maxh} {set maxh $ch}
	}
    }
}
