class TkTimer - tk-0.2.0 Documentation

# class TkTimer

### Constants

DEFAULT_IGNORE_EXCEPTIONS
TkCommandNames
Tk_CBID
Tk_CBTBL

### Attributes

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

### Public Class Methods

callback(obj_id) click to toggle source

    # File lib/tk/timer.rb, line 40
    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) click to toggle source

    # File lib/tk/timer.rb, line 46
    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) click to toggle source

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

      @wait_var = TkVariable.new(0)

      @at_end_proc = nil

      @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 exception 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) click to toggle source

class methods

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

### Public Instance Methods

add_procs(*procs) click to toggle source

    # File lib/tk/timer.rb, line 313
    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

at_end(*arg, &b) click to toggle source

    # File lib/tk/timer.rb, line 486
    def at_end(*arg, &b)
      if arg.empty?
        if b
          @at_end_proc = b
        else
          # no proc
          return @at_end_proc
        end
      else
        fail ArgumentError, "wrong number of arguments" if arg.length != 1 || b
        @at_end_proc = arg[0]
      end
      self
    end

cancel() click to toggle source

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

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

Also aliased as: stop
cancel_on_exception=(mode) click to toggle source

    # File lib/tk/timer.rb, line 241
    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?() click to toggle source

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

cb_call() click to toggle source

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

continue(wait=nil) click to toggle source

    # File lib/tk/timer.rb, line 451
    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() click to toggle source

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

delete_at(n) click to toggle source

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

delete_procs(*procs) click to toggle source

    # File lib/tk/timer.rb, line 327
    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() click to toggle source

instance methods

    # File lib/tk/timer.rb, line 70
    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() click to toggle source

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

eventloop_wait(check_root = false) click to toggle source

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

get_procs() click to toggle source

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

info() click to toggle source

    # File lib/tk/timer.rb, line 477
    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() click to toggle source

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

loop_rest=(rest) click to toggle source

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

mutex() click to toggle source

    # File lib/tk/timer.rb, line 17
    def mutex; @mutex; end

reset(*reset_args) click to toggle source

    # File lib/tk/timer.rb, line 412
    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) click to toggle source

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

running?() click to toggle source

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

set_callback(sleep, args=nil) click to toggle source

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

set_interval(interval) click to toggle source

    # File lib/tk/timer.rb, line 265
    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) click to toggle source

    # File lib/tk/timer.rb, line 111
    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
        __at_end__
        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
          __at_end__
          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) click to toggle source

    # File lib/tk/timer.rb, line 275
    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) click to toggle source

    # File lib/tk/timer.rb, line 350
    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() click to toggle source

    # File lib/tk/timer.rb, line 468
    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) click to toggle source

    # File lib/tk/timer.rb, line 368
    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() click to toggle source

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

thread_wait(check_root = false) click to toggle source

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

tkwait(on_thread = true) click to toggle source

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

wait(on_thread = true, check_root = false) click to toggle source

    # File lib/tk/timer.rb, line 501
    def wait(on_thread = true, check_root = false)
      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

### Private Instance Methods

__at_end__() click to toggle source

    # File lib/tk/timer.rb, line 218
    def __at_end__
      @at_end_proc.call(self) if @at_end_proc
      @wait_var.value = 0  # for wait
    end