1# 2# animated wave demo (called by 'widget') 3# 4# based on Tcl/Tk8.5a2 widget demos 5 6# destroy toplevel widget for this demo script 7if defined?($aniwave_demo) && $aniwave_demo 8 $aniwave_demo.destroy 9 $aniwave_demo = nil 10end 11 12# create toplevel widget 13$aniwave_demo = TkToplevel.new {|w| 14 title("Animated Wave Demonstration") 15 iconname("aniwave") 16 positionWindow(w) 17} 18 19base_frame = TkFrame.new($aniwave_demo).pack(:fill=>:both, :expand=>true) 20 21# create label 22msg = TkLabel.new(base_frame) { 23 font $font 24 wraplength '4i' 25 justify 'left' 26 text 'This demonstration contains a canvas widget with a line item inside it. The animation routines work by adjusting the coordinates list of the line.' 27} 28msg.pack('side'=>'top') 29 30# create frame 31TkFrame.new(base_frame) {|frame| 32 TkButton.new(frame) { 33 text 'Dismiss' 34 command proc{ 35 tmppath = $aniwave_demo 36 $aniwave_demo = nil 37 tmppath.destroy 38 } 39 }.pack('side'=>'left', 'expand'=>'yes') 40 41 TkButton.new(frame) { 42 text 'See Code' 43 command proc{showCode 'aniwave'} 44 }.pack('side'=>'left', 'expand'=>'yes') 45 46}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m') 47 48# animated wave 49class AnimatedWaveDemo 50 def initialize(frame, dir=:left) 51 @direction = dir 52 53 # create canvas widget 54 @c = TkCanvas.new(frame, :width=>300, :height=>200, 55 :background=>'black') 56 @c.pack(:padx=>10, :pady=>10, :expand=>true) 57 58 # Creates a coordinates list of a wave. 59 @waveCoords = [] 60 @backupCoords = [] 61 n = 0 62 (-10..300).step(5){|n| @waveCoords << [n, 100]; @backupCoords << [n, 100] } 63 n = 305 64 @waveCoords << [n, 0]; @backupCoords << [n, 0] 65 @waveCoords << [n+5, 200]; @backupCoords << [n+5, 200] 66 @coordsLen = @waveCoords.length 67 68 # Create a smoothed line and arrange for its coordinates to be the 69 # contents of the variable waveCoords. 70 @line = TkcLine.new(@c, @waveCoords, 71 :width=>1, :fill=>'green', :smooth=>true) 72 73 # Main animation "loop". 74 # Theoretically 100 frames-per-second (==10ms between frames) 75 @timer = TkTimer.new(10){ basicMotion; reverser } 76 77 # Arrange for the animation loop to stop when the canvas is deleted 78 @c.bindtags_unshift(TkBindTag.new('Destroy'){ @timer.stop }) 79 end 80 81 # Basic motion handler. Given what direction the wave is travelling 82 # in, it advances the y coordinates in the coordinate-list one step in 83 # that direction. 84 def basicMotion 85 @backupCoords, @waveCoords = @waveCoords, @backupCoords 86 (0...@coordsLen).each{|idx| 87 if @direction == :left 88 @waveCoords[idx][1] = @backupCoords[(idx+1 == @coordsLen)? 0: idx+1][1] 89 else 90 @waveCoords[idx][1] = @backupCoords[(idx == 0)? -1: idx-1][1] 91 end 92 } 93 @line.coords(@waveCoords) 94 end 95 96 # Oscillation handler. This detects whether to reverse the direction 97 # of the wave by checking to see if the peak of the wave has moved off 98 # the screen (whose size we know already.) 99 def reverser 100 if @waveCoords[0][1] < 10 101 @direction = :right 102 elsif @waveCoords[-1][1] < 10 103 @direction = :left 104 end 105 end 106 107 # animation control 108 def move 109 @timer.start 110 end 111 112 def stop 113 @timer.stop 114 end 115end 116 117# Start the animation processing 118AnimatedWaveDemo.new(base_frame, :left).move 119