summaryrefslogtreecommitdiff
path: root/ext/tk/lib/tkafter.rb
diff options
context:
space:
mode:
Diffstat (limited to 'ext/tk/lib/tkafter.rb')
-rw-r--r--ext/tk/lib/tkafter.rb296
1 files changed, 296 insertions, 0 deletions
diff --git a/ext/tk/lib/tkafter.rb b/ext/tk/lib/tkafter.rb
new file mode 100644
index 0000000000..be2e50ff3a
--- /dev/null
+++ b/ext/tk/lib/tkafter.rb
@@ -0,0 +1,296 @@
+#
+# tkafter.rb : methods for Tcl/Tk after command
+# 1998/07/02 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+#
+require 'tk'
+
+class TkAfter
+ include TkCore
+ extend TkCore
+
+ Tk_CBID = [0]
+ Tk_CBTBL = {}
+
+ INTERP._invoke("proc", "rb_after", "args", "ruby [format \"TkAfter.callback %%Q!%s!\" $args]")
+
+ ###############################
+ # class methods
+ ###############################
+ def TkAfter.callback(arg)
+ @after_id = nil
+ arg = Array(tk_split_list(arg))
+ obj_id = arg.shift
+ ex_obj = Tk_CBTBL[obj_id]
+ return nil if ex_obj == nil; # canceled
+ _get_eval_string(ex_obj.do_callback(*arg))
+ end
+
+ def TkAfter.info
+ tk_call('after', 'info').split(' ').filter{|id|
+ ret = Tk_CBTBL.find{|key,val| val.after_id == id}
+ (ret == nil)? id: ret[1]
+ }
+ end
+
+ ###############################
+ # instance methods
+ ###############################
+ def do_callback(*args)
+ @in_callback = true
+ ret = @current_proc.call(*args)
+ if @set_next
+ set_next_callback(*args)
+ else
+ @set_next = true
+ end
+ @in_callback = false
+ ret
+ end
+
+ def set_callback(sleep, args=nil)
+ @after_script = "rb_after #{@id} #{_get_eval_string(args)}"
+ @after_id = tk_call('after', sleep, @after_script)
+ @current_script = [sleep, @after_script]
+ end
+
+ def set_next_callback(*args)
+ if @running == false || @proc_max == 0 || @do_loop == 0
+ Tk_CBTBL[@id] = nil ;# for GC
+ @running = false
+ return
+ end
+ if @current_pos >= @proc_max
+ if @do_loop < 0 || (@do_loop -= 1) > 0
+ @current_pos = 0
+ else
+ Tk_CBTBL[@id] = nil ;# for GC
+ @running = false
+ return
+ end
+ end
+
+ @current_args = args
+
+ if @sleep_time.kind_of? Proc
+ sleep = @sleep_time.call(*args)
+ else
+ sleep = @sleep_time
+ end
+ @current_sleep = sleep
+
+ cmd, *cmd_args = @loop_proc[@current_pos]
+ @current_pos += 1
+ @current_proc = cmd
+
+ if cmd_args[0].kind_of? Proc
+ #c = cmd_args.shift
+ #cb_args = c.call(*(cmd_args + args))
+ cb_args = cmd_args[0].call(*args)
+ else
+ cb_args = cmd_args
+ end
+
+ set_callback(sleep, cb_args)
+ end
+
+ def initialize(*args)
+ @id = format("a%.4d", Tk_CBID[0])
+ Tk_CBID[0] += 1
+
+ @set_next = true
+
+ @init_sleep = 0
+ @init_proc = nil
+ @init_args = []
+
+ @current_script = []
+ @current_proc = nil
+ @current_args = nil
+
+ @sleep_time = 0
+ @current_sleep = 0
+ @loop_exec = 0
+ @do_loop = 0
+ @loop_proc = []
+ @proc_max = 0
+ @current_pos = 0
+
+ @after_id = nil
+ @after_script = nil
+
+ set_procs(*args) if args != []
+
+ @running = false
+ end
+
+ attr :after_id
+ attr :after_script
+ attr :current_proc
+ attr :current_sleep
+
+ attr_accessor :loop_exec
+
+ def get_procs
+ [@init_sleep, @init_proc, @init_args, @sleep_time, @loop_exec, @loop_proc]
+ end
+
+ def current_status
+ [@running, @current_sleep, @current_proc, @current_args, @do_loop]
+ end
+
+ def running?
+ @running
+ end
+
+ def loop_rest
+ @do_loop
+ end
+
+ def loop_rest=(rest)
+ @do_loop = rest
+ end
+
+ def set_procs(interval, loop_exec, *procs)
+ if !interval == 'idle' \
+ && !interval.kind_of?(Integer) && !interval.kind_of?(Proc)
+ fail format("%s need to be Integer or Proc", interval.inspect)
+ end
+ @sleep_time = interval
+
+ @loop_proc = []
+ procs.each{|e|
+ if e.kind_of? Proc
+ @loop_proc.push([e])
+ else
+ @loop_proc.push(e)
+ end
+ }
+ @proc_max = @loop_proc.size
+ @current_pos = 0
+
+ @do_loop = 0
+ if loop_exec
+ if loop_exec.kind_of?(Integer) && loop_exec < 0
+ @loop_exec = -1
+ elsif loop_exec == nil || loop_exec == false || loop_exec == 0
+ @loop_exec = 1
+ else
+ if not loop_exec.kind_of?(Integer)
+ fail format("%s need to be Integer", loop_exec.inspect)
+ end
+ @loop_exec = loop_exec
+ end
+ @do_loop = @loop_exec
+ end
+
+ self
+ end
+
+ def add_procs(*procs)
+ procs.each{|e|
+ if e.kind_of? Proc
+ @loop_proc.push([e])
+ else
+ @loop_proc.push(e)
+ end
+ }
+ @proc_max = @loop_proc.size
+
+ self
+ end
+
+ def set_start_proc(sleep, init_proc, *init_args)
+ if !sleep == 'idle' && !sleep.kind_of?(Integer)
+ fail format("%s need to be Integer", sleep.inspect)
+ end
+ @init_sleep = sleep
+ @init_proc = init_proc
+ @init_args = init_args
+ self
+ end
+
+ def start(*init_args)
+ return nil if @running
+
+ Tk_CBTBL[@id] = self
+ @do_loop = @loop_exec
+ @current_pos = 0
+
+ argc = init_args.size
+ if argc > 0
+ sleep = init_args.shift
+ if !sleep == 'idle' && !sleep.kind_of?(Integer)
+ fail format("%s need to be Integer", sleep.inspect)
+ end
+ @init_sleep = sleep
+ end
+ @init_proc = init_args.shift if argc > 1
+ @init_args = init_args if argc > 0
+
+ @current_sleep = @init_sleep
+ @running = true
+ if @init_proc
+ if not @init_proc.kind_of? Proc
+ fail format("%s need to be Proc", @init_proc.inspect)
+ end
+ @current_proc = @init_proc
+ set_callback(sleep, @init_args)
+ @set_next = false if @in_callback
+ else
+ set_next_callback(*@init_args)
+ end
+
+ self
+ end
+
+ def restart(*restart_args)
+ cancel if @running
+ if restart_args == []
+ start(@init_sleep, @init_proc, *@init_args)
+ else
+ start(*restart_args)
+ end
+ end
+
+ def cancel
+ @running = false
+ tk_call 'after', 'cancel', @after_id if @after_id
+ @after_id = nil
+ Tk_CBTBL[@id] = nil ;# for GC
+ self
+ end
+ alias stop cancel
+
+ def continue(wait=nil)
+ sleep, cmd = @current_script
+ return nil if cmd == nil || @running == true
+ if wait
+ if not wait.kind_of? Integer
+ fail format("%s need to be Integer", wait.inspect)
+ end
+ sleep = wait
+ end
+ Tk_CBTBL[@id] = self
+ @running = true
+ @after_id = tk_call('after', sleep, cmd)
+ self
+ end
+
+ def skip
+ return nil if @running == false
+ cancel
+ Tk_CBTBL[@id] = self
+ @running = true
+ set_next_callback(@current_args)
+ self
+ end
+
+ def info
+ if @after_id
+ inf = tk_split_list(tk_call('after', 'info', @after_id))
+ [Tk_CBTBL[inf[0][1]], inf[1]]
+ else
+ nil
+ end
+ end
+end