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