# 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/inspector/main.tcl,v $
# $Author: forster $
# $Revision: 1.16 $
# $Date: 1999/02/22 22:31:00 $
# $Locker:  $
# $State: Exp $
#
#------------------------------------------ CVS
#
# (C) University of Passau 1995-1999, Graphlet Project
#     Author: Michael Forster

package require Graphlet
package provide Graphscript [gt_version]

package require Flatbutton

namespace eval ::GT {

    namespace export inspector
    
    proc inspector { { editor {} } } {
	global GT_event

	if { $editor == {} } { ;# we come from an event
	    set editor $GT_event(editor)
	}

	set IS $editor.inspector
	    
	::GT::IS::show $IS
	    
	return $IS
    }
}

namespace eval ::GT::IS {

    namespace export				\
	create_menu_entry			\
	hide					\
	show

    init

    #================================================== Menu Entry
    
    proc create_menu_entry { editor menu description } {
	variable _Visible
	
	set IS $editor.inspector

	GT::pset { label accel underline state } $description
	
	if {![string match {[0-9]*} $underline]} {
	    set state $underline
	}
	
	set underline [string first ^ $label]
	if {$underline != -1} {
	    regsub \\^ $label "" label
	} else {
	    set underline {}
	}

	set arguments [list \
			   -label $label \
			   -variable ::GT::IS::_VisibilityIndicator($IS) \
			   -command [list ::GT::IS::toggle $IS]]
	
	if {$accel != {}} {
	    lappend arguments -accelerator $accel
	    bind $editor [GT::generate_binding $accel] \
		"::GT::IS::toggle $IS"
	}

	if {$underline != {}} {
	    lappend arguments -underline $underline
	}

	if {$state != {}} {
	    lappend arguments -state $state
	}

	eval $menu add checkbutton $arguments
    }

    #================================================== Creation

    proc create { IS } {
	variable _Pages
	variable _Options

	# create window components

	create_mainwindow $IS
	
	set toolbar [create_toolbar $IS $IS.toolbar] 
	set pageFrame [frame $IS.page] \

	if { $_Options(dock) } {
	    $pageFrame configure \
		-relief $_Options(raised) -bd 1
	}

	# pack components
	
	pack $toolbar \
	    -fill x

	pack $pageFrame \
	    -fill both \
	    -expand true

	# show first page

	open_page $IS
	switch_to $IS [lindex $_Pages 0]

	# traces

	set editor [winfo parent $IS]
	set code [namespace code "selection_changed $IS"]
	
	global GT_selection
	trace var GT_selection($editor,selected,node) w $code
	trace var GT_selection($editor,selected,edge) w $code
	::GT::add_hook post_draw_hook [list $code]
    }

    proc create_mainwindow { IS } {
	variable _Options
	
	if { $_Options(dock) } {
	    
	    frame $IS \
		-class Inspector \
		-relief $_Options(sunken) -bd 1
	    
	    set editor [winfo parent $IS]

	    # ensure that the editor window does not resize
	    
	    update idletasks
	    wm geometry $editor [wm geometry $editor]

	    pack $IS \
		-side right \
		-before $editor.drawing \
		-fill y -expand false \
		-pady 3

	    pack [create_titlebar $IS $IS.titlebar] \
		-side top \
		-fill x

	} else {
	    
	    # create toplevel window: transient, not resizable,
	    #                         right of the editor

	    toplevel $IS \
		-class Inspector
	    
	    set editor [winfo parent $IS]

	    wm transient $IS $editor
	    wm resizable $IS 0 0
	    wm protocol $IS WM_DELETE_WINDOW [namespace code "hide $IS"]
	    
	    set x [expr [winfo x $editor] + [winfo width $editor] -100]
	    set y [winfo y $editor]
	    wm geometry $IS +$x+$y
	}
	
	return $IS
    }

    proc create_titlebar { IS titlebar } {
	variable _Options
	
	# titlebar frame
	
	frame $titlebar \
	    -relief $_Options(raised) -bd 1

	# close button
	
	set close [Flatbutton::create $titlebar.close \
		       -image [GT::get_image inspector/button/close_small] \
		       -command [namespace code "hide $IS"] \
		       -takefocus 0 \
		  ]

	pack $close -side right -padx 2 -pady 2
	
	# titlebar text
	pack [label $titlebar.title] -side left -padx 3
	
	return $titlebar
    }

    proc create_toolbar { IS toolbar } {
	variable _
	variable _Pages
	variable _PageTitle
	variable _Options
	
	if { $_Options(dock) } {
	    frame $toolbar \
		-relief $_Options(raised) -bd 1
	} else {
	    frame $toolbar \
		-relief groove -bd 2
	}

	pack [frame $toolbar.border] \
	    -padx 3 -pady 2
	
	# create toolbar buttons

	foreach page $_Pages {

	    set but [Flatbutton::create $toolbar.$page \
			 -image [GT::get_image inspector/button/$page] \
			 -command [namespace code "switch_to $IS $page"] \
		     ]

	    pack $but \
		-in $toolbar.border \
		-side left

	    GT::tooltips $but $_PageTitle($page)
	}

	if { !$_Options(dock) } {
	    foreach { name icon tooltip } {
		hide close_page "Roll inspector up or down"
		roll up "Close inspector"
	    } {

		set but [Flatbutton::create $toolbar.$name \
			     -image [GT::get_image inspector/button/$icon] \
			     -command [namespace code "$name $IS"] \
			     -takefocus 0 \
			 ] 

		pack $but \
		    -in $toolbar.border \
		    -side right

		set _($IS,${name}_button) $but
		
		GT::tooltips $but $tooltip
	    }
	}
	
	return $toolbar
    }
    
    proc create_page { IS frame page } {
	variable _PageLayout

	foreach { regionName regionTitle regionControls } $_PageLayout($page) {
	    create_region $IS $frame $page $regionName $regionTitle $regionControls
	}
    }

    proc create_region { IS frame page regionName regionTitle regionControls } {

	set region [frame $frame.$regionName]
	
	pack $region \
	    -side top \
	    -fill x \
	    -padx 3
	
	pack [create_sep $region.sep $regionTitle] \
	    -fill x \
	    -padx 2

	foreach { controlType controlName controlAttrs } $regionControls {
	    create_control $IS $region $controlType $controlName $controlAttrs
	}
    }
    
    proc create_sep { sep label } {
	variable _Options
	
	frame $sep
	
	# left line
	
	pack [frame $sep.left \
		  -relief $_Options(sunken) -bd 1 \
		  -height 2 -width 10 \
		 ] \
	    -side left

	# right line

	pack [frame $sep.right \
		  -relief $_Options(sunken) -bd 1 \
		  -height 2 \
		 ] \
	    -side right -fill x -expand true

	# text
	
	pack [label $sep.text -text $label] 
	
	return $sep
    }
    
    proc create_control { IS controlsFrame controlType controlName controlAttrs } {
	variable _Value
	
	foreach attr $controlAttrs {
	    trace var _Value($IS,$attr) w \
		[namespace code "write_attrs $IS $attr ;\#"]
	}

	foreach attr $controlAttrs {
	    disable_update $IS $attr
	}

	pack [${controlType}::create $IS $controlsFrame.$controlName $controlAttrs] \
	    -side top \
	    -fill x

	foreach attr $controlAttrs {
	    enable_update $IS $attr
	}
    }
	
    #================================================== Visibility
    
    proc toggle { IS } {
	variable _Visible
	
	if { ![info exists _Visible($IS)] || !$_Visible($IS) } {
	    show $IS
	} else {
	    hide $IS
	}
    }

    proc show { IS } {
	variable _
	variable _Initialized
	variable _Options
	variable _Visible
	variable _VisibilityIndicator

	if ![info exists _Initialized] {
	    init
	}
	
	# Show Inspector, create if neccessary
	
	if [winfo exists $IS] {
	    if { $_Options(dock) } {
		pack $IS \
		    -side right \
		    -before [winfo parent $IS].drawing \
		    -fill y -expand false \
		    -pady 3
	    } else {
		raise $IS
		wm deiconify $IS
	    }
	} else {
	    create $IS
	}
	set _Visible($IS) 1
	set _VisibilityIndicator($IS) 1
    }

    proc hide { IS } {
	variable _Options
	variable _Visible
	variable _VisibilityIndicator

	# hide inspector

	if { $_Options(dock) } {
	    pack forget $IS
	} else {
	    wm withdraw $IS
	}
	set _Visible($IS) 0
	set _VisibilityIndicator($IS) 0
    }

    #================================================== Open_Page / Close
	
    proc open_page { IS } {
	variable _
	variable _Open
	variable _Options

	set _Open($IS) 1
	if { !$_Options(dock) } {
	    $_($IS,roll_button) configure -image [GT::get_image inspector/button/up]
	}
	
	pack $IS.page -fill both
    }

    proc close_page { IS } {
	variable _
	variable _Open
	variable _Options
	
	set _Open($IS) 0
	if { !$_Options(dock) } {
	    $_($IS,roll_button) configure -image [GT::get_image inspector/button/down]
	}
	
	pack forget $IS.page
    }

    #================================================== Actions
	
    proc roll { IS } {
	variable _Open
	
	if $_Open($IS) {
	    close_page $IS
	} else {
	    open_page $IS
	}
    }

    proc switch_to { IS page } {
	variable _Open
	variable _PageTitle
	variable _CurrentPage

	# create page if neccessary
	
	set frame $IS.page.$page
	if ![winfo exists $frame] {
	    create_page $IS [frame $frame] $page
	}

	# open inspector
	
	if !$_Open($IS) {
	    open_page $IS
	}

	# hide old page
	
	if [info exists _CurrentPage($IS)] {
	    if { [string compare $_CurrentPage($IS) $page] == 0} return
	    pack forget $IS.page.$_CurrentPage($IS)
	}

	# update toolbar

	if { [info exists _CurrentPage($IS)] } {
	    set button $IS.toolbar.$_CurrentPage($IS)
	    $button deselect
	}
	$IS.toolbar.$page select

	# show new page

	set _CurrentPage($IS) $page
	pack $IS.page.$_CurrentPage($IS) -fill both -expand true
	
	# set window title
	
	set_title $IS "$_PageTitle($page)"

	update_selection $IS
    }

    proc next_page { IS offset } {
	variable _CurrentPage
	variable _Pages

	set index [lsearch -exact $_Pages $_CurrentPage($IS)]
	set index [expr ($index + $offset) % [llength $_Pages]]

	switch_to $IS [lindex $_Pages $index]
    }

    proc set_title { IS title } {
	variable _Options
	
	if { $_Options(dock) } {
	    $IS.titlebar.title configure -text $title
	} else {
	    wm title $IS $title
	}
    }

    #================================================== Selection Tracking
    
    proc selection_changed { IS args } {
	variable _

	# wait a bit, because updating too often slows down

	set waittime 30
	
	set IDVar _($IS,wait_id)
	if {[info exists $IDVar]} {
	    after cancel [set $IDVar]
	}
	set $IDVar [after $waittime [namespace code "unset $IDVar;
                                                     update_selection $IS"]]
    }

    proc update_selection { IS } {
	global GT_selection
	variable _CurrentPage
	variable _PageAttrs
	variable _PageCtls
	variable _HaveNodes
	variable _HaveEdges

	set editor [winfo parent $IS]
	
	set _HaveNodes($IS) \
	    [expr ![GT::lempty $GT_selection($editor,selected,node)]]
	set _HaveEdges($IS) \
	    [expr ![GT::lempty $GT_selection($editor,selected,edge)]]

	set pageName $_CurrentPage($IS)
	foreach attr $_PageAttrs($pageName) {
	    read_attr $IS $attr
	}
	foreach { controlType regionName controlName } $_PageCtls($pageName) {
	    ${controlType}::update $IS $IS.page.$pageName.$regionName.$controlName
	}
    }
}

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

