1#
2# animated label widget demo (called by 'widget')
3#
4# based on Tcl/Tk8.5a2 widget demos
5
6if defined?($anilabel_demo) && $anilabel_demo
7  $anilabel_demo.destroy
8  $anilabel_demo = nil
9end
10
11# demo toplevel widget
12$anilabel_demo = TkToplevel.new {|w|
13  title("Animated Label Demonstration")
14  iconname("anilabel")
15  positionWindow(w)
16}
17
18base_frame = TkFrame.new($anilabel_demo).pack(:fill=>:both, :expand=>true)
19
20# label
21msg = TkLabel.new(base_frame) {
22  font $font
23  wraplength '4i'
24  justify 'left'
25  text "Four animated labels are displayed below; each of the labels on the left is animated by making the text message inside it appear to scroll, and the label on the right is animated by animating the image that it displays."
26}
27msg.pack('side'=>'top')
28
29# frame
30TkFrame.new(base_frame) {|frame|
31  TkButton.new(frame) {
32    text 'Dismiss'
33    command proc{
34      tmppath = $anilabel_demo
35      $anilabel_demo = nil
36      tmppath.destroy
37    }
38  }.pack('side'=>'left', 'expand'=>'yes')
39
40  TkButton.new(frame) {
41    text 'See Code'
42    command proc{showCode 'anilabel'}
43  }.pack('side'=>'left', 'expand'=>'yes')
44
45}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
46
47# create frame for label demo
48f_left = TkLabelFrame.new(base_frame,  :text=>'Scrolling Texts')
49f_right = TkLabelFrame.new(base_frame, :text=>'GIF Image')
50Tk.pack(f_left, f_right, 'side'=>'left', 'expand'=>'yes', 'fill'=>'both',
51        'padx'=>10, 'pady'=>10)
52
53# animated label
54class AnimatedTextLabel < TkLabel
55  def initialize(*args)
56    super(*args)
57    @timer = TkTimer.new{ _animation_callback }
58    @timer.loop_exec = -1
59    # bind('Destroy'){ @timer.stop }
60    @btag = TkBindTag.new('Destroy'){ @timer.stop }
61    self.bindtags_unshift(@btag)
62  end
63
64  def _animation_callback()
65    txt = self.text
66    self.text = (txt[1..-1] << txt[0])
67  end
68  private :_animation_callback
69
70  def start(interval)
71    @timer.set_interval(interval)
72    @timer.start
73  end
74
75  def stop
76    @timer.stop
77  end
78end
79
80# animated image
81class AnimatedImageLabel < AnimatedTextLabel
82  def initialize(*args)
83    super(*args)
84    @destroy_image = false
85    @btag.bind_append('Destroy'){
86      if @destroy_image
87        begin
88          self.image.delete
89        rescue
90        end
91      end
92    }
93  end
94  attr_accessor :destroy_image
95
96  def _animation_callback()
97    img = self.image
98
99    fmt = img.format
100    if fmt.kind_of?(Array)
101      if fmt[1].kind_of?(Hash)
102        # fmt == ['GIF', {'index'=>idx}]
103        idx = fmt[1]['index']
104      else
105        # fmt == ['GIF', '-index', idx]  :: Ruby1.8.2 returns this.
106        idx = fmt[2]
107      end
108    elsif fmt.kind_of?(String) && fmt =~ /GIF -index (\d+)/
109      idx = $1.to_i
110    else
111      idx = -1
112    end
113
114    begin
115      img.format("GIF -index #{idx + 1}")
116    rescue => e
117      img.format("GIF -index 0")
118    end
119  end
120  private :_animation_callback
121end
122
123# create labels
124l1 = AnimatedTextLabel.new(f_left, :borderwidth=>4, :relief=>:ridge,
125                           :font=>{:family=>'Courier', :size=>10})
126l2 = AnimatedTextLabel.new(f_left, :borderwidth=>4, :relief=>:groove,
127                           :font=>{:family=>'Courier', :size=>10})
128l3 = AnimatedTextLabel.new(f_left, :borderwidth=>4, :relief=>:flat,
129                           :font=>{:family=>'Courier', :size=>10}, :width=>18)
130Tk.pack(l1, l2, l3,
131        :side=>:top, :expand=>true, :anchor=>:w, :padx=>10, :pady=>10)
132
133limg = AnimatedImageLabel.new(f_right, :borderwidth=>0)
134limg.pack(:side=>:top, :expand=>true, :padx=>10, :pady=>10)
135
136# base64-encoded animated GIF file
137tclPowerdData = <<EOD
138    R0lGODlhKgBAAPQAAP//////zP//AP/MzP/Mmf/MAP+Zmf+ZZv+ZAMz//8zM
139    zMyZmcyZZsxmZsxmAMwzAJnMzJmZzJmZmZlmmZlmZplmM5kzM2aZzGZmzGZm
140    mWZmZmYzZmYzMzNmzDMzZgAzmSH+IE1hZGUgd2l0aCBHSU1QIGJ5IExARGVt
141    YWlsbHkuY29tACH5BAVkAAEALAAAAAAqAEAAAAX+YCCOZEkyTKM2jOm66yPP
142    dF03bx7YcuHIDkGBR7SZeIyhTID4FZ+4Es8nQyCe2EeUNJ0peY2s9mi7PhAM
143    ngEAMGRbUpvzSxskLh1J+Hkg134OdDIDEB+GHxtYMEQMTjMGEYeGFoomezaC
144    DZGSHFmLXTQKkh8eNQVpZ2afmDQGHaOYSoEyhhcklzVmMpuHnaZmDqiGJbg0
145    qFqvh6UNAwB7VA+OwydEjgujkgrPNhbTI8dFvNgEYcHcHx0lB1kX2IYeA2G6
146    NN0YfkXJ2BsAMuAzHB9cZMk3qoEbRzUACsRCUBK5JxsC3iMiKd8GN088SIyT
147    0RAFSROyeEg38caDiB/+JEgqxsODrZJ1BkT0oHKSmI0ceQxo94HDpg0qsuDk
148    UmRAMgu8OgwQ+uIJgUMVeGXA+IQkzEeHGvD8cIGlDXsLiRjQ+EHroQhea7xY
149    8IQBSgYYDi1IS+OFBCgaDMGVS3fGi5BPJpBaENdQ0EomKGD56IHwO39EXiSC
150    Ysgxor5+Xfgq0qByYUpiXmwuoredB2aYH4gWWda0B7SeNENpEJHC1ghi+pS4
151    AJpIAwWvKPBi+8YEht5EriEqpFfMlhEdkBNpx0HUhwypx5T4IB1MBg/Ws2sn
152    wV3MSQOkzI8fUd48Aw3dOZto71x85hHtHijYv18Gf/3GqCdDCXHNoICBobSo
153    IqBqJLyCoH8JPrLgdh88CKCFD0CGmAiGYPgffwceZh6FC2ohIIklnkhehTNY
154    4CIHHGzgwYw01ujBBhvAqKOLLq5AAk9kuSPkkKO40NB+h1gnypJIIvkBf09a
155    N5QIRz5p5ZJXJpmlIVhOGQA2TmIJZZhKKmmll2BqyWSXWUrZpQtpatlmk1c2
156    KaWRHeTZEJF8SqLDn/hhsOeQgBbqAh6DGqronxeARUIIACH5BAUeAAAALAUA
157    LgAFAAUAAAUM4CeKz/OV5YmqaRkCACH5BAUeAAEALAUALgAKAAUAAAUUICCK
158    z/OdJVCaa7p+7aOWcDvTZwgAIfkEBR4AAQAsCwAuAAkABQAABRPgA4zP95zA
159    eZqoWqqpyqLkZ38hACH5BAUKAAEALAcALgANAA4AAAU7ICA+jwiUJEqeKau+
160    r+vGaTmac63v/GP9HM7GQyx+jsgkkoRUHJ3Qx0cK/VQVTKtWwbVKn9suNunc
161    WkMAIfkEBQoAAAAsBwA3AAcABQAABRGgIHzk842j+Yjlt5KuO8JmCAAh+QQF
162    CgAAACwLADcABwAFAAAFEeAnfN9TjqP5oOWziq05lmUIACH5BAUKAAAALA8A
163    NwAHAAUAAAUPoPCJTymS3yiQj4qOcPmEACH5BAUKAAAALBMANwAHAAUAAAUR
164    oCB+z/MJX2o+I2miKimiawgAIfkEBQoAAAAsFwA3AAcABQAABRGgIHzfY47j
165    Q4qk+aHl+pZmCAAh+QQFCgAAACwbADcABwAFAAAFEaAgfs/zCV9qPiNJouo7
166    ll8IACH5BAUKAAAALB8ANwADAAUAAAUIoCB8o0iWZggAOw==
167EOD
168
169l1.text('* Slow Animation *').start(300)
170l2.text('* Fast Animation *').start(80)
171l3.text('This is a longer scrolling text in a widget that will not show the whole message at once. ').start(150)
172
173limg.destroy_image = true
174limg.image(TkPhotoImage.new(:format=>'GIF', :data=>tclPowerdData)).start(100)
175