#  
#  Module menuConfig.tcl
#
#  $Log: menuConfig.tcl,v $
#  Revision 1.3  2006/10/26 10:23:11  vfom
#  *** empty log message ***
#
#  Revision 1.2  2006/10/26 09:39:17  vfom
#  Added code for netstate server query
#
# 
#
package require BLT 
# 
# Globals: 
#menuConfigArray - definitions for service menus 
#		This array used in procedures for configuration reading and saving. 
# 
# Export procedures:  
#	makeServiceMenus  - makes all defined in menuConfigArray service menus. 
#		On exit, in global namespace remains popup menus corresponding to 
#		defined in array.     
#                  
#	editServiceMenus  - dialog for modifying currently defined menus 
#		On exit menuConfigArray may be changed, and service menus re-maked. 
# 
#    	getServiceMenus  - returns list of names of all currenly defined menus. 
#  
# 
# 
#
namespace eval SrvMenu { 
variable editServiceMenu_exitFlag	0	\
	menuAddCommand_exitFlag		0	\
	menuAddFunction_exitFlag	0	\
     	menuAddCascade_exitFlag		0	\
	maxSrvMenuIndex			0	\
	arrIndex			0	\
	activeItem			0	\
	c_function			Dummy	
} 
# 
# 
proc menuAddCommandAction { h my_index ename ecmd mode } {
     set mname [$ename get ]     
     set mcmd  [$ecmd get ]     
     if { [string equal $mname ""] } { 	
        tk_dialog $h.dlg "menuAddCommand" \
	    "Need non empty Menu item name." \
	    error 0 [msgcat::mc "Approve"]
	    	return     
	}      
	if { [string equal $mcmd ""] } {
	 	tk_dialog $h.dlg "menuAddCommand" \
		    "Need non empty Menu item command arguments."\
		    error 0 [msgcat::mc "Approve"]
        	return
	} 

    if { [string equal $mode new ] } {

	incr SrvMenu::maxSrvMenuIndex
	set mnew [ $h insert -at $my_index end i$SrvMenu::maxSrvMenuIndex ]

	$h entry configure $mnew -label [join $mname ]
	$h entry configure $mnew -data  [list type command ]
	$h entry configure $mnew -data  [list cmd_line  $mcmd ]
	$h open $mnew
    } else {
	$h entry configure $my_index -label [join $mname]
	$h entry configure $my_index -data  [list cmd_line $mcmd ]
    }

    set SrvMenu::menuAddCommand_exitFlag 1
}
#
proc menuAddCommand { h my_index mode } {

    set w .editServiceMenus.menuAddCommand

    if {[ winfo exists $w ]} then  {
	raise $w ;
	return
    }
    toplevel $w -class Dialog
    wm transient $w [winfo toplevel [winfo parent $w]]
    wm title $w [msgcat::mc "Add Menu Command"]
#
    set curr_row 0
    set wf $w.entryFrame
    frame $wf
    pack $wf -side top -padx 10 -pady 10
#
    label $wf.lname -text [msgcat::mc "Command Name:"]
    grid $wf.lname -in $wf \
	-row $curr_row -column 0 -rowspan 1 -columnspan 1 -sticky e
#    
    entry $wf.ename -width 40
    grid $wf.ename -in $wf \
	-row $curr_row -column 1 -rowspan 1 -columnspan 1 -sticky w

    if { [string equal $mode new ] } {
        $wf.ename delete 0 end
    } else {
        $wf.ename insert 0  [join [ $h entry cget $my_index -label ] ]
    }
    incr curr_row
#        
    label $wf.lcmd -text [msgcat::mc "Command Arguments:"]
    grid $wf.lcmd -in $wf \
	-row $curr_row -column 0 -rowspan 1 -columnspan 1 -sticky e
    
    entry $wf.ecmd -width 60
    grid $wf.ecmd -in $wf \
	-row $curr_row -column 1 -rowspan 1 -columnspan 1 -sticky w

    if { [string equal $mode new ] } {
        $wf.ecmd delete 0 end
    } else {
	array set idata [ $h entry cget $my_index -data ]
        $wf.ecmd insert 0 $idata(cmd_line)	
    }    
#
    set wb $w.buttonFrame
    frame $wb
    pack $wb -side bottom
    button $wb.ok -text [msgcat::mc "Ok"] \
	-command "menuAddCommandAction $h $my_index $wf.ename $wf.ecmd $mode"
    button $wb.cancel -text [msgcat::mc "Cancel"] -command "set SrvMenu::menuAddCommand_exitFlag 1"
    pack $wb.cancel $wb.ok -side right -padx 5 -pady 5


    bind $wf.ename <Return> "focus $wf.ecmd"
    bind $w  <Return> "menuAddCommandAction $h $my_index $wf.ename $wf.ecmd $mode"

    wm withdraw $w
    update idletasks
    set x [expr {[winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \
	    - [winfo vrootx [winfo parent $w]]}]
    set y [expr {[winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
	    - [winfo vrooty [winfo parent $w]]}]

    wm geometry  $w  +$x+$y
    wm deiconify $w
    raise $w
    set oldFocus [focus]
    set oldGrab [grab current $w]
    if {[string compare $oldGrab ""]} {
	set grabStatus [grab status $oldGrab]
    }
    grab $w
    focus $wf.ename

    tkwait variable SrvMenu::menuAddCommand_exitFlag

    catch {focus $oldFocus}
    grab release $w
    destroy $w
    if {[string compare $oldGrab ""]} {
	if {![string compare $grabStatus "global"]} {
	    grab -global $oldGrab
	} else {
	    grab $oldGrab
	}
    }
    return  

}
#
proc menuAddCascadeAction { h my_index ename mode } {

    set mname [$ename get ]
    if { [string equal $mname ""] } {
	tk_dialog $h.dlg "menuAddCascade"  \
	    "Need non empty Menu item name." \
	    error 0 [msgcat::mc "Approve"]
	return
    } 
    if {[string equal $mode new ]} {
	incr SrvMenu::maxSrvMenuIndex
	set mnew [ $h insert -at $my_index end i$SrvMenu::maxSrvMenuIndex ]
	$h entry configure $mnew -label [join $mname]
	$h entry configure $mnew -data  {type menu}
	$h open $mnew
    } else {
	$h entry configure $my_index -label [join $mname]
    }
    set SrvMenu::menuAddCascade_exitFlag 1
}

#
proc menuAddCascade { h my_index mode } {

    set w .editServiceMenus.menuAddCascade

    if {[ winfo exists $w ]} then  {
	raise $w ;
	return
    }
    toplevel $w -class Dialog
    wm transient $w [winfo toplevel [winfo parent $w]]
    wm title $w [msgcat::mc "Add Menu Cascade"]
#
    set curr_row 0
    set wf $w.entryFrame
    frame $wf
    pack $wf -side top -padx 10 -pady 10
#
    label $wf.lname -text [msgcat::mc "Cascade Name:"]
    grid $wf.lname -in $wf \
	-row $curr_row -column 0 -rowspan 1 -columnspan 1 -sticky e
    
    entry $wf.ename -width 40
    grid $wf.ename -in $wf \
	-row $curr_row -column 1 -rowspan 1 -columnspan 1 -sticky w
    
    if { [string equal $mode new ]  } {
	$wf.ename delete 0 end
    } else {
        $wf.ename insert 0 [join [ $h entry cget $my_index -label ]]
    }
    incr curr_row
#
    set wb $w.buttonFrame
    frame $wb
    pack $wb -side bottom
    button $wb.ok -text [msgcat::mc "Ok"] \
	-command "menuAddCascadeAction $h $my_index $wf.ename $mode"
    button $wb.cancel -text [msgcat::mc "Cancel"] -command "set SrvMenu::menuAddCascade_exitFlag 1"
    pack $wb.cancel $wb.ok -side right -padx 5 -pady 5

    bind $w <Return> "menuAddCascadeAction $h $my_index $wf.ename $mode"

    wm withdraw $w
    update idletasks
    set x [expr {[winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \
	    - [winfo vrootx [winfo parent $w]]}]
    set y [expr {[winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
	    - [winfo vrooty [winfo parent $w]]}]

    wm geometry  $w  +$x+$y
    wm deiconify $w
    raise $w
    set oldFocus [focus]
    set oldGrab [grab current $w]
    if {[string compare $oldGrab ""]} {
	set grabStatus [grab status $oldGrab]
    }
    grab $w
    focus $wf.ename

    tkwait variable SrvMenu::menuAddCascade_exitFlag

    catch {focus $oldFocus}
    grab release $w
    destroy $w
    if {[string compare $oldGrab ""]} {
	if {![string compare $grabStatus "global"]} {
	    grab -global $oldGrab
	} else {
	    grab $oldGrab
	}
    }
    return  
}
#
proc menuAddFunctionAction { h my_index ename eargs mode} {
     set mname [$ename get ]     
     set mfunc $SrvMenu::c_function
     set margs  [$eargs get ]     
     if { [string equal $mname ""] } { 	
	 tk_dialog $h.dlg "menuAddFunction"  \
	    "Need non empty Menu item name." \
	     error 0 [msgcat::mc "Approve"]
	return     
     }      
     if { [string equal $mfunc ""] } {
	 tk_dialog $h.dlg "menuAddFunction"  \
	     "Need non empty Menu item command arguments."\
	     error 0 [msgcat::mc "Approve"]
	 return
     } 
     if { [string equal $mode new ] } {
	incr SrvMenu::maxSrvMenuIndex
	set mnew [ $h insert -at $my_index end i$SrvMenu::maxSrvMenuIndex ]
	$h entry configure $mnew -label [join $mname ]
	$h entry configure $mnew -data  [list type function ]
	$h entry configure $mnew -data  [list cmd_line [list $mfunc $margs]]
	$h open $mnew
    } else {
	$h entry configure $my_index -label [join $mname]
	$h entry configure $my_index -data  [list cmd_line [list $mfunc $margs] ]
    }
    set SrvMenu::menuAddFunction_exitFlag  1
}
#
proc menuAddFunction { h my_index mode } {
    global functionList

    set w .editServiceMenus.menuAddFunction

    if {[ winfo exists $w ]} then  {
	raise $w ;
	return
    }
    toplevel $w -class Dialog
    wm transient $w [winfo toplevel [winfo parent $w]]
    wm title $w [msgcat::mc "Add Menu Function"]
#
    set curr_row 0
    set wf $w.entryFrame
    frame $wf
    pack $wf -side top -padx 10 -pady 10
#
    label $wf.lname -text [msgcat::mc "Function Name:"]
    grid $wf.lname -in $wf \
	-row $curr_row -column 0 -rowspan 1 -columnspan 1 -sticky e
#    
    entry $wf.ename -width 40
    grid $wf.ename -in $wf \
	-row $curr_row -column 1 -rowspan 1 -columnspan 1 -sticky w

    if { [string equal $mode new ] } {
        $wf.ename delete 0 end
    } else {
        $wf.ename insert 0  [join [ $h entry cget $my_index -label ] ]
    }
    incr curr_row
#        
    label $wf.lfunc -text [msgcat::mc "Function:"]
    grid $wf.lfunc -in $wf \
	-row $curr_row -column 0 -rowspan 1 -columnspan 1 -sticky e
    
    if { [string equal $mode new ] } {
        set SrvMenu::c_function Dummy
    } else {
        array set idata [ $h entry cget $my_index -data ]
	set fdata $idata(cmd_line)
        set SrvMenu::c_function [lindex $fdata 0 ]
    }    
    
    eval tk_optionMenu $wf.efunc SrvMenu::c_function $functionList
    grid $wf.efunc -in $wf \
	-row $curr_row -column 1 -rowspan 1 -columnspan 1 -sticky w
    incr curr_row

    label $wf.largs -text [msgcat::mc "Function Argumets:"]
    grid $wf.largs -in $wf \
	-row $curr_row -column 0 -rowspan 1 -columnspan 1 -sticky e
    
    entry $wf.eargs -width 60
    grid $wf.eargs -in $wf \
	-row $curr_row -column 1 -rowspan 1 -columnspan 1 -sticky w

    if { [string equal $mode new ] } {
        $wf.eargs delete 0 end
    } else {
        $wf.eargs insert 0 [join [lrange $fdata 1 end ]]
    }    

    set wb $w.buttonFrame
    frame $wb
    pack $wb -side bottom
    button $wb.ok -text [msgcat::mc "Ok"] \
	-command "menuAddFunctionAction $h $my_index $wf.ename $wf.eargs $mode"
    button $wb.cancel -text [msgcat::mc "Cancel"] -command "set SrvMenu::menuAddFunction_exitFlag 1"
    pack $wb.cancel $wb.ok -side right -padx 5 -pady 5

    bind $wf.ename <Return> "focus $wf.efunk"
    bind $w  <Return> "menuAddFunctionAction $h $my_index $wf.ename $wf.eargs $mode"

    wm withdraw $w
    update idletasks
    set x [expr {[winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \
	    - [winfo vrootx [winfo parent $w]]}]
    set y [expr {[winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
	    - [winfo vrooty [winfo parent $w]]}]

    wm geometry  $w  +$x+$y
    wm deiconify $w
    raise $w
    set oldFocus [focus]
    set oldGrab [grab current $w]
    if {[string compare $oldGrab ""]} {
	set grabStatus [grab status $oldGrab]
    }
    grab $w
    focus $wf.ename

    tkwait variable SrvMenu::menuAddFunction_exitFlag

    catch {focus $oldFocus}
    grab release $w
    destroy $w
    if {[string compare $oldGrab ""]} {
	if {![string compare $grabStatus "global"]} {
	    grab -global $oldGrab
	} else {
	    grab $oldGrab
	}
    }
    return  
}
#
# Procedure converts menu items from HierTree to Array
#
# Usage:  from_Tree_to_Array $h 0
#
proc from_Tree_to_Array { h my_index } {
    global menuConfigArray 

    if { $my_index == 0 } {
	array unset menuConfigArray 
	set SrvMenu::arrIndex 0	
    }
    set items  [$h entry children $my_index ]
    set nitems [llength $items]
#    puts "run= $my_index, $items ($nitems)"
    for { set i 0 } { $i<$nitems } { incr i } {
	set subindex [ lindex $items $i ]
	set fullpath [ $h get -full $subindex ] 
	set subpath  [ lrange [join $fullpath ] 1 end ]
	set sublabel [ $h entry cget $subindex -label ]
	set subdata  [ $h entry cget $subindex -data  ]
	array set myArray $subdata
        set subtype  $myArray(type)
	set depth    [llength $subpath ]
	if { $subtype == "menu" }  {
	    set menuConfigArray($SrvMenu::arrIndex) [list $depth $sublabel [list type menu] ]
	} else {
	    set menuConfigArray($SrvMenu::arrIndex) [list $depth $sublabel \
		[list type $myArray(type) cmd_line $myArray(cmd_line)] ]
	}
	incr SrvMenu::arrIndex
	if { [string equal $subtype menu ] } {
	    from_Tree_to_Array $h $subindex
	}
    }
}
#
# Procedure converts menu items from Array to HierTree
#		 	
# Usage:   set SrvMenu::maxSrvMenuIndex [ from_Array_to_Tree $h 0 1 {} ]
#
proc from_Array_to_Tree { h my_index depth parent_path } {
    global menuConfigArray

    set arr_size [ array size menuConfigArray ]
    for { set i $my_index } { $i < $arr_size } {incr i } {
	set tmp_depth [lindex $menuConfigArray($i) 0 ]
	if { $tmp_depth > $depth } {
	    set i [expr $i + [from_Array_to_Tree $h $i $tmp_depth $tmp_path] -1]	    
	} elseif {$tmp_depth == $depth } {
	    set tmp_path $parent_path
	    lappend tmp_path i$i 
	    set mnew [ $h insert end $tmp_path ] 	
	    $h entry configure $mnew -label [join [lindex $menuConfigArray($i) 1 ] ] 
	    $h entry configure $mnew -data  [lindex  $menuConfigArray($i) 2 ]
	} elseif { $tmp_depth < $depth } {
	    return [expr $i - $my_index]
	}
    } 
    return [expr $i - $my_index]    
}
#
#
proc constructMenu { my_index m depth } {
    global menuConfigArray 
    
    set arr_size [ array size menuConfigArray ]

    for { set i $my_index } { $i < $arr_size } { incr i } {
	set tmp_depth [lindex $menuConfigArray($i) 0 ]
	if { $tmp_depth > $depth } {
	    set i [expr $i + [constructMenu  $i $tmp_path $tmp_depth] - 1]	    
	} elseif {$tmp_depth == $depth } {
	    set tmp_path "$m.i$i" 
	    array set data [lindex  $menuConfigArray($i) 2 ]
	    set type  $data(type)
	    if { $type == "menu" } {
		menu $tmp_path -tearoff 0
		$m add cascade -label [join [lindex $menuConfigArray($i) 1 ] ] -menu $tmp_path
		
	    } elseif {$type == "command" } {
		set cmd_args [list $data(cmd_line)]
    		$m add command -label [join [lindex $menuConfigArray($i) 1 ] ] \
		    -command "execSrvMenuCmd $cmd_args"
	    } elseif {$type == "function" } {
		set func_args [list $data(cmd_line)]
    		$m add command -label [join [lindex $menuConfigArray($i) 1 ] ] \
		    -command "execSrvMenuFunc $func_args"
	    }
	} elseif { $tmp_depth < $depth } {
	    return [expr $i - $my_index]
	}
    } 
    return [expr $i - $my_index]    
}
#
proc makeServiceMenus { } {
    global menuConfigArray editEnable
    set arr_size [ array size menuConfigArray ]
    
    set menu_index 0
    for { set i 0 } { $i < $arr_size } { incr i } {
	set depth [lindex $menuConfigArray($i) 0 ]
	if { $depth == 1 } {
	    set m .canvas.labelpopup_$menu_index
	    if {[ winfo exists $m ]} {
		destroy $m
	    }
	    menu $m -tearoff 0     
	    incr menu_index
	    constructMenu [expr $i + 1] $m [expr $depth + 1]
	    if { $editEnable == "yes" } {
		$m add separator
    		$m add command -label [msgcat::mc "Properties"] -command {
		    global activeID
		    if {$activeID !=""} {
			set node [ .canvas itemcget $activeID -window ]
			if {$node != "" } {
			    NodeProperties $node
    			}
    		    }
    		}
		$m add command -label [msgcat::mc "Start Link"] -command {
		    global editMode
		    set editMode "AddLink1"
		    .canvas configure -cursor tcross    
		}
		$m add command -label [msgcat::mc "Delete"] -command {
		    global activeID
    		    if {$activeID !=""} {
    			set node [ .canvas itemcget $activeID -window ]
			if {$node != "" } {
    			    NodeDelete $node
			}
		    }
		}	
		bind $m <FocusOut> { .canvas delete [.canvas find withtag tempFrame ] }
	    }
	  }    
    }
    bind Label <Button-3> { 
        global activeID editMode 
	if { [string equal $editMode Select ] } {
    	    set activeID [.canvas find withtag %W.icon ]
	    if { $activeID != "" } { 
		set node [ .canvas itemcget $activeID -window ]
		if {$node != "" } {
	    	    set menus [ getServiceMenus ]
	    	    set my_index [lsearch -exact $menus $node_menu($node) ]
	    	    if {[winfo exists .canvas.labelpopup_$my_index]} {
			tk_popup .canvas.labelpopup_$my_index %X %Y 
		    
	    	    } elseif {[winfo exists .canvas.labelpopup_0]} {
			tk_popup .canvas.labelpopup_0 %X %Y         
		    }
		}
	    }
	}
    }
}
#
proc execSrvMenuCmd { cmd } {
    global activeID node_name node_ip node_srcip node_snmpget
    if {$activeID !=""} {
	set node [ .canvas itemcget $activeID -window ]
	if {$node != "" } {
	    #
	    # Expansion: %H - node ip address
	    # 		 %N - node name
	    # 		 %S - node source ip address
	    # 		 %M - node SNMP get community
	    # 		 %P - netstate port
	    # 		 %X - netstate server
	    #
	    set csize [llength $cmd]
	    set newcmd [list]
	    for {set i 0} {$i < $csize} {incr i} {		
		set curarg [lindex $cmd $i]
		regsub -all {%H} $curarg  $node_ip($node)      tmp_arg
		regsub -all {%N} $tmp_arg $node_name($node)    curarg
		regsub -all {%S} $curarg  $node_srcip($node)   tmp_arg
		regsub -all {%M} $tmp_arg $node_snmpget($node) curarg
		regsub -all {%P} $curarg  $::netStateServerPort   tmp_arg
		regsub -all {%X} $tmp_arg $::netStateServer curarg
		lappend newcmd $curarg
	    }	     
	    lappend newcmd &
	    if { [catch { eval exec $newcmd } rezult ] } {
		puts stderr "Error: $rezult"
	    	tk_dialog .canvas.dlg "execSrvMenuCmd"  \
		    "Something wrong:\nCMD was:\n\t$newcmd\n Result:\n\t $rezult " \
		    error 0 [msgcat::mc "Approve"]

	    }
    	}
    }
}
#
proc execSrvMenuFunc { cmd } {
    global activeID menuConfigArray node_ip node_srcip node_name node_snmpget
    if {$activeID !=""} {
	set node [ .canvas itemcget $activeID -window ]
	if {$node != "" } {
	    #
	    # Expansion: %H - node ip address
	    # 		 %N - node name
	    # 		 %S - node source ip address
	    # 		 %M - node SNMP get community
	    # 		 %P - netstate port
	    # 		 %X - netstate server
	    set func_name [lindex $cmd 0]
	    set func_args [lrange $cmd 1 end]
	    if {$func_args != {} } {
		set csize [llength $func_args]
		set new_args [list]
		for {set i 0} {$i < $csize} {incr i} {		
		    set curarg [lindex $func_args $i]
		    regsub -all {%H} $curarg  $node_ip($node)      tmp_arg
		    regsub -all {%N} $tmp_arg $node_name($node)    curarg
		    regsub -all {%S} $curarg  $node_srcip($node)   tmp_arg
		    regsub -all {%M} $tmp_arg $node_snmpget($node) curarg
		    regsub -all {%P} $curarg  $::netStateServerPort   tmp_arg
		    regsub -all {%X} $tmp_arg $::netStateServer curarg
		    lappend new_args $curarg
		}
	    }
	    if { [info procs $func_name ] != "" } {
	     	    eval $func_name $func_args	     
	    }
    	}
    }
}
#
# Procedure returns list of currently defined service menus
#
proc getServiceMenus { } {
    global menuConfigArray
    set mList [ list ]
    set arr_size [ array size menuConfigArray ]
    for { set i 0 } { $i < $arr_size } {incr i } {
	set depth [lindex $menuConfigArray($i) 0 ]
	if { $depth == 1 } {
	    lappend mList [lindex $menuConfigArray($i) 1 ] 
	}
    }
    return $mList
}
#
proc editServiceMenusAction { h } {
    global menuConfigArray
#
# remove all previously-existing service menus
#
    set arr_size [ array size menuConfigArray ]
    for { set i 0 } { $i < $arr_size} {incr i} {
	if {[ winfo exists .canvas.labelpopup_$i ]} {
	    destroy .canvas.labelpopup_$i
	}
    }
#
    from_Tree_to_Array $h 0    
    makeServiceMenus
    set SrvMenu::editServiceMenus_exitFlag   1
} 
#
proc menuMoveUpItem { h my_index } {
    set new_index [$h index -at $my_index prevsibling]
    if { $new_index != {} } {
	$h move $my_index before $new_index
    }
}
#
proc menuMoveDownItem { h my_index } {
    set new_index [$h index -at $my_index nextsibling]
    if { $new_index != {} } {
	set check_last_index [$h index -at $new_index nextsibling]
	if { $check_last_index != {} } {
	    $h move $my_index after $new_index
	} else {
	    $h move $new_index before $my_index
	}
    }
}
#
#
# Main procedure for editing Service Menus
# 
#
proc editServiceMenus { } {
    global menuConfigArray

    set w .editServiceMenus

    if {[ winfo exists $w ]} then  {
	raise $w ;
	return
    }
    toplevel $w -class Dialog
    wm transient $w [winfo toplevel [winfo parent $w]]
    wm title $w [msgcat::mc "Configure Service Menus"]

    set h $w.h
    set vs $w.vs
    set hs $w.hs

    blt::hiertable $h -width 0 -width 700 \
	-yscrollcommand { .editServiceMenus.vs set }  \
        -xscrollcommand { .editServiceMenus.hs set }  \
	-selectmode single \
        -hideroot no 
    
    scrollbar $vs -orient vertical -command { .editServiceMenus.h yview }
    scrollbar $hs -orient horizontal -command { .editServiceMenus.h xview }

    set f $w.buttonFrame
    frame $f
    pack $f -side bottom
    button $f.ok -text [msgcat::mc "Ok"] -command "editServiceMenusAction $h"
    button $f.cancel -text [msgcat::mc "Cancel"] -command "set SrvMenu::editServiceMenus_exitFlag 1"
    pack $f.cancel $f.ok -side right -padx 5 -pady 5

    grid rowconfig	$w 0 -weight 1 -minsize 0
    grid columnconfig	$w 0 -weight 1 -minsize 0

    grid $h  -in $w -padx 1 -pady 1 -row 0 -column 0 -rowspan 1 -columnspan 1 -sticky news
    grid $vs -in $w -padx 1 -pady 1 -row 0 -column 1 -rowspan 1 -columnspan 1 -sticky news
    grid $hs -in $w -padx 1 -pady 1 -row 1 -column 0 -rowspan 1 -columnspan 1 -sticky news
    grid $f  -in $w -padx 1 -pady 1 -row 2 -column 0 -rowspan 1 -columnspan 2 -sticky news     

    $h column insert end type cmd_line
    $h column configure treeView -text [msgcat::mc "Item Name"] -width 300
    $h column configure treeView -hide no -edit no
    $h column configure type -text [msgcat::mc "Item Type"] -justify left 
    $h column configure cmd_line -text [msgcat::mc "Item Arguments"] -justify left

    $h entry configure root -label "."
    #
    # Load service menus into tree
    # 
    set SrvMenu::maxSrvMenuIndex [ from_Array_to_Tree $h 0 1 {} ]

    $h configure -bg white

    focus $h

    set m $w.root_popup
    menu $m -tearoff 0
    $m add command -label [msgcat::mc "Add new Service Menu"] -command {
	menuAddCascade .editServiceMenus.h 0 new
    }
    set m $w.menu_popup
    menu $m -tearoff 0
    $m add command -label [msgcat::mc "Add Command"] -command {
	menuAddCommand .editServiceMenus.h $SrvMenu::activeItem new
    }
    $m add command -label [msgcat::mc "Add Function"] -command {    
	menuAddFunction .editServiceMenus.h $SrvMenu::activeItem new
    }    
    $m add command -label [msgcat::mc "Add Cascade"] -command { 
	menuAddCascade .editServiceMenus.h $SrvMenu::activeItem new
    }
    $m add command -label [msgcat::mc "Modify"]	-command { 
	menuAddCascade .editServiceMenus.h $SrvMenu::activeItem edit
    }
    $m add command -label [msgcat::mc "Move Up"]  -command { 
	menuMoveUpItem .editServiceMenus.h $SrvMenu::activeItem
    }
    $m add command -label [msgcat::mc "Move Down"] -command { 
	menuMoveDownItem .editServiceMenus.h $SrvMenu::activeItem
    }
    $m add command -label [msgcat::mc "Delete"]    -command {
	.editServiceMenus.h delete $SrvMenu::activeItem 
    }
    set m $w.cmd_popup
    menu $m -tearoff 0
    $m add command -label [msgcat::mc "Modify"]	-command { 
	menuAddCommand .editServiceMenus.h $SrvMenu::activeItem edit
    }
    $m add command -label [msgcat::mc "Move Up"]   -command { 
	menuMoveUpItem .editServiceMenus.h $SrvMenu::activeItem
    }
    $m add command -label [msgcat::mc "Move Down"] -command { 
	menuMoveDownItem .editServiceMenus.h $SrvMenu::activeItem
    }
    $m add command -label [msgcat::mc "Delete"]	   -command {
	.editServiceMenus.h delete $SrvMenu::activeItem 
    }
    set m $w.func_popup
    menu $m -tearoff 0
    $m add command -label [msgcat::mc "Modify"]	-command { 
	menuAddFunction .editServiceMenus.h $SrvMenu::activeItem edit
    }
    $m add command -label [msgcat::mc "Move Up"]   -command { 
	menuMoveUpItem .editServiceMenus.h $SrvMenu::activeItem
    }
    $m add command -label [msgcat::mc "Move Down"] -command { 
	menuMoveDownItem .editServiceMenus.h $SrvMenu::activeItem
    }
    $m add command -label [msgcat::mc "Delete"]	   -command {
	.editServiceMenus.h delete $SrvMenu::activeItem 
    }


    bind $h <Button-1> {
        set SrvMenu::activeItem [ %W nearest %x %y ]
	set x [%W curselection ]
	if { $x !="" } {
	    %W selection clear $x
	}
	%W selection set [lindex $SrvMenu::activeItem 0]	
    }
    
    bind $h <Button-3> { 
	set w .editServiceMenus
        set SrvMenu::activeItem [ %W nearest %x %y ]
	set x [%W curselection ]
	if { $x !="" } {
	    %W selection clear $x
	}
	%W selection set [lindex $SrvMenu::activeItem 0]	
        set item [ %W get $SrvMenu::activeItem ]
	if { $SrvMenu::activeItem == 0 } {
	    tk_popup $w.root_popup %X %Y
        } else {
	    array set idata [ %W entry cget $SrvMenu::activeItem -data  ] 
	    set itype  $idata(type)
	    if { [string equal $itype menu] } {
    		tk_popup $w.menu_popup %X %Y 
	    } elseif { [string equal $itype command]} {
    		tk_popup $w.cmd_popup %X %Y 
	    } elseif { [string equal $itype function]} {   
    		tk_popup $w.func_popup %X %Y 
	    }
	}
    }
    
    wm withdraw $w
    update idletasks
    set x [expr {[winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \
	    - [winfo vrootx [winfo parent $w]]}]
    set y [expr {[winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
	    - [winfo vrooty [winfo parent $w]]}]

    wm geometry  $w  +$x+$y
    wm deiconify $w
    raise $w
    set oldFocus [focus]
    set oldGrab [grab current $w]
    if {[string compare $oldGrab ""]} {
	set grabStatus [grab status $oldGrab]
    }
    grab $w
    focus $f.ok

    tkwait variable SrvMenu::editServiceMenus_exitFlag

    catch {focus $oldFocus}
    grab release $w
    destroy $w
    if {[string compare $oldGrab ""]} {
	if {![string compare $grabStatus "global"]} {
	    grab -global $oldGrab
	} else {
	    grab $oldGrab
	}
    }
    return  
}
#
