diff options
Diffstat (limited to 'ext/tk/lib/tk')
45 files changed, 2722 insertions, 855 deletions
diff --git a/ext/tk/lib/tk/autoload.rb b/ext/tk/lib/tk/autoload.rb index 6b3773f4ea..0773f7708d 100644 --- a/ext/tk/lib/tk/autoload.rb +++ b/ext/tk/lib/tk/autoload.rb @@ -1,9 +1,19 @@ # # autoload # - -####################### +############################################ # geometry manager +module Tk + autoload :Grid, 'tk/grid' + def Grid(*args); TkGrid.configure(*args); end + + autoload :Pack, 'tk/pack' + def Pack(*args); TkPack.configure(*args); end + + autoload :Place, 'tk/place' + def Place(*args); TkPlace.configure(*args); end +end + autoload :TkGrid, 'tk/grid' def TkGrid(*args); TkGrid.configure(*args); end @@ -14,19 +24,117 @@ autoload :TkPlace, 'tk/place' def TkPlace(*args); TkPlace.configure(*args); end -####################### -# others +############################################ +# classes on Tk module +module Tk + autoload :Button, 'tk/button' + + autoload :Canvas, 'tk/canvas' + + autoload :CheckButton, 'tk/checkbutton' + autoload :Checkbutton, 'tk/checkbutton' + + autoload :Entry, 'tk/entry' + + autoload :Frame, 'tk/frame' + + autoload :Label, 'tk/label' + + autoload :LabelFrame, 'tk/labelframe' + autoload :Labelframe, 'tk/labelframe' + + autoload :Listbox, 'tk/listbox' + + autoload :Menu, 'tk/menu' + autoload :MenuClone, 'tk/menu' + autoload :CloneMenu, 'tk/menu' + autoload :SystemMenu, 'tk/menu' + autoload :SysMenu_Help, 'tk/menu' + autoload :SysMenu_System, 'tk/menu' + autoload :SysMenu_Apple, 'tk/menu' + autoload :Menubutton, 'tk/menu' + autoload :MenuButton, 'tk/menu' + autoload :OptionMenubutton, 'tk/menu' + autoload :OptionMenBbutton, 'tk/menu' + + autoload :Message, 'tk/message' + + autoload :PanedWindow, 'tk/panedwindow' + autoload :Panedwindow, 'tk/panedwindow' + + autoload :RadioButton, 'tk/radiobutton' + autoload :Radiobutton, 'tk/radiobutton' + + autoload :Root, 'tk/root' + + autoload :Scale, 'tk/scale' + + autoload :Scrollbar, 'tk/scrollbar' + autoload :XScrollbar, 'tk/scrollbar' + autoload :YScrollbar, 'tk/scrollbar' + + autoload :Spinbox, 'tk/spinbox' + + autoload :Text, 'tk/text' + + autoload :Toplevel, 'tk/toplevel' +end + + +############################################ +# sub-module of Tk +module Tk + autoload :Clock, 'tk/clock' + + autoload :OptionObj, 'tk/optionobj' + + autoload :X_Scrollable, 'tk/scrollable' + autoload :Y_Scrollable, 'tk/scrollable' + autoload :Scrollable, 'tk/scrollable' + + autoload :Wm, 'tk/wm' + autoload :Wm_for_General, 'tk/wm' + + autoload :MacResource, 'tk/macpkg' + + autoload :WinDDE, 'tk/winpkg' + autoload :WinRegistry, 'tk/winpkg' + + autoload :ValidateConfigure, 'tk/validation' + autoload :ItemValidateConfigure, 'tk/validation' + + autoload :EncodedString, 'tk/encodedstr' + def Tk.EncodedString(str, enc = nil); Tk::EncodedString.new(str, enc); end + + autoload :BinaryString, 'tk/encodedstr' + def Tk.BinaryString(str); Tk::BinaryString.new(str); end + + autoload :UTF8_String, 'tk/encodedstr' + def Tk.UTF8_String(str); Tk::UTF8_String.new(str); end + +end + + +############################################ +# toplevel classes/modules (fixed) autoload :TkBgError, 'tk/bgerror' autoload :TkBindTag, 'tk/bindtag' autoload :TkBindTagAll, 'tk/bindtag' autoload :TkDatabaseClass, 'tk/bindtag' -autoload :TkButton, 'tk/button' - autoload :TkConsole, 'tk/console' -autoload :TkCanvas, 'tk/canvas' +autoload :TkcItem, 'tk/canvas' +autoload :TkcArc, 'tk/canvas' +autoload :TkcBitmap, 'tk/canvas' +autoload :TkcImage, 'tk/canvas' +autoload :TkcLine, 'tk/canvas' +autoload :TkcOval, 'tk/canvas' +autoload :TkcPolygon, 'tk/canvas' +autoload :TkcRectangle, 'tk/canvas' +autoload :TkcText, 'tk/canvas' +autoload :TkcWindow, 'tk/canvas' autoload :TkcTagAccess, 'tk/canvastag' autoload :TkcTag, 'tk/canvastag' @@ -36,9 +144,6 @@ autoload :TkcTagAll, 'tk/canvastag' autoload :TkcTagCurrent, 'tk/canvastag' autoload :TkcTagGroup, 'tk/canvastag' -autoload :TkCheckButton, 'tk/checkbutton' -autoload :TkCheckbutton, 'tk/checkbutton' - autoload :TkClipboard, 'tk/clipboard' autoload :TkComposite, 'tk/composite' @@ -52,14 +157,10 @@ autoload :TkWarning, 'tk/dialog' autoload :TkWarning2, 'tk/dialog' autoload :TkWarningObj, 'tk/dialog' -autoload :TkEntry, 'tk/entry' - autoload :TkEvent, 'tk/event' autoload :TkFont, 'tk/font' -autoload :TkTreatTagFont, 'tk/font' - -autoload :TkFrame, 'tk/frame' +autoload :TkNamedFont, 'tk/font' autoload :TkImage, 'tk/image' autoload :TkBitmapImage, 'tk/image' @@ -71,30 +172,12 @@ autoload :TkTreatItemFont, 'tk/itemfont' autoload :TkKinput, 'tk/kinput' -autoload :TkLabel, 'tk/label' - -autoload :TkLabelFrame, 'tk/labelframe' -autoload :TkLabelframe, 'tk/labelframe' - -autoload :TkListbox, 'tk/listbox' - -autoload :TkMacResource, 'tk/macpkg' - -autoload :TkMenu, 'tk/menu' -autoload :TkMenuClone, 'tk/menu' autoload :TkSystemMenu, 'tk/menu' -autoload :TkSysMenu_Help, 'tk/menu' -autoload :TkSysMenu_System, 'tk/menu' -autoload :TkSysMenu_Apple, 'tk/menu' -autoload :TkMenubutton, 'tk/menu' -autoload :TkOptionMenubutton, 'tk/menu' autoload :TkMenubar, 'tk/menubar' autoload :TkMenuSpec, 'tk/menuspec' -autoload :TkMessage, 'tk/message' - autoload :TkManageFocus, 'tk/mngfocus' autoload :TkMsgCatalog, 'tk/msgcat' @@ -110,53 +193,46 @@ autoload :TkPackage, 'tk/package' autoload :TkPalette, 'tk/palette' -autoload :TkPanedWindow, 'tk/panedwindow' -autoload :TkPanedwindow, 'tk/panedwindow' - -autoload :TkRadioButton, 'tk/radiobutton' -autoload :TkRadiobutton, 'tk/radiobutton' - autoload :TkRoot, 'tk/root' -autoload :TkScale, 'tk/scale' - -autoload :TkScrollbar, 'tk/scrollbar' -autoload :TkXScrollbar, 'tk/scrollbar' -autoload :TkYScrollbar, 'tk/scrollbar' - autoload :TkScrollbox, 'tk/scrollbox' autoload :TkSelection, 'tk/selection' -autoload :TkSpinbox, 'tk/spinbox' - autoload :TkTreatTagFont, 'tk/tagfont' -autoload :TkText, 'tk/text' - autoload :TkTextImage, 'tk/textimage' +autoload :TktImage, 'tk/textimage' autoload :TkTextMark, 'tk/textmark' autoload :TkTextNamedMark, 'tk/textmark' autoload :TkTextMarkInsert, 'tk/textmark' autoload :TkTextMarkCurrent, 'tk/textmark' autoload :TkTextMarkAnchor, 'tk/textmark' +autoload :TktMark, 'tk/textmark' +autoload :TktNamedMark, 'tk/textmark' +autoload :TktMarkInsert, 'tk/textmark' +autoload :TktMarkCurrent, 'tk/textmark' +autoload :TktMarkAnchor, 'tk/textmark' autoload :TkTextTag, 'tk/texttag' autoload :TkTextNamedTag, 'tk/texttag' autoload :TkTextTagSel, 'tk/texttag' +autoload :TktTag, 'tk/texttag' +autoload :TktNamedTag, 'tk/texttag' +autoload :TktTagSel, 'tk/texttag' autoload :TkTextWindow, 'tk/textwindow' +autoload :TktWindow, 'tk/textwindow' autoload :TkAfter, 'tk/timer' autoload :TkTimer, 'tk/timer' autoload :TkRTTimer, 'tk/timer' -autoload :TkToplevel, 'tk/toplevel' - autoload :TkTextWin, 'tk/txtwin_abst' autoload :TkValidation, 'tk/validation' +autoload :TkValidateCommand, 'tk/validation' autoload :TkVariable, 'tk/variable' autoload :TkVarAccess, 'tk/variable' @@ -166,31 +242,173 @@ autoload :TkNamedVirtualEvent,'tk/virtevent' autoload :TkWinfo, 'tk/winfo' -autoload :TkWinDDE, 'tk/winpkg' -autoload :TkWinRegistry, 'tk/winpkg' - autoload :TkXIM, 'tk/xim' -####################### -# sub-module of Tk +############################################ +# toplevel classes/modules (switchable) module Tk - autoload :Clock, 'tk/clock' - autoload :OptionObj, 'tk/optionobj' - autoload :X_Scrollable, 'tk/scrollable' - autoload :Y_Scrollable, 'tk/scrollable' - autoload :Scrollable, 'tk/scrollable' - autoload :Wm, 'tk/wm' + @TOPLEVEL_ALIAS_TABLE = {} + @TOPLEVEL_ALIAS_TABLE[:Tk] = { + :TkButton => 'tk/button', - autoload :ValidateConfigure, 'tk/validation' - autoload :ItemValidateConfigure, 'tk/validation' + :TkCanvas => 'tk/canvas', - autoload :EncodedString, 'tk/encodedstr' - def Tk.EncodedString(str, enc = nil); Tk::EncodedString.new(str, enc); end + :TkCheckButton => 'tk/checkbutton', + :TkCheckbutton => 'tk/checkbutton', - autoload :BinaryString, 'tk/encodedstr' - def Tk.BinaryString(str); Tk::BinaryString.new(str); end + # :TkDialog => 'tk/dialog', + # :TkDialog2 => 'tk/dialog', + # :TkDialogObj => 'tk/dialog', + # :TkWarning => 'tk/dialog', + # :TkWarning2 => 'tk/dialog', + # :TkWarningObj => 'tk/dialog', - autoload :UTF8_String, 'tk/encodedstr' - def Tk.UTF8_String(str); Tk::UTF8_String.new(str); end + :TkEntry => 'tk/entry', + + :TkFrame => 'tk/frame', + + :TkLabel => 'tk/label', + + :TkLabelFrame => 'tk/labelframe', + :TkLabelframe => 'tk/labelframe', + + :TkListbox => 'tk/listbox', + + :TkMacResource => 'tk/macpkg', + + :TkMenu => 'tk/menu', + :TkMenuClone => 'tk/menu', + :TkCloneMenu => 'tk/menu', + # :TkSystemMenu => 'tk/menu', + :TkSysMenu_Help => 'tk/menu', + :TkSysMenu_System => 'tk/menu', + :TkSysMenu_Apple => 'tk/menu', + :TkMenubutton => 'tk/menu', + :TkMenuButton => 'tk/menu', + :TkOptionMenubutton => 'tk/menu', + :TkOptionMenuButton => 'tk/menu', + + :TkMessage => 'tk/message', + + :TkPanedWindow => 'tk/panedwindow', + :TkPanedwindow => 'tk/panedwindow', + + :TkRadioButton => 'tk/radiobutton', + :TkRadiobutton => 'tk/radiobutton', + + # :TkRoot => 'tk/root', + + :TkScale => 'tk/scale', + + :TkScrollbar => 'tk/scrollbar', + :TkXScrollbar => 'tk/scrollbar', + :TkYScrollbar => 'tk/scrollbar', + + :TkSpinbox => 'tk/spinbox', + + :TkText => 'tk/text', + + :TkToplevel => 'tk/toplevel', + + :TkWinDDE => 'tk/winpkg', + :TkWinRegistry => 'tk/winpkg', + } + + @TOPLEVEL_ALIAS_OWNER = {} + + @TOPLEVEL_ALIAS_SETUP_PROC = {} + + @current_default_widget_set = nil +end + + +############################################ +# methods to control default widget set +############################################ + +class << Tk + def default_widget_set + @current_default_widget_set + end + + def default_widget_set=(target) + target = target.to_sym + return target if target == @current_default_widget_set + + if (cmd = @TOPLEVEL_ALIAS_SETUP_PROC[target]) + cmd.call(target) + end + + _replace_toplevel_aliases(target) + end + + def __set_toplevel_aliases__(target, obj, *symbols) + @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) + 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) + end + } + end + + # 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) + else + # file => loaded class object + Object.const_set(sym, file) + end + @TOPLEVEL_ALIAS_OWNER[sym] = target + } + + # update current alias + @current_default_widget_set = target + end +end + +############################################ +# setup default widget set => :Tk +Tk.default_widget_set = :Tk + + +############################################ +# depend on the version of Tcl/Tk +# major, minor, type, type_name, patchlevel = TclTkLib.get_version + +############################################ +# Ttk (Tile) support +=begin +if major > 8 || + (major == 8 && minor > 5) || + (major == 8 && minor == 5 && type >= TclTkLib::RELEASE_TYPE::BETA) + # Tcl/Tk 8.5 beta or later + Object.autoload :Ttk, 'tkextlib/tile' + Tk.autoload :Tile, 'tkextlib/tile' + + require 'tk/ttk_selector' end +=end +Object.autoload :Ttk, 'tkextlib/tile' +Tk.autoload :Tile, 'tkextlib/tile' +require 'tk/ttk_selector' diff --git a/ext/tk/lib/tk/bindtag.rb b/ext/tk/lib/tk/bindtag.rb index 9023a08e06..88c8367a88 100644 --- a/ext/tk/lib/tk/bindtag.rb +++ b/ext/tk/lib/tk/bindtag.rb @@ -8,30 +8,64 @@ class TkBindTag #BTagID_TBL = {} BTagID_TBL = TkCore::INTERP.create_table - Tk_BINDTAG_ID = ["btag".freeze, "00000".taint].freeze - TkCore::INTERP.init_ip_env{ BTagID_TBL.clear } + (Tk_BINDTAG_ID = ["btag".freeze, "00000".taint]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + TkCore::INTERP.init_ip_env{ + BTagID_TBL.mutex.synchronize{ BTagID_TBL.clear } + } def TkBindTag.id2obj(id) - BTagID_TBL[id]? BTagID_TBL[id]: id + BTagID_TBL.mutex.synchronize{ + (BTagID_TBL[id])? BTagID_TBL[id]: id + } end +=begin def TkBindTag.new_by_name(name, *args, &b) - return BTagID_TBL[name] if BTagID_TBL[name] + BTagID_TBL.mutex.synchronize{ + return BTagID_TBL[name] if BTagID_TBL[name] + } + self.new.instance_eval{ - BTagID_TBL.delete @id - @id = name - BTagID_TBL[@id] = self + BTagID_TBL.mutex.synchronize{ + BTagID_TBL.delete @id + @id = name + BTagID_TBL[@id] = self + } bind(*args, &b) if args != [] self } end +=end + def TkBindTag.new_by_name(name, *args, &b) + obj = nil + BTagID_TBL.mutex.synchronize{ + if BTagID_TBL[name] + obj = BTagID_TBL[name] + else + (obj = BTagID_TBL[name] = self.allocate).instance_eval{ + @id = name + } + end + } + bind(*args, &b) if obj && args != [] + obj + end def initialize(*args, &b) - # @id = Tk_BINDTAG_ID.join('') - @id = Tk_BINDTAG_ID.join(TkCore::INTERP._ip_id_) - Tk_BINDTAG_ID[1].succ! - BTagID_TBL[@id] = self + Tk_BINDTAG_ID.mutex.synchronize{ + # @id = Tk_BINDTAG_ID.join('') + @id = Tk_BINDTAG_ID.join(TkCore::INTERP._ip_id_) + Tk_BINDTAG_ID[1].succ! + } + BTagID_TBL.mutex.synchronize{ + BTagID_TBL[@id] = self + } bind(*args, &b) if args != [] end @@ -63,14 +97,37 @@ end class TkDatabaseClass<TkBindTag +=begin def self.new(name, *args, &b) - return BTagID_TBL[name] if BTagID_TBL[name] + BTagID_TBL.mutex.synchronize{ + return BTagID_TBL[name] if BTagID_TBL[name] + } super(name, *args, &b) end def initialize(name, *args, &b) @id = name - BTagID_TBL[@id] = self + BTagID_TBL.mutex.synchronize{ + BTagID_TBL[@id] = self + } + bind(*args, &b) if args != [] + end +=end + def self.new(name, *args, &b) + BTagID_TBL.mutex.synchronize{ + if BTagID_TBL[name] + BTagID_TBL[name] + else + BTagID_TBL[name] = self.allocate.instance_eval{ + initialize(name, *args, &b) + self + } + end + } + end + + def initialize(name, *args, &b) + @id = name bind(*args, &b) if args != [] end diff --git a/ext/tk/lib/tk/button.rb b/ext/tk/lib/tk/button.rb index 407a47c400..770a5785bb 100644 --- a/ext/tk/lib/tk/button.rb +++ b/ext/tk/lib/tk/button.rb @@ -4,7 +4,7 @@ require 'tk' require 'tk/label' -class TkButton<TkLabel +class Tk::Button<Tk::Label TkCommandNames = ['button'.freeze].freeze WidgetClassName = 'Button'.freeze WidgetClassNames[WidgetClassName] = self @@ -25,3 +25,6 @@ class TkButton<TkLabel self end end + +#TkButton = Tk::Button unless Object.const_defined? :TkButton +Tk.__set_toplevel_aliases__(:Tk, Tk::Button, :TkButton) diff --git a/ext/tk/lib/tk/canvas.rb b/ext/tk/lib/tk/canvas.rb index c30fd79bb9..fceadd5e9c 100644 --- a/ext/tk/lib/tk/canvas.rb +++ b/ext/tk/lib/tk/canvas.rb @@ -1,6 +1,5 @@ # # tk/canvas.rb - Tk canvas classes -# $Date$ # by Yukihiro Matsumoto <matz@caelum.co.jp> # require 'tk' @@ -40,7 +39,7 @@ module TkCanvasItemConfig private :__item_pathname end -class TkCanvas<TkWindow +class Tk::Canvas<TkWindow include TkCanvasItemConfig include Tk::Scrollable @@ -186,11 +185,17 @@ class TkCanvas<TkWindow end def delete(*args) - if TkcItem::CItemID_TBL[self.path] + tbl = nil + TkcItem::CItemID_TBL.mutex.synchronize{ + tbl = TkcItem::CItemID_TBL[self.path] + } + if tbl args.each{|tag| find('withtag', tag).each{|item| if item.kind_of?(TkcItem) - TkcItem::CItemID_TBL[self.path].delete(item.id) + TkcItem::CItemID_TBL.mutex.synchronize{ + tbl.delete(item.id) + } end } } @@ -573,6 +578,10 @@ class TkCanvas<TkWindow end end +#TkCanvas = Tk::Canvas unless Object.const_defined? :TkCanvas +Tk.__set_toplevel_aliases__(:Tk, Tk::Canvas, :TkCanvas) + + class TkcItem<TkObject extend Tk include TkcTagAccess @@ -581,9 +590,12 @@ class TkcItem<TkObject CItemTypeName = nil CItemTypeToClass = {} + CItemID_TBL = TkCore::INTERP.create_table - TkCore::INTERP.init_ip_env{ CItemID_TBL.clear } + TkCore::INTERP.init_ip_env{ + CItemID_TBL.mutex.synchronize{ CItemID_TBL.clear } + } def TkcItem.type2class(type) CItemTypeToClass[type] @@ -591,8 +603,13 @@ class TkcItem<TkObject def TkcItem.id2obj(canvas, id) cpath = canvas.path - return id unless CItemID_TBL[cpath] - CItemID_TBL[cpath][id]? CItemID_TBL[cpath][id]: id + CItemID_TBL.mutex.synchronize{ + if CItemID_TBL[cpath] + CItemID_TBL[cpath][id]? CItemID_TBL[cpath][id]: id + else + id + end + } end ######################################## @@ -658,15 +675,17 @@ class TkcItem<TkObject ######################################## def initialize(parent, *args) - #unless parent.kind_of?(TkCanvas) - # fail ArgumentError, "expect TkCanvas for 1st argument" + #unless parent.kind_of?(Tk::Canvas) + # fail ArgumentError, "expect Tk::Canvas for 1st argument" #end @parent = @c = parent @path = parent.path @id = create_self(*args) # an integer number as 'canvas item id' - CItemID_TBL[@path] = {} unless CItemID_TBL[@path] - CItemID_TBL[@path][@id] = self + CItemID_TBL.mutex.synchronize{ + CItemID_TBL[@path] = {} unless CItemID_TBL[@path] + CItemID_TBL[@path][@id] = self + } end def create_self(*args) self.class.create(@c, *args) # return an integer number as 'canvas item id' @@ -687,7 +706,9 @@ class TkcItem<TkObject def delete @c.delete @id - CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path] + CItemID_TBL.mutex.synchronize{ + CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path] + } self end alias remove delete diff --git a/ext/tk/lib/tk/canvastag.rb b/ext/tk/lib/tk/canvastag.rb index a5650ee68b..7feea1575c 100644 --- a/ext/tk/lib/tk/canvastag.rb +++ b/ext/tk/lib/tk/canvastag.rb @@ -199,14 +199,26 @@ class TkcTag<TkObject include TkcTagAccess CTagID_TBL = TkCore::INTERP.create_table - Tk_CanvasTag_ID = ['ctag'.freeze, '00000'.taint].freeze - TkCore::INTERP.init_ip_env{ CTagID_TBL.clear } + (Tk_CanvasTag_ID = ['ctag'.freeze, '00000'.taint]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + TkCore::INTERP.init_ip_env{ + CTagID_TBL.mutex.synchronize{ CTagID_TBL.clear } + } def TkcTag.id2obj(canvas, id) cpath = canvas.path - return id unless CTagID_TBL[cpath] - CTagID_TBL[cpath][id]? CTagID_TBL[cpath][id]: id + CTagID_TBL.mutex.synchronize{ + if CTagID_TBL[cpath] + CTagID_TBL[cpath][id]? CTagID_TBL[cpath][id]: id + else + id + end + } end def initialize(parent, mode=nil, *args) @@ -215,11 +227,15 @@ class TkcTag<TkObject #end @c = parent @cpath = parent.path - # @path = @id = Tk_CanvasTag_ID.join('') - @path = @id = Tk_CanvasTag_ID.join(TkCore::INTERP._ip_id_) - CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath] - CTagID_TBL[@cpath][@id] = self - Tk_CanvasTag_ID[1].succ! + Tk_CanvasTag_ID.mutex.synchronize{ + # @path = @id = Tk_CanvasTag_ID.join('') + @path = @id = Tk_CanvasTag_ID.join(TkCore::INTERP._ip_id_) + Tk_CanvasTag_ID[1].succ! + } + CTagID_TBL.mutex.synchronize{ + CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath] + CTagID_TBL[@cpath][@id] = self + } if mode tk_call_without_enc(@c.path, "addtag", @id, mode, *args) end @@ -238,7 +254,9 @@ class TkcTag<TkObject def delete @c.delete @id - CTagID_TBL[@cpath].delete(@id) if CTagID_TBL[@cpath] + CTagID_TBL.mutex.synchronize{ + CTagID_TBL[@cpath].delete(@id) if CTagID_TBL[@cpath] + } self end alias remove delete @@ -288,23 +306,38 @@ class TkcTag<TkObject end class TkcTagString<TkcTag - def self.new(parent, name, *args) - if CTagID_TBL[parent.path] && CTagID_TBL[parent.path][name] - return CTagID_TBL[parent.path][name] - else - super(parent, name, *args) + def self.new(parent, name, mode=nil, *args) + obj = nil + CTagID_TBL.mutex.synchronize{ + if CTagID_TBL[parent.path] && CTagID_TBL[parent.path][name] + obj = CTagID_TBL[parent.path][name] + else + # super(parent, name, *args) + (obj = self.allocate).instance_eval{ + @c = parent + @cpath = parent.path + @path = @id = name + CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath] + CTagID_TBL[@cpath][@id] = self + } + end + } + if obj && mode + tk_call_without_enc(@c.path, "addtag", @id, mode, *args) end + obj end def initialize(parent, name, mode=nil, *args) + # dummy:: not called by 'new' method + #unless parent.kind_of?(TkCanvas) # fail ArgumentError, "expect TkCanvas for 1st argument" #end @c = parent @cpath = parent.path @path = @id = name - CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath] - CTagID_TBL[@cpath][@id] = self + if mode tk_call_without_enc(@c.path, "addtag", @id, mode, *args) end @@ -312,7 +345,11 @@ class TkcTagString<TkcTag end TkcNamedTag = TkcTagString -class TkcTagAll<TkcTag +class TkcTagAll<TkcTagString + def self.new(parent) + super(parent, 'all') + end +=begin def initialize(parent) #unless parent.kind_of?(TkCanvas) # fail ArgumentError, "expect TkCanvas for 1st argument" @@ -320,12 +357,19 @@ class TkcTagAll<TkcTag @c = parent @cpath = parent.path @path = @id = 'all' - CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath] - CTagID_TBL[@cpath][@id] = self + CTagID_TBL.mutex.synchronize{ + CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath] + CTagID_TBL[@cpath][@id] = self + } end +=end end -class TkcTagCurrent<TkcTag +class TkcTagCurrent<TkcTagString + def self.new(parent) + super(parent, 'current') + end +=begin def initialize(parent) #unless parent.kind_of?(TkCanvas) # fail ArgumentError, "expect TkCanvas for 1st argument" @@ -333,13 +377,21 @@ class TkcTagCurrent<TkcTag @c = parent @cpath = parent.path @path = @id = 'current' - CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath] - CTagID_TBL[@cpath][@id] = self + CTagID_TBL.mutex.synchronize{ + CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath] + CTagID_TBL[@cpath][@id] = self + } end +=end end class TkcGroup<TkcTag - Tk_cGroup_ID = ['tkcg'.freeze, '00000'.taint].freeze + (Tk_cGroup_ID = ['tkcg'.freeze, '00000'.taint]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + #def create_self(parent, *args) def initialize(parent, *args) #unless parent.kind_of?(TkCanvas) @@ -347,11 +399,15 @@ class TkcGroup<TkcTag #end @c = parent @cpath = parent.path - # @path = @id = Tk_cGroup_ID.join('') - @path = @id = Tk_cGroup_ID.join(TkCore::INTERP._ip_id_) - CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath] - CTagID_TBL[@cpath][@id] = self - Tk_cGroup_ID[1].succ! + Tk_cGroup_ID.mutex.synchronize{ + # @path = @id = Tk_cGroup_ID.join('') + @path = @id = Tk_cGroup_ID.join(TkCore::INTERP._ip_id_) + Tk_cGroup_ID[1].succ! + } + CTagID_TBL.mutex.synchronize{ + CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath] + CTagID_TBL[@cpath][@id] = self + } include(*args) if args != [] end #private :create_self diff --git a/ext/tk/lib/tk/checkbutton.rb b/ext/tk/lib/tk/checkbutton.rb index d76d99c0f2..b1186a87ed 100644 --- a/ext/tk/lib/tk/checkbutton.rb +++ b/ext/tk/lib/tk/checkbutton.rb @@ -4,7 +4,7 @@ require 'tk' require 'tk/radiobutton' -class TkCheckButton<TkRadioButton +class Tk::CheckButton<Tk::RadioButton TkCommandNames = ['checkbutton'.freeze].freeze WidgetClassName = 'Checkbutton'.freeze WidgetClassNames[WidgetClassName] = self @@ -22,4 +22,9 @@ class TkCheckButton<TkRadioButton self end end -TkCheckbutton = TkCheckButton + +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) diff --git a/ext/tk/lib/tk/composite.rb b/ext/tk/lib/tk/composite.rb index eaed8ed363..728b02f608 100644 --- a/ext/tk/lib/tk/composite.rb +++ b/ext/tk/lib/tk/composite.rb @@ -34,7 +34,8 @@ module TkComposite if klass # WidgetClassName is a known class - if klass <= TkFrame || klass < TkComposite + #if klass <= TkFrame || klass < TkComposite + if klass <= TkFrame || klass < Tk::Frame || klass < TkComposite # klass is valid for the base frame if self.class <= klass # use my classname @@ -50,7 +51,8 @@ module TkComposite else # klass is invalid for the base frame - if self.class < TkFrame || self.class.superclass < TkComposite + #if self.class < TkFrame || self.class.superclass < TkComposite + if self.class < TkFrame || self.class.superclass < Tk::Frame || self.class.superclass < TkComposite # my class name is valid for the base frame -> use my classname base_class_name = self.class.name if base_class_name == '' @@ -69,7 +71,8 @@ module TkComposite else # no valid WidgetClassName - if self.class < TkFrame || self.class.superclass < TkComposite + #if self.class < TkFrame || self.class.superclass < TkComposite + if self.class < TkFrame || self.class.superclass < Tk::Frame || self.class.superclass < TkComposite # my class name is valid for the base frame -> use my classname base_class_name = self.class.name if base_class_name == '' @@ -108,8 +111,12 @@ module TkComposite end if base_class_name + # @frame = Tk::Frame.new(parent, :class=>base_class_name) + # --> use current TkFrame class @frame = TkFrame.new(parent, :class=>base_class_name) else + # @frame = Tk::Frame.new(parent) + # --> use current TkFrame class @frame = TkFrame.new(parent) end @path = @epath = @frame.path @@ -133,6 +140,11 @@ module TkComposite def initialize_composite(*args) end private :initialize_composite + def inspect + str = super + str.chop << ' @epath=' << @epath.inspect << '>' + end + def option_methods(*opts) opts.each{|m_set, m_cget, m_info| m_set = m_set.to_s diff --git a/ext/tk/lib/tk/encodedstr.rb b/ext/tk/lib/tk/encodedstr.rb index 797e514a4c..02de0b0d85 100644 --- a/ext/tk/lib/tk/encodedstr.rb +++ b/ext/tk/lib/tk/encodedstr.rb @@ -70,13 +70,89 @@ module Tk # @encoding = ( enc || # ((self.class::Encoding)? # self.class::Encoding : Tk.encoding_system) ) - @encoding = ( enc || - ((self.class::Encoding)? + enc ||= (self.class::Encoding)? self.class::Encoding : - ((Tk.encoding)? Tk.encoding : Tk.encoding_system) ) ) + ((Tk.encoding)? Tk.encoding : Tk.encoding_system) + if TkCore::WITH_ENCODING + unless encobj = Tk::Encoding::ENCODING_TABLE.get_obj(enc) + fail ArgumentError, "unsupported Tk encoding '#{enc}'" + end + self.force_encoding(encobj) + else + @encoding = enc + end + end + + if TkCore::WITH_ENCODING + alias encoding_obj encoding + alias __encoding encoding + def encoding + Tk::Encoding::ENCODING_TABLE.get_name(super()) + end + else + def encoding + @encoding + end + alias encoding_obj encoding end - attr_reader :encoding + if TkCore::WITH_ENCODING + # wrapper methods for compatibility + alias __instance_variable_get instance_variable_get + alias __instance_variable_set instance_variable_set + alias __instance_eval instance_eval + alias __instance_variables instance_variables + + def instance_variable_get(key) + if (key.to_s == '@encoding') + self.encoding + else + super(key) + end + end + + def instance_variable_set(key, value) + if (key.to_s == '@encoding') + if value + self.force_encoding(value) + else + self.force_encoding(Tk::Encoding::UNKNOWN) + end + value + else + super(key, value) + end + end + + def instance_eval(*args, &b) + old_enc = @encoding = self.encoding + + ret = super(*args, &b) + + if @encoding + if @encoding != old_enc + # modified by user + self.force_encoding(@encoding) + end + remove_instance_variable(:@encoding) + else + begin + remove_instance_variable(:@encoding) + # user sets to nil -> use current default + self.force_encoding(Tk.encoding) + rescue NameError + # removed by user -> ignore, because user don't use @encoding + end + end + ret + end + end + + def instance_variables + ret = super() + ret << :@encoding # fake !! + ret + end end # def Tk.EncodedString(str, enc = nil) # Tk::EncodedString.new(str, enc) diff --git a/ext/tk/lib/tk/entry.rb b/ext/tk/lib/tk/entry.rb index 4ac3f28229..8ce8def1e7 100644 --- a/ext/tk/lib/tk/entry.rb +++ b/ext/tk/lib/tk/entry.rb @@ -1,6 +1,5 @@ # # tk/entry.rb - Tk entry classes -# $Date$ # by Yukihiro Matsumoto <matz@caelum.co.jp> require 'tk' @@ -8,7 +7,7 @@ require 'tk/label' require 'tk/scrollable' require 'tk/validation' -class TkEntry<TkLabel +class Tk::Entry<Tk::Label include X_Scrollable include TkValidation @@ -115,3 +114,6 @@ class TkEntry<TkLabel val end end + +#TkEntry = Tk::Entry unless Object.const_defined? :TkEntry +Tk.__set_toplevel_aliases__(:Tk, Tk::Entry, :TkEntry) diff --git a/ext/tk/lib/tk/event.rb b/ext/tk/lib/tk/event.rb index 70a1e38bbe..0042fcaa63 100644 --- a/ext/tk/lib/tk/event.rb +++ b/ext/tk/lib/tk/event.rb @@ -39,7 +39,9 @@ module TkEvent RESIZEREQ = 0x200000 CIRCREQ = 0x400000 - MWHEEL = 0x10000000 + MWHEEL = KEY + + STRING_DATA = 0x80000000 # special flag for 'data' field ALL = 0xFFFFFFFF @@ -155,7 +157,7 @@ module TkEvent 'borderwidth' => (Grp::CREATE|Grp::CONFIG), 'button' => Grp::BUTTON, 'count' => Grp::EXPOSE, - 'data' => Grp::VIRTUAL, + 'data' => (Grp::VIRTUAL|Grp::STRING_DATA), 'delta' => Grp::MWHEEL, 'detail' => (Grp::FOCUS|Grp::CROSSING), 'focus' => Grp::CROSSING, @@ -223,7 +225,8 @@ module TkEvent rescue next end - next if !val || val == '??' + # next if !val || val == '??' + next if !val || (val == '??' && (flag & Grp::STRING_DATA)) fields[key] = val } @@ -298,31 +301,54 @@ module TkEvent [ ?b, ?n, :num ], [ ?c, ?n, :count ], [ ?d, ?s, :detail ], + # ?e [ ?f, ?b, :focus ], + # ?g [ ?h, ?n, :height ], [ ?i, ?s, :win_hex ], + # ?j [ ?k, ?n, :keycode ], + # ?l [ ?m, ?s, :mode ], + # ?n [ ?o, ?b, :override ], [ ?p, ?s, :place ], + # ?q + # ?r [ ?s, ?x, :state ], [ ?t, ?n, :time ], + # ?u + [ ?v, ?n, :value_mask ], [ ?w, ?n, :width ], [ ?x, ?n, :x ], [ ?y, ?n, :y ], + # ?z [ ?A, ?s, :char ], [ ?B, ?n, :borderwidth ], + # ?C [ ?D, ?n, :wheel_delta ], [ ?E, ?b, :send_event ], + # ?F + # ?G + # ?H + # ?I + # ?J [ ?K, ?s, :keysym ], + # ?L + # ?M [ ?N, ?n, :keysym_num ], + # ?O [ ?P, ?s, :property ], + # ?Q [ ?R, ?s, :rootwin_id ], [ ?S, ?s, :subwindow ], [ ?T, ?n, :type ], + # ?U + # ?V [ ?W, ?w, :widget ], [ ?X, ?n, :x_root ], [ ?Y, ?n, :y_root ], + # ?Z nil ] @@ -345,6 +371,22 @@ module TkEvent nil ] + # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) + KEY_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) + end + inf + } + + PROC_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + end + inf + } + # setup tables to be used by scan_args, _get_subst_key, _get_all_subst_keys # # _get_subst_key() and _get_all_subst_keys() generates key-string diff --git a/ext/tk/lib/tk/font.rb b/ext/tk/lib/tk/font.rb index ab58ac5762..4641d8a640 100644 --- a/ext/tk/lib/tk/font.rb +++ b/ext/tk/lib/tk/font.rb @@ -11,13 +11,18 @@ class TkFont TkCommandNames = ['font'.freeze].freeze - Tk_FontID = ["@font".freeze, "00000".taint].freeze + (Tk_FontID = ["@font".freeze, "00000".taint]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + Tk_FontNameTBL = TkCore::INTERP.create_table Tk_FontUseTBL = TkCore::INTERP.create_table TkCore::INTERP.init_ip_env{ - Tk_FontNameTBL.clear - Tk_FontUseTBL.clear + Tk_FontNameTBL.mutex.synchronize{ Tk_FontNameTBL.clear } + Tk_FontUseTBL.mutex.synchronize{ Tk_FontUseTBL.clear } } # option_type : default => string @@ -31,13 +36,26 @@ class TkFont MetricType = Hash.new(?n) MetricType['fixed'] = ?b + # system font names + SYSTEM_FONT_NAMES = [] + def SYSTEM_FONT_NAMES.add(font_names) + (@mutex ||= Mutex.new).synchronize{ + self.replace(self | font_names.map{|name| name.to_s}) + } + end + def SYSTEM_FONT_NAMES.include?(name) + (@mutex ||= Mutex.new).synchronize{ + super(name.to_s) + } + end + # set default font case Tk::TK_VERSION - when /^4\.*/ + when /^4\..*/ DEFAULT_LATIN_FONT_NAME = 'a14'.freeze DEFAULT_KANJI_FONT_NAME = 'k14'.freeze - when /^8\.*/ + when /^8\.[0-4]/ if JAPANIZED_TK begin fontnames = tk_call('font', 'names') @@ -103,6 +121,15 @@ class TkFont DEFAULT_LATIN_FONT_NAME = ltn.freeze DEFAULT_KANJI_FONT_NAME = knj.freeze + when /^8\.[5-9]/, /^9\..*/ + if tk_call('font', 'names') =~ /\bTkDefaultFont\b/ + DEFAULT_LATIN_FONT_NAME = 'TkDefaultFont'.freeze + DEFAULT_KANJI_FONT_NAME = 'TkDefaultFont'.freeze + else + DEFAULT_LATIN_FONT_NAME = 'Helvetica'.freeze + DEFAULT_KANJI_FONT_NAME = 'mincho'.freeze + end + else # unknown version DEFAULT_LATIN_FONT_NAME = 'Helvetica'.freeze DEFAULT_KANJI_FONT_NAME = 'mincho'.freeze @@ -121,6 +148,7 @@ class TkFont unless compound.kind_of?(TkFont) fail ArgumentError, "a TkFont object is expected for the 1st argument" end + @compound = compound case type when 'kanji', 'latin', 'ascii' @@ -145,6 +173,9 @@ class TkFont def font @compound.__send__(@type + '_font_id') end + alias font_id font + alias name font + alias to_s font def [](slot) @compound.__send__(@type + '_configinfo', slot) @@ -163,6 +194,14 @@ class TkFont ################################### # class methods ################################### + def TkFont.is_system_font?(fnt) + # true --> system font which is available on the current system + # false --> not system font (or unknown system font) + # nil --> system font name, but not available on the current system + fnt = fnt.to_s + SYSTEM_FONT_NAMES.include?(fnt) && self.names.index(fnt) && true + end + def TkFont.actual(fnt, option=nil) fnt = '{}' if fnt == '' if fnt.kind_of?(TkFont) @@ -171,6 +210,9 @@ class TkFont actual_core(fnt, nil, option) end end + def TkFont.actual_hash(fnt, option=nil) + Hash[TkFont.actual_hash(fnt, option)] + end def TkFont.actual_displayof(fnt, win, option=nil) fnt = '{}' if fnt == '' @@ -181,6 +223,9 @@ class TkFont actual_core(fnt, win, option) end end + def TkFont.actual_hash_displayof(fnt, option=nil) + Hash[TkFont.actual_hash_displayof(fnt, option)] + end def TkFont.configure(fnt, slot, value=None) if fnt.kind_of?(TkFont) @@ -234,6 +279,33 @@ class TkFont metrics_core(fnt, nil, option) end end + def TkFont.metrics_hash(fnt, option=nil) + if option + val = TkFont.metrics(fnt, option) + case TkFont::MetricsType[option.to_s] + when ?n + val = TkComm::num_or_str(val) + when ?b + val = TkComm::bool(val) + else + # do nothing + end + return val + end + + h = Hash[TkFont.metrics(fnt)] + h.keys.each{|k| + case TkFont::MetricsType[k.to_s] + when ?n + h[k] = TkComm::num_or_str(h[k]) + when ?b + h[k] = TkComm::bool(h[k]) + else + # do nothing + end + } + h + end def TkFont.metrics_displayof(fnt, win, option=nil) fnt = '{}' if fnt == '' @@ -244,13 +316,40 @@ class TkFont metrics_core(fnt, win, option) end end + def TkFont.metrics_hash_displayof(fnt, win, option=nil) + if option + val = TkFont.metrics_displayof(fnt, win, option) + case TkFont::MetricsType[option.to_s] + when ?n + val = TkComm::num_or_str(val) + when ?b + val = TkComm::bool(val) + else + # do nothing + end + return val + end + + h = Hash[TkFont.metrics_displayof(fnt, win, option)] + h.keys.each{|k| + case TkFont::MetricsType[k.to_s] + when ?n + h[k] = TkComm::num_or_str(h[k]) + when ?b + h[k] = TkComm::bool(h[k]) + else + # do nothing + end + } + h + end def TkFont.families(win=nil) case (Tk::TK_VERSION) - when /^4\.*/ + when /^4\..*/ ['fixed'] - when /^8\.*/ + when /^8\..*/ if win tk_split_simplelist(tk_call('font', 'families', '-displayof', win)) else @@ -261,13 +360,16 @@ class TkFont def TkFont.names case (Tk::TK_VERSION) - when /^4\.*/ + when /^4\..*/ r = ['fixed'] r += ['a14', 'k14'] if JAPANIZED_TK - Tk_FontNameTBL.each_value{|obj| r.push(obj)} - r | [] + Tk_FontNameTBL.mutex.synchronize{ + Tk_FontNameTBL.each_value{|obj| r.push(obj)} + } + #r | [] + r.uniq - when /^8\.*/ + when /^8\..*/ tk_split_simplelist(tk_call('font', 'names')) end @@ -285,10 +387,15 @@ class TkFont end def TkFont.get_obj(name) + name = name.to_s if name =~ /^(@font[0-9]+)(|c|l|k)$/ - Tk_FontNameTBL[$1] + Tk_FontNameTBL.mutex.synchronize{ + Tk_FontNameTBL[$1] + } else - nil + Tk_FontNameTBL.mutex.synchronize{ + Tk_FontNameTBL[name] + } end end @@ -298,7 +405,7 @@ class TkFont path = [win, tag, key].join(';') case (Tk::TK_VERSION) - when /^4\.*/ + when /^4\..*/ regexp = /^-(|kanji)#{key} / conf_list = tk_split_simplelist(tk_call(*args)). @@ -324,7 +431,7 @@ class TkFont TkFont.new(ltn, knj).call_font_configure([path, key], *args) - when /^8\.*/ + when /^8\.[0-4]/ regexp = /^-#{key} / conf_list = tk_split_simplelist(tk_call(*args)). @@ -360,26 +467,66 @@ class TkFont compound = [] end if compound == [] - TkFont.new(fnt).call_font_configure([path, key], *args) + if TkFont.is_system_font?(fnt) + TkNamedFont.new(fnt).call_font_configure([path, key], *args) + else + TkFont.new(fnt).call_font_configure([path, key], *args) + end else TkFont.new(compound[0], compound[1]).call_font_configure([path, key], *args) end end + + when /^8\.[5-9]/, /^9\..*/ + regexp = /^-#{key} / + + conf_list = tk_split_simplelist(tk_call(*args)). + find_all{|prop| prop =~ regexp}. + collect{|prop| tk_split_simplelist(prop)} + + if conf_list.size == 0 + raise RuntimeError, "the widget may not support 'font' option" + end + + args << {} + + optkey = "-#{key}" + + info = conf_list.find{|conf| conf[0] == optkey} + fnt = info[-1] + fnt = nil if fnt == [] || fnt == "" + + unless fnt + # create dummy + # TkFont.new(nil, nil).call_font_configure([path, key], *args) + dummy_fnt = TkFont.allocate + dummy_fnt.instance_eval{ init_dummy_fontobj() } + dummy_fnt + else + if TkFont.is_system_font?(fnt) + TkNamedFont.new(fnt).call_font_configure([path, key], *args) + else + TkFont.new(fnt).call_font_configure([path, key], *args) + end + end end end def TkFont.used_on(path=nil) - if path - Tk_FontUseTBL[path] - else - Tk_FontUseTBL.values | [] - end + Tk_FontUseTBL.mutex.synchronize{ + if path + Tk_FontUseTBL[path] + else + # Tk_FontUseTBL.values | [] + Tk_FontUseTBL.values.uniq + end + } end def TkFont.failsafe(font) begin - if /^8\.*/ === Tk::TK_VERSION && JAPANIZED_TK + if /^8\..*/ === Tk::TK_VERSION && JAPANIZED_TK tk_call('font', 'failsafe', font) end rescue @@ -392,15 +539,20 @@ class TkFont private ################################### def init_dummy_fontobj - @id = Tk_FontID.join(TkCore::INTERP._ip_id_) - Tk_FontID[1].succ! - Tk_FontNameTBL[@id] = self + Tk_FontID.mutex.synchronize{ + @id = Tk_FontID.join(TkCore::INTERP._ip_id_) + Tk_FontID[1].succ! + } + Tk_FontNameTBL.mutex.synchronize{ + Tk_FontNameTBL[@id] = self + } - @latin_desscendant = nil - @kanji_desscendant = nil + # @latin_desscendant = nil + # @kanji_desscendant = nil + @descendant = [nil, nil] # [latin, kanji] case (Tk::TK_VERSION) - when /^4\.*/ + when /^4\..*/ @latinfont = "" @kanjifont = "" if JAPANIZED_TK @@ -436,13 +588,23 @@ class TkFont ltn = '{}' if ltn == '' knj = '{}' if knj == '' - # @id = Tk_FontID.join('') - @id = Tk_FontID.join(TkCore::INTERP._ip_id_) - Tk_FontID[1].succ! - Tk_FontNameTBL[@id] = self + Tk_FontID.mutex.synchronize{ + # @id = Tk_FontID.join('') + @id = Tk_FontID.join(TkCore::INTERP._ip_id_) + Tk_FontID[1].succ! + } + Tk_FontNameTBL.mutex.synchronize{ + Tk_FontNameTBL[@id] = self + } + + # @latin_desscendant = nil + # @kanji_desscendant = nil + @descendant = [nil, nil] # [latin, kanji] - @latin_desscendant = nil - @kanji_desscendant = nil + # @latinfont = @id + 'l' + # @kanjifont = @id + 'k' + # @compoundfont = @id + 'c' + # @fontslot = {} if knj.kind_of?(Hash) && !keys keys = knj @@ -474,7 +636,7 @@ class TkFont if ltn if JAPANIZED_TK && !knj - if Tk::TK_VERSION =~ /^4.*/ + if Tk::TK_VERSION =~ /^4..*/ knj = DEFAULT_KANJI_FONT_NAME else knj = ltn @@ -625,9 +787,14 @@ class TkFont if JAPANIZED_TK @compoundfont = [[@latinfont], [@kanjifont]] @fontslot = {'font'=>@latinfont, 'kanjifont'=>@kanjifont} + # @fontslot.clear + # @fontslot['font'] = @latinfont + # @fontslot['kanjifont'] = @kanjifont else @compoundfont = @latinfont @fontslot = {'font'=>@latinfont} + # @fontslot.clear + # @fontslot['font'] = @latinfont end end @@ -753,6 +920,7 @@ class TkFont end @fontslot = {'font'=>@compoundfont} + # @fontslot['font'] = @compoundfont begin tk_call('font', 'create', @compoundfont, '-compound', [@latinfont, @kanjifont], *hash_kv(keys)) @@ -833,6 +1001,7 @@ class TkFont end @fontslot = {'font'=>@compoundfont} + # @fontslot['font'] = @compoundfont tk_call('font', 'configure', @compoundfont, *hash_kv(keys)) end end @@ -888,24 +1057,32 @@ class TkFont keys = _symbolkey2str(args.pop).update(fontslot) args.concat(hash_kv(keys)) tk_call(*args) - Tk_FontUseTBL[[win, tag, optkey].join(';')] = self + Tk_FontUseTBL.mutex.synchronize{ + Tk_FontUseTBL[[win, tag, optkey].join(';')] = self + } self end def used ret = [] - Tk_FontUseTBL.each{|key,value| + table = nil + Tk_FontUseTBL.mutex.synchronize{ + table = Tk_FontUseTBL.clone # to avoid deadlock + } + table.each{|key,value| next unless self == value if key.include?(';') win, tag, optkey = key.split(';') winobj = tk_tcl2ruby(win) - if winobj.kind_of? TkText + #if winobj.kind_of? TkText + if winobj.kind_of?(TkText) || winobj.kind_of?(Tk::Text) if optkey ret.push([winobj, winobj.tagid2obj(tag), optkey]) else ret.push([winobj, winobj.tagid2obj(tag)]) end - elsif winobj.kind_of? TkCanvas + #elsif winobj.kind_of? TkCanvas + elsif winobj.kind_of?(TkCanvas) || winobj.kind_of?(Tk::Canvas) if (tagobj = TkcTag.id2obj(winobj, tag)).kind_of? TkcTag if optkey ret.push([winobj, tagobj, optkey]) @@ -925,7 +1102,8 @@ class TkFont ret.push([winobj, tag]) end end - elsif winobj.kind_of? TkMenu + #elsif winobj.kind_of? TkMenu + elsif winobj.kind_of?(TkMenu) || winobj.kind_of?(Tk::Menu) if optkey ret.push([winobj, tag, optkey]) else @@ -957,6 +1135,8 @@ class TkFont @compoundfont end alias font_id font + alias name font + alias to_s font def latin_font_id @latinfont @@ -964,11 +1144,18 @@ class TkFont def latin_font # @latinfont + if @descendant[0] # [0] -> latin + @descendant[0] + else + @descendant[0] = DescendantFont.new(self, 'latin') + end +=begin if @latin_descendant @latin_descendant else @latin_descendant = DescendantFont.new(self, 'latin') end +=end end alias latinfont latin_font @@ -978,50 +1165,87 @@ class TkFont def kanji_font # @kanjifont + if @descendant[1] # [1] -> kanji + @descendant[1] + else + @descendant[1] = DescendantFont.new(self, 'kanji') + end +=begin if @kanji_descendant @kanji_descendant else @kanji_descendant = DescendantFont.new(self, 'kanji') end +=end end alias kanjifont kanji_font def actual(option=nil) actual_core(@compoundfont, nil, option) end + def actual_hash(option=nil) + Hash[actual(option)] + end def actual_displayof(win, option=nil) win = '.' unless win actual_core(@compoundfont, win, option) end + def actual_hash_displayof(win, option=nil) + Hash[actual_displayof(win, option)] + end def latin_actual(option=nil) - actual_core(@latinfont, nil, option) + if @latinfont == nil + actual_core(@compoundfont, nil, option) # use @compoundfont + else + actual_core(@latinfont, nil, option) + end + end + def latin_actual_hash(option=nil) + Hash[latin_actual(option)] end def latin_actual_displayof(win, option=nil) win = '.' unless win - actual_core(@latinfont, win, option) + if @latinfont == nil + actual_core(@compoundfont, win, option) # use @compoundfont + else + actual_core(@latinfont, win, option) + end + end + def latin_actual_hash_displayof(win, option=nil) + Hash[latin_actual_displayof(win, option)] end def kanji_actual(option=nil) #if JAPANIZED_TK - if @kanjifont != "" + if @kanjifont == nil + actual_core(@compoundfont, nil, option) # use @compoundfont + elsif @kanjifont != "" actual_core(@kanjifont, nil, option) else actual_core_tk4x(nil, nil, option) end end + def kanji_actual_hash(option=nil) + Hash[kanji_actual(option)] + end def kanji_actual_displayof(win, option=nil) #if JAPANIZED_TK - if @kanjifont != "" + if @kanjifont == nil + actual_core(@compoundfont, nil, option) # use @compoundfont + elsif @kanjifont != "" win = '.' unless win actual_core(@kanjifont, win, option) else actual_core_tk4x(nil, win, option) end end + def kanji_actual_hash_displayof(win, option=nil) + Hash[kanji_actual_displayof(win, option)] + end def [](slot) configinfo slot @@ -1065,10 +1289,15 @@ class TkFont configinfo(slot) end end + def latin_current_configinfo(slot=nil) + Hash[latin_configinfo(slot)] + end def kanji_configure(slot, value=None) #if JAPANIZED_TK - if @kanjifont != "" + if @kanjifont == nil + configure_core(@compoundfont, slot, value) # use @compoundfont + elsif @kanjifont != "" configure_core(@kanjifont, slot, value) configure('size'=>configinfo('size')) # to reflect new configuration else @@ -1080,13 +1309,18 @@ class TkFont def kanji_configinfo(slot=nil) #if JAPANIZED_TK - if @kanjifont != "" + if @kanjifont == nil + configure_core(@compoundfont, slot) # use @compoundfont + elsif @kanjifont != "" configinfo_core(@kanjifont, slot) else #[] configinfo(slot) end end + def kanji_current_configinfo(slot=nil) + Hash[kanji_configinfo(slot)] + end def replace(ltn, knj=None) knj = ltn if knj == None @@ -1096,12 +1330,30 @@ class TkFont end def latin_replace(ltn) - latin_replace_core(ltn) - reset_pointadjust + if @latinfont + latin_replace_core(ltn) + reset_pointadjust + else + # not compound font -> copy properties of ltn + latinkeys = {} + begin + actual_core(ltn).each{|key,val| latinkeys[key] = val} + rescue + latinkeys = {} + end + begin + tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys)) + rescue + # not exist? (deleted?) -> create font + tk_call('font', 'create', @compoundfont, *hash_kv(latinkeys)) + end + end + self end def kanji_replace(knj) + return self unless @kanjifont # ignore kanji_replace_core(knj) reset_pointadjust self @@ -1119,41 +1371,215 @@ class TkFont def metrics(option=nil) metrics_core(@compoundfont, nil, option) end + def metrics_hash(option=nil) + if option + val = metrics(option) + case TkFont::MetricsType[option.to_s] + when ?n + val = TkComm::num_or_str(val) + when ?b + val = TkComm::bool(val) + else + # do nothing + end + return val + end + + h = Hash[metrics(option)] + h.keys.each{|k| + case TkFont::MetricsType[k.to_s] + when ?n + h[k] = TkComm::num_or_str(h[k]) + when ?b + h[k] = TkComm::bool(h[k]) + else + # do nothing + end + } + h + end def metrics_displayof(win, option=nil) win = '.' unless win metrics_core(@compoundfont, win, option) end + def metrics_hash_displayof(win, option=nil) + if option + val = metrics_displayof(win, option) + case TkFont::MetricsType[option.to_s] + when ?n + val = TkComm::num_or_str(val) + when ?b + val = TkComm::bool(val) + else + # do nothing + end + return val + end + + h = Hash[metrics_displayof(win, option)] + h.keys.each{|k| + case TkFont::MetricsType[k.to_s] + when ?n + h[k] = TkComm::num_or_str(h[k]) + when ?b + h[k] = TkComm::bool(h[k]) + else + # do nothing + end + } + h + end def latin_metrics(option=nil) - metrics_core(@latinfont, nil, option) + if @latinfont == nil + metrics_core(@compoundfont, nil, option) # use @compoundfont + else + metrics_core(@latinfont, nil, option) + end + end + def latin_metrics_hash(option=nil) + if option + val = latin_metrics(option) + case TkFont::MetricsType[option.to_s] + when ?n + val = TkComm::num_or_str(val) + when ?b + val = TkComm::bool(val) + else + # do nothing + end + return val + end + + h = Hash[latin_metrics(option)] + h.keys.each{|k| + case TkFont::MetricsType[k.to_s] + when ?n + h[k] = TkComm::num_or_str(h[k]) + when ?b + h[k] = TkComm::bool(h[k]) + else + # do nothing + end + } + h end def latin_metrics_displayof(win, option=nil) win = '.' unless win - metrics_core(@latinfont, win, option) + if @latinfont == nil + metrics_core(@compoundfont, win, option) # use @compoundfont + else + metrics_core(@latinfont, win, option) + end + end + def latin_metrics_hash_displayof(win, option=nil) + if option + val = latin_metrics_displayof(win, option) + case TkFont::MetricsType[option.to_s] + when ?n + val = TkComm::num_or_str(val) + when ?b + val = TkComm::bool(val) + else + # do nothing + end + return val + end + + h = Hash[latin_metrics_displayof(win, option)] + h.keys.each{|k| + case TkFont::MetricsType[k.to_s] + when ?n + h[k] = TkComm::num_or_str(h[k]) + when ?b + h[k] = TkComm::bool(h[k]) + else + # do nothing + end + } + h end def kanji_metrics(option=nil) - if JAPANIZED_TK + if @latinfont == nil + metrics_core(@compoundfont, nil, option) # use @compoundfont + elsif JAPANIZED_TK metrics_core(@kanjifont, nil, option) else metrics_core_tk4x(nil, nil, option) end end + def kanji_metrics_hash(option=nil) + if option + val = kanji_metrics(option) + case TkFont::MetricsType[option.to_s] + when ?n + val = TkComm::num_or_str(val) + when ?b + val = TkComm::bool(val) + else + # do nothing + end + return val + end + + h = Hash[kanji_metrics(option)] + h.keys.each{|k| + case TkFont::MetricsType[k.to_s] + when ?n + h[k] = TkComm::num_or_str(h[k]) + when ?b + h[k] = TkComm::bool(h[k]) + else + # do nothing + end + } + h + end def kanji_metrics_displayof(win, option=nil) - if JAPANIZED_TK - win = '.' unless win + win = '.' unless win + if @latinfont == nil + metrics_core(@compoundfont, win, option) # use @compoundfont + elsif JAPANIZED_TK metrics_core(@kanjifont, win, option) else metrics_core_tk4x(nil, win, option) end end + def kanji_metrics_hash_displayof(win, option=nil) + if option + val = kanji_metrics_displayof(win, option) + case TkFont::MetricsType[option.to_s] + when ?n + val = TkComm::num_or_str(val) + when ?b + val = TkComm::bool(val) + else + # do nothing + end + return val + end + + h = Hash[kanji_metrics_displayof(win, option)] + h.keys.each{|k| + case TkFont::MetricsType[k.to_s] + when ?n + h[k] = TkComm::num_or_str(h[k]) + when ?b + h[k] = TkComm::bool(h[k]) + else + # do nothing + end + } + h + end def reset_pointadjust begin - if /^8\.*/ === Tk::TK_VERSION && JAPANIZED_TK + if /^8\..*/ === Tk::TK_VERSION && JAPANIZED_TK configure('pointadjust' => latin_actual.assoc('size')[1].to_f / kanji_actual.assoc('size')[1].to_f ) end @@ -1166,7 +1592,7 @@ class TkFont # private alias ################################### case (Tk::TK_VERSION) - when /^4\.*/ + when /^4\..*/ alias create_latinfont create_latinfont_tk4x alias create_kanjifont create_kanjifont_tk4x alias create_compoundfont create_compoundfont_tk4x @@ -1471,32 +1897,44 @@ module TkFont::CoreMethods end def delete_core_tk4x - TkFont::Tk_FontNameTBL.delete(@id) - TkFont::Tk_FontUseTBL.delete_if{|key,value| value == self} + TkFont::Tk_FontNameTBL.mutex.synchronize{ + TkFont::Tk_FontNameTBL.delete(@id) + } + TkFont::Tk_FontUseTBL.mutex.synchronize{ + TkFont::Tk_FontUseTBL.delete_if{|key,value| value == self} + } end def delete_core_tk8x begin - tk_call('font', 'delete', @latinfont) + tk_call('font', 'delete', @latinfont) if @latinfont rescue end begin - tk_call('font', 'delete', @kanjifont) + tk_call('font', 'delete', @kanjifont) if @kanjifont rescue end begin - tk_call('font', 'delete', @compoundfont) + tk_call('font', 'delete', @compoundfont) if @compoundfont rescue end - TkFont::Tk_FontNameTBL.delete(@id) - TkFont::Tk_FontUseTBL.delete_if{|key,value| value == self} + TkFont::Tk_FontNameTBL.mutex.synchronize{ + TkFont::Tk_FontNameTBL.delete(@id) + } + TkFont::Tk_FontUseTBL.mutex.synchronize{ + TkFont::Tk_FontUseTBL.delete_if{|key,value| value == self} + } end def latin_replace_core_tk4x(ltn) create_latinfont_tk4x(ltn) @compoundfont[0] = [@latinfont] if JAPANIZED_TK @fontslot['font'] = @latinfont - TkFont::Tk_FontUseTBL.dup.each{|w, fobj| + table = nil + TkFont::Tk_FontUseTBL.mutex.synchronize{ + table = TkFont::Tk_FontUseTBL.clone + } + table.each{|w, fobj| if self == fobj begin if w.include?(';') @@ -1504,11 +1942,14 @@ module TkFont::CoreMethods optkey = 'font' if optkey == nil || optkey == '' winobj = tk_tcl2ruby(win) # winobj.tagfont_configure(tag, {'font'=>@latinfont}) - if winobj.kind_of? TkText + #if winobj.kind_of? TkText + if winobj.kind_of?(TkText) || winobj.kind_of?(Tk::Text) tk_call(win, 'tag', 'configure', tag, "-#{optkey}", @latinfont) - elsif winobj.kind_of? TkCanvas + #elsif winobj.kind_of? TkCanvas + elsif winobj.kind_of?(TkCanvas) || winobj.kind_of?(Tk::Canvas) tk_call(win, 'itemconfigure', tag, "-#{optkey}", @latinfont) - elsif winobj.kind_of? TkMenu + #elsif winobj.kind_of? TkMenu + elsif winobj.kind_of?(TkMenu) || winobj.kind_of?(Tk::Menu) tk_call(win, 'entryconfigure', tag, "-#{optkey}", @latinfont) else raise RuntimeError, "unknown widget type" @@ -1518,7 +1959,9 @@ module TkFont::CoreMethods tk_call(w, 'configure', '-font', @latinfont) end rescue - TkFont::Tk_FontUseTBL.delete(w) + TkFont::Tk_FontUseTBL.mutex.synchronize{ + TkFont::Tk_FontUseTBL.delete(w) + } end end } @@ -1531,7 +1974,11 @@ module TkFont::CoreMethods create_kanjifont_tk4x(knj) @compoundfont[1] = [@kanjifont] @fontslot['kanjifont'] = @kanjifont - TkFont::Tk_FontUseTBL.dup.each{|w, fobj| + table = nil + TkFont::Tk_FontUseTBL.mutex.synchronize{ + table = TkFont::Tk_FontUseTBL.clone + } + table.dup.each{|w, fobj| if self == fobj begin if w.include?(';') @@ -1539,11 +1986,14 @@ module TkFont::CoreMethods optkey = 'kanjifont' unless optkey winobj = tk_tcl2ruby(win) # winobj.tagfont_configure(tag, {'kanjifont'=>@kanjifont}) - if winobj.kind_of? TkText + #if winobj.kind_of? TkText + if winobj.kind_of?(TkText) || winobj.kind_of?(Tk::Text) tk_call(win, 'tag', 'configure', tag, "-#{optkey}", @kanjifont) - elsif winobj.kind_of? TkCanvas + #elsif winobj.kind_of? TkCanvas + elsif winobj.kind_of?(TkCanvas) || winobj.kind_of?(Tk::Canvas) tk_call(win, 'itemconfigure', tag, "-#{optkey}", @kanjifont) - elsif winobj.kind_of? TkMenu + #elsif winobj.kind_of? TkMenu + elsif winobj.kind_of?(TkMenu) || winobj.kind_of?(Tk::Menu) tk_call(win, 'entryconfigure', tag, "-#{optkey}", @latinfont) else raise RuntimeError, "unknown widget type" @@ -1553,7 +2003,9 @@ module TkFont::CoreMethods tk_call(w, 'configure', '-kanjifont', @kanjifont) end rescue - TkFont::Tk_FontUseTBL.delete(w) + Tk_FontUseTBL.mutex.synchronize{ + TkFont::Tk_FontUseTBL.delete(w) + } end end } @@ -1618,8 +2070,11 @@ module TkFont::CoreMethods rescue latinkeys = {} end - if latinkeys != {} + begin tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys)) + rescue + # not exist? (deleted?) -> create font + tk_call('font', 'create', @compoundfont, *hash_kv(latinkeys)) end end self @@ -1711,6 +2166,13 @@ module TkFont::CoreMethods r = [] while key=l.shift r.push [key[1..-1], l.shift.to_i] +=begin + if key == '-fixed' # boolean value + r.push [key[1..-1], bool(l.shift)] + else + r.push [key[1..-1], l.shift.to_i] + end +=end end r end @@ -1720,7 +2182,7 @@ module TkFont::CoreMethods # private alias ################################### case (Tk::TK_VERSION) - when /^4\.*/ + when /^4\..*/ alias actual_core actual_core_tk4x alias configure_core configure_core_tk4x alias configinfo_core configinfo_core_tk4x @@ -1760,3 +2222,117 @@ class TkFont include TkFont::CoreMethods extend TkFont::CoreMethods end + +class TkNamedFont < TkFont + # for built-in named fonts + def TkNamedFont.find(name) + name = name.to_s + unless (obj = Tk_FontNameTBL[name]) + obj = self.new(name) if TkFont.is_system_font?(name) + end + obj + end + + def TkNamedFont.new(name, keys=nil) + name = name.to_s + obj = nil + Tk_FontNameTBL.mutex.synchronize{ + unless (obj = Tk_FontNameTBL[name]) + (obj = self.allocate).instance_eval{ + @id = @compoundfont = name.to_s + @latinfont = nil + @kanjifont = nil + @descendant = [self, self] # [latin, kanji] : dummy + Tk_FontNameTBL[@id] = self + } + end + } + obj.instance_eval{ initialize(name, keys) } + obj + end + + ########################### + private + ########################### + def initialize(name, keys=nil) + @id = @compoundfont = name.to_s + + # if not exist named font, create it. + begin + if keys + tk_call('font', 'configure', @compoundfont, keys) + else + tk_call('font', 'configure', @compoundfont) + end + rescue + # the named font doesn't exist -> create + if keys + tk_call('font', 'create', @compoundfont, keys) + else + tk_call('font', 'create', @compoundfont) + end + end + end + + def create_latinfont(fnt) + # ignore + end + def create_kanjifont(fnt) + # ignore + end + def create_compoundfont(ltn, knj, keys) + # ignore + end + + ########################### + public + ########################### + def latin_font_id + @compoundfont + end + def kanji_font_id + @compoundfont + end +end + +####################################### +# define system font names +####################################### +if Tk::TCL_MAJOR_VERSION > 8 || + (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION >= 5) + # add standard fonts of Tcl/Tk 8.5+ + TkFont::SYSTEM_FONT_NAMES.add [ + 'TkDefaultFont', 'TkTextFont', 'TkFixedFont', 'TkMenuFont', + 'TkHeadingFont', 'TkCaptionFont', 'TkSmallCaptionFont', + 'TkIconFont', 'TkTooltipFont' + ] +end + +# platform-specific fonts +# -- windows +TkFont::SYSTEM_FONT_NAMES.add [ + 'ansifixed', 'ansi', 'device', 'oemfixed', 'systemfixed', 'system' +] + +# -- macintosh, macosx +TkFont::SYSTEM_FONT_NAMES.add ['system', 'application'] + +if Tk::TCL_MAJOR_VERSION > 8 || + (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION >= 5) + TkFont::SYSTEM_FONT_NAMES.add ['menu'] +end + +# -- macosx (Aqua theme) +if Tk::TCL_MAJOR_VERSION > 8 || + (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION >= 5) + TkFont::SYSTEM_FONT_NAMES.add [ + 'systemSystemFont', 'systemEmphasizedSystemFont', + 'systemSmallSystemFont', 'systemSmallEmphasizedSystemFont', + 'systemApplicationFont', 'systemLabelFont', 'systemViewsFont', + 'systemMenuTitleFont', 'systemMenuItemFont', 'systemMenuItemMarkFont', + 'systemMenuItemCmdKeyFont', 'systemWindowTitleFont', + 'systemPushButtonFont', 'systemUtilityWindowTitleFont', + 'systemAlertHeaderFont', 'systemToolbarFont', 'systemMiniSystemFont', + 'systemDetailSystemFont', 'systemDetailEmphasizedSystemFont' + ] +end diff --git a/ext/tk/lib/tk/frame.rb b/ext/tk/lib/tk/frame.rb index 6636fef5b5..263b160f29 100644 --- a/ext/tk/lib/tk/frame.rb +++ b/ext/tk/lib/tk/frame.rb @@ -3,7 +3,7 @@ # require 'tk' -class TkFrame<TkWindow +class Tk::Frame<TkWindow TkCommandNames = ['frame'.freeze].freeze WidgetClassName = 'Frame'.freeze WidgetClassNames[WidgetClassName] = self @@ -126,3 +126,6 @@ class TkFrame<TkWindow end end end + +#TkFrame = Tk::Frame unless Object.const_defined? :TkFrame +Tk.__set_toplevel_aliases__(:Tk, Tk::Frame, :TkFrame) diff --git a/ext/tk/lib/tk/image.rb b/ext/tk/lib/tk/image.rb index 35e2c4e394..57f82cb812 100644 --- a/ext/tk/lib/tk/image.rb +++ b/ext/tk/lib/tk/image.rb @@ -10,9 +10,16 @@ class TkImage<TkObject TkCommandNames = ['image'.freeze].freeze Tk_IMGTBL = TkCore::INTERP.create_table - Tk_Image_ID = ['i'.freeze, '00000'.taint].freeze - TkCore::INTERP.init_ip_env{ Tk_IMGTBL.clear } + (Tk_Image_ID = ['i'.freeze, '00000'.taint]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + TkCore::INTERP.init_ip_env{ + Tk_IMGTBL.mutex.synchronize{ Tk_IMGTBL.clear } + } def self.new(keys=nil) if keys.kind_of?(Hash) @@ -27,7 +34,10 @@ class TkImage<TkObject obj = name else name = _get_eval_string(name) - obj = Tk_IMGTBL[name] + obj = nil + Tk_IMGTBL.mutex.synchronize{ + obj = Tk_IMGTBL[name] + } end if obj if !(keys[:without_creating] || keys['without_creating']) @@ -43,7 +53,13 @@ class TkImage<TkObject end end end - super(keys) + (obj = self.allocate).instance_eval{ + Tk_IMGTBL.mutex.synchronize{ + initialize(keys) + Tk_IMGTBL[@path] = self + } + } + obj end def initialize(keys=nil) @@ -55,19 +71,22 @@ class TkImage<TkObject without_creating = keys.delete('without_creating') end unless @path - # @path = Tk_Image_ID.join('') - @path = Tk_Image_ID.join(TkCore::INTERP._ip_id_) - Tk_Image_ID[1].succ! + Tk_Image_ID.mutex.synchronize{ + # @path = Tk_Image_ID.join('') + @path = Tk_Image_ID.join(TkCore::INTERP._ip_id_) + Tk_Image_ID[1].succ! + } end unless without_creating tk_call_without_enc('image', 'create', @type, @path, *hash_kv(keys, true)) end - Tk_IMGTBL[@path] = self end def delete - Tk_IMGTBL.delete(@id) if @id + Tk_IMGTBL.mutex.synchronize{ + Tk_IMGTBL.delete(@id) if @id + } tk_call_without_enc('image', 'delete', @path) self end @@ -85,8 +104,10 @@ class TkImage<TkObject end def TkImage.names - Tk.tk_call_without_enc('image', 'names').split.collect!{|id| - (Tk_IMGTBL[id])? Tk_IMGTBL[id] : id + Tk_IMGTBL.mutex.synchronize{ + Tk.tk_call_without_enc('image', 'names').split.collect!{|id| + (Tk_IMGTBL[id])? Tk_IMGTBL[id] : id + } } end diff --git a/ext/tk/lib/tk/itemconfig.rb b/ext/tk/lib/tk/itemconfig.rb index a7885e74f3..dbc45a9e7c 100644 --- a/ext/tk/lib/tk/itemconfig.rb +++ b/ext/tk/lib/tk/itemconfig.rb @@ -115,6 +115,14 @@ module TkItemConfigMethod include TkTreatItemFont include TkItemConfigOptkeys + def TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + @mode || false + end + def TkItemConfigMethod.__set_IGNORE_UNKNOWN_CONFIGURE_OPTION__!(mode) + fail SecurityError, "can't change the mode" if $SAFE>=4 + @mode = (mode)? true: false + end + def __item_cget_cmd(id) # maybe need to override [self.path, 'itemcget', id] @@ -149,7 +157,7 @@ module TkItemConfigMethod ################################################ - def itemcget(tagOrId, option) + def __itemcget_core(tagOrId, option) orig_opt = option option = option.to_s @@ -224,8 +232,27 @@ module TkItemConfigMethod tk_tcl2ruby(tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}")), true) end end + private :__itemcget_core - def itemconfigure(tagOrId, slot, value=None) + def itemcget(tagOrId, option) + unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + __itemcget_core(tagOrId, option) + else + begin + __itemcget_core(tagOrId, option) + rescue => e + begin + __itemconfiginfo_core(tagOrId) + # not tag error -> option is unknown + nil + rescue + fail e # tag error + end + end + end + end + + def __itemconfigure_core(tagOrId, slot, value=None) if slot.kind_of? Hash slot = _symbolkey2str(slot) @@ -288,6 +315,48 @@ module TkItemConfigMethod end self end + private :__itemconfigure_core + + def __check_available_itemconfigure_options(tagOrId, keys) + id = tagid(tagOrId) + availables = self.current_itemconfiginfo(id).keys + + # add non-standard keys + availables |= __font_optkeys.map{|k| + [k.to_s, "latin#{k}", "ascii#{k}", "kanji#{k}"] + }.flatten + availables |= __item_methodcall_optkeys(id).keys.map{|k| k.to_s} + availables |= __item_keyonly_optkeys(id).keys.map{|k| k.to_s} + + keys = _symbolkey2str(keys) + keys.delete_if{|k, v| !(availables.include?(k))} + end + + def itemconfigure(tagOrId, slot, value=None) + unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + __itemconfigure_core(tagOrId, slot, value) + else + if slot.kind_of?(Hash) + begin + __itemconfigure_core(tagOrId, slot) + rescue + slot = __check_available_configure_options(tagOrId, slot) + __itemconfigure_core(tagOrId, slot) unless slot.empty? + end + else + begin + __itemconfigure_core(tagOrId, slot, value) + rescue => e + begin + __itemconfiginfo_core(tagOrId) + rescue + fail e # tag error + end + end + end + end + self + end def __itemconfiginfo_core(tagOrId, slot = nil) if TkComm::GET_CONFIGINFO_AS_ARRAY @@ -299,6 +368,10 @@ module TkItemConfigMethod conf[__item_configinfo_struct(tagid(tagOrId))[:key]][1..-1] if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \ || conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 ) + fnt = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] + if TkFont.is_system_font?(fnt) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkNamedFont.new(fnt) + end conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = tagfontobj(tagid(tagOrId), fontkey) elsif ( __item_configinfo_struct(tagid(tagOrId))[:alias] \ && conf.size == __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 \ @@ -635,6 +708,10 @@ module TkItemConfigMethod fontconf = ret.assoc(optkey) if fontconf && fontconf.size > 2 ret.delete_if{|inf| inf[0] =~ /^(|latin|ascii|kanji)#{optkey}$/} + fnt = fontconf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] + if TkFont.is_system_font?(fnt) + fontconf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkNamedFont.new(fnt) + end fontconf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = tagfontobj(tagid(tagOrId), optkey) ret.push(fontconf) end @@ -658,7 +735,11 @@ module TkItemConfigMethod if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \ || conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 ) - conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = fontobj(tagid(tagOrId), fontkey) + fnt = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] + if TkFont.is_system_font?(fnt) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkNamedFont.new(fnt) + end + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = tagfontobj(tagid(tagOrId), fontkey) { conf.shift => conf } elsif ( __item_configinfo_struct(tagid(tagOrId))[:alias] \ && conf.size == __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 ) @@ -1006,6 +1087,10 @@ module TkItemConfigMethod ret.delete('latin' << optkey) ret.delete('ascii' << optkey) ret.delete('kanji' << optkey) + fnt = fontconf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] + if TkFont.is_system_font?(fnt) + fontconf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkNamedFont.new(fnt) + end fontconf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = tagfontobj(tagid(tagOrId), optkey) ret[optkey] = fontconf end @@ -1023,7 +1108,21 @@ module TkItemConfigMethod private :__itemconfiginfo_core def itemconfiginfo(tagOrId, slot = nil) - __itemconfiginfo_core(tagOrId, slot) + if slot && TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + begin + __itemconfiginfo_core(tagOrId, slot) + rescue => e + begin + __itemconfiginfo_core(tagOrId) + # not tag error -> option is unknown + Array.new(__item_configinfo_struct.values.max).unshift(slot.to_s) + rescue + fail e # tag error + end + end + else + __itemconfiginfo_core(tagOrId, slot) + end end def current_itemconfiginfo(tagOrId, slot = nil) diff --git a/ext/tk/lib/tk/label.rb b/ext/tk/lib/tk/label.rb index 8b45db9b30..80b3d778f1 100644 --- a/ext/tk/lib/tk/label.rb +++ b/ext/tk/lib/tk/label.rb @@ -3,7 +3,7 @@ # require 'tk' -class TkLabel<TkWindow +class Tk::Label<TkWindow TkCommandNames = ['label'.freeze].freeze WidgetClassName = 'Label'.freeze WidgetClassNames[WidgetClassName] = self @@ -16,3 +16,6 @@ class TkLabel<TkWindow #end #private :create_self end + +#TkLabel = Tk::Label unless Object.const_defined? :TkLabel +Tk.__set_toplevel_aliases__(:Tk, Tk::Label, :TkLabel) diff --git a/ext/tk/lib/tk/labelframe.rb b/ext/tk/lib/tk/labelframe.rb index 73d5603200..995b5b7e72 100644 --- a/ext/tk/lib/tk/labelframe.rb +++ b/ext/tk/lib/tk/labelframe.rb @@ -4,7 +4,7 @@ require 'tk' require 'tk/frame' -class TkLabelFrame<TkFrame +class Tk::LabelFrame<Tk::Frame TkCommandNames = ['labelframe'.freeze].freeze WidgetClassName = 'Labelframe'.freeze WidgetClassNames[WidgetClassName] = self @@ -22,4 +22,8 @@ class TkLabelFrame<TkFrame end private :__val2ruby_optkeys end -TkLabelframe = TkLabelFrame + +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) diff --git a/ext/tk/lib/tk/listbox.rb b/ext/tk/lib/tk/listbox.rb index 41d02d279e..bb039ffb0e 100644 --- a/ext/tk/lib/tk/listbox.rb +++ b/ext/tk/lib/tk/listbox.rb @@ -15,7 +15,7 @@ module TkListItemConfig private :__item_listval_optkeys end -class TkListbox<TkTextWin +class Tk::Listbox<TkTextWin include TkListItemConfig include Scrollable @@ -277,3 +277,6 @@ class TkListbox<TkTextWin end =end end + +#TkListbox = Tk::Listbox unless Object.const_defined? :TkListbox +Tk.__set_toplevel_aliases__(:Tk, Tk::Listbox, :TkListbox) diff --git a/ext/tk/lib/tk/macpkg.rb b/ext/tk/lib/tk/macpkg.rb index 1802073f46..67b0a4bb60 100644 --- a/ext/tk/lib/tk/macpkg.rb +++ b/ext/tk/lib/tk/macpkg.rb @@ -20,9 +20,14 @@ module Tk end end -module TkMacResource +module Tk::MacResource +end +#TkMacResource = Tk::MacResource +Tk.__set_toplevel_aliases__(:Tk, Tk::MacResource, :TkMacResource) + +module Tk::MacResource extend Tk - extend TkMacResource + extend Tk::MacResource TkCommandNames = ['resource'.freeze].freeze diff --git a/ext/tk/lib/tk/menu.rb b/ext/tk/lib/tk/menu.rb index ddddc8e53e..8ba3156293 100644 --- a/ext/tk/lib/tk/menu.rb +++ b/ext/tk/lib/tk/menu.rb @@ -42,7 +42,7 @@ module TkMenuEntryConfig private :itemconfiginfo, :current_itemconfiginfo end -class TkMenu<TkWindow +class Tk::Menu<TkWindow include Wm include TkMenuEntryConfig extend TkMenuSpec @@ -140,9 +140,9 @@ class TkMenu<TkWindow type = keys.delete('type') if keys.has_key?('type') if keys.empty? - TkMenuClone.new(self, parent, type) + Tk::MenuClone.new(self, parent, type) else - TkMenuClone.new(self, parent, type, keys) + Tk::MenuClone.new(self, parent, type, keys) end end @@ -202,6 +202,9 @@ class TkMenu<TkWindow tk_send_without_enc('unpost') self end + def xposition(index) + number(tk_send_without_enc('xposition', _get_eval_enc_str(index))) + end def yposition(index) number(tk_send_without_enc('yposition', _get_eval_enc_str(index))) end @@ -381,8 +384,11 @@ class TkMenu<TkWindow =end end +#TkMenu = Tk::Menu unless Object.const_defined? :TkMenu +Tk.__set_toplevel_aliases__(:Tk, Tk::Menu, :TkMenu) + -class TkMenuClone<TkMenu +class Tk::MenuClone<Tk::Menu =begin def initialize(parent, type=None) widgetname = nil @@ -436,9 +442,12 @@ class TkMenuClone<TkMenu @src_menu end end -TkCloneMenu = TkMenuClone +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) -module TkSystemMenu +module Tk::SystemMenu def initialize(parent, keys=nil) if parent.kind_of? Hash keys = _symbolkey2str(parent) @@ -461,38 +470,60 @@ module TkSystemMenu end end end +TkSystemMenu = Tk::SystemMenu -class TkSysMenu_Help<TkMenu +class Tk::SysMenu_Help<Tk::Menu # for all platform - include TkSystemMenu + include Tk::SystemMenu 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) -class TkSysMenu_System<TkMenu +class Tk::SysMenu_System<Tk::Menu # for Windows - include TkSystemMenu + include Tk::SystemMenu 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) -class TkSysMenu_Apple<TkMenu +class Tk::SysMenu_Apple<Tk::Menu # for Machintosh - include TkSystemMenu + include Tk::SystemMenu 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) -class TkMenubutton<TkLabel +class Tk::Menubutton<Tk::Label TkCommandNames = ['menubutton'.freeze].freeze WidgetClassName = 'Menubutton'.freeze WidgetClassNames[WidgetClassName] = self def create_self(keys) if keys and keys != None - # tk_call_without_enc('menubutton', @path, *hash_kv(keys, true)) - tk_call_without_enc(self.class::TkCommandNames[0], @path, - *hash_kv(keys, true)) + unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + # tk_call_without_enc('menubutton', @path, *hash_kv(keys, true)) + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + begin + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + rescue + tk_call_without_enc(self.class::TkCommandNames[0], @path) + keys = __check_available_configure_options(keys) + unless keys.empty? + tk_call_without_enc('destroy', @path) + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + end + end + end else # tk_call_without_enc('menubutton', @path) tk_call_without_enc(self.class::TkCommandNames[0], @path) @@ -506,10 +537,13 @@ class TkMenubutton<TkLabel private :__boolval_optkeys end -TkMenuButton = TkMenubutton +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) -class TkOptionMenubutton<TkMenubutton +class Tk::OptionMenubutton<Tk::Menubutton TkCommandNames = ['tk_optionMenu'.freeze].freeze class OptionMenu<TkMenu @@ -596,6 +630,9 @@ class TkOptionMenubutton<TkMenubutton @menu.delete(index, last) self end + def xposition(index) + @menu.xposition(index) + end def yposition(index) @menu.yposition(index) end @@ -629,4 +666,9 @@ class TkOptionMenubutton<TkMenubutton @menu.current_entryconfiginfo(index, key) end end -TkOptionMenuButton = TkOptionMenubutton + +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) diff --git a/ext/tk/lib/tk/menubar.rb b/ext/tk/lib/tk/menubar.rb index 392b6fbd4e..ef9da809b9 100644 --- a/ext/tk/lib/tk/menubar.rb +++ b/ext/tk/lib/tk/menubar.rb @@ -89,7 +89,7 @@ require 'tk/frame' require 'tk/composite' require 'tk/menuspec' -class TkMenubar<TkFrame +class TkMenubar<Tk::Frame include TkComposite include TkMenuSpec diff --git a/ext/tk/lib/tk/menuspec.rb b/ext/tk/lib/tk/menuspec.rb index 118a4f42b1..d9322c9986 100644 --- a/ext/tk/lib/tk/menuspec.rb +++ b/ext/tk/lib/tk/menuspec.rb @@ -61,8 +61,12 @@ module TkMenuSpec tearoff = orig_opts.delete('tearoff') if orig_opts.key?('tearoff') if menu_name + #menu = Tk::Menu.new(parent, :widgetname=>menu_name, :tearoff=>tearoff) + # --> use current TkMenu class menu = TkMenu.new(parent, :widgetname=>menu_name, :tearoff=>tearoff) else + #menu = Tk::Menu.new(parent, :tearoff=>tearoff) + # --> use current TkMenu class menu = TkMenu.new(parent, :tearoff=>tearoff) end @@ -150,7 +154,7 @@ module TkMenuSpec def _use_menubar?(parent) use_menubar = false - if parent.kind_of?(TkRoot) || parent.kind_of?(TkToplevel) + if parent.kind_of?(Tk::Root) || parent.kind_of?(Tk::Toplevel) return true else begin @@ -164,7 +168,11 @@ module TkMenuSpec private :_use_menubar? def _create_menu_for_menubar(parent) - unless (mbar = parent.menu).kind_of?(TkMenu) + #unless (mbar = parent.menu).kind_of?(TkMenu) + # --> use current TkMenu class + mbar = parent.menu + unless parent.menu.kind_of?(Tk::Menu) || parent.menu.kind_of?(TkMenu) + #mbar = Tk::Menu.new(parent, :tearoff=>false) mbar = TkMenu.new(parent, :tearoff=>false) parent.menu(mbar) end @@ -221,6 +229,8 @@ module TkMenuSpec else # menubar by menubuttons + #mbtn = Tk::Menubutton.new(parent) + # --> use current TkMenubutton class mbtn = TkMenubutton.new(parent) menu_name = nil diff --git a/ext/tk/lib/tk/message.rb b/ext/tk/lib/tk/message.rb index 79121bebb3..946b68c704 100644 --- a/ext/tk/lib/tk/message.rb +++ b/ext/tk/lib/tk/message.rb @@ -4,7 +4,7 @@ require 'tk' require 'tk/label' -class TkMessage<TkLabel +class Tk::Message<Tk::Label TkCommandNames = ['message'.freeze].freeze WidgetClassName = 'Message'.freeze WidgetClassNames[WidgetClassName] = self @@ -17,3 +17,6 @@ class TkMessage<TkLabel #end private :create_self end + +#TkMessage = Tk::Message unless Object.const_defined? :TkMessage +Tk.__set_toplevel_aliases__(:Tk, Tk::Message, :TkMessage) diff --git a/ext/tk/lib/tk/msgcat.rb b/ext/tk/lib/tk/msgcat.rb index 061e43fd89..162953f425 100644 --- a/ext/tk/lib/tk/msgcat.rb +++ b/ext/tk/lib/tk/msgcat.rb @@ -74,7 +74,11 @@ class TkMsgCatalog < TkObject "\n---< backtrace of Ruby side >-----\n" + _toUTF8(e.backtrace.join("\n")) + "\n---< backtrace of Tk side >-------" - msg.instance_variable_set(:@encoding, 'utf-8') + if TkCore::WITH_ENCODING + msg.force_encoding('utf-8') + else + msg.instance_variable_set(:@encoding, 'utf-8') + end rescue Exception msg = e.class.inspect + ': ' + e.message + "\n" + "\n---< backtrace of Ruby side >-----\n" + diff --git a/ext/tk/lib/tk/namespace.rb b/ext/tk/lib/tk/namespace.rb index 5bf6474c5b..9d2213ff51 100644 --- a/ext/tk/lib/tk/namespace.rb +++ b/ext/tk/lib/tk/namespace.rb @@ -12,17 +12,24 @@ class TkNamespace < TkObject ].freeze Tk_Namespace_ID_TBL = TkCore::INTERP.create_table - Tk_Namespace_ID = ["ns".freeze, "00000".taint].freeze + + (Tk_Namespace_ID = ["ns".freeze, "00000".taint]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } Tk_NsCode_RetObjID_TBL = TkCore::INTERP.create_table TkCore::INTERP.init_ip_env{ - Tk_Namespace_ID_TBL.clear - Tk_NsCode_RetObjID_TBL.clear + Tk_Namespace_ID_TBL.mutex.synchronize{ Tk_Namespace_ID_TBL.clear } + Tk_NsCode_RetObjID_TBL.mutex.synchronize{ Tk_NsCode_RetObjID_TBL.clear } } def TkNamespace.id2obj(id) - Tk_Namespace_ID_TBL[id]? Tk_Namespace_ID_TBL[id]: id + Tk_Namespace_ID_TBL.mutex.synchronize{ + Tk_Namespace_ID_TBL[id]? Tk_Namespace_ID_TBL[id]: id + } end ##################################### @@ -65,11 +72,13 @@ class TkNamespace < TkObject def cget(slot) if slot == :namespace || slot == 'namespace' ns = super(slot) - if TkNamespace::Tk_Namespace_ID_TBL.key?(ns) - TkNamespace::Tk_Namespace_ID_TBL[ns] - else - ns - end + Tk_Namespace_ID_TBL.mutex.synchronize{ + if TkNamespace::Tk_Namespace_ID_TBL.key?(ns) + TkNamespace::Tk_Namespace_ID_TBL[ns] + else + ns + end + } else super(slot) end @@ -79,9 +88,11 @@ class TkNamespace < TkObject if slot if slot == :namespace || slot == 'namespace' val = super(slot) - if TkNamespace::Tk_Namespace_ID_TBL.key?(val) - val = TkNamespace::Tk_Namespace_ID_TBL[val] - end + Tk_Namespace_ID_TBL.mutex.synchronize{ + if TkNamespace::Tk_Namespace_ID_TBL.key?(val) + val = TkNamespace::Tk_Namespace_ID_TBL[val] + end + } else val = super(slot) end @@ -96,19 +107,23 @@ class TkNamespace < TkObject info = super() if TkComm::GET_CONFIGINFO_AS_ARRAY - info.map!{|inf| - if inf[0] == 'namespace' && - TkNamespace::Tk_Namespace_ID_TBL.key?(inf[-1]) - [inf[0], TkNamespace::Tk_Namespace_ID_TBL[inf[-1]]] - else - inf - end + Tk_Namespace_ID_TBL.mutex.synchronize{ + info.map!{|inf| + if inf[0] == 'namespace' && + TkNamespace::Tk_Namespace_ID_TBL.key?(inf[-1]) + [inf[0], TkNamespace::Tk_Namespace_ID_TBL[inf[-1]]] + else + inf + end + } } else # ! TkComm::GET_CONFIGINFO_AS_ARRAY val = info['namespace'] - if TkNamespace::Tk_Namespace_ID_TBL.key?(val) - info['namespace'] = TkNamespace::Tk_Namespace_ID_TBL[val] - end + Tk_Namespace_ID_TBL.mutex.synchronize{ + if TkNamespace::Tk_Namespace_ID_TBL.key?(val) + info['namespace'] = TkNamespace::Tk_Namespace_ID_TBL[val] + end + } end info @@ -215,9 +230,11 @@ class TkNamespace < TkObject def initialize(name = nil, parent = nil) unless name - # name = Tk_Namespace_ID.join('') - name = Tk_Namespace_ID.join(TkCore::INTERP._ip_id_) - Tk_Namespace_ID[1].succ! + Tk_Namespace_ID.mutex.synchronize{ + # name = Tk_Namespace_ID.join('') + name = Tk_Namespace_ID.join(TkCore::INTERP._ip_id_) + Tk_Namespace_ID[1].succ! + } end name = __tk_call('namespace', 'current') if name == '' if parent @@ -252,7 +269,9 @@ class TkNamespace < TkObject # create namespace __tk_call('namespace', 'eval', @fullname, '') - Tk_Namespace_ID_TBL[@fullname] = self + Tk_Namespace_ID_TBL.mutex.synchronize{ + Tk_Namespace_ID_TBL[@fullname] = self + } end def self.children(*args) @@ -260,11 +279,13 @@ class TkNamespace < TkObject # <pattern> must be glob-style pattern tk_split_simplelist(tk_call('namespace', 'children', *args)).collect{|ns| # ns is fullname - if Tk_Namespace_ID_TBL.key?(ns) - Tk_Namespace_ID_TBL[ns] - else - ns - end + Tk_Namespace_ID_TBL.mutex.synchronize{ + if Tk_Namespace_ID_TBL.key?(ns) + Tk_Namespace_ID_TBL[ns] + else + ns + end + } } end def children(pattern=None) @@ -290,14 +311,24 @@ class TkNamespace < TkObject def code(script = Proc.new) if script.kind_of?(String) cmd = proc{|*args| - ret = ScopeArgs.new(@fullname,*args).instance_eval(script) + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + obj = ScopeArgs.new(@fullname,*args) + ret = obj.instance_exec(obj, script) + else + ret = ScopeArgs.new(@fullname,*args).instance_eval(script) + end id = ret.object_id TkNamespace::Tk_NsCode_RetObjID_TBL[id] = ret id } elsif script.kind_of?(Proc) cmd = proc{|*args| - ret = ScopeArgs.new(@fullname,*args).instance_eval(&script) + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + obj = ScopeArgs.new(@fullname,*args) + ret = obj.instance_exec(obj, &script) + else + ret = ScopeArgs.new(@fullname,*args).instance_eval(&script) + end id = ret.object_id TkNamespace::Tk_NsCode_RetObjID_TBL[id] = ret id @@ -319,11 +350,13 @@ class TkNamespace < TkObject def self.current ns = self.current_path - if Tk_Namespace_ID_TBL.key?(ns) - Tk_Namespace_ID_TBL[ns] - else - ns - end + Tk_Namespace_ID_TBL.mutex.synchronize{ + if Tk_Namespace_ID_TBL.key?(ns) + Tk_Namespace_ID_TBL[ns] + else + ns + end + } end def current_namespace # ns_tk_call('namespace', 'current') @@ -335,11 +368,13 @@ class TkNamespace < TkObject def self.delete(*ns_list) tk_call('namespace', 'delete', *ns_list) ns_list.each{|ns| - if ns.kind_of?(TkNamespace) - Tk_Namespace_ID_TBL.delete(ns.path) - else - Tk_Namespace_ID_TBL.delete(ns.to_s) - end + Tk_Namespace_ID_TBL.mutex.synchronize{ + if ns.kind_of?(TkNamespace) + Tk_Namespace_ID_TBL.delete(ns.path) + else + Tk_Namespace_ID_TBL.delete(ns.to_s) + end + } } end def delete @@ -371,7 +406,7 @@ class TkNamespace < TkObject def self.eval(namespace, cmd = Proc.new, *args) #tk_call('namespace', 'eval', namespace, cmd, *args) - TkNamespace.new(namespece).eval(cmd, *args) + TkNamespace.new(namespace).eval(cmd, *args) end =begin def eval(cmd = Proc.new, *args) @@ -444,11 +479,13 @@ class TkNamespace < TkObject def self.parent(namespace=None) ns = tk_call('namespace', 'parent', namespace) - if Tk_Namespace_ID_TBL.key?(ns) - Tk_Namespace_ID_TBL[ns] - else - ns - end + Tk_Namespace_ID_TBL.mutex.synchronize{ + if Tk_Namespace_ID_TBL.key?(ns) + Tk_Namespace_ID_TBL[ns] + else + ns + end + } end def parent tk_call('namespace', 'parent', @fullname) diff --git a/ext/tk/lib/tk/optiondb.rb b/ext/tk/lib/tk/optiondb.rb index a806f3971d..186811d37d 100644 --- a/ext/tk/lib/tk/optiondb.rb +++ b/ext/tk/lib/tk/optiondb.rb @@ -8,7 +8,11 @@ module TkOptionDB extend Tk TkCommandNames = ['option'.freeze].freeze - CmdClassID = ['CMD_CLASS'.freeze, '00000'.taint].freeze + (CmdClassID = ['CMD_CLASS'.freeze, '00000'.taint]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } module Priority WidgetDefault = 20 @@ -250,8 +254,10 @@ module TkOptionDB def __create_new_class(klass, func, safe = 4, add = false, parent = nil) if klass.kind_of?(TkWindow) carrier = klass.path - klass = CmdClassID.join(TkCore::INTERP._ip_id_) - CmdClassID[1].succ! + CmdClassID.mutex.synchronize{ + klass = CmdClassID.join(TkCore::INTERP._ip_id_) + CmdClassID[1].succ! + } parent = nil # ignore parent else klass = klass.to_s if klass.kind_of?(Symbol) @@ -312,7 +318,7 @@ module TkOptionDB :singleton_methods, :remove_const, :remove_method, :undef_method, :to_s, :inspect, :display, :method, :methods, :respond_to?, :instance_variable_get, :instance_variable_set, :instance_method, - :instance_eval, :instance_variables, :kind_of?, :is_a?, + :instance_eval, :instance_exec, :instance_variables, :kind_of?, :is_a?, :private_methods, :protected_methods, :public_methods ].each{|m| alias_method(m, :__null_method) } @@ -362,7 +368,7 @@ module TkOptionDB def new_proc_class_random(klass, func, safe = 4, add = false, &b) eval_under_random_base(){ - TkOption.new_proc_class(klass, func, safe, add, self, &b) + TkOptionDB.new_proc_class(klass, func, safe, add, self, &b) } end module_function :new_proc_class_random diff --git a/ext/tk/lib/tk/package.rb b/ext/tk/lib/tk/package.rb index d1eb27674d..0c329732f5 100644 --- a/ext/tk/lib/tk/package.rb +++ b/ext/tk/lib/tk/package.rb @@ -136,4 +136,8 @@ module TkPackage def vsatisfies(version1, version2) bool(tk_call('package', 'vsatisfies', version1, version2)) end + + def prefer(setting = None) + tk_call('package', 'prefer', setting) + end end diff --git a/ext/tk/lib/tk/panedwindow.rb b/ext/tk/lib/tk/panedwindow.rb index c6cf3cd11f..ba8a7e9743 100644 --- a/ext/tk/lib/tk/panedwindow.rb +++ b/ext/tk/lib/tk/panedwindow.rb @@ -3,7 +3,7 @@ # require 'tk' -class TkPanedWindow<TkWindow +class Tk::PanedWindow<TkWindow TkCommandNames = ['panedwindow'.freeze].freeze WidgetClassName = 'Panedwindow'.freeze WidgetClassNames[WidgetClassName] = self @@ -229,4 +229,9 @@ class TkPanedWindow<TkWindow list(tk_send_without_enc('panes')) end end -TkPanedwindow = TkPanedWindow + +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) diff --git a/ext/tk/lib/tk/radiobutton.rb b/ext/tk/lib/tk/radiobutton.rb index f8f67d709a..1f864ec06b 100644 --- a/ext/tk/lib/tk/radiobutton.rb +++ b/ext/tk/lib/tk/radiobutton.rb @@ -4,7 +4,7 @@ require 'tk' require 'tk/button' -class TkRadioButton<TkButton +class Tk::RadioButton<Tk::Button TkCommandNames = ['radiobutton'.freeze].freeze WidgetClassName = 'Radiobutton'.freeze WidgetClassNames[WidgetClassName] = self @@ -63,4 +63,9 @@ class TkRadioButton<TkButton end end end -TkRadiobutton = TkRadioButton + +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) diff --git a/ext/tk/lib/tk/root.rb b/ext/tk/lib/tk/root.rb index 0e5584c7c1..7237b4c614 100644 --- a/ext/tk/lib/tk/root.rb +++ b/ext/tk/lib/tk/root.rb @@ -5,7 +5,7 @@ require 'tk' require 'tk/wm' require 'tk/menuspec' -class TkRoot<TkWindow +class Tk::Root<TkWindow include Wm include TkMenuSpec @@ -14,28 +14,7 @@ class TkRoot<TkWindow end private :__methodcall_optkeys -=begin - ROOT = [] - def TkRoot.new(keys=nil) - if ROOT[0] - Tk_WINDOWS["."] = ROOT[0] - return ROOT[0] - end - new = super(:without_creating=>true, :widgetname=>'.') - if keys # wm commands - keys.each{|k,v| - if v.kind_of? Array - new.send(k,*v) - else - new.send(k,v) - end - } - end - ROOT[0] = new - Tk_WINDOWS["."] = new - end -=end - def TkRoot.new(keys=nil, &b) + def Root.new(keys=nil, &b) unless TkCore::INTERP.tk_windows['.'] TkCore::INTERP.tk_windows['.'] = super(:without_creating=>true, :widgetname=>'.'){} @@ -62,7 +41,13 @@ class TkRoot<TkWindow } end - root.instance_eval(&b) if block_given? + if block_given? + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + root.instance_exec(root, &b) + else + root.instance_eval(&b) + end + end root end @@ -102,7 +87,9 @@ class TkRoot<TkWindow self.menu end - def TkRoot.destroy + def Root.destroy TkCore::INTERP._invoke('destroy', '.') end end + +TkRoot = Tk::Root unless Object.const_defined? :TkRoot diff --git a/ext/tk/lib/tk/scale.rb b/ext/tk/lib/tk/scale.rb index 0b703aa055..bf2791ec55 100644 --- a/ext/tk/lib/tk/scale.rb +++ b/ext/tk/lib/tk/scale.rb @@ -3,7 +3,7 @@ # require 'tk' -class TkScale<TkWindow +class Tk::Scale<TkWindow TkCommandNames = ['scale'.freeze].freeze WidgetClassName = 'Scale'.freeze WidgetClassNames[WidgetClassName] = self @@ -14,9 +14,24 @@ class TkScale<TkWindow cmd = keys.delete('command') keys['command'] = proc{|val| cmd.call(val.to_f)} end - #tk_call_without_enc('scale', @path, *hash_kv(keys, true)) - tk_call_without_enc(self.class::TkCommandNames[0], @path, - *hash_kv(keys, true)) + unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + #tk_call_without_enc('scale', @path, *hash_kv(keys, true)) + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + begin + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + rescue + tk_call_without_enc(self.class::TkCommandNames[0], @path) + keys = __check_available_configure_options(keys) + unless keys.empty? + tk_call_without_enc('destroy', @path) + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + end + end + end else #tk_call_without_enc('scale', @path) tk_call_without_enc(self.class::TkCommandNames[0], @path) @@ -84,3 +99,6 @@ class TkScale<TkWindow val end end + +#TkScale = Tk::Scale unless Object.const_defined? :TkScale +Tk.__set_toplevel_aliases__(:Tk, Tk::Scale, :TkScale) diff --git a/ext/tk/lib/tk/scrollbar.rb b/ext/tk/lib/tk/scrollbar.rb index 70aadfdd4c..521fc7e400 100644 --- a/ext/tk/lib/tk/scrollbar.rb +++ b/ext/tk/lib/tk/scrollbar.rb @@ -3,7 +3,7 @@ # require 'tk' -class TkScrollbar<TkWindow +class Tk::Scrollbar<TkWindow TkCommandNames = ['scrollbar'.freeze].freeze WidgetClassName = 'Scrollbar'.freeze WidgetClassNames[WidgetClassName] = self @@ -19,9 +19,24 @@ class TkScrollbar<TkWindow } if keys and keys != None - #tk_call_without_enc('scrollbar', @path, *hash_kv(keys, true)) - tk_call_without_enc(self.class::TkCommandNames[0], @path, - *hash_kv(keys, true)) + unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + #tk_call_without_enc('scrollbar', @path, *hash_kv(keys, true)) + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + begin + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + rescue + tk_call_without_enc(self.class::TkCommandNames[0], @path) + keys = __check_available_configure_options(keys) + unless keys.empty? + tk_call_without_enc('destroy', @path) + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + end + end + end else #tk_call_without_enc('scrollbar', @path) tk_call_without_enc(self.class::TkCommandNames[0], @path) @@ -103,9 +118,33 @@ class TkScrollbar<TkWindow def activate(element=None) tk_send_without_enc('activate', element) end + + def moveto(fraction) + tk_send_without_enc('moveto', fraction) + self + end + + def scroll(*args) + tk_send_without_enc('scroll', *args) + self + end + + def scroll_units(num) + scroll(num, 'units') + self + end + + def scroll_pages(num) + scroll(num, 'pages') + self + end end -class TkXScrollbar<TkScrollbar +#TkScrollbar = Tk::Scrollbar unless Object.const_defined? :TkScrollbar +Tk.__set_toplevel_aliases__(:Tk, Tk::Scrollbar, :TkScrollbar) + + +class Tk::XScrollbar<Tk::Scrollbar def create_self(keys) keys = {} unless keys keys['orient'] = 'horizontal' @@ -114,7 +153,11 @@ class TkXScrollbar<TkScrollbar private :create_self end -class TkYScrollbar<TkScrollbar +#TkXScrollbar = Tk::XScrollbar unless Object.const_defined? :TkXScrollbar +Tk.__set_toplevel_aliases__(:Tk, Tk::XScrollbar, :TkXScrollbar) + + +class Tk::YScrollbar<Tk::Scrollbar def create_self(keys) keys = {} unless keys keys['orient'] = 'vertical' @@ -122,3 +165,6 @@ class TkYScrollbar<TkScrollbar end private :create_self end + +#TkYScrollbar = Tk::YScrollbar unless Object.const_defined? :TkYScrollbar +Tk.__set_toplevel_aliases__(:Tk, Tk::YScrollbar, :TkYScrollbar) diff --git a/ext/tk/lib/tk/scrollbox.rb b/ext/tk/lib/tk/scrollbox.rb index fd04057fb6..d20742a666 100644 --- a/ext/tk/lib/tk/scrollbox.rb +++ b/ext/tk/lib/tk/scrollbox.rb @@ -1,16 +1,19 @@ # # tk/scrollbox.rb - Tk Listbox with Scrollbar # as an example of Composite Widget -# $Date$ # by Yukihiro Matsumoto <matz@netlab.co.jp> # require 'tk' require 'tk/listbox' -class TkScrollbox<TkListbox +class TkScrollbox<Tk::Listbox include TkComposite def initialize_composite(keys=nil) + #list = Tk::Listbox.new(@frame) + # -> use current TkListbox class list = TkListbox.new(@frame) + #scroll = Tk::Scrollbar.new(@frame) + # -> use current TkScrollbar class scroll = TkScrollbar.new(@frame) @path = list.path diff --git a/ext/tk/lib/tk/spinbox.rb b/ext/tk/lib/tk/spinbox.rb index 9a10977d12..e372c58009 100644 --- a/ext/tk/lib/tk/spinbox.rb +++ b/ext/tk/lib/tk/spinbox.rb @@ -1,12 +1,11 @@ # # tk/spinbox.rb - Tk spinbox classes -# $Date$ # by Yukihiro Matsumoto <matz@caelum.co.jp> # require 'tk' require 'tk/entry' -class TkSpinbox<TkEntry +class Tk::Spinbox<Tk::Entry TkCommandNames = ['spinbox'.freeze].freeze WidgetClassName = 'Spinbox'.freeze WidgetClassNames[WidgetClassName] = self @@ -38,6 +37,22 @@ class TkSpinbox<TkEntry nil ] + # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) + KEY_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) + end + inf + } + + PROC_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + end + inf + } + _setup_subst_table(KEY_TBL, PROC_TBL); def self.ret_val(val) @@ -97,3 +112,6 @@ class TkSpinbox<TkEntry _fromUTF8(tk_send_without_enc('set', _get_eval_enc_str(str))) end end + +#TkSpinbox = Tk::Spinbox unless Object.const_defined? :TkSpinbox +Tk.__set_toplevel_aliases__(:Tk, Tk::Spinbox, :TkSpinbox) diff --git a/ext/tk/lib/tk/text.rb b/ext/tk/lib/tk/text.rb index 49d4b5625b..14b9be23f0 100644 --- a/ext/tk/lib/tk/text.rb +++ b/ext/tk/lib/tk/text.rb @@ -1,6 +1,5 @@ # # tk/text.rb - Tk text classes -# $Date$ # by Yukihiro Matsumoto <matz@caelum.co.jp> require 'tk' require 'tk/itemfont' @@ -60,7 +59,7 @@ module TkTextTagConfig private :itemconfiginfo, :current_itemconfiginfo end -class TkText<TkTextWin +class Tk::Text<TkTextWin ItemConfCMD = ['tag'.freeze, 'configure'.freeze].freeze #include TkTreatTextTagFont include TkTextTagConfig @@ -74,9 +73,9 @@ class TkText<TkTextWin mod = mod.to_s if mod =~ /^\s*[+-]?\d/ - TkText::IndexString.new(String.new(id) << ' + ' << mod) + Tk::Text::IndexString.new(String.new(id) << ' + ' << mod) else - TkText::IndexString.new(String.new(id) << ' ' << mod) + Tk::Text::IndexString.new(String.new(id) << ' ' << mod) end end @@ -85,20 +84,20 @@ class TkText<TkTextWin mod = mod.to_s if mod =~ /^\s*[+-]?\d/ - TkText::IndexString.new(String.new(id) << ' - ' << mod) + Tk::Text::IndexString.new(String.new(id) << ' - ' << mod) elsif mod =~ /^\s*[-]\s+(\d.*)$/ - TkText::IndexString.new(String.new(id) << ' - -' << $1) + Tk::Text::IndexString.new(String.new(id) << ' - -' << $1) else - TkText::IndexString.new(String.new(id) << ' ' << mod) + Tk::Text::IndexString.new(String.new(id) << ' ' << mod) end end def chars(mod) fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer) if mod < 0 - TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' chars') + Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' chars') else - TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' chars') + Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' chars') end end alias char chars @@ -107,9 +106,9 @@ class TkText<TkTextWin # Tk8.5 feature fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer) if mod < 0 - TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display chars') + Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display chars') else - TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display chars') + Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display chars') end end alias display_char display_chars @@ -118,9 +117,9 @@ class TkText<TkTextWin # Tk8.5 feature fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer) if mod < 0 - TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any chars') + Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any chars') else - TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any chars') + Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any chars') end end alias any_char any_chars @@ -129,9 +128,9 @@ class TkText<TkTextWin # Tk8.5 feature fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer) if mod < 0 - TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' indices') + Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' indices') else - TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' indices') + Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' indices') end end @@ -139,9 +138,9 @@ class TkText<TkTextWin # Tk8.5 feature fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer) if mod < 0 - TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display indices') + Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display indices') else - TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display indices') + Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display indices') end end @@ -149,18 +148,18 @@ class TkText<TkTextWin # Tk8.5 feature fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer) if mod < 0 - TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any indices') + Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any indices') else - TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any indices') + Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any indices') end end def lines(mod) fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer) if mod < 0 - TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' lines') + Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' lines') else - TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' lines') + Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' lines') end end alias line lines @@ -169,9 +168,9 @@ class TkText<TkTextWin # Tk8.5 feature fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer) if mod < 0 - TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display_lines') + Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display_lines') else - TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display lines') + Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display lines') end end alias display_line display_lines @@ -180,43 +179,43 @@ class TkText<TkTextWin # Tk8.5 feature fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer) if mod < 0 - TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any_lines') + Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any_lines') else - TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any lines') + Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any lines') end end alias any_line any_lines def linestart - TkText::IndexString.new(String.new(id) << ' linestart') + Tk::Text::IndexString.new(String.new(id) << ' linestart') end def lineend - TkText::IndexString.new(String.new(id) << ' lineend') + Tk::Text::IndexString.new(String.new(id) << ' lineend') end def display_linestart # Tk8.5 feature - TkText::IndexString.new(String.new(id) << ' display linestart') + Tk::Text::IndexString.new(String.new(id) << ' display linestart') end def display_lineend # Tk8.5 feature - TkText::IndexString.new(String.new(id) << ' display lineend') + Tk::Text::IndexString.new(String.new(id) << ' display lineend') end def wordstart - TkText::IndexString.new(String.new(id) << ' wordstart') + Tk::Text::IndexString.new(String.new(id) << ' wordstart') end def wordend - TkText::IndexString.new(String.new(id) << ' wordend') + Tk::Text::IndexString.new(String.new(id) << ' wordend') end def display_wordstart # Tk8.5 feature - TkText::IndexString.new(String.new(id) << ' display wordstart') + Tk::Text::IndexString.new(String.new(id) << ' display wordstart') end def display_wordend # Tk8.5 feature - TkText::IndexString.new(String.new(id) << ' display wordend') + Tk::Text::IndexString.new(String.new(id) << ' display wordend') end end @@ -251,7 +250,11 @@ class TkText<TkTextWin def self.new(*args, &block) obj = super(*args){} obj.init_instance_variable - obj.instance_eval(&block) if defined? yield + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + obj.instance_exec(obj, &block) if defined? yield + else + obj.instance_eval(&block) if defined? yield + end obj end @@ -261,8 +264,12 @@ class TkText<TkTextWin end def __destroy_hook__ - TkTextTag::TTagID_TBL.delete(@path) - TkTextMark::TMarkID_TBL.delete(@path) + TkTextTag::TTagID_TBL.mutex.synchronize{ + TkTextTag::TTagID_TBL.delete(@path) + } + TkTextTag::TMarkID_TBL.mutex.synchronize{ + TkTextMark::TMarkID_TBL.delete(@path) + } end def create_self(keys) @@ -285,16 +292,16 @@ class TkText<TkTextWin private :__strval_optkeys def self.at(x, y) - TkText::IndexString.at(x, y) + Tk::Text::IndexString.at(x, y) end def at(x, y) - TkText::IndexString.at(x, y) + Tk::Text::IndexString.at(x, y) end def index(idx) - TkText::IndexString.new(tk_send_without_enc('index', - _get_eval_enc_str(idx))) + Tk::Text::IndexString.new(tk_send_without_enc('index', + _get_eval_enc_str(idx))) end def get_displaychars(*index) @@ -713,15 +720,17 @@ class TkText<TkTextWin def tag_delete(*tags) tk_send_without_enc('tag', 'delete', *(tags.collect{|tag| _get_eval_enc_str(tag)})) - if TkTextTag::TTagID_TBL[@path] - tags.each{|tag| - if tag.kind_of?(TkTextTag) - TkTextTag::TTagID_TBL[@path].delete(tag.id) - else - TkTextTag::TTagID_TBL[@path].delete(tag) - end - } - end + TkTextTag::TTagID_TBL.mutex.synchronize{ + if TkTextTag::TTagID_TBL[@path] + tags.each{|tag| + if tag.kind_of?(TkTextTag) + TkTextTag::TTagID_TBL[@path].delete(tag.id) + else + TkTextTag::TTagID_TBL[@path].delete(tag) + end + } + end + } self end alias deltag tag_delete @@ -968,7 +977,7 @@ class TkText<TkTextWin false, true) r = [] while key=l.shift - r.push [TkText::IndexString.new(key), TkText::IndexString.new(l.shift)] + r.push [Tk::Text::IndexString.new(key), Tk::Text::IndexString.new(l.shift)] end r end @@ -978,7 +987,7 @@ class TkText<TkTextWin _get_eval_enc_str(tag), _get_eval_enc_str(first), _get_eval_enc_str(last))).collect{|idx| - TkText::IndexString.new(idx) + Tk::Text::IndexString.new(idx) } end @@ -987,7 +996,7 @@ class TkText<TkTextWin _get_eval_enc_str(tag), _get_eval_enc_str(first), _get_eval_enc_str(last))).collect{|idx| - TkText::IndexString.new(idx) + Tk::Text::IndexString.new(idx) } end @@ -1183,6 +1192,11 @@ class TkText<TkTextWin end def _ktext_length(txt) + if TkCore::WITH_ENCODING ### Ruby 1.9 !!!!!!!!!!!!! + return txt.length + end + ########################### + if $KCODE !~ /n/i return txt.gsub(/[^\Wa-zA-Z_\d]/, ' ').length end @@ -1232,7 +1246,7 @@ class TkText<TkTextWin if ret == "" nil else - TkText::IndexString.new(ret) + Tk::Text::IndexString.new(ret) end end @@ -1267,7 +1281,7 @@ class TkText<TkTextWin if ret == "" nil else - TkText::IndexString.new(ret) + Tk::Text::IndexString.new(ret) end end @@ -1456,10 +1470,10 @@ class TkText<TkTextWin # retrieve index idx = str.index(/ /, i) if idx - result.push(TkText::IndexString.new(str[i..(idx-1)])) + result.push(Tk::Text::IndexString.new(str[i..(idx-1)])) i = idx + 1 else - result.push(TkText::IndexString.new(str[i..-1])) + result.push(Tk::Text::IndexString.new(str[i..-1])) break end end @@ -1527,13 +1541,17 @@ class TkText<TkTextWin end end +#TkText = Tk::Text unless Object.const_defined? :TkText +Tk.__set_toplevel_aliases__(:Tk, Tk::Text, :TkText) + + ####################################### -class TkText::Peer < TkText +class Tk::Text::Peer < Tk::Text # Tk8.5 feature def initialize(text, parent=nil, keys={}) - unless text.kind_of?(TkText) - fail ArgumentError, "TkText is expected for 1st argument" + unless text.kind_of?(Tk::Text) + fail ArgumentError, "Tk::Text is expected for 1st argument" end @src_text = text super(parent, keys) diff --git a/ext/tk/lib/tk/textimage.rb b/ext/tk/lib/tk/textimage.rb index a29b23c7dd..d4c973213d 100644 --- a/ext/tk/lib/tk/textimage.rb +++ b/ext/tk/lib/tk/textimage.rb @@ -5,11 +5,11 @@ require 'tk' require 'tk/text' class TkTextImage<TkObject - include TkText::IndexModMethods + include Tk::Text::IndexModMethods def initialize(parent, index, keys) - #unless parent.kind_of?(TkText) - # fail ArgumentError, "expect TkText for 1st argument" + #unless parent.kind_of?(Tk::Text) + # fail ArgumentError, "expect Tk::Text for 1st argument" #end @t = parent if index == 'end' || index == :end @@ -34,7 +34,7 @@ class TkTextImage<TkObject end def id - TkText::IndexString.new(@id) + Tk::Text::IndexString.new(@id) end def mark @path @@ -80,3 +80,5 @@ class TkTextImage<TkObject value end end + +TktImage = TkTextImage diff --git a/ext/tk/lib/tk/textmark.rb b/ext/tk/lib/tk/textmark.rb index 650d95af70..72c1ce1ab4 100644 --- a/ext/tk/lib/tk/textmark.rb +++ b/ext/tk/lib/tk/textmark.rb @@ -5,38 +5,54 @@ require 'tk' require 'tk/text' class TkTextMark<TkObject - include TkText::IndexModMethods + include Tk::Text::IndexModMethods TMarkID_TBL = TkCore::INTERP.create_table - Tk_TextMark_ID = ['mark'.freeze, '00000'.taint].freeze - TkCore::INTERP.init_ip_env{ TMarkID_TBL.clear } + (Tk_TextMark_ID = ['mark'.freeze, '00000'.taint]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + TkCore::INTERP.init_ip_env{ + TMarkID_TBL.mutex.synchronize{ TMarkID_TBL.clear } + } def TkTextMark.id2obj(text, id) tpath = text.path - return id unless TMarkID_TBL[tpath] - TMarkID_TBL[tpath][id]? TMarkID_TBL[tpath][id]: id + TMarkID_TBL.mutex.synchronize{ + if TMarkID_TBL[tpath] + TMarkID_TBL[tpath][id]? TMarkID_TBL[tpath][id]: id + else + id + end + } end def initialize(parent, index) - #unless parent.kind_of?(TkText) - # fail ArgumentError, "expect TkText for 1st argument" + #unless parent.kind_of?(Tk::Text) + # fail ArgumentError, "expect Tk::Text for 1st argument" #end @parent = @t = parent @tpath = parent.path - # @path = @id = Tk_TextMark_ID.join('') - @path = @id = Tk_TextMark_ID.join(TkCore::INTERP._ip_id_).freeze - TMarkID_TBL[@id] = self - TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath] - TMarkID_TBL[@tpath][@id] = self - Tk_TextMark_ID[1].succ! + Tk_TextMark_ID.mutex.synchronize{ + # @path = @id = Tk_TextMark_ID.join('') + @path = @id = Tk_TextMark_ID.join(TkCore::INTERP._ip_id_).freeze + Tk_TextMark_ID[1].succ! + } + TMarkID_TBL.mutex.synchronize{ + TMarkID_TBL[@id] = self + TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath] + TMarkID_TBL[@tpath][@id] = self + } tk_call_without_enc(@t.path, 'mark', 'set', @id, _get_eval_enc_str(index)) @t._addtag id, self end def id - TkText::IndexString.new(@id) + Tk::Text::IndexString.new(@id) end def exist? @@ -49,15 +65,15 @@ class TkTextMark<TkObject end =begin - # move to TkText::IndexModMethods module + # move to Tk::Text::IndexModMethods module def +(mod) return chars(mod) if mod.kind_of?(Numeric) mod = mod.to_s if mod =~ /^\s*[+-]?\d/ - TkText::IndexString.new(@id + ' + ' + mod) + Tk::Text::IndexString.new(@id + ' + ' + mod) else - TkText::IndexString.new(@id + ' ' + mod) + Tk::Text::IndexString.new(@id + ' ' + mod) end end @@ -66,11 +82,11 @@ class TkTextMark<TkObject mod = mod.to_s if mod =~ /^\s*[+-]?\d/ - TkText::IndexString.new(@id + ' - ' + mod) + Tk::Text::IndexString.new(@id + ' - ' + mod) elsif mod =~ /^\s*[-]\s+(\d.*)$/ - TkText::IndexString.new(@id + ' - -' + $1) + Tk::Text::IndexString.new(@id + ' - -' + $1) else - TkText::IndexString.new(@id + ' ' + mod) + Tk::Text::IndexString.new(@id + ' ' + mod) end end =end @@ -121,46 +137,68 @@ class TkTextMark<TkObject end end end +TktMark = TkTextMark class TkTextNamedMark<TkTextMark - def self.new(parent, name, *args) - if TMarkID_TBL[parent.path] && TMarkID_TBL[parent.path][name] - return TMarkID_TBL[parent.path][name] - else - super(parent, name, *args) - end + def self.new(parent, name, index=nil) + TMarkID_TBL.mutex.synchronize{ + if TMarkID_TBL[parent.path] && TMarkID_TBL[parent.path][name] + obj = TMarkID_TBL[parent.path][name] + else + # super(parent, name, *args) + (obj = self.allocate).instance_eval{ + @parent = @t = parent + @tpath = parent.path + @path = @id = name + TMarkID_TBL[@id] = self + TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath] + TMarkID_TBL[@tpath][@id] = self unless TMarkID_TBL[@tpath][@id] + @t._addtag @id, self + } + obj + end + + if obj && index + tk_call_without_enc(parent.path, 'mark', 'set', name, + _get_eval_enc_str(index)) + end + obj + } end def initialize(parent, name, index=nil) - #unless parent.kind_of?(TkText) - # fail ArgumentError, "expect TkText for 1st argument" + # dummy:: not called by 'new' method + + #unless parent.kind_of?(Tk::Text) + # fail ArgumentError, "expect Tk::Text for 1st argument" #end @parent = @t = parent @tpath = parent.path @path = @id = name - TMarkID_TBL[@id] = self - TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath] - TMarkID_TBL[@tpath][@id] = self unless TMarkID_TBL[@tpath][@id] tk_call_without_enc(@t.path, 'mark', 'set', @id, _get_eval_enc_str(index)) if index - @t._addtag id, self + @t._addtag @id, self end end +TktNamedMark = TkTextNamedMark class TkTextMarkInsert<TkTextNamedMark def self.new(parent,*args) super(parent, 'insert', *args) end end +TktMarkInsert = TkTextMarkInsert class TkTextMarkCurrent<TkTextNamedMark def self.new(parent,*args) super(parent, 'current', *args) end end +TktMarkCurrent = TkTextMarkCurrent class TkTextMarkAnchor<TkTextNamedMark def self.new(parent,*args) super(parent, 'anchor', *args) end end +TktMarkAnchor = TkTextMarkAnchor diff --git a/ext/tk/lib/tk/texttag.rb b/ext/tk/lib/tk/texttag.rb index cc2c56210f..792d544fe7 100644 --- a/ext/tk/lib/tk/texttag.rb +++ b/ext/tk/lib/tk/texttag.rb @@ -7,17 +7,29 @@ require 'tk/tagfont' class TkTextTag<TkObject include TkTreatTagFont - include TkText::IndexModMethods + include Tk::Text::IndexModMethods TTagID_TBL = TkCore::INTERP.create_table - Tk_TextTag_ID = ['tag'.freeze, '00000'.taint].freeze - TkCore::INTERP.init_ip_env{ TTagID_TBL.clear } + (Tk_TextTag_ID = ['tag'.freeze, '00000'.taint]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + TkCore::INTERP.init_ip_env{ + TTagID_TBL.mutex.synchronize{ TTagID_TBL.clear } + } def TkTextTag.id2obj(text, id) tpath = text.path - return id unless TTagID_TBL[tpath] - TTagID_TBL[tpath][id]? TTagID_TBL[tpath][id]: id + TTagID_TBL.mutex.synchronize{ + if TTagID_TBL[tpath] + TTagID_TBL[tpath][id]? TTagID_TBL[tpath][id]: id + else + id + end + } end def initialize(parent, *args) @@ -26,12 +38,16 @@ class TkTextTag<TkObject #end @parent = @t = parent @tpath = parent.path - # @path = @id = Tk_TextTag_ID.join('') - @path = @id = Tk_TextTag_ID.join(TkCore::INTERP._ip_id_).freeze - # TTagID_TBL[@id] = self - TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath] - TTagID_TBL[@tpath][@id] = self - Tk_TextTag_ID[1].succ! + Tk_TextTag_ID.mutex.synchronize{ + # @path = @id = Tk_TextTag_ID.join('') + @path = @id = Tk_TextTag_ID.join(TkCore::INTERP._ip_id_).freeze + Tk_TextTag_ID[1].succ! + } + TTagID_TBL.mutex.synchronize{ + TTagID_TBL[@id] = self + TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath] + TTagID_TBL[@tpath][@id] = self + } #tk_call @t.path, "tag", "configure", @id, *hash_kv(keys) if args != [] keys = args.pop @@ -47,7 +63,7 @@ class TkTextTag<TkObject end def id - TkText::IndexString.new(@id) + Tk::Text::IndexString.new(@id) end def exist? @@ -60,11 +76,11 @@ class TkTextTag<TkObject end def first - TkText::IndexString.new(@id + '.first') + Tk::Text::IndexString.new(@id + '.first') end def last - TkText::IndexString.new(@id + '.last') + Tk::Text::IndexString.new(@id + '.last') end def add(*indices) @@ -83,7 +99,7 @@ class TkTextTag<TkObject l = tk_split_simplelist(tk_call_without_enc(@t.path, 'tag', 'ranges', @id)) r = [] while key=l.shift - r.push [TkText::IndexString.new(key), TkText::IndexString.new(l.shift)] + r.push [Tk::Text::IndexString.new(key), Tk::Text::IndexString.new(l.shift)] end r end @@ -92,7 +108,7 @@ class TkTextTag<TkObject simplelist(tk_call_without_enc(@t.path, 'tag', 'nextrange', @id, _get_eval_enc_str(first), _get_eval_enc_str(last))).collect{|idx| - TkText::IndexString.new(idx) + Tk::Text::IndexString.new(idx) } end @@ -100,7 +116,7 @@ class TkTextTag<TkObject simplelist(tk_call_without_enc(@t.path, 'tag', 'prevrange', @id, _get_eval_enc_str(first), _get_eval_enc_str(last))).collect{|idx| - TkText::IndexString.new(idx) + Tk::Text::IndexString.new(idx) } end @@ -221,40 +237,58 @@ class TkTextTag<TkObject def destroy tk_call_without_enc(@t.path, 'tag', 'delete', @id) - TTagID_TBL[@tpath].delete(@id) if TTagID_TBL[@tpath] + TTagID_TBL.mutex.synchronize{ + TTagID_TBL[@tpath].delete(@id) if TTagID_TBL[@tpath] + } self end end +TktTag = TkTextTag class TkTextNamedTag<TkTextTag def self.new(parent, name, *args) - if TTagID_TBL[parent.path] && TTagID_TBL[parent.path][name] - tagobj = TTagID_TBL[parent.path][name] - if args != [] - keys = args.pop - if keys.kind_of?(Hash) - tagobj.add(*args) if args != [] - tagobj.configure(keys) - else - args.push keys - tagobj.add(*args) - end + tagobj = nil + TTagID_TBL.mutex.synchronize{ + if TTagID_TBL[parent.path] && TTagID_TBL[parent.path][name] + tagobj = TTagID_TBL[parent.path][name] + else + # super(parent, name, *args) + (tagobj = self.allocate).instance_eval{ + @parent = @t = parent + @tpath = parent.path + @path = @id = name + TTagID_TBL[@id] = self + TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath] + TTagID_TBL[@tpath][@id] = self unless TTagID_TBL[@tpath][@id] + @t._addtag @id, self + } + end + } + + if args != [] + keys = args.pop + if keys.kind_of?(Hash) + tagobj.add(*args) if args != [] + tagobj.configure(keys) + else + args.push keys + tagobj.add(*args) end - return tagobj - else - super(parent, name, *args) end + + tagobj end def initialize(parent, name, *args) - #unless parent.kind_of?(TkText) - # fail ArgumentError, "expect TkText for 1st argument" + # dummy:: not called by 'new' method + + #unless parent.kind_of?(Tk::Text) + # fail ArgumentError, "expect Tk::Text for 1st argument" #end @parent = @t = parent @tpath = parent.path @path = @id = name - TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath] - TTagID_TBL[@tpath][@id] = self unless TTagID_TBL[@tpath][@id] + #if mode # tk_call @t.path, "addtag", @id, *args #end @@ -268,12 +302,14 @@ class TkTextNamedTag<TkTextTag add(*args) end end - @t._addtag id, self + @t._addtag @id, self end end +TktNamedTag = TkTextNamedTag class TkTextTagSel<TkTextNamedTag def self.new(parent, *args) super(parent, 'sel', *args) end end +TktTagSel = TkTextTagSel diff --git a/ext/tk/lib/tk/textwindow.rb b/ext/tk/lib/tk/textwindow.rb index 605c40addd..a577329358 100644 --- a/ext/tk/lib/tk/textwindow.rb +++ b/ext/tk/lib/tk/textwindow.rb @@ -5,11 +5,11 @@ require 'tk' require 'tk/text' class TkTextWindow<TkObject - include TkText::IndexModMethods + include Tk::Text::IndexModMethods def initialize(parent, index, keys = {}) - #unless parent.kind_of?(TkText) - # fail ArgumentError, "expect TkText for 1st argument" + #unless parent.kind_of?(Tk::Text) + # fail ArgumentError, "expect Tk::Text for 1st argument" #end @t = parent if index == 'end' || index == :end @@ -55,7 +55,7 @@ class TkTextWindow<TkObject end def id - TkText::IndexString.new(_epath(@id)) + Tk::Text::IndexString.new(_epath(@id)) end def mark @path @@ -147,3 +147,5 @@ class TkTextWindow<TkObject value end end + +TktWindow = TkTextWindow diff --git a/ext/tk/lib/tk/timer.rb b/ext/tk/lib/tk/timer.rb index 47f2b79350..3588f0c480 100644 --- a/ext/tk/lib/tk/timer.rb +++ b/ext/tk/lib/tk/timer.rb @@ -11,7 +11,12 @@ class TkTimer TkCommandNames = ['after'.freeze].freeze - Tk_CBID = ['a'.freeze, '00000'.taint].freeze + (Tk_CBID = ['a'.freeze, '00000'.taint]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + Tk_CBTBL = {}.taint TkCore::INTERP.add_tk_procs('rb_after', 'id', <<-'EOL') @@ -96,9 +101,9 @@ class TkTimer return self end @after_script = "rb_after #{@id}" - @after_id = tk_call_without_enc('after', sleep, @after_script) @current_args = args @current_script = [sleep, @after_script] + @after_id = tk_call_without_enc('after', sleep, @after_script) self end @@ -138,9 +143,11 @@ class TkTimer end def initialize(*args, &b) - # @id = Tk_CBID.join('') - @id = Tk_CBID.join(TkCore::INTERP._ip_id_) - Tk_CBID[1].succ! + Tk_CBID.mutex.synchronize{ + # @id = Tk_CBID.join('') + @id = Tk_CBID.join(TkCore::INTERP._ip_id_) + Tk_CBID[1].succ! + } @wait_var = TkVariable.new(0) diff --git a/ext/tk/lib/tk/toplevel.rb b/ext/tk/lib/tk/toplevel.rb index 5e199e1330..2d99eda44c 100644 --- a/ext/tk/lib/tk/toplevel.rb +++ b/ext/tk/lib/tk/toplevel.rb @@ -5,7 +5,7 @@ require 'tk' require 'tk/wm' require 'tk/menuspec' -class TkToplevel<TkWindow +class Tk::Toplevel<TkWindow include Wm include TkMenuSpec @@ -117,9 +117,10 @@ class TkToplevel<TkWindow end if @classname.kind_of? TkBindTag @db_class = @classname - @classname = @classname.id + keys['class'] = @classname = @classname.id elsif @classname @db_class = TkDatabaseClass.new(@classname) + keys['class'] = @classname else @db_class = self.class @classname = @db_class::WidgetClassName @@ -165,9 +166,10 @@ class TkToplevel<TkWindow end if @classname.kind_of? TkBindTag @db_class = @classname - @classname = @classname.id + keys['class'] = @classname = @classname.id elsif @classname @db_class = TkDatabaseClass.new(@classname) + keys['class'] = @classname else @db_class = self.class @classname = @db_class::WidgetClassName @@ -255,3 +257,6 @@ class TkToplevel<TkWindow end end end + +#TkToplevel = Tk::Toplevel unless Object.const_defined? :TkToplevel +Tk.__set_toplevel_aliases__(:Tk, Tk::Toplevel, :TkToplevel) diff --git a/ext/tk/lib/tk/validation.rb b/ext/tk/lib/tk/validation.rb index 0c5b5c61b9..1da38c776d 100644 --- a/ext/tk/lib/tk/validation.rb +++ b/ext/tk/lib/tk/validation.rb @@ -249,6 +249,22 @@ class TkValidateCommand nil ] + # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) + KEY_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) + end + inf + } + + PROC_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + end + inf + } + _setup_subst_table(KEY_TBL, PROC_TBL); # diff --git a/ext/tk/lib/tk/variable.rb b/ext/tk/lib/tk/variable.rb index e5cacadc1a..f738a96ee7 100644 --- a/ext/tk/lib/tk/variable.rb +++ b/ext/tk/lib/tk/variable.rb @@ -16,11 +16,22 @@ 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].freeze + (Tk_VARIABLE_ID = ["v".freeze, "00000".taint]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + TkCore::INTERP.init_ip_env{ + TkVar_CB_TBL.mutex.synchronize{ TkVar_CB_TBL.clear } + TkVar_ID_TBL.mutex.synchronize{ TkVar_ID_TBL.clear } + } + + major, minor, type, type_name, patchlevel = TclTkLib.get_version + USE_OLD_TRACE_OPTION_STYLE = (major < 8) || (major == 8 && minor < 4) #TkCore::INTERP.add_tk_procs('rb_var', 'args', # "ruby [format \"TkVariable.callback %%Q!%s!\" $args]") -TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL') + TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL') if {[set st [catch {eval {ruby_cmd TkVariable callback} $args} ret]] != 0} { set idx [string first "\n\n" $ret] if {$idx > 0} { @@ -44,10 +55,10 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL') def TkVariable.callback(id, name1, name2, op) #name1,name2,op = tk_split_list(args) #name1,name2,op = tk_split_simplelist(args) - if TkVar_CB_TBL[id] + if cb_obj = TkVar_CB_TBL[id] #_get_eval_string(TkVar_CB_TBL[name1].trace_callback(name2,op)) begin - _get_eval_string(TkVar_CB_TBL[id].trace_callback(name2, op)) + _get_eval_string(cb_obj.trace_callback(name2, op)) rescue SystemExit exit(0) rescue Interrupt @@ -59,7 +70,11 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL') "\n---< backtrace of Ruby side >-----\n" + _toUTF8(e.backtrace.join("\n")) + "\n---< backtrace of Tk side >-------" - msg.instance_variable_set(:@encoding, 'utf-8') + if TkCore::WITH_ENCODING + msg.force_encoding('utf-8') + else + msg.instance_variable_set(:@encoding, 'utf-8') + end rescue Exception msg = e.class.inspect + ': ' + e.message + "\n" + "\n---< backtrace of Ruby side >-----\n" + @@ -267,11 +282,15 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL') def initialize(val="", type=nil) # @id = Tk_VARIABLE_ID.join('') begin - @id = Tk_VARIABLE_ID.join(TkCore::INTERP._ip_id_) - Tk_VARIABLE_ID[1].succ! + Tk_VARIABLE_ID.mutex.synchronize{ + @id = Tk_VARIABLE_ID.join(TkCore::INTERP._ip_id_) + Tk_VARIABLE_ID[1].succ! + } end until INTERP._invoke_without_enc('info', 'globals', @id).empty? - TkVar_ID_TBL[@id] = self + TkVar_ID_TBL.mutex.synchronize{ + TkVar_ID_TBL[@id] = self + } @var = @id @elem = nil @@ -1263,56 +1282,101 @@ end end end + def _check_trace_opt(opts) + if opts.kind_of?(Array) + opt_str = opts.map{|s| s.to_s}.join(' ') + else + opt_str = opts.to_s + end + + fail ArgumentError, 'null trace option' if opt_str.empty? + + if opt_str =~ /[^arwu\s]/ + # new format (Tcl/Tk8.4+?) + if opts.kind_of?(Array) + opt_ary = opts.map{|opt| opt.to_s.strip} + else + opt_ary = opt_str.split(/\s+|\|/) + opt_ary.delete('') + end + if USE_OLD_TRACE_OPTION_STYLE + opt_ary.uniq.map{|opt| + case opt + when 'array' + 'a' + when 'read' + 'r' + when 'write' + 'w' + when 'unset' + 'u' + else + fail ArgumentError, "unsupported trace option '#{opt}' on Tcl/Tk#{Tk::TCL_PATCHLEVEL}" + end + }.join + else + opt_ary + end + else + # old format + opt_ary = opt_str.delete('^arwu').split(//).uniq + if USE_OLD_TRACE_OPTION_STYLE + opt_ary.join + else + opt_ary.map{|c| + case c + when 'a' + 'array' + when 'r' + 'read' + when 'w' + 'write' + when 'u' + 'unset' + end + } + end + end + end + private :_check_trace_opt + def trace(opts, cmd = Proc.new) - @trace_var = [] if @trace_var == nil - #opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') - opts = opts.to_s - opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') - @trace_var.unshift([opts,cmd]) + opts = _check_trace_opt(opts) + (@trace_var ||= []).unshift([opts,cmd]) + if @trace_opts == nil TkVar_CB_TBL[@id] = self - @trace_opts = opts.dup - Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts, - 'rb_var ' << @id) -=begin - if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION - # TCL_VERSION >= 8.4 - Tk.tk_call_without_enc('trace', 'add', 'variable', - @id, @trace_opts, 'rb_var') + @trace_opts = opts + if USE_OLD_TRACE_OPTION_STYLE + Tk.tk_call_without_enc('trace', 'variable', + @id, @trace_opts, 'rb_var ' << @id) else - # TCL_VERSION <= 8.3 - Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts, 'rb_var') + Tk.tk_call_without_enc('trace', 'add', 'variable', + @id, @trace_opts, 'rb_var ' << @id) end -=end else newopts = @trace_opts.dup - #opts.each_byte{|c| newopts += c.chr unless newopts.index(c)} - opts.each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)} - if newopts != @trace_opts - Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts, - 'rb_var ' << @id) - @trace_opts.replace(newopts) - Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts, - 'rb_var ' << @id) -=begin - if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION - # TCL_VERSION >= 8.4 - Tk.tk_call_without_enc('trace', 'remove', 'variable', - @id, @trace_opts, 'rb_var') - @trace_opts.replace(newopts) - Tk.tk_call_without_enc('trace', 'add', 'variable', - @id, @trace_opts, 'rb_var') - else - # TCL_VERSION <= 8.3 + if USE_OLD_TRACE_OPTION_STYLE + opts.each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)} + if newopts != @trace_opts Tk.tk_call_without_enc('trace', 'vdelete', - @id, @trace_opts, 'rb_var') + @id, @trace_opts, 'rb_var ' << @id) @trace_opts.replace(newopts) Tk.tk_call_without_enc('trace', 'variable', - @id, @trace_opts, 'rb_var') + @id, @trace_opts, 'rb_var ' << @id) + end + else + newopts |= opts + unless (newopts - @trace_opts).empty? + Tk.tk_call_without_enc('trace', 'remove', 'variable', + @id, @trace_opts, 'rb_var ' << @id) + @trace_opts.replace(newopts) + Tk.tk_call_without_enc('trace', 'add', 'variable', + @id, @trace_opts, 'rb_var ' << @id) end -=end end end + self end @@ -1321,65 +1385,54 @@ end fail(RuntimeError, "invalid for a TkVariable which denotes an element of Tcl's array") end - @trace_elem = {} if @trace_elem == nil - @trace_elem[elem] = [] if @trace_elem[elem] == nil - opts = opts.to_s - opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') - @trace_elem[elem].unshift([opts,cmd]) + + opts = _check_trace_opt(opts) + + ((@trace_elem ||= {})[elem] ||= []).unshift([opts,cmd]) + if @trace_opts == nil TkVar_CB_TBL[@id] = self - @trace_opts = opts.dup - Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts, - 'rb_var ' << @id) -=begin - if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION - # TCL_VERSION >= 8.4 + @trace_opts = opts + if USE_OLD_TRACE_OPTION_STYLE Tk.tk_call_without_enc('trace', 'add', 'variable', - @id, @trace_opts, 'rb_var') + @id, @trace_opts, 'rb_var ' << @id) else - # TCL_VERSION <= 8.3 Tk.tk_call_without_enc('trace', 'variable', - @id, @trace_opts, 'rb_var') + @id, @trace_opts, 'rb_var ' << @id) end -=end else newopts = @trace_opts.dup - # opts.each_byte{|c| newopts += c.chr unless newopts.index(c)} - opts.each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)} - if newopts != @trace_opts - Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts, - 'rb_var ' << @id) - @trace_opts.replace(newopts) - Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts, - 'rb_var ' << @id) -=begin - if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION - # TCL_VERSION >= 8.4 - Tk.tk_call_without_enc('trace', 'remove', 'variable', - @id, @trace_opts, 'rb_var') - @trace_opts.replace(newopts) - Tk.tk_call_without_enc('trace', 'add', 'variable', - @id, @trace_opts, 'rb_var') - else - # TCL_VERSION <= 8.3 + if USE_OLD_TRACE_OPTION_STYLE + opts.each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)} + if newopts != @trace_opts Tk.tk_call_without_enc('trace', 'vdelete', - @id, @trace_opts, 'rb_var') + @id, @trace_opts, 'rb_var ' << @id) @trace_opts.replace(newopts) Tk.tk_call_without_enc('trace', 'variable', - @id, @trace_opts, 'rb_var') + @id, @trace_opts, 'rb_var ' << @id) + end + else + newopts |= opts + unless (newopts - @trace_opts).empty? + Tk.tk_call_without_enc('trace', 'remove', 'variable', + @id, @trace_opts, 'rb_var ' << @id) + @trace_opts.replace(newopts) + Tk.tk_call_without_enc('trace', 'add', 'variable', + @id, @trace_opts, 'rb_var ' << @id) end -=end end end + self end - def trace_vinfo + def trace_info return [] unless @trace_var @trace_var.dup end + alias trace_vinfo trace_info - def _trace_vinfo_for_element(elem) + def trace_info_for_element(elem) if @elem fail(RuntimeError, "invalid for a TkVariable which denotes an element of Tcl's array") @@ -1388,141 +1441,180 @@ end return [] unless @trace_elem[elem] @trace_elem[elem].dup end + alias trace_vinfo_for_element trace_info_for_element - def trace_vdelete(opts,cmd) + def trace_remove(opts,cmd) return self unless @trace_var.kind_of? Array - opts = opts.to_s - opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') + + opts = _check_trace_opt(opts) + idx = -1 - newopts = '' - @trace_var.each_with_index{|e,i| - 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)} - e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)} - } + if USE_OLD_TRACE_OPTION_STYLE + newopts = '' + @trace_var.each_with_index{|e, i| + if idx < 0 && e[1] == cmd + diff = false + ['a', 'r', 'w', 'u'].each{|c| + break if (diff = e[0].index(c) ^ opts.index(c)) + } + unless diff + #find + idx = i + next + end + end + e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)} + } + else + newopts = [] + @trace_var.each_with_index{|e, i| + if idx < 0 && e[1] == cmd && + e[0].size == opts.size && (e[0] - opts).empty? + # find + idx = i + next + end + newopts |= e[0] + } + end + if idx >= 0 @trace_var.delete_at(idx) else return self end - @trace_elem.each{|elem| + (@trace_elem ||= {}).each{|elem| @trace_elem[elem].each{|e| - # e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)} - e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)} + if USE_OLD_TRACE_OPTION_STYLE + e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)} + else + newopts |= e[0] + end } } - newopts = newopts.to_s - newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('') - if newopts != @trace_opts - Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts, - 'rb_var ' << @id) -=begin - if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION - # TCL_VERSION >= 8.4 - Tk.tk_call_without_enc('trace', 'remove', 'variable', - @id, @trace_opts, 'rb_var') - else - # TCL_VERSION <= 8.3 + if USE_OLD_TRACE_OPTION_STYLE + diff = false + @trace_opts.each_byte{|c| break if (diff = ! newopts.index(c))} + if diff Tk.tk_call_without_enc('trace', 'vdelete', - @id, @trace_opts, 'rb_var') + @id, @trace_opts, 'rb_var ' << @id) + @trace_opts.replace(newopts) + unless @trace_opts.empty? + Tk.tk_call_without_enc('trace', 'variable', + @id, @trace_opts, 'rb_var ' << @id) + end end -=end - @trace_opts.replace(newopts) - if @trace_opts != '' - Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts, - 'rb_var ' << @id) -=begin - if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION - # TCL_VERSION >= 8.4 + else + unless (@trace_opts - newopts).empty? + Tk.tk_call_without_enc('trace', 'remove', 'variable', + @id, @trace_opts, 'rb_var ' << @id) + @trace_opts.replace(newopts) + unless @trace_opts.empty? Tk.tk_call_without_enc('trace', 'add', 'variable', - @id, @trace_opts, 'rb_var') - else - # TCL_VERSION <= 8.3 - Tk.tk_call_without_enc('trace', 'variable', - @id, @trace_opts, 'rb_var') + @id, @trace_opts, 'rb_var ' << @id) end -=end end end self end + alias trace_delete trace_remove + alias trace_vdelete trace_remove - def trace_vdelete_for_element(elem,opts,cmd) + def trace_remove_for_element(elem,opts,cmd) if @elem fail(RuntimeError, "invalid for a TkVariable which denotes an element of Tcl's array") end return self unless @trace_elem.kind_of? Hash return self unless @trace_elem[elem].kind_of? Array - opts = opts.to_s - opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') + + opts = _check_trace_opt(opts) + idx = -1 - @trace_elem[elem].each_with_index{|e,i| - if idx < 0 && e[0] == opts && e[1] == cmd - idx = i - next - end - } + if USE_OLD_TRACE_OPTION_STYLE + @trace_elem[elem].each_with_index{|e, i| + if idx < 0 && e[1] == cmd + diff = false + ['a', 'r', 'w', 'u'].each{|c| + break if (diff = e[0].index(c) ^ opts.index(c)) + } + unless diff + #find + idx = i + next + end + end + } + else + @trace_elem[elem].each_with_index{|e, i| + if idx < 0 && e[1] == cmd && + e[0].size == opts.size && (e[0] - opts).empty? + # find + idx = i + next + end + } + end + if idx >= 0 @trace_elem[elem].delete_at(idx) else return self end - newopts = '' - @trace_var.each{|e| - # e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)} - e[0].each_byte{|c| newopts.concat(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)} - e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)} + if USE_OLD_TRACE_OPTION_STYLE + newopts = '' + @trace_var.each{|e| + e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)} } - } + @trace_elem.each{|elem| + @trace_elem[elem].each{|e| + e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)} + } + } + else + newopts = [] + @trace_var.each{|e| + newopts |= e[0] + } + @trace_elem.each{|elem| + @trace_elem[elem].each{|e| + e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)} + } + } + end - newopts = newopts.to_s - newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('') - if newopts != @trace_opts - Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts, - 'rb_var ' << @id) -=begin - if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION - # TCL_VERSION >= 8.4 - Tk.tk_call_without_enc('trace', 'remove', 'variable', - @id, @trace_opts, 'rb_var') - else - # TCL_VERSION <= 8.3 + if USE_OLD_TRACE_OPTION_STYLE + diff = false + @trace_opts.each_byte{|c| break if (diff = ! newopts.index(c))} + if diff Tk.tk_call_without_enc('trace', 'vdelete', - @id, @trace_opts, 'rb_var') + @id, @trace_opts, 'rb_var ' << @id) + @trace_opts.replace(newopts) + unless @trace_opts.empty? + Tk.tk_call_without_enc('trace', 'variable', + @id, @trace_opts, 'rb_var ' << @id) + end end -=end - @trace_opts.replace(newopts) - if @trace_opts != '' - Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts, - 'rb_var ' << @id) -=begin - if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION - # TCL_VERSION >= 8.4 + else + unless (@trace_opts - newopts).empty? + Tk.tk_call_without_enc('trace', 'remove', 'variable', + @id, @trace_opts, 'rb_var ' << @id) + @trace_opts.replace(newopts) + unless @trace_opts.empty? Tk.tk_call_without_enc('trace', 'add', 'variable', - @id, @trace_opts, 'rb_var') - else - # TCL_VERSION <= 8.3 - Tk.tk_call_without_enc('trace', 'variable', @id, - @trace_opts, 'rb_var') + @id, @trace_opts, 'rb_var ' << @id) end -=end end end self end + alias trace_delete_for_element trace_remove_for_element + alias trace_vdelete_for_element trace_remove_for_element end class TkVarAccess<TkVariable @@ -1532,12 +1624,23 @@ class TkVarAccess<TkVariable return name end - if v = TkVar_ID_TBL[name] - v.value = args[0] unless args.empty? - return v - end + name = name.to_s + v = nil + TkVar_ID_TBL.mutex.synchronize{ + if v = TkVar_ID_TBL[name] + v.value = args[0] unless args.empty? + return v + else + (v = self.allocate).instance_eval{ + @id = name + TkVar_ID_TBL[@id] = self + @var = @id + } + end + } - super(name, *args) + v.instance_eval{ initialize(name, *args) } + v end def self.new_hash(name, *args) @@ -1549,27 +1652,38 @@ class TkVarAccess<TkVariable return name end - if v = TkVar_ID_TBL[name] - unless v.is_hash? - fail ArgumentError, "already exist as a scalar variable" + name = name.to_s + v = nil + TkVar_ID_TBL.mutex.synchronize{ + if v = TkVar_ID_TBL[name] + unless v.is_hash? + fail ArgumentError, "already exist as a scalar variable" + end + v.value = args[0] unless args.empty? + return v + else + (v = self.allocate).instance_eval{ + @id = name + TkVar_ID_TBL[@id] = self + @var = @id + } end - v.value = args[0] unless args.empty? - return v - end + } INTERP._invoke_without_enc('global', name) if args.empty? && INTERP._invoke_without_enc('array', 'exist', name) == '0' - self.new(name, {}) # force creating + v.instance_eval{ initialize(name, {}) } # force creating else - self.new(name, *args) + v.instance_eval{ initialize(name, *args) } end + v end def initialize(varname, val=nil) - @id = varname - TkVar_ID_TBL[@id] = self + # @id = varname + # TkVar_ID_TBL[@id] = self - @var = @id + # @var = @id @elem = nil @def_default = false diff --git a/ext/tk/lib/tk/virtevent.rb b/ext/tk/lib/tk/virtevent.rb index d47e80aecd..ae31ac1f8f 100644 --- a/ext/tk/lib/tk/virtevent.rb +++ b/ext/tk/lib/tk/virtevent.rb @@ -9,10 +9,17 @@ class TkVirtualEvent<TkObject TkCommandNames = ['event'.freeze].freeze - TkVirtualEventID = ["VirtEvent".freeze, "00000".taint].freeze + (TkVirtualEventID = ["VirtEvent".freeze, "00000".taint]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + TkVirtualEventTBL = TkCore::INTERP.create_table - TkCore::INTERP.init_ip_env{ TkVirtualEventTBL.clear } + TkCore::INTERP.init_ip_env{ + TkVirtualEventTBL.mutex.synchronize{ TkVirtualEventTBL.clear } + } class PreDefVirtEvent<self def self.new(event, *sequences) @@ -21,22 +28,30 @@ class TkVirtualEvent<TkObject elsif event !~ /^<.*>$/ event = '<' + event + '>' end - if TkVirtualEvent::TkVirtualEventTBL.has_key?(event) - TkVirtualEvent::TkVirtualEventTBL[event] - else - super(event, *sequences) - end + TkVirtualEvent::TkVirtualEventTBL.mutex.synchronize{ + if TkVirtualEvent::TkVirtualEventTBL.has_key?(event) + TkVirtualEvent::TkVirtualEventTBL[event] + else + # super(event, *sequences) + (obj = self.allocate).instance_eval{ + initialize(event, *sequences) + TkVirtualEvent::TkVirtualEventTBL[@id] = self + } + end + } end def initialize(event, *sequences) @path = @id = event - TkVirtualEvent::TkVirtualEventTBL[@id] = self - add(*sequences) + _add_sequences(sequences) end end def TkVirtualEvent.getobj(event) - obj = TkVirtualEventTBL[event] + obj = nil + TkVirtualEventTBL.mutex.synchronize{ + obj = TkVirtualEventTBL[event] + } if obj obj else @@ -55,19 +70,31 @@ class TkVirtualEvent<TkObject end def initialize(*sequences) - # @path = @id = '<' + TkVirtualEventID.join('') + '>' - @path = @id = '<' + TkVirtualEventID.join(TkCore::INTERP._ip_id_) + '>' - TkVirtualEventID[1].succ! - add(*sequences) + TkVirtualEventID.mutex.synchronize{ + # @path = @id = '<' + TkVirtualEventID.join('') + '>' + @path = @id = '<' + TkVirtualEventID.join(TkCore::INTERP._ip_id_) + '>' + TkVirtualEventID[1].succ! + } + _add_sequences(sequences) end - def add(*sequences) - if sequences != [] + def _add_sequences(seq_ary) + unless seq_ary.empty? tk_call_without_enc('event', 'add', "<#{@id}>", - *(sequences.collect{|seq| + *(seq_ary.collect{|seq| "<#{tk_event_sequence(seq)}>" }) ) - TkVirtualEventTBL[@id] = self + end + self + end + private :_add_sequences + + def add(*sequences) + if sequences != [] + _add_sequences(sequences) + TkVirtualEventTBL.mutex.synchronize{ + TkVirtualEventTBL[@id] = self + } end self end @@ -75,20 +102,26 @@ class TkVirtualEvent<TkObject def delete(*sequences) if sequences == [] tk_call_without_enc('event', 'delete', "<#{@id}>") - TkVirtualEventTBL.delete(@id) + TkVirtualEventTBL.mutex.synchronize{ + TkVirtualEventTBL.delete(@id) + } else tk_call_without_enc('event', 'delete', "<#{@id}>", *(sequences.collect{|seq| "<#{tk_event_sequence(seq)}>" }) ) - TkVirtualEventTBL.delete(@id) if info == [] + if tk_call_without_enc('event','info',"<#{@id}>").empty? + TkVirtualEventTBL.mutex.synchronize{ + TkVirtualEventTBL.delete(@id) + } + end end self end def info tk_call_without_enc('event','info',"<#{@id}>").split(/\s+/).collect!{|seq| - l = seq.scan(/<*[^<>]+>*/).collect!{|subseq| + lst = seq.scan(/<*[^<>]+>*/).collect!{|subseq| case (subseq) when /^<<[^<>]+>>$/ TkVirtualEvent.getobj(subseq[1..-2]) @@ -98,7 +131,7 @@ class TkVirtualEvent<TkObject subseq.split('') end }.flatten - (l.size == 1) ? l[0] : l + (lst.size == 1) ? lst[0] : lst } end end diff --git a/ext/tk/lib/tk/winpkg.rb b/ext/tk/lib/tk/winpkg.rb index 737fb959b5..89fb391c77 100644 --- a/ext/tk/lib/tk/winpkg.rb +++ b/ext/tk/lib/tk/winpkg.rb @@ -7,9 +7,14 @@ # require 'tk' -module TkWinDDE +module Tk::WinDDE +end +#TkWinDDE = Tk::WinDDE +Tk.__set_toplevel_aliases__(:Tk, Tk::WinDDE, :TkWinDDE) + +module Tk::WinDDE extend Tk - extend TkWinDDE + extend Tk::WinDDE TkCommandNames = ['dde'.freeze].freeze @@ -85,9 +90,14 @@ module TkWinDDE :poke, :request, :services, :eval end -module TkWinRegistry +module Tk::WinRegistry +end +#TkWinRegistry = Tk::WinRegistry +Tk.__set_toplevel_aliases__(:Tk, Tk::WinRegistry, :TkWinRegistry) + +module Tk::WinRegistry extend Tk - extend TkWinRegistry + extend Tk::WinRegistry TkCommandNames = ['registry'.freeze].freeze diff --git a/ext/tk/lib/tk/wm.rb b/ext/tk/lib/tk/wm.rb index 1f432a3848..49dd4d73c2 100644 --- a/ext/tk/lib/tk/wm.rb +++ b/ext/tk/lib/tk/wm.rb @@ -5,273 +5,407 @@ require 'tk' module Tk module Wm - include TkComm + #include TkComm + extend TkCore TkCommandNames = ['wm'.freeze].freeze TOPLEVEL_METHODCALL_OPTKEYS = {} - def aspect(*args) + def Wm.aspect(win, *args) if args.length == 0 - list(tk_call_without_enc('wm', 'aspect', path)) + list(tk_call_without_enc('wm', 'aspect', win.epath)) else args = args[0] if args.length == 1 && args[0].kind_of?(Array) - tk_call('wm', 'aspect', path, *args) - self + tk_call('wm', 'aspect', win.epath, *args) + win end end + def aspect(*args) + Wm.aspect(self, *args) + end + alias wm_aspect aspect TOPLEVEL_METHODCALL_OPTKEYS['aspect'] = 'aspect' - def attributes(slot=nil,value=None) + def Wm.attributes(win, slot=nil,value=TkComm::None) if slot == nil - lst = tk_split_list(tk_call('wm', 'attributes', path)) + lst = tk_split_list(tk_call('wm', 'attributes', win.epath)) info = {} while key = lst.shift info[key[1..-1]] = lst.shift end info elsif slot.kind_of? Hash - tk_call('wm', 'attributes', path, *hash_kv(slot)) - self - elsif value == None - tk_call('wm', 'attributes', path, "-#{slot}") + tk_call('wm', 'attributes', win.epath, *hash_kv(slot)) + win + elsif value == TkComm::None + tk_call('wm', 'attributes', win.epath, "-#{slot}") else - tk_call('wm', 'attributes', path, "-#{slot}", value) - self + tk_call('wm', 'attributes', win.epath, "-#{slot}", value) + win end end + def attributes(slot=nil,value=TkComm::None) + Wm.attributes(self, slot, value) + end + alias wm_attributes attributes TOPLEVEL_METHODCALL_OPTKEYS['attributes'] = 'attributes' - def client(name=None) - if name == None - tk_call('wm', 'client', path) + def Wm.client(win, name=TkComm::None) + if name == TkComm::None + tk_call('wm', 'client', win.epath) else name = '' if name == nil - tk_call('wm', 'client', path, name) - self + tk_call('wm', 'client', win.epath, name) + win end end + def client(name=TkComm::None) + Wm.client(self, name) + end + alias wm_client client TOPLEVEL_METHODCALL_OPTKEYS['client'] = 'client' - def colormapwindows(*args) + def Wm.colormapwindows(win, *args) if args.size == 0 - list(tk_call_without_enc('wm', 'colormapwindows', path)) + list(tk_call_without_enc('wm', 'colormapwindows', win.epath)) else args = args[0] if args.length == 1 && args[0].kind_of?(Array) - tk_call_without_enc('wm', 'colormapwindows', path, *args) - self + tk_call_without_enc('wm', 'colormapwindows', win.epath, *args) + win end end + def colormapwindows(*args) + Wm.colormapwindows(self, *args) + end + alias wm_colormapwindows colormapwindows TOPLEVEL_METHODCALL_OPTKEYS['colormapwindows'] = 'colormapwindows' - def wm_command(value=nil) + def Wm.command(win, value=nil) if value - tk_call('wm', 'command', path, value) - self + tk_call('wm', 'command', epath, value) + win else - #procedure(tk_call('wm', 'command', path)) - tk_call('wm', 'command', path) + #procedure(tk_call('wm', 'command', epath)) + tk_call('wm', 'command', epath) end end + def wm_command(value=nil) + Wm.command(self, value) + end TOPLEVEL_METHODCALL_OPTKEYS['wm_command'] = 'wm_command' - def deiconify(ex = true) + def Wm.deiconify(win, ex = true) if ex - tk_call_without_enc('wm', 'deiconify', path) + tk_call_without_enc('wm', 'deiconify', win.epath) else - self.iconify + Wm.iconify(win) end - self + win end + def deiconify(ex = true) + Wm.deiconify(self, ex) + end + alias wm_deiconify deiconify - def focusmodel(mode = nil) + def Wm.focusmodel(win, mode = nil) if mode - tk_call_without_enc('wm', 'focusmodel', path, mode) - self + tk_call_without_enc('wm', 'focusmodel', win.epath, mode) + win else - tk_call_without_enc('wm', 'focusmodel', path) + tk_call_without_enc('wm', 'focusmodel', win.epath) end end + def focusmodel(mode = nil) + Wm.focusmodel(self, mode) + end + alias wm_focusmodel focusmodel TOPLEVEL_METHODCALL_OPTKEYS['focusmodel'] = 'focusmodel' + def Wm.forget(win) + # Tcl/Tk 8.5+ + # work with dockable frames + tk_call_without_enc('wm', 'forget', win.epath) + win + end + def wm_forget + Wm.forget(self) + end + + def Wm.frame(win) + tk_call_without_enc('wm', 'frame', win.epath) + end def frame - tk_call_without_enc('wm', 'frame', path) + Wm.frame(self) end + alias wm_frame frame - def geometry(geom=nil) + def Wm.geometry(win, geom=nil) if geom - tk_call_without_enc('wm', 'geometry', path, geom) - self + tk_call_without_enc('wm', 'geometry', win.epath, geom) + win else - tk_call_without_enc('wm', 'geometry', path) + tk_call_without_enc('wm', 'geometry', win.epath) end end + def geometry(geom=nil) + Wm.geometry(self, geom) + end + alias wm_geometry geometry TOPLEVEL_METHODCALL_OPTKEYS['geometry'] = 'geometry' - def wm_grid(*args) + def Wm.grid(win, *args) if args.size == 0 - list(tk_call_without_enc('wm', 'grid', path)) + list(tk_call_without_enc('wm', 'grid', win.epath)) else args = args[0] if args.length == 1 && args[0].kind_of?(Array) - tk_call_without_enc('wm', 'grid', path, *args) - self + tk_call_without_enc('wm', 'grid', win.epath, *args) + win end end + def wm_grid(*args) + Wm.grid(self, *args) + end TOPLEVEL_METHODCALL_OPTKEYS['wm_grid'] = 'wm_grid' - def group(leader = nil) + def Wm.group(win, leader = nil) if leader - tk_call('wm', 'group', path, leader) - self + tk_call('wm', 'group', win.epath, leader) + win else - window(tk_call('wm', 'group', path)) + window(tk_call('wm', 'group', win.epath)) end end + def group(leader = nil) + Wm.group(self, leader) + end + alias wm_group group TOPLEVEL_METHODCALL_OPTKEYS['group'] = 'group' - def iconbitmap(bmp=nil) + def Wm.iconbitmap(win, bmp=nil) if bmp - tk_call_without_enc('wm', 'iconbitmap', path, bmp) - self + tk_call_without_enc('wm', 'iconbitmap', win.epath, bmp) + win else - image_obj(tk_call_without_enc('wm', 'iconbitmap', path)) + image_obj(tk_call_without_enc('wm', 'iconbitmap', win.epath)) end end + def iconbitmap(bmp=nil) + Wm.iconbitmap(self, bmp) + end + alias wm_iconbitmap iconbitmap TOPLEVEL_METHODCALL_OPTKEYS['iconbitmap'] = 'iconbitmap' - def iconphoto(*imgs) + def Wm.iconphoto(win, *imgs) if imgs.empty? - @wm_iconphoto = nil unless defined? @wm_iconphoto - return @wm_iconphoto + win.instance_eval{ + @wm_iconphoto = nil unless defined? @wm_iconphoto + return @wm_iconphoto + } end imgs = imgs[0] if imgs.length == 1 && imgs[0].kind_of?(Array) - tk_call_without_enc('wm', 'iconphoto', path, *imgs) - @wm_iconphoto = imgs - self + tk_call_without_enc('wm', 'iconphoto', win.epath, *imgs) + win.instance_eval{ @wm_iconphoto = imgs } + win + end + def iconphoto(*imgs) + Wm.iconphoto(self, *imgs) end + alias wm_iconphoto iconphoto TOPLEVEL_METHODCALL_OPTKEYS['iconphoto'] = 'iconphoto' - def iconphoto_default(*imgs) + def Wm.iconphoto_default(win, *imgs) imgs = imgs[0] if imgs.length == 1 && imgs[0].kind_of?(Array) - tk_call_without_enc('wm', 'iconphoto', path, '-default', *imgs) - self + tk_call_without_enc('wm', 'iconphoto', win.epath, '-default', *imgs) + win + end + def iconphoto_default(*imgs) + Wm.iconphoto_default(self, *imgs) end + alias wm_iconphoto_default iconphoto_default - def iconify(ex = true) + def Wm.iconify(win, ex = true) if ex - tk_call_without_enc('wm', 'iconify', path) + tk_call_without_enc('wm', 'iconify', win.epath) else - self.deiconify + Wm.deiconify(win) end - self + win + end + def iconify(ex = true) + Wm.iconify(self, ex) end + alias wm_iconify iconify - def iconmask(bmp=nil) + def Wm.iconmask(win, bmp=nil) if bmp - tk_call_without_enc('wm', 'iconmask', path, bmp) - self + tk_call_without_enc('wm', 'iconmask', win.epath, bmp) + win else - image_obj(tk_call_without_enc('wm', 'iconmask', path)) + image_obj(tk_call_without_enc('wm', 'iconmask', win.epath)) end end + def iconmask(bmp=nil) + Wm.iconmask(self, bmp) + end + alias wm_iconmask iconmask TOPLEVEL_METHODCALL_OPTKEYS['iconmask'] = 'iconmask' - def iconname(name=nil) + def Wm.iconname(win, name=nil) if name - tk_call('wm', 'iconname', path, name) - self + tk_call('wm', 'iconname', win.epath, name) + win else - tk_call('wm', 'iconname', path) + tk_call('wm', 'iconname', win.epath) end end + def iconname(name=nil) + Wm.iconname(self, name) + end + alias wm_iconname iconname TOPLEVEL_METHODCALL_OPTKEYS['iconname'] = 'iconname' - def iconposition(*args) + def Wm.iconposition(win, *args) if args.size == 0 - list(tk_call_without_enc('wm', 'iconposition', path)) + list(tk_call_without_enc('wm', 'iconposition', win.epath)) else args = args[0] if args.length == 1 && args[0].kind_of?(Array) - tk_call_without_enc('wm', 'iconposition', path, *args) - self + tk_call_without_enc('wm', 'iconposition', win.epath, *args) + win end end + def iconposition(*args) + Wm.iconposition(self, *args) + end + alias wm_iconposition iconposition TOPLEVEL_METHODCALL_OPTKEYS['iconposition'] = 'iconposition' - def iconwindow(win = nil) - if win - tk_call_without_enc('wm', 'iconwindow', path, win) - self + def Wm.iconwindow(win, iconwin = nil) + if iconwin + tk_call_without_enc('wm', 'iconwindow', win.epath, iconwin) + win else - w = tk_call_without_enc('wm', 'iconwindow', path) + w = tk_call_without_enc('wm', 'iconwindow', win.epath) (w == '')? nil: window(w) end end + def iconwindow(iconwin = nil) + Wm.iconwindow(self, iconwin) + end + alias wm_iconwindow iconwindow TOPLEVEL_METHODCALL_OPTKEYS['iconwindow'] = 'iconwindow' - def maxsize(*args) + def Wm.manage(win) + # Tcl/Tk 8.5+ feature + tk_call_without_enc('wm', 'manage', win.epath) + win + end + def wm_manage + Wm.manage(self) + end +=begin + def Wm.manage(win, use_id = nil) + # Tcl/Tk 8.5+ feature + # -------------------------------------------------------------- + # In the future release, I want to support to embed the 'win' + # into the container which has window-id 'use-id'. + # It may give users frexibility on controlling their GUI. + # However, it may be difficult for current Tcl/Tk (Tcl/Tk8.5.1), + # because it seems to require to modify Tcl/Tk's source code. + # -------------------------------------------------------------- + if use_id + tk_call_without_enc('wm', 'manage', win.epath, '-use', use_id) + else + tk_call_without_enc('wm', 'manage', win.epath) + end + win + end +=end + + def Wm.maxsize(win, *args) if args.size == 0 - list(tk_call_without_enc('wm', 'maxsize', path)) + list(tk_call_without_enc('wm', 'maxsize', win.epath)) else args = args[0] if args.length == 1 && args[0].kind_of?(Array) - tk_call_without_enc('wm', 'maxsize', path, *args) - self + tk_call_without_enc('wm', 'maxsize', win.epath, *args) + win end end + def maxsize(*args) + Wm.maxsize(self, *args) + end + alias wm_maxsize maxsize TOPLEVEL_METHODCALL_OPTKEYS['maxsize'] = 'maxsize' - def minsize(*args) + def Wm.minsize(win, *args) if args.size == 0 - list(tk_call_without_enc('wm', 'minsize', path)) + list(tk_call_without_enc('wm', 'minsize', win.epath)) else args = args[0] if args.length == 1 && args[0].kind_of?(Array) - tk_call_without_enc('wm', 'minsize', path, *args) - self + tk_call_without_enc('wm', 'minsize', win.path, *args) + win end end + def minsize(*args) + Wm.minsize(self, *args) + end + alias wm_minsize minsize TOPLEVEL_METHODCALL_OPTKEYS['minsize'] = 'minsize' - def overrideredirect(mode=None) - if mode == None - bool(tk_call_without_enc('wm', 'overrideredirect', path)) + def Wm.overrideredirect(win, mode=TkComm::None) + if mode == TkComm::None + bool(tk_call_without_enc('wm', 'overrideredirect', win.epath)) else - tk_call_without_enc('wm', 'overrideredirect', path, mode) - self + tk_call_without_enc('wm', 'overrideredirect', win.epath, mode) + win end end + def overrideredirect(mode=TkComm::None) + Wm.overrideredirect(self, mode=TkComm::None) + end + alias wm_overrideredirect overrideredirect TOPLEVEL_METHODCALL_OPTKEYS['overrideredirect'] = 'overrideredirect' - def positionfrom(who=None) - if who == None - r = tk_call_without_enc('wm', 'positionfrom', path) + def Wm.positionfrom(win, who=TkComm::None) + if who == TkComm::None + r = tk_call_without_enc('wm', 'positionfrom', win.epath) (r == "")? nil: r else - tk_call_without_enc('wm', 'positionfrom', path, who) - self + tk_call_without_enc('wm', 'positionfrom', win.epath, who) + win end end + def positionfrom(who=TkComm::None) + Wm.positionfrom(self, who) + end + alias wm_positionfrom positionfrom TOPLEVEL_METHODCALL_OPTKEYS['positionfrom'] = 'positionfrom' - def protocol(name=nil, cmd=nil, &b) + def Wm.protocol(win, name=nil, cmd=nil, &b) if cmd - tk_call_without_enc('wm', 'protocol', path, name, cmd) - self + tk_call_without_enc('wm', 'protocol', win.epath, name, cmd) + win elsif b - tk_call_without_enc('wm', 'protocol', path, name, proc(&b)) - self + tk_call_without_enc('wm', 'protocol', win.epath, name, proc(&b)) + win elsif name - result = tk_call_without_enc('wm', 'protocol', path, name) + result = tk_call_without_enc('wm', 'protocol', win.epath, name) (result == "")? nil : tk_tcl2ruby(result) else - tk_split_simplelist(tk_call_without_enc('wm', 'protocol', path)) + tk_split_simplelist(tk_call_without_enc('wm', 'protocol', win.epath)) end end + def protocol(name=nil, cmd=nil, &b) + Wm.protocol(self, name, cmd, &b) + end + alias wm_protocol protocol - def protocols(kv=nil) + def Wm.protocols(win, kv=nil) unless kv ret = {} - self.protocol.each{|name| - ret[name] = self.protocol(name) + Wm.protocol(win).each{|name| + ret[name] = Wm.protocol(win, name) } return ret end @@ -279,82 +413,140 @@ module Tk unless kv.kind_of?(Hash) fail ArgumentError, 'expect a hash of protocol=>command' end - kv.each{|k, v| self.protocol(k, v)} - self + kv.each{|k, v| Wm.protocol(win, k, v)} + win end + def protocols(kv=nil) + Wm.protocols(self, kv) + end + alias wm_protocols protocols TOPLEVEL_METHODCALL_OPTKEYS['protocols'] = 'protocols' - def resizable(*args) + def Wm.resizable(win, *args) if args.length == 0 - list(tk_call_without_enc('wm', 'resizable', path)).collect{|e| bool(e)} + list(tk_call_without_enc('wm', 'resizable', win.epath)).map!{|e| bool(e)} else args = args[0] if args.length == 1 && args[0].kind_of?(Array) - tk_call_without_enc('wm', 'resizable', path, *args) - self + tk_call_without_enc('wm', 'resizable', win.epath, *args) + win end end + def resizable(*args) + Wm.resizable(self, *args) + end + alias wm_resizable resizable TOPLEVEL_METHODCALL_OPTKEYS['resizable'] = 'resizable' - def sizefrom(who=None) - if who == None - r = tk_call_without_enc('wm', 'sizefrom', path) + def Wm.sizefrom(win, who=TkComm::None) + if who == TkComm::None + r = tk_call_without_enc('wm', 'sizefrom', win.epath) (r == "")? nil: r else - tk_call_without_enc('wm', 'sizefrom', path, who) - self + tk_call_without_enc('wm', 'sizefrom', win.epath, who) + win end end + def sizefrom(who=TkComm::None) + Wm.sizefrom(self, who) + end + alias wm_sizefrom sizefrom TOPLEVEL_METHODCALL_OPTKEYS['sizefrom'] = 'sizefrom' + def Wm.stackorder(win) + list(tk_call('wm', 'stackorder', win.epath)) + end def stackorder - list(tk_call('wm', 'stackorder', path)) + Wm.stackorder(self) end + alias wm_stackorder stackorder - def stackorder_isabove(win) - bool(tk_call('wm', 'stackorder', path, 'isabove', win)) + def Wm.stackorder_isabove(win, target) + bool(tk_call('wm', 'stackorder', win.epath, 'isabove', target)) + end + def Wm.stackorder_is_above(win, target) + Wm.stackorder_isabove(win, target) + end + def stackorder_isabove(target) + Wm.stackorder_isabove(self, target) end + alias stackorder_is_above stackorder_isabove + alias wm_stackorder_isabove stackorder_isabove + alias wm_stackorder_is_above stackorder_isabove - def stackorder_isbelow(win) - bool(tk_call('wm', 'stackorder', path, 'isbelow', win)) + def Wm.stackorder_isbelow(win, target) + bool(tk_call('wm', 'stackorder', win.epath, 'isbelow', target)) end + def Wm.stackorder_is_below(win, target) + Wm.stackorder_isbelow(win, target) + end + def stackorder_isbelow(target) + Wm.stackorder_isbelow(self, target) + end + alias stackorder_is_below stackorder_isbelow + alias wm_stackorder_isbelow stackorder_isbelow + alias wm_stackorder_is_below stackorder_isbelow - def state(st=nil) + def Wm.state(win, st=nil) if st - tk_call_without_enc('wm', 'state', path, st) - self + tk_call_without_enc('wm', 'state', win.epath, st) + win else - tk_call_without_enc('wm', 'state', path) + tk_call_without_enc('wm', 'state', win.epath) end end + def state(st=nil) + Wm.state(self, st) + end + alias wm_state state TOPLEVEL_METHODCALL_OPTKEYS['state'] = 'state' - def title(str=nil) + def Wm.title(win, str=nil) if str - tk_call('wm', 'title', path, str) - self + tk_call('wm', 'title', win.epath, str) + win else - tk_call('wm', 'title', path) + tk_call('wm', 'title', win.epath) end end + def title(str=nil) + Wm.title(self, str) + end + alias wm_title title TOPLEVEL_METHODCALL_OPTKEYS['title'] = 'title' - def transient(master=nil) + def Wm.transient(win, master=nil) if master - tk_call_without_enc('wm', 'transient', path, master) - self + tk_call_without_enc('wm', 'transient', win.epath, master) + win else - window(tk_call_without_enc('wm', 'transient', path)) + window(tk_call_without_enc('wm', 'transient', win.epath)) end end + def transient(master=nil) + Wm.transient(self, master) + end + alias wm_transient transient TOPLEVEL_METHODCALL_OPTKEYS['transient'] = 'transient' - def withdraw(ex = true) + def Wm.withdraw(win, ex = true) if ex - tk_call_without_enc('wm', 'withdraw', path) + tk_call_without_enc('wm', 'withdraw', win.epath) else - self.deiconify + Wm.deiconify(win) end - self + win end + def withdraw(ex = true) + Wm.withdraw(self, ex) + end + alias wm_withdraw withdraw + end + + module Wm_for_General + Wm.instance_methods.each{|m| + if (m = m.to_s) =~ /^wm_(.*)$/ + eval "def #{m}(*args); Tk::Wm.#{$1}(self, *args); end" + end + } end end |