animator.tcl
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:21k
源码类别:

通讯编程

开发平台:

Visual C++

  1. #
  2. # Copyright (C) 1998 by USC/ISI
  3. # All rights reserved.                                            
  4. #                                                                
  5. # Redistribution and use in source and binary forms are permitted
  6. # provided that the above copyright notice and this paragraph are
  7. # duplicated in all such forms and that any documentation, advertising
  8. # materials, and other materials related to such distribution and use
  9. # acknowledge that the software was developed by the University of
  10. # Southern California, Information Sciences Institute.  The name of the
  11. # University may not be used to endorse or promote products derived from
  12. # this software without specific prior written permission.
  13. # THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  14. # WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  15. # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16. # $Header: /cvsroot/nsnam/nam-1/tcl/animator.tcl,v 1.48 2007/02/18 22:44:54 tom_henderson Exp $
  17. #-----------------------------------------------------------------------
  18. # Animator instproc init { trace_file args }
  19. #   - Do initializations that are done only once for all netmodels
  20. #-----------------------------------------------------------------------
  21. Animator instproc init { trace_file args } {
  22.   # Move all global variables to instvar
  23.   $self instvar windows trace tracefile 
  24.         prevRate rateSlider currRate netModel 
  25.         running peers peerName granularity direction 
  26.         nam_name graphs NETWORK_MODEL nam_record_filename 
  27.         nam_record_frame id_ sliderPressed maxmon analysis_flag 
  28.         colorname fcolorname now mintime maxtime prevTime range 
  29.         welcome analysis_OK analysis_ready nam_version viewctr 
  30.         plotmarks maxtimeflag pipemode enable_edit_ showenergy_ 
  31.         backward do_validate_nam
  32.   $self instvar observerlist_
  33.   set observerlist_ ""
  34.   # Create shadow
  35.   $self next
  36.   set id_ [Animator set id_]
  37.   Animator set id_ [incr id_]
  38.   Animator instvar SyncAnimator_
  39.   if ![info exists SyncAnimator_] {
  40.     set SyncAnimator_ {}  ;# Empty list
  41.   }
  42.   $self tkvar isSync_
  43.   set isSync_ 0
  44.   set tracefile $trace_file
  45.   set nam_name $tracefile
  46.   
  47.   set showenergy_ 0
  48.   set analysis_flag 0
  49.   set analysis_OK 0
  50.   set analysis_ready 0
  51.   set nam_version 0
  52.   set welcome "                              Welcome to NamGraph 1.13                               "
  53.   # network model used. can be customized in .nam.tcl in current 
  54.   # directory
  55.   set NETWORK_MODEL NetworkModel
  56.   # these next two should be bound variables (or something better)
  57.   set nam_record_filename nam
  58.   set nam_record_frame 0
  59.   set sliderPressed 0
  60.   set direction 1
  61.   set running 0
  62.   # initialize variables for snapshot
  63.   set backward 0
  64.   set do_validate_nam 0
  65.   set viewctr 0
  66.   set maxmon 0
  67.   # Color database used by Statistics module
  68.   set colorname(0) black
  69.   set colorname(1) navy
  70.   set colorname(2) cornflowerblue
  71.   set colorname(3) blue
  72.   set colorname(4) deepskyblue
  73.   set colorname(5) steelblue
  74.   set colorname(6) dodgerblue
  75.   set colorname(7) darkolivegreen
  76.   set fcolorname(0) red
  77.   set fcolorname(1) brown
  78.   set fcolorname(2) purple
  79.   set fcolorname(3) orange
  80.   set fcolorname(4) chocolate
  81.   set fcolorname(5) salmon
  82.   set fcolorname(6) greenyellow
  83.   set fcolorname(7) gold
  84.   
  85.   #plotmarks
  86.   if ![info exists plotmarks] {
  87.     # Initialize - loop assign ?
  88.     set plotmarks(0) mark1
  89.     set plotmarks(1) mark2
  90.     set plotmarks(2) mark3
  91.     set plotmarks(3) mark4
  92.     set plotmarks(4) mark5
  93.     set plotmarks(5) mark6
  94.     set plotmarks(6) mark7
  95.     set plotmarks(7) mark8
  96.     set plotmarks(8) mark1
  97.     set plotmarks(9) mark2
  98.     set plotmarks(10) mark3
  99.     set plotmarks(11) mark4
  100.     set plotmarks(12) mark5
  101.     set plotmarks(13) mark6
  102.     set plotmarks(14) mark7 
  103.     set plotmarks(15) mark8
  104.   }
  105.   set graphs ""
  106.   set statsViews ""
  107.   $self infer-network-model $tracefile
  108.   $self nam_analysis $tracefile
  109.   set netModel [new $NETWORK_MODEL $self $tracefile]
  110.   if [catch {
  111.     set trace [new Trace $tracefile $self]
  112.     set now [$trace mintime]
  113.     set mintime $now
  114.     set maxtime [expr [$trace maxtime] + .05]
  115.     set pipemode 0
  116.     if { [$trace maxtime] == 0 } {
  117.         set maxtime 3.0
  118.         set pipemode 1
  119.         set maxtimeflag 0 
  120.     }
  121.     set range [expr $maxtime - $mintime]
  122.     set prevTime $mintime
  123.     $trace connect $netModel
  124.   } errMsg] {
  125.     error "$errMsg" 
  126.   }
  127.   $self build-ui
  128.   # build-ui{} sets currRate. We allow setting animation rate from 
  129.   # an initialization file using an "one-time" class variable
  130.   Animator instvar INIT_RATE_ INIT_TIME_
  131.   if [info exists INIT_RATE_] {
  132.     set currRate [expr 10.0 * log10([time2real $INIT_RATE_])]
  133.     Animator unset INIT_RATE_
  134.   }
  135.   if [info exists INIT_TIME_] {
  136.     set now [time2real $INIT_TIME_]
  137.     Animator unset INIT_TIME_
  138.   }
  139.   # Initialize peers
  140.   set peerName ""
  141.   set peers ""
  142.   if {$args != ""} {
  143.     catch "array set opts $args"
  144.     if [info exists opts(p)] {
  145.       set peerName $opts(p)
  146.       peer_init $peerName
  147.     }
  148.     if [info exists opts(f)] {
  149.       # User-specified initialization file
  150.       if [file exists $opts(f)] {
  151.         source $opts(f)
  152.       }
  153.     }
  154.     if [info exists opts(j)] {
  155.       # Startup time
  156.       set now [time2real $opts(j)]
  157.     }
  158.     if [info exists opts(r)] {
  159.       # Startup animation rate
  160.       set currRate [expr 10.0 * log10([time2real $opts(r)])]
  161.     }
  162.     if [info exists opts(z)] {
  163.       # Playing nam automatically
  164.       set do_validate_nam 1
  165.     }    
  166.     if [info exists opts(s)] {
  167.       # Playing all windows in sync
  168.       set isSync_ 1
  169.     }
  170.   }
  171.   if [catch {
  172.     $self settime $now
  173.     $self set_rate $currRate 1
  174.   } errMsg] {
  175.     error "$errMsg" 
  176.   }
  177.   if { $showenergy_ == 1 } {
  178.      $self energy_view
  179.   }
  180.   # Hook it to the trace
  181.   $trace connect [new TraceHook $self]
  182.   if { $do_validate_nam == 1 } {
  183.     $self play 1
  184.   }
  185. }
  186. #-----------------------------------------------------------------------
  187. #
  188. #-----------------------------------------------------------------------
  189. Animator instproc infer-network-model { tracefile } {
  190.   #nam_prelayout parses the tracefile before any layout is attempted
  191.   #to see if there is enough header information to use manual layout
  192.   #or whether auto-layout must be performed.
  193.   $self instvar NETWORK_MODEL
  194.   #set file [open $tracefile "r"]
  195.   set stream [new NamStream $tracefile]
  196.   set NETWORK_MODEL NetworkModel
  197.   if { ![regexp "^_" $stream] } {
  198.     puts "nnam: Unable to open the file "$tracefile"n"
  199.     exit
  200.   }
  201.   # skip all beginning non "*" events
  202.   set time "0"
  203.   while {([$stream eof]==0)&&([string compare $time "*"]!=0)} {
  204.     set line [$stream gets]
  205.     set time [get_trace_item "-t" $line]
  206.   }
  207.   set num_link 0 
  208.   while {([$stream eof]==0)&&([string compare $time "*"]==0)} {
  209.     set cmd [lindex $line 0]
  210.     set time [get_trace_item "-t" $line]
  211.     if {[string compare $time "*"]!=0} {
  212.       break
  213.     }
  214.     # Checking for autolayout (l) and wireless modes (W)
  215.     switch $cmd {
  216.       "l" {
  217.         set direction [get_trace_item "-O" $line]
  218.         if {$direction==""} {
  219.           set direction [get_trace_item "-o" $line]
  220.         }
  221.         if {$direction==""} {
  222.           set NETWORK_MODEL NetworkModel/Auto
  223.         }
  224.         incr num_link
  225.       }
  226.       "W" {
  227.         set NETWORK_MODEL NetworkModel/Wireless
  228.         set width [get_trace_item "-x" $line]
  229.         set height [get_trace_item "-y" $line]
  230.         NetworkModel/Wireless set Wpxmax_ $width
  231.         NetworkModel/Wireless set Wpymax_ $height
  232.         break
  233.       }
  234.     }
  235.     # XXX
  236.     # assuming that every line end with End-OF-Line
  237.     set line [$stream gets]
  238.   }
  239.   $stream close
  240.   if {$num_link == 0 && [string compare $NETWORK_MODEL "NetworkModel/Wireless"] !=0 } {
  241.     # No link
  242.     set NETWORK_MODEL NetworkModel/Auto
  243.   }
  244. }
  245. #-----------------------------------------------------------------------
  246. #
  247. #-----------------------------------------------------------------------
  248. Animator instproc peer_init { name handle } {
  249. $self peer $name 0 $handle
  250. $self peer_cmd 0 "peer "[tk appname]" 1 $self"
  251. }
  252. Animator instproc peer_cmd { async cmd } {
  253. $self instvar peers
  254. foreach s $peers {
  255. remote_cmd $async [lindex $s 0] "[lindex $s 1] $cmd"
  256. }
  257. $self sync_cmd $cmd
  258. }
  259. Animator instproc sync_cmd { cmd } {
  260. $self tkvar isSync_
  261. if !$isSync_ {
  262. return
  263. }
  264. Animator instvar SyncAnimator_
  265. foreach s $SyncAnimator_ {
  266. if {$s == $self} { continue }
  267. eval $s $cmd
  268. }
  269. }
  270. Animator instproc peer { name remote handle } {
  271. $self instvar peers
  272. if { $remote } {
  273. peer_cmd 1 "peer "$name" 0 $self"
  274. foreach s $peers {
  275. set p [lindex $s 0]
  276. set h [lindex $s 1]
  277. remote_cmd 1 $name "peer "$p" 0 $h"
  278. }
  279. }
  280. lappend peers [list $name $handle]
  281. }
  282. Animator instproc backFrame { } {
  283. $self instvar now timeStep
  284. $self settime [expr $now - $timeStep]
  285. }
  286. Animator instproc nextFrame { } {
  287.   $self instvar now timeStep direction
  288.   if {$direction > 0} {
  289.     $self settime [expr $now + $timeStep]
  290.   } else {
  291.     $self settime [expr $now - $timeStep]
  292.   }
  293. }
  294. Animator instproc stopmaxtime { stoptime } {
  295. $self instvar maxtimeflag maxtime now mslider pipemode
  296. if {$pipemode == 0 } { return}
  297. if {$maxtimeflag == 1} {return}
  298. set maxtimeflag 1
  299. set maxtime $stoptime
  300. set now $stoptime
  301. $mslider setcurrenttime $now
  302. $mslider setpipemode 0
  303. }
  304. #-----------------------------------------------------------------------
  305. # Animator instproc settime t 
  306. #  - Set time slider to a tick value between 0 and 1000.
  307. #  - t is the current time
  308. #-----------------------------------------------------------------------
  309. Animator instproc settime t {
  310.   $self instvar sliderPressed range mintime timeSlider trace now 
  311.         maxtime graphs netViews statsViews maxtimeflag mslider pipemode
  312.   $self instvar netModel
  313.   $self tkvar nowDisp
  314.   $self tkvar showData_ showRouting_ showMac_
  315.   $netModel select-pkt $showData_  $showRouting_  $showMac_
  316.   # We have come to the end of the animation
  317.   if { $t > $maxtime } {
  318.     if {$pipemode == 0 } {
  319.       $self stop 1
  320.       return
  321.     # Since we are reading from a pipe
  322.     # we must extend the maximum time of the animation
  323.     } else {
  324.       # maxtime has been reached
  325.       if {$maxtimeflag == 1} {
  326.         $self stop 1
  327.         set range [expr $maxtime-$mintime]
  328.         $mslider setmaxtime $maxtime 
  329.         # maxtime window has been found. go back to normal case
  330.         set pipemode 0
  331.         return
  332.       # enlarge the maxtime window
  333.       } else {
  334.         set maxtime [expr $maxtime+10.0]
  335.         set range [expr $maxtime-$mintime]
  336.         $mslider setmaxtime $maxtime 
  337.       }
  338.     }
  339.   # Continue with the animation at this time
  340.   } elseif { $t < $mintime } {
  341.     set t $mintime
  342.   }
  343.   set now $t
  344.   set nowDisp [format %.6f $now]
  345.   # Move timeslider to proper position
  346.   if { $sliderPressed == 0 } {
  347.       $self timesliderset $now
  348.   }
  349.   # tell current animator time to observer
  350.   $self notifyObservers $now
  351.   set event [$trace settime $now $sliderPressed]
  352.   foreach graph $graphs {
  353.       $graph settime $t
  354.   }
  355.   foreach netView $netViews {
  356.       $self update_monitors $netView $now
  357.   }
  358.   # Update positions of annotations
  359.   $self update_annotations $now
  360. }
  361. #-----------------------------------------------------------------------
  362. #
  363. #-----------------------------------------------------------------------
  364. Animator instproc slidetime { tick remote } {
  365. $self instvar now range mintime trace
  366. set now [expr ($tick * $range) / 1000. + $mintime]
  367. $self settime $now
  368. if { $remote } {
  369. #$self peer_cmd 1 "slidetime $tick 0"
  370. # XXX it should do settime instead of slidetime
  371. $self peer_cmd 1 "settime $now"
  372. }
  373. }
  374. Animator instproc recordFrame {} {
  375. # xxx: needs more support for multiple views,
  376. # and for standard filename endings
  377. $self instvar netViews nam_record_filename nam_record_frame
  378. foreach netView $netViews {
  379. $netView record_frame [format "$nam_record_filename%05d.xwd" $nam_record_frame]
  380. incr nam_record_frame
  381. }
  382. }
  383. Animator instproc renderFrame { } {
  384. $self instvar running direction sliderPressed granularity 
  385. pending_frame_
  386. $self tkvar nam_record_animation
  387. if { $running && !$sliderPressed } {
  388. $self nextFrame
  389. update idletasks
  390. if $nam_record_animation {
  391. $self recordFrame
  392. }
  393. set pending_frame_ [after $granularity "$self renderFrame"]
  394. }
  395. }
  396. Animator instproc redrawFrame {} {
  397. $self instvar now
  398. $self settime $now
  399. }
  400. Animator instproc remote_set_direction {t dir} {
  401. $self instvar direction
  402. $self settime $t
  403. set direction $dir
  404. }
  405. Animator instproc set_forward_dir remote {
  406. $self instvar direction now 
  407. set direction 1
  408. if { $remote } {
  409. $self peer_cmd 1 "remote_set_direction $now 1"
  410. }
  411. }
  412. Animator instproc set_backward_dir remote {
  413. $self instvar direction now
  414. set direction -1
  415. if { $remote } {
  416. $self peer_cmd 1 "remote_set_direction $now -1"
  417. }
  418. }
  419. Animator instproc remote_play t {
  420.         $self settime $t
  421.         $self play 0
  422. }
  423. Animator instproc play {remote} {
  424. $self instvar running now
  425. set running 1
  426. after 0 "$self renderFrame"
  427. if { $remote } {
  428. $self peer_cmd 1 "remote_play $now"
  429. }
  430. }
  431. Animator instproc remote_stop t {
  432.         $self stop 0
  433.         $self settime $t
  434. }
  435. Animator instproc stop remote {
  436. $self instvar running now
  437. set running 0
  438. if { $remote } {
  439. $self peer_cmd 1 "remote_stop $now"
  440. }
  441. }
  442. Animator instproc reset { } {
  443. $self settime 0.
  444. $self peer_cmd 1 "settime 0."
  445. }
  446. Animator instproc rewind { } {
  447. $self instvar now timeStep
  448. set t [expr $now - $timeStep*25.0]
  449. $self settime $t
  450. $self peer_cmd 1 "settime $t"
  451. }
  452. Animator instproc fast_fwd { } {
  453. $self instvar now timeStep
  454.         set t [expr $now + $timeStep*25.0]
  455.         $self settime $t
  456. $self peer_cmd 1 "settime $t"
  457. }
  458. Animator instproc next_event { } {
  459. $self instvar trace running
  460. set t [$trace nxtevent]
  461. $self settime $t
  462. $self peer_cmd 1 "settime $t"
  463. if { !$running } {
  464. $self nextFrame
  465. $self peer_cmd 1 nextFrame
  466. }
  467. }
  468. Animator instproc set_rate_ext { v remote } {
  469. $self instvar timeStep stepDisp rateSlider currRate
  470. set orig_v $v
  471. set timeStep [time2real $v]
  472. set v [expr 10.0 * log10($timeStep)]
  473. set stepDisp [step_format $timeStep]
  474.         if { [$rateSlider get] != $v } { $rateSlider set $v }
  475. set currRate $v
  476. if { $remote } {
  477. $self peer_cmd 1 "set_rate $orig_v 0"
  478. }
  479. }
  480. Animator instproc set_rate { v remote } {
  481. $self instvar timeStep stepDisp rateSlider currRate
  482. set orig_v $v
  483. set timeStep [expr pow(10, $v / 10.)]
  484. set stepDisp [step_format $timeStep]
  485.         if { [$rateSlider get] != $v } { $rateSlider set $v }
  486. set currRate $v
  487. if { $remote } {
  488. $self peer_cmd 1 "set_rate $orig_v 0"
  489. }
  490. }
  491. # set how long broadcast packets are visible
  492. Animator instproc set_bcast_duration { time } {
  493. $self instvar netModel
  494. $netModel set bcast_duration_ $time
  495. }
  496. # set the radius of broadcast packets
  497. Animator instproc set_bcast_radius { time } {
  498. $self instvar netModel
  499. $netModel set bcast_radius_ $time
  500. }
  501. # Set time to its previous value (before it was changed by
  502. # pressing mouse button 1 on the time slider).
  503. Animator instproc time_undo { } {
  504.         $self instvar timeSlider prevTime now
  505.         set currTime $now
  506.         $self settime $prevTime
  507. $self peer_cmd 1 "settime $prevTime"
  508.         set prevTime $currTime
  509. }
  510. # Set rate to its previous value (before it was changed by
  511. # pressing mouse button 1 on the rate slider).
  512. Animator instproc rate_undo { } {
  513.         $self instvar prevRate rateSlider
  514.         set tmpRate [$rateSlider get]
  515.         $self set_rate $prevRate 1
  516.         $rateSlider set $prevRate
  517.         set prevRate $tmpRate
  518. }
  519. ## following implements auto fast forward:  when nothing is going
  520. ## on time is moved forward to next event.
  521. # for now, this proc can be called from the trace file using an 
  522. # annotation to enable auto fast forward
  523. Animator instproc auto_ff { } {
  524. $self tkvar nam_auto_ff
  525. set nam_auto_ff 1
  526. }
  527. # skip to next event 
  528. Animator instproc speedup { t } {
  529. $self instvar running 
  530. $self tkvar nam_auto_ff
  531. if { $nam_auto_ff && $running } {
  532. $self next_event 
  533. }
  534. }
  535. # do nothing, but could be more interesting when paired with a different
  536. # implementation of speedup.  e.g., speedup could adjust timeStep and
  537. # this proc could restore it.
  538. Animator instproc normalspeed { } {
  539. }
  540. Animator instproc button_release_1 t {
  541.         $self instvar timeSlider sliderPressed
  542. $self slidetime $t 1
  543.         $timeSlider set $t
  544. set sliderPressed 0
  545. }
  546. Animator instproc button_press_1 s {
  547. $self instvar sliderPressed prevTime
  548. set sliderPressed 1
  549.         set prevTime $s
  550. }
  551. Animator instproc displayStep args {
  552. $self instvar rateSlider stepDisp
  553. $rateSlider configure -label "Step: $stepDisp"
  554. }
  555. Animator instproc back_step { } {
  556.         $self instvar running
  557.         if $running { $self stop 1 }
  558. $self backFrame
  559. $self peer_cmd 1 backFrame
  560. }
  561. Animator instproc toggle_pause { } {
  562.         $self instvar running
  563.         if $running {
  564. $self stop 1
  565. } else {
  566. $self play 1
  567. }
  568. }
  569. Animator instproc single_step { } {
  570.         $self instvar running
  571.         if $running { $self stop 1 }
  572.         $self nextFrame
  573. $self peer_cmd 1 nextFrame
  574. }
  575. Animator instproc dead name {
  576. $self instvar peers
  577. set i [lsearch -exact $peers $name]
  578. set peers [lreplace $peers $i $i]
  579. }
  580. Animator instproc destroy {} {
  581. [AnimControl instance] close-animator $self
  582. $self next
  583. }
  584. Animator instproc cleanup {} {
  585. # We should do all tkvar-related cleanup before doing "delete"
  586. if [$self is-sync] {
  587. $self remove-sync $self
  588. }
  589. $self instvar pending_frame_ tlw_ balloon_
  590. # In case there's a balloon hanging around
  591. delete $balloon_
  592. destroy $tlw_
  593. # Cancel pending animation events
  594. if [info exists pending_frame_] {
  595. after cancel $pending_frame_
  596. }
  597. }
  598. Animator instproc done { } {
  599.         $self peer_cmd 1 "dead "[tk appname]""
  600. $self cleanup
  601. delete $self
  602. }
  603. Animator instproc all_done { } {
  604. $self peer_cmd 1 "destroy"
  605. $self cleanup
  606. delete $self
  607. }
  608. Animator instproc local_change_rate inc {
  609.         $self instvar timeStep stepDisp
  610.         if $inc {
  611.         set timeStep [expr $timeStep + $timeStep*0.05]
  612. } else {
  613.         set timeStep [expr $timeStep - $timeStep*0.05]
  614. }     
  615.         set stepDisp [step_format $timeStep]
  616. }
  617. Animator instproc change_rate inc {
  618. $self instvar timeStep
  619. $self local_change_rate $inc
  620. $self peer_cmd 1 "local_change_rate $inc"
  621. }
  622. Animator instproc ncolor {n0 color} {
  623. $self instvar netModel
  624. $netModel ncolor $n0 $color
  625. }
  626. Animator instproc ecolor {n0 n1 color} {
  627. $self instvar netModel
  628. $netModel ecolor $n0 $n1 $color
  629. $netModel ecolor $n1 $n0 $color
  630. }
  631. Animator instproc add-sync { anim } {
  632. Animator instvar SyncAnimator_
  633. lappend SyncAnimator_ $anim
  634. $self tkvar isSync_
  635. }
  636. Animator instproc remove-sync { anim } {
  637. Animator instvar SyncAnimator_
  638. set pos [lsearch $SyncAnimator_ $anim]
  639. if {$pos != -1} {
  640. set SyncAnimator_ [lreplace $SyncAnimator_ $pos $pos]
  641. }
  642. }
  643. Animator instproc is-sync {} {
  644. $self tkvar isSync_
  645. return $isSync_
  646. }
  647. Animator instproc get-sync {} {
  648. Animator instvar SyncAnimator_
  649. return $SyncAnimator_
  650. }
  651. Animator instproc get-name {} {
  652. $self instvar nam_name
  653. return $nam_name
  654. }
  655. Animator instproc get-tkwin {} {
  656. $self instvar tlw_
  657. return $tlw_
  658. }
  659. # XXX better to inherit it from Observable
  660.         
  661. # Adds an observer to the set of observers for this object.
  662. # @param   o   an observer to be added. 
  663. Animator instproc addObserver { o } {
  664.     $self instvar observerlist_
  665.     set cnt 0
  666.     set oid [$o id]
  667.     foreach ob $observerlist_ {
  668.         set obid [$ob id]
  669.         if { $oid == $obid } {
  670.             set cnt 1
  671.             break;
  672.         } 
  673.     }   
  674.     
  675.     if { $cnt == 0 } {
  676.         lappend observerlist_ $o
  677.     }   
  678. }
  679. # Deletes an observer from the set of observers of this object.
  680. # @param   o   the observer to be deleted.
  681.                 
  682. Animator instproc  deleteObserver { o } { 
  683.     $self instvar observerlist_
  684.     set backlist_ ""
  685.     set oid [$o id]
  686.     foreach ob $observerlist_ {
  687.         set obid [$ob id]
  688.         if { $oid != $obid } {
  689.             lappend backlist_ $ob
  690.         } else {
  691.             $o destory
  692.         }
  693.     }
  694.     
  695.     set observerlist_ $backlist_
  696. }
  697. #----------------------------------------------------------------------
  698. # If this object has changed, as indicated by the
  699. # hasChanged method, then notify all of its observers
  700. # and then call the clearChanged method to indicate
  701. # that this object has no longer changed.
  702. #
  703. # Each observer has its update method called with two
  704. # arguments: this observable object and the arg argument
  705. #
  706. # - What is an observer?  looks like it is NamgraphModel,
  707. #   NamgraphView, TimesliderNamgraphView, and TimesliderView
  708. #----------------------------------------------------------------------
  709. Animator instproc notifyObservers { arg } {
  710.     $self instvar observerlist_
  711.     #??? Synchronization here before updating ???
  712.     foreach ob $observerlist_ {
  713.         if ![ catch { $ob info class } ] {
  714.             $ob update $arg
  715.         }
  716.     }
  717. }
  718. Animator instproc show-energy {} {
  719.     $self instvar showenergy_
  720.     set showenergy_ 1
  721. }
  722. # Returns the number of observers of this object.
  723. Animator instproc countObservers {} {
  724.     $self instvar observerlist_
  725.     set size [llength $observerlist_]
  726.     return $size
  727. }