* wrap the command-proc of TkScale : pass the numeric object to the proc

* better support for widgets created on Tk interpreter (without Ruby)
* a little more stable on Multiple Tk interpreters running


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4242 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nagai 2003-07-31 07:59:18 +00:00
parent 89769459ba
commit 7126624b4e
4 changed files with 117 additions and 24 deletions

View File

@ -5,6 +5,13 @@
require 'tcltklib' require 'tcltklib'
require 'thread' require 'thread'
################################################
# ignore exception on the mainloop
# TclTkLib.mainloop_abort_on_exception = false
TclTkLib.mainloop_abort_on_exception = nil
################################################ ################################################
# exceptiopn to treat the return value from IP # exceptiopn to treat the return value from IP
class MultiTkIp_OK < Exception class MultiTkIp_OK < Exception
@ -22,17 +29,11 @@ class MultiTkIp_OK < Exception
end end
MultiTkIp_OK.freeze MultiTkIp_OK.freeze
################################################ ################################################
# methods for construction # methods for construction
class MultiTkIp class MultiTkIp
SLAVE_IP_ID = ['slave'.freeze, '0']
# ignore exception on the mainloop
#TclTkLib.mainloop_abort_on_exception = false
TclTkLib.mainloop_abort_on_exception = nil
######################################
SLAVE_IP_ID = ['slave'.freeze, '00000']
@@IP_TABLE = {} @@IP_TABLE = {}
@ -827,6 +828,32 @@ end
# depend on TclTkIp # depend on TclTkIp
class MultiTkIp class MultiTkIp
def mainloop(check_root = true, restart_on_dead = true)
unless restart_on_dead
@interp.mainloop(check_root)
else
begin
loop do
@interp.mainloop(check_root)
if check_root
begin
break if @interp._invoke('winfo', 'exists?', '.') == "1"
rescue Exception
break
end
end
end
rescue StandardError
if TclTkLib.mainloop_abort_on_exception != nil
STDERR.print("warning: Tk mainloop on ", @interp.inspect,
" receives ", $!.class.inspect,
" exception (ignore) : ", $!.message, "\n");
end
retry
end
end
end
def make_safe def make_safe
@interp.make_safe @interp.make_safe
end end

View File

@ -50,28 +50,27 @@ module TkComm
if ruby_class = WidgetClassNames[tk_class] if ruby_class = WidgetClassNames[tk_class]
ruby_class_name = ruby_class.name ruby_class_name = ruby_class.name
gen_class_name = ruby_class_name + 'GeneratedOnTk' # gen_class_name = ruby_class_name + 'GeneratedOnTk'
gen_class_name = ruby_class_name
classname_def = '' classname_def = ''
elsif Object.const_defined?('Tk' + tk_class) elsif Object.const_defined?('Tk' + tk_class)
ruby_class_name = 'Tk' + tk_class ruby_class_name = 'Tk' + tk_class
gen_class_name = ruby_class_name + 'GeneratedOnTk' # gen_class_name = ruby_class_name + 'GeneratedOnTk'
gen_class_name = ruby_class_name
classname_def = '' classname_def = ''
else else
ruby_class_name = 'TkWindow' ruby_class_name = 'TkWindow'
gen_class_name = ruby_class_name + tk_class + 'GeneratedOnTk' # gen_class_name = ruby_class_name + tk_class + 'GeneratedOnTk'
gen_class_name = 'TkWidget_' + tk_class
classname_def = "WidgetClassName = '#{tk_class}'.freeze" classname_def = "WidgetClassName = '#{tk_class}'.freeze"
end end
unless Object.const_defined? gen_class_name unless Object.const_defined? gen_class_name
Object.class_eval "class #{gen_class_name}<#{ruby_class_name} Object.class_eval "class #{gen_class_name}<#{ruby_class_name}
#{classname_def} #{classname_def}
def initialize(path)
@path=path
#Tk_WINDOWS[@path] = self
TkCore::INTERP.tk_windows[@path] = self
end
end" end"
end end
Object.class_eval "#{gen_class_name}.new('#{path}')" Object.class_eval "#{gen_class_name}.new('widgetname'=>'#{path}',
'without_creating'=>true)"
end end
private :_genobj_for_tkwidget private :_genobj_for_tkwidget
module_function :_genobj_for_tkwidget module_function :_genobj_for_tkwidget
@ -889,11 +888,34 @@ module TkCore
tk_call('info', *args) tk_call('info', *args)
end end
def mainloop(check_root = true) def mainloop(check_root = true, restart_on_dead = true)
unless restart_on_dead
TclTkLib.mainloop(check_root) TclTkLib.mainloop(check_root)
else
begin
loop do
TclTkLib.mainloop(check_root)
if check_root
begin
break if TkWinfo.exist?('.')
rescue Exception
break
end
end
end
rescue StandardError
if TclTkLib.mainloop_abort_on_exception != nil
STDERR.print("warning: Tk mainloop on ", TkCore::INTERP.inspect,
" receives ", $!.class.inspect,
" exception (ignore) : ", $!.message, "\n");
end
retry
end
end
end end
def mainloop_watchdog(check_root = true) def mainloop_watchdog(check_root = true)
# watchdog restarts mainloop when mainloop is dead
TclTkLib.mainloop_watchdog(check_root) TclTkLib.mainloop_watchdog(check_root)
end end
@ -3739,12 +3761,12 @@ class TkWindow<TkObject
def destroy def destroy
super super
_destroy_children _destroy_children
tk_call 'destroy', epath
if defined?(@cmdtbl) if defined?(@cmdtbl)
for id in @cmdtbl for id in @cmdtbl
uninstall_cmd id uninstall_cmd id
end end
end end
tk_call 'destroy', epath
uninstall_win uninstall_win
end end
@ -4392,12 +4414,46 @@ class TkScale<TkWindow
def create_self(keys) def create_self(keys)
if keys and keys != None if keys and keys != None
if keys.key?('command')
cmd = keys.delete('command')
keys['command'] = proc{|val| cmd.call(val.to_f)}
end
tk_call 'scale', @path, *hash_kv(keys) tk_call 'scale', @path, *hash_kv(keys)
else else
tk_call 'scale', @path tk_call 'scale', @path
end end
end end
def _wrap_command_arg(cmd)
proc{|val|
if val.kind_of?(String)
cmd.call(number(val))
else
cmd.call(val)
end
}
end
private :_wrap_command_arg
def configure_cmd(slot, value)
configure(slot=>value)
end
def configure(slot, value=None)
if (slot == 'command' || slot == :command)
configure('command'=>value)
elsif slot.kind_of?(Hash) &&
(slot.key?('command') || slot.key?(:command))
slot = _symbolkey2str(slot)
slot['command'] = __wrap_command_arg(slot.delete('command'))
end
super(slot, value)
end
def command(cmd=Proc.new)
configure('command'=>cmd)
end
def get(x=None, y=None) def get(x=None, y=None)
number(tk_send('get', x, y)) number(tk_send('get', x, y))
end end
@ -5098,10 +5154,11 @@ TkBindTag::ALL.bind(TkVirtualEvent.new('Destroy'), proc{|widget|
else else
w = widget.to_s w = widget.to_s
end end
if widget.respond_to?(:__destroy_hook__) && if widget.respond_to?(:__destroy_hook__)
TkCore::INTERP._invoke('winfo','exist',w) == '1'
begin begin
if TkCore::INTERP._invoke('winfo','exist',w) == '1'
widget.__destroy_hook__ widget.__destroy_hook__
end
rescue Exception rescue Exception
end end
end end

View File

@ -114,7 +114,14 @@ class TkTimer
@id = Tk_CBID.join @id = Tk_CBID.join
Tk_CBID[1].succ! Tk_CBID[1].succ!
@cb_cmd = TkCore::INTERP.get_cb_entry(self.method(:do_callback)) # @cb_cmd = TkCore::INTERP.get_cb_entry(self.method(:do_callback))
@cb_cmd = TkCore::INTERP.get_cb_entry(proc{
begin
self.do_callback
rescue
self.cancel
end
})
@set_next = true @set_next = true

View File

@ -55,6 +55,8 @@ safe_slave1.eval_proc(cmd, 'safe1') # label -> .w00016
safe_slave2.eval_proc(cmd, 'safe2') # label -> .w00020 safe_slave2.eval_proc(cmd, 'safe2') # label -> .w00020
cmd.call('master') # label -> .w00024 cmd.call('master') # label -> .w00024
#second_master = MultiTkIp.new(&cmd)
TkTimer.new(2000, -1, proc{p ['safe1', safe_slave1.deleted?]}).start TkTimer.new(2000, -1, proc{p ['safe1', safe_slave1.deleted?]}).start
TkTimer.new(2000, -1, proc{p ['safe2', safe_slave2.deleted?]}).start TkTimer.new(2000, -1, proc{p ['safe2', safe_slave2.deleted?]}).start
TkTimer.new(2000, -1, proc{p ['trusted', trusted_slave.deleted?]}).start TkTimer.new(2000, -1, proc{p ['trusted', trusted_slave.deleted?]}).start