diff options
author | nagai <nagai@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2009-07-12 23:08:32 +0000 |
---|---|---|
committer | nagai <nagai@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2009-07-12 23:08:32 +0000 |
commit | ed6ce8b43b6f25df1d4809ac799de4dd1c85c1f3 (patch) | |
tree | 09bc05d679d0f224a29fee44d10beea321bdc0b5 /ext/tk/lib/tk | |
parent | e13fb8029b87943ab8af2211226b7c9347d3976d (diff) |
* ext/tk/extconf.rb: New strategy for searching Tcl/Tk libraries.
* ext/tk/*: Support new features of Tcl/Tk8.6b1 and minor bug fixes.
( [KNOWN BUG] Ruby/Tk on Ruby 1.9 will not work on Cygwin. )
* ext/tk/*: Unify sources between Ruby 1.8 & 1.9.
Improve default_widget_set handling.
* ext/tk/*: Multi-TkInterpreter (multi-tk.rb) works on Ruby 1.8 & 1.9.
( [KNOWN BUG] On Ruby 1.8, join to a long term Thread on Tk
callbacks may freeze. On Ruby 1.9, cannot create a second
master interpreter (creating slaves are OK); supported master
interpreter is the default master interpreter only. )
* ext/tk/lib/tkextlib/*: Update supported versions of Tk extensions.
Tcllib 1.8/Tklib 0.4.1 ==> Tcllib 1.11.1/Tklib 0.5
BWidgets 1.7 ==> BWidgets 1.8
TkTable 2.9 ==> TkTable 2.10
TkTreeCtrl 2005-12-02 ==> TkTreeCtrl 2.2.9
Tile 0.8.0/8.5.1 ==> Tile 0.8.3/8.6b1
IncrTcl 2005-02-14 ==> IncrTcl 2008-12-15
TclX 2005-02-07 ==> TclX 2008-12-15
Trofs 0.4.3 ==> Trofs 0.4.4
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@24063 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/tk/lib/tk')
41 files changed, 1196 insertions, 138 deletions
diff --git a/ext/tk/lib/tk/autoload.rb b/ext/tk/lib/tk/autoload.rb index df888eb927..2ebee9ea24 100644 --- a/ext/tk/lib/tk/autoload.rb +++ b/ext/tk/lib/tk/autoload.rb @@ -27,6 +27,8 @@ def TkPlace(*args); TkPlace.configure(*args); end ############################################ # classes on Tk module module Tk + autoload :Busy, 'tk/busy' + autoload :Button, 'tk/button' autoload :Canvas, 'tk/canvas' @@ -319,9 +321,16 @@ module Tk @TOPLEVEL_ALIAS_SETUP_PROC = {} + @AUTOLOAD_FILE_SYM_TABLE = Hash.new{|h,k| h[k]={}} # TABLE[file][sym] -> obj + @current_default_widget_set = nil + + module TOPLEVEL_ALIASES; end end +class Object + include Tk::TOPLEVEL_ALIASES +end ############################################ # methods to control default widget set @@ -343,50 +352,387 @@ class << Tk _replace_toplevel_aliases(target) end - def __set_toplevel_aliases__(target, obj, *symbols) + def widget_set_symbols + @TOPLEVEL_ALIAS_TABLE.keys + end + + def toplevel_aliases_on_widget_set(widget_set) + if (tbl = @TOPLEVEL_ALIAS_TABLE[widget_set.to_sym]) + tbl.collect{|k, v| (v.nil?)? nil: k}.compact + else + fail ArgumentError, "unknown widget_set #{widget_set.to_sym.inspect}" + end + end + + def __toplevel_alias_setup_proc__(*target_list, &cmd) + target_list.each{|target| @TOPLEVEL_ALIAS_SETUP_PROC[target.to_sym] = cmd} + end + + def topobj_defined?(sym) #=> alias_filename or object or false + Object.autoload?(sym) || + (Object.const_defined?(sym) && Object.const_get(sym)) + end + def topalias_defined?(sym) #=> alias_filename or object or false + Tk::TOPLEVEL_ALIASES.autoload?(sym) || + (Tk::TOPLEVEL_ALIASES.const_defined?(sym) && + Tk::TOPLEVEL_ALIASES.const_get(sym)) + end + def define_topobj(sym, obj) + if obj.kind_of? String + # obj is an autoload path + Object.autoload(sym, obj) + unless Object.autoload?(sym) + # file is autoloaded? + if @AUTOLOAD_FILE_SYM_TABLE.has_key?(obj) && + (loaded_obj = @AUTOLOAD_FILE_SYM_TABLE[obj][sym]) + Object.const_set(sym, loaded_obj) + else + fail ArgumentError, "cannot define autoload file (already loaded?)" + end + end + else + # object + Object.const_set(sym, obj) + end + end + def define_topalias(sym, obj) + if obj.kind_of? String + # obj is an autoload path + Tk::TOPLEVEL_ALIASES.autoload(sym, obj) + unless Tk::TOPLEVEL_ALIASES.autoload?(sym) + # file is autoloaded? + if @AUTOLOAD_FILE_SYM_TABLE.has_key?(obj) && + (loaded_obj = @AUTOLOAD_FILE_SYM_TABLE[obj][sym]) + Tk::TOPLEVEL_ALIASES.const_set(sym, loaded_obj) + else + fail ArgumentError, "cannot define autoload file (already loaded?)" + end + end + else + # object + Tk::TOPLEVEL_ALIASES.const_set(sym, obj) + end + end + def replace_topobj(sym, obj) #=> old_obj (alias_filename or object) or nil + if old_obj = topobj_defined?(sym) + Object.class_eval{remove_const sym} rescue nil # ignore err + end + define_topobj(sym, obj) + old_obj + end + def replace_topalias(sym, obj) #=> old_obj (alias_filename or object) or nil + if old_obj = topalias_defined?(sym) + Tk::TOPLEVEL_ALIASES.module_eval{remove_const sym} rescue nil #ignore err + end + define_topalias(sym, obj) + old_obj + end + private :topobj_defined?, :topalias_defined? + private :define_topobj, :define_topalias + private :replace_topobj, :replace_topalias + + def __regist_toplevel_aliases__(target, obj, *symbols) + # initial regist @TOPLEVEL_ALIAS_TABLE[target = target.to_sym] ||= {} symbols.each{|sym| @TOPLEVEL_ALIAS_TABLE[target][sym = sym.to_sym] = obj - # if @current_default_widget_set == target - if @TOPLEVEL_ALIAS_OWNER[sym] == target - Object.class_eval{remove_const sym} if Object.const_defined?(sym) - Object.const_set(sym, obj) + if !topalias_defined?(sym) || target == @current_default_widget_set + @TOPLEVEL_ALIAS_OWNER[sym] = target + replace_topalias(sym, obj) + replace_topobj(sym, obj) unless obj.kind_of?(String) # NOT autoload end } end - ################################### - private - def _replace_toplevel_aliases(target) - # check already autoloaded - if (table = @TOPLEVEL_ALIAS_TABLE[current = @current_default_widget_set]) - table.each{|sym, file| - if !Object.autoload?(sym) && Object.const_defined?(sym) && - @TOPLEVEL_ALIAS_TABLE[current][sym].kind_of?(String) - # autoload -> class - @TOPLEVEL_ALIAS_TABLE[current][sym] = Object.const_get(sym) + def regist_sym_for_loaded_file(auto, obj, sym) + @AUTOLOAD_FILE_SYM_TABLE[auto][sym] = obj + + reg = /^#{Regexp.quote(auto)}(\.rb|\.so|)$/ + @TOPLEVEL_ALIAS_TABLE.each_key{|set| + if @TOPLEVEL_ALIAS_TABLE[set][sym] =~ reg + @TOPLEVEL_ALIAS_TABLE[set][sym] = obj + if @TOPLEVEL_ALIAS_OWNER[sym].nil? || @TOPLEVEL_ALIAS_OWNER[sym] == set + replace_topalias(sym, obj) + replace_topobj(sym, obj) if set == @current_default_widget_set end - } + end + } + if (f = Object.autoload?(sym)) && f =~ reg + replace_topobj(sym, obj) end + if (f = Tk::TOPLEVEL_ALIASES.autoload?(sym)) && f =~ reg + replace_topalias(sym, obj) + end + end + private :regist_sym_for_loaded_file + + def set_topalias(target, obj, sym) + # obj is a kind of String : define autoload path + # Class : use the class object + if target == @current_default_widget_set + case @TOPLEVEL_ALIAS_OWNER[sym] + when false + # Object::sym is out of control. --> not change + # Make ALIAS::sym under control, because target widget set is current. + # Keep OWNER[sym] + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + + when target + if current_obj = topobj_defined?(sym) + if current_obj == obj + # Make current_obj under control. + # Keep Object::sym. + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + + else # current_obj != obj + if current_obj == topalias_defined?(sym) + # Change controlled object + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + replace_topobj(sym, obj) + + else # current_obj != topalias_defined?(sym) + # Maybe current_obj is defined by user. --> OWNER[sym] = faise + # Keep Object::sym. + @TOPLEVEL_ALIAS_OWNER[sym] = false + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + end + end + + else # NOT topobj_defined?(sym) + # New definition for sym at target. + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + define_topobj(sym, obj) + end + + when nil + # New definition for sym at target. + @TOPLEVEL_ALIAS_OWNER[sym] = target + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + + else # others + # Maybe planning to make sym under control. + @TOPLEVEL_ALIAS_OWNER[sym] = target + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + replace_topobj(sym, obj) + end + + else # target != @current_default_widget_set + case @TOPLEVEL_ALIAS_OWNER[sym] + when false + # Object::sym is out of control. --> not change + if topalias_defined?(sym) + # ALIAS[sym] may be defined by other widget set. + # Keep Object::sym (even if it is not defined) + # Keep ALIAS[sym]. + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + + else # NOT topalias_defined?(sym) + # Nobody controls ALIAS[sym]. + # At leaset, current widget set doesn't control ALIAS[sym]. + # Keep Object::sym (even if it is not defined) + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + define_topalias(sym, obj) + end + + when target + # Maybe change controlled object, because Object::sym is under control. + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + replace_topobj(sym, obj) + + when nil + # New definition for sym + @TOPLEVEL_ALIAS_OWNER[sym] = target + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + replace_topobj(sym, obj) + + else # others + # An other widget set controls sym. + # Keep Object::sym (even if it is not defined) + # Keep ALIAS[sym]. + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + + end + end + + sym + end + private :set_topalias - # setup autoloads - @TOPLEVEL_ALIAS_TABLE[target].each{|sym, file| - Object.class_eval{remove_const sym} if Object.const_defined?(sym) - if file.kind_of?(String) - # file => autoload target file - Object.autoload(sym, file) + def __set_toplevel_aliases__(target, obj, *symbols) + # obj is a kind of String : define autoload path + # Class : use the class object + target = target.to_sym + symbols.each{|sym| set_topalias(target, obj, sym.to_sym)} + end + + def __set_loaded_toplevel_aliases__(autopath, target, obj, *symbols) + # autopath is an autoload file + # Currently, this method doesn't support that autoload loads + # different toplevels between <basename>.rb and <basename>.so extension. + shortpath = (autopath =~ /^(.*)(.rb|.so)$/)? $1: autopath + target = target.to_sym + symbols.map!{|sym| sym.to_sym} + + symbols.each{|sym| regist_sym_for_loaded_file(shortpath, obj, sym) } + symbols.each{|sym| set_topalias(target, obj, sym)} + end + + def backup_current_topdef(sym) + return if (current = @current_default_widget_set).nil? + + case @TOPLEVEL_ALIAS_OWNER[sym] + when false + # Object::sym is out of control. + if (cur_alias = topalias_defined?(sym)) && ! cur_alias.kind_of?(String) + @TOPLEVEL_ALIAS_TABLE[current][sym] = cur_alias + end + + when current + if cur_obj = topobj_defined?(sym) + if ! cur_obj.kind_of?(String) && (cur_alias = topalias_defined?(sym)) + if cur_alias.kind_of?(String) + # Mayby, user replaced Object::sym. + # Make Object::sym out of control. + @TOPLEVEL_ALIAS_OWNER[sym] = false + elsif cur_obj == cur_alias + # Possibley, defined normally. Backup it + @TOPLEVEL_ALIAS_TABLE[current][sym] = cur_alias + else + # Mayby, user replaced Object::sym. + # Make Object::sym out of control. + @TOPLEVEL_ALIAS_OWNER[sym] = false + end + end + else + # Mayby, user replaced Object::sym. + # Make Object::sym out of control. + @TOPLEVEL_ALIAS_OWNER[sym] = false + end + + when nil + # Object::sym is out of control. + if (cur_alias = topalias_defined?(sym)) && ! cur_alias.kind_of?(String) + # Possibley, defined normally. Backup it. + @TOPLEVEL_ALIAS_TABLE[current][sym] = cur_alias + end + else + # No authority to control Object::sym and ALIASES::sym. + # Do nothing. + end + end + private :backup_current_topdef + + def _replace_toplevel_aliases(target) + # backup + @TOPLEVEL_ALIAS_TABLE[target].each_key{|sym| + backup_current_topdef(sym) + } + + # replace + @TOPLEVEL_ALIAS_TABLE[target].each_key{|sym| + next if (obj = @TOPLEVEL_ALIAS_TABLE[target][sym]).nil? + if @TOPLEVEL_ALIAS_OWNER[sym] == false + # Object::sym is out of control. --> not change + # Keep OWNER[sym]. + replace_topalias(sym, obj) else - # file => loaded class object - Object.const_set(sym, file) + # New definition + @TOPLEVEL_ALIAS_OWNER[sym] = target + replace_topalias(sym, obj) + replace_topobj(sym, obj) end - @TOPLEVEL_ALIAS_OWNER[sym] = target } - # update current alias + # change default_widget_set @current_default_widget_set = target end + private :_replace_toplevel_aliases + + def __import_toplevel_aliases__(target, *symbols) + current = @current_default_widget_set + symbols.each{|sym| + sym = sym.to_sym + if (obj = @TOPLEVEL_ALIAS_TABLE[target][sym]).nil? + # remove + @TOPLEVEL_ALIAS_TABLE[current].delete(sym) + @TOPLEVEL_ALIAS_OWNER.delete(sym) + Tk::TOPLEVEL_ALIASES.module_eval{remove_const sym} if topalias_defined?(sym) + Object.class_eval{remove_const sym} if topobj_defined?(sym) + + elsif obj == false + # remove, but OWNER[sym] <- false and not treat Object::sym + @TOPLEVEL_ALIAS_TABLE[current].delete(sym) + @TOPLEVEL_ALIAS_OWNER[sym] = false + Tk::TOPLEVEL_ALIASES.module_eval{remove_const sym} if topalias_defined?(sym) + + elsif @TOPLEVEL_ALIAS_OWNER[sym] == false + # Object::sym is out of control. --> not change + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[current][sym] = obj + replace_topalias(sym, obj) + + else + # new definition under control + @TOPLEVEL_ALIAS_OWNER[sym] = current + @TOPLEVEL_ALIAS_TABLE[current][sym] = obj + replace_topalias(sym, obj) + replace_topobj(sym, obj) + end + } + end + + def __remove_toplevel_aliases__(*symbols) + # remove toplevel aliases of current widget set + current = @current_default_widget_set + symbols.each{|sym| + sym = sym.to_sym + @TOPLEVEL_ALIAS_TABLE[current].delete(sym) + @TOPLEVEL_ALIAS_OWNER.delete(sym) + Tk::TOPLEVEL_ALIASES.module_eval{remove_const sym} if topalias_defined?(sym) + Object.class_eval{remove_const sym} if topobj_defined?(sym) + } + end + + def __reset_toplevel_owner__(*symbols) + symbols.each{|sym| @TOPLEVEL_ALIAS_OWNER.delete(sym.to_sym)} + end + + def __disable_toplevel_control__(*symbols) + symbols.each{|sym| @TOPLEVEL_ALIAS_OWNER[sym.to_sym] = false} + end + + def __create_widget_set__(new_set, src_set={}) + new_set = new_set.to_sym + if @TOPLEVEL_ALIAS_TABLE[new_set] + fail RuntimeError, "A widget-set #{new_set.inspect} is already exist." + end + if src_set.kind_of?(Symbol) + # new_set is an alias name of existed widget set. + @TOPLEVEL_ALIAS_TABLE[new_set] = @TOPLEVEL_ALIAS_TABLE[src_set] + else + @TOPLEVEL_ALIAS_TABLE[new_set] = {} + src_set.each{|sym, obj| set_topalias(new_set, obj, sym.to_sym) } + end + end end + ############################################ # setup default widget set => :Tk Tk.default_widget_set = :Tk diff --git a/ext/tk/lib/tk/bindtag.rb b/ext/tk/lib/tk/bindtag.rb index 88c8367a88..23b4e0b7c3 100644 --- a/ext/tk/lib/tk/bindtag.rb +++ b/ext/tk/lib/tk/bindtag.rb @@ -9,7 +9,7 @@ class TkBindTag #BTagID_TBL = {} BTagID_TBL = TkCore::INTERP.create_table - (Tk_BINDTAG_ID = ["btag".freeze, "00000".taint]).instance_eval{ + (Tk_BINDTAG_ID = ["btag".freeze, TkUtil.untrust("00000")]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze diff --git a/ext/tk/lib/tk/busy.rb b/ext/tk/lib/tk/busy.rb new file mode 100644 index 0000000000..7f4f89f524 --- /dev/null +++ b/ext/tk/lib/tk/busy.rb @@ -0,0 +1,118 @@ +# +# tk/busy.rb: support 'tk busy' command (Tcl/Tk8.6 or later) +# +require 'tk' + +module Tk::Busy + include TkCore + extend TkCore + extend TkItemConfigMethod +end + +class << Tk::Busy + def __item_cget_cmd(win) + # maybe need to override + ['tk', 'busy', 'cget', win.path] + end + private :__item_cget_cmd + + def __item_config_cmd(win) + # maybe need to override + ['tk', 'busy', 'configure', win.path] + end + private :__item_config_cmd + + def __item_confinfo_cmd(win) + # maybe need to override + __item_config_cmd(win) + end + private :__item_confinfo_cmd + + alias cget_tkstring itemcget_tkstring + alias cget itemcget + alias cget_strict itemcget_strict + alias configure itemconfigure + alias configinfo itemconfiginfo + alias current_configinfo current_itemconfiginfo + + private :itemcget_tkstring, :itemcget, :itemcget_strict + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo + + def method_missing(id, *args) + name = id.id2name + case args.length + when 1 + if name[-1] == ?= + configure name[0..-2], args[0] + args[0] + else + configure name, args[0] + self + end + when 0 + begin + cget(name) + rescue + super(id, *args) + end + else + super(id, *args) + end + end + + def hold(win, keys={}) + tk_call_without_enc('tk', 'busy', 'hold', win, *hash_kv(keys)) + win + end + + def forget(*wins) + tk_call_without_enc('tk', 'busy', 'forget', *wins) + self + end + + def current(pat=None) + list(tk_call('tk', 'busy', 'current', pat)) + end + + def status(win) + bool(tk_call_without_enc('tk', 'busy', 'status', win)) + end +end + +module Tk::Busy + def busy_configinfo(option=nil) + Tk::Busy.configinfo(self, option) + end + + def busy_current_configinfo(option=nil) + Tk::Busy.current_configinfo(self, option) + end + + def busy_configure(option, value=None) + Tk::Busy.configure(self, option, value) + self + end + + def busy_cget(option) + Tk::Busy.configure(self, option) + end + + def busy(keys={}) + Tk::Busy.hold(self, keys) + self + end + alias busy_hold busy + + def busy_forget + Tk::Busy.forget(self) + self + end + + def busy_current? + ! Tk::Busy.current(self.path).empty? + end + + def busy_status + Tk::Busy.status(self) + end +end diff --git a/ext/tk/lib/tk/button.rb b/ext/tk/lib/tk/button.rb index 770a5785bb..65233c91b6 100644 --- a/ext/tk/lib/tk/button.rb +++ b/ext/tk/lib/tk/button.rb @@ -7,7 +7,7 @@ require 'tk/label' class Tk::Button<Tk::Label TkCommandNames = ['button'.freeze].freeze WidgetClassName = 'Button'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self #def create_self(keys) # if keys and keys != None # tk_call_without_enc('button', @path, *hash_kv(keys, true)) @@ -27,4 +27,5 @@ class Tk::Button<Tk::Label end #TkButton = Tk::Button unless Object.const_defined? :TkButton -Tk.__set_toplevel_aliases__(:Tk, Tk::Button, :TkButton) +#Tk.__set_toplevel_aliases__(:Tk, Tk::Button, :TkButton) +Tk.__set_loaded_toplevel_aliases__('tk/button.rb', :Tk, Tk::Button, :TkButton) diff --git a/ext/tk/lib/tk/canvas.rb b/ext/tk/lib/tk/canvas.rb index b05a619939..1e24c0be97 100644 --- a/ext/tk/lib/tk/canvas.rb +++ b/ext/tk/lib/tk/canvas.rb @@ -45,7 +45,7 @@ class Tk::Canvas<TkWindow TkCommandNames = ['canvas'.freeze].freeze WidgetClassName = 'Canvas'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __destroy_hook__ TkcItem::CItemID_TBL.delete(@path) @@ -265,6 +265,12 @@ class Tk::Canvas<TkWindow self end + def imove(tagOrId, idx, x, y) + tk_send_without_enc('imove', tagid(tagOrId), idx, x, y) + self + end + alias i_move imove + def index(tagOrId, idx) number(tk_send_without_enc('index', tagid(tagOrId), idx)) end @@ -523,11 +529,18 @@ class Tk::Canvas<TkWindow self end - def move(tag, x, y) - tk_send_without_enc('move', tagid(tag), x, y) + def move(tag, dx, dy) + tk_send_without_enc('move', tagid(tag), dx, dy) self end + def moveto(tag, x, y) + # Tcl/Tk 8.6 or later + tk_send_without_enc('moveto', tagid(tag), x, y) + self + end + alias move_to moveto + def postscript(keys) tk_send("postscript", *hash_kv(keys)) end @@ -541,6 +554,15 @@ class Tk::Canvas<TkWindow self end + def rchars(tag, first, last, str_or_coords) + # Tcl/Tk 8.6 or later + str_or_coords = str_or_coords.flatten if str_or_coords.kinad_of? Array + tk_send_without_enc('rchars', tagid(tag), first, last, str_or_coords) + self + end + alias replace_chars rchars + alias replace_coords rchars + def scale(tag, x, y, xs, ys) tk_send_without_enc('scale', tagid(tag), x, y, xs, ys) self @@ -581,7 +603,8 @@ class Tk::Canvas<TkWindow end #TkCanvas = Tk::Canvas unless Object.const_defined? :TkCanvas -Tk.__set_toplevel_aliases__(:Tk, Tk::Canvas, :TkCanvas) +#Tk.__set_toplevel_aliases__(:Tk, Tk::Canvas, :TkCanvas) +Tk.__set_loaded_toplevel_aliases__('tk/canvas.rb', :Tk, Tk::Canvas, :TkCanvas) class TkcItem<TkObject diff --git a/ext/tk/lib/tk/canvastag.rb b/ext/tk/lib/tk/canvastag.rb index 4e57a159bf..495d92a9a8 100644 --- a/ext/tk/lib/tk/canvastag.rb +++ b/ext/tk/lib/tk/canvastag.rb @@ -60,6 +60,9 @@ module TkcTagAccess @c.itembindinfo(@id, seq) end + def cget_tkstring(option) + @c.itemcget_tkstring(@id, option) + end def cget(option) @c.itemcget(@id, option) end @@ -116,6 +119,13 @@ module TkcTagAccess self end + def imove(idx, x, y) + # Tcl/Tk 8.6 or later + @c.imove(@id, idx, x, y) + self + end + alias i_move imove + def index(idx) @c.index(@id, idx) end @@ -135,6 +145,13 @@ module TkcTagAccess self end + def moveto(x, y) + # Tcl/Tk 8.6 or later + @c.moveto(@id, x, y) + self + end + alias move_to moveto + def raise(abovethis=None) @c.raise(@id, abovethis) self @@ -145,6 +162,14 @@ module TkcTagAccess self end + def rchars(first, last, str_or_coords) + # Tcl/Tk 8.6 or later + @c.rchars(@id, first, last, str_or_coords) + self + end + alias replace_chars rchars + alias replace_coords rchars + def select_adjust(index) @c.select('adjust', @id, index) self @@ -203,7 +228,7 @@ class TkcTag<TkObject CTagID_TBL = TkCore::INTERP.create_table - (Tk_CanvasTag_ID = ['ctag'.freeze, '00000'.taint]).instance_eval{ + (Tk_CanvasTag_ID = ['ctag'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze @@ -389,7 +414,7 @@ class TkcTagCurrent<TkcTagString end class TkcGroup<TkcTag - (Tk_cGroup_ID = ['tkcg'.freeze, '00000'.taint]).instance_eval{ + (Tk_cGroup_ID = ['tkcg'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze diff --git a/ext/tk/lib/tk/checkbutton.rb b/ext/tk/lib/tk/checkbutton.rb index c1c4905c5e..b7449541c5 100644 --- a/ext/tk/lib/tk/checkbutton.rb +++ b/ext/tk/lib/tk/checkbutton.rb @@ -7,7 +7,7 @@ require 'tk/radiobutton' class Tk::CheckButton<Tk::RadioButton TkCommandNames = ['checkbutton'.freeze].freeze WidgetClassName = 'Checkbutton'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self #def create_self(keys) # if keys and keys != None # tk_call_without_enc('checkbutton', @path, *hash_kv(keys, true)) @@ -26,5 +26,7 @@ end Tk::Checkbutton = Tk::CheckButton #TkCheckButton = Tk::CheckButton unless Object.const_defined? :TkCheckButton #TkCheckbutton = Tk::Checkbutton unless Object.const_defined? :TkCheckbutton -Tk.__set_toplevel_aliases__(:Tk, Tk::CheckButton, - :TkCheckButton, :TkCheckbutton) +#Tk.__set_toplevel_aliases__(:Tk, Tk::CheckButton, +# :TkCheckButton, :TkCheckbutton) +Tk.__set_loaded_toplevel_aliases__('tk/checkbutton.rb', :Tk, Tk::CheckButton, + :TkCheckButton, :TkCheckbutton) diff --git a/ext/tk/lib/tk/composite.rb b/ext/tk/lib/tk/composite.rb index 9a4aafda18..e267c7a22b 100644 --- a/ext/tk/lib/tk/composite.rb +++ b/ext/tk/lib/tk/composite.rb @@ -145,16 +145,34 @@ module TkComposite str.chop << ' @epath=' << @epath.inspect << '>' end + def _get_opt_method_list(arg) + m_set, m_cget, m_info = arg + m_set = m_set.to_s + m_cget = m_set if !m_cget && self.method(m_set).arity == -1 + m_cget = m_cget.to_s if m_cget + m_info = m_info.to_s if m_info + [m_set, m_cget, m_info] + end + private :_get_opt_method_list + def option_methods(*opts) - opts.each{|m_set, m_cget, m_info| - m_set = m_set.to_s - m_cget = m_set if !m_cget && self.method(m_set).arity == -1 - m_cget = m_cget.to_s if m_cget - m_info = m_info.to_s if m_info - @option_methods[m_set] = { - :set => m_set, :cget => m_cget, :info => m_info + if opts.size == 1 && opts[0].kind_of?(Hash) + # {name => [m_set, m_cget, m_info], name => method} style + opts[0].each{|name, arg| + m_set, m_cget, m_info = _get_opt_method_list(arg) + @option_methods[name.to_s] = { + :set => m_set, :cget => m_cget, :info => m_info + } } - } + else + # [m_set, m_cget, m_info] or method style + opts.each{|arg| + m_set, m_cget, m_info = _get_opt_method_list(arg) + @option_methods[m_set] = { + :set => m_set, :cget => m_cget, :info => m_info + } + } + end end def delegate_alias(alias_opt, option, *wins) @@ -215,6 +233,14 @@ module TkComposite end private :__cget_delegates + def cget_tkstring(slot) + if (ret = __cget_delegates(slot)) == None + super(slot) + else + _get_eval_string(ret) + end + end + def cget(slot) if (ret = __cget_delegates(slot)) == None super(slot) diff --git a/ext/tk/lib/tk/entry.rb b/ext/tk/lib/tk/entry.rb index 8ce8def1e7..d4aa03f2b6 100644 --- a/ext/tk/lib/tk/entry.rb +++ b/ext/tk/lib/tk/entry.rb @@ -13,7 +13,7 @@ class Tk::Entry<Tk::Label TkCommandNames = ['entry'.freeze].freeze WidgetClassName = 'Entry'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self #def create_self(keys) # super(__conv_vcmd_on_hash_kv(keys)) @@ -116,4 +116,5 @@ class Tk::Entry<Tk::Label end #TkEntry = Tk::Entry unless Object.const_defined? :TkEntry -Tk.__set_toplevel_aliases__(:Tk, Tk::Entry, :TkEntry) +#Tk.__set_toplevel_aliases__(:Tk, Tk::Entry, :TkEntry) +Tk.__set_loaded_toplevel_aliases__('tk/entry.rb', :Tk, Tk::Entry, :TkEntry) diff --git a/ext/tk/lib/tk/event.rb b/ext/tk/lib/tk/event.rb index d07b3b5a85..bf4e122322 100644 --- a/ext/tk/lib/tk/event.rb +++ b/ext/tk/lib/tk/event.rb @@ -8,7 +8,7 @@ end ######################## require 'tkutil' -require 'tk' +require 'tk' unless Object.const_defined? :TkComm ######################## @@ -482,6 +482,26 @@ module TkEvent end }) end + elsif cmd.respond_to?(:arity) && cmd.arity == 0 # args.size == 0 + args = '' + if cmd.kind_of?(String) + id = cmd + elsif cmd.kind_of?(TkCallbackEntry) + id = install_cmd(cmd) + else + id = install_cmd(proc{ + begin + TkUtil.eval_cmd(cmd) + rescue Exception=>e + if TkCore::INTERP.kind_of?(TclTkIp) + fail e + else + # MultiTkIp + fail Exception, "#{e.class}: #{e.message.dup}" + end + end + }) + end else keys, args = klass._get_all_subst_keys diff --git a/ext/tk/lib/tk/font.rb b/ext/tk/lib/tk/font.rb index da6482c122..03db850f96 100644 --- a/ext/tk/lib/tk/font.rb +++ b/ext/tk/lib/tk/font.rb @@ -11,7 +11,7 @@ class TkFont TkCommandNames = ['font'.freeze].freeze - (Tk_FontID = ["@font".freeze, "00000".taint]).instance_eval{ + (Tk_FontID = ["@font".freeze, TkUtil.untrust("00000")]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze @@ -211,7 +211,7 @@ class TkFont end end def TkFont.actual_hash(fnt, option=nil) - Hash[TkFont.actual_hash(fnt, option)] + Hash[TkFont.actual(fnt, option)] end def TkFont.actual_displayof(fnt, win, option=nil) @@ -224,7 +224,7 @@ class TkFont end end def TkFont.actual_hash_displayof(fnt, option=nil) - Hash[TkFont.actual_hash_displayof(fnt, option)] + Hash[TkFont.actual_displayof(fnt, option)] end def TkFont.configure(fnt, slot, value=None) @@ -2199,7 +2199,7 @@ module TkFont::CoreMethods alias measure_core measure_core_tk4x alias metrics_core metrics_core_tk4x - when /^8\.[0-5]/ + when /^8\.[0-9]/ alias actual_core actual_core_tk8x alias configure_core configure_core_tk8x alias configinfo_core configinfo_core_tk8x @@ -2342,3 +2342,10 @@ if Tk::TCL_MAJOR_VERSION > 8 || 'systemDetailSystemFont', 'systemDetailEmphasizedSystemFont' ] end + +####################################### +# autoload +####################################### +class TkFont + autoload :Chooser, 'tk/fontchooser' +end diff --git a/ext/tk/lib/tk/fontchooser.rb b/ext/tk/lib/tk/fontchooser.rb new file mode 100644 index 0000000000..f9f816be59 --- /dev/null +++ b/ext/tk/lib/tk/fontchooser.rb @@ -0,0 +1,166 @@ +# +# tk/fontchooser.rb -- "tk fontchooser" support (Tcl/Tk8.6 or later) +# +require 'tk' +require 'tk/font' + +module TkFont::Chooser + extend TkCore +end + +class << TkFont::Chooser + def method_missing(id, *args) + name = id.id2name + case args.length + when 1 + if name[-1] == ?= + configure name[0..-2], args[0] + args[0] + else + configure name, args[0] + self + end + when 0 + begin + cget(name) + rescue + super(id, *args) + end + else + super(id, *args) + end + end + + def __conviginfo_value(key, val) + case key + when 'parent' + window(val) + when 'title' + val + when 'font' + if (lst = tk_split_simplelist(val)).size == 1 + lst[0] + else + lst.map{|elem| num_or_str(elem)} + end + when 'command' + tk_tcl2ruby(val) + when 'visible' + bool(val) + else # unkown + val + end + end + private :__conviginfo_value + + def configinfo(option=nil) + if !option && TkComm::GET_CONFIGINFOwoRES_AS_ARRAY + lst = tk_split_simplelist(tk_call('tk', 'fontchooser', 'configure')) + ret = [] + TkComm.slice_ary(lst, 2){|k, v| + k = k[1..-1] + ret << [k, __conviginfo_value(k, v)] + } + ret + else + current_configinfo(option) + end + end + + def current_configinfo(option=nil) + if option + opt = option.to_s + fail ArgumentError, "Invalid option `#{option.inspect}'" if opt.empty? + __conviginfo_value(option.to_s, tk_call('tk','fontchooser', + 'configure',"-#{opt}")) + else + lst = tk_split_simplelist(tk_call('tk', 'fontchooser', 'configure')) + ret = {} + TkComm.slice_ary(lst, 2){|k, v| + k = k[1..-1] + ret[k] = __conviginfo_value(k, v) + } + ret + end + end + + def configure(option, value=None) + if option.kind_of? Hash + tk_call('tk', 'fontchooser', 'configure', + *hash_kv(_symbolkey2str(option))) + else + opt = option.to_s + fail ArgumentError, "Invalid option `#{option.inspect}'" if opt.empty? + tk_call('tk', 'fontchooser', 'configure', "-#{opt}", value) + end + self + end + + def configure_cmd(slot, value) + configure(slot, install_cmd(value)) + end + + def command(cmd=nil, &b) + if cmd + configure_cmd('command', cmd) + elsif b + configure_cmd('command', Proc.new(&b)) + else + cget('command') + end + end + + def cget(slot) + configinfo slot + end + + def [](slot) + cget slot + end + + def []=(slot, val) + configure slot, val + val + end + + def show + tk_call('tk', 'fontchooser', 'show') + self + end + + def hide + tk_call('tk', 'fontchooser', 'hide') + self + end + + def toggle + cget(:visible) ? hide: show + self + end + + def set_for(target, title="Font") + if target.kind_of? TkFont + configs = { + :font=>target.actual_hash, + :command=>proc{|fnt, *args| + target.configure(TkFont.actual_hash(fnt)) + } + } + else + configs = { + :font=>target.cget_tkstring(:font), + :command=>proc{|fnt, *args| + target.font = TkFont.actual_hash_displayof(fnt, target) + } + } + end + + configs[:title] = title if title + configure(configs) + target + end + + def unset + configure(:command, nil) + end +end diff --git a/ext/tk/lib/tk/frame.rb b/ext/tk/lib/tk/frame.rb index 263b160f29..5118939732 100644 --- a/ext/tk/lib/tk/frame.rb +++ b/ext/tk/lib/tk/frame.rb @@ -6,7 +6,7 @@ require 'tk' class Tk::Frame<TkWindow TkCommandNames = ['frame'.freeze].freeze WidgetClassName = 'Frame'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self ################# old version # def initialize(parent=nil, keys=nil) @@ -128,4 +128,5 @@ class Tk::Frame<TkWindow end #TkFrame = Tk::Frame unless Object.const_defined? :TkFrame -Tk.__set_toplevel_aliases__(:Tk, Tk::Frame, :TkFrame) +#Tk.__set_toplevel_aliases__(:Tk, Tk::Frame, :TkFrame) +Tk.__set_loaded_toplevel_aliases__('tk/frame.rb', :Tk, Tk::Frame, :TkFrame) diff --git a/ext/tk/lib/tk/image.rb b/ext/tk/lib/tk/image.rb index 09f173909d..79d9ce8d00 100644 --- a/ext/tk/lib/tk/image.rb +++ b/ext/tk/lib/tk/image.rb @@ -11,7 +11,7 @@ class TkImage<TkObject Tk_IMGTBL = TkCore::INTERP.create_table - (Tk_Image_ID = ['i'.freeze, '00000'.taint]).instance_eval{ + (Tk_Image_ID = ['i'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze diff --git a/ext/tk/lib/tk/itemconfig.rb b/ext/tk/lib/tk/itemconfig.rb index cd05d7ea53..14396048ba 100644 --- a/ext/tk/lib/tk/itemconfig.rb +++ b/ext/tk/lib/tk/itemconfig.rb @@ -162,6 +162,13 @@ module TkItemConfigMethod ################################################ + + def itemcget_tkstring(tagOrId, option) + opt = option.to_s + fail ArgumentError, "Invalid option `#{option.inspect}'" if opt.length == 0 + tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{opt}")) + end + def __itemcget_core(tagOrId, option) orig_opt = option option = option.to_s diff --git a/ext/tk/lib/tk/label.rb b/ext/tk/lib/tk/label.rb index 80b3d778f1..05e430e49b 100644 --- a/ext/tk/lib/tk/label.rb +++ b/ext/tk/lib/tk/label.rb @@ -6,7 +6,7 @@ require 'tk' class Tk::Label<TkWindow TkCommandNames = ['label'.freeze].freeze WidgetClassName = 'Label'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self #def create_self(keys) # if keys and keys != None # tk_call_without_enc('label', @path, *hash_kv(keys, true)) @@ -18,4 +18,5 @@ class Tk::Label<TkWindow end #TkLabel = Tk::Label unless Object.const_defined? :TkLabel -Tk.__set_toplevel_aliases__(:Tk, Tk::Label, :TkLabel) +#Tk.__set_toplevel_aliases__(:Tk, Tk::Label, :TkLabel) +Tk.__set_loaded_toplevel_aliases__('tk/label.rb', :Tk, Tk::Label, :TkLabel) diff --git a/ext/tk/lib/tk/labelframe.rb b/ext/tk/lib/tk/labelframe.rb index 995b5b7e72..6f679e55b5 100644 --- a/ext/tk/lib/tk/labelframe.rb +++ b/ext/tk/lib/tk/labelframe.rb @@ -7,7 +7,7 @@ require 'tk/frame' class Tk::LabelFrame<Tk::Frame TkCommandNames = ['labelframe'.freeze].freeze WidgetClassName = 'Labelframe'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self #def create_self(keys) # if keys and keys != None # tk_call_without_enc('labelframe', @path, *hash_kv(keys, true)) @@ -26,4 +26,6 @@ end Tk::Labelframe = Tk::LabelFrame #TkLabelFrame = Tk::LabelFrame unless Object.const_defined? :TkLabelFrame #TkLabelframe = Tk::Labelframe unless Object.const_defined? :TkLabelframe -Tk.__set_toplevel_aliases__(:Tk, Tk::LabelFrame, :TkLabelFrame, :TkLabelframe) +#Tk.__set_toplevel_aliases__(:Tk, Tk::LabelFrame, :TkLabelFrame, :TkLabelframe) +Tk.__set_loaded_toplevel_aliases__('tk/labelframe.rb', :Tk, Tk::LabelFrame, + :TkLabelFrame, :TkLabelframe) diff --git a/ext/tk/lib/tk/listbox.rb b/ext/tk/lib/tk/listbox.rb index 4357fafc27..6742b2132c 100644 --- a/ext/tk/lib/tk/listbox.rb +++ b/ext/tk/lib/tk/listbox.rb @@ -21,7 +21,7 @@ class Tk::Listbox<TkTextWin TkCommandNames = ['listbox'.freeze].freeze WidgetClassName = 'Listbox'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self #def create_self(keys) # if keys and keys != None @@ -279,4 +279,6 @@ class Tk::Listbox<TkTextWin end #TkListbox = Tk::Listbox unless Object.const_defined? :TkListbox -Tk.__set_toplevel_aliases__(:Tk, Tk::Listbox, :TkListbox) +#Tk.__set_toplevel_aliases__(:Tk, Tk::Listbox, :TkListbox) +Tk.__set_loaded_toplevel_aliases__('tk/listbox.rb', :Tk, Tk::Listbox, + :TkListbox) diff --git a/ext/tk/lib/tk/macpkg.rb b/ext/tk/lib/tk/macpkg.rb index 67b0a4bb60..3ca7953c13 100644 --- a/ext/tk/lib/tk/macpkg.rb +++ b/ext/tk/lib/tk/macpkg.rb @@ -23,7 +23,9 @@ end module Tk::MacResource end #TkMacResource = Tk::MacResource -Tk.__set_toplevel_aliases__(:Tk, Tk::MacResource, :TkMacResource) +#Tk.__set_toplevel_aliases__(:Tk, Tk::MacResource, :TkMacResource) +Tk.__set_loaded_toplevel_aliases__('tk/macpkg.rb', :Tk, Tk::MacResource, + :TkMacResource) module Tk::MacResource extend Tk diff --git a/ext/tk/lib/tk/menu.rb b/ext/tk/lib/tk/menu.rb index 3e122e6987..bcd250026d 100644 --- a/ext/tk/lib/tk/menu.rb +++ b/ext/tk/lib/tk/menu.rb @@ -33,13 +33,14 @@ module TkMenuEntryConfig end private :__item_val2ruby_optkeys + alias entrycget_tkstring itemcget_tkstring alias entrycget itemcget alias entrycget_strict itemcget_strict alias entryconfigure itemconfigure alias entryconfiginfo itemconfiginfo alias current_entryconfiginfo current_itemconfiginfo - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo end @@ -50,7 +51,7 @@ class Tk::Menu<TkWindow TkCommandNames = ['menu'.freeze].freeze WidgetClassName = 'Menu'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self #def create_self(keys) # if keys and keys != None @@ -386,8 +387,32 @@ class Tk::Menu<TkWindow end #TkMenu = Tk::Menu unless Object.const_defined? :TkMenu -Tk.__set_toplevel_aliases__(:Tk, Tk::Menu, :TkMenu) +#Tk.__set_toplevel_aliases__(:Tk, Tk::Menu, :TkMenu) +Tk.__set_loaded_toplevel_aliases__('tk/menu.rb', :Tk, Tk::Menu, :TkMenu) + + +module Tk::Menu::TkInternalFunction; end +class << Tk::Menu::TkInternalFunction + # These methods calls internal functions of Tcl/Tk. + # So, They may not work on your Tcl/Tk. + def next_menu(menu, dir='next') + dir = dir.to_s + case dir + when 'next', 'forward', 'down' + dir = 'right' + when 'previous', 'backward', 'up' + dir = 'left' + end + + Tk.tk_call('::tk::MenuNextMenu', menu, dir) + end + def next_entry(menu, delta) + # delta is increment value of entry index. + # For example, +1 denotes 'next entry' and -1 denotes 'previous entry'. + Tk.tk_call('::tk::MenuNextEntry', menu, delta) + end +end class Tk::MenuClone<Tk::Menu =begin @@ -446,7 +471,9 @@ end Tk::CloneMenu = Tk::MenuClone #TkMenuClone = Tk::MenuClone unless Object.const_defined? :TkMenuClone #TkCloneMenu = Tk::CloneMenu unless Object.const_defined? :TkCloneMenu -Tk.__set_toplevel_aliases__(:Tk, Tk::MenuClone, :TkMenuClone, :TkCloneMenu) +#Tk.__set_toplevel_aliases__(:Tk, Tk::MenuClone, :TkMenuClone, :TkCloneMenu) +Tk.__set_loaded_toplevel_aliases__('tk/menu.rb', :Tk, Tk::MenuClone, + :TkMenuClone, :TkCloneMenu) module Tk::SystemMenu def initialize(parent, keys=nil) @@ -480,7 +507,9 @@ class Tk::SysMenu_Help<Tk::Menu SYSMENU_NAME = 'help' end #TkSysMenu_Help = Tk::SysMenu_Help unless Object.const_defined? :TkSysMenu_Help -Tk.__set_toplevel_aliases__(:Tk, Tk::SysMenu_Help, :TkSysMenu_Help) +#Tk.__set_toplevel_aliases__(:Tk, Tk::SysMenu_Help, :TkSysMenu_Help) +Tk.__set_loaded_toplevel_aliases__('tk/menu.rb', :Tk, Tk::SysMenu_Help, + :TkSysMenu_Help) class Tk::SysMenu_System<Tk::Menu @@ -489,7 +518,9 @@ class Tk::SysMenu_System<Tk::Menu SYSMENU_NAME = 'system' end #TkSysMenu_System = Tk::SysMenu_System unless Object.const_defined? :TkSysMenu_System -Tk.__set_toplevel_aliases__(:Tk, Tk::SysMenu_System, :TkSysMenu_System) +#Tk.__set_toplevel_aliases__(:Tk, Tk::SysMenu_System, :TkSysMenu_System) +Tk.__set_loaded_toplevel_aliases__('tk/menu.rb', :Tk, Tk::SysMenu_System, + :TkSysMenu_System) class Tk::SysMenu_Apple<Tk::Menu @@ -498,13 +529,15 @@ class Tk::SysMenu_Apple<Tk::Menu SYSMENU_NAME = 'apple' end #TkSysMenu_Apple = Tk::SysMenu_Apple unless Object.const_defined? :TkSysMenu_Apple -Tk.__set_toplevel_aliases__(:Tk, Tk::SysMenu_Apple, :TkSysMenu_Apple) +#Tk.__set_toplevel_aliases__(:Tk, Tk::SysMenu_Apple, :TkSysMenu_Apple) +Tk.__set_loaded_toplevel_aliases__('tk/menu.rb', :Tk, Tk::SysMenu_Apple, + :TkSysMenu_Apple) class Tk::Menubutton<Tk::Label TkCommandNames = ['menubutton'.freeze].freeze WidgetClassName = 'Menubutton'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def create_self(keys) if keys and keys != None unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ @@ -541,7 +574,9 @@ end Tk::MenuButton = Tk::Menubutton #TkMenubutton = Tk::Menubutton unless Object.const_defined? :TkMenubutton #TkMenuButton = Tk::MenuButton unless Object.const_defined? :TkMenuButton -Tk.__set_toplevel_aliases__(:Tk, Tk::Menubutton, :TkMenubutton, :TkMenuButton) +#Tk.__set_toplevel_aliases__(:Tk, Tk::Menubutton, :TkMenubutton, :TkMenuButton) +Tk.__set_loaded_toplevel_aliases__('tk/menu.rb', :Tk, Tk::Menubutton, + :TkMenubutton, :TkMenuButton) class Tk::OptionMenubutton<Tk::Menubutton @@ -677,5 +712,7 @@ end Tk::OptionMenuButton = Tk::OptionMenubutton #TkOptionMenubutton = Tk::OptionMenubutton unless Object.const_defined? :TkOptionMenubutton #TkOptionMenuButton = Tk::OptionMenuButton unless Object.const_defined? :TkOptionMenuButton -Tk.__set_toplevel_aliases__(:Tk, Tk::OptionMenubutton, - :TkOptionMenubutton, :TkOptionMenuButton) +#Tk.__set_toplevel_aliases__(:Tk, Tk::OptionMenubutton, +# :TkOptionMenubutton, :TkOptionMenuButton) +Tk.__set_loaded_toplevel_aliases__('tk/menu.rb', :Tk, Tk::OptionMenubutton, + :TkOptionMenubutton, :TkOptionMenuButton) diff --git a/ext/tk/lib/tk/menubar.rb b/ext/tk/lib/tk/menubar.rb index ac537cb4ec..9d5571c470 100644 --- a/ext/tk/lib/tk/menubar.rb +++ b/ext/tk/lib/tk/menubar.rb @@ -93,24 +93,30 @@ class TkMenubar<Tk::Frame include TkComposite include TkMenuSpec - def initialize(parent = nil, spec = nil, options = nil) + def initialize(parent = nil, spec = nil, options = {}) if parent.kind_of? Hash - options = _symbolkey2str(parent) - spec = options.delete('spec') - super(options) - else - super(parent, options) + options = parent + parent = nil + spec = (options.has_key?('spec'))? options.delete('spec'): nil end + _symbolkey2str(options) + menuspec_opt = {} + TkMenuSpec::MENUSPEC_OPTKEYS.each{|key| + menuspec_opt[key] = options.delete(key) if options.has_key?(key) + } + + super(parent, options) + @menus = [] - spec.each{|info| add_menu(info)} if spec + spec.each{|info| add_menu(info, menuspec_opt)} if spec options.each{|key, value| configure(key, value)} if options end - def add_menu(menu_info) - mbtn, menu = _create_menubutton(@frame, menu_info) + def add_menu(menu_info, menuspec_opt={}) + mbtn, menu = _create_menubutton(@frame, menu_info, menuspec_opt) submenus = _get_cascade_menus(menu).flatten diff --git a/ext/tk/lib/tk/menuspec.rb b/ext/tk/lib/tk/menuspec.rb index 3f38ab5140..d7521555cd 100644 --- a/ext/tk/lib/tk/menuspec.rb +++ b/ext/tk/lib/tk/menuspec.rb @@ -7,9 +7,12 @@ # This file can be distributed under the terms of the Ruby. # # The format of the menu_spec is: -# [ menu_info, menu_info, ... ] +# [ menubutton_info, menubutton_info, ... ] # -# And the format of the menu_info is: +# The format of the menubutton_info is: +# [ menubutton_info, entry_info, entry_info, ... ] +# +# And each format of *_info is: # [ # [text, underline, configs], # menu button/entry (*1) # [label, command, underline, accelerator, configs], # command entry @@ -22,12 +25,24 @@ # ... # ] # +# A menu_info is an array of menu entries: +# [ entry_info, entry_info, ... ] +# +# # underline, accelerator, and configs are optional pearameters. # Hashes are OK instead of Arrays. Then the entry type ('command', # 'checkbutton', 'radiobutton' or 'cascade') is given by 'type' key # (e.g. :type=>'cascade'). When type is 'cascade', an array of menu_info # is acceptable for 'menu' key (then, create sub-menu). # +# If the value of underline is true instead of an integer, +# check whether the text/label string contains a '&' character. +# When includes, the first '&' is removed and its following character is +# converted the corresponding 'underline' option (first '&' is removed). +# Else if the value of underline is a String or a Regexp, +# use the result of label.index(underline) as the index of underline +# (don't remove matched substring). +# # NOTE: (*1) # If you want to make special menus (*.help for UNIX, *.system for Win, # and *.apple for Mac), append 'menu_name'=>name (name is 'help' for UNIX, @@ -39,6 +54,10 @@ # to the configs of the cascade entry. module TkMenuSpec + extend TkMenuSpec + + MENUSPEC_OPTKEYS = [ 'layout_proc' ] + def _create_menu(parent, menu_info, menu_name = nil, tearoff = false, default_opts = nil) if tearoff.kind_of?(Hash) @@ -59,6 +78,7 @@ module TkMenuSpec end tearoff = orig_opts.delete('tearoff') if orig_opts.key?('tearoff') + tearoff = false unless tearoff # nil --> false if menu_name #menu = Tk::Menu.new(parent, :widgetname=>menu_name, :tearoff=>tearoff) @@ -84,6 +104,23 @@ module TkMenuSpec tearoff, menu_opts) options['menu'] = submenu end + case options['underline'] + when String, Regexp + if options['label'] && + (idx = options['label'].index(options['underline'])) + options['underline'] = idx + else + options['underline'] = -1 + end + when true + if options['label'] && (idx = options['label'].index('&')) + options['label'] = options['label'].dup + options['label'][idx] = '' + options['underline'] = idx + else + options['underline'] = -1 + end + end menu.add(item_type, options) elsif item_info.kind_of?(Array) @@ -138,6 +175,25 @@ module TkMenuSpec end options.update(opts) end + + case options['underline'] + when String, Regexp + if options['label'] && + (idx = options['label'].index(options['underline'])) + options['underline'] = idx + else + options['underline'] = -1 + end + when true + if options['label'] && (idx = options['label'].index('&')) + options['label'] = options['label'].dup + options['label'][idx] = '' + options['underline'] = idx + else + options['underline'] = -1 + end + end + menu.add(item_type, options) elsif /^-+$/ =~ item_info @@ -177,7 +233,7 @@ module TkMenuSpec end private :_create_menu_for_menubar - def _create_menubutton(parent, menu_info, tearoff=false, default_opts = nil) + def _create_menubutton(parent, menu_info, tearoff=false, default_opts = {}) btn_info = menu_info[0] if tearoff.kind_of?(Hash) @@ -186,14 +242,49 @@ module TkMenuSpec end if default_opts.kind_of?(Hash) - keys = _symbolkey2str(default_opts) - else - keys = {} + default_opts = _symbolkey2str(default_opts) + + if default_opts.has_key?('layout_proc') + layout_proc = default_opts.delete('layout_proc') + end + + _vertical_mbar_bind_proc = proc{|m, dir| + Tk::Menu::TkInternalFunction.next_menu(m, dir) rescue nil + # ignore error when the internal function doesn't exist + } + + case layout_proc + when :vertical, 'vertical', :vertical_left, 'vertical_left' + layout_proc = proc{|_parent, _mbtn| + _mbtn.direction :right + _mbtn.pack(:side=>:top, :fill=>:x) + + menu = _mbtn.menu + menu.bind('Tab', _vertical_mbar_bind_proc, :widget, 'forward') + menu.bind('Alt-Tab', _vertical_mbar_bind_proc, :widget, 'backward') + } + when :vertical_right, 'vertical_right' + layout_proc = proc{|_parent, _mbtn| + _mbtn.direction :left + _mbtn.pack(:side=>:top, :fill=>:x) + + menu = _mbtn.menu + menu.bind('Tab', _vertical_mbar_bind_proc, :widget, 'forward') + menu.bind('Alt-Tab', _vertical_mbar_bind_proc, :widget, 'backward') + } + when :horizontal, 'horizontal' + layout_proc = proc{|_parent, _mbtn| _mbtn.pack(:side=>:left)} + else + # do nothing + end end + keys = default_opts.dup + tearoff = keys.delete('tearoff') if keys.key?('tearoff') + tearoff = false unless tearoff # nil --> false - if _use_menubar?(parent) + if _use_menubar?(parent) && ! layout_proc # menubar by menu entries mbar = _create_menu_for_menubar(parent) @@ -202,14 +293,52 @@ module TkMenuSpec if btn_info.kind_of?(Hash) keys.update(_symbolkey2str(btn_info)) menu_name = keys.delete('menu_name') - keys['label'] = keys.delete('text') if keys.key?('text') + keys['label'] = keys.delete('text') || '' + + case keys['underline'] + when String, Regexp + if idx = keys['label'].index(keys['underline']) + keys['underline'] = idx + else + keys['underline'] = -1 + end + when true + if idx = keys['label'].index('&') + keys['label'] = keys['label'].dup + keys['label'][idx] = '' + keys['underline'] = idx + else + keys['underline'] = -1 + end + end + elsif btn_info.kind_of?(Array) keys['label'] = btn_info[0] if btn_info[0] - keys['underline'] = btn_info[1] if btn_info[1] + + case btn_info[1] + when Integer + keys['underline'] = btn_info[1] + when String, Regexp + if idx = keys['label'].index(btn_info[1]) + keys['underline'] = idx + else + keys['underline'] = -1 + end + when true + if idx = keys['label'].index('&') + keys['label'] = keys['label'].dup + keys['label'][idx] = '' + keys['underline'] = idx + else + keys['underline'] = -1 + end + end + if btn_info[2]&&btn_info[2].kind_of?(Hash) keys.update(_symbolkey2str(btn_info[2])) menu_name = keys.delete('menu_name') end + else keys = {:label=>btn_info} end @@ -234,9 +363,42 @@ module TkMenuSpec if btn_info.kind_of?(Hash) keys.update(_symbolkey2str(btn_info)) menu_name = keys.delete('menu_name') - keys['text'] = keys.delete('label') if keys.key?('label') + keys['text'] = keys.delete('label') || '' + case keys['underline'] + when String, Regexp + if idx = keys['text'].index(keys['underline']) + keys['underline'] = idx + else + keys['underline'] = -1 + end + when true + if idx = keys['text'].index('&') + keys['text'] = keys['text'].dup + keys['text'][idx] = '' + keys['underline'] = idx + else + keys['underline'] = -1 + end + end mbtn.configure(keys) + elsif btn_info.kind_of?(Array) + case btn_info[1] + when String, Regexp + if btn_info[0] && (idx = btn_info[0].index(btn_info[1])) + btn_info[1] = idx + else + btn_info[1] = -1 + end + when true + if btn_info[0] && (idx = btn_info[0].index('&')) + btn_info[0] = btn_info[0].dup + btn_info[0][idx] = '' + btn_info[1] = idx + else + btn_info[1] = -1 + end + end mbtn.configure('text', btn_info[0]) if btn_info[0] mbtn.configure('underline', btn_info[1]) if btn_info[1] # mbtn.configure('accelerator', btn_info[2]) if btn_info[2] @@ -245,22 +407,41 @@ module TkMenuSpec menu_name = keys.delete('menu_name') mbtn.configure(keys) end + else mbtn.configure('text', btn_info) end - mbtn.pack('side' => 'left') - menu = _create_menu(mbtn, menu_info[1..-1], menu_name, tearoff, default_opts) - mbtn.menu(menu) + if layout_proc.kind_of?(Proc) || layout_proc.kind_of?(Method) + # e.g. make a vertical menubar + # :layout_proc => proc{|parent, btn| btn.pack(:side=>:top, :fill=>:x)} + layout_proc.call(parent, mbtn) + else + mbtn.pack('side' => 'left') + end + [mbtn, menu] end end private :_create_menubutton + def _create_menubar(parent, menu_spec, tearoff = false, opts = nil) + if tearoff.kind_of?(Hash) + opts = tearoff + tearoff = false + end + tearoff = false unless tearoff # nil --> false + menu_spec.each{|menu_info| + _create_menubutton(parent, menu_info, tearoff, opts) + } + parent + end + private :_create_menubar + def _get_cascade_menus(menu) menus = [] (0..(menu.index('last'))).each{|idx| diff --git a/ext/tk/lib/tk/message.rb b/ext/tk/lib/tk/message.rb index 946b68c704..5f73b3066f 100644 --- a/ext/tk/lib/tk/message.rb +++ b/ext/tk/lib/tk/message.rb @@ -7,7 +7,7 @@ require 'tk/label' class Tk::Message<Tk::Label TkCommandNames = ['message'.freeze].freeze WidgetClassName = 'Message'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self #def create_self(keys) # if keys and keys != None # tk_call_without_enc('message', @path, *hash_kv(keys, true)) @@ -19,4 +19,6 @@ class Tk::Message<Tk::Label end #TkMessage = Tk::Message unless Object.const_defined? :TkMessage -Tk.__set_toplevel_aliases__(:Tk, Tk::Message, :TkMessage) +#Tk.__set_toplevel_aliases__(:Tk, Tk::Message, :TkMessage) +Tk.__set_loaded_toplevel_aliases__('tk/message.rb', :Tk, Tk::Message, + :TkMessage) diff --git a/ext/tk/lib/tk/msgcat.rb b/ext/tk/lib/tk/msgcat.rb index f90dbc5efa..4abbcad85e 100644 --- a/ext/tk/lib/tk/msgcat.rb +++ b/ext/tk/lib/tk/msgcat.rb @@ -36,7 +36,7 @@ class TkMsgCatalog < TkObject MSGCAT_EXT = '.msg' - UNKNOWN_CBTBL = Hash.new{|hash,key| hash[key] = {}}.taint + UNKNOWN_CBTBL = TkUtil.untrust(Hash.new{|hash,key| hash[key] = {}}) TkCore::INTERP.add_tk_procs('::msgcat::mcunknown', 'args', <<-'EOL') if {[set st [catch {eval {ruby_cmd TkMsgCatalog callback} [namespace current] $args} ret]] != 0} { diff --git a/ext/tk/lib/tk/namespace.rb b/ext/tk/lib/tk/namespace.rb index dfb162cda8..4af891995e 100644 --- a/ext/tk/lib/tk/namespace.rb +++ b/ext/tk/lib/tk/namespace.rb @@ -13,7 +13,7 @@ class TkNamespace < TkObject Tk_Namespace_ID_TBL = TkCore::INTERP.create_table - (Tk_Namespace_ID = ["ns".freeze, "00000".taint]).instance_eval{ + (Tk_Namespace_ID = ["ns".freeze, TkUtil.untrust("00000")]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze diff --git a/ext/tk/lib/tk/optiondb.rb b/ext/tk/lib/tk/optiondb.rb index 9d366c13ea..0f3be30ff7 100644 --- a/ext/tk/lib/tk/optiondb.rb +++ b/ext/tk/lib/tk/optiondb.rb @@ -8,7 +8,7 @@ module TkOptionDB extend Tk TkCommandNames = ['option'.freeze].freeze - (CmdClassID = ['CMD_CLASS'.freeze, '00000'.taint]).instance_eval{ + (CmdClassID = ['CMD_CLASS'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze diff --git a/ext/tk/lib/tk/panedwindow.rb b/ext/tk/lib/tk/panedwindow.rb index 4e70ede9bf..04407802ea 100644 --- a/ext/tk/lib/tk/panedwindow.rb +++ b/ext/tk/lib/tk/panedwindow.rb @@ -6,7 +6,7 @@ require 'tk' class Tk::PanedWindow<TkWindow TkCommandNames = ['panedwindow'.freeze].freeze WidgetClassName = 'Panedwindow'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self #def create_self(keys) # if keys and keys != None # tk_call_without_enc('panedwindow', @path, *hash_kv(keys, true)) @@ -254,5 +254,7 @@ end Tk::Panedwindow = Tk::PanedWindow #TkPanedWindow = Tk::PanedWindow unless Object.const_defined? :TkPanedWindow #TkPanedwindow = Tk::Panedwindow unless Object.const_defined? :TkPanedwindow -Tk.__set_toplevel_aliases__(:Tk, Tk::PanedWindow, - :TkPanedWindow, :TkPanedwindow) +#Tk.__set_toplevel_aliases__(:Tk, Tk::PanedWindow, +# :TkPanedWindow, :TkPanedwindow) +Tk.__set_loaded_toplevel_aliases__('tk/panedwindow.rb', :Tk, Tk::PanedWindow, + :TkPanedWindow, :TkPanedwindow) diff --git a/ext/tk/lib/tk/radiobutton.rb b/ext/tk/lib/tk/radiobutton.rb index 1d75dc220d..627df6d9cf 100644 --- a/ext/tk/lib/tk/radiobutton.rb +++ b/ext/tk/lib/tk/radiobutton.rb @@ -7,7 +7,7 @@ require 'tk/button' class Tk::RadioButton<Tk::Button TkCommandNames = ['radiobutton'.freeze].freeze WidgetClassName = 'Radiobutton'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self #def create_self(keys) # if keys and keys != None # tk_call_without_enc('radiobutton', @path, *hash_kv(keys, true)) @@ -67,5 +67,7 @@ end Tk::Radiobutton = Tk::RadioButton #TkRadioButton = Tk::RadioButton unless Object.const_defined? :TkRadioButton #TkRadiobutton = Tk::Radiobutton unless Object.const_defined? :TkRadiobutton -Tk.__set_toplevel_aliases__(:Tk, Tk::RadioButton, - :TkRadioButton, :TkRadiobutton) +#Tk.__set_toplevel_aliases__(:Tk, Tk::RadioButton, +# :TkRadioButton, :TkRadiobutton) +Tk.__set_loaded_toplevel_aliases__('tk/radiobutton.rb', :Tk, Tk::RadioButton, + :TkRadioButton, :TkRadiobutton) diff --git a/ext/tk/lib/tk/root.rb b/ext/tk/lib/tk/root.rb index ca6260927a..b4f0bd107f 100644 --- a/ext/tk/lib/tk/root.rb +++ b/ext/tk/lib/tk/root.rb @@ -52,7 +52,7 @@ class Tk::Root<TkWindow end WidgetClassName = 'Tk'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def self.to_eval # self::WidgetClassName diff --git a/ext/tk/lib/tk/scale.rb b/ext/tk/lib/tk/scale.rb index 58283216b8..0bdcead7f2 100644 --- a/ext/tk/lib/tk/scale.rb +++ b/ext/tk/lib/tk/scale.rb @@ -6,7 +6,7 @@ require 'tk' class Tk::Scale<TkWindow TkCommandNames = ['scale'.freeze].freeze WidgetClassName = 'Scale'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def create_self(keys) if keys and keys != None @@ -108,4 +108,5 @@ class Tk::Scale<TkWindow end #TkScale = Tk::Scale unless Object.const_defined? :TkScale -Tk.__set_toplevel_aliases__(:Tk, Tk::Scale, :TkScale) +#Tk.__set_toplevel_aliases__(:Tk, Tk::Scale, :TkScale) +Tk.__set_loaded_toplevel_aliases__('tk/scale.rb', :Tk, Tk::Scale, :TkScale) diff --git a/ext/tk/lib/tk/scrollbar.rb b/ext/tk/lib/tk/scrollbar.rb index decc4205c4..c0ac201acb 100644 --- a/ext/tk/lib/tk/scrollbar.rb +++ b/ext/tk/lib/tk/scrollbar.rb @@ -6,7 +6,7 @@ require 'tk' class Tk::Scrollbar<TkWindow TkCommandNames = ['scrollbar'.freeze].freeze WidgetClassName = 'Scrollbar'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def create_self(keys) @assigned = [] @@ -148,7 +148,9 @@ class Tk::Scrollbar<TkWindow end #TkScrollbar = Tk::Scrollbar unless Object.const_defined? :TkScrollbar -Tk.__set_toplevel_aliases__(:Tk, Tk::Scrollbar, :TkScrollbar) +#Tk.__set_toplevel_aliases__(:Tk, Tk::Scrollbar, :TkScrollbar) +Tk.__set_loaded_toplevel_aliases__('tk/scrollbar.rb', :Tk, Tk::Scrollbar, + :TkScrollbar) class Tk::XScrollbar<Tk::Scrollbar @@ -161,7 +163,9 @@ class Tk::XScrollbar<Tk::Scrollbar end #TkXScrollbar = Tk::XScrollbar unless Object.const_defined? :TkXScrollbar -Tk.__set_toplevel_aliases__(:Tk, Tk::XScrollbar, :TkXScrollbar) +#Tk.__set_toplevel_aliases__(:Tk, Tk::XScrollbar, :TkXScrollbar) +Tk.__set_loaded_toplevel_aliases__('tk/scrollbar.rb', :Tk, Tk::XScrollbar, + :TkXScrollbar) class Tk::YScrollbar<Tk::Scrollbar @@ -174,4 +178,6 @@ class Tk::YScrollbar<Tk::Scrollbar end #TkYScrollbar = Tk::YScrollbar unless Object.const_defined? :TkYScrollbar -Tk.__set_toplevel_aliases__(:Tk, Tk::YScrollbar, :TkYScrollbar) +#Tk.__set_toplevel_aliases__(:Tk, Tk::YScrollbar, :TkYScrollbar) +Tk.__set_loaded_toplevel_aliases__('tk/scrollbar.rb', :Tk, Tk::YScrollbar, + :TkYScrollbar) diff --git a/ext/tk/lib/tk/spinbox.rb b/ext/tk/lib/tk/spinbox.rb index 2fcc916237..f2917d60ca 100644 --- a/ext/tk/lib/tk/spinbox.rb +++ b/ext/tk/lib/tk/spinbox.rb @@ -8,7 +8,7 @@ require 'tk/entry' class Tk::Spinbox<Tk::Entry TkCommandNames = ['spinbox'.freeze].freeze WidgetClassName = 'Spinbox'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self class SpinCommand < TkValidateCommand class ValidateArgs < TkUtil::CallbackSubst @@ -100,13 +100,36 @@ class Tk::Spinbox<Tk::Entry tk_send_without_enc('identify', x, y) end + def invoke(elem) + tk_send_without_enc('invoke', elem) + self + end + def spinup - tk_send_without_enc('invoke', 'spinup') + begin + tk_send_without_enc('invoke', 'buttonup') + rescue RuntimeError => e + # old version of element? + begin + tk_send_without_enc('invoke', 'spinup') + rescue + fail e + end + end self end def spindown - tk_send_without_enc('invoke', 'spindown') + begin + tk_send_without_enc('invoke', 'buttondown') + rescue RuntimeError => e + # old version of element? + begin + tk_send_without_enc('invoke', 'spinup') + rescue + fail e + end + end self end @@ -116,4 +139,6 @@ class Tk::Spinbox<Tk::Entry end #TkSpinbox = Tk::Spinbox unless Object.const_defined? :TkSpinbox -Tk.__set_toplevel_aliases__(:Tk, Tk::Spinbox, :TkSpinbox) +#Tk.__set_toplevel_aliases__(:Tk, Tk::Spinbox, :TkSpinbox) +Tk.__set_loaded_toplevel_aliases__('tk/spinbox.rb', :Tk, Tk::Spinbox, + :TkSpinbox) diff --git a/ext/tk/lib/tk/text.rb b/ext/tk/lib/tk/text.rb index 42b8be475e..bc2aa0a293 100644 --- a/ext/tk/lib/tk/text.rb +++ b/ext/tk/lib/tk/text.rb @@ -29,6 +29,9 @@ module TkTextTagConfig end private :__item_pathname + def tag_cget_tkstring(tagOrId, option) + itemcget_tkstring(['tag', tagOrId], option) + end def tag_cget(tagOrId, option) itemcget(['tag', tagOrId], option) end @@ -45,6 +48,9 @@ module TkTextTagConfig current_itemconfiginfo(['tag', tagOrId], slot) end + def window_cget_tkstring(tagOrId, option) + itemcget_tkstring(['window', tagOrId], option) + end def window_cget(tagOrId, option) itemcget(['window', tagOrId], option) end @@ -61,7 +67,7 @@ module TkTextTagConfig current_itemconfiginfo(['window', tagOrId], slot) end - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo end @@ -251,7 +257,7 @@ class Tk::Text<TkTextWin TkCommandNames = ['text'.freeze].freeze WidgetClassName = 'Text'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def self.new(*args, &block) obj = super(*args){} @@ -1570,7 +1576,8 @@ class Tk::Text<TkTextWin end #TkText = Tk::Text unless Object.const_defined? :TkText -Tk.__set_toplevel_aliases__(:Tk, Tk::Text, :TkText) +#Tk.__set_toplevel_aliases__(:Tk, Tk::Text, :TkText) +Tk.__set_loaded_toplevel_aliases__('tk/text.rb', :Tk, Tk::Text, :TkText) ####################################### @@ -1587,7 +1594,8 @@ class Tk::Text::Peer < Tk::Text def create_self(keys) if keys and keys != None - tk_call_without_enc(@src_text.path, 'peer', 'create', @path) + tk_call_without_enc(@src_text.path, 'peer', 'create', + @path, *hash_kv(keys, true)) else tk_call_without_enc(@src_text.path, 'peer', 'create', @path) end diff --git a/ext/tk/lib/tk/textmark.rb b/ext/tk/lib/tk/textmark.rb index e9743475e0..d1888c5e54 100644 --- a/ext/tk/lib/tk/textmark.rb +++ b/ext/tk/lib/tk/textmark.rb @@ -9,7 +9,7 @@ class TkTextMark<TkObject TMarkID_TBL = TkCore::INTERP.create_table - (Tk_TextMark_ID = ['mark'.freeze, '00000'.taint]).instance_eval{ + (Tk_TextMark_ID = ['mark'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze diff --git a/ext/tk/lib/tk/texttag.rb b/ext/tk/lib/tk/texttag.rb index 7bd59bf8ee..96692014e4 100644 --- a/ext/tk/lib/tk/texttag.rb +++ b/ext/tk/lib/tk/texttag.rb @@ -11,7 +11,7 @@ class TkTextTag<TkObject TTagID_TBL = TkCore::INTERP.create_table - (Tk_TextTag_ID = ['tag'.freeze, '00000'.taint]).instance_eval{ + (Tk_TextTag_ID = ['tag'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze @@ -129,6 +129,9 @@ class TkTextTag<TkObject val end + def cget_tkstring(key) + @t.tag_cget_tkstring @id, key + end def cget(key) @t.tag_cget @id, key end diff --git a/ext/tk/lib/tk/timer.rb b/ext/tk/lib/tk/timer.rb index 686d4bd483..be2a8919e4 100644 --- a/ext/tk/lib/tk/timer.rb +++ b/ext/tk/lib/tk/timer.rb @@ -11,13 +11,13 @@ class TkTimer TkCommandNames = ['after'.freeze].freeze - (Tk_CBID = ['a'.freeze, '00000'.taint]).instance_eval{ + (Tk_CBID = ['a'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze } - Tk_CBTBL = {}.taint + Tk_CBTBL = TkUtil.untrust({}) TkCore::INTERP.add_tk_procs('rb_after', 'id', <<-'EOL') if {[set st [catch {eval {ruby_cmd TkTimer callback} $id} ret]] != 0} { diff --git a/ext/tk/lib/tk/toplevel.rb b/ext/tk/lib/tk/toplevel.rb index 917264aef7..30ef009517 100644 --- a/ext/tk/lib/tk/toplevel.rb +++ b/ext/tk/lib/tk/toplevel.rb @@ -11,7 +11,7 @@ class Tk::Toplevel<TkWindow TkCommandNames = ['toplevel'.freeze].freeze WidgetClassName = 'Toplevel'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self ################# old version # def initialize(parent=nil, screen=nil, classname=nil, keys=nil) @@ -259,4 +259,6 @@ class Tk::Toplevel<TkWindow end #TkToplevel = Tk::Toplevel unless Object.const_defined? :TkToplevel -Tk.__set_toplevel_aliases__(:Tk, Tk::Toplevel, :TkToplevel) +#Tk.__set_toplevel_aliases__(:Tk, Tk::Toplevel, :TkToplevel) +Tk.__set_loaded_toplevel_aliases__('tk/toplevel.rb', :Tk, Tk::Toplevel, + :TkToplevel) diff --git a/ext/tk/lib/tk/ttk_selector.rb b/ext/tk/lib/tk/ttk_selector.rb index 7a0dd34038..522249e6a9 100644 --- a/ext/tk/lib/tk/ttk_selector.rb +++ b/ext/tk/lib/tk/ttk_selector.rb @@ -53,21 +53,43 @@ module Tk :TkTreeview => 'tkextlib/tile/treeview', } - @TOPLEVEL_ALIAS_TABLE[:Tile] = @TOPLEVEL_ALIAS_TABLE[:Ttk] + + # @TOPLEVEL_ALIAS_TABLE[:Tile] = @TOPLEVEL_ALIAS_TABLE[:Ttk] + Tk.__create_widget_set__(:Tile, :Ttk) + + ############################################ + # depend on the version of Tcl/Tk + major, minor, type, patchlevel = TclTkLib.get_version + + # ttk::spinbox is supported on Tcl/Tk8.6b1 or later + if ([major,minor,type,patchlevel] <=> + [8,6,TclTkLib::RELEASE_TYPE::BETA,1]) >= 0 + @TOPLEVEL_ALIAS_TABLE[:Ttk].update( + :TkSpinbox => 'tkextlib/tile/tspinbox' + ) + end ################################################ # register some Ttk widgets as default # (Ttk is a standard library on Tcl/Tk8.5+) @TOPLEVEL_ALIAS_TABLE[:Ttk].each{|sym, file| - unless Object.autoload?(sym) || Object.const_defined?(sym) - Object.autoload(sym, file) - end + #unless Tk::TOPLEVEL_ALIASES.autoload?(sym) || Tk::TOPLEVEL_ALIASES.const_defined?(sym) + # @TOPLEVEL_ALIAS_OWNER[sym] = :Ttk + # Tk::TOPLEVEL_ALIASES.autoload(sym, file) + #end + Tk.__regist_toplevel_aliases__(:Ttk, file, sym) } ################################################ - @TOPLEVEL_ALIAS_SETUP_PROC[:Tile] = - @TOPLEVEL_ALIAS_SETUP_PROC[:Ttk] = proc{|mod| + # @TOPLEVEL_ALIAS_SETUP_PROC[:Tile] = + # @TOPLEVEL_ALIAS_SETUP_PROC[:Ttk] = proc{|mod| + # unless Tk.autoload?(:Tile) || Tk.const_defined?(:Tile) + # Object.autoload :Ttk, 'tkextlib/tile' + # Tk.autoload :Tile, 'tkextlib/tile' + # end + # } + Tk.__toplevel_alias_setup_proc__(:Ttk, :Tile){|mod| unless Tk.autoload?(:Tile) || Tk.const_defined?(:Tile) Object.autoload :Ttk, 'tkextlib/tile' Tk.autoload :Tile, 'tkextlib/tile' diff --git a/ext/tk/lib/tk/variable.rb b/ext/tk/lib/tk/variable.rb index bdd441705b..6fc2ffdf2f 100644 --- a/ext/tk/lib/tk/variable.rb +++ b/ext/tk/lib/tk/variable.rb @@ -16,7 +16,7 @@ class TkVariable #TkVar_ID_TBL = {} TkVar_CB_TBL = TkCore::INTERP.create_table TkVar_ID_TBL = TkCore::INTERP.create_table - (Tk_VARIABLE_ID = ["v".freeze, "00000".taint]).instance_eval{ + (Tk_VARIABLE_ID = ["v".freeze, TkUtil.untrust("00000")]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze @@ -1239,6 +1239,14 @@ end end end + def ===(other) + if other.kind_of?(TkVariable) + self.id == other.id + else + super + end + end + def zero? numeric.zero? end diff --git a/ext/tk/lib/tk/virtevent.rb b/ext/tk/lib/tk/virtevent.rb index ba771da647..19c0dac380 100644 --- a/ext/tk/lib/tk/virtevent.rb +++ b/ext/tk/lib/tk/virtevent.rb @@ -9,7 +9,7 @@ class TkVirtualEvent<TkObject TkCommandNames = ['event'.freeze].freeze - (TkVirtualEventID = ["VirtEvent".freeze, "00000".taint]).instance_eval{ + (TkVirtualEventID = ["VirtEvent".freeze, TkUtil.untrust("00000")]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze diff --git a/ext/tk/lib/tk/winpkg.rb b/ext/tk/lib/tk/winpkg.rb index a131731560..80e0439ace 100644 --- a/ext/tk/lib/tk/winpkg.rb +++ b/ext/tk/lib/tk/winpkg.rb @@ -10,7 +10,8 @@ require 'tk' module Tk::WinDDE end #TkWinDDE = Tk::WinDDE -Tk.__set_toplevel_aliases__(:Tk, Tk::WinDDE, :TkWinDDE) +#Tk.__set_toplevel_aliases__(:Tk, Tk::WinDDE, :TkWinDDE) +Tk.__set_loaded_toplevel_aliases__('tk/winpkg.rb', :Tk, Tk::WinDDE, :TkWinDDE) module Tk::WinDDE extend Tk @@ -93,7 +94,9 @@ end module Tk::WinRegistry end #TkWinRegistry = Tk::WinRegistry -Tk.__set_toplevel_aliases__(:Tk, Tk::WinRegistry, :TkWinRegistry) +#Tk.__set_toplevel_aliases__(:Tk, Tk::WinRegistry, :TkWinRegistry) +Tk.__set_loaded_toplevel_aliases__('tk/winpkg.rb', :Tk, Tk::WinRegistry, + :TkWinRegistry) module Tk::WinRegistry extend Tk |