summaryrefslogtreecommitdiff
path: root/ext/tk/lib/tk.rb
diff options
context:
space:
mode:
Diffstat (limited to 'ext/tk/lib/tk.rb')
-rw-r--r--ext/tk/lib/tk.rb296
1 files changed, 242 insertions, 54 deletions
diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb
index bac2ae35f9..2e33c4294c 100644
--- a/ext/tk/lib/tk.rb
+++ b/ext/tk/lib/tk.rb
@@ -132,6 +132,13 @@ module TkComm
end
private :tk_tcl2ruby, :tk_split_list, :tk_split_simplelist
+ def _symbolkey2str(keys)
+ h = {}
+ keys.each{|key,value| h[key.to_s] = value}
+ h
+ end
+ private :_symbolkey2str
+
def hash_kv(keys)
conf = []
if keys and keys != None
@@ -204,6 +211,8 @@ module TkComm
return nil if str == None
if str.kind_of?(String)
# do nothing
+ elsif str.kind_of?(Symbol)
+ str = str.id2name
elsif str.kind_of?(Hash)
str = hash_kv(str).join(" ")
elsif str.kind_of?(Array)
@@ -259,13 +268,15 @@ module TkComm
end
private :install_cmd, :uninstall_cmd
- def install_win(ppath)
- id = format("w%.4d", Tk_IDs[1])
- Tk_IDs[1] += 1
+ def install_win(ppath,name=nil)
+ if !name or name == ''
+ name = format("w%.4d", Tk_IDs[1])
+ Tk_IDs[1] += 1
+ end
if !ppath or ppath == "."
- @path = format(".%s", id);
+ @path = format(".%s", name);
else
- @path = format("%s.%s", ppath, id)
+ @path = format("%s.%s", ppath, name)
end
Tk_WINDOWS[@path] = self
end
@@ -483,6 +494,8 @@ module TkCore
}
EOL
+ EventFlag = TclTkLib::EventFlag
+
def callback_break
fail TkCallbackBreak, "Tk callback returns 'break' status"
end
@@ -616,12 +629,42 @@ module TkCore
tk_call('info', *args)
end
- def mainloop
- TclTkLib.mainloop
+ def mainloop(check_root = true)
+ TclTkLib.mainloop(check_root)
end
- def restart
+ def mainloop_watchdog(check_root = true)
+ TclTkLib.mainloop_watchdog(check_root)
+ end
+
+ def do_one_event(flag = 0)
+ TclTkLib.do_one_event(flag)
+ end
+
+ def set_eventloop_tick(timer_tick)
+ TclTkLib.set_eventloop_tick(timer_tick)
+ end
+
+ def get_eventloop_tick()
+ TclTkLib.get_eventloop_tick
+ end
+
+ def set_eventloop_weight(loop_max, no_event_tick)
+ TclTkLib.set_eventloop_weight(loop_max, no_event_tick)
+ end
+
+ def get_eventloop_weight()
+ TclTkLib.get_eventloop_weight
+ end
+
+ def restart(app_name = nil, use = nil)
+ tk_call('set', 'argv0', app_name) if app_name
+ if use
+ tk_call('set', 'argc', 2)
+ tk_call('set', 'argv', "-use #{use}")
+ end
TkCore::INTERP.restart
+ TkComm::Tk_CMDTBL.clear
TkComm::Tk_WINDOWS.clear
nil
end
@@ -2077,12 +2120,87 @@ module TkOption
tk_call 'option', 'clear'
end
def get win, name, klass
- tk_call 'option', 'get', win ,name, klass
+ tk_call('option', 'get', win ,name, klass).taint
end
def readfile file, pri=None
tk_call 'option', 'readfile', file, pri
end
module_function :add, :clear, :get, :readfile
+
+ # support procs on the resource database
+ @@resource_proc_class = Class.new
+ class << @@resource_proc_class
+ private :new
+
+ CARRIER = '.'.freeze
+ METHOD_TBL = {}
+ ADD_METHOD = false
+ SAFE_MODE = 4
+
+ def __check_proc_string__(str)
+ # If you want to check the proc_string, do it in this method.
+ str
+ end
+
+ def method_missing(id, *args)
+ res_proc = self::METHOD_TBL[id]
+ unless res_proc.kind_of? Proc
+ if id == :new || (!self::METHOD_TBL.has_key?(id) && !self::ADD_METHOD)
+ raise NoMethodError,
+ "not support resource-proc '#{id.id2name}' for #{self.name}"
+ end
+ proc_str = TkOption.get(self::CARRIER, id.id2name, '')
+ proc_str = '{' + proc_str + '}' unless /\A\{.*\}\Z/ =~ proc_str
+ proc_str = __check_proc_string__(proc_str)
+ res_proc = eval 'Proc.new' + proc_str
+ self::METHOD_TBL[id] = res_proc
+ end
+ proc{
+ $SAFE = self::SAFE_MODE
+ res_proc.call(*args)
+ }.call
+ end
+
+ private :__check_proc_string__, :method_missing
+ end
+
+ def new_proc_class(klass, func, safe = 4, add = false, parent = nil)
+ klass = klass.to_s if klass.kind_of? Symbol
+ unless (?A..?Z) === klass[0]
+ fail ArgumentError, "bad string '#{klass}' for class name"
+ end
+ unless func.kind_of? Array
+ fail ArgumentError, "method-list must be Array"
+ end
+ func_str = func.join(' ')
+ if parent == nil
+ install_win(parent)
+ elsif parent <= @@resource_proc_class
+ install_win(parent::CARRIER)
+ else
+ fail ArgumentError, "parent must be Resource-Proc class"
+ end
+ carrier = Tk.tk_call('frame', @path, '-class', klass)
+
+ body = <<-"EOD"
+ class #{klass} < TkOption.module_eval('@@resource_proc_class')
+ CARRIER = '#{carrier}'.freeze
+ METHOD_TBL = {}
+ ADD_METHOD = #{add}
+ SAFE_MODE = #{safe}
+ %w(#{func_str}).each{|f| METHOD_TBL[f.intern] = nil }
+ end
+ EOD
+
+ if parent.kind_of?(Class) && parent <= @@resource_proc_class
+ parent.class_eval body
+ eval parent.name + '::' + klass
+ else
+ eval body
+ eval 'TkOption::' + klass
+ end
+ end
+ module_function :new_proc_class
end
module TkTreatFont
@@ -2096,6 +2214,7 @@ module TkTreatFont
alias fontobj font_configinfo
def font_configure(slot)
+ slot = _symbolkey2str(slot)
if (fnt = slot.delete('font'))
if fnt.kind_of? TkFont
return fnt.call_font_configure(self.path, self.path,'configure',slot)
@@ -2203,6 +2322,7 @@ module TkTreatItemFont
def tagfont_configure(tagOrId, slot)
pathname = __item_pathname(tagOrId)
+ slot = _symbolkey2str(slot)
if (fnt = slot.delete('font'))
if fnt.kind_of? TkFont
return fnt.call_font_configure(pathname, self.path,
@@ -2345,7 +2465,7 @@ class TkObject<TkKernel
end
def cget(slot)
- case slot
+ case slot.to_s
when 'text', 'label', 'show', 'data', 'file'
tk_call path, 'cget', "-#{slot}"
else
@@ -2355,16 +2475,20 @@ class TkObject<TkKernel
def configure(slot, value=None)
if slot.kind_of? Hash
- if (slot['font'] || slot['kanjifont'] ||
- slot['latinfont'] || slot['asciifont'] )
- font_configure(slot.dup)
+ if (slot['font'] || slot[:font] ||
+ slot['kanjifont'] || slot[:kanjifont] ||
+ slot['latinfont'] || slot[:latinfont] ||
+ slot['asciifont'] || slot[:asciifont] )
+ font_configure(slot)
else
tk_call path, 'configure', *hash_kv(slot)
end
else
- if (slot == 'font' || slot == 'kanjifont' ||
- slot == 'latinfont' || slot == 'asciifont')
+ if (slot == 'font' || slot == :font ||
+ slot == 'kanjifont' || slot == :kanjifont ||
+ slot == 'latinfont' || slot == :latinfont ||
+ slot == 'asciifont' || slot == :asciifont )
if value == None
fontobj
else
@@ -2381,11 +2505,12 @@ class TkObject<TkKernel
end
def configinfo(slot = nil)
- if slot == 'font' || slot == 'kanjifont'
+ if slot == 'font' || slot == :font ||
+ slot == 'kanjifont' || slot == :kanjifont
fontobj
else
if slot
- case slot
+ case slot.to_s
when 'text', 'label', 'show', 'data', 'file'
conf = tk_split_simplelist(tk_send('configure', "-#{slot}") )
else
@@ -2455,7 +2580,19 @@ class TkWindow<TkObject
extend TkBindCore
def initialize(parent=nil, keys=nil)
- install_win(if parent then parent.path end)
+ if parent.kind_of? Hash
+ keys = _symbolkey2str(parent)
+ keydup = true
+ parent = keys.delete('parent')
+ widgetname = keys.delete('widgetname')
+ install_win(if parent then parent.path end, widgetname)
+ elsif keys
+ keys = _symbolkey2str(keys)
+ widgetname = keys.delete('widgetname')
+ install_win(if parent then parent.path end, widgetname)
+ else
+ install_win(if parent then parent.path end)
+ end
if self.method(:create_self).arity == 0
p 'create_self has no arg' if $DEBUG
create_self
@@ -2464,10 +2601,9 @@ class TkWindow<TkObject
configure(keys)
end
else
- p 'create_self has an arg' if $DEBUG
+ p 'create_self has args' if $DEBUG
fontkeys = {}
if keys
- keys = keys.dup
['font', 'kanjifont', 'latinfont', 'asciifont'].each{|key|
fontkeys[key] = keys.delete(key) if keys.key?(key)
}
@@ -2668,17 +2804,17 @@ class TkWindow<TkObject
tk_call 'grab', 'set', path
elsif args.length == 1
case args[0]
- when 'global'
+ when 'global', :global
return(tk_call 'grab', 'set', '-global', path)
- when 'release'
+ when 'release', :release
return(tk_call 'grab', 'release', path)
else
val = tk_call('grab', args[0], path)
end
case args[0]
- when 'current'
+ when 'current', :current
return window(val)
- when 'status'
+ when 'status', :status
return val
end
else
@@ -2811,15 +2947,27 @@ class TkToplevel<TkWindow
#################
def initialize(parent=nil, screen=nil, classname=nil, keys=nil)
+ if parent.kind_of? Hash
+ keys = _symbolkey2str(parent)
+ @screen = keys['screen']
+ @classname = keys['class']
+ @colormap = keys['colormap']
+ @container = keys['container']
+ @screen = keys['screen']
+ @use = keys['use']
+ @visual = keys['visual']
+ super(keys)
+ return
+ end
if screen.kind_of? Hash
- keys = screen
+ keys = _symbolkey2str(screen)
else
@screen = screen
end
@classname = classname
if keys.kind_of? Hash
- if keys.key?('classname')
- keys = keys.dup
+ keys = _symbolkey2str(keys)
+ if keys.key?(:classname) || keys.key?('classname')
keys['class'] = keys.delete('classname')
end
@classname = keys['class']
@@ -2875,17 +3023,24 @@ class TkFrame<TkWindow
#################
def initialize(parent=nil, keys=nil)
- if keys.kind_of? Hash
- if keys.key?('classname')
- keys = keys.dup
- keys['class'] = keys.delete('classname')
+ if parent.kind_of? Hash
+ keys = _symbolkey2str(parent)
+ else
+ if keys
+ keys = _symbolkey2str(keys)
+ keys['parent'] = parent
+ else
+ keys = {'parent'=>parent}
end
- @classname = keys['class']
- @colormap = keys['colormap']
- @container = keys['container']
- @visual = keys['visual']
end
- super(parent, keys)
+ if keys.key?('classname')
+ keys['class'] = keys.delete('classname')
+ end
+ @classname = keys['class']
+ @colormap = keys['colormap']
+ @container = keys['container']
+ @visual = keys['visual']
+ super(keys)
end
def create_self(keys)
@@ -3170,7 +3325,7 @@ class TkListbox<TkTextWin
end
def itemcget(index, key)
- case key
+ case key.to_s
when 'text', 'label', 'show'
tk_send 'itemcget', index, "-#{key}"
else
@@ -3179,16 +3334,20 @@ class TkListbox<TkTextWin
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)
+ if (key['font'] || key[:font] ||
+ key['kanjifont'] || key[:kanjifont] ||
+ key['latinfont'] || key[:latinfont] ||
+ key['asciifont'] || key[:asciifont] )
+ tagfont_configure(index, _symbolkey2str(key))
else
tk_send 'itemconfigure', index, *hash_kv(key)
end
else
- if (key == 'font' || key == 'kanjifont' ||
- key == 'latinfont' || key == 'asciifont' )
+ if (key == 'font' || key == :font ||
+ key == 'kanjifont' || key == :kanjifont ||
+ key == 'latinfont' || key == :latinfont ||
+ key == 'asciifont' || key == :asciifont )
tagfont_configure(index, {key=>val})
else
tk_call 'itemconfigure', index, "-#{key}", val
@@ -3198,7 +3357,7 @@ class TkListbox<TkTextWin
def itemconfiginfo(index, key=nil)
if key
- case key
+ case key.to_s
when 'text', 'label', 'show'
conf = tk_split_simplelist(tk_send('itemconfigure',index,"-#{key}"))
else
@@ -3305,7 +3464,7 @@ class TkMenu<TkWindow
number(tk_send('yposition', index))
end
def entrycget(index, key)
- case key
+ case key.to_s
when 'text', 'label', 'show'
tk_send 'entrycget', index, "-#{key}"
else
@@ -3314,16 +3473,20 @@ class TkMenu<TkWindow
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)
+ if (key['font'] || key[:font] ||
+ key['kanjifont'] || key[:kanjifont] ||
+ key['latinfont'] || key[:latinfont] ||
+ key['asciifont'] || key[:asciifont])
+ tagfont_configure(index, _symbolkey2str(key))
else
tk_send 'entryconfigure', index, *hash_kv(key)
end
else
- if (key == 'font' || key == 'kanjifont' ||
- key == 'latinfont' || key == 'asciifont' )
+ if (key == 'font' || key == :font ||
+ key == 'kanjifont' || key == :kanjifont ||
+ key == 'latinfont' || key == :latinfont ||
+ key == 'asciifont' || key == :asciifont )
tagfont_configure({key=>val})
else
tk_call 'entryconfigure', index, "-#{key}", val
@@ -3333,7 +3496,7 @@ class TkMenu<TkWindow
def entryconfiginfo(index, key=nil)
if key
- case key
+ case key.to_s
when 'text', 'label', 'show'
conf = tk_split_simplelist(tk_send('entryconfigure',index,"-#{key}"))
else
@@ -3371,17 +3534,28 @@ end
class TkMenuClone<TkMenu
def initialize(parent, type=None)
+ widgetname = nil
+ if parent.kind_of? Hash
+ keys = _symbolkey2str(parent)
+ parent = keys.delete('parent')
+ widgetname = keys.delete('widgetname')
+ type = keys.delete('type'); type = None unless type
+ end
unless parent.kind_of?(TkMenu)
fail ArgumentError, "parent must be TkMenu"
end
@parent = parent
- install_win(@parent.path)
+ install_win(@parent.path, widgetname)
tk_call @parent.path, 'clone', @path, type
end
end
module TkSystemMenu
def initialize(parent, keys=nil)
+ if parent.kind_of? Hash
+ keys = _symbolkey2str(parent)
+ parent = keys.delete('parent')
+ end
fail unless parent.kind_of? TkMenu
@path = format("%s.%s", parent.path, self.type::SYSMENU_NAME)
TkComm::Tk_WINDOWS[@path] = self
@@ -3437,6 +3611,12 @@ class TkOptionMenubutton<TkMenubutton
end
def initialize(parent=nil, var=TkVariable.new, firstval=nil, *vals)
+ if parent.kind_of Hash
+ keys = _symbolkey2str(parent)
+ parent = keys['parent']
+ var = keys['variable'] if keys['variable']
+ firstval, *vals = keys['values']
+ end
fail unless var.kind_of? TkVariable
@variable = var
firstval = @variable.value unless firstval
@@ -3498,9 +3678,17 @@ module TkComposite
extend Tk
def initialize(parent=nil, *args)
- @frame = TkFrame.new(parent)
- @path = @epath = @frame.path
- initialize_composite(*args)
+ if parent.kind_of? Hash
+ keys = _symbolkey2str(parent)
+ parent = keys['parent']
+ keys['parent'] = @frame = TkFrame.new(parent)
+ @path = @epath = @frame.path
+ initialize_composite(keys)
+ else
+ @frame = TkFrame.new(parent)
+ @path = @epath = @frame.path
+ initialize_composite(*args)
+ end
end
def epath