1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/ext/tk/lib/tk.rb
matz c12c7ab1dc matz
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1045 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2000-11-17 09:09:03 +00:00

2941 lines
63 KiB
Ruby

#
# tk.rb - Tk interface modue using tcltklib
# $Date$
# by Yukihiro Matsumoto <matz@netlab.co.jp>
# use Shigehiro's tcltklib
require "tcltklib"
require "tkutil"
module TkComm
WidgetClassNames = {}
None = Object.new
def None.to_s
'None'
end
Tk_CMDTBL = {}
Tk_WINDOWS = {}
def error_at
frames = caller()
frames.delete_if do |c|
c =~ %r!/tk(|core|thcore|canvas|text|entry|scrollbox)\.rb:\d+!
end
frames
end
private :error_at
def _genobj_for_tkwidget(path)
return TkRoot.new if path == '.'
begin
tk_class = TkCore::INTERP._invoke('winfo', 'class', path)
rescue
return path
end
ruby_class = WidgetClassNames[tk_class]
gen_class_name = ruby_class.name + 'GeneratedOnTk'
unless Object.const_defined? gen_class_name
eval "class #{gen_class_name}<#{ruby_class.name}
def initialize(path)
@path=path
Tk_WINDOWS[@path] = self
end
end"
end
eval "#{gen_class_name}.new('#{path}')"
end
def tk_tcl2ruby(val)
if val =~ /^rb_out (c\d+)/
return Tk_CMDTBL[$1]
end
if val.include? ?\s
return val.split.collect{|v| tk_tcl2ruby(v)}
end
case val
when /^@font/
TkFont.get_obj(val)
when /^-?\d+$/
val.to_i
when /^\./
Tk_WINDOWS[val] ? Tk_WINDOWS[val] : _genobj_for_tkwidget(val)
when / /
val.split.collect{|elt|
tk_tcl2ruby(elt)
}
when /^-?\d+\.\d*$/
val.to_f
else
val
end
end
def tk_split_list(str)
return [] if str == ""
idx = str.index('{')
return tk_tcl2ruby(str) unless idx
list = tk_tcl2ruby(str[0,idx])
list = [] if list == ""
str = str[idx+1..-1]
i = -1
brace = 1
str.each_byte {|c|
i += 1
brace += 1 if c == ?{
brace -= 1 if c == ?}
break if brace == 0
}
if str[0, i] == ' '
list.push ' '
else
list.push tk_split_list(str[0, i])
end
list += tk_split_list(str[i+1..-1])
list
end
def tk_split_simplelist(str)
return [] if str == ""
idx = str.index('{')
return str.split unless idx
list = str[0,idx].split
str = str[idx+1..-1]
i = -1
brace = 1
str.each_byte {|c|
i += 1
brace += 1 if c == ?{
brace -= 1 if c == ?}
break if brace == 0
}
if i == 0
list.push ''
elsif str[0, i] == ' '
list.push ' '
else
list.push str[0..i-1]
end
list += tk_split_simplelist(str[i+1..-1])
list
end
private :tk_tcl2ruby, :tk_split_list, :tk_split_simplelist
def hash_kv(keys)
conf = []
if keys and keys != None
for k, v in keys
conf.push("-#{k}")
conf.push(v)
end
end
conf
end
private :hash_kv
def array2tk_list(ary)
ary.collect{|e|
if e.kind_of? Array
"{#{array2tk_list(e)}}"
elsif e.kind_of? Hash
"{#{e.to_a.collect{|ee| array2tk_list(ee)}.join(' ')}}"
else
s = _get_eval_string(e)
(s.index(/\s/))? "{#{s}}": s
end
}.join(" ")
end
private :array2tk_list
def bool(val)
case val
when "1", 1, 'yes', 'true'
TRUE
else
FALSE
end
end
def number(val)
case val
when /^-?\d+$/
val.to_i
when /^-?\d+\.\d*$/
val.to_f
else
val
end
end
def string(val)
if val == "{}"
''
elsif val[0] == ?{
val[1..-2]
else
val
end
end
def list(val)
tk_split_list(val).to_a
end
def window(val)
Tk_WINDOWS[val]
end
def procedure(val)
if val =~ /^rb_out (c\d+)/
Tk_CMDTBL[$1]
else
nil
end
end
private :bool, :number, :string, :list, :window, :procedure
def _get_eval_string(str)
return nil if str == None
if str.kind_of?(String)
# do nothing
elsif str.kind_of?(Hash)
str = hash_kv(str).join(" ")
elsif str.kind_of?(Array)
str = array2tk_list(str)
elsif str.kind_of?(Proc)
str = install_cmd(str)
elsif str == nil
str = ""
elsif str == false
str = "0"
elsif str == true
str = "1"
elsif (str.respond_to?(:to_eval))
str = str.to_eval()
else
str = str.to_s()
end
return str
end
private :_get_eval_string
def ruby2tcl(v)
if v.kind_of?(Hash)
v = hash_kv(v)
v.flatten!
v.collect{|e|ruby2tcl(e)}
else
_get_eval_string(v)
end
end
private :ruby2tcl
Tk_IDs = [0, 0] # [0]-cmdid, [1]-winid
def _curr_cmd_id
id = format("c%.4d", Tk_IDs[0])
end
def _next_cmd_id
id = _curr_cmd_id
Tk_IDs[0] += 1
id
end
def install_cmd(cmd)
return '' if cmd == ''
id = _next_cmd_id
Tk_CMDTBL[id] = cmd
@cmdtbl = [] unless @cmdtbl
@cmdtbl.push id
return format("rb_out %s", id);
end
def uninstall_cmd(id)
id = $1 if /rb_out (c\d+)/ =~ id
Tk_CMDTBL[id] = nil
end
private :install_cmd, :uninstall_cmd
def install_win(ppath)
id = format("w%.4d", Tk_IDs[1])
Tk_IDs[1] += 1
if !ppath or ppath == "."
@path = format(".%s", id);
else
@path = format("%s.%s", ppath, id)
end
Tk_WINDOWS[@path] = self
end
def uninstall_win()
Tk_WINDOWS[@path] = nil
end
class Event
def initialize(seq,b,f,h,k,s,t,w,x,y,aa,ee,kk,nn,ww,tt,xx,yy)
@serial = seq
@num = b
@focus = (f == 1)
@height = h
@keycode = k
@state = s
@time = t
@width = w
@x = x
@y = y
@char = aa
@send_event = (ee == 1)
@keysym = kk
@keysym_num = nn
@type = tt
@widget = ww
@x_root = xx
@y_root = yy
end
attr :serial
attr :num
attr :focus
attr :height
attr :keycode
attr :state
attr :time
attr :width
attr :x
attr :y
attr :char
attr :send_event
attr :keysym
attr :keysym_num
attr :type
attr :widget
attr :x_root
attr :y_root
end
def install_bind(cmd, args=nil)
if args
id = install_cmd(proc{|*arg|
TkUtil.eval_cmd cmd, *arg
})
id + " " + args
else
id = install_cmd(proc{|arg|
TkUtil.eval_cmd cmd, Event.new(*arg)
})
id + ' %# %b %f %h %k %s %t %w %x %y %A %E %K %N %W %T %X %Y'
end
end
def tk_event_sequence(context)
if context.kind_of? TkVirtualEvent
context = context.path
end
if context.kind_of? Array
context = context.collect{|ev|
if context.kind_of? TkVirtualEvent
ev.path
else
ev
end
}.join("><")
end
if /,/ =~ context
context = context.split(/\s*,\s*/).join("><")
else
context
end
end
def _bind_core(mode, what, context, cmd, args=nil)
id = install_bind(cmd, args) if cmd
begin
tk_call(*(what + ["<#{tk_event_sequence(context)}>", mode + id]))
rescue
uninstall_cmd(id) if cmd
fail
end
end
def _bind(what, context, cmd, args=nil)
_bind_core('', what, context, cmd, args)
end
def _bind_append(what, context, cmd, args=nil)
_bind_core('+', what, context, cmd, args)
end
def _bind_remove(what, context)
tk_call(*(what + ["<#{tk_event_sequence(context)}>", '']))
end
def _bindinfo(what, context=nil)
if context
tk_call(*what+["<#{tk_event_sequence(context)}>"]).collect {|cmdline|
if cmdline =~ /^rb_out (c\d+)\s+(.*)$/
[Tk_CMDTBL[$1], $2]
else
cmdline
end
}
else
tk_split_list(tk_call(*what)).collect{|seq|
seq[1..-2].gsub(/></,',')
}
end
end
private :install_bind, :tk_event_sequence,
:_bind_core, :_bind, :_bind_append, :_bind_remove, :_bindinfo
def bind(tagOrClass, context, cmd=Proc.new, args=nil)
_bind(["bind", tagOrClass], context, cmd, args)
end
def bind_append(tagOrClass, context, cmd=Proc.new, args=nil)
_bind_append(["bind", tagOrClass], context, cmd, args)
end
def bind_remove(tagOrClass, context)
_bind_remove(['bind', tagOrClass], context)
end
def bindinfo(tagOrClass, context=nil)
_bindinfo(['bind', tagOrClass], context)
end
def bind_all(context, cmd=Proc.new, args=nil)
_bind(['bind', 'all'], context, cmd, args)
end
def bind_append_all(context, cmd=Proc.new, args=nil)
_bind_append(['bind', 'all'], context, cmd, args)
end
def bindinfo_all(context=nil)
_bindinfo(['bind', 'all'], context)
end
def pack(*args)
TkPack.configure *args
end
def grid(*args)
TkGrid.configure *args
end
def update(idle=nil)
if idle
tk_call 'update', 'idletasks'
else
tk_call 'update'
end
end
end
module TkCore
include TkComm
extend TkComm
INTERP = TclTkIp.new
INTERP._invoke("proc", "rb_out", "args", "if {[set st [catch {ruby [format \"TkCore.callback %%Q!%s!\" $args]} ret]] != 0} {if {[regsub -all {!} $args {\\!} newargs] == 0} {return -code $st $ret} {if {[set st [catch {ruby [format \"TkCore.callback %%Q!%s!\" $newargs]} ret]] != 0} {return -code $st $ret} {return $ret}}} {return $ret}")
def callback_break
fail TkCallbackBreak, "Tk callback returns 'break' status"
end
def callback_continue
fail TkCallbackContinue, "Tk callback returns 'continue' status"
end
def after(ms, cmd=Proc.new)
myid = _curr_cmd_id
cmdid = install_cmd(cmd)
tk_call("after",ms,cmdid)
return
if false #defined? Thread
Thread.start do
ms = Float(ms)/1000
ms = 10 if ms == 0
sleep ms/1000
cmd.call
end
else
cmdid = install_cmd(cmd)
tk_call("after",ms,cmdid)
end
end
def TkCore.callback(arg)
arg = Array(tk_split_list(arg))
_get_eval_string(TkUtil.eval_cmd(Tk_CMDTBL[arg.shift], *arg))
end
def scaling(scale=nil)
if scale
tk_call('tk', 'scaling', scale)
else
Float(number(tk_call('tk', 'scaling')))
end
end
def scaling_displayof(win, scale=nil)
if scale
tk_call('tk', 'scaling', '-displayof', win, scale)
else
Float(number(tk_call('tk', '-displayof', win, 'scaling')))
end
end
def appname(name=None)
tk_call('tk', 'appname', name)
end
def appsend(interp, async, *args)
if async
tk_call('send', '-async', '--', interp, *args)
else
tk_call('send', '--', interp, *args)
end
end
def rb_appsend(interp, async, *args)
args = args.collect!{|c| _get_eval_string(c).gsub(/[][$"]/, '\\\\\&')}
args.push(').to_s"')
appsend(interp, async, 'ruby "(', *args)
end
def appsend_displayof(interp, win, async, *args)
win = '.' if win == nil
if async
tk_call('send', '-async', '-displayof', win, '--', interp, *args)
else
tk_call('send', '-displayor', win, '--', interp, *args)
end
end
def rb_appsend_displayof(interp, win, async, *args)
args = args.collect!{|c| _get_eval_string(c).gsub(/[][$"]/, '\\\\\&')}
args.push(').to_s"')
appsend_displayof(interp, win, async, 'ruby "(', *args)
end
def info(*args)
tk_call('info', *args)
end
def mainloop
TclTkLib.mainloop
end
def event_generate(window, context, keys=nil)
window = window.path if window.kind_of? TkObject
if keys
tk_call('event', 'generate', window,
"<#{tk_event_sequence(context)}>", *hash_kv(keys))
else
tk_call('event', 'generate', window, "<#{tk_event_sequence(context)}>")
end
end
def messageBox(keys)
tk_call 'tk_messageBox', *hash_kv(keys)
end
def getOpenFile(keys = nil)
tk_call 'tk_getOpenFile', *hash_kv(keys)
end
def getSaveFile(keys = nil)
tk_call 'tk_getSaveFile', *hash_kv(keys)
end
def chooseColor(keys = nil)
tk_call 'tk_chooseColor', *hash_kv(keys)
end
def tk_call(*args)
print args.join(" "), "\n" if $DEBUG
args.collect! {|x|ruby2tcl(x)}
args.compact!
args.flatten!
begin
res = INTERP._invoke(*args)
rescue NameError
err = $!
begin
args.unshift "unknown"
res = INTERP._invoke(*args)
rescue
fail unless /^invalid command/ =~ $!
fail err
end
end
if INTERP._return_value() != 0
fail RuntimeError, res, error_at
end
print "==> ", res, "\n" if $DEBUG
return res
end
end
module Tk
include TkCore
extend Tk
TCL_VERSION = INTERP._invoke("info", "tclversion")
TK_VERSION = INTERP._invoke("set", "tk_version")
JAPANIZED_TK = (INTERP._invoke("info", "commands", "kanji") != "")
def root
TkRoot.new
end
def bell
tk_call 'bell'
end
def Tk.focus(display=nil)
if display == nil
r = tk_call('focus')
else
r = tk_call('focus', '-displayof', display)
end
tk_tcl2ruby(r)
end
def Tk.focus_lastfor(win)
tk_tcl2ruby(tk_call('focus', '-lastfor', win))
end
def Tk.show_kinsoku(mode='both')
begin
if /^8\.*/ === TK_VERSION && JAPANIZED_TK
tk_split_simplelist(tk_call('kinsoku', 'show', mode))
end
rescue
end
end
def Tk.add_kinsoku(chars, mode='both')
begin
if /^8\.*/ === TK_VERSION && JAPANIZED_TK
tk_split_simplelist(tk_call('kinsoku', 'add', mode,
*(chars.split(''))))
else
[]
end
rescue
[]
end
end
def Tk.delete_kinsoku(chars, mode='both')
begin
if /^8\.*/ === TK_VERSION && JAPANIZED_TK
tk_split_simplelist(tk_call('kinsoku', 'delete', mode,
*(chars.split(''))))
end
rescue
end
end
def toUTF8(str,encoding)
INTERP._toUTF8(str,encoding)
end
def fromUTF8(str,encoding)
INTERP._fromUTF8(str,encoding)
end
module Scrollable
def xscrollcommand(cmd=Proc.new)
configure_cmd 'xscrollcommand', cmd
end
def yscrollcommand(cmd=Proc.new)
configure_cmd 'yscrollcommand', cmd
end
def xview(*index)
v = tk_send('xview', *index)
list(v) if index.size == 0
end
def yview(*index)
v = tk_send('yview', *index)
list(v) if index.size == 0
end
def xscrollbar(bar=nil)
if bar
@xscrollbar = bar
@xscrollbar.orient 'horizontal'
self.xscrollcommand {|arg| @xscrollbar.set *arg}
@xscrollbar.command {|arg| self.xview *arg}
end
@xscrollbar
end
def yscrollbar(bar=nil)
if bar
@yscrollbar = bar
@yscrollbar.orient 'vertical'
self.yscrollcommand {|arg| @yscrollbar.set *arg}
@yscrollbar.command {|arg| self.yview *arg}
end
@yscrollbar
end
end
module Wm
include TkComm
def aspect(*args)
w = tk_call('wm', 'aspect', path, *args)
list(w) if args.length == 0
end
def client(name=None)
tk_call 'wm', 'client', path, name
end
def colormapwindows(*args)
list(tk_call('wm', 'colormapwindows', path, *args))
end
def wm_command(value=None)
string(tk_call('wm', 'command', path, value))
end
def deiconify
tk_call 'wm', 'deiconify', path
end
def focusmodel(*args)
tk_call 'wm', 'focusmodel', path, *args
end
def frame
tk_call('wm', 'frame', path)
end
def geometry(*args)
tk_call('wm', 'geometry', path, *args)
end
def grid(*args)
w = tk_call('wm', 'grid', path, *args)
list(w) if args.size == 0
end
def group(*args)
w = tk_call 'wm', 'group', path, *args
window(w) if args.size == 0
end
def iconbitmap(*args)
tk_call 'wm', 'iconbitmap', path, *args
end
def iconify
tk_call 'wm', 'iconify', path
end
def iconmask(*args)
tk_call 'wm', 'iconmask', path, *args
end
def iconname(*args)
tk_call 'wm', 'iconname', path, *args
end
def iconposition(*args)
w = tk_call('wm', 'iconposition', path, *args)
list(w) if args.size == 0
end
def iconwindow(*args)
w = tk_call('wm', 'iconwindow', path, *args)
window(w) if args.size == 0
end
def maxsize(*args)
w = tk_call('wm', 'maxsize', path, *args)
list(w) if args.size == 0
end
def minsize(*args)
w = tk_call('wm', 'minsize', path, *args)
list(w) if args.size == 0
end
def overrideredirect(bool=None)
if bool == None
bool(tk_call('wm', 'overrideredirect', path))
else
tk_call 'wm', 'overrideredirect', path, bool
end
end
def positionfrom(*args)
tk_call 'wm', 'positionfrom', path, *args
end
def protocol(name=nil, cmd=nil)
if cmd
tk_call('wm', 'protocol', path, name, cmd)
elsif name
result = tk_call('wm', 'protocol', path, name)
(result == "")? nil : tk_tcl2ruby(result)
else
tk_split_simplelist(tk_call('wm', 'protocol', path))
end
end
def resizable(*args)
w = tk_call('wm', 'resizable', path, *args)
if args.length == 0
list(w).collect{|e| bool(e)}
end
end
def sizefrom(*args)
tk_call('wm', 'sizefrom', path, *args)
end
def state
tk_call 'wm', 'state', path
end
def title(*args)
tk_call 'wm', 'title', path, *args
end
def transient(*args)
window(tk_call 'wm', 'transient', path, *args)
end
def withdraw
tk_call 'wm', 'withdraw', path
end
end
end
###########################################
# convert kanji string to/from utf-8
###########################################
if /^8\.[1-9]/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK
class TclTkIp
# from tkencoding.rb by ttate@jaist.ac.jp
alias __eval _eval
alias __invoke _invoke
private :__eval
private :__invoke
attr_accessor :encoding
def _eval(cmd)
if @encoding
_fromUTF8(__eval(_toUTF8(cmd, @encoding)), @encoding)
else
__eval(cmd)
end
end
def _invoke(*cmds)
if @encoding
cmds = cmds.collect{|cmd| _toUTF8(cmd, @encoding)}
_fromUTF8(__invoke(*cmds), @encoding)
else
__invoke(*cmds)
end
end
end
module Tk
def encoding=(name)
INTERP.encoding = name
end
def encoding
INTERP.encoding
end
def encoding_names
tk_split_simplelist(tk_call('encoding', 'names'))
end
def encoding_system
tk_call('encoding', 'system')
end
def encoding_system=(enc)
tk_call('encoding', 'system', enc)
end
end
# estimate encoding
case $KCODE
when /^e/i # EUC
Tk.encoding = 'euc-jp'
when /^s/i # SJIS
Tk.encoding = 'shiftjis'
when /^u/i # UTF8
Tk.encoding = 'utf-8'
else # NONE
begin
Tk.encoding = Tk.encoding_system
rescue StandardError, NameError
Tk.encoding = 'utf-8'
end
end
else
# dummy methods
module Tk
def encoding=(name)
nil
end
def encoding
nil
end
def encoding_names
nil
end
def encoding_system
nil
end
def encoding_system=(enc)
nil
end
end
end
module TkBindCore
def bind(context, cmd=Proc.new, args=nil)
Tk.bind(to_eval, context, cmd, args)
end
def bind_append(context, cmd=Proc.new, args=nil)
Tk.bind_append(to_eval, context, cmd, args)
end
def bind_remove(context)
Tk.bind_remove(to_eval, context)
end
def bindinfo(context=nil)
Tk.bindinfo(to_eval, context)
end
end
class TkBindTag
include TkBindCore
BTagID_TBL = {}
Tk_BINDTAG_ID = ["btag00000"]
def TkBindTag.id2obj(id)
BTagID_TBL[id]? BTagID_TBL[id]: id
end
def initialize(*args)
@id = Tk_BINDTAG_ID[0]
Tk_BINDTAG_ID[0] = Tk_BINDTAG_ID[0].succ
BTagID_TBL[@id] = self
bind(*args) if args != []
end
def to_eval
@id
end
def inspect
format "#<TkBindTag: %s>", @id
end
end
class TkBindTagAll<TkBindTag
BindTagALL = []
def TkBindTagAll.new(*args)
if BindTagALL[0]
BindTagALL[0].bind(*args) if args != []
else
new = super()
BindTagALL[0] = new
end
BindTagALL[0]
end
def initialize(*args)
@id = 'all'
BindTagALL[0].bind(*args) if args != []
end
end
class TkVariable
include Tk
extend TkCore
TkVar_CB_TBL = {}
Tk_VARIABLE_ID = ["v00000"]
INTERP._invoke("proc", "rb_var", "args", "ruby [format \"TkVariable.callback %%Q!%s!\" $args]")
def TkVariable.callback(args)
name1,name2,op = tk_split_list(args)
if TkVar_CB_TBL[name1]
_get_eval_string(TkVar_CB_TBL[name1].trace_callback(name2,op))
else
''
end
end
def initialize(val="")
@id = Tk_VARIABLE_ID[0]
Tk_VARIABLE_ID[0] = Tk_VARIABLE_ID[0].succ
if val == []
INTERP._eval(format('global %s; set %s(0) 0; unset %s(0)',
@id, @id, @id))
elsif val.kind_of?(Array)
a = []
val.each_with_index{|e,i| a.push(i); a.push(array2tk_list(e))}
s = '"' + a.join(" ").gsub(/[][$"]/, '\\\\\&') + '"'
INTERP._eval(format('global %s; array set %s %s', @id, @id, s))
elsif val.kind_of?(Hash)
s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\
.gsub(/[][$"]/, '\\\\\&') + '"'
INTERP._eval(format('global %s; array set %s %s', @id, @id, s))
else
s = '"' + _get_eval_string(val).gsub(/[][$"]/, '\\\\\&') + '"'
INTERP._eval(format('global %s; set %s %s', @id, @id, s))
end
end
def wait
INTERP._eval("tkwait variable #{@id}")
end
def id
@id
end
def value
begin
INTERP._eval(format('global %s; set %s', @id, @id))
rescue
if INTERP._eval(format('global %s; array exists %s', @id, @id)) != "1"
fail
else
Hash[*tk_split_simplelist(INTERP._eval(format('global %s; array get %s',
@id, @id)))]
end
end
end
def value=(val)
begin
s = '"' + _get_eval_string(val).gsub(/[][$"]/, '\\\\\&') + '"'
INTERP._eval(format('global %s; set %s %s', @id, @id, s))
rescue
if INTERP._eval(format('global %s; array exists %s', @id, @id)) != "1"
fail
else
if val == []
INTERP._eval(format('global %s; unset %s; set %s(0) 0; unset %s(0)',
@id, @id, @id, @id))
elsif val.kind_of?(Array)
a = []
val.each_with_index{|e,i| a.push(i); a.push(array2tk_list(e))}
s = '"' + a.join(" ").gsub(/[][$"]/, '\\\\\&') + '"'
INTERP._eval(format('global %s; unset %s; array set %s %s',
@id, @id, @id, s))
elsif val.kind_of?(Hash)
s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\
.gsub(/[][$"]/, '\\\\\&') + '"'
INTERP._eval(format('global %s; unset %s; array set %s %s',
@id, @id, @id, s))
else
fail
end
end
end
end
def [](index)
INTERP._eval(format('global %s; set %s(%s)',
@id, @id, _get_eval_string(index)))
end
def []=(index,val)
INTERP._eval(format('global %s; set %s(%s) %s', @id, @id,
_get_eval_string(index), _get_eval_string(val)))
end
def to_i
Integer(number(value))
end
def to_f
Float(number(value))
end
def to_s
String(string(value))
end
def inspect
format "#<TkVariable: %s>", @id
end
def ==(other)
case other
when TkVariable
self.equal(self)
when String
self.to_s == other
when Integer
self.to_i == other
when Float
self.to_f == other
when Array
self.to_a == other
else
false
end
end
def to_a
list(value)
end
def to_eval
@id
end
def unset(elem=nil)
if elem
INTERP._eval(format('global %s; unset %s(%s)',
@id, @id, tk_tcl2ruby(elem)))
else
INTERP._eval(format('global %s; unset %s', @id, @id))
end
end
alias remove unset
def trace_callback(elem, op)
if @trace_var.kind_of? Array
@trace_var.each{|m,e| e.call(self,elem,op) if m.index(op)}
end
if elem.kind_of? String
if @trace_elem[elem].kind_of? Array
@trace_elem[elem].each{|m,e| e.call(self,elem,op) if m.index(op)}
end
end
end
def trace(opts, cmd)
@trace_var = [] if @trace_var == nil
opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
@trace_var.unshift([opts,cmd])
if @trace_opts == nil
TkVar_CB_TBL[@id] = self
@trace_opts = opts
Tk.tk_call('trace', 'variable', @id, @trace_opts, 'rb_var')
else
newopts = @trace_opts.dup
opts.each_byte{|c| newopts += c.chr unless newopts.index(c)}
if newopts != @trace_opts
Tk.tk_call('trace', 'vdelete', @id, @trace_opts, 'rb_var')
@trace_opts.replace(newopts)
Tk.tk_call('trace', 'variable', @id, @trace_opts, 'rb_var')
end
end
end
def trace_element(elem, opts, cmd)
@trace_elem = {} if @trace_elem == nil
@trace_elem[elem] = [] if @trace_elem[elem] == nil
opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
@trace_elem[elem].unshift([opts,cmd])
if @trace_opts == nil
TkVar_CB_TBL[@id] = self
@trace_opts = opts
Tk.tk_call('trace', 'variable', @id, @trace_opts, 'rb_var')
else
newopts = @trace_opts.dup
opts.each_byte{|c| newopts += c.chr unless newopts.index(c)}
if newopts != @trace_opts
Tk.tk_call('trace', 'vdelete', @id, @trace_opts, 'rb_var')
@trace_opts.replace(newopts)
Tk.tk_call('trace', 'variable', @id, @trace_opts, 'rb_var')
end
end
end
def trace_vinfo
return [] unless @trace_var
@trace_var.dup
end
def trace_vinfo_for_element(elem)
return [] unless @trace_elem
return [] unless @trace_elem[elem]
@trace_elem[elem].dup
end
def trace_vdelete(opts,cmd)
return unless @trace_var.kind_of? Array
opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
idx = -1
newopts = ''
@trace_var.each_with_index{|i,e|
if idx < 0 && e[0] == opts && e[1] == cmd
idx = i
next
end
e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
}
if idx >= 0
@trace_var.delete_at(idx)
else
return
end
@trace_elem.each{|elem|
@trace_elem[elem].each{|e|
e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
}
}
newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('')
if newopts != @trace_opts
Tk.tk_call('trace', 'vdelete', @id, @trace_opts, 'rb_var')
@trace_opts.replace(newopts)
if @trace_opts != ''
Tk.tk_call('trace', 'variable', @id, @trace_opts, 'rb_var')
end
end
end
def trace_vdelete_for_element(elem,opts,cmd)
return unless @trace_elem.kind_of? Hash
return unless @trace_elem[elem].kind_of? Array
opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
idx = -1
@trace_elem[elem].each_with_index{|i,e|
if idx < 0 && e[0] == opts && e[1] == cmd
idx = i
next
end
}
if idx >= 0
@trace_elem[elem].delete_at(idx)
else
return
end
newopts = ''
@trace_var.each{|e|
e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
}
@trace_elem.each{|elem|
@trace_elem[elem].each{|e|
e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
}
}
newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('')
if newopts != @trace_opts
Tk.tk_call('trace', 'vdelete', @id, @trace_opts, 'rb_var')
@trace_opts.replace(newopts)
if @trace_opts != ''
Tk.tk_call('trace', 'variable', @id, @trace_opts, 'rb_var')
end
end
end
end
class TkVarAccess<TkVariable
def initialize(varname, val=nil)
@id = varname
if val
s = '"' + _get_eval_string(val).gsub(/[][$"]/, '\\\\\&') + '"' #"
INTERP._eval(format('global %s; set %s %s', @id, @id, s))
end
end
end
module TkSelection
include Tk
extend Tk
def clear(win=Tk.root)
tk_call 'selection', 'clear', win.path
end
def get(type=None)
tk_call 'selection', 'get', type
end
def TkSelection.handle(win, func, type=None, format=None)
tk_call 'selection', 'handle', win.path, func, type, format
end
def handle(func, type=None, format=None)
TkSelection.handle self, func, type, format
end
def TkSelection.own(win=None, func=None)
window(tk_call 'selection', 'own', win, func)
end
def own(func=None)
TkSelection.own self, func
end
module_function :clear, :get
end
module TkKinput
include Tk
extend Tk
def TkKinput.start(window, style=None)
tk_call 'kinput_start', window.path, style
end
def kinput_start(style=None)
TkKinput.start(self, style)
end
def TkKinput.send_spot(window)
tk_call 'kinput_send_spot', window.path
end
def kinput_send_spot
TkKinput.send_spot(self)
end
def TkKinput.input_start(window, keys=nil)
tk_call 'kanjiInput', 'start', window.path, *hash_kv(keys)
end
def kanji_input_start(keys=nil)
TkKinput.input_start(self, keys)
end
def TkKinput.attribute_config(window, slot, value=None)
if slot.kind_of? Hash
tk_call 'kanjiInput', 'attribute', window.path, *hash_kv(slot)
else
tk_call 'kanjiInput', 'attribute', window.path, "-#{slot}", value
end
end
def kinput_attribute_config(slot, value=None)
TkKinput.attribute_config(self, slot, value)
end
def TkKinput.attribute_info(window, slot=nil)
if slot
conf = tk_split_list(tk_call('kanjiInput', 'attribute',
window.path, "-#{slot}"))
conf[0] = conf[0][1..-1]
conf
else
tk_split_list(tk_call('kanjiInput', 'attribute',
window.path)).collect{|conf|
conf[0] = conf[0][1..-1]
conf
}
end
end
def kinput_attribute_info(slot=nil)
TkKinput.attribute_info(self, slot)
end
def TkKinput.input_end(window)
tk_call 'kanjiInput', 'end', window.path
end
def kanji_input_end
TkKinput.input_end(self)
end
end
module TkXIM
include Tk
extend Tk
def TkXIM.useinputmethods(window=nil, value=nil)
if window
if value
tk_call 'tk', 'useinputmethods', '-displayof', window.path, value
else
tk_call 'tk', 'useinputmethods', '-displayof', window.path
end
else
if value
tk_call 'tk', 'useinputmethods', value
else
tk_call 'tk', 'useinputmethods'
end
end
end
def TkXIM.configure(window, slot, value=None)
begin
if /^8\.*/ === Tk::TK_VERSION && JAPANIZED_TK
if slot.kind_of? Hash
tk_call 'imconfigure', window.path, *hash_kv(slot)
else
tk_call 'imconfigure', window.path, "-#{slot}", value
end
end
rescue
end
end
def TkXIM.configinfo(window, slot=nil)
begin
if /^8\.*/ === Tk::TK_VERSION && JAPANIZED_TK
if slot
conf = tk_split_list(tk_call('imconfigure', window.path, "-#{slot}"))
conf[0] = conf[0][1..-1]
conf
else
tk_split_list(tk_call('imconfigure', window.path)).collect{|conf|
conf[0] = conf[0][1..-1]
conf
}
end
else
[]
end
rescue
[]
end
end
def useinputmethods(value=nil)
TkXIM.useinputmethods(self, value=nil)
end
def imconfigure(window, slot, value=None)
TkXIM.configinfo(window, slot, value)
end
def imconfiginfo(slot=nil)
TkXIM.configinfo(window, slot)
end
end
module TkXIM
include Tk
extend Tk
def TkXIM.useinputmethods(window=nil,value=nil)
if window
if value
tk_call 'tk', 'useinputmethods', '-displayof', window.path, value
else
tk_call 'tk', 'useinputmethods', '-displayof', window.path
end
else
if value
tk_call 'tk', 'useinputmethods', value
else
tk_call 'tk', 'useinputmethods'
end
end
end
def useinputmethods(value=nil)
TkXIM.useinputmethods(self,value)
end
end
module TkWinfo
include Tk
extend Tk
def TkWinfo.atom(name)
number(tk_call 'winfo', 'atom', name)
end
def winfo_atom(name)
TkWinfo.atom name
end
def TkWinfo.atomname(id)
tk_call 'winfo', 'atomname', id
end
def winfo_atomname(id)
TkWinfo.atomname id
end
def TkWinfo.cells(window)
number(tk_call('winfo', 'cells', window.path))
end
def winfo_cells
TkWinfo.cells self
end
def TkWinfo.children(window)
c = tk_call('winfo', 'children', window.path)
list(c)
end
def winfo_children
TkWinfo.children self
end
def TkWinfo.classname(window)
tk_call 'winfo', 'class', window.path
end
def winfo_classname
TkWinfo.classname self
end
def TkWinfo.colormapfull(window)
bool(tk_call('winfo', 'colormapfull', window.path))
end
def winfo_colormapfull
TkWinfo.colormapfull self
end
def TkWinfo.containing(rootX, rootY)
path = tk_call('winfo', 'containing', rootX, rootY)
window(path)
end
def winfo_containing(x, y)
TkWinfo.containing x, y
end
def TkWinfo.depth(window)
number(tk_call('winfo', 'depth', window.path))
end
def winfo_depth
TkWinfo.depth self
end
def TkWinfo.exist?(window)
bool(tk_call('winfo', 'exists', window.path))
end
def winfo_exist?
TkWinfo.exist? self
end
def TkWinfo.fpixels(window, number)
number(tk_call('winfo', 'fpixels', window.path, number))
end
def winfo_fpixels(number)
TkWinfo.fpixels self, number
end
def TkWinfo.geometry(window)
tk_call('winfo', 'geometry', window.path)
end
def winfo_geometry
TkWinfo.geometry self
end
def TkWinfo.height(window)
number(tk_call('winfo', 'height', window.path))
end
def winfo_height
TkWinfo.height self
end
def TkWinfo.id(window)
tk_call('winfo', 'id', window.path)
end
def winfo_id
TkWinfo.id self
end
def TkWinfo.interps(window=nil)
if window
tk_split_simplelist(tk_call('winfo', 'interps',
'-displayof', window.path))
else
tk_split_simplelist(tk_call('winfo', 'interps'))
end
end
def winfo_interps
TkWinfo.interps self
end
def TkWinfo.mapped?(window)
bool(tk_call('winfo', 'ismapped', window.path))
end
def winfo_mapped?
TkWinfo.mapped? self
end
def TkWinfo.manager(window)
tk_call('winfo', 'manager', window.path)
end
def winfo_manager
TkWinfo.manager self
end
def TkWinfo.appname(window)
tk_call('winfo', 'name', window.path)
end
def winfo_appname
TkWinfo.appname self
end
def TkWinfo.parent(window)
window(tk_call('winfo', 'parent', window.path))
end
def winfo_parent
TkWinfo.parent self
end
def TkWinfo.widget(id)
window(tk_call('winfo', 'pathname', id))
end
def winfo_widget(id)
TkWinfo.widget id
end
def TkWinfo.pixels(window, number)
number(tk_call('winfo', 'pixels', window.path, number))
end
def winfo_pixels(number)
TkWinfo.pixels self, number
end
def TkWinfo.reqheight(window)
number(tk_call('winfo', 'reqheight', window.path))
end
def winfo_reqheight
TkWinfo.reqheight self
end
def TkWinfo.reqwidth(window)
number(tk_call('winfo', 'reqwidth', window.path))
end
def winfo_reqwidth
TkWinfo.reqwidth self
end
def TkWinfo.rgb(window, color)
list(tk_call('winfo', 'rgb', window.path, color))
end
def winfo_rgb(color)
TkWinfo.rgb self, color
end
def TkWinfo.rootx(window)
number(tk_call('winfo', 'rootx', window.path))
end
def winfo_rootx
TkWinfo.rootx self
end
def TkWinfo.rooty(window)
number(tk_call('winfo', 'rooty', window.path))
end
def winfo_rooty
TkWinfo.rooty self
end
def TkWinfo.screen(window)
tk_call 'winfo', 'screen', window.path
end
def winfo_screen
TkWinfo.screen self
end
def TkWinfo.screencells(window)
number(tk_call('winfo', 'screencells', window.path))
end
def winfo_screencells
TkWinfo.screencells self
end
def TkWinfo.screendepth(window)
number(tk_call('winfo', 'screendepth', window.path))
end
def winfo_screendepth
TkWinfo.screendepth self
end
def TkWinfo.screenheight (window)
number(tk_call('winfo', 'screenheight', window.path))
end
def winfo_screenheight
TkWinfo.screenheight self
end
def TkWinfo.screenmmheight(window)
number(tk_call('winfo', 'screenmmheight', window.path))
end
def winfo_screenmmheight
TkWinfo.screenmmheight self
end
def TkWinfo.screenmmwidth(window)
number(tk_call('winfo', 'screenmmwidth', window.path))
end
def winfo_screenmmwidth
TkWinfo.screenmmwidth self
end
def TkWinfo.screenvisual(window)
tk_call 'winfo', 'screenvisual', window.path
end
def winfo_screenvisual
TkWinfo.screenvisual self
end
def TkWinfo.screenwidth(window)
number(tk_call('winfo', 'screenwidth', window.path))
end
def winfo_screenwidth
TkWinfo.screenwidth self
end
def TkWinfo.server(window)
tk_call 'winfo', 'server', window.path
end
def winfo_server
TkWinfo.server self
end
def TkWinfo.toplevel(window)
window(tk_call('winfo', 'toplevel', window.path))
end
def winfo_toplevel
TkWinfo.toplevel self
end
def TkWinfo.visual(window)
tk_call 'winfo', 'visual', window.path
end
def winfo_visual
TkWinfo.visual self
end
def TkWinfo.visualid(window)
tk_call 'winfo', 'visualid', window.path
end
def winfo_visualid
TkWinfo.visualid self
end
def TkWinfo.visualsavailable(window, includeids=false)
if includeids
v = tk_call('winfo', 'visualsavailable', window.path, "includeids")
else
v = tk_call('winfo', 'visualsavailable', window.path)
end
list(v)
end
def winfo_visualsavailable(includeids=false)
TkWinfo.visualsavailable self, includeids
end
def TkWinfo.vrootheight(window)
number(tk_call('winfo', 'vrootheight', window.path))
end
def winfo_vrootheight
TkWinfo.vrootheight self
end
def TkWinfo.vrootwidth(window)
number(tk_call('winfo', 'vrootwidth', window.path))
end
def winfo_vrootwidth
TkWinfo.vrootwidth self
end
def TkWinfo.vrootx(window)
number(tk_call('winfo', 'vrootx', window.path))
end
def winfo_vrootx
TkWinfo.vrootx self
end
def TkWinfo.vrooty(window)
number(tk_call('winfo', 'vrooty', window.path))
end
def winfo_vrooty
TkWinfo.vrooty self
end
def TkWinfo.width(window)
number(tk_call('winfo', 'width', window.path))
end
def winfo_width
TkWinfo.width self
end
def TkWinfo.x(window)
number(tk_call('winfo', 'x', window.path))
end
def winfo_x
TkWinfo.x self
end
def TkWinfo.y(window)
number(tk_call('winfo', 'y', window.path))
end
def winfo_y
TkWinfo.y self
end
def TkWinfo.viewable(window)
bool(tk_call 'winfo', 'viewable', window.path)
end
def winfo_viewable
TkWinfo.viewable self
end
def TkWinfo.pointerx(window)
number(tk_call('winfo', 'pointerx', window.path))
end
def winfo_pointerx
TkWinfo.pointerx self
end
def TkWinfo.pointery(window)
number(tk_call('winfo', 'pointery', window.path))
end
def winfo_pointery
TkWinfo.pointery self
end
def TkWinfo.pointerxy(window)
list(tk_call('winfo', 'pointerxy', window.path))
end
def winfo_pointerxy
TkWinfo.pointerxy self
end
end
module TkPack
include Tk
extend Tk
def configure(win, *args)
if args[-1].kind_of?(Hash)
keys = args.pop
end
wins = [win.epath]
for i in args
wins.push i.epath
end
tk_call "pack", 'configure', *(wins+hash_kv(keys))
end
def forget(*args)
tk_call 'pack', 'forget' *args
end
def propagate(master, bool=None)
bool(tk_call('pack', 'propagate', master.epath, bool))
end
module_function :configure, :forget, :propagate
end
module TkGrid
include Tk
extend Tk
def bbox(*args)
list(tk_call('grid', 'bbox', *args))
end
def configure(widget, *args)
if args[-1].kind_of?(Hash)
keys = args.pop
end
wins = [widget.epath]
for i in args
wins.push i.epath
end
tk_call "grid", 'configure', *(wins+hash_kv(keys))
end
def columnconfigure(master, index, args)
tk_call "grid", 'columnconfigure', master, index, *hash_kv(args)
end
def rowconfigure(master, index, args)
tk_call "grid", 'rowconfigure', master, index, *hash_kv(args)
end
def add(widget, *args)
configure(widget, *args)
end
def forget(*args)
tk_call 'grid', 'forget', *args
end
def info(slave)
list(tk_call('grid', 'info', slave))
end
def location(master, x, y)
list(tk_call('grid', 'location', master, x, y))
end
def propagate(master, bool=None)
bool(tk_call('grid', 'propagate', master.epath, bool))
end
def remove(*args)
tk_call 'grid', 'remove', *args
end
def size(master)
tk_call 'grid', 'size', master
end
def slaves(args)
list(tk_call('grid', 'slaves', *hash_kv(args)))
end
module_function :bbox, :forget, :propagate, :info
module_function :remove, :size, :slaves, :location
module_function :configure, :columnconfigure, :rowconfigure
end
module TkOption
include Tk
extend Tk
def add pat, value, pri=None
tk_call 'option', 'add', pat, value, pri
end
def clear
tk_call 'option', 'clear'
end
def get win, name, klass
tk_call 'option', 'get', win ,name, klass
end
def readfile file, pri=None
tk_call 'option', 'readfile', file, pri
end
module_function :add, :clear, :get, :readfile
end
module TkTreatFont
def font_configinfo
ret = TkFont.used_on(self.path)
if ret == nil
ret = TkFont.init_widget_font(self.path, self.path, 'configure')
end
ret
end
alias fontobj font_configinfo
def font_configure(slot)
if (fnt = slot.delete('font'))
if fnt.kind_of? TkFont
return fnt.call_font_configure(self.path, self.path,'configure',slot)
else
latinfont_configure(fnt) if fnt
end
end
if (ltn = slot.delete('latinfont'))
latinfont_configure(ltn) if ltn
end
if (ltn = slot.delete('asciifont'))
latinfont_configure(ltn) if ltn
end
if (knj = slot.delete('kanjifont'))
kanjifont_configure(knj) if knj
end
tk_call(self.path, 'configure', *hash_kv(slot)) if slot != {}
self
end
def latinfont_configure(ltn, keys=nil)
fobj = fontobj
if ltn.kind_of? TkFont
conf = {}
ltn.latin_configinfo.each{|key,val| conf[key] = val}
if keys
fobj.latin_configure(conf.update(keys))
else
fobj.latin_configure(conf)
end
else
fobj.latin_replace(ltn)
end
end
alias asciifont_configure latinfont_configure
def kanjifont_configure(knj, keys=nil)
fobj = fontobj
if knj.kind_of? TkFont
conf = {}
knj.kanji_configinfo.each{|key,val| conf[key] = val}
if keys
fobj.kanji_configure(conf.update(keys))
else
fobj.kanji_configure(cond)
end
else
fobj.kanji_replace(knj)
end
end
def font_copy(window, tag=nil)
if tag
window.tagfontobj(tag).configinfo.each{|key,value|
fontobj.configure(key,value)
}
fontobj.replace(window.tagfontobj(tag).latin_font,
window.tagfontobj(tag).kanji_font)
else
window.fontobj.configinfo.each{|key,value|
fontobj.configure(key,value)
}
fontobj.replace(window.fontobj.latin_font, window.fontobj.kanji_font)
end
end
def latinfont_copy(window, tag=nil)
if tag
fontobj.latin_replace(window.tagfontobj(tag).latin_font)
else
fontobj.latin_replace(window.fontobj.latin_font)
end
end
alias asciifont_copy latinfont_copy
def kanjifont_copy(window, tag=nil)
if tag
fontobj.kanji_replace(window.tagfontobj(tag).kanji_font)
else
fontobj.kanji_replace(window.fontobj.kanji_font)
end
end
end
class TkObject<TkKernel
include Tk
include TkTreatFont
include TkBindCore
def path
return @path
end
def epath
return @path
end
def to_eval
@path
end
def tk_send(cmd, *rest)
tk_call path, cmd, *rest
end
private :tk_send
def method_missing(id, *args)
name = id.id2name
case args.length
when 1
configure name, args[0]
when 0
begin
cget name
rescue
fail NameError, "undefined local variable or method `#{name}' for #{self.to_s}", error_at
end
else
fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at
end
end
def [](id)
cget id
end
def []=(id, val)
configure id, val
end
def cget(slot)
tk_tcl2ruby tk_call path, 'cget', "-#{slot}"
end
def configure(slot, value=None)
if slot.kind_of? Hash
if (slot['font'] || slot['kanjifont'] ||
slot['latinfont'] || slot['asciifont'] )
font_configure(slot.dup)
else
tk_call path, 'configure', *hash_kv(slot)
end
else
if (slot == 'font' || slot == 'kanjifont' ||
slot == 'latinfont' || slot == 'asciifont')
if value == None
fontobj
else
font_configure({slot=>value})
end
else
tk_call path, 'configure', "-#{slot}", value
end
end
end
def configure_cmd(slot, value)
configure slot, install_cmd(value)
end
def configinfo(slot = nil)
if slot == 'font' || slot == 'kanjifont'
fontobj
else
if slot
conf = tk_split_list(tk_send('configure', "-#{slot}") )
conf[0] = conf[0][1..-1]
conf
else
ret = tk_split_list(tk_send('configure') ).collect{|conf|
conf[0] = conf[0][1..-1]
conf
}
if ret.assoc('font')
ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'}
ret.push(['font', fontobj])
else
ret
end
end
end
end
def event_generate(context, keys=nil)
if keys
tk_call('event', 'generate', path,
"<#{tk_event_sequence(context)}>", *hash_kv(keys))
else
tk_call('event', 'generate', path, "<#{tk_event_sequence(context)}>")
end
end
def tk_trace_variable(v)
unless v.kind_of?(TkVariable)
fail ArgumentError, format("requires TkVariable given %s", v.type)
end
v
end
private :tk_trace_variable
def destroy
tk_call 'trace', 'vdelete', @tk_vn, 'w', @var_id if @var_id
end
end
class TkWindow<TkObject
extend TkBindCore
def initialize(parent=nil, keys=nil)
install_win(if parent then parent.path end)
create_self
if keys
# tk_call @path, 'configure', *hash_kv(keys)
configure(keys)
end
end
def create_self
end
private :create_self
def pack(keys = nil)
tk_call 'pack', epath, *hash_kv(keys)
self
end
def unpack
tk_call 'pack', 'forget', epath
self
end
def grid(keys = nil)
tk_call 'grid', epath, *hash_kv(keys)
self
end
def ungrid
tk_call 'grid', 'forget', epath
self
end
def place(keys = nil)
tk_call 'place', epath, *hash_kv(keys)
self
end
def unplace
tk_call 'place', 'forget', epath
self
end
alias place_forget unplace
def place_config(keys)
tk_call "place", 'configure', epath, *hash_kv(keys)
end
def place_info()
ilist = list(tk_call('place', 'info', epath))
info = {}
while key = ilist.shift
info[key[1..-1]] = ilist.shift
end
return info
end
def pack_slaves()
list(tk_call('pack', 'slaves', epath))
end
def pack_info()
ilist = list(tk_call('pack', 'info', epath))
info = {}
while key = ilist.shift
info[key[1..-1]] = ilist.shift
end
return info
end
def place_slaves()
list(tk_call('place', 'slaves', epath))
end
def focus(force=false)
if force
tk_call 'focus', '-force', path
else
tk_call 'focus', path
end
self
end
def grab(*args)
if !args or args.length == 0
tk_call 'grab', 'set', path
elsif args.length == 1
case args[0]
when 'global'
tk_call 'grab', 'set', '-global', path
else
val = tk_call('grab', args[0], path)
end
case args[0]
when 'current'
return window(val)
when 'status'
return val
end
else
fail ArgumentError, 'wrong # of args'
end
end
def lower(below=None)
tk_call 'lower', epath, below
self
end
def raise(above=None)
tk_call 'raise', epath, above
self
end
def command(cmd=Proc.new)
configure_cmd 'command', cmd
end
def colormodel model=None
tk_call 'tk', 'colormodel', path, model
self
end
def destroy
tk_call 'destroy', epath
if @cmdtbl
for id in @cmdtbl
uninstall_cmd id
end
end
uninstall_win
end
def wait_visibility
tk_call 'tkwait', 'visibility', path
end
alias wait wait_visibility
def wait_destroy
tk_call 'tkwait', 'window', epath
end
def bindtags(taglist=nil)
if taglist
fail unless taglist.kind_of? Array
tk_call('bindtags', path, taglist)
else
list(tk_call('bindtags', path)).collect{|tag|
if tag.kind_of?(String)
if cls = WidgetClassNames[tag]
cls
elsif btag = TkBindTag.id2obj(tag)
btag
else
tag
end
else
tag
end
}
end
end
end
class TkRoot<TkWindow
include Wm
ROOT = []
def TkRoot.new
return ROOT[0] if ROOT[0]
new = super
ROOT[0] = new
Tk_WINDOWS["."] = new
end
WidgetClassName = 'Tk'.freeze
WidgetClassNames[WidgetClassName] = self
def self.to_eval
WidgetClassName
end
def create_self
@path = '.'
end
def path
"."
end
end
class TkToplevel<TkWindow
include Wm
WidgetClassName = 'Toplevel'.freeze
WidgetClassNames[WidgetClassName] = self
def self.to_eval
WidgetClassName
end
def initialize(parent=nil, screen=nil, classname=nil, keys=nil)
if screen.kind_of? Hash
keys = screen.dup
else
@screen = screen
end
@classname = classname
if keys.kind_of? Hash
keys = keys.dup
@classname = keys.delete('classname') if keys.key?('classname')
@colormap = keys.delete('colormap') if keys.key?('colormap')
@container = keys.delete('container') if keys.key?('container')
@screen = keys.delete('screen') if keys.key?('screen')
@use = keys.delete('use') if keys.key?('use')
@visual = keys.delete('visual') if keys.key?('visual')
end
super(parent, keys)
end
def create_self
s = []
s << "-class" << @classname if @classname
s << "-colormap" << @colormap if @colormap
s << "-container" << @container if @container
s << "-screen" << @screen if @screen
s << "-use" << @use if @use
s << "-visual" << @visual if @visual
tk_call 'toplevel', @path, *s
end
def specific_class
@classname
end
end
class TkFrame<TkWindow
WidgetClassName = 'Frame'.freeze
WidgetClassNames[WidgetClassName] = self
def self.to_eval
WidgetClassName
end
def initialize(parent=nil, keys=nil)
if keys.kind_of? Hash
keys = keys.dup
@classname = keys.delete('classname') if keys.key?('classname')
@colormap = keys.delete('colormap') if keys.key?('colormap')
@container = keys.delete('container') if keys.key?('container')
@visual = keys.delete('visual') if keys.key?('visual')
end
super(parent, keys)
end
def create_self
s = []
s << "-class" << @classname if @classname
s << "-colormap" << @colormap if @colormap
s << "-container" << @container if @container
s << "-visual" << @visual if @visual
tk_call 'frame', @path, *s
end
end
class TkLabel<TkWindow
WidgetClassName = 'Label'.freeze
WidgetClassNames[WidgetClassName] = self
def self.to_eval
WidgetClassName
end
def create_self
tk_call 'label', @path
end
def textvariable(v)
configure 'textvariable', tk_trace_variable(v)
end
end
class TkButton<TkLabel
WidgetClassNames['Button'] = self
def TkButton.to_eval
'Button'
end
def create_self
tk_call 'button', @path
end
def invoke
tk_send 'invoke'
end
def flash
tk_send 'flash'
end
end
class TkRadiobutton<TkButton
WidgetClassNames['Radiobutton'] = self
def TkRadiobutton.to_eval
'Radiobutton'
end
def create_self
tk_call 'radiobutton', @path
end
def deselect
tk_send 'deselect'
end
def select
tk_send 'select'
end
def variable(v)
configure 'variable', tk_trace_variable(v)
end
end
tkRadioButton = TkRadiobutton
class TkCheckbutton<TkRadiobutton
WidgetClassNames['Checkbutton'] = self
def TkCheckbutton.to_eval
'Checkbutton'
end
def create_self
tk_call 'checkbutton', @path
end
def toggle
tk_send 'toggle'
end
end
TkCheckButton = TkCheckbutton
class TkMessage<TkLabel
WidgetClassNames['Message'] = self
def TkMessage.to_eval
'Message'
end
def create_self
tk_call 'message', @path
end
end
class TkScale<TkWindow
WidgetClassName = 'Scale'.freeze
WidgetClassNames[WidgetClassName] = self
def self.to_eval
WidgetClassName
end
def create_self
tk_call 'scale', path
end
def get
number(tk_send('get'))
end
def set(val)
tk_send "set", val
end
def value
get
end
def value= (val)
set val
end
end
class TkScrollbar<TkWindow
WidgetClassName = 'Scrollbar'.freeze
WidgetClassNames[WidgetClassName] = self
def self.to_eval
WidgetClassName
end
def create_self
tk_call 'scrollbar', path
end
def delta(deltax=None, deltay=None)
number(tk_send('delta', deltax, deltay))
end
def fraction(x=None, y=None)
number(tk_send('fraction', x, y))
end
def identify(x=None, y=None)
tk_send('fraction', x, y)
end
def get
ary1 = tk_send('get').split
ary2 = []
for i in ary1
ary2.push number(i)
end
ary2
end
def set(first, last)
tk_send "set", first, last
end
end
class TkTextWin<TkWindow
def create_self
fail TypeError, "TkTextWin is abstract class"
end
def bbox(index)
tk_send 'bbox', index
end
def delete(first, last=None)
tk_send 'delete', first, last
end
def get(*index)
tk_send 'get', *index
end
def index(index)
tk_send 'index', index
end
def insert(index, chars, *args)
tk_send 'insert', index, chars, *args
end
def scan_mark(x, y)
tk_send 'scan', 'mark', x, y
end
def scan_dragto(x, y)
tk_send 'scan', 'dragto', x, y
end
def see(index)
tk_send 'see', index
end
end
class TkListbox<TkTextWin
include Scrollable
WidgetClassNames['Listbox'] = self
def TkListbox.to_eval
'Listbox'
end
def create_self
tk_call 'listbox', path
end
def activate(y)
tk_send 'activate', y
end
def curselection
list(tk_send('curselection'))
end
def get(*index)
v = tk_send('get', *index)
if index.size == 1
v
else
tk_split_simplelist(v)
end
end
def nearest(y)
tk_send('nearest', y).to_i
end
def size
tk_send('size').to_i
end
def selection_anchor(index)
tk_send 'selection', 'anchor', index
end
def selection_clear(first, last=None)
tk_send 'selection', 'clear', first, last
end
def selection_includes(index)
bool(tk_send('selection', 'includes', index))
end
def selection_set(first, last=None)
tk_send 'selection', 'set', first, last
end
def itemcget(index, key)
tk_tcl2ruby tk_send 'itemcget', index, "-#{key}"
end
def itemconfigure(index, key, val=None)
if key.kind_of? Hash
if (key['font'] || key['kanjifont'] ||
key['latinfont'] || key['asciifont'])
tagfont_configure(index, key.dup)
else
tk_send 'itemconfigure', index, *hash_kv(key)
end
else
if (key == 'font' || key == 'kanjifont' ||
key == 'latinfont' || key == 'asciifont' )
tagfont_configure({key=>val})
else
tk_call 'itemconfigure', index, "-#{key}", val
end
end
end
def itemconfiginfo(index, key=nil)
if key
conf = tk_split_list(tk_send('itemconfigure',index,"-#{key}"))
conf[0] = conf[0][1..-1]
conf
else
tk_split_list(tk_send('itemconfigure', index)).collect{|conf|
conf[0] = conf[0][1..-1]
conf
}
end
end
end
module TkTreatMenuEntryFont
def tagfont_configinfo(index)
pathname = self.path + ';' + index
ret = TkFont.used_on(pathname)
if ret == nil
ret = TkFont.init_widget_font(pathname,
self.path, 'entryconfigure', index)
end
ret
end
alias tagfontobj tagfont_configinfo
def tagfont_configure(index, slot)
pathname = self.path + ';' + index
if (fnt = slot.delete('font'))
if fnt.kind_of? TkFont
return fnt.call_font_configure(pathname,
self.path,'entryconfigure',index,slot)
else
latintagfont_configure(index, fnt) if fnt
end
end
if (ltn = slot.delete('latinfont'))
latintagfont_configure(index, ltn) if ltn
end
if (ltn = slot.delete('asciifont'))
latintagfont_configure(index, ltn) if ltn
end
if (knj = slot.delete('kanjifont'))
kanjitagfont_configure(index, knj) if knj
end
tk_call(self.path, 'entryconfigure', index, *hash_kv(slot)) if slot != {}
self
end
def latintagfont_configure(index, ltn, keys=nil)
fobj = tagfontobj(index)
if ltn.kind_of? TkFont
conf = {}
ltn.latin_configinfo.each{|key,val| conf[key] = val if val != []}
if conf == {}
fobj.latin_replace(ltn)
fobj.latin_configure(keys) if keys
elsif keys
fobj.latin_configure(conf.update(keys))
else
fobj.latin_configure(conf)
end
else
fobj.latin_replace(ltn)
end
end
alias asciitagfont_configure latintagfont_configure
def kanjitagfont_configure(index, knj, keys=nil)
fobj = tagfontobj(index)
if knj.kind_of? TkFont
conf = {}
knj.kanji_configinfo.each{|key,val| conf[key] = val if val != []}
if conf == {}
fobj.kanji_replace(knj)
fobj.kanji_configure(keys) if keys
elsif keys
fobj.kanji_configure(conf.update(keys))
else
fobj.kanji_configure(conf)
end
else
fobj.kanji_replace(knj)
end
end
def tagfont_copy(index, window, wintag=nil)
if wintag
window.tagfontobj(wintag).configinfo.each{|key,value|
tagfontobj(index).configure(key,value)
}
tagfontobj(index).replace(window.tagfontobj(wintag).latin_font,
window.tagfontobj(wintag).kanji_font)
else
window.tagfont(wintag).configinfo.each{|key,value|
tagfontobj(index).configure(key,value)
}
tagfontobj(index).replace(window.fontobj.latin_font,
window.fontobj.kanji_font)
end
end
def latintagfont_copy(index, window, wintag=nil)
if wintag
tagfontobj(index).latin_replace(window.tagfontobj(wintag).latin_font)
else
tagfontobj(index).latin_replace(window.fontobj.latin_font)
end
end
alias asciitagfont_copy latintagfont_copy
def kanjitagfont_copy(index, window, wintag=nil)
if wintag
tagfontobj(index).kanji_replace(window.tagfontobj(wintag).kanji_font)
else
tagfontobj(index).kanji_replace(window.fontobj.kanji_font)
end
end
end
class TkMenu<TkWindow
include TkTreatMenuEntryFont
WidgetClassName = 'Menu'.freeze
WidgetClassNames[WidgetClassName] = self
def self.to_eval
WidgetClassName
end
def create_self
tk_call 'menu', path
end
def activate(index)
tk_send 'activate', index
end
def add(type, keys=nil)
tk_send 'add', type, *hash_kv(keys)
end
def index(index)
tk_send 'index', index
end
def invoke(index)
tk_send 'invoke', index
end
def insert(index, type, keys=nil)
tk_send 'add', index, type, *hash_kv(keys)
end
def delete(index, last=None)
tk_send 'delete', index, last
end
def popup(x, y, index=nil)
tk_call 'tk_popup', path, x, y, index
end
def post(x, y)
tk_send 'post', x, y
end
def postcascade(index)
tk_send 'postcascade', index
end
def postcommand(cmd=Proc.new)
configure_cmd 'postcommand', cmd
end
def menutype(index)
tk_send 'type', index
end
def unpost
tk_send 'unpost'
end
def yposition(index)
number(tk_send('yposition', index))
end
def entrycget(index, key)
tk_tcl2ruby tk_send 'entrycget', index, "-#{key}"
end
def entryconfigure(index, key, val=None)
if key.kind_of? Hash
if (key['font'] || key['kanjifont'] ||
key['latinfont'] || key['asciifont'])
tagfont_configure(index, key.dup)
else
tk_send 'entryconfigure', index, *hash_kv(key)
end
else
if (key == 'font' || key == 'kanjifont' ||
key == 'latinfont' || key == 'asciifont' )
tagfont_configure({key=>val})
else
tk_call 'entryconfigure', index, "-#{key}", val
end
end
end
def entryconfiginfo(index, key=nil)
if key
conf = tk_split_list(tk_send('entryconfigure',index,"-#{key}"))
conf[0] = conf[0][1..-1]
conf
else
tk_split_list(tk_send('entryconfigure', index)).collect{|conf|
conf[0] = conf[0][1..-1]
conf
}
end
end
end
module TkSystemMenu
def initialize(parent, keys=nil)
fail unless parent.kind_of? TkMenu
@path = format("%s.%s", parent.path, self.type::SYSMENU_NAME)
TkComm::Tk_WINDOWS[@path] = self
create_self
configure(keys) if keys
end
end
class TkSysMenu_Help<TkMenu
# for all platform
include TkSystemMenu
SYSMENU_NAME = 'help'
end
class TkSysMenu_System<TkMenu
# for Windows
include TkSystemMenu
SYSMENU_NAME = 'system'
end
class TkSysMenu_Apple<TkMenu
# for Machintosh
include TkSystemMenu
SYSMENU_NAME = 'apple'
end
class TkMenubutton<TkLabel
WidgetClassNames['Menubutton'] = self
def TkMenubutton.to_eval
'Menubutton'
end
def create_self
tk_call 'menubutton', path
end
end
class TkOptionMenubutton<TkMenubutton
class OptionMenu<TkMenu
def initialize(parent)
@path = parent.path + '.menu'
TkComm::Tk_WINDOWS[@path] = self
end
end
def initialize(parent=nil, var=TkVariable.new, firstval=nil, *vals)
fail unless var.kind_of? TkVariable
@variable = var
firstval = @variable.value unless firstval
@variable.value = firstval
install_win(if parent then parent.path end)
@menu = OptionMenu.new(self)
tk_call 'tk_optionMenu', @path, @variable.id, firstval, *vals
end
def value
@variable.value
end
def activate(index)
@menu.activate(index)
end
def add(value)
@menu.add('radiobutton', 'variable'=>@variable,
'label'=>value, 'value'=>value)
end
def index(index)
@menu.index(index)
end
def invoke(index)
@menu.invoke(index)
end
def insert(index, value)
@menu.add(index, 'radiobutton', 'variable'=>@variable,
'label'=>value, 'value'=>value)
end
def delete(index, last=None)
@menu.delete(index, last)
end
def yposition(index)
@menu.yposition(index)
end
def menucget(index, key)
@menu.cget(index, key)
end
def menuconfigure(index, key, val=None)
@menu.configure(index, key, val)
end
def menuconfiginfo(index, key=nil)
@menu.configinfo(index, key)
end
def entrycget(index, key)
@menu.entrycget(index, key)
end
def entryconfigure(index, key, val=None)
@menu.entryconfigure(index, key, val)
end
def entryconfiginfo(index, key=nil)
@menu.entryconfiginfo(index, key)
end
end
module TkComposite
include Tk
extend Tk
def initialize(parent=nil, *args)
@frame = TkFrame.new(parent)
@path = @epath = @frame.path
initialize_composite(*args)
end
def epath
@epath
end
def initialize_composite(*args) end
private :initialize_composite
def delegate(option, *wins)
unless @delegates
@delegates = {}
@delegates['DEFAULT'] = @frame
end
if @delegates[option].kind_of?(Array)
for i in wins
@delegates[option].push(i)
end
else
@delegates[option] = wins
end
end
def configure(slot, value=None)
if slot.kind_of? Hash
slot.each{|slot,value| configure slot, value}
else
if @delegates and @delegates[slot]
for i in @delegates[slot]
if not i
i = @delegates['DEFALUT']
redo
else
last = i.configure(slot, value)
end
end
last
else
super
end
end
end
end
module TkClipboard
include Tk
extend Tk
def clear
tk_call 'clipboard', 'clear'
end
def get
begin
tk_call 'selection', 'get', '-selection', 'CLIPBOARD'
rescue
''
end
end
def set(data)
clear
append(data)
end
def append(data)
tk_call 'clipboard', 'append', data
end
module_function :clear, :set, :get, :append
end
autoload :TkCanvas, 'tkcanvas'
autoload :TkImage, 'tkcanvas'
autoload :TkBitmapImage, 'tkcanvas'
autoload :TkPhotoImage, 'tkcanvas'
autoload :TkEntry, 'tkentry'
autoload :TkText, 'tktext'
autoload :TkDialog, 'tkdialog'
autoload :TkMenubar, 'tkmenubar'
autoload :TkAfter, 'tkafter'
autoload :TkPalette, 'tkpalette'
autoload :TkFont, 'tkfont'
autoload :TkVirtualEvent, 'tkvirtevent'