1# -*- coding: utf-8 -*-
2#
3# animated wave demo (called by 'widget')
4#
5# based on Tcl/Tk8.5a2 widget demos
6
7# destroy toplevel widget for this demo script
8if defined?($aniwave_demo) && $aniwave_demo
9  $aniwave_demo.destroy
10  $aniwave_demo = nil
11end
12
13# create toplevel widget
14$aniwave_demo = TkToplevel.new {|w|
15  title("Animated Wave Demonstration")
16  iconname("aniwave")
17  positionWindow(w)
18}
19
20base_frame = TkFrame.new($aniwave_demo).pack(:fill=>:both, :expand=>true)
21
22# create label
23msg = TkLabel.new(base_frame) {
24  font $font
25  wraplength '4i'
26  justify 'left'
27  text 'このデモでは、ラインアイテムが一つだけ描かれたキャンバスウィジェットが表示されています。アニメーション処理は、そのラインアイテムの座標値を変更することで実現しています。'
28}
29msg.pack('side'=>'top')
30
31# create frame
32TkFrame.new(base_frame) {|frame|
33  TkButton.new(frame) {
34    #text '了解'
35    text '閉じる'
36    command proc{
37      tmppath = $aniwave_demo
38      $aniwave_demo = nil
39      tmppath.destroy
40    }
41  }.pack('side'=>'left', 'expand'=>'yes')
42
43  TkButton.new(frame) {
44    text 'コード参照'
45    command proc{showCode 'aniwave'}
46  }.pack('side'=>'left', 'expand'=>'yes')
47
48}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
49
50# animated wave
51class AnimatedWaveDemo
52  def initialize(frame, dir=:left)
53    @direction = dir
54
55    # create canvas widget
56    @c = TkCanvas.new(frame, :width=>300, :height=>200,
57                      :background=>'black')
58    @c.pack(:padx=>10, :pady=>10, :expand=>true)
59
60    # Creates a coordinates list of a wave.
61    @waveCoords = []
62    @backupCoords = []
63    n = 0
64    (-10..300).step(5){|n| @waveCoords << [n, 100]; @backupCoords << [n, 100] }
65    n = 305
66    @waveCoords << [n, 0]; @backupCoords << [n, 0]
67    @waveCoords << [n+5, 200]; @backupCoords << [n+5, 200]
68    @coordsLen = @waveCoords.length
69
70    # Create a smoothed line and arrange for its coordinates to be the
71    # contents of the variable waveCoords.
72    @line = TkcLine.new(@c, @waveCoords,
73                        :width=>1, :fill=>'green', :smooth=>true)
74
75    # Main animation "loop".
76    # Theoretically 100 frames-per-second (==10ms between frames)
77    @timer = TkTimer.new(10){ basicMotion; reverser }
78
79    # Arrange for the animation loop to stop when the canvas is deleted
80    @c.bindtags_unshift(TkBindTag.new('Destroy'){ @timer.stop })
81  end
82
83  # Basic motion handler. Given what direction the wave is travelling
84  # in, it advances the y coordinates in the coordinate-list one step in
85  # that direction.
86  def basicMotion
87    @backupCoords, @waveCoords = @waveCoords, @backupCoords
88    (0...@coordsLen).each{|idx|
89      if @direction == :left
90        @waveCoords[idx][1] = @backupCoords[(idx+1 == @coordsLen)? 0: idx+1][1]
91      else
92        @waveCoords[idx][1] = @backupCoords[(idx == 0)? -1: idx-1][1]
93      end
94    }
95    @line.coords(@waveCoords)
96  end
97
98  # Oscillation handler. This detects whether to reverse the direction
99  # of the wave by checking to see if the peak of the wave has moved off
100  # the screen (whose size we know already.)
101  def reverser
102    if @waveCoords[0][1] < 10
103      @direction = :right
104    elsif @waveCoords[-1][1] < 10
105      @direction = :left
106    end
107  end
108
109  # animation control
110  def move
111    @timer.start
112  end
113
114  def stop
115    @timer.stop
116  end
117end
118
119# Start the animation processing
120AnimatedWaveDemo.new(base_frame, :left).move
121