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