# This software is distributed under the Lesser General Public License
#
# inspector/main.tcl
#
# Main file for the inspector
#
#------------------------------------------ CVS
#
# CVS Headers -- The following headers are generated by the CVS
# version control system. Note that especially the attribute
# Author is not necessarily the author of the code.
#
# $Source: /home/br/CVS/graphlet/lib/graphscript/modes/zoom_mode.tcl,v $
# $Author: himsolt $
# $Revision: 1.4 $
# $Date: 1999/03/05 20:42:31 $
# $Locker:  $
# $State: Exp $
#
#------------------------------------------ CVS
#
# (C) University of Passau 1995-1999, Graphlet Project
#     Author: Michael Forster

package require Graphlet
package provide Graphscript [gt_version]

namespace eval GT {
    
    namespace export \
	action_zoom_mode \
	ev_zoombox_start \
	ev_zoombox_motion \
	ev_zoombox_end

    #================================================== mode switching
    
    proc action_zoom_mode  { editor } {
	switch_to_mode $editor zoom_mode
    }

    proc init_zoom_mode { editor mode } {
	global GT
	if ![info exists GT($editor,zoom_mode_saved_cursor)] {
	    set GT($editor,zoom_mode_saved_cursor) [$editor cget -cursor]
	    $GT($editor,canvas) configure \
		-cursor sizing
	}
	return {}
    }

    proc leave_zoom_mode { editor mode } {
	global GT
	$GT($editor,canvas) configure \
	    -cursor $GT($editor,zoom_mode_saved_cursor)
	unset GT($editor,zoom_mode_saved_cursor)
	return {}
    }
    
    #================================================== event handlers
    
    proc ev_zoombox_start {args} {

	global GT_event
	
	set x $GT_event(canvasx)
	set y $GT_event(canvasy)
	set canvas $GT_event(W)
	
	set GT_event(zoombox_start_x) $x
	set GT_event(zoombox_start_y) $y
	set GT_event(zooming) 1
	
	$canvas create rect $x $y $x $y \
	    -tag zoom_rect
	
	return -code break
    }

    proc ev_zoombox_motion {args} {
	
	global GT_event

	if [info exists GT_event(zooming)] {
	    $GT_event(W) coords zoom_rect \
		$GT_event(zoombox_start_x) $GT_event(zoombox_start_y) \
		$GT_event(canvasx) $GT_event(canvasy)
	}

	return -code break
    }

    proc ev_zoombox_end {args} {

	global GT GT_event
	set canvas $GT_event(W)
	set editor $GT_event(editor)
	set graph $GT($editor,graph)

	if ![info exists GT_event(zooming)] {
	    return -code break
	} 

	$canvas delete zoom_rect

	# calculate zoom rect coordinates

	zoom_to_rect $canvas $graph \
	    $GT_event(zoombox_start_x) $GT_event(zoombox_start_y) \
	    $GT_event(canvasx) $GT_event(canvasy)

	# clean up
	
	unset GT_event(zoombox_start_x)
	unset GT_event(zoombox_start_y)
	unset GT_event(zooming)

	return -code break
    }

    proc ev_zoom_out {args} {
	global GT GT_event

	set canvas $GT_event(W)
	set editor $GT_event(editor)
	set graph $GT($editor,graph)

	set center_x $GT_event(canvasx)
	set center_y $GT_event(canvasy)

	set zoom 0.5

	get_canvas_size $canvas width height

	set width [expr $width/$zoom]
	set height [expr $height/$zoom]

	set x0 [expr $zoom*($center_x - $width/2)]
	set y0 [expr $zoom*($center_y - $width/2)]

	zoom_to $canvas $graph $zoom $x0 $y0	
    }

    #================================================== utility routines
    
    proc get_canvas_size { canvas width_var height_var } {
	upvar 1 $width_var width
	upvar 1 $height_var height
	
	set correction [expr \
			    2*[$canvas cget -borderwidth] + \
			    2*[$canvas cget -highlightthickness] \
			   ]
	
	set width [expr [winfo width $canvas] - $correction]
	set height [expr [winfo height $canvas] - $correction]
    }

    proc zoom_to_rect { canvas graph x0 y0 x1 y1 } {

	global GT_options

	# normalize rect coordinates
	
	if { $y1 < $y0 } {
	    set tmp $y1
	    set y1 $y0
	    set y0 $tmp
	}
	if { $x1 < $x0 } {
	    set tmp $x1
	    set x1 $x0
	    set x0 $tmp
	}

	set width  [expr $x1-$x0]
	set height [expr $y1-$y0]

	# calculate canvas size

	get_canvas_size $canvas canvas_width canvas_height

	# calculate zoom factor and new origin

	if { $width >= $GT_options(minimum_selection_rect_width) ||
	     $height >= $GT_options(minimum_selection_rect_width) } {

	    set zoom_x [expr $canvas_width/$width]
	    set zoom_y [expr $canvas_height/$height]

	    if { $zoom_y < $zoom_x } {
		set zoom $zoom_y
		set origin_x [expr ($x0+$x1)/2 * $zoom_y - $width/2 * $zoom_x]
		set origin_y [expr $y0 * $zoom]
	    } else {
		set zoom $zoom_x
		set origin_x [expr $x0 * $zoom]
		set origin_y [expr ($y0+$y1)/2 * $zoom_x - $height/2 * $zoom_y]
	    }

	    zoom_to $canvas $graph $zoom $origin_x $origin_y
	}
    }
    
    proc zoom_to { canvas graph zoom origin_x origin_y } {
	
	# set zoom factor in canvas
	
	foreach c [$graph canvas] {
	    if { [lindex $c 0] == $canvas } {

		set x [expr [lindex $c 1] * $zoom]
		set y [expr [lindex $c 2] * $zoom]
		lappend canvases [list $canvas $x $y]
	    } else {
		lappend canvases $c
	    }
	}
	
	$graph canvas $canvases
	$graph draw -force true

	# move to new origin

	set scroll_region [$canvas cget -scrollregion]
	set scroll_width [lindex $scroll_region 2]
	set scroll_height [lindex $scroll_region 3]

	$canvas xview moveto [expr $origin_x/$scroll_width]
	$canvas yview moveto [expr $origin_y/$scroll_height]
}                               
}

#---------------------------------------------------------------------------
#   Set emacs variables
#---------------------------------------------------------------------------
# ;;; Local Variables: ***
# ;;; mode: tcl ***
# ;;; tcl-indent-level: 4 ***
# ;;; End: ***
#---------------------------------------------------------------------------
#   end of file
#---------------------------------------------------------------------------
