mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* ext/tk/tcltklib.c: enforce thread-check and exception-handling to
avoid SEGV trouble. * ext/tk/tkutil/tkutil.c; fix a bug on converting a SJIS string array to a Tcl's list string. * ext/tk/tcltklib.c: wrap Tcl's original "namespace" command to protect from namespace crash. * ext/tk/lib/multi-tk.rb: enforce exception-handling. * ext/tk/lib/multi-tk.rb: catch IRB_EXIT to work on irb. * ext/tk/lib/tk.rb: ditto. * ext/tk/tcltklib.c: add TclTkLib.mainloop_thread? * ext/tk/lib/multi-tk.rb: (bug fix) callback returns a value. * ext/tk/lib/tk/canvas.rb (delete): bug fix when multiple arguments. * ext/tk/lib/clock.rb: fix 'no method error'. * ext/tk/lib/clock.rb (self.clicks): accept a Symbol argument. * ext/tk/lib/variable.rb: be able to set default_value_type; :numeric, :bool, :string, :symbol, :list, :numlist or nil (default; same to :string). If set a type, TkVariable#value returns a value of the type. * ext/tk/lib/tkextlib/tclx/tclx.rb: add Tk::TclX.signal to warn the risk of using TclX extension's 'signal' command. * ext/tk/sample/irbtk.rb: irb with Ruby/Tk. * ext/tk/sample/demos-*/anilabel.rb: bug fix on 'show code' * ext/tk/sample/demos-*/aniwave.rb: new Ruby/Tk animation demo. * ext/tk/sample/demos-*/pendulum.rb: ditto. * ext/tk/sample/demos-*/goldberg.rb: ditto. * ext/tk/sample/demos-*/widget: add entries of animation demos. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8046 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
16771ba23c
commit
3124427ccb
24 changed files with 7685 additions and 696 deletions
47
ChangeLog
47
ChangeLog
|
@ -1,3 +1,50 @@
|
|||
Wed Mar 2 16:03:08 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
|
||||
|
||||
* ext/tk/tcltklib.c: enforce thread-check and exception-handling to
|
||||
avoid SEGV trouble.
|
||||
|
||||
* ext/tk/tkutil/tkutil.c; fix a bug on converting a SJIS string array
|
||||
to a Tcl's list string.
|
||||
|
||||
* ext/tk/tcltklib.c: wrap Tcl's original "namespace" command to
|
||||
protect from namespace crash.
|
||||
|
||||
* ext/tk/lib/multi-tk.rb: enforce exception-handling.
|
||||
|
||||
* ext/tk/lib/multi-tk.rb: catch IRB_EXIT to work on irb.
|
||||
|
||||
* ext/tk/lib/tk.rb: ditto.
|
||||
|
||||
* ext/tk/tcltklib.c: add TclTkLib.mainloop_thread?
|
||||
|
||||
* ext/tk/lib/multi-tk.rb: (bug fix) callback returns a value.
|
||||
|
||||
* ext/tk/lib/tk/canvas.rb (delete): bug fix when multiple arguments.
|
||||
|
||||
* ext/tk/lib/clock.rb: fix 'no method error'.
|
||||
|
||||
* ext/tk/lib/clock.rb (self.clicks): accept a Symbol argument.
|
||||
|
||||
* ext/tk/lib/variable.rb: be able to set default_value_type; :numeric,
|
||||
:bool, :string, :symbol, :list, :numlist or nil (default; same to
|
||||
:string). If set a type, TkVariable#value returns a value of the
|
||||
type.
|
||||
|
||||
* ext/tk/lib/tkextlib/tclx/tclx.rb: add Tk::TclX.signal to warn the
|
||||
risk of using TclX extension's 'signal' command.
|
||||
|
||||
* ext/tk/sample/irbtk.rb: irb with Ruby/Tk.
|
||||
|
||||
* ext/tk/sample/demos-*/anilabel.rb: bug fix on 'show code'
|
||||
|
||||
* ext/tk/sample/demos-*/aniwave.rb: new Ruby/Tk animation demo.
|
||||
|
||||
* ext/tk/sample/demos-*/pendulum.rb: ditto.
|
||||
|
||||
* ext/tk/sample/demos-*/goldberg.rb: ditto.
|
||||
|
||||
* ext/tk/sample/demos-*/widget: add entries of animation demos.
|
||||
|
||||
Wed Mar 2 12:21:18 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* eval.c (rb_eval): [EXPERIMENTAL] NODE_LAMBDA implemented.
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2005-02-20 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
|
||||
|
||||
* ext/tk/lib/tclx/tclx.rb: warning TclX's 'signal' command.
|
||||
|
||||
2005-01-25 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
|
||||
|
||||
* ext/tk/lib/tkextlib/blt/component.rb: bug fix. cannot accept
|
||||
|
|
|
@ -126,12 +126,22 @@ module TclTklib
|
|||
: defined as 0.
|
||||
|
||||
[module methods]
|
||||
mainloop(check_root = true)
|
||||
mainloop(check_root = true)
|
||||
: Starts the eventloop. If 'check_root' is true, this method
|
||||
: doesn't return when a root widget exists.
|
||||
: If 'check_root' is false, doen't return by the other
|
||||
: reasons than exceptions.
|
||||
|
||||
mainloop_thread?
|
||||
: Returns whether the current thread executes the eventloop.
|
||||
: If true, the eventloop is working on the current thread.
|
||||
: If no eventloop is working, this method returns nil.
|
||||
: And if the other thread executes the eventloop, returns false.
|
||||
:
|
||||
: *** ATTENTION ***
|
||||
: When this methods returns false, it is dangerous to call a Tk
|
||||
: interpreter directly.
|
||||
|
||||
mainloop_watchdog(check_root = true)
|
||||
: On the normal eventloop, some kinds of callback operations
|
||||
: cause deadlock. To avoid some of such deadlocks, this
|
||||
|
|
|
@ -230,6 +230,15 @@ require "tcltklib"
|
|||
: WINDOW 以外のイベントは発生しうるため ).終了には,外部
|
||||
: からの働き掛け ( スレッドを活用するなど ) が必要.
|
||||
|
||||
mainloop_thread?
|
||||
: カレントスレッドがイベントループを実行しているスレッド
|
||||
: かどうかを返す.
|
||||
: イベントループを実行しているスレッドであれば true を,
|
||||
: どのスレッドでもイベントループが実行されていない場合は
|
||||
: nil を,他のスレッドでイベントループが実行されている場
|
||||
: 合は false を返す.
|
||||
: false の際に Tk インタープリタを直接呼ぶのは危険である.
|
||||
|
||||
mainloop_watchdog(check_root = true)
|
||||
: 通常のイベントループでは,イベント処理の内容によっては
|
||||
: デッドロックを引き起こす可能性がある (例えばイベントに
|
||||
|
@ -377,7 +386,7 @@ require "tcltklib"
|
|||
: 失敗した場合は RuntimeError の例外を発生する.
|
||||
|
||||
safe?
|
||||
: Tcl/Tk インタープリタを safe インタープリタであるかを調べる.
|
||||
: Tcl/Tk インタープリタが safe インタープリタであるかを調べる.
|
||||
: safe インタープリタであれば true を返す.
|
||||
|
||||
allow_ruby_exit?
|
||||
|
|
|
@ -77,17 +77,22 @@ class MultiTkIp
|
|||
cmd.inspect
|
||||
end
|
||||
def call(*args)
|
||||
begin
|
||||
unless @ip.deleted?
|
||||
@ip.cb_eval(@cmd, *args)
|
||||
end
|
||||
rescue TkCallbackBreak, TkCallbackContinue => e
|
||||
fail e
|
||||
rescue Exception => e
|
||||
if @ip.safe?
|
||||
# ignore
|
||||
else
|
||||
unless @ip.deleted?
|
||||
current = Thread.current
|
||||
backup_ip = current['callback_ip']
|
||||
current['callback_ip'] = @ip
|
||||
begin
|
||||
@ip.cb_eval(@cmd, *args)
|
||||
rescue TkCallbackBreak, TkCallbackContinue => e
|
||||
fail e
|
||||
rescue Exception => e
|
||||
if @ip.safe?
|
||||
nil # ignore
|
||||
else
|
||||
fail e
|
||||
end
|
||||
ensure
|
||||
current['callback_ip'] = backup_ip
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -105,19 +110,23 @@ class MultiTkIp
|
|||
|
||||
def _check_and_return(thread, exception, wait=0)
|
||||
unless thread
|
||||
unless exception.kind_of?(MultiTkIp_OK) || safe?
|
||||
unless exception.kind_of?(MultiTkIp_OK)
|
||||
msg = "#{exception.class}: #{exception.message}"
|
||||
|
||||
if @interp.deleted?
|
||||
warn("Warning (#{self}): " + msg)
|
||||
return nil
|
||||
end
|
||||
|
||||
if safe?
|
||||
warn("Warning (#{self}): " + msg) if $DEBUG
|
||||
return nil
|
||||
end
|
||||
|
||||
begin
|
||||
if @interp.deleted?
|
||||
warn('Warning: ' + msg)
|
||||
elsif @interp._eval_without_enc('info command bgerror').size != 0
|
||||
@interp._eval(@interp._merge_tklist('bgerror', msg))
|
||||
else
|
||||
warn('Warning: ' + msg)
|
||||
end
|
||||
@interp._eval_without_enc(@interp._merge_tklist('bgerror', msg))
|
||||
rescue Exception => e
|
||||
warn('Warning: ' + msg)
|
||||
warn('Warning: ' + e.message)
|
||||
warn("Warning (#{self}): " + msg)
|
||||
end
|
||||
end
|
||||
return nil
|
||||
|
@ -230,8 +239,18 @@ class MultiTkIp
|
|||
def _receiver_eval_proc_core(safe_level, thread, cmd, *args)
|
||||
begin
|
||||
#ret = proc{$SAFE = safe_level; cmd.call(*args)}.call
|
||||
ret = cmd.call(safe_level, *args)
|
||||
|
||||
#ret = cmd.call(safe_level, *args)
|
||||
normal_ret = false
|
||||
ret = catch(:IRB_EXIT) do # IRB hack
|
||||
retval = cmd.call(safe_level, *args)
|
||||
normal_ret = true
|
||||
retval
|
||||
end
|
||||
unless normal_ret
|
||||
# catch IRB_EXIT
|
||||
exit(ret)
|
||||
end
|
||||
ret
|
||||
rescue SystemExit => e
|
||||
# delete IP
|
||||
unless @interp.deleted?
|
||||
|
@ -297,7 +316,8 @@ class MultiTkIp
|
|||
_check_and_return(thread, MultiTkIp_OK.new(nil))
|
||||
end
|
||||
|
||||
if master? && !safe? && allow_ruby_exit?
|
||||
# if master? && !safe? && allow_ruby_exit?
|
||||
if !@interp.deleted? && master? && !safe? && allow_ruby_exit?
|
||||
=begin
|
||||
ObjectSpace.each_object(TclTkIp){|obj|
|
||||
obj.delete unless obj.deleted?
|
||||
|
@ -380,6 +400,16 @@ class MultiTkIp
|
|||
|
||||
rescue Exception => e
|
||||
# raise exception
|
||||
begin
|
||||
bt = _toUTF8(e.backtrace.join("\n"))
|
||||
bt.instance_variable_set(:@encoding, 'utf-8')
|
||||
rescue Exception
|
||||
bt = e.backtrace.join("\n")
|
||||
end
|
||||
begin
|
||||
@interp._set_global_var('errorInfo', bt)
|
||||
rescue Exception
|
||||
end
|
||||
_check_and_return(thread, e)
|
||||
|
||||
else
|
||||
|
@ -411,7 +441,8 @@ class MultiTkIp
|
|||
def _receiver_mainloop(check_root)
|
||||
Thread.new{
|
||||
while !@interp.deleted?
|
||||
break if @interp._invoke_without_enc('info', 'command', '.').size == 0
|
||||
inf = @interp._invoke_without_enc('info', 'command', '.')
|
||||
break if !inf.kind_of?(String) || inf != '.'
|
||||
sleep 0.5
|
||||
end
|
||||
}
|
||||
|
@ -742,8 +773,8 @@ class MultiTkIp
|
|||
# create toplevel widget
|
||||
begin
|
||||
top = TkToplevel.new(toplevel_keys)
|
||||
rescue NameError
|
||||
fail unless @interp.safe?
|
||||
rescue NameError => e
|
||||
fail e unless @interp.safe?
|
||||
fail SecurityError, "unable create toplevel on the safe interpreter"
|
||||
end
|
||||
msg = "Untrusted Ruby/Tk applet (#{slave_name})"
|
||||
|
@ -870,7 +901,11 @@ class MultiTkIp
|
|||
fail SecurityError, "cannot create a master-ip at level #{$SAFE}"
|
||||
end
|
||||
|
||||
if !master.master? && master.safe?
|
||||
if master.deleted? && safeip == nil
|
||||
fail RuntimeError, "cannot create a slave of a deleted interpreter"
|
||||
end
|
||||
|
||||
if !master.deleted? && !master.master? && master.safe?
|
||||
fail SecurityError, "safe-slave-ip cannot create a new interpreter"
|
||||
end
|
||||
|
||||
|
@ -964,15 +999,20 @@ class MultiTkIp
|
|||
undef :instance_eval
|
||||
end
|
||||
|
||||
# dummy call for initialization
|
||||
self.eval_proc{ Tk.tk_call('set', 'tcl_patchLevel') }
|
||||
|
||||
self.freeze # defend against modification
|
||||
end
|
||||
|
||||
######################################
|
||||
|
||||
def _default_delete_hook(slave)
|
||||
if @slave_ip_top[slave].kind_of?(String)
|
||||
@slave_ip_tbl.delete(slave)
|
||||
top = @slave_ip_top.delete(slave)
|
||||
if top.kind_of?(String)
|
||||
# call default hook of safetk.tcl (ignore exceptions)
|
||||
if @slave_ip_top[slave] == ''
|
||||
if top == ''
|
||||
begin
|
||||
@interp._eval("::safe::disallowTk #{slave}")
|
||||
rescue
|
||||
|
@ -980,20 +1020,19 @@ class MultiTkIp
|
|||
end
|
||||
else # toplevel path
|
||||
begin
|
||||
@interp._eval("::safe::tkDelete {} #{@slave_ip_top[slave]} #{slave}")
|
||||
@interp._eval("::safe::tkDelete {} #{top} #{slave}")
|
||||
rescue
|
||||
warn("Waring: fail to call '::safe::tkDelete'") if $DEBUG
|
||||
begin
|
||||
@interp._eval("destroy #{@slave_ip_top[slave]}")
|
||||
@interp._eval("destroy #{top}")
|
||||
rescue
|
||||
warn("Waring: fail to destroy toplevel") if $DEBUG
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@slave_ip_tbl.delete(slave)
|
||||
@slave_ip_top.delete(slave)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
@ -1007,10 +1046,14 @@ class MultiTkIp
|
|||
end
|
||||
|
||||
def self.__getip
|
||||
if Thread.current.group == ThreadGroup::Default
|
||||
current = Thread.current
|
||||
if TclTkLib.mainloop_thread? != false && current['callback_ip']
|
||||
return current['callback_ip']
|
||||
end
|
||||
if current.group == ThreadGroup::Default
|
||||
@@DEFAULT_MASTER
|
||||
else
|
||||
ip = @@IP_TABLE[Thread.current.group]
|
||||
ip = @@IP_TABLE[current.group]
|
||||
unless ip
|
||||
fail SecurityError,
|
||||
"cannot call Tk methods on #{Thread.current.inspect}"
|
||||
|
@ -1093,9 +1136,15 @@ class MultiTkIp
|
|||
def inspect
|
||||
s = self.to_s.chop!
|
||||
if master?
|
||||
s << ':master'
|
||||
if @interp.deleted?
|
||||
s << ':deleted-master'
|
||||
else
|
||||
s << ':master'
|
||||
end
|
||||
else
|
||||
if @interp.safe?
|
||||
if @interp.deleted?
|
||||
s << ':deleted-slave'
|
||||
elsif @interp.safe?
|
||||
s << ':safe-slave'
|
||||
else
|
||||
s << ':trusted-slave'
|
||||
|
@ -1281,11 +1330,13 @@ class MultiTkIp
|
|||
#self.eval_callback{ TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *args)) }
|
||||
#ret = self.eval_callback{ TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *args)) }
|
||||
ret = self.eval_callback(*args){|safe, *params|
|
||||
$SAFE=safe; TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *params))
|
||||
$SAFE=safe
|
||||
TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *params))
|
||||
}
|
||||
if ret.kind_of?(Exception)
|
||||
raise ret
|
||||
raise ret
|
||||
end
|
||||
ret
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1300,10 +1351,11 @@ class MultiTkIp
|
|||
end
|
||||
|
||||
# on IP thread
|
||||
if (@cmd_receiver == Thread.current)
|
||||
if @cmd_receiver == Thread.current ||
|
||||
(!req_val && TclTkLib.mainloop_thread? != false) # callback
|
||||
begin
|
||||
ret = cmd.call(*args)
|
||||
rescue SystemExit
|
||||
rescue SystemExit => e
|
||||
# exit IP
|
||||
warn("Warning: "+ $! + " on " + self.inspect) if $DEBUG
|
||||
begin
|
||||
|
@ -1318,6 +1370,18 @@ class MultiTkIp
|
|||
((e.message.length > 0)? ' "' + e.message + '"': '') +
|
||||
" on " + self.inspect)
|
||||
end
|
||||
=begin
|
||||
begin
|
||||
bt = _toUTF8(e.backtrace.join("\n"))
|
||||
bt.instance_variable_set(:@encoding, 'utf-8')
|
||||
rescue Exception
|
||||
bt = e.backtrace.join("\n")
|
||||
end
|
||||
begin
|
||||
@interp._set_global_var('errorInfo', bt)
|
||||
rescue Exception
|
||||
end
|
||||
=end
|
||||
ret = e
|
||||
end
|
||||
return ret
|
||||
|
@ -1353,7 +1417,7 @@ class MultiTkIp
|
|||
self._eval_without_enc('exit')
|
||||
rescue Exception
|
||||
end
|
||||
if !safe? && allow_ruby_exit?
|
||||
if !self.deleted? && !safe? && allow_ruby_exit?
|
||||
self.delete
|
||||
fail e
|
||||
else
|
||||
|
@ -1380,11 +1444,34 @@ class MultiTkIp
|
|||
end
|
||||
end
|
||||
=end
|
||||
=begin
|
||||
def eval_callback(*args)
|
||||
if block_given?
|
||||
eval_proc_core(false, Proc.new, *args)
|
||||
# eval_proc_core(Thread.current, Proc.new, *args)
|
||||
else
|
||||
cmd = args.shift
|
||||
eval_proc_core(false, *args)
|
||||
# eval_proc_core(Thread.current, *args)
|
||||
end
|
||||
end
|
||||
=end
|
||||
def eval_callback(*args)
|
||||
if block_given?
|
||||
cmd = Proc.new
|
||||
else
|
||||
cmd = args.shift
|
||||
end
|
||||
if TclTkLib.mainloop_thread? != false
|
||||
args.unshift(safe_level)
|
||||
end
|
||||
current = Thread.current
|
||||
backup_ip = current['callback_ip']
|
||||
current['callback_ip'] = self
|
||||
begin
|
||||
eval_proc_core(false, cmd, *args)
|
||||
ensure
|
||||
current['callback_ip'] = backup_ip
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1399,7 +1486,7 @@ class MultiTkIp
|
|||
=end
|
||||
def eval_proc(*args)
|
||||
# The scope of the eval-block of 'eval_proc' method is different from
|
||||
# the enternal. If you want to pass local values to the eval-block,
|
||||
# the external. If you want to pass local values to the eval-block,
|
||||
# use arguments of eval_proc method. They are passed to block-arguments.
|
||||
if block_given?
|
||||
cmd = Proc.new
|
||||
|
@ -1408,11 +1495,24 @@ class MultiTkIp
|
|||
fail ArgumentError, "A Proc or Method object is expected for 1st argument"
|
||||
end
|
||||
end
|
||||
eval_proc_core(true,
|
||||
proc{|safe, *params|
|
||||
$SAFE=safe; Thread.new(*params, &cmd).value
|
||||
},
|
||||
*args)
|
||||
if TclTkLib.mainloop_thread? == true
|
||||
# call from eventloop
|
||||
current = Thread.current
|
||||
backup_ip = current['callback_ip']
|
||||
current['callback_ip'] = self
|
||||
begin
|
||||
eval_proc_core(false, cmd, safe_level, *args)
|
||||
ensure
|
||||
current['callback_ip'] = backup_ip
|
||||
end
|
||||
else
|
||||
eval_proc_core(true,
|
||||
proc{|safe, *params|
|
||||
$SAFE=safe
|
||||
Thread.new(*params, &cmd).value
|
||||
},
|
||||
*args)
|
||||
end
|
||||
end
|
||||
alias call eval_proc
|
||||
|
||||
|
@ -1739,7 +1839,7 @@ end
|
|||
|
||||
# depend on TclTkIp
|
||||
class MultiTkIp
|
||||
def mainloop(check_root = true, restart_on_dead = false)
|
||||
def mainloop(check_root = true, restart_on_dead = true)
|
||||
#return self if self.slave?
|
||||
#return self if self != @@DEFAULT_MASTER
|
||||
if self != @@DEFAULT_MASTER
|
||||
|
@ -1752,7 +1852,11 @@ class MultiTkIp
|
|||
rescue MultiTkIp_OK => ret
|
||||
# return value
|
||||
@wait_on_mainloop[1] = false
|
||||
return ret.value.value
|
||||
if ret.value.kind_of?(Thread)
|
||||
return ret.value.value
|
||||
else
|
||||
return ret.value
|
||||
end
|
||||
rescue SystemExit
|
||||
# exit IP
|
||||
warn("Warning: " + $! + " on " + self.inspect) if $DEBUG
|
||||
|
@ -1762,7 +1866,7 @@ class MultiTkIp
|
|||
rescue Exception
|
||||
end
|
||||
self.delete
|
||||
rescue Exception => e
|
||||
rescue StandardError => e
|
||||
if $DEBUG
|
||||
warn("Warning: " + e.class.inspect +
|
||||
((e.message.length > 0)? ' "' + e.message + '"': '') +
|
||||
|
@ -1779,31 +1883,59 @@ class MultiTkIp
|
|||
|
||||
unless restart_on_dead
|
||||
@wait_on_mainloop[1] = true
|
||||
=begin
|
||||
begin
|
||||
@interp.mainloop(check_root)
|
||||
rescue StandardError => e
|
||||
if $DEBUG
|
||||
warn("Warning: " + e.class.inspect +
|
||||
((e.message.length > 0)? ' "' + e.message + '"': '') +
|
||||
" on " + self.inspect)
|
||||
end
|
||||
end
|
||||
=end
|
||||
@interp.mainloop(check_root)
|
||||
@wait_on_mainloop[1] = false
|
||||
else
|
||||
begin
|
||||
loop do
|
||||
@wait_on_mainloop[1] = true
|
||||
loop do
|
||||
break unless self.alive?
|
||||
if check_root
|
||||
begin
|
||||
break if TclTkLib.num_of_mainwindows == 0
|
||||
rescue Exception
|
||||
break
|
||||
break unless self.alive?
|
||||
if check_root
|
||||
begin
|
||||
break if TclTkLib.num_of_mainwindows == 0
|
||||
rescue StandardError
|
||||
break
|
||||
end
|
||||
end
|
||||
break if @interp.deleted?
|
||||
begin
|
||||
@interp.mainloop(check_root)
|
||||
rescue StandardError => e
|
||||
if TclTkLib.mainloop_abort_on_exception != nil
|
||||
#STDERR.print("Warning: Tk mainloop receives ", $!.class.inspect,
|
||||
# " exception (ignore) : ", $!.message, "\n");
|
||||
if $DEBUG
|
||||
warn("Warning: Tk mainloop receives " << e.class.inspect <<
|
||||
" exception (ignore) : " << e.message);
|
||||
end
|
||||
end
|
||||
@interp.mainloop(check_root)
|
||||
#raise e
|
||||
rescue Exception => e
|
||||
=begin
|
||||
if TclTkLib.mainloop_abort_on_exception != nil
|
||||
#STDERR.print("Warning: Tk mainloop receives ", $!.class.inspect,
|
||||
# " exception (ignore) : ", $!.message, "\n");
|
||||
if $DEBUG
|
||||
warn("Warning: Tk mainloop receives " << e.class.inspect <<
|
||||
" exception (ignore) : " << e.message);
|
||||
end
|
||||
end
|
||||
=end
|
||||
raise e
|
||||
ensure
|
||||
@wait_on_mainloop[1] = false
|
||||
Thread.pass # avoid eventloop conflict
|
||||
end
|
||||
#rescue StandardError
|
||||
rescue Exception
|
||||
if TclTkLib.mainloop_abort_on_exception != nil
|
||||
STDERR.print("Warning: Tk mainloop receives ", $!.class.inspect,
|
||||
" exception (ignore) : ", $!.message, "\n");
|
||||
end
|
||||
retry
|
||||
ensure
|
||||
@wait_on_mainloop[1] = false
|
||||
end
|
||||
end
|
||||
self
|
||||
|
@ -1875,18 +2007,17 @@ class MultiTkIp
|
|||
@interp._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}")
|
||||
rescue Exception
|
||||
end
|
||||
=begin
|
||||
|
||||
begin
|
||||
@interp._invoke('destroy', '.') unless @interp.deleted?
|
||||
rescue Exception
|
||||
end
|
||||
=end
|
||||
|
||||
if @safe_base && !@interp.deleted?
|
||||
# do 'exit' to call the delete_hook procedure
|
||||
@interp._eval_without_enc('exit')
|
||||
else
|
||||
@interp.delete unless @interp.deleted?
|
||||
end
|
||||
@interp.delete
|
||||
self
|
||||
end
|
||||
|
||||
|
|
|
@ -565,6 +565,15 @@ end
|
|||
module_function :bool, :number, :num_or_str, :string
|
||||
module_function :list, :simplelist, :window, :image_obj, :procedure
|
||||
|
||||
def subst(str, *opts)
|
||||
# opts := :nobackslashes | :nocommands | novariables
|
||||
tk_call('subst',
|
||||
*(opts.collect{|opt|
|
||||
opt = opt.to_s
|
||||
(opt[0] == ?-)? opt: '-' << opt
|
||||
} << str))
|
||||
end
|
||||
|
||||
def _toUTF8(str, encoding = nil)
|
||||
TkCore::INTERP._toUTF8(str, encoding)
|
||||
end
|
||||
|
@ -1110,13 +1119,14 @@ module TkCore
|
|||
INTERP._invoke_without_enc('bind', 'all', "<#{WIDGET_DESTROY_HOOK}>",
|
||||
install_cmd(proc{|path|
|
||||
unless TkCore::INTERP.deleted?
|
||||
if (widget = TkCore::INTERP.tk_windows[path])
|
||||
if widget.respond_to?(:__destroy_hook__)
|
||||
begin
|
||||
begin
|
||||
if (widget=TkCore::INTERP.tk_windows[path])
|
||||
if widget.respond_to?(:__destroy_hook__)
|
||||
widget.__destroy_hook__
|
||||
rescue Exception
|
||||
end
|
||||
end
|
||||
rescue Exception=>e
|
||||
p e if $DEBUG
|
||||
end
|
||||
end
|
||||
}) << ' %W')
|
||||
|
@ -1175,11 +1185,24 @@ module TkCore
|
|||
|
||||
def TkCore.callback(*arg)
|
||||
begin
|
||||
TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg)
|
||||
rescue SystemExit
|
||||
exit(0)
|
||||
rescue Interrupt
|
||||
exit!(1)
|
||||
if TkCore::INTERP.tk_cmd_tbl.kind_of?(Hash)
|
||||
#TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg)
|
||||
normal_ret = false
|
||||
ret = catch(:IRB_EXIT) do # IRB hack
|
||||
retval = TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg)
|
||||
normal_ret = true
|
||||
retval
|
||||
end
|
||||
unless normal_ret
|
||||
# catch IRB_EXIT
|
||||
exit(ret)
|
||||
end
|
||||
ret
|
||||
end
|
||||
rescue SystemExit=>e
|
||||
exit(e.status)
|
||||
rescue Interrupt=>e
|
||||
fail(e)
|
||||
rescue Exception => e
|
||||
begin
|
||||
msg = _toUTF8(e.class.inspect) + ': ' +
|
||||
|
@ -1194,6 +1217,8 @@ module TkCore
|
|||
e.backtrace.join("\n") +
|
||||
"\n---< backtrace of Tk side >-------"
|
||||
end
|
||||
# TkCore::INTERP._set_global_var('errorInfo', msg)
|
||||
# fail(e)
|
||||
fail(e, msg)
|
||||
end
|
||||
end
|
||||
|
@ -1383,6 +1408,22 @@ module TkCore
|
|||
TclTkLib.mainloop(check_root)
|
||||
end
|
||||
|
||||
def mainloop_thread?
|
||||
# true : current thread is mainloop
|
||||
# nil : there is no mainloop
|
||||
# false : mainloop is running on the other thread
|
||||
# ( At then, it is dangerous to call Tk interpreter directly. )
|
||||
TclTkLib.mainloop_thread?
|
||||
end
|
||||
|
||||
def mainloop_exist?
|
||||
TclTkLib.mainloop_thread? != nil
|
||||
end
|
||||
|
||||
def is_mainloop?
|
||||
TclTkLib.mainloop_thread? == true
|
||||
end
|
||||
|
||||
def mainloop_watchdog(check_root = true)
|
||||
# watchdog restarts mainloop when mainloop is dead
|
||||
TclTkLib.mainloop_watchdog(check_root)
|
||||
|
@ -1738,13 +1779,34 @@ module Tk
|
|||
end
|
||||
|
||||
def Tk.pack(*args)
|
||||
#TkPack.configure(*args)
|
||||
TkPack(*args)
|
||||
TkPack.configure(*args)
|
||||
end
|
||||
def Tk.pack_forget(*args)
|
||||
TkPack.forget(*args)
|
||||
end
|
||||
def Tk.unpack(*args)
|
||||
TkPack.forget(*args)
|
||||
end
|
||||
|
||||
def Tk.grid(*args)
|
||||
TkGrid.configure(*args)
|
||||
end
|
||||
def Tk.grid_forget(*args)
|
||||
TkGrid.forget(*args)
|
||||
end
|
||||
def Tk.ungrid(*args)
|
||||
TkGrid.forget(*args)
|
||||
end
|
||||
|
||||
def Tk.place(*args)
|
||||
TkPlace.configure(*args)
|
||||
end
|
||||
def Tk.place_forget(*args)
|
||||
TkPlace.forget(*args)
|
||||
end
|
||||
def Tk.unplace(*args)
|
||||
TkPlace.forget(*args)
|
||||
end
|
||||
|
||||
def Tk.update(idle=nil)
|
||||
if idle
|
||||
|
@ -3541,7 +3603,7 @@ class TkWindow<TkObject
|
|||
self
|
||||
end
|
||||
|
||||
def grid_forget
|
||||
def grid_forget
|
||||
#tk_call('grid', 'forget', epath)
|
||||
TkGrid.forget(self)
|
||||
self
|
||||
|
@ -3940,7 +4002,7 @@ end
|
|||
#Tk.freeze
|
||||
|
||||
module Tk
|
||||
RELEASE_DATE = '2005-01-28'.freeze
|
||||
RELEASE_DATE = '2005-03-02'.freeze
|
||||
|
||||
autoload :AUTO_PATH, 'tk/variable'
|
||||
autoload :TCL_PACKAGE_PATH, 'tk/variable'
|
||||
|
@ -3950,7 +4012,6 @@ module Tk
|
|||
autoload :TCL_PRECISION, 'tk/variable'
|
||||
end
|
||||
|
||||
|
||||
# call setup script for Tk extension libraries (base configuration)
|
||||
begin
|
||||
require 'tkextlib/setup.rb'
|
||||
|
|
|
@ -159,8 +159,10 @@ class TkCanvas<TkWindow
|
|||
|
||||
def delete(*args)
|
||||
if TkcItem::CItemID_TBL[self.path]
|
||||
find('withtag', *args).each{|item|
|
||||
TkcItem::CItemID_TBL[self.path].delete(item.id)
|
||||
args.each{|tag|
|
||||
find('withtag', tag).each{|item|
|
||||
TkcItem::CItemID_TBL[self.path].delete(item.id)
|
||||
}
|
||||
}
|
||||
end
|
||||
tk_send_without_enc('delete', *args.collect{|t| tagid(t)})
|
||||
|
|
|
@ -5,13 +5,17 @@ require 'tk'
|
|||
|
||||
module Tk
|
||||
module Clock
|
||||
include Tk
|
||||
extend TkCore
|
||||
|
||||
def self.add(clk, *args)
|
||||
tk_call_without_enc('clock','add', clk, *args).to_i
|
||||
end
|
||||
|
||||
def self.clicks(ms=nil)
|
||||
ms = ms.to_s if ms.kind_of?(Symbol)
|
||||
case ms
|
||||
when nil
|
||||
when nil, ''
|
||||
tk_call_without_enc('clock','clicks').to_i
|
||||
when /^mic/
|
||||
tk_call_without_enc('clock','clicks','-microseconds').to_i
|
||||
|
|
|
@ -420,6 +420,7 @@ class TkTimer
|
|||
@wait_var.value = 0
|
||||
tk_call 'after', 'cancel', @after_id if @after_id
|
||||
@after_id = nil
|
||||
|
||||
Tk_CBTBL.delete(@id) ;# for GC
|
||||
self
|
||||
end
|
||||
|
|
|
@ -126,7 +126,81 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL')
|
|||
self
|
||||
end
|
||||
|
||||
def initialize(val="")
|
||||
def default_value_type
|
||||
@type
|
||||
end
|
||||
|
||||
def default_value_type=(type)
|
||||
if type.kind_of?(Class)
|
||||
if type == NilClass
|
||||
@type = nil
|
||||
elsif type == Numeric
|
||||
@type = :numeric
|
||||
elsif type == TrueClass || type == FalseClass
|
||||
@type = :bool
|
||||
elsif type == String
|
||||
@type = :string
|
||||
elsif type == Symbol
|
||||
@type = :symbol
|
||||
elsif type == Array
|
||||
@type = :list
|
||||
else
|
||||
@type = nil
|
||||
end
|
||||
else
|
||||
case(type)
|
||||
when nil
|
||||
@type = nil
|
||||
when :numeric, 'numeric'
|
||||
@type = :numeric
|
||||
when true, false, :bool, 'bool'
|
||||
@type = :bool
|
||||
when :string, 'string'
|
||||
@type = :string
|
||||
when :symbol, 'symbol'
|
||||
@type = :symbol
|
||||
when :list, 'list'
|
||||
@type = :list
|
||||
when :numlist, 'numlist'
|
||||
@type = :numlist
|
||||
else
|
||||
self.default_value_type = type.class
|
||||
end
|
||||
end
|
||||
@type
|
||||
end
|
||||
|
||||
def _to_default_type(val)
|
||||
return val unless @type
|
||||
if val.kind_of?(Hash)
|
||||
val.keys.each{|k| val[k] = _to_default_type(val[k]) }
|
||||
val
|
||||
else
|
||||
begin
|
||||
case(@type)
|
||||
when :numeric
|
||||
number(val)
|
||||
when :bool
|
||||
TkComm
|
||||
when :string
|
||||
val
|
||||
when :symbol
|
||||
val.intern
|
||||
when :list
|
||||
tk_split_simplelist(val)
|
||||
when :numlist
|
||||
tk_split_simplelist(val).collect!{|v| number(v)}
|
||||
else
|
||||
val
|
||||
end
|
||||
rescue
|
||||
val
|
||||
end
|
||||
end
|
||||
end
|
||||
private :_to_default_type
|
||||
|
||||
def initialize(val="", type=nil)
|
||||
# @id = Tk_VARIABLE_ID.join('')
|
||||
@id = Tk_VARIABLE_ID.join(TkCore::INTERP._ip_id_)
|
||||
Tk_VARIABLE_ID[1].succ!
|
||||
|
@ -139,6 +213,8 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL')
|
|||
@trace_elem = nil
|
||||
@trace_opts = nil
|
||||
|
||||
self.default_value_type = type
|
||||
|
||||
begin
|
||||
INTERP._unset_global_var(@id)
|
||||
rescue
|
||||
|
@ -242,13 +318,25 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL')
|
|||
def is_hash?
|
||||
#ITNERP._eval("global #{@id}; array exist #{@id}") == '1'
|
||||
INTERP._invoke_without_enc('global', @id)
|
||||
INTERP._invoke_without_enc('array', 'exist', @id) == '1'
|
||||
# INTERP._invoke_without_enc('array', 'exist', @id) == '1'
|
||||
TkComm.bool(INTERP._invoke_without_enc('array', 'exist', @id))
|
||||
end
|
||||
|
||||
def is_scalar?
|
||||
! is_hash?
|
||||
end
|
||||
|
||||
def exist?(idx = nil)
|
||||
INTERP._invoke_without_enc('global', @id)
|
||||
if idx
|
||||
# array
|
||||
TkComm.bool(tk_call('info', 'exist', "#{@id}")) &&
|
||||
TkComm.bool(tk_call('info', 'exist', "#{@id}(#{idx})"))
|
||||
else
|
||||
TkComm.bool(tk_call('info', 'exist', @id))
|
||||
end
|
||||
end
|
||||
|
||||
def keys
|
||||
if (is_scalar?)
|
||||
fail RuntimeError, 'cannot get keys from a scalar variable'
|
||||
|
@ -258,6 +346,11 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL')
|
|||
tk_split_simplelist(INTERP._fromUTF8(INTERP._invoke_without_enc('array', 'names', @id)))
|
||||
end
|
||||
|
||||
def size
|
||||
INTERP._invoke_without_enc('global', @id)
|
||||
TkComm.number(INTERP._invoke_without_enc('array', 'size', @id))
|
||||
end
|
||||
|
||||
def clear
|
||||
if (is_scalar?)
|
||||
fail RuntimeError, 'cannot clear a scalar variable'
|
||||
|
@ -274,7 +367,6 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL')
|
|||
self
|
||||
end
|
||||
|
||||
|
||||
unless const_defined?(:USE_TCLs_SET_VARIABLE_FUNCTIONS)
|
||||
USE_TCLs_SET_VARIABLE_FUNCTIONS = true
|
||||
end
|
||||
|
@ -284,10 +376,11 @@ if USE_TCLs_SET_VARIABLE_FUNCTIONS
|
|||
# use Tcl function version of set tkvariable
|
||||
###########################################################################
|
||||
|
||||
def value
|
||||
def _value
|
||||
#if INTERP._eval("global #{@id}; array exist #{@id}") == '1'
|
||||
INTERP._invoke_without_enc('global', @id)
|
||||
if INTERP._invoke('array', 'exist', @id) == '1'
|
||||
# if INTERP._invoke('array', 'exist', @id) == '1'
|
||||
if TkComm.bool(INTERP._invoke('array', 'exist', @id))
|
||||
#Hash[*tk_split_simplelist(INTERP._eval("global #{@id}; array get #{@id}"))]
|
||||
Hash[*tk_split_simplelist(INTERP._invoke('array', 'get', @id))]
|
||||
else
|
||||
|
@ -306,6 +399,7 @@ if USE_TCLs_SET_VARIABLE_FUNCTIONS
|
|||
}
|
||||
self.value
|
||||
elsif val.kind_of?(Array)
|
||||
=begin
|
||||
INTERP._set_global_var(@id, '')
|
||||
val.each{|v|
|
||||
#INTERP._set_variable(@id, _toUTF8(_get_eval_string(v)),
|
||||
|
@ -316,6 +410,8 @@ if USE_TCLs_SET_VARIABLE_FUNCTIONS
|
|||
TclTkLib::VarAccessFlag::LIST_ELEMENT)
|
||||
}
|
||||
self.value
|
||||
=end
|
||||
_fromUTF8(INTERP._set_global_var(@id, array2tk_list(val)))
|
||||
else
|
||||
#_fromUTF8(INTERP._set_global_var(@id, _toUTF8(_get_eval_string(val))))
|
||||
_fromUTF8(INTERP._set_global_var(@id, _get_eval_string(val, true)))
|
||||
|
@ -325,7 +421,8 @@ if USE_TCLs_SET_VARIABLE_FUNCTIONS
|
|||
def [](*idxs)
|
||||
index = idxs.collect{|idx| _get_eval_string(idx, true)}.join(',')
|
||||
begin
|
||||
_fromUTF8(INTERP._get_global_var2(@id, index))
|
||||
# _fromUTF8(INTERP._get_global_var2(@id, index))
|
||||
_to_default_type(_fromUTF8(INTERP._get_global_var2(@id, index)))
|
||||
rescue => e
|
||||
case @def_default
|
||||
when :proc
|
||||
|
@ -365,7 +462,7 @@ else
|
|||
# use Ruby script version of set tkvariable (traditional methods)
|
||||
###########################################################################
|
||||
|
||||
def value
|
||||
def _value
|
||||
begin
|
||||
INTERP._eval(Kernel.format('global %s; set %s', @id, @id))
|
||||
#INTERP._eval(Kernel.format('set %s', @id))
|
||||
|
@ -436,7 +533,8 @@ else
|
|||
def [](*idxs)
|
||||
index = idxs.collect{|idx| _get_eval_string(idx)}.join(',')
|
||||
begin
|
||||
INTERP._eval(Kernel.format('global %s; set %s(%s)', @id, @id, index))
|
||||
# INTERP._eval(Kernel.format('global %s; set %s(%s)', @id, @id, index))
|
||||
_to_default_type(INTERP._eval(Kernel.format('global %s; set %s(%s)', @id, @id, index)))
|
||||
rescue => e
|
||||
case @def_default
|
||||
when :proc
|
||||
|
@ -483,8 +581,19 @@ else
|
|||
|
||||
end
|
||||
|
||||
protected :_value
|
||||
|
||||
def value
|
||||
_to_default_type(_value)
|
||||
end
|
||||
|
||||
def value_type=(val)
|
||||
self.default_value_type = val
|
||||
self.value=(val)
|
||||
end
|
||||
|
||||
def numeric
|
||||
number(value)
|
||||
number(_value)
|
||||
end
|
||||
def numeric=(val)
|
||||
case val
|
||||
|
@ -497,17 +606,20 @@ end
|
|||
end
|
||||
val
|
||||
end
|
||||
def numeric_type=(val)
|
||||
@type = :numeric
|
||||
self.numeric=(val)
|
||||
end
|
||||
|
||||
def bool
|
||||
# see Tcl_GetBoolean man-page
|
||||
case value.downcase
|
||||
case _value.downcase
|
||||
when '0', 'false', 'no', 'off'
|
||||
false
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
def bool=(val)
|
||||
if ! val
|
||||
self.value = '0'
|
||||
|
@ -520,30 +632,48 @@ end
|
|||
end
|
||||
end
|
||||
end
|
||||
def bool_type=(val)
|
||||
@type = :bool
|
||||
self.bool=(val)
|
||||
end
|
||||
|
||||
def to_i
|
||||
number(value).to_i
|
||||
number(_value).to_i
|
||||
end
|
||||
|
||||
def to_f
|
||||
number(value).to_f
|
||||
number(_value).to_f
|
||||
end
|
||||
|
||||
def to_s
|
||||
#string(value).to_s
|
||||
value
|
||||
_value
|
||||
end
|
||||
alias string= value=
|
||||
def string_type=(val)
|
||||
@type = :string
|
||||
self.value=(val)
|
||||
end
|
||||
|
||||
def to_sym
|
||||
value.intern
|
||||
_value.intern
|
||||
end
|
||||
alias symbol= value=
|
||||
def symbol_type=(val)
|
||||
@type = :symbol
|
||||
self.value=(val)
|
||||
end
|
||||
|
||||
def list
|
||||
#tk_split_list(value)
|
||||
tk_split_simplelist(value)
|
||||
tk_split_simplelist(_value)
|
||||
end
|
||||
alias to_a list
|
||||
|
||||
def numlist
|
||||
list.collect!{|val| number(val)}
|
||||
end
|
||||
|
||||
def list=(val)
|
||||
case val
|
||||
when Array
|
||||
|
@ -555,6 +685,39 @@ end
|
|||
end
|
||||
val
|
||||
end
|
||||
alias numlist= list=
|
||||
|
||||
def list_type=(val)
|
||||
@type = :list
|
||||
self.list=(val)
|
||||
end
|
||||
def numlist_type=(val)
|
||||
@type = :numlist
|
||||
self.numlist=(val)
|
||||
end
|
||||
|
||||
def lappend(*elems)
|
||||
tk_call('lappend', @id, *elems)
|
||||
self
|
||||
end
|
||||
|
||||
def lindex(idx)
|
||||
tk_call('lindex', self._value, idx)
|
||||
end
|
||||
alias lget lindex
|
||||
|
||||
def lget_i(idx)
|
||||
number(lget(idx)).to_i
|
||||
end
|
||||
|
||||
def lget_f(idx)
|
||||
number(lget(idx)).to_f
|
||||
end
|
||||
|
||||
def lset(idx, val)
|
||||
tk_call('lset', @id, idx, val)
|
||||
self
|
||||
end
|
||||
|
||||
def inspect
|
||||
#Kernel.format "#<TkVariable: %s>", @id
|
||||
|
@ -564,7 +727,7 @@ end
|
|||
def coerce(other)
|
||||
case other
|
||||
when TkVariable
|
||||
[other.value, self.value]
|
||||
[other._value, self._value]
|
||||
when String
|
||||
[other, self.to_s]
|
||||
when Symbol
|
||||
|
@ -576,7 +739,7 @@ end
|
|||
when Array
|
||||
[other, self.to_a]
|
||||
else
|
||||
[other, self.value]
|
||||
[other, self._value]
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -599,12 +762,12 @@ end
|
|||
when Array
|
||||
self.to_a + other
|
||||
when String
|
||||
self.value + other
|
||||
self._value + other
|
||||
else
|
||||
begin
|
||||
number(self.value) + other
|
||||
number(self._value) + other
|
||||
rescue
|
||||
self.value + other.to_s
|
||||
self._value + other.to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -612,37 +775,40 @@ end
|
|||
if other.kind_of?(Array)
|
||||
self.to_a - other
|
||||
else
|
||||
number(self.value) - other
|
||||
number(self._value) - other
|
||||
end
|
||||
end
|
||||
def *(other)
|
||||
begin
|
||||
number(self.value) * other
|
||||
rescue
|
||||
self.value * other
|
||||
end
|
||||
num_or_str(self._value) * other.to_i
|
||||
#begin
|
||||
# number(self._value) * other
|
||||
#rescue
|
||||
# self._value * other
|
||||
#end
|
||||
end
|
||||
def /(other)
|
||||
number(self.value) / other
|
||||
number(self._value) / other
|
||||
end
|
||||
def %(other)
|
||||
begin
|
||||
number(self.value) % other
|
||||
rescue
|
||||
self.value % other
|
||||
end
|
||||
num_or_str(self._value) % other.to_i
|
||||
#begin
|
||||
# number(self._value) % other
|
||||
#rescue
|
||||
# self._value % other
|
||||
#end
|
||||
end
|
||||
def **(other)
|
||||
number(self.value) ** other
|
||||
number(self._value) ** other
|
||||
end
|
||||
def =~(other)
|
||||
self.value =~ other
|
||||
self._value =~ other
|
||||
end
|
||||
|
||||
def ==(other)
|
||||
case other
|
||||
when TkVariable
|
||||
self.equal?(other)
|
||||
#self.equal?(other)
|
||||
self._value == other._value
|
||||
when String
|
||||
self.to_s == other
|
||||
when Symbol
|
||||
|
@ -654,7 +820,8 @@ end
|
|||
when Array
|
||||
self.to_a == other
|
||||
when Hash
|
||||
self.value == other
|
||||
# false if self is not an assoc array
|
||||
self._value == other
|
||||
else
|
||||
false
|
||||
end
|
||||
|
@ -673,17 +840,17 @@ end
|
|||
val = other.numeric
|
||||
other = val
|
||||
rescue
|
||||
other = other.value
|
||||
other = other._value
|
||||
end
|
||||
end
|
||||
if other.kind_of?(Numeric)
|
||||
begin
|
||||
return self.numeric <=> other
|
||||
rescue
|
||||
return self.value <=> other.to_s
|
||||
return self._value <=> other.to_s
|
||||
end
|
||||
else
|
||||
return self.value <=> other
|
||||
return self._value <=> other
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -27,6 +27,16 @@ module Tk
|
|||
Tk.tk_call('infox', *args)
|
||||
end
|
||||
|
||||
def self.signal(*args)
|
||||
warn("Warning: Don't recommend to use TclX's 'signal' command. Please use Ruby's 'Signal.trap' method")
|
||||
Tk.tk_call('signal', *args)
|
||||
end
|
||||
|
||||
def self.signal_restart(*args)
|
||||
warn("Warning: Don't recommend to use TclX's 'signal' command. Please use Ruby's 'Signal.trap' method")
|
||||
Tk.tk_call('signal', '-restart', *args)
|
||||
end
|
||||
|
||||
##############################
|
||||
|
||||
class XPG3_MsgCat
|
||||
|
|
|
@ -37,7 +37,7 @@ TkFrame.new($anilabel_demo) {|frame|
|
|||
|
||||
TkButton.new(frame) {
|
||||
text 'See Code'
|
||||
command proc{showCode 'label'}
|
||||
command proc{showCode 'anilabel'}
|
||||
}.pack('side'=>'left', 'expand'=>'yes')
|
||||
|
||||
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
|
||||
|
|
115
ext/tk/sample/demos-en/aniwave.rb
Normal file
115
ext/tk/sample/demos-en/aniwave.rb
Normal file
|
@ -0,0 +1,115 @@
|
|||
#
|
||||
# animated wave demo (called by 'widget')
|
||||
#
|
||||
# based on Tcl/Tk8.5a2 widget demos
|
||||
|
||||
# destroy toplevel widget for this demo script
|
||||
if defined?($aniwave_demo) && $aniwave_demo
|
||||
$aniwave_demo.destroy
|
||||
$aniwave_demo = nil
|
||||
end
|
||||
|
||||
# create toplevel widget
|
||||
$aniwave_demo = TkToplevel.new {|w|
|
||||
title("Animated Wave Demonstration")
|
||||
iconname("aniwave")
|
||||
positionWindow(w)
|
||||
}
|
||||
|
||||
# create label
|
||||
msg = TkLabel.new($aniwave_demo) {
|
||||
font $font
|
||||
wraplength '4i'
|
||||
justify 'left'
|
||||
text 'This demonstration contains a canvas widget with a line item inside it. The animation routines work by adjusting the coordinates list of the line.'
|
||||
}
|
||||
msg.pack('side'=>'top')
|
||||
|
||||
# create frame
|
||||
TkFrame.new($aniwave_demo) {|frame|
|
||||
TkButton.new(frame) {
|
||||
text 'Dismiss'
|
||||
command proc{
|
||||
tmppath = $aniwave_demo
|
||||
$aniwave_demo = nil
|
||||
tmppath.destroy
|
||||
}
|
||||
}.pack('side'=>'left', 'expand'=>'yes')
|
||||
|
||||
TkButton.new(frame) {
|
||||
text 'See Code'
|
||||
command proc{showCode 'aniwave'}
|
||||
}.pack('side'=>'left', 'expand'=>'yes')
|
||||
|
||||
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
|
||||
|
||||
# animated wave
|
||||
class AnimatedWaveDemo
|
||||
def initialize(frame, dir=:left)
|
||||
@direction = dir
|
||||
|
||||
# create canvas widget
|
||||
@c = TkCanvas.new(frame, :width=>300, :height=>200,
|
||||
:background=>'black')
|
||||
@c.pack(:padx=>10, :pady=>10, :expand=>true)
|
||||
|
||||
# Creates a coordinates list of a wave.
|
||||
@waveCoords = []
|
||||
@backupCoords = []
|
||||
n = 0
|
||||
(-10..300).step(5){|n| @waveCoords << [n, 100]; @backupCoords << [n, 100] }
|
||||
@waveCoords << [n, 0]; @backupCoords << [n, 0]
|
||||
@waveCoords << [n+5, 200]; @backupCoords << [n+5, 200]
|
||||
@coordsLen = @waveCoords.length
|
||||
|
||||
# Create a smoothed line and arrange for its coordinates to be the
|
||||
# contents of the variable waveCoords.
|
||||
@line = TkcLine.new(@c, @waveCoords,
|
||||
:width=>1, :fill=>'green', :smooth=>true)
|
||||
|
||||
# Main animation "loop".
|
||||
# Theoretically 100 frames-per-second (==10ms between frames)
|
||||
@timer = TkTimer.new(10){ basicMotion; reverser }
|
||||
|
||||
# Arrange for the animation loop to stop when the canvas is deleted
|
||||
@c.bindtags_unshift(TkBindTag.new('Destroy'){ @timer.stop })
|
||||
end
|
||||
|
||||
# Basic motion handler. Given what direction the wave is travelling
|
||||
# in, it advances the y coordinates in the coordinate-list one step in
|
||||
# that direction.
|
||||
def basicMotion
|
||||
@backupCoords, @waveCoords = @waveCoords, @backupCoords
|
||||
(0...@coordsLen).each{|idx|
|
||||
if @direction == :left
|
||||
@waveCoords[idx][1] = @backupCoords[(idx+1 == @coordsLen)? 0: idx+1][1]
|
||||
else
|
||||
@waveCoords[idx][1] = @backupCoords[(idx == 0)? -1: idx-1][1]
|
||||
end
|
||||
}
|
||||
@line.coords(@waveCoords)
|
||||
end
|
||||
|
||||
# Oscillation handler. This detects whether to reverse the direction
|
||||
# of the wave by checking to see if the peak of the wave has moved off
|
||||
# the screen (whose size we know already.)
|
||||
def reverser
|
||||
if @waveCoords[0][1] < 10
|
||||
@direction = :right
|
||||
elsif @waveCoords[-1][1] < 10
|
||||
@direction = :left
|
||||
end
|
||||
end
|
||||
|
||||
# animation control
|
||||
def move
|
||||
@timer.start
|
||||
end
|
||||
|
||||
def stop
|
||||
@timer.stop
|
||||
end
|
||||
end
|
||||
|
||||
# Start the animation processing
|
||||
AnimatedWaveDemo.new($aniwave_demo, :left).move
|
1968
ext/tk/sample/demos-en/goldberg.rb
Normal file
1968
ext/tk/sample/demos-en/goldberg.rb
Normal file
File diff suppressed because it is too large
Load diff
223
ext/tk/sample/demos-en/pendulum.rb
Normal file
223
ext/tk/sample/demos-en/pendulum.rb
Normal file
|
@ -0,0 +1,223 @@
|
|||
#
|
||||
# This demonstration illustrates how Tcl/Tk can be used to construct
|
||||
# simulations of physical systems.
|
||||
# (called by 'widget')
|
||||
#
|
||||
# based on Tcl/Tk8.5a2 widget demos
|
||||
|
||||
# destroy toplevel widget for this demo script
|
||||
if defined?($pendulum_demo) && $pendulum_demo
|
||||
$pendulum_demo.destroy
|
||||
$pendulum_demo = nil
|
||||
end
|
||||
|
||||
# create toplevel widget
|
||||
$pendulum_demo = TkToplevel.new {|w|
|
||||
title("Pendulum Animation Demonstration")
|
||||
iconname("pendulum")
|
||||
positionWindow(w)
|
||||
}
|
||||
|
||||
# create label
|
||||
msg = TkLabel.new($pendulum_demo) {
|
||||
font $font
|
||||
wraplength '4i'
|
||||
justify 'left'
|
||||
text 'This demonstration shows how Ruby/Tk can be used to carry out animations that are linked to simulations of physical systems. In the left canvas is a graphical representation of the physical system itself, a simple pendulum, and in the right canvas is a graph of the phase space of the system, which is a plot of the angle (relative to the vertical) against the angular velocity. The pendulum bob may be repositioned by clicking and dragging anywhere on the left canvas.'
|
||||
}
|
||||
msg.pack('side'=>'top')
|
||||
|
||||
# create frame
|
||||
TkFrame.new($pendulum_demo) {|frame|
|
||||
TkButton.new(frame) {
|
||||
text 'Dismiss'
|
||||
command proc{
|
||||
tmppath = $pendulum_demo
|
||||
$pendulum_demo = nil
|
||||
tmppath.destroy
|
||||
}
|
||||
}.pack('side'=>'left', 'expand'=>'yes')
|
||||
|
||||
TkButton.new(frame) {
|
||||
text 'See Code'
|
||||
command proc{showCode 'pendulum'}
|
||||
}.pack('side'=>'left', 'expand'=>'yes')
|
||||
|
||||
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
|
||||
|
||||
# animated wave
|
||||
class PendulumAnimationDemo
|
||||
def initialize(frame)
|
||||
# Create some structural widgets
|
||||
pane = TkPanedWindow.new(frame).pack(:fill=>:both, :expand=>true)
|
||||
pane.add(@lf1 = TkLabelFrame.new(pane, :text=>'Pendulum Simulation'))
|
||||
pane.add(@lf2 = TkLabelFrame.new(pane, :text=>'Phase Space'))
|
||||
|
||||
# Create the canvas containing the graphical representation of the
|
||||
# simulated system.
|
||||
@c = TkCanvas.new(@lf1, :width=>320, :height=>200, :background=>'white',
|
||||
:borderwidth=>2, :relief=>:sunken)
|
||||
TkcText.new(@c, 5, 5, :anchor=>:nw,
|
||||
:text=>'Click to Adjust Bob Start Position')
|
||||
# Coordinates of these items don't matter; they will be set properly below
|
||||
@plate = TkcLine.new(@c, 0, 25, 320, 25, :width=>2, :fill=>'grey50')
|
||||
@rod = TkcLine.new(@c, 1, 1, 1, 1, :width=>3, :fill=>'black')
|
||||
@bob = TkcOval.new(@c, 1, 1, 2, 2,
|
||||
:width=>3, :fill=>'yellow', :outline=>'black')
|
||||
TkcOval.new(@c, 155, 20, 165, 30, :fill=>'grey50', :outline=>'')
|
||||
|
||||
# pack
|
||||
@c.pack(:fill=>:both, :expand=>true)
|
||||
|
||||
# Create the canvas containing the phase space graph; this consists of
|
||||
# a line that gets gradually paler as it ages, which is an extremely
|
||||
# effective visual trick.
|
||||
@k = TkCanvas.new(@lf2, :width=>320, :height=>200, :background=>'white',
|
||||
:borderwidth=>2, :relief=>:sunken)
|
||||
@y_axis = TkcLine.new(@k, 160, 200, 160, 0, :fill=>'grey75', :arrow=>:last)
|
||||
@x_axis = TkcLine.new(@k, 0, 100, 320, 100, :fill=>'grey75', :arrow=>:last)
|
||||
|
||||
@graph = {}
|
||||
90.step(0, -10){|i|
|
||||
# Coordinates of these items don't matter;
|
||||
# they will be set properly below
|
||||
@graph[i] = TkcLine.new(@k, 0, 0, 1, 1, :smooth=>true, :fill=>"grey#{i}")
|
||||
}
|
||||
|
||||
# labels
|
||||
@label_theta = TkcText.new(@k, 0, 0, :anchor=>:ne,
|
||||
:text=>'q', :font=>'Symbol 8')
|
||||
@label_dtheta = TkcText.new(@k, 0, 0, :anchor=>:ne,
|
||||
:text=>'dq', :font=>'Symbol 8')
|
||||
|
||||
# pack
|
||||
@k.pack(:fill=>:both, :expand=>true)
|
||||
|
||||
# Initialize some variables
|
||||
@points = []
|
||||
@theta = 45.0
|
||||
@dTheta = 0.0
|
||||
@length = 150
|
||||
|
||||
# init display
|
||||
showPendulum
|
||||
|
||||
# animation loop
|
||||
@timer = TkTimer.new(15){ repeat }
|
||||
|
||||
# binding
|
||||
@c.bindtags_unshift(btag = TkBindTag.new)
|
||||
btag.bind('Destroy'){ @timer.stop }
|
||||
btag.bind('1', proc{|x, y| @timer.stop; showPendulum(x, y)}, '%x %y')
|
||||
btag.bind('B1-Motion', proc{|x, y| showPendulum(x, y)}, '%x %y')
|
||||
btag.bind('ButtonRelease-1',
|
||||
proc{|x, y| showPendulum(x, y); @timer.start }, '%x %y')
|
||||
|
||||
btag.bind('Configure', proc{|w| @plate.coords(0, 25, w, 25)}, '%w')
|
||||
|
||||
@k.bind('Configure', proc{|h, w|
|
||||
@psh = h/2;
|
||||
@psw = w/2
|
||||
@x_axis.coords(2, @psh, w-2, @psh)
|
||||
@y_axis.coords(@psw, h-2, @psw, 2)
|
||||
@label_theta.coords(@psw-4, 6)
|
||||
@label_dtheta.coords(w-6, @psh+4)
|
||||
}, '%h %w')
|
||||
|
||||
# animation start
|
||||
@timer.start(500)
|
||||
end
|
||||
|
||||
# This procedure makes the pendulum appear at the correct place on the
|
||||
# canvas. If the additional arguments x, y are passed instead of computing
|
||||
# the position of the pendulum from the length of the pendulum rod and its
|
||||
# angle, the length and angle are computed in reverse from the given
|
||||
# location (which is taken to be the centre of the pendulum bob.)
|
||||
def showPendulum(x=nil, y=nil)
|
||||
if x && y && (x != 160 || y != 25)
|
||||
@dTheta = 0.0
|
||||
x2 = x - 160
|
||||
y2 = y - 25
|
||||
@length = Math.hypot(x2, y2)
|
||||
@theta = Math.atan2(x2,y2)*180/Math::PI
|
||||
else
|
||||
angle = @theta*Math::PI/180
|
||||
x = 160 + @length*Math.sin(angle)
|
||||
y = 25 + @length*Math.cos(angle)
|
||||
end
|
||||
|
||||
@rod.coords(160, 25, x, y)
|
||||
@bob.coords(x-15, y-15, x+15, y+15)
|
||||
end
|
||||
|
||||
# Update the phase-space graph according to the current angle and the
|
||||
# rate at which the angle is changing (the first derivative with
|
||||
# respect to time.)
|
||||
def showPhase
|
||||
@points << @theta + @psw << -20*@dTheta + @psh
|
||||
if @points.length > 100
|
||||
@points = @points[-100..-1]
|
||||
end
|
||||
(0...100).step(10){|i|
|
||||
first = - i
|
||||
last = 11 - i
|
||||
last = -1 if last >= 0
|
||||
next if first > last
|
||||
lst = @points[first..last]
|
||||
@graph[i].coords(lst) if lst && lst.length >= 4
|
||||
}
|
||||
end
|
||||
|
||||
# This procedure is the "business" part of the simulation that does
|
||||
# simple numerical integration of the formula for a simple rotational
|
||||
# pendulum.
|
||||
def recomputeAngle
|
||||
scaling = 3000.0/@length/@length
|
||||
|
||||
# To estimate the integration accurately, we really need to
|
||||
# compute the end-point of our time-step. But to do *that*, we
|
||||
# need to estimate the integration accurately! So we try this
|
||||
# technique, which is inaccurate, but better than doing it in a
|
||||
# single step. What we really want is bound up in the
|
||||
# differential equation:
|
||||
# .. - sin theta
|
||||
# theta + theta = -----------
|
||||
# length
|
||||
# But my math skills are not good enough to solve this!
|
||||
|
||||
# first estimate
|
||||
firstDDTheta = -Math.sin(@theta * Math::PI/180) * scaling
|
||||
midDTheta = @dTheta + firstDDTheta
|
||||
midTheta = @theta + (@dTheta + midDTheta)/2
|
||||
# second estimate
|
||||
midDDTheta = -Math.sin(midTheta * Math::PI/180) * scaling
|
||||
midDTheta = @dTheta + (firstDDTheta + midDDTheta)/2
|
||||
midTheta = @theta + (@dTheta + midDTheta)/2
|
||||
# Now we do a double-estimate approach for getting the final value
|
||||
# first estimate
|
||||
midDDTheta = -Math.sin(midTheta * Math::PI/180) * scaling
|
||||
lastDTheta = midDTheta + midDDTheta
|
||||
lastTheta = midTheta + (midDTheta+ lastDTheta)/2
|
||||
# second estimate
|
||||
lastDDTheta = -Math.sin(lastTheta * Math::PI/180) * scaling
|
||||
lastDTheta = midDTheta + (midDDTheta + lastDDTheta)/2
|
||||
lastTheta = midTheta + (midDTheta + lastDTheta)/2
|
||||
# Now put the values back in our globals
|
||||
@dTheta = lastDTheta
|
||||
@theta = lastTheta
|
||||
end
|
||||
|
||||
# This method ties together the simulation engine and the graphical
|
||||
# display code that visualizes it.
|
||||
def repeat
|
||||
# Simulate
|
||||
recomputeAngle
|
||||
|
||||
# Update the display
|
||||
showPendulum
|
||||
showPhase
|
||||
end
|
||||
end
|
||||
|
||||
# Start the animation processing
|
||||
PendulumAnimationDemo.new($pendulum_demo)
|
|
@ -392,6 +392,12 @@ txt.insert('end', "\n")
|
|||
txt.insert('end', "Animation\n", tag_title)
|
||||
txt.insert('end', " \n ", tag_demospace)
|
||||
txt.insert('end', "1. Animated labels (if supported)\n", tag_demo, "demo-anilabel")
|
||||
txt.insert('end', " \n ", tag_demospace)
|
||||
txt.insert('end', "2. Animated wave (if supported)\n", tag_demo, "demo-aniwave")
|
||||
txt.insert('end', " \n ", tag_demospace)
|
||||
txt.insert('end', "3. Pendulum simulation (if supported)\n", tag_demo, "demo-pendulum")
|
||||
txt.insert('end', " \n ", tag_demospace)
|
||||
txt.insert('end', "4. A celebration of Rube Goldberg (if supported)\n", tag_demo, "demo-goldberg")
|
||||
|
||||
txt.insert('end', "\n")
|
||||
txt.insert('end', "Miscellaneous\n", tag_title)
|
||||
|
@ -785,7 +791,7 @@ end
|
|||
#
|
||||
def aboutBox
|
||||
Tk.messageBox('icon'=>'info', 'type'=>'ok', 'title'=>'About Widget Demo',
|
||||
'message'=>"Ruby/Tk widget demonstration Ver.1.5.0-en\n\n" +
|
||||
'message'=>"Ruby/Tk widget demonstration Ver.1.5.2-en\n\n" +
|
||||
"based on demos of Tk8.1 -- 8.5 " +
|
||||
"( Copyright:: " +
|
||||
"(c) 1996-1997 Sun Microsystems, Inc. / " +
|
||||
|
|
|
@ -39,7 +39,7 @@ TkFrame.new($anilabel_demo) {|frame|
|
|||
|
||||
TkButton.new(frame) {
|
||||
text 'コード参照'
|
||||
command proc{showCode 'label'}
|
||||
command proc{showCode 'anilabel'}
|
||||
}.pack('side'=>'left', 'expand'=>'yes')
|
||||
|
||||
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
|
||||
|
|
116
ext/tk/sample/demos-jp/aniwave.rb
Normal file
116
ext/tk/sample/demos-jp/aniwave.rb
Normal file
|
@ -0,0 +1,116 @@
|
|||
#
|
||||
# animated wave demo (called by 'widget')
|
||||
#
|
||||
# based on Tcl/Tk8.5a2 widget demos
|
||||
|
||||
# destroy toplevel widget for this demo script
|
||||
if defined?($aniwave_demo) && $aniwave_demo
|
||||
$aniwave_demo.destroy
|
||||
$aniwave_demo = nil
|
||||
end
|
||||
|
||||
# create toplevel widget
|
||||
$aniwave_demo = TkToplevel.new {|w|
|
||||
title("Animated Wave Demonstration")
|
||||
iconname("aniwave")
|
||||
positionWindow(w)
|
||||
}
|
||||
|
||||
# create label
|
||||
msg = TkLabel.new($aniwave_demo) {
|
||||
font $font
|
||||
wraplength '4i'
|
||||
justify 'left'
|
||||
text 'このデモでは、ラインアイテムが一つだけ描かれたキャンバスウィジェットが表示されています。アニメーション処理は、そのラインアイテムの座標値を変更することで実現しています。'
|
||||
}
|
||||
msg.pack('side'=>'top')
|
||||
|
||||
# create frame
|
||||
TkFrame.new($aniwave_demo) {|frame|
|
||||
TkButton.new(frame) {
|
||||
#text '了解'
|
||||
text '閉じる'
|
||||
command proc{
|
||||
tmppath = $aniwave_demo
|
||||
$aniwave_demo = nil
|
||||
tmppath.destroy
|
||||
}
|
||||
}.pack('side'=>'left', 'expand'=>'yes')
|
||||
|
||||
TkButton.new(frame) {
|
||||
text 'コード参照'
|
||||
command proc{showCode 'aniwave'}
|
||||
}.pack('side'=>'left', 'expand'=>'yes')
|
||||
|
||||
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
|
||||
|
||||
# animated wave
|
||||
class AnimatedWaveDemo
|
||||
def initialize(frame, dir=:left)
|
||||
@direction = dir
|
||||
|
||||
# create canvas widget
|
||||
@c = TkCanvas.new(frame, :width=>300, :height=>200,
|
||||
:background=>'black')
|
||||
@c.pack(:padx=>10, :pady=>10, :expand=>true)
|
||||
|
||||
# Creates a coordinates list of a wave.
|
||||
@waveCoords = []
|
||||
@backupCoords = []
|
||||
n = 0
|
||||
(-10..300).step(5){|n| @waveCoords << [n, 100]; @backupCoords << [n, 100] }
|
||||
@waveCoords << [n, 0]; @backupCoords << [n, 0]
|
||||
@waveCoords << [n+5, 200]; @backupCoords << [n+5, 200]
|
||||
@coordsLen = @waveCoords.length
|
||||
|
||||
# Create a smoothed line and arrange for its coordinates to be the
|
||||
# contents of the variable waveCoords.
|
||||
@line = TkcLine.new(@c, @waveCoords,
|
||||
:width=>1, :fill=>'green', :smooth=>true)
|
||||
|
||||
# Main animation "loop".
|
||||
# Theoretically 100 frames-per-second (==10ms between frames)
|
||||
@timer = TkTimer.new(10){ basicMotion; reverser }
|
||||
|
||||
# Arrange for the animation loop to stop when the canvas is deleted
|
||||
@c.bindtags_unshift(TkBindTag.new('Destroy'){ @timer.stop })
|
||||
end
|
||||
|
||||
# Basic motion handler. Given what direction the wave is travelling
|
||||
# in, it advances the y coordinates in the coordinate-list one step in
|
||||
# that direction.
|
||||
def basicMotion
|
||||
@backupCoords, @waveCoords = @waveCoords, @backupCoords
|
||||
(0...@coordsLen).each{|idx|
|
||||
if @direction == :left
|
||||
@waveCoords[idx][1] = @backupCoords[(idx+1 == @coordsLen)? 0: idx+1][1]
|
||||
else
|
||||
@waveCoords[idx][1] = @backupCoords[(idx == 0)? -1: idx-1][1]
|
||||
end
|
||||
}
|
||||
@line.coords(@waveCoords)
|
||||
end
|
||||
|
||||
# Oscillation handler. This detects whether to reverse the direction
|
||||
# of the wave by checking to see if the peak of the wave has moved off
|
||||
# the screen (whose size we know already.)
|
||||
def reverser
|
||||
if @waveCoords[0][1] < 10
|
||||
@direction = :right
|
||||
elsif @waveCoords[-1][1] < 10
|
||||
@direction = :left
|
||||
end
|
||||
end
|
||||
|
||||
# animation control
|
||||
def move
|
||||
@timer.start
|
||||
end
|
||||
|
||||
def stop
|
||||
@timer.stop
|
||||
end
|
||||
end
|
||||
|
||||
# Start the animation processing
|
||||
AnimatedWaveDemo.new($aniwave_demo, :left).move
|
1974
ext/tk/sample/demos-jp/goldberg.rb
Normal file
1974
ext/tk/sample/demos-jp/goldberg.rb
Normal file
File diff suppressed because it is too large
Load diff
224
ext/tk/sample/demos-jp/pendulum.rb
Normal file
224
ext/tk/sample/demos-jp/pendulum.rb
Normal file
|
@ -0,0 +1,224 @@
|
|||
#
|
||||
# This demonstration illustrates how Tcl/Tk can be used to construct
|
||||
# simulations of physical systems.
|
||||
# (called by 'widget')
|
||||
#
|
||||
# based on Tcl/Tk8.5a2 widget demos
|
||||
|
||||
# destroy toplevel widget for this demo script
|
||||
if defined?($pendulum_demo) && $pendulum_demo
|
||||
$pendulum_demo.destroy
|
||||
$pendulum_demo = nil
|
||||
end
|
||||
|
||||
# create toplevel widget
|
||||
$pendulum_demo = TkToplevel.new {|w|
|
||||
title("Pendulum Animation Demonstration")
|
||||
iconname("pendulum")
|
||||
positionWindow(w)
|
||||
}
|
||||
|
||||
# create label
|
||||
msg = TkLabel.new($pendulum_demo) {
|
||||
font $font
|
||||
wraplength '4i'
|
||||
justify 'left'
|
||||
text 'このデモは、物理系のシミュレーションに関わるようなアニメーション実行するために Ruby/Tk をどのように用いることができるかを示しています。左側のキャンバスは単純な振り子である物理系自体のグラフィカル表現であるのに対し、右側のキャンバスは系の位相空間のグラフ(角速度と角度とをプロットしたもの)になっています。左側のキャンバス上でクリックおよびドラッグを行って振り子の重りの位置を変えてみてください。'
|
||||
}
|
||||
msg.pack('side'=>'top')
|
||||
|
||||
# create frame
|
||||
TkFrame.new($pendulum_demo) {|frame|
|
||||
TkButton.new(frame) {
|
||||
#text '了解'
|
||||
text '閉じる'
|
||||
command proc{
|
||||
tmppath = $pendulum_demo
|
||||
$pendulum_demo = nil
|
||||
tmppath.destroy
|
||||
}
|
||||
}.pack('side'=>'left', 'expand'=>'yes')
|
||||
|
||||
TkButton.new(frame) {
|
||||
text 'コード参照'
|
||||
command proc{showCode 'pendulum'}
|
||||
}.pack('side'=>'left', 'expand'=>'yes')
|
||||
|
||||
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
|
||||
|
||||
# animated wave
|
||||
class PendulumAnimationDemo
|
||||
def initialize(frame)
|
||||
# Create some structural widgets
|
||||
pane = TkPanedWindow.new(frame).pack(:fill=>:both, :expand=>true)
|
||||
pane.add(@lf1 = TkLabelFrame.new(pane, :text=>'Pendulum Simulation'))
|
||||
pane.add(@lf2 = TkLabelFrame.new(pane, :text=>'Phase Space'))
|
||||
|
||||
# Create the canvas containing the graphical representation of the
|
||||
# simulated system.
|
||||
@c = TkCanvas.new(@lf1, :width=>320, :height=>200, :background=>'white',
|
||||
:borderwidth=>2, :relief=>:sunken)
|
||||
TkcText.new(@c, 5, 5, :anchor=>:nw,
|
||||
:text=>'Click to Adjust Bob Start Position')
|
||||
# Coordinates of these items don't matter; they will be set properly below
|
||||
@plate = TkcLine.new(@c, 0, 25, 320, 25, :width=>2, :fill=>'grey50')
|
||||
@rod = TkcLine.new(@c, 1, 1, 1, 1, :width=>3, :fill=>'black')
|
||||
@bob = TkcOval.new(@c, 1, 1, 2, 2,
|
||||
:width=>3, :fill=>'yellow', :outline=>'black')
|
||||
TkcOval.new(@c, 155, 20, 165, 30, :fill=>'grey50', :outline=>'')
|
||||
|
||||
# pack
|
||||
@c.pack(:fill=>:both, :expand=>true)
|
||||
|
||||
# Create the canvas containing the phase space graph; this consists of
|
||||
# a line that gets gradually paler as it ages, which is an extremely
|
||||
# effective visual trick.
|
||||
@k = TkCanvas.new(@lf2, :width=>320, :height=>200, :background=>'white',
|
||||
:borderwidth=>2, :relief=>:sunken)
|
||||
@y_axis = TkcLine.new(@k, 160, 200, 160, 0, :fill=>'grey75', :arrow=>:last)
|
||||
@x_axis = TkcLine.new(@k, 0, 100, 320, 100, :fill=>'grey75', :arrow=>:last)
|
||||
|
||||
@graph = {}
|
||||
90.step(0, -10){|i|
|
||||
# Coordinates of these items don't matter;
|
||||
# they will be set properly below
|
||||
@graph[i] = TkcLine.new(@k, 0, 0, 1, 1, :smooth=>true, :fill=>"grey#{i}")
|
||||
}
|
||||
|
||||
# labels
|
||||
@label_theta = TkcText.new(@k, 0, 0, :anchor=>:ne,
|
||||
:text=>'q', :font=>'Symbol 8')
|
||||
@label_dtheta = TkcText.new(@k, 0, 0, :anchor=>:ne,
|
||||
:text=>'dq', :font=>'Symbol 8')
|
||||
|
||||
# pack
|
||||
@k.pack(:fill=>:both, :expand=>true)
|
||||
|
||||
# Initialize some variables
|
||||
@points = []
|
||||
@theta = 45.0
|
||||
@dTheta = 0.0
|
||||
@length = 150
|
||||
|
||||
# init display
|
||||
showPendulum
|
||||
|
||||
# animation loop
|
||||
@timer = TkTimer.new(15){ repeat }
|
||||
|
||||
# binding
|
||||
@c.bindtags_unshift(btag = TkBindTag.new)
|
||||
btag.bind('Destroy'){ @timer.stop }
|
||||
btag.bind('1', proc{|x, y| @timer.stop; showPendulum(x, y)}, '%x %y')
|
||||
btag.bind('B1-Motion', proc{|x, y| showPendulum(x, y)}, '%x %y')
|
||||
btag.bind('ButtonRelease-1',
|
||||
proc{|x, y| showPendulum(x, y); @timer.start }, '%x %y')
|
||||
|
||||
btag.bind('Configure', proc{|w| @plate.coords(0, 25, w, 25)}, '%w')
|
||||
|
||||
@k.bind('Configure', proc{|h, w|
|
||||
@psh = h/2;
|
||||
@psw = w/2
|
||||
@x_axis.coords(2, @psh, w-2, @psh)
|
||||
@y_axis.coords(@psw, h-2, @psw, 2)
|
||||
@label_theta.coords(@psw-4, 6)
|
||||
@label_dtheta.coords(w-6, @psh+4)
|
||||
}, '%h %w')
|
||||
|
||||
# animation start
|
||||
@timer.start(500)
|
||||
end
|
||||
|
||||
# This procedure makes the pendulum appear at the correct place on the
|
||||
# canvas. If the additional arguments x, y are passed instead of computing
|
||||
# the position of the pendulum from the length of the pendulum rod and its
|
||||
# angle, the length and angle are computed in reverse from the given
|
||||
# location (which is taken to be the centre of the pendulum bob.)
|
||||
def showPendulum(x=nil, y=nil)
|
||||
if x && y && (x != 160 || y != 25)
|
||||
@dTheta = 0.0
|
||||
x2 = x - 160
|
||||
y2 = y - 25
|
||||
@length = Math.hypot(x2, y2)
|
||||
@theta = Math.atan2(x2,y2)*180/Math::PI
|
||||
else
|
||||
angle = @theta*Math::PI/180
|
||||
x = 160 + @length*Math.sin(angle)
|
||||
y = 25 + @length*Math.cos(angle)
|
||||
end
|
||||
|
||||
@rod.coords(160, 25, x, y)
|
||||
@bob.coords(x-15, y-15, x+15, y+15)
|
||||
end
|
||||
|
||||
# Update the phase-space graph according to the current angle and the
|
||||
# rate at which the angle is changing (the first derivative with
|
||||
# respect to time.)
|
||||
def showPhase
|
||||
@points << @theta + @psw << -20*@dTheta + @psh
|
||||
if @points.length > 100
|
||||
@points = @points[-100..-1]
|
||||
end
|
||||
(0...100).step(10){|i|
|
||||
first = - i
|
||||
last = 11 - i
|
||||
last = -1 if last >= 0
|
||||
next if first > last
|
||||
lst = @points[first..last]
|
||||
@graph[i].coords(lst) if lst && lst.length >= 4
|
||||
}
|
||||
end
|
||||
|
||||
# This procedure is the "business" part of the simulation that does
|
||||
# simple numerical integration of the formula for a simple rotational
|
||||
# pendulum.
|
||||
def recomputeAngle
|
||||
scaling = 3000.0/@length/@length
|
||||
|
||||
# To estimate the integration accurately, we really need to
|
||||
# compute the end-point of our time-step. But to do *that*, we
|
||||
# need to estimate the integration accurately! So we try this
|
||||
# technique, which is inaccurate, but better than doing it in a
|
||||
# single step. What we really want is bound up in the
|
||||
# differential equation:
|
||||
# .. - sin theta
|
||||
# theta + theta = -----------
|
||||
# length
|
||||
# But my math skills are not good enough to solve this!
|
||||
|
||||
# first estimate
|
||||
firstDDTheta = -Math.sin(@theta * Math::PI/180) * scaling
|
||||
midDTheta = @dTheta + firstDDTheta
|
||||
midTheta = @theta + (@dTheta + midDTheta)/2
|
||||
# second estimate
|
||||
midDDTheta = -Math.sin(midTheta * Math::PI/180) * scaling
|
||||
midDTheta = @dTheta + (firstDDTheta + midDDTheta)/2
|
||||
midTheta = @theta + (@dTheta + midDTheta)/2
|
||||
# Now we do a double-estimate approach for getting the final value
|
||||
# first estimate
|
||||
midDDTheta = -Math.sin(midTheta * Math::PI/180) * scaling
|
||||
lastDTheta = midDTheta + midDDTheta
|
||||
lastTheta = midTheta + (midDTheta+ lastDTheta)/2
|
||||
# second estimate
|
||||
lastDDTheta = -Math.sin(lastTheta * Math::PI/180) * scaling
|
||||
lastDTheta = midDTheta + (midDDTheta + lastDDTheta)/2
|
||||
lastTheta = midTheta + (midDTheta + lastDTheta)/2
|
||||
# Now put the values back in our globals
|
||||
@dTheta = lastDTheta
|
||||
@theta = lastTheta
|
||||
end
|
||||
|
||||
# This method ties together the simulation engine and the graphical
|
||||
# display code that visualizes it.
|
||||
def repeat
|
||||
# Simulate
|
||||
recomputeAngle
|
||||
|
||||
# Update the display
|
||||
showPendulum
|
||||
showPhase
|
||||
end
|
||||
end
|
||||
|
||||
# Start the animation processing
|
||||
PendulumAnimationDemo.new($pendulum_demo)
|
|
@ -442,6 +442,12 @@ txt.insert('end', "\n")
|
|||
txt.insert('end', "アニメーション\n", tag_kanji_title)
|
||||
txt.insert('end', " \n ", tag_demospace)
|
||||
txt.insert('end', "1. アニメーションラベル (機能に対応したバージョンのTkが必要)\n", tag_demo, "demo-anilabel")
|
||||
txt.insert('end', " \n ", tag_demospace)
|
||||
txt.insert('end', "2. 波形のアニメーション (機能に対応したバージョンのTkが必要)\n", tag_demo, "demo-aniwave")
|
||||
txt.insert('end', " \n ", tag_demospace)
|
||||
txt.insert('end', "3. 振り子のシミュレーション (機能に対応したバージョンのTkが必要)\n", tag_demo, "demo-pendulum")
|
||||
txt.insert('end', " \n ", tag_demospace)
|
||||
txt.insert('end', "4. A celebration of Rube Goldberg (機能に対応したバージョンのTkが必要)\n", tag_demo, "demo-goldberg")
|
||||
|
||||
txt.insert('end', "\n")
|
||||
#txt.insert('end', "その他\n", tag_middle)
|
||||
|
@ -813,7 +819,7 @@ end
|
|||
#
|
||||
def aboutBox
|
||||
Tk.messageBox('icon'=>'info', 'type'=>'ok', 'title'=>'About Widget Demo',
|
||||
'message'=>"Ruby/Tk ウィジェットデモ Ver.1.5.0-jp\n\n" +
|
||||
'message'=>"Ruby/Tk ウィジェットデモ Ver.1.5.2-jp\n\n" +
|
||||
"based on demos of Tk8.1 -- 8.5 " +
|
||||
"( Copyright:: " +
|
||||
"(c) 1996-1997 Sun Microsystems, Inc. / " +
|
||||
|
|
30
ext/tk/sample/irbtk.rb
Normal file
30
ext/tk/sample/irbtk.rb
Normal file
|
@ -0,0 +1,30 @@
|
|||
#!/usr/local/bin/ruby
|
||||
#
|
||||
# irbtk.rb - irb with Ruby/Tk
|
||||
#
|
||||
# If you want to use 'multi-tk.rb', give option '--multi-tk'.
|
||||
# And if you want to use 'remote-tk.rb', give option '--remote-tk'.
|
||||
# If you want both, you don't need to give both options, because
|
||||
# 'remote-tk.rb' includes 'multi-tk.rb'.
|
||||
# ( There is no trouble even if you give both options. )
|
||||
#
|
||||
require 'remote-tk' if ARGV.delete('--remote-tk')
|
||||
require 'multi-tk' if ARGV.delete('--multi-tk')
|
||||
|
||||
require "tk"
|
||||
module Tk
|
||||
MAINLOOP = Thread.new{ mainloop }
|
||||
end
|
||||
|
||||
require "irb"
|
||||
|
||||
if __FILE__ == $0
|
||||
IRB.start(__FILE__)
|
||||
else
|
||||
# check -e option
|
||||
if /^-e$/ =~ $0
|
||||
IRB.start(__FILE__)
|
||||
else
|
||||
IRB.setup(__FILE__)
|
||||
end
|
||||
end
|
2903
ext/tk/tcltklib.c
2903
ext/tk/tcltklib.c
File diff suppressed because it is too large
Load diff
|
@ -8,12 +8,20 @@
|
|||
|
||||
************************************************/
|
||||
|
||||
#define TKUTIL_RELEASE_DATE "2005-01-25"
|
||||
#define TKUTIL_RELEASE_DATE "2005-03-02"
|
||||
|
||||
#include "ruby.h"
|
||||
#include "rubysig.h"
|
||||
#include "st.h"
|
||||
|
||||
/* check ruby_version */
|
||||
#include "version.h"
|
||||
#if RUBY_VERSION_MINOR == 9
|
||||
#define ST_FOREACH_PASS_ERR_ARG 1 /* Ruby 1.9 */
|
||||
#else
|
||||
#define ST_FOREACH_PASS_ERR_ARG 0 /* Ruby 1.8 (from 2005/02/08) */
|
||||
#endif
|
||||
|
||||
static VALUE cMethod;
|
||||
|
||||
static VALUE cTclTkLib;
|
||||
|
@ -200,23 +208,35 @@ fromUTF8_toDefaultEnc(str, self)
|
|||
}
|
||||
|
||||
|
||||
#if ST_FOREACH_PASS_ERR_ARG
|
||||
static void
|
||||
hash_check(err)
|
||||
int err;
|
||||
{
|
||||
if (err) {
|
||||
rb_raise(rb_eRuntimeError, "hash modified");
|
||||
rb_raise(rb_eRuntimeError, "hash modified during iteration");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ST_FOREACH_PASS_ERR_ARG
|
||||
static int
|
||||
to_strkey(key, value, hash, err)
|
||||
VALUE key;
|
||||
VALUE value;
|
||||
VALUE hash;
|
||||
int err;
|
||||
#else
|
||||
static int
|
||||
to_strkey(key, value, hash)
|
||||
VALUE key;
|
||||
VALUE value;
|
||||
VALUE hash;
|
||||
#endif
|
||||
{
|
||||
#if ST_FOREACH_PASS_ERR_ARG
|
||||
hash_check(err);
|
||||
#endif
|
||||
if (key == Qundef) return ST_CONTINUE;
|
||||
rb_hash_aset(hash, rb_funcall(key, ID_to_s, 0, 0), value);
|
||||
return ST_CHECK;
|
||||
|
@ -236,14 +256,16 @@ tk_symbolkey2str(self, keys)
|
|||
}
|
||||
|
||||
static VALUE get_eval_string_core _((VALUE, VALUE, VALUE));
|
||||
static VALUE ary2list _((VALUE, VALUE));
|
||||
static VALUE ary2list2 _((VALUE, VALUE));
|
||||
static VALUE ary2list _((VALUE, VALUE, VALUE));
|
||||
static VALUE ary2list2 _((VALUE, VALUE, VALUE));
|
||||
static VALUE hash2list _((VALUE, VALUE));
|
||||
static VALUE hash2list_enc _((VALUE, VALUE));
|
||||
static VALUE hash2kv _((VALUE, VALUE, VALUE));
|
||||
|
||||
static VALUE
|
||||
ary2list(ary, self)
|
||||
ary2list(ary, enc_flag, self)
|
||||
VALUE ary;
|
||||
VALUE enc_flag;
|
||||
VALUE self;
|
||||
{
|
||||
int idx, idx2, size, size2;
|
||||
|
@ -266,29 +288,36 @@ ary2list(ary, self)
|
|||
val = RARRAY(ary)->ptr[idx];
|
||||
switch(TYPE(val)) {
|
||||
case T_ARRAY:
|
||||
RARRAY(dst)->ptr[RARRAY(dst)->len++] = ary2list(val, self);
|
||||
RARRAY(dst)->ptr[RARRAY(dst)->len++]
|
||||
= ary2list(val, enc_flag, self);
|
||||
break;
|
||||
|
||||
case T_HASH:
|
||||
/* RARRAY(dst)->ptr[RARRAY(dst)->len++] = hash2list(val, self); */
|
||||
val = hash2kv(val, Qnil, self);
|
||||
val = hash2kv(val, enc_flag, self);
|
||||
size2 = RARRAY(val)->len;
|
||||
for(idx2 = 0; idx2 < size2; idx2++) {
|
||||
val2 = RARRAY(val)->ptr[idx2];
|
||||
switch(TYPE(val2)) {
|
||||
case T_ARRAY:
|
||||
RARRAY(dst)->ptr[RARRAY(dst)->len++]
|
||||
= ary2list(val2, self);
|
||||
= ary2list(val2, enc_flag, self);
|
||||
break;
|
||||
|
||||
case T_HASH:
|
||||
RARRAY(dst)->ptr[RARRAY(dst)->len++]
|
||||
= hash2list(val2, self);
|
||||
if (RTEST(enc_flag)) {
|
||||
RARRAY(dst)->ptr[RARRAY(dst)->len++]
|
||||
= hash2list_enc(val2, self);
|
||||
} else {
|
||||
RARRAY(dst)->ptr[RARRAY(dst)->len++]
|
||||
= hash2list(val2, self);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (val2 != TK_None) {
|
||||
RARRAY(dst)->ptr[RARRAY(dst)->len++]
|
||||
= get_eval_string_core(val2, Qnil, self);
|
||||
= get_eval_string_core(val2, enc_flag, self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -297,7 +326,7 @@ ary2list(ary, self)
|
|||
default:
|
||||
if (val != TK_None) {
|
||||
RARRAY(dst)->ptr[RARRAY(dst)->len++]
|
||||
= get_eval_string_core(val, Qnil, self);
|
||||
= get_eval_string_core(val, enc_flag, self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -305,8 +334,9 @@ ary2list(ary, self)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
ary2list2(ary, self)
|
||||
ary2list2(ary, enc_flag, self)
|
||||
VALUE ary;
|
||||
VALUE enc_flag;
|
||||
VALUE self;
|
||||
{
|
||||
int idx, size;
|
||||
|
@ -320,17 +350,23 @@ ary2list2(ary, self)
|
|||
val = RARRAY(ary)->ptr[idx];
|
||||
switch(TYPE(val)) {
|
||||
case T_ARRAY:
|
||||
RARRAY(dst)->ptr[RARRAY(dst)->len++] = ary2list(val, self);
|
||||
RARRAY(dst)->ptr[RARRAY(dst)->len++]
|
||||
= ary2list(val, enc_flag, self);
|
||||
break;
|
||||
|
||||
case T_HASH:
|
||||
RARRAY(dst)->ptr[RARRAY(dst)->len++] = hash2list(val, self);
|
||||
if (RTEST(enc_flag)) {
|
||||
RARRAY(dst)->ptr[RARRAY(dst)->len++] = hash2list(val, self);
|
||||
} else {
|
||||
RARRAY(dst)->ptr[RARRAY(dst)->len++]
|
||||
= hash2list_enc(val, self);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (val != TK_None) {
|
||||
RARRAY(dst)->ptr[RARRAY(dst)->len++]
|
||||
= get_eval_string_core(val, Qnil, self);
|
||||
= get_eval_string_core(val, enc_flag, self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -448,16 +484,26 @@ assoc2kv_enc(assoc, ary, self)
|
|||
}
|
||||
}
|
||||
|
||||
#if ST_FOREACH_PASS_ERR_ARG
|
||||
static int
|
||||
push_kv(key, val, args, err)
|
||||
VALUE key;
|
||||
VALUE val;
|
||||
VALUE args;
|
||||
int err;
|
||||
#else
|
||||
static int
|
||||
push_kv(key, val, args)
|
||||
VALUE key;
|
||||
VALUE val;
|
||||
VALUE args;
|
||||
#endif
|
||||
{
|
||||
volatile VALUE ary;
|
||||
|
||||
#if ST_FOREACH_PASS_ERR_ARG
|
||||
hash_check(err);
|
||||
#endif
|
||||
ary = RARRAY(args)->ptr[0];
|
||||
|
||||
if (key == Qundef) return ST_CONTINUE;
|
||||
|
@ -498,16 +544,26 @@ hash2kv(hash, ary, self)
|
|||
}
|
||||
}
|
||||
|
||||
#if ST_FOREACH_PASS_ERR_ARG
|
||||
static int
|
||||
push_kv_enc(key, val, args, err)
|
||||
VALUE key;
|
||||
VALUE val;
|
||||
VALUE args;
|
||||
int err;
|
||||
#else
|
||||
static int
|
||||
push_kv_enc(key, val, args)
|
||||
VALUE key;
|
||||
VALUE val;
|
||||
VALUE args;
|
||||
#endif
|
||||
{
|
||||
volatile VALUE ary;
|
||||
|
||||
#if ST_FOREACH_PASS_ERR_ARG
|
||||
hash_check(err);
|
||||
#endif
|
||||
ary = RARRAY(args)->ptr[0];
|
||||
|
||||
if (key == Qundef) return ST_CONTINUE;
|
||||
|
@ -556,7 +612,7 @@ hash2list(hash, self)
|
|||
VALUE hash;
|
||||
VALUE self;
|
||||
{
|
||||
return ary2list2(hash2kv(hash, Qnil, self), self);
|
||||
return ary2list2(hash2kv(hash, Qnil, self), Qfalse, self);
|
||||
}
|
||||
|
||||
|
||||
|
@ -565,7 +621,7 @@ hash2list_enc(hash, self)
|
|||
VALUE hash;
|
||||
VALUE self;
|
||||
{
|
||||
return ary2list2(hash2kv_enc(hash, Qnil, self), self);
|
||||
return ary2list2(hash2kv_enc(hash, Qnil, self), Qfalse, self);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
|
@ -669,11 +725,7 @@ get_eval_string_core(obj, enc_flag, self)
|
|||
}
|
||||
|
||||
case T_ARRAY:
|
||||
if (RTEST(enc_flag)) {
|
||||
return fromDefaultEnc_toUTF8(ary2list(obj, self), self);
|
||||
} else {
|
||||
return ary2list(obj, self);
|
||||
}
|
||||
return ary2list(obj, enc_flag, self);
|
||||
|
||||
case T_FALSE:
|
||||
return rb_str_new2("0");
|
||||
|
|
Loading…
Reference in a new issue