Class: TkTimer

Class | TkTimer
In: | tk/lib/tk/timer.rb
Parent: | Object

### Methods

add_procs callback cancel cancel_on_exception= cancel_on_exception? cb_call continue current_status delete_at delete_procs do_callback eventloop_tkwait eventloop_wait get_procs info info loop_rest loop_rest= new reset restart running? set_callback set_interval set_next_callback set_procs set_start_proc skip start start stop thread_tkwait thread_wait tkwait wait

### Included Modules

TkCore

### Constants

TkCommandNames | = | ['after'.freeze].freeze
Tk_CBID | = | ['a'.freeze, '00000'.taint].freeze
Tk_CBTBL | = | {}.taint
DEFAULT_IGNORE_EXCEPTIONS | = | [ NameError, RuntimeError ].freeze

### External Aliases

current_sleep | -> | current_interval

### Attributes

after_id | [R] |
after_script | [R] |
current_args | [R] |
current_proc | [R] |
current_sleep | [R] |
loop_exec | [RW] |
return_value | [R] |

### Public Class methods

callback(obj_id)

[Source]

    # File tk/lib/tk/timer.rb, line 35
      def self.callback(obj_id)
        ex_obj = Tk_CBTBL[obj_id]
        return "" if ex_obj == nil; # canceled
        ex_obj.cb_call
      end

info(obj = nil)

[Source]

    # File tk/lib/tk/timer.rb, line 41
      def self.info(obj = nil)
        if obj
          if obj.kind_of?(TkTimer)
            if obj.after_id
              inf = tk_split_list(tk_call_without_enc('after','info',obj.after_id))
              [Tk_CBTBL[inf[0][1]], inf[1]]
            else
              nil
            end
          else
            fail ArgumentError, "TkTimer object is expected"
          end
        else
          tk_call_without_enc('after', 'info').split(' ').collect!{|id|
            ret = Tk_CBTBL.find{|key,val| val.after_id == id}
            (ret == nil)? id: ret[1]
          }
        end
      end

new(*args, &b)

[Source]

    # File tk/lib/tk/timer.rb, line 141
      def initialize(*args, &b)
        # @id = Tk_CBID.join('')
        @id = Tk_CBID.join(TkCore::INTERP._ip_id_)
        Tk_CBID[1].succ!

        @wait_var = TkVariable.new(0)

        @cb_cmd = TkCore::INTERP.get_cb_entry(self.method(:do_callback))

        @set_next = true

        @init_sleep = 0
        @init_proc = nil
        @init_args = []

        @current_script = []
        @current_proc = nil
        @current_args = nil
        @return_value = 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

        @cancel_on_exception = DEFAULT_IGNORE_EXCEPTIONS
        # Unless @cancel_on_exception, Ruby/Tk shows an error dialog box when
        # an excepsion is raised on TkTimer callback procedure.
        # If @cancel_on_exception is an array of exception classes and the raised
        # exception is included in the array, Ruby/Tk cancels executing TkTimer
        # callback procedures silently (TkTimer#cancel is called and no dialog is
        # shown).

        if b
          case args.size
          when 0
            add_procs(b)
          when 1
            args << -1 << b
          else
            args << b
          end
        end

        set_procs(*args) if args != []

        @running = false
        @in_callback = false
      end

start(*args, &b)

class methods

[Source]

    # File tk/lib/tk/timer.rb, line 31
      def self.start(*args, &b)
        self.new(*args, &b).start
      end

### Public Instance methods

add_procs(*procs)

[Source]

    # File tk/lib/tk/timer.rb, line 296
      def add_procs(*procs)
        procs.each{|e|
          # if e.kind_of?(Proc)
          if TkComm._callback_entry?(e)
            @loop_proc.push([e])
          else
            @loop_proc.push(e)
          end
        }
        @proc_max = @loop_proc.size

        self
      end

cancel()

[Source]

    # File tk/lib/tk/timer.rb, line 422
      def cancel
        @running = false
        @wait_var.value = 0
        tk_call 'after', 'cancel', @after_id if @after_id
        @after_id = nil

        Tk_CBTBL.delete(@id) ;# for GC
        self
      end

cancel_on_exception=(mode)

[Source]

    # File tk/lib/tk/timer.rb, line 224
      def cancel_on_exception=(mode)
        if mode.kind_of?(Array)
          @cancel_on_exception = mode
        elsif mode
          @cancel_on_exception = DEFAULT_IGNORE_EXCEPTIONS
        else
          @cancel_on_exception = false
        end
        #self
      end

cancel_on_exception?()

[Source]

    # File tk/lib/tk/timer.rb, line 220
      def cancel_on_exception?
        @cancel_on_exception
      end

cb_call()

[Source]

    # File tk/lib/tk/timer.rb, line 207
      def cb_call
        @cb_cmd.call
      end

continue(wait=nil)

[Source]

    # File tk/lib/tk/timer.rb, line 433
      def continue(wait=nil)
        fail RuntimeError, "is already running" if @running
        return restart() if @current_script.empty?
        sleep, cmd = @current_script
        fail RuntimeError, "no procedure to continue" unless cmd
        if wait
          unless wait.kind_of?(Integer)
            fail ArgumentError, "expect Integer for 1st argument"
          end
          sleep = wait
        end
        Tk_CBTBL[@id] = self
        @running = true
        @after_id = tk_call_without_enc('after', sleep, cmd)
        self
      end

current_status()

[Source]

    # File tk/lib/tk/timer.rb, line 215
      def current_status
        [@running, @current_sleep, @current_proc, @current_args,
          @do_loop, @cancel_on_exception]
      end

delete_at(n)

[Source]

    # File tk/lib/tk/timer.rb, line 326
      def delete_at(n)
        @loop_proc.delete_at(n)
        @proc_max = @loop_proc.size
        cancel if @proc_max == 0
        self
      end

delete_procs(*procs)

[Source]

    # File tk/lib/tk/timer.rb, line 310
      def delete_procs(*procs)
        procs.each{|e|
          # if e.kind_of?(Proc)
          if TkComm._callback_entry?(e)
            @loop_proc.delete([e])
          else
            @loop_proc.delete(e)
          end
        }
        @proc_max = @loop_proc.size

        cancel if @proc_max == 0

        self
      end

do_callback()

instance methods

[Source]

    # File tk/lib/tk/timer.rb, line 65
      def do_callback
        @in_callback = true
        @after_id = nil
        begin
          @return_value = @current_proc.call(self)
        rescue SystemExit
          exit(0)
        rescue Interrupt
          exit!(1)
        rescue Exception => e
          if @cancel_on_exception &&
              @cancel_on_exception.find{|exc| e.kind_of?(exc)}
            cancel
            @return_value = e
            @in_callback = false
            return e
          else
            fail e
          end
        end
        if @set_next
          set_next_callback(@current_args)
        else
          @set_next = true
        end
        @in_callback = false
        @return_value
      end

eventloop_tkwait()

[Source]

    # File tk/lib/tk/timer.rb, line 497
      def eventloop_tkwait
        wait(false, true)
      end

eventloop_wait(check_root = false)

[Source]

    # File tk/lib/tk/timer.rb, line 488
      def eventloop_wait(check_root = false)
        wait(false, check_root)
      end

get_procs()

[Source]

    # File tk/lib/tk/timer.rb, line 211
      def get_procs
        [@init_sleep, @init_proc, @init_args, @sleep_time, @loop_exec, @loop_proc]
      end

info()

[Source]

    # File tk/lib/tk/timer.rb, line 459
      def info
        if @after_id
          inf = tk_split_list(tk_call_without_enc('after', 'info', @after_id))
          [Tk_CBTBL[inf[0][1]], inf[1]]
        else
          nil
        end
      end

loop_rest()

[Source]

    # File tk/lib/tk/timer.rb, line 239
      def loop_rest
        @do_loop
      end

loop_rest=(rest)

[Source]

    # File tk/lib/tk/timer.rb, line 243
      def loop_rest=(rest)
        @do_loop = rest
        #self
      end

reset(*reset_args)

[Source]

    # File tk/lib/tk/timer.rb, line 395
      def reset(*reset_args)
        restart() if @running

        if @init_proc
          @return_value = @init_proc.call(self)
        else
          @return_value = nil
        end

        @current_pos   = 0
        @current_args  = @init_args
        @current_script = []

        @set_next = false if @in_callback

        self
      end

restart(*restart_args, &b)

[Source]

    # File tk/lib/tk/timer.rb, line 413
      def restart(*restart_args, &b)
        cancel if @running
        if restart_args == [] && !b
          start(@init_sleep, @init_proc, *@init_args)
        else
          start(*restart_args, &b)
        end
      end

running?()

[Source]

    # File tk/lib/tk/timer.rb, line 235
      def running?
        @running
      end

set_callback(sleep, args=nil)

[Source]

    # File tk/lib/tk/timer.rb, line 94
      def set_callback(sleep, args=nil)
        if TkCore::INTERP.deleted?
          self.cancel
          return self
        end
        @after_script = "rb_after #{@id}"
        @after_id = tk_call_without_enc('after', sleep, @after_script)
        @current_args = args
        @current_script = [sleep, @after_script]
        self
      end

set_interval(interval)

[Source]

    # File tk/lib/tk/timer.rb, line 248
      def set_interval(interval)
        #if interval != 'idle' && interval != :idle      #  && !interval.kind_of?(Integer) && !interval.kind_of?(Proc)
        if interval != 'idle' && interval != :idle \
          && !interval.kind_of?(Integer) && !TkComm._callback_entry?(interval)
          fail ArgumentError, "expect Integer or Proc"
        end
        @sleep_time = interval
      end

set_next_callback(args)

[Source]

    # File tk/lib/tk/timer.rb, line 106
      def set_next_callback(args)
        if @running == false || @proc_max == 0 || @do_loop == 0
          Tk_CBTBL.delete(@id) ;# for GC
          @running = false
          @wait_var.value = 0
          return
        end
        if @current_pos >= @proc_max
          if @do_loop < 0 || (@do_loop -= 1) > 0
            @current_pos = 0
          else
            Tk_CBTBL.delete(@id) ;# for GC
            @running = false
            @wait_var.value = 0
            return
          end
        end

        @current_args = args

        # if @sleep_time.kind_of?(Proc)
        if TkComm._callback_entry?(@sleep_time)
          sleep = @sleep_time.call(self)
        else
          sleep = @sleep_time
        end
        @current_sleep = sleep

        cmd, *cmd_args = @loop_proc[@current_pos]
        @current_pos += 1
        @current_proc = cmd

        set_callback(sleep, cmd_args)
      end

set_procs(interval, loop_exec, *procs)

[Source]

    # File tk/lib/tk/timer.rb, line 258
      def set_procs(interval, loop_exec, *procs)
        #if interval != 'idle' && interval != :idle      #   && !interval.kind_of?(Integer) && !interval.kind_of?(Proc)
        if interval != 'idle' && interval != :idle \
          && !interval.kind_of?(Integer) && !TkComm._callback_entry?(interval)
          fail ArgumentError, "expect Integer or Proc for 1st argument"
        end
        @sleep_time = interval

        @loop_proc = []
        procs.each{|e|
          # if e.kind_of?(Proc)
          if TkComm._callback_entry?(e)
            @loop_proc.push([e])
          else
            @loop_proc.push(e)
          end
        }
        @proc_max = @loop_proc.size
        @current_pos = 0

        if loop_exec.kind_of?(Integer) && loop_exec < 0
          @loop_exec = -1
        elsif loop_exec == true
          @loop_exec = -1
        elsif loop_exec == nil || loop_exec == false || loop_exec == 0
          @loop_exec = 0
        else
          if not loop_exec.kind_of?(Integer)
            fail ArgumentError, "expect Integer for 2nd argument"
          end
          @loop_exec = loop_exec
        end
        @do_loop = @loop_exec

        self
      end

set_start_proc(sleep=nil, init_proc=nil, *init_args, &b)

[Source]

    # File tk/lib/tk/timer.rb, line 333
      def set_start_proc(sleep=nil, init_proc=nil, *init_args, &b)
        # set parameters for 'restart'
        sleep = @init_sleep unless sleep

        if sleep != 'idle' && sleep != :idle && !sleep.kind_of?(Integer)
          fail ArgumentError, "expect Integer or 'idle' for 1st argument"
        end

        @init_sleep = sleep
        @init_proc = init_proc
        @init_args = init_args

        @init_proc = b if !@init_proc && b
        @init_proc = proc{|*args| } if @init_sleep > 0 && !@init_proc

        self
      end

skip()

[Source]

    # File tk/lib/tk/timer.rb, line 450
      def skip
        fail RuntimeError, "is not running now" unless @running
        cancel
        Tk_CBTBL[@id] = self
        @running = true
        set_next_callback(@current_args)
        self
      end

start(*init_args, &b)

[Source]

    # File tk/lib/tk/timer.rb, line 351
      def start(*init_args, &b)
        return nil if @running

        Tk_CBTBL[@id] = self
        @do_loop = @loop_exec
        @current_pos = 0
        @return_value = nil
        @after_id = nil

        @init_sleep = 0
        @init_proc  = nil
        @init_args  = nil

        argc = init_args.size
        if argc > 0
          sleep = init_args.shift
          if sleep != 'idle' && sleep != :idle && !sleep.kind_of?(Integer)
            fail ArgumentError, "expect Integer or 'idle' for 1st argument"
          end
          @init_sleep = sleep
        end
        @init_proc = init_args.shift if argc > 1
        @init_args = init_args if argc > 2

        @init_proc = b if !@init_proc && b
        @init_proc = proc{|*args| } if @init_sleep > 0 && !@init_proc

        @current_sleep = @init_sleep
        @running = true
        if @init_proc
          # if not @init_proc.kind_of?(Proc)
          if !TkComm._callback_entry?(@init_proc)
            fail ArgumentError, "Argument '#{@init_proc}' need to be Proc"
          end
          @current_proc = @init_proc
          set_callback(@init_sleep, @init_args)
          @set_next = false if @in_callback
        else
          set_next_callback(@init_args)
        end

        self
      end

stop()

Alias for cancel

thread_tkwait()

[Source]

    # File tk/lib/tk/timer.rb, line 500
      def thread_tkwait
        wait(true, true)
      end

thread_wait(check_root = false)

[Source]

    # File tk/lib/tk/timer.rb, line 491
      def thread_wait(check_root = false)
        wait(true, check_root)
      end

tkwait(on_thread = true)

[Source]

    # File tk/lib/tk/timer.rb, line 494
      def tkwait(on_thread = true)
        wait(on_thread, true)
      end

wait(on_thread = true, check_root = false)

[Source]

    # File tk/lib/tk/timer.rb, line 468
      def wait(on_thread = true, check_root = false)
        if $SAFE >= 4
          fail SecurityError, "can't wait timer at $SAFE >= 4"
        end

        unless @running
          if @return_value.kind_of?(Exception)
            fail @return_value
          else
            return @return_value
          end
        end

        @wait_var.wait(on_thread, check_root)
        if @return_value.kind_of?(Exception)
          fail @return_value
        else
          @return_value
        end
      end

[Validate]