#---------------------------------------------------------- # This is a tk shell for AGNI. # This program enables you to interactively build a distributed # system using AGNI. # # The AGNI Project - DISTRIBUTED SCRIPTING FOR THE PEOPLE! # National Institute of Standards and Technology. # Gaithersburg, Maryland. # # Author : M.Ranganathan. # #---------------------------------------------------------- proc check_error { error_string } { if { [string first ETCL_Error $error_string] == -1 } { return 0 } else { return 1 } } if { $tcl_platform(platform) == "unix" } { append auto_path " $env(AGNI_HOME)/applications/support" } else { set AGNI_HOME [file attrib $env(AGNI_HOME) -shortname] append auto_path " $AGNI_HOME/applications/support" } catch { package require balloon package require getopt } error_string if { [string first "can" $error_string] != -1 } { tk_messageBox -icon error -type ok -message $error_string exit } catch { if { $tcl_platform(platform) != "unix" } { load "$AGNI_HOME/lib/etcl.dll" } else { load $env(AGNI_HOME)/lib/libetcl.so Etcl } } error_string catch { unset env(AGNI_LOCAL) } foo if { [string first "couldn't load file" $error_string] != -1 } { tk_messageBox -icon error -type ok -message $error_string exit } #---------------------------------------------------------------------- # The following global variables are used to track the state of # the gui and the system. # max_objs - number of boxes on the screen. # avail_objs - number of available oject locations. # open_streamlist currently open list of streams. # sarray - mapping from stream name to the index of the object array. # stream_objs - an array that holds one rectangular screen object per open # stream and place holder rectangles for streams that are not # open. # name_label - is the label that pops up whenver the cursor slides over an # open MStream. # synch_flag - synchronous flag for append. #----------------------------------------------------------------------- set open_streamlist {} # Generate a cascade menu containing a list of agents and attach the given # command to each item in the list proc gen_agent_list { w sname cmd } { set agents [list_agents $sname] $w delete 0 end foreach agent $agents { $w add command -label "Agent $agent" -command \ "$cmd $sname $agent" } } # Generate a cascade menu containing a list of locations and attach the # given command to each item in the list. proc gen_active_locations { w sname cmd } { set count 0 $w delete 0 end set locations [get_active_locations] set hosts [get_active_hosts] foreach loc $locations { set host [lindex $hosts $count] $w add command -label "$loc ($host)" -command \ "$cmd $sname $loc" incr count } } proc popup_name { stream_name } { global name_label catch { stream_location $stream_name } location if { [check_error $location] != 0 } { tk_messageBox -icon error -type ok -message $location StreamClose $stream_name "" } else { .name_frame.label configure -text "$stream_name currently at $location" } } proc popdown_name {} { .name_frame.label configure -text " " } # set up a balloon for the appropriate button proc menu_help { but item text } { global help_tips set help_tips($but,$item) $text } proc button_help { but text } { global help_tips set help_tips($but) $text } proc StreamAppend { streamname } { global synch_flag$streamname set w .append_dialog$streamname.frame # Extract the text string from the text widget. set text_attrib [$w.text dump -text 1.0 end] for { set i 1} { $i < [llength $text_attrib] } { incr i 3 } { set text_string [append text_string [lindex $text_attrib $i]] } set synch_flag synch_flag$streamname # extract the synchronous button. set flagval [set $synch_flag] if { $flagval == "" } { catch { set retval [stream_append $streamname $text_string -synchronous] } error_string if { [check_error $error_string] != 0 } { tk_messageBox -icon error -type ok -message $error_string } } else { catch { stream_append $streamname $text_string } error_string if { [check_error $error_string] != 0 } { tk_messageBox -icon error -type ok -message $error_string } } } # set up a scrolling text widget to append to an open stream. proc StreamAppendDialog { streamname } { global synch_flag$streamname global asynch_flag$streamname set synch_flag$streamname 1 set asynch_flag$streamname {} toplevel .append_dialog$streamname set toplev .append_dialog$streamname wm title $toplev "Send Message to $streamname" set w [frame $toplev.frame] label $w.label -text "Enter text to send to $streamname" text $w.text -width 50 -height 10 radiobutton $w.synch_flag \ -command "set synch_flag$streamname {}; set asynch_flag$streamname 1 " \ -variable synch_flag$streamname -text "Synch" radiobutton $w.asynch_flag \ -command "set asynch_flag$streamname {}; set synch_flag$streamname 1 " \ -variable asynch_flag$streamname -text "Asynch" button $w.ok -command "StreamAppend $streamname " \ -text OK -background green button $w.cancel -command "destroy $toplev" \ -text Done -background red grid $w.label -row 0 -column 0 -sticky ew grid $w.text -row 1 -column 0 -stick ew grid $w.synch_flag -row 2 -column 0 -sticky w grid $w.asynch_flag -row 2 -column 1 -sticky w grid $w.ok -row 3 -column 0 -sticky w grid $w.cancel -row 3 -column 1 -sticky w pack $w } # Get stuff from the GUI and register an agent with the stream. proc RegisterAgent {streamname} { set w .register_agent$streamname set text_attrib [$w.text dump -text 1.0 end] for { set i 1} { $i < [llength $text_attrib] } { incr i 3 } { set agent_script [append agent_script [lindex $text_attrib $i]] } set argv [$w.argframe.argv get] catch { register_agent $streamname $argv $agent_script } error_string if { [check_error $error_string] != 0 } { tk_messageBox -icon error -type ok -message $error_string } destroy $w } # Set up a scrolling text widget with prompts to register an agent proc RegisterAgentDialog { streamname } { toplevel .register_agent$streamname set toplev .register_agent$streamname label $toplev.label1 -text "Enter Argument to send to Agent" frame $toplev.argframe label $toplev.argframe.arglabel -text "argv" entry $toplev.argframe.argv -width 80 wm title $toplev "Register an Agent for $streamname" text $toplev.text -width 80 -height 30 \ -yscroll "$toplev.yscroll set" scrollbar $toplev.yscroll -command "$toplev.text yview" label $toplev.label2 -text "Enter Agent Script:" $toplev.text insert 0.0 " # Uncomment and add code to the handlers you want. # on_stream_append { # Message consumption handler. # Be careful to return something on synchronous append ! # return OK # } # on_stream_relocation { # Handler to execute on agent relocation. # } # on_stream_failure { # Handler to execute on failure of location where stream resides. # } # on_agent_exit { # finalizer. # } " frame $toplev.buttons button $toplev.buttons.ok -text "OK" -background green \ -command "RegisterAgent $streamname" button $toplev.buttons.cancel -text "CANCEL" -background red \ -command "destroy $toplev" pack $toplev.label1 pack $toplev.argframe pack $toplev.argframe.arglabel $toplev.argframe.argv -side left -ipadx 5 pack $toplev.yscroll -side right -fill y pack $toplev.label2 pack $toplev.text pack $toplev.buttons -side bottom -fill x -pady 2m pack $toplev.buttons.ok $toplev.buttons.cancel -side left \ -ipadx 10 -expand 1 } # Move a stream to a new location. proc StreamMove {streamname loc} { catch { set newloc [stream_move $streamname $loc] } error_string if { [check_error $error_string] != 0 } { tk_messageBox -icon error -type ok -message $error_string } } proc KillAgent { streamname agent} { set answer [tk_messageBox -message \ "Killing an agent removes all its handlers. Proceed?" \ -type yesno -icon warning] if { $answer == "yes" } { catch { kill_agent $streamname $agent } error_string if { [check_error $error_string] != 0 } { tk_messageBox -icon error -type ok -message $error_string } } } proc GetAgentCode { streamname agent } { # Get the agent code and display it in a scrollable text widget. toplevel .gac_$streamname$agent set toplev .gac_$streamname$agent wm title $toplev "Agent Code for $streamname Agent $agent" set code [get_agent_code $streamname $agent] text $toplev.text -width 80 -height 20 \ -yscroll "$toplev.yscroll set" \ -xscroll "$toplev.xscroll set" $toplev.text insert 0.0 $code scrollbar $toplev.yscroll -command "$toplev.text yview" scrollbar $toplev.xscroll -command "$toplev.text xview" \ -orient horizontal button $toplev.ok -command "destroy $toplev" -text "OK" \ -background green grid $toplev.text -row 0 -column 0 grid $toplev.yscroll -row 0 -column 1 -sticky ns grid $toplev.xscroll -row 1 -column 0 -sticky ew grid $toplev.ok -row 2 -column 0 } # Destroy the stream and remove its representation from the canvas. proc StreamDestroy { stream_name w } { global open_streamlist global sarray global stream_objs global avail_objs set answer [tk_messageBox -message \ "Destroying a stream removes all its Agents. Proceed?" \ -type yesno -icon warning] if { $answer == "no" } { return } catch { stream_destroy $stream_name } error_string if { [check_error $error_string] != 0 } { tk_messageBox -icon error -type ok -message $error_string return } set index [lsearch -exact $open_streamlist $stream_name] if { $index == -1 } { tk_messageBox -icon error -type ok \ -message "Internal Error!" exit } # call etcl to close stream here set open_streamlist [lreplace $open_streamlist $index $index] set oid $sarray($stream_name) .canvas_frame.c itemconfigure $stream_objs($oid) -fill "" .canvas_frame.c bind $stream_objs($oid) "" .canvas_frame.c bind $stream_objs($oid) "" .canvas_frame.c bind $stream_objs($oid) "" set avail_objs($oid) 1 destroy $w } proc get_stream_list {} { set streams [list_streams] set stream_list {} for { set i 0 } { $i < [llength $streams] } { incr i 2 } { lappend stream_list [lindex $streams $i] } return $stream_list } # Close an open stream - get rid of its bindings so we can no longer # invoke operations on it from the shell. proc StreamClose { stream_name w} { global open_streamlist global sarray global stream_objs global avail_objs global op_inprogress global sarray set index [lsearch -exact $open_streamlist $stream_name] if { $index == -1 } { tk_messageBox -icon error -type ok \ -message "Internal Error!" exit } # call etcl to close stream here set open_streamlist [lreplace $open_streamlist $index $index] set oid $sarray($stream_name) set avail_objs($oid) 1 set op_inprogress($stream_name) 0 # Destroy the menu if { $w != "" } { destroy $w } # Update the canvas and re-do bindings. .canvas_frame.c itemconfigure $stream_objs($oid) -fill "" .canvas_frame.c bind $stream_objs($oid) "" .canvas_frame.c bind $stream_objs($oid) "" .canvas_frame.c bind $stream_objs($oid) "" } # Open an existing stream proc open_stream { stream_name } { global open_streamlist global sarray global stream_objs global avail_objs global max_objs global help_tips global op_inprogress # find a box in our GUI to assign. set found 0 for { set index 0 } { $index < $max_objs } { incr index } { if { $avail_objs($index) == 1} { set found 1 break } } # If we already have an open stream handle then return. if { [lsearch -exact $open_streamlist $stream_name] != -1 } { tk_messageBox -icon info -type ok \ -message "The stream is already open!" return } # Call AGNI to open the stream catch { stream_open $stream_name } error_string if { [check_error $error_string] != 0 } { tk_messageBox -icon info -type ok \ -message $error_string return } set op_inprogress($stream_name) 0 if {$found == 1} { set avail_objs($index) 0 } else { tk_messageBox -icon error -type ok \ -message "Cant open any more streams - GUI is full" return } lappend open_streamlist $stream_name set sarray($stream_name) $index .canvas_frame.c bind $stream_objs($index) \ "operations_menu $stream_name" .canvas_frame.c bind $stream_objs($index) \ "popup_name $stream_name" .canvas_frame.c bind $stream_objs($index) \ "popdown_name" .canvas_frame.c itemconfigure $stream_objs($index) -fill red } # Make a button state active proc ActivateButton { sname toplev } { global op_inprogress global stream_objs global sarray set op_inprogress($sname) 0 set index $sarray($sname) .canvas_frame.c itemconfigure $stream_objs($index) -fill red destroy $toplev } # Setup the operations menu for individual streams. proc operations_menu { sname } { global op_inprogress global sarray global stream_objs if { $op_inprogress($sname) == 1 } { return } set op_inprogress($sname) 1 set index $sarray($sname) .canvas_frame.c itemconfigure $stream_objs($index) -fill blue toplevel .opmenu_frame$sname set toplev .opmenu_frame$sname wm title $toplev "Operations" frame $toplev.frame -width 15 set w $toplev.frame label $w.label -text "Operation to perform on $sname" button $w.done -text "DONE" -background green \ -command "ActivateButton $sname $toplev" button $w.register_agent -text "Register Agent" \ -command "RegisterAgentDialog $sname" button_help $w.register_agent "Register an Agent for $sname" button $w.stream_close -text "Close" \ -command "StreamClose $sname $toplev" button_help $w.close "Close $sname in this program." button $w.stream_destroy -text "Destroy" \ -command "StreamDestroy $sname $toplev" button_help $w.stream_destroy "Destroy MStream $sname and all its Agents " button $w.stream_append -text "Send Message" \ -command "StreamAppendDialog $sname" button_help $w.stream_append "Send a message to MStream $sname" menubutton $w.stream_move \ -text "Move" -menu $w.stream_move.locations -relief raised button_help $w.stream_move "Move $sname to a new location" set move_menu [menu $w.stream_move.locations -tearoff 0 \ -postcommand "gen_active_locations \ $w.stream_move.locations $sname StreamMove" ] menubutton $w.kill_agent -text "Kill Agent" \ -menu $w.kill_agent.agent_list -relief raised set kill_menu [menu $w.kill_agent.agent_list -tearoff 0 \ -postcommand "gen_agent_list $w.kill_agent.agent_list \ $sname KillAgent" ] menubutton $w.get_agent_code -text "View Agent Code" \ -menu $w.get_agent_code.agent_list -relief raised set view_menu [menu $w.get_agent_code.agent_list -tearoff 0 \ -postcommand "gen_agent_list $w.get_agent_code.agent_list \ $sname GetAgentCode" ] set i 0 foreach item [list $w $w.label $w.stream_append $w.register_agent \ $w.stream_close $w.stream_destroy $w.get_agent_code \ $w.kill_agent $w.stream_move] { grid $item -row $i -column 0 -sticky ew incr i } grid $w.done -row $i -column 0 -ipadx 10 -sticky ew } # Setup the initial canvas. proc setup_canvas { cframe } { global open_streamlist global stream_objs global avail_objs global max_objs set w $cframe set c $w.c frame $w.grid scrollbar $w.hscroll -orient horiz -command "$c xview" scrollbar $w.vscroll -command "$c yview" canvas $c -relief sunken -borderwidth 2 \ -scrollregion {0c 0c 50c 40c} \ -xscrollcommand "$w.hscroll set" \ -yscrollcommand "$w.vscroll set" pack $w.grid -expand yes -fill both -padx 1 -pady 1 grid rowconfig $w.grid 0 -weight 1 -minsize 0 grid columnconfig $w.grid 0 -weight 1 -minsize 0 grid $c -padx 1 -in $w.grid -pady 1 \ -row 0 -column 0 -rowspan 1 -columnspan 1 -sticky news grid $w.vscroll -in $w.grid -padx 1 -pady 1 \ -row 0 -column 1 -rowspan 1 -columnspan 1 -sticky news grid $w.hscroll -in $w.grid -padx 1 -pady 1 \ -row 1 -column 0 -rowspan 1 -columnspan 1 -sticky news set bg green set count 0 for {set i 0} {$i < 20} {incr i} { set x [expr { 3*$i}] for {set j 0; set y 0} {$j < 20} {incr j; incr y 2} { set objid [ $c create rect ${x}c ${y}c \ [expr $x+1]c [expr $y+1]c \ -outline "" -fill "" -tags rect] # keep track of the object ids for the rectangles. set stream_objs($count) $objid set avail_objs($count) 1 incr count } } set max_objs $count } # Create a stream and update the gui. proc StreamCreate {} { global open_streamlist global sarray global avail_objs global stream_objs global max_objs global op_inprogress set w .create set text_attrib [$w.text dump -text 1.0 end] # set resctl_script "{" for { set i 1} { $i < [llength $text_attrib] } { incr i 3 } { set resctl_script [append resctl_script [lindex $text_attrib $i]] } # append resctl_script "}" set streamname [$w.stream_name get] set index [lsearch -exact $open_streamlist $streamname] if { $index != -1 } { tk_messageBox -icon error -type ok \ -message "Stream $streamname exists!" destroy $w return } catch { stream_create $streamname -controller $resctl_script } error_string if { [check_error $error_string] != 0 } { tk_messageBox -icon error -type ok -message $error_string return } set op_inprogress($streamname) 0 set found 0 for { set index 0 } { $index < $max_objs } { incr index } { if { $avail_objs($index) == 1} { set found 1 break } } if {$found == 1} { set avail_objs($index) 0 } else { tk_messageBox -icon error -type ok \ -message "Cant open any more streams - GUI is full" return } lappend open_streamlist $streamname set sarray($streamname) $index .canvas_frame.c bind $stream_objs($index) \ "operations_menu $streamname" .canvas_frame.c bind $stream_objs($index) \ "popup_name $streamname" .canvas_frame.c bind $stream_objs($index) \ "popdown_name" .canvas_frame.c itemconfigure $stream_objs($index) -fill red destroy $w } # Ask the user for information in order to create a stream. proc StreamCreateDialog {} { toplevel .create wm title .create "Create a new MStream" set create_authscript 0 label .create.label1 -text "Enter stream name to create: " entry .create.stream_name -width 80 text .create.text -width 80 -height 30 \ -yscroll ".create.yscroll set" scrollbar .create.yscroll -command ".create.text yview" label .create.label2 -text "Enter Optional Stream Controller: " .create.text insert 0.0 " # Uncomment and add code to the handlers you want. # # on_stream_append { # Message consumption handler. # argv contains the message appended. # schedule agents and run_scheduled_agents to get user registered # agents to run as follows: # # foreach i \[list_agents\] { # schedule_agent \$i # } # run_scheduled_agents # } # on_stream_move { # Policy handler to verify reconfiguration. # argv contains the target location. # Return 0 to allow the move and 1 to disallow it. # return 0 # } # on_stream_new_agent { # Handler to authenticate new agent registrations. # use stream_sender_name and stream_sender_location to # query about the senders name and location. # return 0 to allow the agent addition and 1 to disallow it. # return 0 # } # on_stream_move_fail { # Handler to run when relocation fails. # } # on_stream_relocation { # Handler for the relocation event. # Runs at the target location after the move completes. # schedule agents and run_scheduled_agents to get user registered # agents to run as follows: # # foreach i \[list_agents\] { # schedule_agent \$i # } # run_scheduled_agents # } # on_stream_failure { # Handler to run at system controller on failure. # } # on_stream_open { # Handler to approve/disapprove opens. # Return 0 to approve the open and 1 to disapprove it. # return 0 # } # on_stream_close { # Notification on stream close. # } # on_stream_agent_kill { # [lindex argv 0] contains stream name # [lindex argv 1] contains agent_id # } # post_process { # Post processing handler # # Use get_move_targets and set_move_target to choose the relocation # target. # # Use get_current_event to query the context for which # post-processing has been invoked. # # } " frame .create.buttons button .create.buttons.ok -text "OK" -background green \ -command "StreamCreate" button .create.buttons.cancel -text "CANCEL" -background red \ -command "destroy .create" pack .create.label1 pack .create.stream_name pack .create.yscroll -side right -fill y pack .create.label2 pack .create.text pack .create.buttons -side bottom -fill x -pady 2m pack .create.buttons.ok .create.buttons.cancel -side left \ -ipadx 10 -expand 1 } # Get the active locations proc get_active_locations {} { set peer_map [get_active_peer_map] set active_peers {} for { set i 0} { $i < [llength $peer_map] } { incr i 2 } { lappend active_peers [lindex $peer_map $i] } return $active_peers } # Get the active hosts proc get_active_hosts {} { set peer_map [get_active_peer_map] set active_peers {} for { set i 1} { $i < [llength $peer_map] } { incr i 2 } { lappend active_peers [lindex $peer_map $i] } return $active_peers } # Show the active locations in a list box proc show_active_map {} { } # Show the peer map (active and inactive locations) proc show_peer_map {} { toplevel .plist set w .plist wm title $w "Peer map" } # Open the selected stream proc open_selected_stream {} { global lbox_name global stream_list set cursel [ $lbox_name curselection ] set stream_name [lindex $stream_list $cursel] open_stream $stream_name } # generate a list box with the list of streams and open proc SelectAndOpenStream {} { global lbox_name global stream_list set stream_list [get_stream_list] toplevel .slist set w .slist wm title $w "Pick a stream to open" label $w.msg -justify left -text \ "Pick a MStream to open:" pack $w.msg -side top frame $w.frame -borderwidth 5 # pack the frame in the top level window. pack $w.frame -side top -expand yes -fill x scrollbar $w.frame.yscroll -command "$w.frame.list yview" scrollbar $w.frame.xscroll -orient horizontal \ -command $w.frame.list.xview listbox $w.frame.list -selectmode single \ -width 20 -height 10 -setgrid 1 \ -yscroll "$w.frame.yscroll set" \ -xscroll "$w.frame.xscroll set" set lbox_name $w.frame.list foreach s $stream_list { $w.frame.list insert end $s } grid $w.frame.list -row 0 -column 0 -rowspan 1 -sticky news grid $w.frame.yscroll -row 0 -column 1 -columnspan 1 -sticky news grid $w.frame.xscroll -row 1 -column 0 -columnspan 1 -sticky news grid rowconfig $w.frame 0 -weight 1 -minsize 0 grid columnconfig $w.frame 0 -weight 1 -minsize 0 frame $w.buttons pack $w.buttons -side bottom -fill x -pady 2m button $w.buttons.dismiss -text "CANCEL" -command { destroy .slist } button $w.buttons.open -text "OK" -command { open_selected_stream destroy .slist } pack $w.buttons.dismiss -side left pack $w.buttons.open -side right } proc StartDaemonAndJoinSession {} { global env set session_name [.session.session_frame.session_name get] set sitectl_script [.session.sitectl_frame.sitectl_ent get] set sessionctl_script [.session.sysctl_frame.sysctl_ent get] if { $sitectl_script != "" && $sessionctl_script != "" } { exec $env(AGNI_HOME)/bin/agnid -h $session_name \ -l $sitectl_script -s $sessionctl_script & } elseif { $sitectl_script != "" } { exec $env(AGNI_HOME)/bin/agnid -h $session_name \ -l $sitectl_script & } elseif { $sessionctl_script != "" } { exec $env(AGNI_HOME)/bin/agnid -h $session_name \ -s $sessionctl_script & } else { exec $env(AGNI_HOME)/bin/agnid -h $session_name & } after 2000 catch { join_session $session_name } error_string if { [check_error $error_string] != 0 } { tk_messageBox -icon error -type ok -message $error_string } else { .opframe.shell configure -state active .opframe.leave_session configure -state active .opframe.mb configure -state active .opframe.join_session configure -state disabled destroy .session set fd [open "$env(HOME)/.agnirc" "w+"] puts $fd "join_session $session_name " close $fd label .name_frame.session_name -text "Session: $session_name" \ -foreground red pack .name_frame.session_name } } proc LeaveSession {} { global env global open_streamlist set answer [tk_messageBox -message \ "Leaving the session will kill the AGNI daemon. Proceed?" \ -type yesno -icon warning] if { $answer == "no" } { return } leave_session file delete "$env(HOME)/.agnirc" .opframe.shell configure -state disabled .opframe.leave_session configure -state disabled .opframe.mb configure -state disabled .opframe.join_session configure -state active destroy .name_frame.session_name foreach stream $open_streamlist { StreamClose $stream "" } # Clean up the canvas. } proc FileDialog { w ent } { set types { { "Tcl scripts" {.tcl .etcl}} { "All files" * } } set file [tk_getOpenFile -filetypes $types -parent $w] if [string compare $file ""] { $ent delete 0 end $ent insert 0 $file $ent xview end } } proc JoinSession {} { toplevel .session set w .session wm title $w "Start daemon and join a session" label $w.msg -justify left -text \ "This will start your agni daemon and attempt to join a session. A session is specified as a pair - name (or IP address):port. Leave the name blank (specify only :port) if you are the session leader" set f0 [frame $w.session_frame] entry $f0.session_name -width 60 label $f0.label -text "Session: " -width 25 pack $f0.label $f0.session_name -side left set f [frame $w.sitectl_frame] label $f.sitectl_label -text "Site Controller Script:" -width 25 entry $f.sitectl_ent -width 40 button $f.sitectl_but -command "FileDialog $w $f.sitectl_ent" \ -text "Browse..." pack $f.sitectl_label $f.sitectl_ent $f.sitectl_but -side left set f1 [frame $w.sysctl_frame] label $f1.sysctl_label -text "System Controller Script:" -width 25 entry $f1.sysctl_ent -width 40 button $f1.sysctl_but -command "FileDialog $w $f1.sysctl_ent" \ -text "Browse..." pack $f1.sysctl_label $f1.sysctl_ent $f1.sysctl_but -side left frame $w.buttons button $w.buttons.ok -text "OK" -command "StartDaemonAndJoinSession" \ -background green button $w.buttons.cancel -text "CANCEL" -command "destroy .session" \ -background red pack $w.buttons.ok $w.buttons.cancel -side left -fill x -expand 1 pack $w.msg $f0 $f $f1 $w.buttons } proc Quit {} { leave_session exit } #-- HERE is the main script ---- wm title . "AGNI Distributed System builder" frame .opframe -width 100 -height 30 init_balloons -delay 300 #--- edit menu items ------ menubutton .opframe.mb -text "Edit" -menu .opframe.mb.menu -relief raised set m [menu .opframe.mb.menu -tearoff 0] $m add command -label "Create Stream" -command { StreamCreateDialog } menu_help $m 0 "Create a new MStream" $m add command -label "Open Stream" -command { SelectAndOpenStream } menu_help $m 1 "Open an existing MStream" #--- Peers menu items ---- # menubutton .opframe.mb1 -text "Peers" -menu .opframe.mb1.menu # set m1 [menu .opframe.mb1.menu -tearoff 0] # $m1 add command -label "Peer Map" -command { show_peermap } # menu_help $m1 0 "Map all peer identifiers" # $m1 add command -label "Active Map" -command { show_active_map } # menu_help $m1 1 "Show identity of active peers" #--- Shell if { $tcl_platform(platform) != "unix" } { set m [ button .opframe.shell -text "Shell" \ -command "exec xterm -e $env(AGNI_HOME)/bin/etcl &" ] } else { set m [ button .opframe.shell -text "Shell" \ -command "exec $env(AGNI_HOME)/bin/etcl &" ] } button_help $m "Start a text-mode shell to interact with AGNI" #endif #--- Leave Session set m [ button .opframe.leave_session -text \ "Leave Session" -command "LeaveSession"] menu_help $m 1 "Leave the current MStream Session. " #--- Join Session set m [button .opframe.join_session -text "Join Session" \ -command "JoinSession"] menu_help $m 1 "Join an MStream Session." #--- Quit button .opframe.quit -text "Quit" -command Quit button_help .opframe.quit "Exit this program" #---- Streams menu set i 0 foreach w [list .opframe.mb .opframe.join_session .opframe.leave_session \ .opframe.shell .opframe.quit ] { grid $w -row $i -column 0 -sticky ew incr i } .opframe.shell configure -state disabled .opframe.leave_session configure -state disabled .opframe.mb configure -state disabled pack .opframe -side left frame .canvas_frame setup_canvas .canvas_frame pack .canvas_frame frame .name_frame -width 300 -height 10 pack .name_frame set name_label [label .name_frame.label -text " "] pack $name_label