Index: ext/tk/stubs.c =================================================================== --- ext/tk/stubs.c (revision 23917) +++ ext/tk/stubs.c (working copy) @@ -11,6 +11,25 @@ /*------------------------------*/ +#ifdef __MACOS__ +# include +# include + +static int call_macinit = 0; + +static void +_macinit() +{ + if (!call_macinit) { + tcl_macQdPtr = &qd; /* setup QuickDraw globals */ + Tcl_MacSetEventProc(TkMacConvertEvent); /* setup event handler */ + call_macinit = 1; + } +} +#endif + +/*------------------------------*/ + static int nativethread_checked = 0; static void @@ -301,6 +320,10 @@ if (!Tk_InitStubs(tcl_ip, (char *)"8.1", 0)) return FAIL_Tk_InitStubs; + +#ifdef __MACOS__ + _macinit(); +#endif } return TCLTK_STUBS_OK; @@ -336,6 +359,10 @@ if (!Tk_InitStubs(tcl_ip, (char *)"8.1", 0)) return FAIL_Tk_InitStubs; + +#ifdef __MACOS__ + _macinit(); +#endif } return TCLTK_STUBS_OK; @@ -490,6 +517,9 @@ return FAIL_Tk_Init; if (!call_tk_stubs_init) { +#ifdef __MACOS__ + _macinit(); +#endif call_tk_stubs_init = 1; } @@ -509,6 +539,9 @@ return FAIL_Tk_Init; if (!call_tk_stubs_init) { +#ifdef __MACOS__ + _macinit(); +#endif call_tk_stubs_init = 1; } Index: ext/tk/sample/demos-jp/widget =================================================================== --- ext/tk/sample/demos-jp/widget (revision 23917) +++ ext/tk/sample/demos-jp/widget (working copy) @@ -190,10 +190,14 @@ yscrollcommand proc{|first,last| scr.set first,last} } scr.command(proc{|*args| txt.yview(*args)}) + # txt.pack('in'=>textFrame, 'expand'=>'yes', 'fill'=>'both', 'padx'=>1) - txt.pack('in'=>textFrame, 'expand'=>'yes', 'fill'=>'both') +# txt.pack('in'=>textFrame, 'expand'=>'yes', 'fill'=>'both') # textFrame.pack('expand'=>'yes', 'fill'=>'both', 'padx'=>1, 'pady'=>2) textFrame.pack('expand'=>'yes', 'fill'=>'both') + # $root.withdraw.deiconify + Tk.update_idletasks + txt.pack('in'=>textFrame, 'expand'=>'yes', 'fill'=>'both') statusBar = TkFrame.new($root) {|f| if $tk_version =~ /^4.*/ @@ -1070,7 +1074,7 @@ # def aboutBox Tk.messageBox('icon'=>'info', 'type'=>'ok', 'title'=>'About Widget Demo', - 'message'=>"Ruby/Tk ウィジェットデモ Ver.1.7.0-jp\n\n" + + 'message'=>"Ruby/Tk ウィジェットデモ Ver.1.7.1-jp\n\n" + "based on demos of Tk8.1 -- 8.5 " + "( Copyright of Tcl/Tk demos:: " + "(c) 1996-1997 Sun Microsystems, Inc. / " + Index: ext/tk/sample/editable_listbox.rb =================================================================== --- ext/tk/sample/editable_listbox.rb (revision 23917) +++ ext/tk/sample/editable_listbox.rb (working copy) @@ -1,5 +1,5 @@ # -# Editable_TkListbox class +# Tk::Editable_Listbox class # # When "DoubleClick-1" on a listbox item, the entry box is opend on the # item. And when hit "Return" key on the entry box after modifying the @@ -10,20 +10,69 @@ # require 'tk' -class Editable_TkListbox < TkListbox - def _ebox_placer(coord_y) - idx = self.nearest(coord_y) - x, y, w, h = self.bbox(idx) +class Tk::Editable_Listbox < TkListbox + def _ebox_move(idx) + x, y, w, h = bbox(idx) + return unless y && h @ebox.place(:x => 0, :relwidth => 1.0, - :y => y - self.selectborderwidth, - :height => h + 2 * self.selectborderwidth) + :y => y - selectborderwidth, + :height => h + 2 * selectborderwidth) @ebox.pos = idx - @ebox.value = self.listvariable.list[idx] @ebox.focus end - private :_ebox_placer + def _ebox_placer(idx) + _ebox_move(idx) + @ebox.value = listvariable.list[idx] + @ebox.xview_moveto(self.xview[0]) + end + def _ebox_erase + @ebox.place_forget + @ebox.pos = -1 + end + private :_ebox_move, :_ebox_placer, :_ebox_erase + + def _setup_ebox_bindings + # bindings for entry + @ebox.bind('Return'){ + list = listvariable.list + list[@ebox.pos] = @ebox.value + listvariable.value = list + _ebox_erase + focus + } + + @ebox.bind('Escape'){ _ebox_erase } + end + def _setup_listbox_bindings + # bindings for listbox + bind('FocusIn'){ + if (idx = @ebox.pos) >= 0 + see(idx) if bbox(idx).empty? + @ebox.focus(true) + end + } + + bind('Double-1', '%y'){|y| _ebox_placer(nearest(y)) } + + bind('Return'){ + if idx = index(:active) + _ebox_placer(idx) + end + } + end + private :_setup_ebox_bindings, :_setup_listbox_bindings + + def yview(*args) + if bbox(@ebox.pos).empty? + @ebox.place_forget + else + _ebox_move(@ebox.pos) + end + super + end + def create_self(keys) super(keys) @@ -37,33 +86,25 @@ def self.pos=(idx); @pos = idx; end } - @ebox.bind('Return'){ - list = self.listvariable.list - list[@ebox.pos] = @ebox.value - self.listvariable.value = list - @ebox.place_forget - @ebox.pos = -1 - } - - @ebox.bind('Escape'){ - @ebox.place_forget - @ebox.pos = -1 - } - - self.bind('Double-1', '%y'){|y| _ebox_placer(y) } + _setup_ebox_bindings + _setup_listbox_bindings end end if $0 == __FILE__ + #lbox0 = TkListbox.new.pack(:side=>:left) + #lbox0.insert(:end, 0,1,2,3,4,5,6,7,8,9,0,1,2,3) + scr = TkScrollbar.new.pack(:side=>:right, :fill=>:y) - lbox1 = Editable_TkListbox.new.pack(:side=>:left) - lbox2 = Editable_TkListbox.new.pack(:side=>:left) + lbox1 = Tk::Editable_Listbox.new.pack(:side=>:left) + lbox2 = Tk::Editable_Listbox.new.pack(:side=>:left) scr.assign(lbox1, lbox2) lbox1.insert(:end, *%w(a b c d e f g h i j k l m n)) lbox2.insert(:end, 0,1,2,3,4,5,6,7,8,9,0,1,2,3) + Tk.mainloop end Index: ext/tk/sample/tkballoonhelp.rb =================================================================== --- ext/tk/sample/tkballoonhelp.rb (revision 23917) +++ ext/tk/sample/tkballoonhelp.rb (working copy) @@ -7,11 +7,15 @@ # please try to use the Tix extension of Tcl/Tk under Ruby/Tk. # # The interval time to display a balloon help is defined 'interval' option -# (default is 1000ms). +# (default is 750ms). # require 'tk' -class TkBalloonHelp'bisque').pack + # @label = TkLabel.new(@frame, 'background'=>'bisque').pack + @label = TkLabel.new(@frame, + 'foreground'=>DEFAULT_FOREGROUND, + 'background'=>DEFAULT_BACKGROUND).pack @label.configure(_symbolkey2str(keys)) unless keys.empty? @path = @label end @@ -118,41 +125,42 @@ if __FILE__ == $0 TkButton.new('text'=>'This button has a balloon help') {|b| pack('fill'=>'x') - TkBalloonHelp.new(b, 'text'=>' Message ') + Tk::BalloonHelp.new(b, 'text'=>' Message ') } TkButton.new('text'=>'This button has another balloon help') {|b| pack('fill'=>'x') - TkBalloonHelp.new(b, 'text'=>'configured message', - 'interval'=>200, 'font'=>'courier', - 'background'=>'gray', 'foreground'=>'red') + Tk::BalloonHelp.new(b, + 'text'=>"CONFIGURED MESSAGE\nchange colors, and so on", + 'interval'=>200, 'font'=>'courier', + 'background'=>'gray', 'foreground'=>'red') } sb = TkScrollbox.new.pack(:fill=>:x) sb.insert(:end, *%w(aaa bbb ccc ddd eee fff ggg hhh iii jjj kkk lll mmm)) =begin # CASE1 : command takes no arguemnt - bh = TkBalloonHelp.new(sb, :interval=>500, - :relief=>:ridge, :background=>'white', - :command=>proc{ - y = TkWinfo.pointery(sb) - TkWinfo.rooty(sb) - bh.text "current index == #{sb.nearest(y)}" - }) + bh = Tk::BalloonHelp.new(sb, :interval=>500, + :relief=>:ridge, :background=>'white', + :command=>proc{ + y = TkWinfo.pointery(sb) - TkWinfo.rooty(sb) + bh.text "current index == #{sb.nearest(y)}" + }) =end =begin # CASE2 : command takes 2 arguemnts - bh = TkBalloonHelp.new(sb, :interval=>500, - :relief=>:ridge, :background=>'white', - :command=>proc{|x, y| - bh.text "current index == #{sb.nearest(y)}" - }) + bh = Tk::BalloonHelp.new(sb, :interval=>500, + :relief=>:ridge, :background=>'white', + :command=>proc{|x, y| + bh.text "current index == #{sb.nearest(y)}" + }) =end =begin # CASE3 : command takes 3 arguemnts - TkBalloonHelp.new(sb, :interval=>500, - :relief=>:ridge, :background=>'white', - :command=>proc{|x, y, bhelp| - bhelp.text "current index == #{sb.nearest(y)}" - }) + Tk::BalloonHelp.new(sb, :interval=>500, + :relief=>:ridge, :background=>'white', + :command=>proc{|x, y, bhelp| + bhelp.text "current index == #{sb.nearest(y)}" + }) =end =begin # CASE4a : command is a Proc object and takes 4 arguemnts @@ -160,16 +168,16 @@ bhelp.text "current index == #{parent.nearest(y)}" } - TkBalloonHelp.new(sb, :interval=>500, - :relief=>:ridge, :background=>'white', - :command=>cmd) + Tk::BalloonHelp.new(sb, :interval=>500, + :relief=>:ridge, :background=>'white', + :command=>cmd) sb2 = TkScrollbox.new.pack(:fill=>:x) sb2.insert(:end, *%w(AAA BBB CCC DDD EEE FFF GGG HHH III JJJ KKK LLL MMM)) - TkBalloonHelp.new(sb2, :interval=>500, - :padx=>5, :relief=>:raised, - :background=>'gray25', :foreground=>'white', - :command=>cmd) + Tk::BalloonHelp.new(sb2, :interval=>500, + :padx=>5, :relief=>:raised, + :background=>'gray25', :foreground=>'white', + :command=>cmd) =end #=begin # CASE4b : command is a Method object and takes 4 arguemnts @@ -178,16 +186,16 @@ end cmd = self.method(:set_msg) - TkBalloonHelp.new(sb, :interval=>500, - :relief=>:ridge, :background=>'white', - :command=>cmd) + Tk::BalloonHelp.new(sb, :interval=>500, + :relief=>:ridge, :background=>'white', + :command=>cmd) sb2 = TkScrollbox.new.pack(:fill=>:x) sb2.insert(:end, *%w(AAA BBB CCC DDD EEE FFF GGG HHH III JJJ KKK LLL MMM)) - TkBalloonHelp.new(sb2, :interval=>500, - :padx=>5, :relief=>:raised, - :background=>'gray25', :foreground=>'white', - :command=>cmd) + Tk::BalloonHelp.new(sb2, :interval=>500, + :padx=>5, :relief=>:raised, + :background=>'gray25', :foreground=>'white', + :command=>cmd) #=end Tk.mainloop Index: ext/tk/sample/tktextframe.rb =================================================================== --- ext/tk/sample/tktextframe.rb (revision 23917) +++ ext/tk/sample/tktextframe.rb (working copy) @@ -5,9 +5,53 @@ # require 'tk' -class TkTextFrame < TkText +module Tk::ScrollbarComposite include TkComposite + def component_construct_keys + # If a component requires options for construction, + # return an Array of option-keys. + [] + end + private :component_construct_keys + + def create_component(keys={}) + # This method must return the created component widget. + end + private :create_component + + def component_delegates + # if want to override defalut option-methods or delegates, + # please define here. + end + private :component_delegates + + def define_delegates + # option methods for scrollbars + option_methods([:scrollbarwidth, :get_scrollbarwidth]) + + # set receiver widgets for configure methods (with alias) + delegate_alias('scrollbarrelief', 'relief', @h_scroll, @v_scroll) + delegate_alias('framebackground', 'background', + @frame, @h_scroll, @v_scroll) + delegate_alias('activeframebackground', 'activebackground', + @h_scroll, @v_scroll) + + # set receiver widgets for configure methods + delegate('DEFAULT', @component) + delegate('troughcolor', @h_scroll, @v_scroll) + delegate('repeatdelay', @h_scroll, @v_scroll) + delegate('repeatinterval', @h_scroll, @v_scroll) + delegate('borderwidth', @frame) + delegate('relief', @frame) + + component_delegates + end + private :define_delegates + + DEFAULT_VSCROLL = true + DEFAULT_HSCROLL = true + def initialize_composite(keys={}) keys = _symbolkey2str(keys) @@ -15,55 +59,123 @@ @v_scroll = TkScrollbar.new(@frame, 'orient'=>'vertical') @h_scroll = TkScrollbar.new(@frame, 'orient'=>'horizontal') - # create a text widget - @text = TkText.new(@frame, 'wrap'=>'none') + # create a component + construct_keys = {} + ((component_construct_keys.map{|k| k.to_s}) & keys.keys).each{|k| + construct_keys[k] = keys.delete(k) + } + # create a component (the component must be scrollable) + @component = create_component(construct_keys) + # set default receiver of method calls - @path = @text.path + @path = @component.path # assign scrollbars - @text.xscrollbar(@h_scroll) - @text.yscrollbar(@v_scroll) + @component.xscrollbar(@h_scroll) + @component.yscrollbar(@v_scroll) # allignment TkGrid.rowconfigure(@frame, 0, 'weight'=>1, 'minsize'=>0) TkGrid.columnconfigure(@frame, 0, 'weight'=>1, 'minsize'=>0) - @text.grid('row'=>0, 'column'=>0, 'sticky'=>'news') + @component.grid('row'=>0, 'column'=>0, 'sticky'=>'news') # scrollbars ON - vscroll(keys.delete('vscroll'){true}) - hscroll(keys.delete('hscroll'){true}) + vscroll(keys.delete('vscroll'){self.class::DEFAULT_VSCROLL}) + hscroll(keys.delete('hscroll'){self.class::DEFAULT_HSCROLL}) - # set background of the text widget -=begin - color = keys.delete('textbackground') - textbackground(color) if color -=end - # please check the differences of the following definitions + # do configure + define_delegates + + # do configure + configure keys unless keys.empty? + end + private :initialize_composite + + # get/set width of scrollbar + def get_scrollbarwidth + @v_scroll.width + end + def set_scrollbarwidth(width) + @v_scroll.width(width) + @h_scroll.width(width) + end + alias :scrollbarwidth :set_scrollbarwidth + + def hook_vscroll_on(*args); end + def hook_vscroll_off(*args); end + def hook_hscroll_on(*args); end + def hook_hscroll_off(*args); end + private :hook_vscroll_on,:hook_vscroll_off,:hook_hscroll_on,:hook_hscroll_off + + # vertical scrollbar : ON/OFF + def vscroll(mode, *args) + st = TkGrid.info(@v_scroll) + if mode && st.size == 0 then + @v_scroll.grid('row'=>0, 'column'=>1, 'sticky'=>'ns') + hook_vscroll_on(*args) + elsif !mode && st.size != 0 then + @v_scroll.ungrid + hook_vscroll_off(*args) + end + self + end + + # horizontal scrollbar : ON/OFF + def hscroll(mode, *args) + st = TkGrid.info(@h_scroll) + if mode && st.size == 0 then + @h_scroll.grid('row'=>1, 'column'=>0, 'sticky'=>'ew') + hook_hscroll_on(*args) + elsif !mode && st.size != 0 then + @h_scroll.ungrid + hook_hscroll_off(*args) + end + self + end +end + +################################################ + +class TkTextFrame < TkText + include Tk::ScrollbarComposite + + # def component_construct_keys; []; end + # private :component_construct_keys + + def create_component(keys={}) + # keys has options which are listed by component_construct_keys method. + @text = TkText.new(@frame, 'wrap'=>'none') + @text.configure(keys) unless keys.empty? + + # option methods for component option_methods( - [:scrollbarwidth, :get_scrollbarwidth], [:textbackground, nil, :textbg_info], :textborderwidth, :textrelief ) - # set receiver widgets for configure methods (with alias) - delegate_alias('scrollbarrelief', 'relief', @h_scroll, @v_scroll) + # return the created componet + @text + end + private :create_component - # set receiver widgets for configure methods - delegate('DEFAULT', @text) - delegate('background', @frame, @h_scroll, @v_scroll) - delegate('activebackground', @h_scroll, @v_scroll) - delegate('troughcolor', @h_scroll, @v_scroll) - delegate('repeatdelay', @h_scroll, @v_scroll) - delegate('repeatinterval', @h_scroll, @v_scroll) - delegate('borderwidth', @frame) - delegate('relief', @frame) + # def component_delegates; end + # private :component_delegates - # do configure - configure keys unless keys.empty? + def hook_hscroll_on(wrap_mode=nil) + if wrap_mode + wrap wrap_mode + else + wrap 'none' # => self.wrap('none') + end end - private :initialize_composite + def hook_hscroll_off(wrap_mode) + wrap wrap_mode # => self.wrap(wrap_mode) + end + def hscroll(mode, wrap_mode="char") + super + end # set background color of text widget def textbackground(color = nil) @@ -103,47 +215,13 @@ def textrelief(type) @text.relief(type) end - - # get/set width of scrollbar - def get_scrollbarwidth - @v_scroll.width - end - def set_scrollbarwidth(width) - @v_scroll.width(width) - @h_scroll.width(width) - end - alias :scrollbarwidth :set_scrollbarwidth - - # vertical scrollbar : ON/OFF - def vscroll(mode) - st = TkGrid.info(@v_scroll) - if mode && st.size == 0 then - @v_scroll.grid('row'=>0, 'column'=>1, 'sticky'=>'ns') - elsif !mode && st.size != 0 then - @v_scroll.ungrid - end - self - end - - # horizontal scrollbar : ON/OFF - def hscroll(mode, wrap_mode="char") - st = TkGrid.info(@h_scroll) - if mode && st.size == 0 then - @h_scroll.grid('row'=>1, 'column'=>0, 'sticky'=>'ew') - wrap 'none' # => self.wrap('none') - elsif !mode && st.size != 0 then - @h_scroll.ungrid - wrap wrap_mode # => self.wrap(wrap_mode) - end - self - end end - ################################################ # test ################################################ if __FILE__ == $0 + TkLabel.new(:text=>'TkTextFrame is an example of Tk::ScrollbarComposite module.').pack f = TkFrame.new.pack('fill'=>'x') #t = TkTextFrame.new.pack t = TkTextFrame.new(:textborderwidth=>3, @@ -158,5 +236,46 @@ 'command'=>proc{t.hscroll(true)}).pack('side'=>'left') TkButton.new(f, 'text'=>'hscr OFF', 'command'=>proc{t.hscroll(false)}).pack('side'=>'left') + + ############################################ + + # Tk.default_widget_set = :Ttk + + TkFrame.new.pack(:pady=>10) + TkLabel.new(:text=>'The following is another example of Tk::ScrollbarComposite module.').pack + + #---------------------------------- + class ScrListbox < TkListbox + include Tk::ScrollbarComposite + + DEFAULT_HSCROLL = false + + def create_component(keys={}) + TkListbox.new(@frame, keys) + end + private :create_component + end + #---------------------------------- + + f = TkFrame.new.pack(:pady=>5) + lbox = ScrListbox.new(f).pack(:side=>:left) + lbox.value = %w(aa bb cc dd eeeeeeeeeeeeeeeeeeeeeeeeee ffffffffff gg hh ii jj kk ll mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm nn oo pp qq) + fb = TkFrame.new(f).pack(:expand=>true, :fill=>:y, :padx=>5) + TkButton.new(fb, 'text'=>'lbox hscr OFF', + 'command'=>proc{lbox.hscroll(false)}).pack(:side=>:bottom, + :fill=>:x) + TkButton.new(fb, 'text'=>'lbox hscr ON', + 'command'=>proc{lbox.hscroll(true)}).pack(:side=>:bottom, + :fill=>:x) + TkFrame.new(fb).pack(:pady=>5, :side=>:bottom) + TkButton.new(fb, 'text'=>'lbox vscr OFF', + 'command'=>proc{lbox.vscroll(false)}).pack(:side=>:bottom, + :fill=>:x) + TkButton.new(fb, 'text'=>'lbox vscr ON', + 'command'=>proc{lbox.vscroll(true)}).pack(:side=>:bottom, + :fill=>:x) + + ############################################ + Tk.mainloop end Index: ext/tk/sample/tkalignbox.rb =================================================================== --- ext/tk/sample/tkalignbox.rb (revision 23917) +++ ext/tk/sample/tkalignbox.rb (working copy) @@ -10,10 +10,10 @@ require 'tk' -class TkAlignBox < TkFrame +class Tk::AlignBox < TkFrame def initialize(*args) - if self.class == TkAlignBox - fail RuntimeError, "TkAlignBox is an abstract class" + if self.class == Tk::AlignBox + fail RuntimeError, "Tk::AlignBox is an abstract class" end @padx = 0 @pady = 0 @@ -31,12 +31,12 @@ end def _set_framesize - fail RuntimeError, "TkAlignBox is an abstract class" + fail RuntimeError, "Tk::AlignBox is an abstract class" end private :_set_framesize def _place_config(widget, idx, cnt) - fail RuntimeError, "TkAlignBox is an abstract class" + fail RuntimeError, "Tk::AlignBox is an abstract class" end private :_place_config @@ -117,7 +117,7 @@ attr_accessor :propagate end -class TkHBox < TkAlignBox +class Tk::HBox < Tk::AlignBox def _set_framesize bd = self.borderwidth self.width((@max_width + 2*@padx) * @widgets.size + 2*bd) @@ -134,9 +134,9 @@ end private :_place_config end -TkHLBox = TkHBox +Tk::HLBox = Tk::HBox -class TkHRBox < TkHBox +class Tk::HRBox < Tk::HBox def _place_config(widget, idx, cnt) widget.place_in(self, 'relx'=>(cnt - idx - 1)/cnt, 'x'=>@padx, @@ -147,7 +147,7 @@ private :_place_config end -class TkVBox < TkAlignBox +class Tk::VBox < Tk::AlignBox def _set_framesize bd = self.borderwidth self.width(@max_width + 2*@padx + 2*bd) @@ -164,9 +164,9 @@ end private :_place_config end -TkVTBox = TkVBox +Tk::VTBox = Tk::VBox -class TkVBBox < TkVBox +class Tk::VBBox < Tk::VBox def _place_config(widget, idx, cnt) widget.place_in(self, 'relx'=>0, 'x'=>@padx, @@ -181,31 +181,31 @@ # test ################################################ if __FILE__ == $0 - f = TkHBox.new(:borderwidth=>3, :relief=>'ridge').pack + f = Tk::HBox.new(:borderwidth=>3, :relief=>'ridge').pack f.add(TkButton.new(f, :text=>'a'), TkButton.new(f, :text=>'aa', :font=>'Helvetica 16'), TkButton.new(f, :text=>'aaa'), TkButton.new(f, :text=>'aaaa')) - f = TkHBox.new(:borderwidth=>3, :relief=>'ridge', + f = Tk::HBox.new(:borderwidth=>3, :relief=>'ridge', :padx=>7, :pady=>3, :background=>'yellow').pack f.add(TkButton.new(f, :text=>'a'), TkButton.new(f, :text=>'aa', :font=>'Helvetica 16'), TkButton.new(f, :text=>'aaa'), TkButton.new(f, :text=>'aaaa')) - f = TkVBox.new(:borderwidth=>5, :relief=>'groove').pack + f = Tk::VBox.new(:borderwidth=>5, :relief=>'groove').pack(:fill=>:y, :expand=>true) f.add(TkButton.new(f, :text=>'a'), TkButton.new(f, :text=>'aa', :font=>'Helvetica 30'), TkButton.new(f, :text=>'aaa'), TkButton.new(f, :text=>'aaaa')) - f = TkHRBox.new(:borderwidth=>3, :relief=>'raised').pack(:fill=>:x) + f = Tk::HRBox.new(:borderwidth=>3, :relief=>'raised').pack(:fill=>:x) f.add(TkButton.new(f, :text=>'a'), TkButton.new(f, :text=>'aa'), TkButton.new(f, :text=>'aaa')) - f = TkVBBox.new(:borderwidth=>3, :relief=>'ridge').pack(:fill=>:x) + f = Tk::VBBox.new(:borderwidth=>3, :relief=>'ridge').pack(:fill=>:x) f.propagate = false f.height 100 f.add(TkFrame.new(f){|ff| Index: ext/tk/sample/demos-en/widget =================================================================== --- ext/tk/sample/demos-en/widget (revision 23917) +++ ext/tk/sample/demos-en/widget (working copy) @@ -170,9 +170,12 @@ } scr.command(proc{|*args| txt.yview(*args)}) # txt.pack('in'=>textFrame, 'expand'=>'yes', 'fill'=>'both', 'padx'=>1) - txt.pack('in'=>textFrame, 'expand'=>'yes', 'fill'=>'both') +# txt.pack('in'=>textFrame, 'expand'=>'yes', 'fill'=>'both') # textFrame.pack('expand'=>'yes', 'fill'=>'both', 'padx'=>1, 'pady'=>2) textFrame.pack('expand'=>'yes', 'fill'=>'both') + # $root.withdraw.deiconify + Tk.update_idletasks + txt.pack('in'=>textFrame, 'expand'=>'yes', 'fill'=>'both') statusBar = TkFrame.new($root) {|f| if $tk_version =~ /^4.*/ @@ -1035,7 +1038,7 @@ # def aboutBox Tk.messageBox('icon'=>'info', 'type'=>'ok', 'title'=>'About Widget Demo', - 'message'=>"Ruby/Tk widget demonstration Ver.1.7.0-en\n\n" + + 'message'=>"Ruby/Tk widget demonstration Ver.1.7.1-en\n\n" + "based on demos of Tk8.1 -- 8.5 " + "( Copyright of Tcl/Tk demos:: " + "(c) 1996-1997 Sun Microsystems, Inc. / " + Index: ext/tk/sample/tkcombobox.rb =================================================================== --- ext/tk/sample/tkcombobox.rb (revision 23917) +++ ext/tk/sample/tkcombobox.rb (working copy) @@ -5,7 +5,7 @@ # require 'tk' -class TkAutoScrollbox < TkListbox +class Tk::AutoScrollListbox < TkListbox include TkComposite @@up_bmp = TkBitmapImage.new(:data=><<startwait, - :interval=>interval).pack(:fill=>:both, - :expand=>true) + @lst = Tk::AutoScrollListbox.new(@top, + :startwait=>startwait, + :interval=>interval).pack(:fill=>:both, + :expand=>true) @ent_list = [] @var = TkVariable.new @@ -406,9 +396,9 @@ ################################################ if __FILE__ == $0 v = TkVariable.new - e = TkCombobox.new(:height=>7, :scrollbar=>true, :textvariable=>v, - :arrowrelief=>:flat, :arrowborderwidth=>0, - :startwait=>400, :interval=>200).pack + e = Tk::Combobox.new(:height=>7, :scrollbar=>true, :textvariable=>v, + :arrowrelief=>:flat, :arrowborderwidth=>0, + :startwait=>400, :interval=>200).pack e.values(%w(aa bb cc dd ee ff gg hh ii jj kk ll mm nn oo pp qq rr ss tt uu)) #e.see(e.list_index('end') - 2) e.value = 'cc' @@ -421,8 +411,9 @@ TkFrame.new(:relief=>:raised, :borderwidth=>2, :height=>3).pack(:fill=>:x, :expand=>true, :padx=>5, :pady=>3) - l = TkAutoScrollbox.new(nil, :relief=>:groove, :borderwidth=>4, - :width=>20).pack(:fill=>:both, :expand=>true) + l = Tk::AutoScrollListbox.new(nil, :relief=>:groove, :borderwidth=>4, + :height=>7, :width=>20).pack(:fill=>:both, + :expand=>true) (0..20).each{|i| l.insert('end', "line #{i}")} TkFrame.new(:relief=>:ridge, :borderwidth=>3){ Index: ext/tk/sample/scrollframe.rb =================================================================== --- ext/tk/sample/scrollframe.rb (revision 23917) +++ ext/tk/sample/scrollframe.rb (working copy) @@ -220,17 +220,26 @@ # f.hscroll(false) + # add a text widget Tk.after(3000){ t = TkText.new(f).pack(:expand=>true, :fill=>:both) - t.insert(:end, 'Here is a text widget') + t.insert(:end, "An example of Tk::ScrollFrame widget.\n\n") + t.insert(:end, "Here is a text widget.\n") + t.insert(:end, "Please resize the application window, ") + t.insert(:end, "and try the scrollbars ") + t.insert(:end, "to move the view of packed widgets.\n") } + # remove a vertical scrollbar, and then the scrollframe is not scrollable. Tk.after(6000){ f.vscroll(false) } + # add a vertical scrollbar, and make the scrollframe scrollable. Tk.after(9000){ f.vscroll(true) } + # remove a horizontal scrollbar, and then the scrollframe is not scrollable. Tk.after(12000){ f.hscroll(false) } + # add a horizontal scrollbar, and make the scrollframe scrollable. Tk.after(15000){ f.hscroll(true) } Tk.mainloop Index: ext/tk/tcltklib.c =================================================================== --- ext/tk/tcltklib.c (revision 23917) +++ ext/tk/tcltklib.c (working copy) @@ -4,7 +4,7 @@ * Oct. 24, 1997 Y. Matsumoto */ -#define TCLTKLIB_RELEASE_DATE "2008-12-22" +#define TCLTKLIB_RELEASE_DATE "2009-07-01" #include "ruby.h" @@ -15,6 +15,19 @@ #include "version.h" #endif +#ifdef RUBY_VM +static VALUE rb_thread_critical; /* dummy */ +int rb_thread_check_trap_pending(); +#else +/* use rb_thread_critical on Ruby 1.8.x */ +#include "rubysig.h" +#endif + +#if defined(HAVE_RB_PROC_NEW) && !defined(RUBY_VM) +/* Ruby 1.8 :: rb_proc_new() was hidden from intern.h at 2008/04/22 */ +extern VALUE rb_proc_new _((VALUE (*)(ANYARGS/* VALUE yieldarg[, VALUE procarg] */), VALUE)); +#endif + #undef EXTERN /* avoid conflict with tcl.h of tcl8.2 or before */ #include #ifdef HAVE_STDARG_PROTOTYPES @@ -49,9 +62,6 @@ #define TCL_FINAL_RELEASE 2 /* "final" */ #endif -static VALUE rb_thread_critical; /* dummy */ -int rb_thread_check_trap_pending(); - static struct { int major; int minor; @@ -91,6 +101,14 @@ # endif #endif +#ifndef CONST86 +# if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION <= 5 /* Tcl8.0.x -- 8.5.x */ +# define CONST86 +# else +# define CONST86 CONST84 +# endif +#endif + /* copied from eval.c */ #define TAG_RETURN 0x1 #define TAG_BREAK 0x2 @@ -191,10 +209,10 @@ /* Tcl's object type */ #if TCL_MAJOR_VERSION >= 8 static const char Tcl_ObjTypeName_ByteArray[] = "bytearray"; -static Tcl_ObjType *Tcl_ObjType_ByteArray; +static CONST86 Tcl_ObjType *Tcl_ObjType_ByteArray; static const char Tcl_ObjTypeName_String[] = "string"; -static Tcl_ObjType *Tcl_ObjType_String; +static CONST86 Tcl_ObjType *Tcl_ObjType_String; #if TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION >= 1) #define IS_TCL_BYTEARRAY(obj) ((obj)->typePtr == Tcl_ObjType_ByteArray) @@ -407,6 +425,7 @@ static VALUE eventloop_thread; +static Tcl_Interp *eventloop_interp; #ifdef RUBY_USE_NATIVE_THREAD Tcl_ThreadId tk_eventloop_thread_id; /* native thread ID of Tcl interpreter */ #endif @@ -460,6 +479,8 @@ #define NO_THREAD_INTERRUPT_TIME 100/*milliseconds ( 1 -- 999 ) */ #endif +#define EVENT_HANDLER_TIMEOUT 100/*milliseconds*/ + static int event_loop_max = DEFAULT_EVENT_LOOP_MAX; static int no_event_tick = DEFAULT_NO_EVENT_TICK; static int no_event_wait = DEFAULT_NO_EVENT_WAIT; @@ -1630,6 +1651,7 @@ { DUMP1("trap check"); +#ifdef RUBY_VM if (rb_thread_check_trap_pending()) { if (check_var != (int*)NULL) { /* wait command */ @@ -1639,11 +1661,35 @@ rb_thread_check_ints(); } } +#else + if (rb_trap_pending) { + run_timer_flag = 0; + if (rb_prohibit_interrupt || check_var != (int*)NULL) { + /* pending or on wait command */ + return 0; + } else { + rb_trap_exec(); + } + } +#endif return 1; } static int +check_eventloop_interp() +{ + DUMP1("check eventloop_interp"); + if (eventloop_interp != (Tcl_Interp*)NULL + && Tcl_InterpDeleted(eventloop_interp)) { + DUMP2("eventloop_interp(%p) was deleted", eventloop_interp); + return 1; + } + + return 0; +} + +static int lib_eventloop_core(check_root, update_flag, check_var, interp) int check_root; int update_flag; @@ -1684,6 +1730,8 @@ #endif for(;;) { + if (check_eventloop_interp()) return 0; + #if USE_EVLOOP_THREAD_ALONE_CHECK_FLAG if (thread_alone_check_flag && rb_thread_alone()) { #else @@ -1776,6 +1824,7 @@ } TRAP_CHECK(); + if (check_eventloop_interp()) return 0; DUMP1("check Root Widget"); if (check_root && tk_stubs_init_p() && Tk_GetNumMainWindows() == 0) { @@ -1962,6 +2011,7 @@ } TRAP_CHECK(); + if (check_eventloop_interp()) return 0; DUMP1("check Root Widget"); if (check_root && tk_stubs_init_p() && Tk_GetNumMainWindows() == 0) { @@ -2205,6 +2255,7 @@ VALUE *argv; VALUE self; { + volatile VALUE ret; struct tcltkip *ptr = get_ip(self); /* ip is deleted? */ @@ -2216,7 +2267,11 @@ /* slave IP */ return Qnil; } - return lib_mainloop(argc, argv, self); + + eventloop_interp = ptr->ip; + ret = lib_mainloop(argc, argv, self); + eventloop_interp = (Tcl_Interp*)NULL; + return ret; } @@ -2306,7 +2361,7 @@ { VALUE check_rootwidget; -#ifdef RUBY_USE_NATIVE_THREAD +#ifdef RUBY_VM rb_raise(rb_eNotImpError, "eventloop_watchdog is not implemented on Ruby VM."); #endif @@ -2812,7 +2867,17 @@ #endif #endif +#ifdef RUBY_VM code = tcl_protect_core(interp, proc, data); +#else + do { + int old_trapflag = rb_trap_immediate; + rb_trap_immediate = 0; + code = tcl_protect_core(interp, proc, data); + rb_trap_immediate = old_trapflag; + } while (0); +#endif + return code; } @@ -2906,6 +2971,7 @@ thr_crit_bup = rb_thread_critical; rb_thread_critical = Qfalse; ret = rb_apply(arg->receiver, arg->method, arg->args); + DUMP2("rb_apply return:%lx", ret); rb_thread_critical = thr_crit_bup; DUMP1("finish ip_ruby_cmd_core"); @@ -3374,7 +3440,11 @@ } /* trap check */ +#ifdef RUBY_VM if (rb_thread_check_trap_pending()) { +#else + if (rb_trap_pending) { +#endif Tcl_Release(interp); return TCL_RETURN; @@ -3442,6 +3512,7 @@ static CONST char *updateOptions[] = {"idletasks", (char *) NULL}; enum updateOptions {REGEXP_IDLETASKS}; volatile VALUE current_thread = rb_thread_current(); + struct timeval t; DUMP1("Ruby's 'thread_update' is called"); if (interp == (Tcl_Interp*)NULL) { @@ -3529,10 +3600,17 @@ DUMP1("set idle proc"); Tcl_DoWhenIdle(rb_threadUpdateProc, (ClientData) param); + t.tv_sec = (time_t)0; + t.tv_usec = (long)((EVENT_HANDLER_TIMEOUT)*1000.0); + while(!param->done) { - DUMP1("wait for complete idle proc"); - /* rb_thread_stop(); */ - rb_thread_sleep_forever(); + DUMP1("wait for complete idle proc"); + /* rb_thread_stop(); */ + /* rb_thread_sleep_forever(); */ + rb_thread_wait_for(t); + if (NIL_P(eventloop_thread)) { + break; + } } #if 0 /* use Tcl_EventuallyFree */ @@ -3740,7 +3818,11 @@ } /* trap check */ +#ifdef RUBY_VM if (rb_thread_check_trap_pending()) { +#else + if (rb_trap_pending) { +#endif #if TCL_MAJOR_VERSION >= 8 Tcl_DecrRefCount(objv[1]); #endif @@ -4029,7 +4111,11 @@ } /* trap check */ - if (rb_thread_check_trap_pending()) { +#ifdef RUBY_VM + if (rb_thread_check_trap_pending()) { +#else + if (rb_trap_pending) { +#endif Tcl_Release(interp); return TCL_RETURN; @@ -4089,7 +4175,11 @@ } /* trap check */ - if (rb_thread_check_trap_pending()) { +#ifdef RUBY_VM + if (rb_thread_check_trap_pending()) { +#else + if (rb_trap_pending) { +#endif #if TCL_MAJOR_VERSION >= 8 Tcl_DecrRefCount(objv[2]); #endif @@ -4184,7 +4274,11 @@ } /* trap check */ - if (rb_thread_check_trap_pending()) { +#ifdef RUBY_VM + if (rb_thread_check_trap_pending()) { +#else + if (rb_trap_pending) { +#endif Tcl_Release(interp); return TCL_RETURN; @@ -4304,6 +4398,7 @@ int ret, dummy; int thr_crit_bup; volatile VALUE current_thread = rb_thread_current(); + struct timeval t; DUMP1("Ruby's 'thread_vwait' is called"); if (interp == (Tcl_Interp*)NULL) { @@ -4398,9 +4493,16 @@ return TCL_ERROR; } + t.tv_sec = (time_t)0; + t.tv_usec = (long)((EVENT_HANDLER_TIMEOUT)*1000.0); + while(!param->done) { - /* rb_thread_stop(); */ - rb_thread_sleep_forever(); + /* rb_thread_stop(); */ + /* rb_thread_sleep_forever(); */ + rb_thread_wait_for(t); + if (NIL_P(eventloop_thread)) { + break; + } } thr_crit_bup = rb_thread_critical; @@ -4459,6 +4561,7 @@ int ret, dummy; int thr_crit_bup; volatile VALUE current_thread = rb_thread_current(); + struct timeval t; DUMP1("Ruby's 'thread_tkwait' is called"); if (interp == (Tcl_Interp*)NULL) { @@ -4612,9 +4715,16 @@ return TCL_ERROR; } + t.tv_sec = (time_t)0; + t.tv_usec = (long)((EVENT_HANDLER_TIMEOUT)*1000.0); + while(!param->done) { - /* rb_thread_stop(); */ - rb_thread_sleep_forever(); + /* rb_thread_stop(); */ + /* rb_thread_sleep_forever(); */ + rb_thread_wait_for(t); + if (NIL_P(eventloop_thread)) { + break; + } } thr_crit_bup = rb_thread_critical; @@ -4691,10 +4801,17 @@ rb_thread_critical = thr_crit_bup; + t.tv_sec = (time_t)0; + t.tv_usec = (long)((EVENT_HANDLER_TIMEOUT)*1000.0); + while(param->done != TKWAIT_MODE_VISIBILITY) { - if (param->done == TKWAIT_MODE_DESTROY) break; - /* rb_thread_stop(); */ - rb_thread_sleep_forever(); + if (param->done == TKWAIT_MODE_DESTROY) break; + /* rb_thread_stop(); */ + /* rb_thread_sleep_forever(); */ + rb_thread_wait_for(t); + if (NIL_P(eventloop_thread)) { + break; + } } thr_crit_bup = rb_thread_critical; @@ -4806,9 +4923,16 @@ rb_thread_critical = thr_crit_bup; + t.tv_sec = (time_t)0; + t.tv_usec = (long)((EVENT_HANDLER_TIMEOUT)*1000.0); + while(param->done != TKWAIT_MODE_DESTROY) { - /* rb_thread_stop(); */ - rb_thread_sleep_forever(); + /* rb_thread_stop(); */ + /* rb_thread_sleep_forever(); */ + rb_thread_wait_for(t); + if (NIL_P(eventloop_thread)) { + break; + } } Tcl_Release(window); @@ -5073,7 +5197,9 @@ } /* delete root widget */ -#if 0 /* cause SEGV on Ruby 1.9 */ +#ifdef RUBY_VM + /* cause SEGV on Ruby 1.9 */ +#else DUMP1("check `destroy'"); if (Tcl_GetCommandInfo(ip, "destroy", &info)) { DUMP1("call `destroy .'"); @@ -5490,6 +5616,7 @@ ; } + st = ruby_tcl_stubs_init(); /* from Tcl_AppInit() */ if (with_tk) { DUMP1("Tk_Init"); @@ -6297,6 +6424,7 @@ volatile VALUE ip_obj = obj; volatile VALUE result; volatile VALUE ret; + struct timeval t; if (!NIL_P(ip_obj) && rb_obj_is_kind_of(ip_obj, tcltkip_class)) { ptr = get_ip(ip_obj); @@ -6406,12 +6534,21 @@ rb_thread_critical = thr_crit_bup; /* wait for the handler to be processed */ + t.tv_sec = (time_t)0; + t.tv_usec = (long)((EVENT_HANDLER_TIMEOUT)*1000.0); + DUMP2("wait for handler (current thread:%lx)", current); while(*alloc_done >= 0) { DUMP2("*** wait for handler (current thread:%lx)", current); /* rb_thread_stop(); */ - rb_thread_sleep_forever(); + /* rb_thread_sleep_forever(); */ + rb_thread_wait_for(t); DUMP2("*** wakeup (current thread:%lx)", current); + if (NIL_P(eventloop_thread)) { + DUMP1("*** lost eventloop thread"); + break; + } + DUMP2("*** wakeup (current thread:%lx)", current); } DUMP2("back from handler (current thread:%lx)", current); @@ -6784,6 +6921,7 @@ volatile VALUE result; volatile VALUE ret; Tcl_QueuePosition position; + struct timeval t; thr_crit_bup = rb_thread_critical; rb_thread_critical = Qtrue; @@ -6792,7 +6930,12 @@ #ifdef RUBY_USE_NATIVE_THREAD ptr = get_ip(ip_obj); + DUMP2("eval status: ptr->tk_thread_id %p", ptr->tk_thread_id); + DUMP2("eval status: Tcl_GetCurrentThread %p", Tcl_GetCurrentThread()); +#else + DUMP2("status: Tcl_GetCurrentThread %p", Tcl_GetCurrentThread()); #endif + DUMP2("status: eventloopt_thread %lx", eventloop_thread); if ( #ifdef RUBY_USE_NATIVE_THREAD @@ -6880,12 +7023,20 @@ rb_thread_critical = thr_crit_bup; /* wait for the handler to be processed */ + t.tv_sec = (time_t)0; + t.tv_usec = (long)((EVENT_HANDLER_TIMEOUT)*1000.0); + DUMP2("wait for handler (current thread:%lx)", current); while(*alloc_done >= 0) { DUMP2("*** wait for handler (current thread:%lx)", current); /* rb_thread_stop(); */ - rb_thread_sleep_forever(); + /* rb_thread_sleep_forever(); */ + rb_thread_wait_for(t); DUMP2("*** wakeup (current thread:%lx)", current); + if (NIL_P(eventloop_thread)) { + DUMP1("*** lost eventloop thread"); + break; + } } DUMP2("back from handler (current thread:%lx)", current); @@ -6931,6 +7082,71 @@ } +static int +ip_cancel_eval_core(interp, msg, flag) + Tcl_Interp *interp; + VALUE msg; + int flag; +{ +#if TCL_MAJOR_VERSION < 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION < 6) + rb_raise(rb_eNotImpError, + "cancel_eval is supported Tcl/Tk8.6 or later."); +#else + Tcl_Obj *msg_obj; + + if (NIL_P(msg)) { + msg_obj = NULL; + } else { + msg_obj = Tcl_NewStringObj(RSTRING_PTR(msg), RSTRING_LEN(msg)); + Tcl_IncrRefCount(msg_obj); + } + + return Tcl_CancelEval(interp, msg_obj, 0, flag); +#endif +} + +static VALUE +ip_cancel_eval(argc, argv, self) + int argc; + VALUE *argv; + VALUE self; +{ + VALUE retval; + + if (rb_scan_args(argc, argv, "01", &retval) == 0) { + retval = Qnil; + } + if (ip_cancel_eval_core(get_ip(self)->ip, retval, 0) == TCL_OK) { + return Qtrue; + } else { + return Qfalse; + } +} + +#ifndef TCL_CANCEL_UNWIND +#define TCL_CANCEL_UNWIND 0x100000 +#endif +static VALUE +ip_cancel_eval_unwind(argc, argv, self) + int argc; + VALUE *argv; + VALUE self; +{ + int flag = 0; + VALUE retval; + + if (rb_scan_args(argc, argv, "01", &retval) == 0) { + retval = Qnil; + } + + flag |= TCL_CANCEL_UNWIND; + if (ip_cancel_eval_core(get_ip(self)->ip, retval, flag) == TCL_OK) { + return Qtrue; + } else { + return Qfalse; + } +} + /* restart Tk */ static VALUE lib_restart_core(interp, argc, argv) @@ -8185,6 +8401,7 @@ volatile VALUE ip_obj = obj; volatile VALUE result; volatile VALUE ret; + struct timeval t; #if TCL_MAJOR_VERSION >= 8 Tcl_Obj **av = (Tcl_Obj **)NULL; @@ -8198,10 +8415,10 @@ #ifdef RUBY_USE_NATIVE_THREAD ptr = get_ip(ip_obj); - DUMP2("status: ptr->tk_thread_id %p", ptr->tk_thread_id); + DUMP2("invoke status: ptr->tk_thread_id %p", ptr->tk_thread_id); + DUMP2("invoke status: Tcl_GetCurrentThread %p", Tcl_GetCurrentThread()); +#else DUMP2("status: Tcl_GetCurrentThread %p", Tcl_GetCurrentThread()); -#else - DUMP2("status: Tcl_GetCurrentThread %lx", Tcl_GetCurrentThread()); #endif DUMP2("status: eventloopt_thread %lx", eventloop_thread); @@ -8285,10 +8502,19 @@ rb_thread_critical = thr_crit_bup; /* wait for the handler to be processed */ + t.tv_sec = (time_t)0; + t.tv_usec = (long)((EVENT_HANDLER_TIMEOUT)*1000.0); + DUMP2("wait for handler (current thread:%lx)", current); while(*alloc_done >= 0) { - /* rb_thread_stop(); */ - rb_thread_sleep_forever(); + /* rb_thread_stop(); */ + /* rb_thread_sleep_forever(); */ + rb_thread_wait_for(t); + DUMP2("*** wakeup (current thread:%lx)", current); + if (NIL_P(eventloop_thread)) { + DUMP1("*** lost eventloop thread"); + break; + } } DUMP2("back from handler (current thread:%lx)", current); @@ -9400,11 +9626,10 @@ { struct tcltkip *ptr; int retry = 0; - int i, idx, objc; + int i, objc; Tcl_Obj **objv; Tcl_Obj *enc_list; volatile VALUE encname = Qnil; - volatile VALUE encobj = Qnil; /* interpreter check */ if (NIL_P(interp)) return 0; @@ -9446,7 +9671,6 @@ VALUE error_mode; { volatile VALUE name = Qnil; - int retry = 0; enc = rb_funcall(enc, ID_to_s, 0, 0); name = rb_hash_lookup(table, enc); @@ -10041,6 +10265,8 @@ rb_define_method(ip, "has_mainwindow?", ip_has_mainwindow_p, 0); rb_define_method(ip, "invalid_namespace?", ip_has_invalid_namespace_p, 0); rb_define_method(ip, "_eval", ip_eval, 1); + rb_define_method(ip, "_cancel_eval", ip_cancel_eval, -1); + rb_define_method(ip, "_cancel_eval_unwind", ip_cancel_eval_unwind, -1); rb_define_method(ip, "_toUTF8", ip_toUTF8, -1); rb_define_method(ip, "_fromUTF8", ip_fromUTF8, -1); rb_define_method(ip, "_thread_vwait", ip_thread_vwait, 1); @@ -10103,6 +10329,7 @@ /* --------------------------------------------------------------- */ eventloop_thread = Qnil; + eventloop_interp = (Tcl_Interp*)NULL; #ifndef DEFAULT_EVENTLOOP_DEPTH #define DEFAULT_EVENTLOOP_DEPTH 7 @@ -10152,4 +10379,3 @@ } /* eof */ - Index: ext/tk/MANUAL_tcltklib.eucj =================================================================== --- ext/tk/MANUAL_tcltklib.eucj (revision 23917) +++ ext/tk/MANUAL_tcltklib.eucj (working copy) @@ -235,8 +235,8 @@ モジュールメソッド get_version() - : Tcl/Tk の major, minor, release-type 番号, release-type 名, - : patchlevel を配列にして返す. + : Tcl/Tk の major, minor, release-type 番号, patchlevel を + : 配列にして返す. mainloop(check_root = true) : イベントループを起動する.check_root が true であれば, @@ -464,6 +464,11 @@ : して登録に成功しさえすれば,以降は _invoke でも利用で : きるようになる. + _cancel_eval(str) + _cancel_eval_unwind(str) + : (Tcl/Tk8.6 or later) + : Tcl_CancelEval() 関数を呼び出し,eval の実行を打ち切る. + _toUTF8(str, encoding=nil) _fromUTF8(str, encoding=nil) : Tcl/Tk が内蔵している UTF8 変換処理を呼び出す. Index: ext/tk/README.tcltklib =================================================================== --- ext/tk/README.tcltklib (revision 23917) +++ ext/tk/README.tcltklib (working copy) @@ -1,18 +1,53 @@ To compile 'tcltklib', you must have Tcl/Tk libraries on your environment. -Although 'extconf.rb' script searches Tcl/Tk libraries and header files, +Although 'extconf.rb' script searches Tcl/Tk libraries and header files +(as default, searches tclConfig.sh/tkConfig.sh and use the defintions on +those; ActiveTcl has high priority on searching unless --without-ActiveTcl), sometimes fails to find them. And then, 'tcltklib' cannot be compiled. If Tcl/Tk libraries or header files are installed but are not found, you can give the information by arguments of the 'configure' script. Please give some or all of the following options. + --with-tk-old-extconf use old "extconf.rb" (default: false). + If current extconf.rb doesn't work properly + (or your install process is based on old + documant about Ruby/Tk install), please try + this option. + + --with-ActiveTcl / --without-ActiveTcl + --with-ActiveTcl= search ActiveTcl libraries (default: true). + When true, try to find installed ActiveTcl. + When is given, use it as the ActiveTcl's + top directory (use /lib, and so on). + Old "extconf.rb" doesn't support this option. + + --with-tk-shlib-search-path= + teach the paths for loading shared-libraries + to linker. + is a path list with the same format + as PATH environment variable. + This option may be experimental. + Old "extconf.rb" doesn't support this option. + --with-tcltkversion= force version of Tcl/Tk libaray (e.g. libtcl8.4g.so ==> --with-tcltkversion=8.4g) + --without-tcl-config / --without-tk-config + --with-tclConfig-dir= + --with-tkConfig-dir= the directory contains 'tclConfig.sh' and + 'tkConfig.sh'. + Current "extconf.rb" uses the information + on tclConfig.sh/tkConfig.rb, if possible. + Old "extconf.rb" doesn't support this option. + --with-tcllib= (e.g. libtcl8.4.so ==> --with-tcllib=tcl8.4) --with-tklib= (e.g. libtk8.4.so ==> --with-tklib=tk8.4) --enable-tcltk-stubs (if you force to enable stubs) + On old "extconf.rb", default is false. + On current "extconf.rb", default is true when + tclConfig.sh/tkConfig.sh have TCL_STUB_LIB_SPEC + /TK_STUB_LIB_SPEC, else default is false. --with-tcl-dir= equal to "--with-tcl-include=/include --with-tcl-lib=/lib" @@ -36,6 +71,12 @@ When this option is given, it is assumed that --enable-tcltk-framework option is given also. + --with-tcl-framework-dir= + Tcl framework directory (e.g. "/Library/Frameworks/Tcl.framework") + + --with-tk-framework-dir= + Tk framework directory (e.g. "/Library/Frameworks/Tk.framework") + --with-tcl-framework-header= Tcl framework headers directory (e.g. "/Library/Frameworks/Tcl.framework/Headers") Index: ext/tk/config_list.in =================================================================== --- ext/tk/config_list.in (revision 0) +++ ext/tk/config_list.in (revision 0) @@ -0,0 +1,31 @@ +with tk-old-extconf +with ActiveTcl +with tk-shlib-search-path +with tcltkversion +with tcl-config +with tk-config +with tclConfig-dir +with tkConfig-dir +with tcllib +with tklib +enable tcltk-stubs +with tcl-dir +with tk-dir +with tcl-include +with tcl-lib +with tcl-lib +with tk-lib +enable mac-tcltk-framework +enable tcltk-framework +with tcltk-framework +with tcl-framework-dir +with tk-framework-dir +with tcl-framework-header +with tk-framework-header +with X11 +with X11-dir +with X11-include +with X11-lib +enable pthread +enable tcl-thread +with tclConfig-file Index: ext/tk/lib/tk.rb =================================================================== --- ext/tk/lib/tk.rb (revision 23917) +++ ext/tk/lib/tk.rb (working copy) @@ -15,7 +15,9 @@ class TclTkIp # backup original (without encoding) _eval and _invoke alias _eval_without_enc _eval + alias __eval__ _eval alias _invoke_without_enc _invoke + alias __invoke__ _invoke def _ip_id_ # for RemoteTkIp @@ -613,9 +615,9 @@ val end end - private :bool, :number, :string, :num_or_str + private :bool, :number, :num_or_str, :num_or_nil, :string private :list, :simplelist, :window, :procedure - module_function :bool, :number, :num_or_str, :string + module_function :bool, :number, :num_or_str, :num_or_nil, :string module_function :list, :simplelist, :window, :image_obj, :procedure def subst(str, *opts) @@ -1130,30 +1132,42 @@ opts = '' end - if WITH_RUBY_VM ### check Ruby 1.9 !!!!!!! - # *** NEED TO FIX *** - ip = TclTkIp.new(name, opts) - if ip._invoke_without_enc('tk', 'windowingsystem') == 'aqua' && - (TclTkLib.get_version <=> [8,4,TclTkLib::RELEASE_TYPE::FINAL,9]) > 0 - # *** KNOWN BUG *** - # Main event loop thread of TkAqua (> Tk8.4.9) must be the main - # application thread. So, ruby1.9 users must call Tk.mainloop on - # the main application thread. - RUN_EVENTLOOP_ON_MAIN_THREAD = true - INTERP = ip - else - unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD - RUN_EVENTLOOP_ON_MAIN_THREAD = false - end - if RUN_EVENTLOOP_ON_MAIN_THREAD + unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD + if WITH_RUBY_VM ### check Ruby 1.9 !!!!!!! + # *** NEED TO FIX *** + ip = TclTkIp.new(name, opts) + if ip._invoke_without_enc('tk', 'windowingsystem') == 'aqua' && + (TclTkLib.get_version<=>[8,4,TclTkLib::RELEASE_TYPE::FINAL,6]) > 0 + # *** KNOWN BUG *** + # Main event loop thread of TkAqua (> Tk8.4.9) must be the main + # application thread. So, ruby1.9 users must call Tk.mainloop on + # the main application thread. + # + # *** ADD (2009/05/10) *** + # In some cases (I don't know the description of conditions), + # TkAqua 8.4.7 has a same kind of hang-up trouble. + # So, if 8.4.7 or later, set RUN_EVENTLOOP_ON_MAIN_THREAD to true. + # When you want to control this mode, please call the following + # (set true/false as you want) before "require 'tk'". + # ---------------------------------------------------------- + # module TkCore; RUN_EVENTLOOP_ON_MAIN_THREAD = true; end + # ---------------------------------------------------------- + # + RUN_EVENTLOOP_ON_MAIN_THREAD = true INTERP = ip else - ip.delete + unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD + RUN_EVENTLOOP_ON_MAIN_THREAD = false + end + if RUN_EVENTLOOP_ON_MAIN_THREAD + INTERP = ip + else + ip.delete + end end - end - ip = nil - else - unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD + ip = nil + + else # Ruby 1.8.x RUN_EVENTLOOP_ON_MAIN_THREAD = false end end @@ -1183,13 +1197,21 @@ #sleep begin - Thread.current[:status].value = TclTkLib.mainloop(true) + #TclTkLib.mainloop_abort_on_exception = false + #Thread.current[:status].value = TclTkLib.mainloop(true) + interp.mainloop_abort_on_exception = false + Thread.current[:status].value = interp.mainloop(true) + rescue SystemExit=>e + Thread.current[:status].value = e rescue Exception=>e Thread.current[:status].value = e + retry if interp.has_mainwindow? ensure INTERP_MUTEX.synchronize{ INTERP_ROOT_CHECK.broadcast } end - Thread.current[:status].value = TclTkLib.mainloop(false) + + #Thread.current[:status].value = TclTkLib.mainloop(false) + Thread.current[:status].value = interp.mainloop(false) } until INTERP_THREAD[:interp] @@ -1321,7 +1343,8 @@ @add_tk_procs.delete_if{|elem| elem.kind_of?(Array) && elem[0].to_s == name } - self._invoke('rename', name, '') + #self._invoke('rename', name, '') + self.__invoke__('rename', name, '') } end def INTERP.init_ip_internal @@ -1704,11 +1727,14 @@ elsif TkCore::RUN_EVENTLOOP_ON_MAIN_THREAD # if TclTkLib::WINDOWING_SYSTEM == 'aqua' && - if TkCore::INTERP._invoke_without_enc('tk','windowingsystem')=='aqua' && - Thread.current != Thread.main && - (TclTkLib.get_version <=> [8,4,TclTkLib::RELEASE_TYPE::FINAL,9]) > 0 - raise RuntimeError, - "eventloop on TkAqua ( > Tk8.4.9 ) works on the main thread only" + #if TkCore::INTERP._invoke_without_enc('tk','windowingsystem')=='aqua' && + # Thread.current != Thread.main && + # (TclTkLib.get_version <=> [8,4,TclTkLib::RELEASE_TYPE::FINAL,9]) > 0 + # raise RuntimeError, + # "eventloop on TkAqua ( > Tk8.4.9 ) works on the main thread only" + #end + if Thread.current != Thread.main + raise RuntimeError, "Tk.mainloop is allowed on the main thread only" end TclTkLib.mainloop(check_root) @@ -3028,7 +3054,7 @@ =begin if ext_enc_obj == Tk::Encoding::UNKNOWN - if defind? DEFAULT_TK_ENCODING + if defined? DEFAULT_TK_ENCODING if DEFAULT_TK_ENCODING.kind_of?(::Encoding) tk_enc_name = DEFAULT_TK_ENCODING.name tksys_enc_name = DEFAULT_TK_ENCODING.name @@ -3126,7 +3152,7 @@ #if ext_enc_name && ext_enc_name != tksys_enc_name int_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(int_enc_obj) if int_enc_name - # use default_external + # use default_internal enc_name = int_enc_name else # use Tk.encoding_system @@ -3279,10 +3305,10 @@ TkFont.init_widget_font(pathname, *__confinfo_cmd) else fonts = {} - optkeys.each{|key| - key = key.to_s - pathname = [win, tag, key].join(';') - fonts[key] = + optkeys.each{|k| + k = k.to_s + pathname = [win, tag, k].join(';') + fonts[k] = TkFont.used_on(pathname) || TkFont.init_widget_font(pathname, *__confinfo_cmd) } @@ -3407,7 +3433,7 @@ if fobj.kind_of?(TkFont) if ltn.kind_of?(TkFont) conf = {} - ltn.latin_configinfo.each{|key,val| conf[key] = val} + ltn.latin_configinfo.each{|k,val| conf[k] = val} if keys fobj.latin_configure(conf.update(keys)) else @@ -3467,7 +3493,7 @@ if fobj.kind_of?(TkFont) if knj.kind_of?(TkFont) conf = {} - knj.kanji_configinfo.each{|key,val| conf[key] = val} + knj.kanji_configinfo.each{|k,val| conf[k] = val} if keys fobj.kanji_configure(conf.update(keys)) else @@ -3701,11 +3727,17 @@ val end + def cget_tkstring(option) + opt = option.to_s + fail ArgumentError, "Invalid option `#{option.inspect}'" if opt.length == 0 + tk_call_without_enc(*(__cget_cmd << "-#{opt}")) + end + def __cget_core(slot) orig_slot = slot slot = slot.to_s - if slot.length == 0 + if slot.length == 0 fail ArgumentError, "Invalid option `#{orig_slot.inspect}'" end @@ -4106,7 +4138,8 @@ else # conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) - conf = tk_split_list(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), 0, false, true) + # conf = tk_split_list(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), 0, false, true) + conf = tk_split_list(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), 1, false, true) end conf[__configinfo_struct[:key]] = conf[__configinfo_struct[:key]][1..-1] @@ -4296,8 +4329,8 @@ end } - __methodcall_optkeys.each{|optkey, method| - ret << [optkey.to_s, '', '', '', self.__send__(method)] + __methodcall_optkeys.each{|optkey, m| + ret << [optkey.to_s, '', '', '', self.__send__(m)] } ret @@ -4335,7 +4368,7 @@ if slot slot = slot.to_s - alias_name, real_name = __optkey_aliases.find{|k, v| k.to_s == slot} + alias_name, real_name = __optkey_aliases.find{|k,var| k.to_s == slot} if real_name slot = real_name.to_s end @@ -4682,8 +4715,8 @@ end } - __methodcall_optkeys.each{|optkey, method| - ret[optkey.to_s] = ['', '', '', self.__send__(method)] + __methodcall_optkeys.each{|optkey, m| + ret[optkey.to_s] = ['', '', '', self.__send__(m)] } ret @@ -4721,18 +4754,18 @@ "there is a configure alias loop about '#{org_slot}'" else ret = {} - configinfo().each{|conf| + configinfo().each{|cnf| if ( ! __configinfo_struct[:alias] \ - || conf.size > __configinfo_struct[:alias] + 1 ) - ret[conf[0]] = conf[-1] + || cnf.size > __configinfo_struct[:alias] + 1 ) + ret[cnf[0]] = cnf[-1] end } ret end else # ! TkComm::GET_CONFIGINFO_AS_ARRAY ret = {} - configinfo(slot).each{|key, conf| - ret[key] = conf[-1] if conf.kind_of?(Array) + configinfo(slot).each{|key, cnf| + ret[key] = cnf[-1] if cnf.kind_of?(Array) } ret end @@ -4864,6 +4897,7 @@ include TkWinfo extend TkBindCore include Tk::Wm_for_General + include Tk::Busy @@WIDGET_INSPECT_FULL = false def TkWindow._widget_inspect_full_? @@ -5551,7 +5585,7 @@ #Tk.freeze module Tk - RELEASE_DATE = '2009-01-13'.freeze + RELEASE_DATE = '2009-07-01'.freeze autoload :AUTO_PATH, 'tk/variable' autoload :TCL_PACKAGE_PATH, 'tk/variable' Index: ext/tk/lib/tkextlib/iwidgets/tabset.rb =================================================================== --- ext/tk/lib/tkextlib/iwidgets/tabset.rb (revision 23917) +++ ext/tk/lib/tkextlib/iwidgets/tabset.rb (working copy) @@ -41,13 +41,14 @@ end end + alias tabcget_tkstring itemcget_tkstring alias tabcget itemcget alias tabcget_strict itemcget_strict alias tabconfigure itemconfigure alias tabconfiginfo itemconfiginfo alias current_tabconfiginfo current_itemconfiginfo - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo #################################### Index: ext/tk/lib/tkextlib/iwidgets/buttonbox.rb =================================================================== --- ext/tk/lib/tkextlib/iwidgets/buttonbox.rb (revision 23917) +++ ext/tk/lib/tkextlib/iwidgets/buttonbox.rb (working copy) @@ -46,13 +46,14 @@ end end + alias buttoncget_tkstring itemcget_tkstring alias buttoncget itemcget alias buttoncget_strict itemcget_strict alias buttonconfigure itemconfigure alias buttonconfiginfo itemconfiginfo alias current_buttonconfiginfo current_itemconfiginfo - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo #################################### Index: ext/tk/lib/tkextlib/iwidgets/dialogshell.rb =================================================================== --- ext/tk/lib/tkextlib/iwidgets/dialogshell.rb (revision 23917) +++ ext/tk/lib/tkextlib/iwidgets/dialogshell.rb (working copy) @@ -46,13 +46,14 @@ end end + alias buttoncget_tkstring itemcget_tkstring alias buttoncget itemcget alias buttoncget_strict itemcget_strict alias buttonconfigure itemconfigure alias buttonconfiginfo itemconfiginfo alias current_buttonconfiginfo current_itemconfiginfo - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo #################################### Index: ext/tk/lib/tkextlib/iwidgets/menubar.rb =================================================================== --- ext/tk/lib/tkextlib/iwidgets/menubar.rb (revision 23917) +++ ext/tk/lib/tkextlib/iwidgets/menubar.rb (working copy) @@ -61,13 +61,14 @@ end end + alias menucget_tkstring itemcget_tkstring alias menucget itemcget alias menucget_strict itemcget_strict alias menuconfigure itemconfigure alias menuconfiginfo itemconfiginfo alias current_menuconfiginfo current_itemconfiginfo - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo #################################### Index: ext/tk/lib/tkextlib/iwidgets/messagebox.rb =================================================================== --- ext/tk/lib/tkextlib/iwidgets/messagebox.rb (revision 23917) +++ ext/tk/lib/tkextlib/iwidgets/messagebox.rb (working copy) @@ -46,13 +46,14 @@ end private :__item_boolval_optkeys + alias typecget_tkstring itemcget_tkstring alias typecget itemcget alias typecget_strict itemcget_strict alias typeconfigure itemconfigure alias typeconfiginfo itemconfiginfo alias current_typeconfiginfo current_itemconfiginfo - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo #################################### Index: ext/tk/lib/tkextlib/iwidgets/radiobox.rb =================================================================== --- ext/tk/lib/tkextlib/iwidgets/radiobox.rb (revision 23917) +++ ext/tk/lib/tkextlib/iwidgets/radiobox.rb (working copy) @@ -46,13 +46,14 @@ end end + alias buttoncget_tkstring itemcget_tkstring alias buttoncget itemcget alias buttoncget_strict itemcget_strict alias buttonconfigure itemconfigure alias buttonconfiginfo itemconfiginfo alias current_buttonconfiginfo current_itemconfiginfo - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo #################################### Index: ext/tk/lib/tkextlib/iwidgets/tabnotebook.rb =================================================================== --- ext/tk/lib/tkextlib/iwidgets/tabnotebook.rb (revision 23917) +++ ext/tk/lib/tkextlib/iwidgets/tabnotebook.rb (working copy) @@ -46,13 +46,14 @@ end end + alias pagecget_tkstring itemcget_tkstring alias pagecget itemcget alias pagecget_strict itemcget_strict alias pageconfigure itemconfigure alias pageconfiginfo itemconfiginfo alias current_pageconfiginfo current_itemconfiginfo - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo #################################### Index: ext/tk/lib/tkextlib/iwidgets/panedwindow.rb =================================================================== --- ext/tk/lib/tkextlib/iwidgets/panedwindow.rb (revision 23917) +++ ext/tk/lib/tkextlib/iwidgets/panedwindow.rb (working copy) @@ -41,13 +41,14 @@ end end + alias panecget_tkstring itemcget_tkstring alias panecget itemcget alias panecget_strict itemcget_strict alias paneconfigure itemconfigure alias paneconfiginfo itemconfiginfo alias current_paneconfiginfo current_itemconfiginfo - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo #################################### Index: ext/tk/lib/tkextlib/iwidgets/notebook.rb =================================================================== --- ext/tk/lib/tkextlib/iwidgets/notebook.rb (revision 23917) +++ ext/tk/lib/tkextlib/iwidgets/notebook.rb (working copy) @@ -41,13 +41,14 @@ end end + alias pagecget_tkstring itemcget_tkstring alias pagecget itemcget alias pagecget_strict itemcget_strict alias pageconfigure itemconfigure alias pageconfiginfo itemconfiginfo alias current_pageconfiginfo current_itemconfiginfo - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo #################################### Index: ext/tk/lib/tkextlib/iwidgets/checkbox.rb =================================================================== --- ext/tk/lib/tkextlib/iwidgets/checkbox.rb (revision 23917) +++ ext/tk/lib/tkextlib/iwidgets/checkbox.rb (working copy) @@ -46,13 +46,14 @@ end end + alias buttoncget_tkstring itemcget_tkstring alias buttoncget itemcget alias buttoncget_strict itemcget_strict alias buttonconfigure itemconfigure alias buttonconfiginfo itemconfiginfo alias current_buttonconfiginfo current_itemconfiginfo - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo #################################### Index: ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb =================================================================== --- ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb (revision 23917) +++ ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb (working copy) @@ -116,6 +116,10 @@ get('-displaychars', *index) end + def image_cget_tkstring(index, slot) + _fromUTF8(tk_send_without_enc('image', 'cget', + _get_eval_enc_str(index), "-#{slot.to_s}")) + end def image_cget_strict(index, slot) case slot.to_s when 'text', 'label', 'show', 'data', 'file' Index: ext/tk/lib/tkextlib/blt/busy.rb =================================================================== --- ext/tk/lib/tkextlib/blt/busy.rb (revision 23917) +++ ext/tk/lib/tkextlib/blt/busy.rb (working copy) @@ -44,6 +44,7 @@ private :__item_config_cmd undef itemcget + undef itemcget_tkstring alias configure itemconfigure alias configinfo itemconfiginfo alias current_configinfo current_itemconfiginfo Index: ext/tk/lib/tkextlib/blt/tabset.rb =================================================================== --- ext/tk/lib/tkextlib/blt/tabset.rb (revision 23917) +++ ext/tk/lib/tkextlib/blt/tabset.rb (working copy) @@ -132,6 +132,9 @@ @t.tab_bindinfo(@id, context) end + def cget_tkstring(*args) + @t.tab_cget_tkstring(@id, *args) + end def cget(*args) @t.tab_cget(@id, *args) end @@ -249,6 +252,7 @@ end private :__item_pathname + alias tab_cget_tkstring itemcget_tkstring alias tab_cget itemcget alias tab_cget_strict itemcget_strict alias tab_configure itemconfigure Index: ext/tk/lib/tkextlib/blt/table.rb =================================================================== --- ext/tk/lib/tkextlib/blt/table.rb (revision 23917) +++ ext/tk/lib/tkextlib/blt/table.rb (working copy) @@ -26,6 +26,9 @@ self end + def blt_table_cget_tkstring(*args) + Tk::BLT::Table.cget_tkstring(self, *args) + end def blt_table_cget(*args) Tk::BLT::Table.cget(self, *args) end @@ -92,6 +95,9 @@ self end + def blt_table_itemcget_tkstring(*args) + Tk::BLT::Table.itemcget_tkstring(self, *args) + end def blt_table_itemcget(*args) Tk::BLT::Table.itemcget(self, *args) end @@ -141,13 +147,14 @@ end private :__item_pathname + alias __itemcget_tkstring itemcget_tkstring alias __itemcget itemcget alias __itemcget_strict itemcget_strict alias __itemconfigure itemconfigure alias __itemconfiginfo itemconfiginfo alias __current_itemconfiginfo current_itemconfiginfo - private :__itemcget, :__itemcget_strict + private :__itemcget_tkstring, :__itemcget, :__itemcget_strict private :__itemconfigure, :__itemconfiginfo, :__current_itemconfiginfo def __boolval_optkeys @@ -180,6 +187,9 @@ ############################################ + def cget_tkstring(container, option) + __itemcget_tkstring([container], option) + end def cget(container, option) __itemcget([container], option) end @@ -199,6 +209,9 @@ __current_itemconfiginfo([container], *args) end + def itemcget_tkstring(container, item, option) + __itemcget_tkstring([container, tagid(item)], option) + end def itemcget(container, item, option) __itemcget([container, tagid(item)], option) end Index: ext/tk/lib/tkextlib/blt/treeview.rb =================================================================== --- ext/tk/lib/tkextlib/blt/treeview.rb (revision 23917) +++ ext/tk/lib/tkextlib/blt/treeview.rb (working copy) @@ -95,6 +95,9 @@ end private :__item_pathname + def column_cget_tkstring(name, option) + itemcget_tkstring(['column', name], option) + end def column_cget(name, option) itemcget(['column', name], option) end @@ -111,6 +114,9 @@ current_itemconfiginfo(['column', name], slot) end + def button_cget_tkstring(option) + itemcget_tkstring('button', option) + end def button_cget(option) itemcget('button', option) end @@ -127,6 +133,9 @@ current_itemconfiginfo('button', slot) end + def entry_cget_tkstring(option) + itemcget_tkstring('entry', option) + end def entry_cget(option) ret = itemcget('entry', option) if option == 'bindtags' || option == :bindtags @@ -181,6 +190,9 @@ ret end + def sort_cget_tkstring(option) + itemcget_tkstring('sort', option) + end def sort_cget(option) itemcget('sort', option) end @@ -197,6 +209,9 @@ current_itemconfiginfo('sort', slot) end + def text_cget_tkstring(option) + itemcget_tkstring('text', option) + end def text_cget(option) itemcget('text', option) end @@ -213,7 +228,7 @@ current_itemconfiginfo('text', slot) end - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo end Index: ext/tk/lib/tkextlib/blt/htext.rb =================================================================== --- ext/tk/lib/tkextlib/blt/htext.rb (revision 23917) +++ ext/tk/lib/tkextlib/blt/htext.rb (working copy) @@ -21,6 +21,7 @@ WidgetClassName = 'Htext'.freeze WidgetClassNames[WidgetClassName] = self + alias window_cget_tkstring itemcget_tkstring alias window_cget itemcget alias window_cget_strict itemcget_strict alias window_configure itemconfigure Index: ext/tk/lib/tkextlib/blt/dragdrop.rb =================================================================== --- ext/tk/lib/tkextlib/blt/dragdrop.rb (revision 23917) +++ ext/tk/lib/tkextlib/blt/dragdrop.rb (working copy) @@ -55,6 +55,7 @@ private :__item_strval_optkeys undef itemcget + undef itemcget_tkstring private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo def source_configure(win, slot, value=None) Index: ext/tk/lib/tkextlib/blt/component.rb =================================================================== --- ext/tk/lib/tkextlib/blt/component.rb (revision 23917) +++ ext/tk/lib/tkextlib/blt/component.rb (working copy) @@ -82,6 +82,9 @@ end private :__item_pathname + def axis_cget_tkstring(id, option) + ret = itemcget_tkstring(['axis', tagid(id)], option) + end def axis_cget(id, option) ret = itemcget(['axis', tagid(id)], option) end @@ -118,6 +121,9 @@ current_itemconfiginfo(['axis', tagid(id)], slot) end + def crosshairs_cget_tkstring(option) + itemcget_tkstring('crosshairs', option) + end def crosshairs_cget(option) itemcget('crosshairs', option) end @@ -134,6 +140,9 @@ current_itemconfiginfo('crosshairs', slot) end + def element_cget_tkstring(id, option) + itemcget_tkstring(['element', tagid(id)], option) + end def element_cget(id, option) itemcget(['element', tagid(id)], option) end @@ -158,6 +167,9 @@ current_itemconfiginfo(['element', tagid(id)], slot) end + def bar_cget_tkstring(id, option) + itemcget_tkstring(['bar', tagid(id)], option) + end def bar_cget(id, option) itemcget(['bar', tagid(id)], option) end @@ -182,6 +194,9 @@ current_itemconfiginfo(['bar', tagid(id)], slot) end + def line_cget_tkstring(id, option) + itemcget_tkstring(['line', tagid(id)], option) + end def line_cget(id, option) itemcget(['line', tagid(id)], option) end @@ -206,6 +221,9 @@ current_itemconfiginfo(['line', tagid(id)], slot) end + def gridline_cget_tkstring(option) + itemcget_tkstring('grid', option) + end def gridline_cget(option) itemcget('grid', option) end @@ -222,6 +240,9 @@ current_itemconfiginfo('grid', slot) end + def legend_cget_tkstring(option) + itemcget_tkstring('legend', option) + end def legend_cget(option) itemcget('legend', option) end @@ -238,6 +259,9 @@ current_itemconfiginfo('legend', slot) end + def pen_cget_tkstring(id, option) + itemcget_tkstring(['pen', tagid(id)], option) + end def pen_cget(id, option) itemcget(['pen', tagid(id)], option) end @@ -262,6 +286,9 @@ current_itemconfiginfo(['pen', tagid(id)], slot) end + def postscript_cget_tkstring(option) + itemcget_tkstring('postscript', option) + end def postscript_cget(option) itemcget('postscript', option) end @@ -278,6 +305,9 @@ current_itemconfiginfo('postscript', slot) end + def marker_cget_tkstring(id, option) + itemcget_tkstring(['marker', tagid(id)], option) + end def marker_cget(id, option) itemcget(['marker', tagid(id)], option) end @@ -302,12 +332,16 @@ current_itemconfiginfo(['marker', tagid(id)], slot) end + alias __itemcget_tkstring itemcget_tkstring alias __itemcget itemcget alias __itemcget_strict itemcget_strict alias __itemconfiginfo itemconfiginfo alias __current_itemconfiginfo current_itemconfiginfo - private :__itemcget, :__itemconfiginfo, :__current_itemconfiginfo + private :__itemcget_tkstring, :__itemcget, :__itemconfiginfo, :__current_itemconfiginfo + def itemcget_tkstring(tagOrId, option) + __itemcget_tkstring(tagid(tagOrId), option) + end def itemcget_strict(tagOrId, option) ret = __itemcget(tagid(tagOrId), option) if option == 'bindtags' || option == :bindtags @@ -373,7 +407,7 @@ ret end - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo ################# @@ -477,6 +511,9 @@ @id end + def cget_tkstring(option) + @chart.axis_cget_tkstring(@id, option) + end def cget(option) @chart.axis_cget(@id, option) end @@ -582,6 +619,9 @@ @id end + def cget_tkstring(option) + @chart.crosshair_cget_tkstring(option) + end def cget(option) @chart.crosshair_cget(option) end @@ -729,6 +769,10 @@ @id end + def cget_tkstring(option) + # @chart.element_cget(@id, option) + @chart.__send__(@typename + '_cget_tkstring', @id, option) + end def cget(option) # @chart.element_cget(@id, option) @chart.__send__(@typename + '_cget', @id, option) @@ -833,6 +877,9 @@ @id end + def cget_tkstring(option) + @chart.gridline_cget_tkstring(option) + end def cget(option) @chart.gridline_cget(option) end @@ -907,6 +954,9 @@ @id end + def cget_tkstring(option) + @chart.legend_cget_tkstring(option) + end def cget(option) @chart.legend_cget(option) end @@ -1036,6 +1086,9 @@ @id end + def cget_tkstring(option) + @chart.pen_cget_tkstring(@id, option) + end def cget(option) @chart.pen_cget(@id, option) end @@ -1106,6 +1159,9 @@ @id end + def cget_tkstring(option) + @chart.postscript_cget_tkstring(option) + end def cget(option) @chart.postscript_cget(option) end @@ -1269,6 +1325,9 @@ @id end + def cget_tkstring(option) + @chart.marker_cget_tkstring(@id, option) + end def cget(option) @chart.marker_cget(@id, option) end @@ -1854,6 +1913,9 @@ ################### + def xaxis_cget_tkstring(option) + itemcget_tkstring('xaxis', option) + end def xaxis_cget(option) itemcget('xaxis', option) end @@ -1926,6 +1988,9 @@ end end + def x2axis_cget_tkstring(option) + itemcget_tkstring('x2axis', option) + end def x2axis_cget(option) itemcget('x2axis', option) end @@ -1998,6 +2063,9 @@ end end + def yaxis_cget_tkstring(option) + itemcget_tkstring('yaxis', option) + end def yaxis_cget(option) itemcget('yaxis', option) end @@ -2070,6 +2138,9 @@ end end + def y2axis_cget_tkstring(option) + itemcget_tkstring('y2axis', option) + end def y2axis_cget(option) itemcget('y2axis', option) end Index: ext/tk/lib/tkextlib/blt/unix_dnd.rb =================================================================== --- ext/tk/lib/tkextlib/blt/unix_dnd.rb (revision 23917) +++ ext/tk/lib/tkextlib/blt/unix_dnd.rb (working copy) @@ -30,9 +30,12 @@ end private :__item_config_cmd - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo + def cget_tkstring(win, option) + itemcget_tkstring(['cget', win], option) + end def cget(win, option) itemcget(['cget', win], option) end @@ -49,6 +52,9 @@ current_itemconfiginfo(['configure', win], slot) end + def token_cget_tkstring(win, option) + itemcget_tkstring(['token', 'cget', win], option) + end def token_cget(win, option) itemcget(['token', 'cget', win], option) end Index: ext/tk/lib/tkextlib/blt/ted.rb =================================================================== --- ext/tk/lib/tkextlib/blt/ted.rb (revision 23917) +++ ext/tk/lib/tkextlib/blt/ted.rb (working copy) @@ -30,9 +30,12 @@ end private :__item_config_cmd - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo + def cget_tkstring(master, option) + itemcget_tkstring(master, option) + end def cget(master, option) itemcget(master, option) end Index: ext/tk/lib/tkextlib/tcllib/tablelist_core.rb =================================================================== --- ext/tk/lib/tkextlib/tcllib/tablelist_core.rb (revision 23917) +++ ext/tk/lib/tkextlib/tcllib/tablelist_core.rb (working copy) @@ -67,6 +67,9 @@ [self.path, mixed_id[0] + 'configure', _to_idx(mixed_id[1])] end + def cell_cget_tkstring(tagOrId, option) + itemcget_tkstring(['cell', tagOrId], option) + end def cell_cget(tagOrId, option) itemcget(['cell', tagOrId], option) end @@ -82,12 +85,16 @@ def current_cell_configinfo(tagOrId, slot=nil) current_itemconfiginfo(['cell', tagOrId], slot) end + alias cellcget_tkstring cell_cget_tkstring alias cellcget cell_cget alias cellcget_strict cell_cget_strict alias cellconfigure cell_configure alias cellconfiginfo cell_configinfo alias current_cellconfiginfo current_cell_configinfo + def column_cget_tkstring(tagOrId, option) + itemcget_tkstring(['column', tagOrId], option) + end def column_cget(tagOrId, option) itemcget(['column', tagOrId], option) end @@ -103,12 +110,16 @@ def current_column_configinfo(tagOrId, slot=nil) current_itemconfiginfo(['column', tagOrId], slot) end + alias columncget_tkstring column_cget_tkstring alias columncget column_cget alias columncget_strict column_cget_strict alias columnconfigure column_configure alias columnconfiginfo column_configinfo alias current_columnconfiginfo current_column_configinfo + def row_cget_tkstring(tagOrId, option) + itemcget_tkstring(['row', tagOrId], option) + end def row_cget(tagOrId, option) itemcget(['row', tagOrId], option) end @@ -124,13 +135,14 @@ def current_row_configinfo(tagOrId, slot=nil) current_itemconfiginfo(['row', tagOrId], slot) end + alias rowcget_tkstring row_cget_tkstring alias rowcget row_cget alias rowcget_strict row_cget_strict alias rowconfigure row_configure alias rowconfiginfo row_configinfo alias current_rowconfiginfo current_row_configinfo - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo end Index: ext/tk/lib/tkextlib/treectrl/tktreectrl.rb =================================================================== --- ext/tk/lib/tkextlib/treectrl/tktreectrl.rb (revision 23917) +++ ext/tk/lib/tkextlib/treectrl/tktreectrl.rb (working copy) @@ -414,6 +414,9 @@ end private :__item_keyonly_optkeys + def column_cget_tkstring(tagOrId, option) + itemcget_tkstring(['column', tagOrId], option) + end def column_cget(tagOrId, option) itemcget(['column', tagOrId], option) end @@ -430,6 +433,9 @@ current_itemconfiginfo(['column', tagOrId], slot) end + def column_dragcget_tkstring(option) + itemcget_tkstring(['column', 'drag'], option) + end def column_dragcget(option) itemcget(['column', 'drag'], option) end @@ -446,6 +452,9 @@ current_itemconfiginfo(['column', 'drag'], slot) end + def debug_cget_tkstring(option) + itemcget_tkstring('debug', option) + end def debug_cget(option) itemcget('debug', option) end @@ -462,6 +471,9 @@ current_itemconfiginfo('debug', slot) end + def dragimage_cget_tkstring(option) + itemcget_tkstring('dragimage', option) + end def dragimage_cget(option) itemcget('dragimage', option) end @@ -478,6 +490,9 @@ current_itemconfiginfo('dragimage', slot) end + def element_cget_tkstring(tagOrId, option) + itemcget_tkstring(['element', tagOrId], option) + end def element_cget(tagOrId, option) itemcget(['element', tagOrId], option) end @@ -494,6 +509,9 @@ current_itemconfiginfo(['element', tagOrId], slot) end + def item_cget_tkstring(tagOrId, option) + itemcget_tkstring(['item', tagOrId], option) + end def item_cget(tagOrId, option) itemcget(['item', tagOrId], option) end @@ -510,6 +528,9 @@ current_itemconfiginfo(['item', tagOrId], slot) end + def item_element_cget_tkstring(item, column, elem, option) + itemcget_tkstring([['item', 'element'], [item, column, elem]], option) + end def item_element_cget(item, column, elem, option) itemcget([['item', 'element'], [item, column, elem]], option) end @@ -526,6 +547,9 @@ current_itemconfiginfo([['item', 'element'], [item, column, elem]], slot) end + def marquee_cget_tkstring(option) + itemcget_tkstring('marquee', option) + end def marquee_cget(option) itemcget('marquee', option) end @@ -542,6 +566,11 @@ current_itemconfiginfo('marquee', slot) end + def notify_cget_tkstring(win, pattern, option) + pattern = "<#{pattern}>" + # "notify" doesn't have cget subcommand. + tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(['notify', [win, pattern]])) << "-#{option}")), false, true)[-1] + end def notify_cget(win, pattern, option) pattern = "<#{pattern}>" # "notify" doesn't have cget subcommand. @@ -571,6 +600,9 @@ current_itemconfiginfo(['notify', [win, pattern]], slot) end + def style_cget_tkstring(tagOrId, option) + itemcget_tkstring(['style', tagOrId], option) + end def style_cget(tagOrId, option) itemcget(['style', tagOrId], option) end @@ -587,7 +619,7 @@ current_itemconfiginfo(['style', tagOrId], slot) end - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo end @@ -1741,6 +1773,9 @@ @id.to_s.dup end + def cget_tkstring(opt) + @tree.column_cget_tkstring(@tree.column_index(@id), opt) + end def cget(opt) @tree.column_cget(@tree.column_index(@id), opt) end @@ -1844,6 +1879,9 @@ @id.dup end + def cget_tkstring(opt) + @tree.element_cget_tkstring(@id, opt) + end def cget(opt) @tree.element_cget(@id, opt) end @@ -1978,6 +2016,9 @@ self end + def cget_tkstring(opt) + @tree.item_cget_tkstring(@id, opt) + end def cget(opt) @tree.item_cget(@id, opt) end @@ -2014,9 +2055,12 @@ @tree.item_element_actual(@id, column, elem, key) end - def element_cget(opt) + def element_cget_tkstring(opt) @tree.item_element_cget(@id, opt) end + def element_cget_tkstring(opt) + @tree.item_element_cget(@id, opt) + end def element_cget_strict(opt) @tree.item_element_cget_strict(@id, opt) end @@ -2268,6 +2312,9 @@ @id.dup end + def cget_tkstring(opt) + @tree.style_cget_tkstring(@id, opt) + end def cget(opt) @tree.style_cget(@id, opt) end Index: ext/tk/lib/tkextlib/bwidget/tree.rb =================================================================== --- ext/tk/lib/tkextlib/bwidget/tree.rb (revision 23917) +++ ext/tk/lib/tkextlib/bwidget/tree.rb (working copy) @@ -139,6 +139,37 @@ _bindinfo_for_event_class(Event_for_Items, [path, 'bindText'], *args) end + def areabind(context, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_for_event_class(Event_for_Items, [path, 'bindArea'], + context, cmd, *args) + self + end + + def areabind_append(context, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append_for_event_class(Event_for_Items, [path, 'bindArea'], + context, cmd, *args) + self + end + + def areabind_remove(*args) + _bind_remove_for_event_class(Event_for_Items, [path, 'bindArea'], *args) + self + end + + def areabindinfo(*args) + _bindinfo_for_event_class(Event_for_Items, [path, 'bindArea'], *args) + end + def close_tree(node, recurse=None) tk_send('closetree', tagid(node), recurse) self @@ -183,7 +214,7 @@ end def open?(node) - bool(@tree.itemcget(tagid(node), 'open')) + bool(self.itemcget(tagid(node), 'open')) end def open_tree(node, recurse=None) @@ -355,6 +386,9 @@ val end + def cget_tkstring(key) + @tree.itemcget_tkstring(@id, key) + end def cget(key) @tree.itemcget(@id, key) end @@ -450,4 +484,3 @@ @tree.visible(@id) end end - Index: ext/tk/lib/tkextlib/bwidget/listbox.rb =================================================================== --- ext/tk/lib/tkextlib/bwidget/listbox.rb (revision 23917) +++ ext/tk/lib/tkextlib/bwidget/listbox.rb (working copy) @@ -294,6 +294,9 @@ val end + def cget_tkstring(key) + @listbox.itemcget_tkstring(@id, key) + end def cget(key) @listbox.itemcget(@id, key) end Index: ext/tk/lib/tkextlib/bwidget/dialog.rb =================================================================== --- ext/tk/lib/tkextlib/bwidget/dialog.rb (revision 23917) +++ ext/tk/lib/tkextlib/bwidget/dialog.rb (working copy) @@ -59,6 +59,13 @@ end end + def cget_tkstring(slot) + if slot.to_s == 'relative' + super('parent') + else + super(slot) + end + end def cget_strict(slot) if slot.to_s == 'relative' super('parent') Index: ext/tk/lib/tkextlib/tktable/tktable.rb =================================================================== --- ext/tk/lib/tkextlib/tktable/tktable.rb (revision 23917) +++ ext/tk/lib/tkextlib/tktable/tktable.rb (working copy) @@ -74,6 +74,9 @@ end private :__item_val2ruby_optkeys + def tag_cget_tkstring(tagOrId, option) + itemcget_tkstring(['tag', tagid(tagOrId)], option) + end def tag_cget(tagOrId, option) itemcget(['tag', tagid(tagOrId)], option) end @@ -90,6 +93,9 @@ current_itemconfiginfo(['tag', tagid(tagOrId)], slot) end + def window_cget_tkstring(tagOrId, option) + itemcget_tkstring(['window', tagid(tagOrId)], option) + end def window_cget(tagOrId, option) itemcget(['window', tagid(tagOrId)], option) end @@ -114,7 +120,7 @@ current_itemconfiginfo(['window', tagid(tagOrId)], slot) end - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo end @@ -197,6 +203,9 @@ @t.tag_lower(@id, target) end + def cget_tkstring(key) + @t.tag_cget_tkstring(@id, key) + end def cget(key) @t.tag_cget(@id, key) end Index: ext/tk/lib/tkextlib/version.rb =================================================================== --- ext/tk/lib/tkextlib/version.rb (revision 23917) +++ ext/tk/lib/tkextlib/version.rb (working copy) @@ -2,5 +2,5 @@ # release date of tkextlib # module Tk - Tkextlib_RELEASE_DATE = '2008-11-25'.freeze + Tkextlib_RELEASE_DATE = '2009-07-01'.freeze end Index: ext/tk/lib/tkextlib/vu/pie.rb =================================================================== --- ext/tk/lib/tkextlib/vu/pie.rb (revision 23917) +++ ext/tk/lib/tkextlib/vu/pie.rb (working copy) @@ -173,6 +173,10 @@ val end + def cget_tkstring(slot) + @pie.itemcget_tkstring(@id, slot) + end + def cget(slot) @pie.itemcget(@id, slot) end Index: ext/tk/lib/tkextlib/tile/tprogressbar.rb =================================================================== --- ext/tk/lib/tkextlib/tile/tprogressbar.rb (revision 23917) +++ ext/tk/lib/tkextlib/tile/tprogressbar.rb (working copy) @@ -13,9 +13,6 @@ end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Progressbar, :TkProgressbar) - - class Tk::Tile::TProgressbar include Tk::Tile::TileWidget @@ -54,3 +51,7 @@ end end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Progressbar, :TkProgressbar) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tprogressbar.rb', + :Ttk, Tk::Tile::Progressbar, :TkProgressbar) Index: ext/tk/lib/tkextlib/tile/tradiobutton.rb =================================================================== --- ext/tk/lib/tkextlib/tile/tradiobutton.rb (revision 23917) +++ ext/tk/lib/tkextlib/tile/tradiobutton.rb (working copy) @@ -15,10 +15,6 @@ end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Radiobutton, - :TkRadiobutton, :TkRadioButton) - - class Tk::Tile::TRadioButton < Tk::RadioButton include Tk::Tile::TileWidget @@ -34,3 +30,9 @@ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Radiobutton, +# :TkRadiobutton, :TkRadioButton) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tradiobutton.rb', + :Ttk, Tk::Tile::Radiobutton, + :TkRadiobutton, :TkRadioButton) Index: ext/tk/lib/tkextlib/tile/tlabelframe.rb =================================================================== --- ext/tk/lib/tkextlib/tile/tlabelframe.rb (revision 23917) +++ ext/tk/lib/tkextlib/tile/tlabelframe.rb (working copy) @@ -15,10 +15,6 @@ end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Labelframe, - :TkLabelframe, :TkLabelFrame) - - class Tk::Tile::TLabelframe < Tk::Tile::TFrame include Tk::Tile::TileWidget @@ -34,3 +30,9 @@ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Labelframe, +# :TkLabelframe, :TkLabelFrame) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tlabelframe.rb', + :Ttk, Tk::Tile::Labelframe, + :TkLabelframe, :TkLabelFrame) Index: ext/tk/lib/tkextlib/tile/tframe.rb =================================================================== --- ext/tk/lib/tkextlib/tile/tframe.rb (revision 23917) +++ ext/tk/lib/tkextlib/tile/tframe.rb (working copy) @@ -13,9 +13,6 @@ end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Frame, :TkFrame) - - class Tk::Tile::TFrame < Tk::Frame include Tk::Tile::TileWidget @@ -31,3 +28,7 @@ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Frame, :TkFrame) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tframe.rb', + :Ttk, Tk::Tile::Frame, :TkFrame) Index: ext/tk/lib/tkextlib/tile/tmenubutton.rb =================================================================== --- ext/tk/lib/tkextlib/tile/tmenubutton.rb (revision 23917) +++ ext/tk/lib/tkextlib/tile/tmenubutton.rb (working copy) @@ -15,10 +15,6 @@ end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Menubutton, - :TkMenubutton, :TkMenuButton) - - class Tk::Tile::TMenubutton < Tk::Menubutton include Tk::Tile::TileWidget @@ -34,3 +30,9 @@ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Menubutton, +# :TkMenubutton, :TkMenuButton) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tmenubutton.rb', + :Ttk, Tk::Tile::Menubutton, + :TkMenubutton, :TkMenuButton) Index: ext/tk/lib/tkextlib/tile/tseparator.rb =================================================================== --- ext/tk/lib/tkextlib/tile/tseparator.rb (revision 23917) +++ ext/tk/lib/tkextlib/tile/tseparator.rb (working copy) @@ -13,9 +13,6 @@ end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Separator, :TkSeparator) - - class Tk::Tile::TSeparator < TkWindow include Tk::Tile::TileWidget @@ -31,3 +28,7 @@ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Separator, :TkSeparator) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tseparator.rb', + :Ttk, Tk::Tile::Separator, :TkSeparator) Index: ext/tk/lib/tkextlib/tile/tentry.rb =================================================================== --- ext/tk/lib/tkextlib/tile/tentry.rb (revision 23917) +++ ext/tk/lib/tkextlib/tile/tentry.rb (working copy) @@ -13,9 +13,6 @@ end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Entry, :TkEntry) - - class Tk::Tile::TEntry < Tk::Entry include Tk::Tile::TileWidget @@ -46,3 +43,7 @@ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Entry, :TkEntry) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tentry.rb', + :Ttk, Tk::Tile::Entry, :TkEntry) Index: ext/tk/lib/tkextlib/tile/treeview.rb =================================================================== --- ext/tk/lib/tkextlib/tile/treeview.rb (revision 23917) +++ ext/tk/lib/tkextlib/tile/treeview.rb (working copy) @@ -12,9 +12,6 @@ end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Treeview, :TkTreeview) - - module Tk::Tile::TreeviewConfig include TkItemConfigMethod @@ -519,16 +516,20 @@ end end + alias __itemcget_tkstring itemcget_tkstring alias __itemcget itemcget alias __itemcget_strict itemcget_strict alias __itemconfigure itemconfigure alias __itemconfiginfo itemconfiginfo alias __current_itemconfiginfo current_itemconfiginfo - private :__itemcget, :__itemcget_strict + private :__itemcget_tkstring, :__itemcget, :__itemcget_strict private :__itemconfigure, :__itemconfiginfo, :__current_itemconfiginfo # Treeview Item + def itemcget_tkstring(tagOrId, option) + __itemcget_tkstring([:item, tagOrId], option) + end def itemcget(tagOrId, option) __itemcget([:item, tagOrId], option) end @@ -546,6 +547,9 @@ end # Treeview Column + def columncget_tkstring(tagOrId, option) + __itemcget_tkstring([:column, tagOrId], option) + end def columncget(tagOrId, option) __itemcget([:column, tagOrId], option) end @@ -561,6 +565,7 @@ def current_columnconfiginfo(tagOrId, slot=nil) __current_itemconfiginfo([:column, tagOrId], slot) end + alias column_cget_tkstring columncget_tkstring alias column_cget columncget alias column_cget_strict columncget_strict alias column_configure columnconfigure @@ -568,6 +573,19 @@ alias current_column_configinfo current_columnconfiginfo # Treeview Heading + def headingcget_tkstring(tagOrId, option) + if __tile_specific_item_optkeys([:heading, tagOrId]).index(option.to_s) + begin + # On tile-0.7.{2-8}, 'state' options has no '-' at its head. + tk_call(*(__item_cget_cmd([:heading, tagOrId]) << option.to_s)) + rescue + # Maybe, 'state' option has '-' in future. + tk_call(*(__item_cget_cmd([:heading, tagOrId]) << "-#{option}")) + end + else + __itemcget_tkstring([:heading, tagOrId], option) + end + end def headingcget_strict(tagOrId, option) if __tile_specific_item_optkeys([:heading, tagOrId]).index(option.to_s) begin @@ -630,6 +648,7 @@ def current_headingconfiginfo(tagOrId, slot=nil) __current_itemconfiginfo([:heading, tagOrId], slot) end + alias heading_cget_tkstring headingcget_tkstring alias heading_cget headingcget alias heading_cget_strict headingcget_strict alias heading_configure headingconfigure @@ -637,6 +656,9 @@ alias current_heading_configinfo current_headingconfiginfo # Treeview Tag + def tagcget_tkstring(tagOrId, option) + __itemcget_tkstring([:tag, :configure, tagOrId], option) + end def tagcget(tagOrId, option) __itemcget([:tag, :configure, tagOrId], option) end @@ -652,6 +674,7 @@ def current_tagconfiginfo(tagOrId, slot=nil) __current_itemconfiginfo([:tag, :configure, tagOrId], slot) end + alias tag_cget_tkstring tagcget_tkstring alias tag_cget tagcget alias tag_cget_strict tagcget_strict alias tag_configure tagconfigure @@ -737,6 +760,9 @@ @id end + def cget_tkstring(option) + @t.itemcget_tkstring(@id, option) + end def cget(option) @t.itemcget(@id, option) end @@ -979,6 +1005,9 @@ @t.tag_bindinfo(@id, seq) end + def cget_tkstring(option) + @t.tagcget_tkstring(@id, option) + end def cget(option) @t.tagcget(@id, option) end @@ -1237,3 +1266,7 @@ end alias tagbindinfo tag_bindinfo end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Treeview, :TkTreeview) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/treeview.rb', + :Ttk, Tk::Tile::Treeview, :TkTreeview) Index: ext/tk/lib/tkextlib/tile/tcombobox.rb =================================================================== --- ext/tk/lib/tkextlib/tile/tcombobox.rb (revision 23917) +++ ext/tk/lib/tkextlib/tile/tcombobox.rb (working copy) @@ -13,9 +13,6 @@ end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Combobox, :TkCombobox) - - class Tk::Tile::TCombobox < Tk::Tile::TEntry include Tk::Tile::TileWidget @@ -52,3 +49,7 @@ tk_send('set', val) end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Combobox, :TkCombobox) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tcombobox.rb', + :Ttk, Tk::Tile::Combobox, :TkCombobox) Index: ext/tk/lib/tkextlib/tile/sizegrip.rb =================================================================== --- ext/tk/lib/tkextlib/tile/sizegrip.rb (revision 23917) +++ ext/tk/lib/tkextlib/tile/sizegrip.rb (working copy) @@ -13,9 +13,6 @@ end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Sizegrip, :TkSizegrip, :TkSizeGrip) - - class Tk::Tile::SizeGrip < TkWindow include Tk::Tile::TileWidget @@ -27,3 +24,9 @@ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Sizegrip, +# :TkSizegrip, :TkSizeGrip) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/sizegrip.rb', + :Ttk, Tk::Tile::Sizegrip, + :TkSizegrip, :TkSizeGrip) Index: ext/tk/lib/tkextlib/tile/tcheckbutton.rb =================================================================== --- ext/tk/lib/tkextlib/tile/tcheckbutton.rb (revision 23917) +++ ext/tk/lib/tkextlib/tile/tcheckbutton.rb (working copy) @@ -15,10 +15,6 @@ end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Checkbutton, - :TkCheckbutton, :TkCheckButton) - - class Tk::Tile::TCheckButton < Tk::CheckButton include Tk::Tile::TileWidget @@ -34,3 +30,9 @@ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Checkbutton, +# :TkCheckbutton, :TkCheckButton) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tcheckbutton.rb', + :Ttk, Tk::Tile::Checkbutton, + :TkCheckbutton, :TkCheckButton) Index: ext/tk/lib/tkextlib/tile/tbutton.rb =================================================================== --- ext/tk/lib/tkextlib/tile/tbutton.rb (revision 23917) +++ ext/tk/lib/tkextlib/tile/tbutton.rb (working copy) @@ -13,9 +13,6 @@ end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Button, :TkButton) - - class Tk::Tile::TButton < Tk::Button include Tk::Tile::TileWidget @@ -31,3 +28,7 @@ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Button, :TkButton) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tbutton.rb', + :Ttk, Tk::Tile::Button, :TkButton) Index: ext/tk/lib/tkextlib/tile/style.rb =================================================================== --- ext/tk/lib/tkextlib/tile/style.rb (revision 23917) +++ ext/tk/lib/tkextlib/tile/style.rb (working copy) @@ -233,6 +233,8 @@ def element_create(name, type, *args) if type == 'image' || type == :image element_create_image(name, *args) + elsif type == 'vsapi' || type == :vsapi + element_create_vsapi(name, *args) else tk_call(TkCommandNames[0], 'element', 'create', name, type, *args) end @@ -279,6 +281,24 @@ end end + def element_create_vsapi(name, class_name, part_id, *args) + # supported on Tcl/Tk 8.6 or later + + # argument check + if (state_map = args.shift || None) + if state_map.kind_of?(Hash) + opts = _symbolkey2str(state_map) + state_map = None + end + end + opts = args.shift || None + fail ArgumentError, "too many arguments" unless args.empty? + + # define a Microsoft Visual Styles element + tk_call(TkCommandNames[0], 'element', 'create', name, 'vsapi', + class_name, part_id, state_map, opts) + end + def element_names() list(tk_call(TkCommandNames[0], 'element', 'names')) end Index: ext/tk/lib/tkextlib/tile/tlabel.rb =================================================================== --- ext/tk/lib/tkextlib/tile/tlabel.rb (revision 23917) +++ ext/tk/lib/tkextlib/tile/tlabel.rb (working copy) @@ -13,9 +13,6 @@ end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Label, :TkLabel) - - class Tk::Tile::TLabel < Tk::Label include Tk::Tile::TileWidget @@ -31,3 +28,7 @@ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Label, :TkLabel) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tlabel.rb', + :Ttk, Tk::Tile::Label, :TkLabel) Index: ext/tk/lib/tkextlib/tile/tnotebook.rb =================================================================== --- ext/tk/lib/tkextlib/tile/tnotebook.rb (revision 23917) +++ ext/tk/lib/tkextlib/tile/tnotebook.rb (working copy) @@ -13,9 +13,6 @@ end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Notebook, :TkNotebook) - - class Tk::Tile::TNotebook < TkWindow ################################ include TkItemConfigMethod @@ -46,8 +43,11 @@ alias tabconfiginfo itemconfiginfo alias current_tabconfiginfo current_itemconfiginfo + def tabcget_tkstring(tagOrId, option) + tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{option}")), false, true)[-1] + end def tabcget_strict(tagOrId, option) - tabconfigure(tagOrId, option)[-1] + tabconfiginfo(tagOrId, option)[-1] end def tabcget(tagOrId, option) unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ @@ -137,3 +137,7 @@ list(tk_send('tabs')) end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Notebook, :TkNotebook) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tnotebook.rb', + :Ttk, Tk::Tile::Notebook, :TkNotebook) Index: ext/tk/lib/tkextlib/tile/tspinbox.rb =================================================================== --- ext/tk/lib/tkextlib/tile/tspinbox.rb (revision 0) +++ ext/tk/lib/tkextlib/tile/tspinbox.rb (revision 0) @@ -0,0 +1,107 @@ +# +# ttk::spinbox widget (Tcl/Tk 8.6b1 or later) +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' +require 'tkextlib/tile.rb' + +module Tk + module Tile + class TSpinbox < Tk::Tile::TEntry + end + Spinbox = TSpinbox + end +end + +class Tk::Tile::TSpinbox < Tk::Tile::TEntry + include Tk::Tile::TileWidget + + if Tk::Tile::USE_TTK_NAMESPACE + TkCommandNames = ['::ttk::spinbox'.freeze].freeze + else + TkCommandNames = ['::tspinbox'.freeze].freeze + end + WidgetClassName = 'TSpinbox'.freeze + WidgetClassNames[WidgetClassName] = self + + class SpinCommand < TkValidateCommand + class ValidateArgs < TkUtil::CallbackSubst + KEY_TBL = [ + [ ?d, ?s, :direction ], + [ ?s, ?e, :current ], + [ ?W, ?w, :widget ], + nil + ] + + PROC_TBL = [ + [ ?s, TkComm.method(:string) ], + [ ?w, TkComm.method(:window) ], + + [ ?e, proc{|val| + #enc = Tk.encoding + enc = ((Tk.encoding)? Tk.encoding : Tk.encoding_system) + if enc + Tk.fromUTF8(TkComm::string(val), enc) + else + TkComm::string(val) + end + } + ], + + nil + ] + + _setup_subst_table(KEY_TBL, PROC_TBL); + + def self.ret_val(val) + (val)? '1': '0' + end + end + + def self._config_keys + ['command'] + end + end + + def __validation_class_list + super() << SpinCommand + end + + Tk::ValidateConfigure.__def_validcmd(binding, SpinCommand) + + def __boolval_optkeys + super() << 'wrap' + end + private :__boolval_optkeys + + def __strval_optkeys + super() << 'buttonbackground' << 'format' + end + private :__strval_optkeys + + def __listval_optkeys + super() << 'values' + end + private :__listval_optkeys + + def self.style(*args) + [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') + end + + def current + number(tk_send_without_enc('current')) + end + def current=(idx) + tk_send_without_enc('current', idx) + end + + def set(val) + tk_send('set', val) + end + + alias identify ttk_identify +end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Spinbox, :TkSpinbox) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tspinbox.rb', + :Ttk, Tk::Tile::Spinbox, :TkSpinbox) Index: ext/tk/lib/tkextlib/tile/tscrollbar.rb =================================================================== --- ext/tk/lib/tkextlib/tile/tscrollbar.rb (revision 23917) +++ ext/tk/lib/tkextlib/tile/tscrollbar.rb (working copy) @@ -13,9 +13,6 @@ end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Scrollbar, :TkScrollbar) - - class Tk::Tile::TScrollbar < Tk::Scrollbar include Tk::Tile::TileWidget @@ -30,8 +27,16 @@ def self.style(*args) [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') end + + alias identify ttk_identify end +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Scrollbar, :TkScrollbar) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tscrollbar.rb', + :Ttk, Tk::Tile::Scrollbar, :TkScrollbar) + +####################################################################### + class Tk::Tile::XScrollbar < Tk::Tile::TScrollbar def create_self(keys) keys = {} unless keys @@ -50,5 +55,9 @@ private :create_self end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::XScrollbar, :TkXScrollbar) -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::YScrollbar, :TkYScrollbar) +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::XScrollbar, :TkXScrollbar) +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::YScrollbar, :TkYScrollbar) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tscrollbar.rb', + :Ttk, Tk::Tile::XScrollbar, :TkXScrollbar) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tscrollbar.rb', + :Ttk, Tk::Tile::YScrollbar, :TkYScrollbar) Index: ext/tk/lib/tkextlib/tile/tpaned.rb =================================================================== --- ext/tk/lib/tkextlib/tile/tpaned.rb (revision 23917) +++ ext/tk/lib/tkextlib/tile/tpaned.rb (working copy) @@ -13,10 +13,6 @@ end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Panedwindow, - :TkPanedwindow, :TkPanedWindow) - - class Tk::Tile::TPaned < TkWindow include Tk::Tile::TileWidget @@ -66,6 +62,12 @@ self end + def panecget_tkstring(pane, slot) + pane = _epath(pane) + tk_send_without_enc('pane', pane, "-#{slot}") + end + alias pane_cget_tkstring panecget_tkstring + def panecget_strict(pane, slot) pane = _epath(pane) tk_tcl2ruby(tk_send_without_enc('pane', pane, "-#{slot}")) @@ -222,10 +224,16 @@ alias current_pane_configinfo current_paneconfiginfo def identify(x, y) - list(tk_send_without_enc('identify', x, y)) + num_or_nil(tk_send_without_enc('identify', x, y)) end def sashpos(idx, newpos=None) num_or_str(tk_send_without_enc('sashpos', idx, newpos)) end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Panedwindow, +# :TkPanedwindow, :TkPanedWindow) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tpaned.rb', + :Ttk, Tk::Tile::Panedwindow, + :TkPanedwindow, :TkPanedWindow) Index: ext/tk/lib/tkextlib/tile/tscale.rb =================================================================== --- ext/tk/lib/tkextlib/tile/tscale.rb (revision 23917) +++ ext/tk/lib/tkextlib/tile/tscale.rb (working copy) @@ -17,9 +17,6 @@ end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Scale, :TkScale) - - class Tk::Tile::TScale < Tk::Scale include Tk::Tile::TileWidget @@ -34,6 +31,8 @@ def self.style(*args) [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') end + + alias identify ttk_identify end class Tk::Tile::TProgress < Tk::Tile::TScale @@ -51,3 +50,7 @@ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Scale, :TkScale) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tscale.rb', + :Ttk, Tk::Tile::Scale, :TkScale) Index: ext/tk/lib/tkextlib/tile.rb =================================================================== --- ext/tk/lib/tkextlib/tile.rb (revision 23917) +++ ext/tk/lib/tkextlib/tile.rb (working copy) @@ -18,12 +18,39 @@ # TkPackage.require('tile', '0.7') if Tk::TK_MAJOR_VERSION > 8 || (Tk::TK_MAJOR_VERSION == 8 && Tk::TK_MINOR_VERSION >= 5) - TkPackage.require('tile') # for compatibility (version check of 'tile') - verstr = TkPackage.require('Ttk') + begin + TkPackage.require('tile') # for compatibility (version check of 'tile') + rescue RuntimeError + # ignore, even if cannot find package 'tile' + end + pkgname = 'Ttk' else - verstr = TkPackage.require('tile') + pkgname = 'tile' end +begin + verstr = TkPackage.require(pkgname) +rescue RuntimeError + # define dummy methods + module Tk + module Tile + CANNOT_FIND_PACKAGE = true + def self.const_missing(sym) + TkPackage.require(PACKAGE_NAME) + end + def self.method_missing(*args) + TkPackage.require(PACKAGE_NAME) + end + end + end + Tk.__cannot_find_tk_package_for_widget_set__(:Ttk, pkgname) + if pkgname == 'Ttk' + verstr = Tk::TK_PATCHLEVEL # dummy + else + verstr = '0.7' # dummy + end +end + ver = verstr.split('.') if ver[0].to_i == 0 # Tile extension package @@ -404,6 +431,9 @@ autoload :TSeparator, 'tkextlib/tile/tseparator' autoload :Separator, 'tkextlib/tile/tseparator' + autoload :TSpinbox, 'tkextlib/tile/tspinbox' + autoload :Spinbox, 'tkextlib/tile/tspinbox' + autoload :TSquare, 'tkextlib/tile/tsquare' autoload :Square, 'tkextlib/tile/tsquare' Index: ext/tk/lib/multi-tk.rb =================================================================== --- ext/tk/lib/multi-tk.rb (revision 23917) +++ ext/tk/lib/multi-tk.rb (working copy) @@ -755,7 +755,12 @@ else ### Ruby 1.9 !!!!!!!!!!! @interp_thread = Thread.new{ current = Thread.current - current[:interp] = interp = TclTkIp.new(name, _keys2opts(keys)) + begin + current[:interp] = interp = TclTkIp.new(name, _keys2opts(keys)) + rescue e + current[:interp] = e + raise e + end #sleep current[:mutex] = mutex = Mutex.new current[:root_check] = cond_var = ConditionVariable.new @@ -771,8 +776,11 @@ begin current[:status].value = interp.mainloop(true) + rescue SystemExit=>e + current[:status].value = e rescue Exception=>e current[:status].value = e + retry if interp.has_mainwindow? ensure mutex.synchronize{ cond_var.broadcast } end Index: ext/tk/lib/tk/busy.rb =================================================================== --- ext/tk/lib/tk/busy.rb (revision 0) +++ ext/tk/lib/tk/busy.rb (revision 0) @@ -0,0 +1,118 @@ +# +# tk/busy.rb: support 'tk busy' command (Tcl/Tk8.6 or later) +# +require 'tk' + +module Tk::Busy + include TkCore + extend TkCore + extend TkItemConfigMethod +end + +class << Tk::Busy + def __item_cget_cmd(win) + # maybe need to override + ['tk', 'busy', 'cget', win.path] + end + private :__item_cget_cmd + + def __item_config_cmd(win) + # maybe need to override + ['tk', 'busy', 'configure', win.path] + end + private :__item_config_cmd + + def __item_confinfo_cmd(win) + # maybe need to override + __item_config_cmd(win) + end + private :__item_confinfo_cmd + + alias cget_tkstring itemcget_tkstring + alias cget itemcget + alias cget_strict itemcget_strict + alias configure itemconfigure + alias configinfo itemconfiginfo + alias current_configinfo current_itemconfiginfo + + private :itemcget_tkstring, :itemcget, :itemcget_strict + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo + + def method_missing(id, *args) + name = id.id2name + case args.length + when 1 + if name[-1] == ?= + configure name[0..-2], args[0] + args[0] + else + configure name, args[0] + self + end + when 0 + begin + cget(name) + rescue + super(id, *args) + end + else + super(id, *args) + end + end + + def hold(win, keys={}) + tk_call_without_enc('tk', 'busy', 'hold', win, *hash_kv(keys)) + win + end + + def forget(*wins) + tk_call_without_enc('tk', 'busy', 'forget', *wins) + self + end + + def current(pat=None) + list(tk_call_without_enc('tk', 'busy', 'current', pat)) + end + + def status(win) + bool(tk_call_without_enc('tk', 'busy', 'status', win)) + end +end + +module Tk::Busy + def busy_configinfo(option=nil) + Tk::Busy.configinfo(self, option) + end + + def busy_current_configinfo(option=nil) + Tk::Busy.current_configinfo(self, option) + end + + def busy_configure(option, value=None) + Tk::Busy.configure(self, option, value) + self + end + + def busy_cget(option) + Tk::Busy.configure(self, option) + end + + def busy(keys={}) + Tk::Busy.hold(self, keys) + self + end + alias busy_hold busy + + def busy_forget + Tk::Busy.forget(self) + self + end + + def busy_current? + ! Tk::Busy.current(self.path).empty? + end + + def busy_status + Tk::Busy.status(self) + end +end Index: ext/tk/lib/tk/toplevel.rb =================================================================== --- ext/tk/lib/tk/toplevel.rb (revision 23917) +++ ext/tk/lib/tk/toplevel.rb (working copy) @@ -259,4 +259,6 @@ end #TkToplevel = Tk::Toplevel unless Object.const_defined? :TkToplevel -Tk.__set_toplevel_aliases__(:Tk, Tk::Toplevel, :TkToplevel) +#Tk.__set_toplevel_aliases__(:Tk, Tk::Toplevel, :TkToplevel) +Tk.__set_loaded_toplevel_aliases__('tk/toplevel.rb', :Tk, Tk::Toplevel, + :TkToplevel) Index: ext/tk/lib/tk/frame.rb =================================================================== --- ext/tk/lib/tk/frame.rb (revision 23917) +++ ext/tk/lib/tk/frame.rb (working copy) @@ -128,4 +128,5 @@ end #TkFrame = Tk::Frame unless Object.const_defined? :TkFrame -Tk.__set_toplevel_aliases__(:Tk, Tk::Frame, :TkFrame) +#Tk.__set_toplevel_aliases__(:Tk, Tk::Frame, :TkFrame) +Tk.__set_loaded_toplevel_aliases__('tk/frame.rb', :Tk, Tk::Frame, :TkFrame) Index: ext/tk/lib/tk/labelframe.rb =================================================================== --- ext/tk/lib/tk/labelframe.rb (revision 23917) +++ ext/tk/lib/tk/labelframe.rb (working copy) @@ -26,4 +26,6 @@ Tk::Labelframe = Tk::LabelFrame #TkLabelFrame = Tk::LabelFrame unless Object.const_defined? :TkLabelFrame #TkLabelframe = Tk::Labelframe unless Object.const_defined? :TkLabelframe -Tk.__set_toplevel_aliases__(:Tk, Tk::LabelFrame, :TkLabelFrame, :TkLabelframe) +#Tk.__set_toplevel_aliases__(:Tk, Tk::LabelFrame, :TkLabelFrame, :TkLabelframe) +Tk.__set_loaded_toplevel_aliases__('tk/labelframe.rb', :Tk, Tk::LabelFrame, + :TkLabelFrame, :TkLabelframe) Index: ext/tk/lib/tk/scrollbar.rb =================================================================== --- ext/tk/lib/tk/scrollbar.rb (revision 23917) +++ ext/tk/lib/tk/scrollbar.rb (working copy) @@ -148,7 +148,9 @@ end #TkScrollbar = Tk::Scrollbar unless Object.const_defined? :TkScrollbar -Tk.__set_toplevel_aliases__(:Tk, Tk::Scrollbar, :TkScrollbar) +#Tk.__set_toplevel_aliases__(:Tk, Tk::Scrollbar, :TkScrollbar) +Tk.__set_loaded_toplevel_aliases__('tk/scrollbar.rb', :Tk, Tk::Scrollbar, + :TkScrollbar) class Tk::XScrollbar 'tkextlib/tile/treeview', } - @TOPLEVEL_ALIAS_TABLE[:Tile] = @TOPLEVEL_ALIAS_TABLE[:Ttk] + # @TOPLEVEL_ALIAS_TABLE[:Tile] = @TOPLEVEL_ALIAS_TABLE[:Ttk] + Tk.__create_widget_set__(:Tile, :Ttk) + + ############################################ + # depend on the version of Tcl/Tk + major, minor, type, patchlevel = TclTkLib.get_version + + # ttk::spinbox is supported on Tcl/Tk8.6b1 or later + if ([major,minor,type,patchlevel] <=> + [8,6,TclTkLib::RELEASE_TYPE::BETA,1]) >= 0 + @TOPLEVEL_ALIAS_TABLE[:Ttk].update( + :TkSpinbox => 'tkextlib/tile/tspinbox' + ) + end + ################################################ # register some Ttk widgets as default # (Ttk is a standard library on Tcl/Tk8.5+) @TOPLEVEL_ALIAS_TABLE[:Ttk].each{|sym, file| - unless Object.autoload?(sym) || Object.const_defined?(sym) - Object.autoload(sym, file) - end + #unless Tk::TOPLEVEL_ALIASES.autoload?(sym) || Tk::TOPLEVEL_ALIASES.const_defined?(sym) + # @TOPLEVEL_ALIAS_OWNER[sym] = :Ttk + # Tk::TOPLEVEL_ALIASES.autoload(sym, file) + #end + Tk.__regist_toplevel_aliases__(:Ttk, file, sym) } ################################################ - @TOPLEVEL_ALIAS_SETUP_PROC[:Tile] = - @TOPLEVEL_ALIAS_SETUP_PROC[:Ttk] = proc{|mod| + # @TOPLEVEL_ALIAS_SETUP_PROC[:Tile] = + # @TOPLEVEL_ALIAS_SETUP_PROC[:Ttk] = proc{|mod| + # unless Tk.autoload?(:Tile) || Tk.const_defined?(:Tile) + # Object.autoload :Ttk, 'tkextlib/tile' + # Tk.autoload :Tile, 'tkextlib/tile' + # end + # } + Tk.__toplevel_alias_setup_proc__(:Ttk, :Tile){|mod| unless Tk.autoload?(:Tile) || Tk.const_defined?(:Tile) Object.autoload :Ttk, 'tkextlib/tile' Tk.autoload :Tile, 'tkextlib/tile' Index: ext/tk/lib/tk/menu.rb =================================================================== --- ext/tk/lib/tk/menu.rb (revision 23917) +++ ext/tk/lib/tk/menu.rb (working copy) @@ -33,13 +33,14 @@ end private :__item_val2ruby_optkeys + alias entrycget_tkstring itemcget_tkstring alias entrycget itemcget alias entrycget_strict itemcget_strict alias entryconfigure itemconfigure alias entryconfiginfo itemconfiginfo alias current_entryconfiginfo current_itemconfiginfo - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo end @@ -386,7 +387,8 @@ end #TkMenu = Tk::Menu unless Object.const_defined? :TkMenu -Tk.__set_toplevel_aliases__(:Tk, Tk::Menu, :TkMenu) +#Tk.__set_toplevel_aliases__(:Tk, Tk::Menu, :TkMenu) +Tk.__set_loaded_toplevel_aliases__('tk/menu.rb', :Tk, Tk::Menu, :TkMenu) class Tk::MenuClone e + # old version of element? + begin + tk_send_without_enc('invoke', 'spinup') + rescue + fail e + end + end self end def spindown - tk_send_without_enc('invoke', 'spindown') + begin + tk_send_without_enc('invoke', 'buttondown') + rescue RuntimeError => e + # old version of element? + begin + tk_send_without_enc('invoke', 'spinup') + rescue + fail e + end + end self end @@ -116,4 +139,6 @@ end #TkSpinbox = Tk::Spinbox unless Object.const_defined? :TkSpinbox -Tk.__set_toplevel_aliases__(:Tk, Tk::Spinbox, :TkSpinbox) +#Tk.__set_toplevel_aliases__(:Tk, Tk::Spinbox, :TkSpinbox) +Tk.__set_loaded_toplevel_aliases__('tk/spinbox.rb', :Tk, Tk::Spinbox, + :TkSpinbox) Index: ext/tk/lib/tk/itemconfig.rb =================================================================== --- ext/tk/lib/tk/itemconfig.rb (revision 23917) +++ ext/tk/lib/tk/itemconfig.rb (working copy) @@ -162,6 +162,13 @@ ################################################ + + def itemcget_tkstring(tagOrId, option) + opt = option.to_s + fail ArgumentError, "Invalid option `#{option.inspect}'" if opt.length == 0 + tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{opt}")) + end + def __itemcget_core(tagOrId, option) orig_opt = option option = option.to_s Index: ext/tk/lib/tk/fontchooser.rb =================================================================== --- ext/tk/lib/tk/fontchooser.rb (revision 0) +++ ext/tk/lib/tk/fontchooser.rb (revision 0) @@ -0,0 +1,166 @@ +# +# tk/fontchooser.rb -- "tk fontchooser" support (Tcl/Tk8.6 or later) +# +require 'tk' +require 'tk/font' + +module TkFont::Chooser + extend TkCore +end + +class << TkFont::Chooser + def method_missing(id, *args) + name = id.id2name + case args.length + when 1 + if name[-1] == ?= + configure name[0..-2], args[0] + args[0] + else + configure name, args[0] + self + end + when 0 + begin + cget(name) + rescue + super(id, *args) + end + else + super(id, *args) + end + end + + def __conviginfo_value(key, val) + case key + when 'parent' + window(val) + when 'title' + val + when 'font' + if (lst = tk_split_simplelist(val)).size == 1 + lst[0] + else + lst.map{|elem| num_or_str(elem)} + end + when 'command' + tk_tcl2ruby(val) + when 'visible' + bool(val) + else # unkown + val + end + end + private :__conviginfo_value + + def configinfo(option=nil) + if !option && TkComm::GET_CONFIGINFOwoRES_AS_ARRAY + lst = tk_split_simplelist(tk_call('tk', 'fontchooser', 'configure')) + ret = [] + lst.each_slice(2){|k, v| + k = k[1..-1] + ret << [k, __conviginfo_value(k, v)] + } + ret + else + current_configinfo(option) + end + end + + def current_configinfo(option=nil) + if option + opt = option.to_s + fail ArgumentError, "Invalid option `#{option.inspect}'" if opt.empty? + __conviginfo_value(option.to_s, tk_call('tk','fontchooser', + 'configure',"-#{opt}")) + else + lst = tk_split_simplelist(tk_call('tk', 'fontchooser', 'configure')) + ret = {} + lst.each_slice(2){|k, v| + k = k[1..-1] + ret[k] = __conviginfo_value(k, v) + } + ret + end + end + + def configure(option, value=None) + if option.kind_of? Hash + tk_call('tk', 'fontchooser', 'configure', + *hash_kv(_symbolkey2str(option))) + else + opt = option.to_s + fail ArgumentError, "Invalid option `#{option.inspect}'" if opt.empty? + tk_call('tk', 'fontchooser', 'configure', "-#{opt}", value) + end + self + end + + def configure_cmd(slot, value) + configure(slot, install_cmd(value)) + end + + def command(cmd=nil, &b) + if cmd + configure_cmd('command', cmd) + elsif b + configure_cmd('command', Proc.new(&b)) + else + cget('command') + end + end + + def cget(slot) + configinfo slot + end + + def [](slot) + cget slot + end + + def []=(slot, val) + configure slot, val + val + end + + def show + tk_call('tk', 'fontchooser', 'show') + self + end + + def hide + tk_call('tk', 'fontchooser', 'hide') + self + end + + def toggle + cget(:visible) ? hide: show + self + end + + def set_for(target, title="Font") + if target.kind_of? TkFont + configs = { + :font=>target.actual_hash, + :command=>proc{|fnt, *args| + target.configure(TkFont.actual_hash(fnt)) + } + } + else + configs = { + :font=>target.cget_tkstring(:font), + :command=>proc{|fnt, *args| + target.font = TkFont.actual_hash_displayof(fnt, target) + } + } + end + + configs[:title] = title if title + configure(configs) + target + end + + def unset + configure(:command, nil) + end +end Index: ext/tk/lib/tk/winpkg.rb =================================================================== --- ext/tk/lib/tk/winpkg.rb (revision 23917) +++ ext/tk/lib/tk/winpkg.rb (working copy) @@ -10,7 +10,8 @@ module Tk::WinDDE end #TkWinDDE = Tk::WinDDE -Tk.__set_toplevel_aliases__(:Tk, Tk::WinDDE, :TkWinDDE) +#Tk.__set_toplevel_aliases__(:Tk, Tk::WinDDE, :TkWinDDE) +Tk.__set_loaded_toplevel_aliases__('tk/winpkg.rb', :Tk, Tk::WinDDE, :TkWinDDE) module Tk::WinDDE extend Tk @@ -93,7 +94,9 @@ module Tk::WinRegistry end #TkWinRegistry = Tk::WinRegistry -Tk.__set_toplevel_aliases__(:Tk, Tk::WinRegistry, :TkWinRegistry) +#Tk.__set_toplevel_aliases__(:Tk, Tk::WinRegistry, :TkWinRegistry) +Tk.__set_loaded_toplevel_aliases__('tk/winpkg.rb', :Tk, Tk::WinRegistry, + :TkWinRegistry) module Tk::WinRegistry extend Tk Index: ext/tk/lib/tk/font.rb =================================================================== --- ext/tk/lib/tk/font.rb (revision 23917) +++ ext/tk/lib/tk/font.rb (working copy) @@ -211,7 +211,7 @@ end end def TkFont.actual_hash(fnt, option=nil) - Hash[TkFont.actual_hash(fnt, option)] + Hash[TkFont.actual(fnt, option)] end def TkFont.actual_displayof(fnt, win, option=nil) @@ -224,7 +224,7 @@ end end def TkFont.actual_hash_displayof(fnt, option=nil) - Hash[TkFont.actual_hash_displayof(fnt, option)] + Hash[TkFont.actual_displayof(fnt, option)] end def TkFont.configure(fnt, slot, value=None) @@ -2199,7 +2199,7 @@ alias measure_core measure_core_tk4x alias metrics_core metrics_core_tk4x - when /^8\.[0-5]/ + when /^8\.[0-9]/ alias actual_core actual_core_tk8x alias configure_core configure_core_tk8x alias configinfo_core configinfo_core_tk8x @@ -2342,3 +2342,10 @@ 'systemDetailSystemFont', 'systemDetailEmphasizedSystemFont' ] end + +####################################### +# autoload +####################################### +class TkFont + autoload :Chooser, 'tk/fontchooser' +end Index: ext/tk/lib/tk/canvastag.rb =================================================================== --- ext/tk/lib/tk/canvastag.rb (revision 23917) +++ ext/tk/lib/tk/canvastag.rb (working copy) @@ -116,6 +116,13 @@ self end + def imove(idx, x, y) + # Tcl/Tk 8.6 or later + @c.imove(@id, idx, x, y) + self + end + alias i_move imove + def index(idx) @c.index(@id, idx) end @@ -135,6 +142,13 @@ self end + def moveto(x, y) + # Tcl/Tk 8.6 or later + @c.moveto(@id, x, y) + self + end + alias move_to moveto + def raise(abovethis=None) @c.raise(@id, abovethis) self @@ -145,6 +159,14 @@ self end + def rchars(first, last, str_or_coords) + # Tcl/Tk 8.6 or later + @c.rchars(@id, first, last, str_or_coords) + self + end + alias replace_chars rchars + alias replace_coords rchars + def select_adjust(index) @c.select('adjust', @id, index) self Index: ext/tk/lib/tk/checkbutton.rb =================================================================== --- ext/tk/lib/tk/checkbutton.rb (revision 23917) +++ ext/tk/lib/tk/checkbutton.rb (working copy) @@ -26,5 +26,7 @@ Tk::Checkbutton = Tk::CheckButton #TkCheckButton = Tk::CheckButton unless Object.const_defined? :TkCheckButton #TkCheckbutton = Tk::Checkbutton unless Object.const_defined? :TkCheckbutton -Tk.__set_toplevel_aliases__(:Tk, Tk::CheckButton, - :TkCheckButton, :TkCheckbutton) +#Tk.__set_toplevel_aliases__(:Tk, Tk::CheckButton, +# :TkCheckButton, :TkCheckbutton) +Tk.__set_loaded_toplevel_aliases__('tk/checkbutton.rb', :Tk, Tk::CheckButton, + :TkCheckButton, :TkCheckbutton) Index: ext/tk/lib/tk/panedwindow.rb =================================================================== --- ext/tk/lib/tk/panedwindow.rb (revision 23917) +++ ext/tk/lib/tk/panedwindow.rb (working copy) @@ -254,5 +254,7 @@ Tk::Panedwindow = Tk::PanedWindow #TkPanedWindow = Tk::PanedWindow unless Object.const_defined? :TkPanedWindow #TkPanedwindow = Tk::Panedwindow unless Object.const_defined? :TkPanedwindow -Tk.__set_toplevel_aliases__(:Tk, Tk::PanedWindow, - :TkPanedWindow, :TkPanedwindow) +#Tk.__set_toplevel_aliases__(:Tk, Tk::PanedWindow, +# :TkPanedWindow, :TkPanedwindow) +Tk.__set_loaded_toplevel_aliases__('tk/panedwindow.rb', :Tk, Tk::PanedWindow, + :TkPanedWindow, :TkPanedwindow) Index: ext/tk/lib/tk/event.rb =================================================================== --- ext/tk/lib/tk/event.rb (revision 23917) +++ ext/tk/lib/tk/event.rb (working copy) @@ -8,7 +8,7 @@ ######################## require 'tkutil' -require 'tk' +require 'tk' unless Object.const_defined? :TkComm ######################## Index: ext/tk/lib/tk/radiobutton.rb =================================================================== --- ext/tk/lib/tk/radiobutton.rb (revision 23917) +++ ext/tk/lib/tk/radiobutton.rb (working copy) @@ -67,5 +67,7 @@ Tk::Radiobutton = Tk::RadioButton #TkRadioButton = Tk::RadioButton unless Object.const_defined? :TkRadioButton #TkRadiobutton = Tk::Radiobutton unless Object.const_defined? :TkRadiobutton -Tk.__set_toplevel_aliases__(:Tk, Tk::RadioButton, - :TkRadioButton, :TkRadiobutton) +#Tk.__set_toplevel_aliases__(:Tk, Tk::RadioButton, +# :TkRadioButton, :TkRadiobutton) +Tk.__set_loaded_toplevel_aliases__('tk/radiobutton.rb', :Tk, Tk::RadioButton, + :TkRadioButton, :TkRadiobutton) Index: ext/tk/lib/tk/macpkg.rb =================================================================== --- ext/tk/lib/tk/macpkg.rb (revision 23917) +++ ext/tk/lib/tk/macpkg.rb (working copy) @@ -23,7 +23,9 @@ module Tk::MacResource end #TkMacResource = Tk::MacResource -Tk.__set_toplevel_aliases__(:Tk, Tk::MacResource, :TkMacResource) +#Tk.__set_toplevel_aliases__(:Tk, Tk::MacResource, :TkMacResource) +Tk.__set_loaded_toplevel_aliases__('tk/macpkg.rb', :Tk, Tk::MacResource, + :TkMacResource) module Tk::MacResource extend Tk Index: ext/tk/lib/tk/autoload.rb =================================================================== --- ext/tk/lib/tk/autoload.rb (revision 23917) +++ ext/tk/lib/tk/autoload.rb (working copy) @@ -27,6 +27,8 @@ ############################################ # classes on Tk module module Tk + autoload :Busy, 'tk/busy' + autoload :Button, 'tk/button' autoload :Canvas, 'tk/canvas' @@ -319,9 +321,16 @@ @TOPLEVEL_ALIAS_SETUP_PROC = {} + @AUTOLOAD_FILE_SYM_TABLE = Hash.new{|h,k| h[k]={}} # TABLE[file][sym] -> obj + @current_default_widget_set = nil + + module TOPLEVEL_ALIASES; end end +class Object + include Tk::TOPLEVEL_ALIASES +end ############################################ # methods to control default widget set @@ -343,50 +352,387 @@ _replace_toplevel_aliases(target) end - def __set_toplevel_aliases__(target, obj, *symbols) + def widget_set_symbols + @TOPLEVEL_ALIAS_TABLE.keys + end + + def toplevel_aliases_on_widget_set(widget_set) + if (tbl = @TOPLEVEL_ALIAS_TABLE[widget_set.to_sym]) + tbl.collect{|k, v| (v.nil?)? nil: k}.compact + else + fail ArgumentError, "unknown widget_set #{widget_set.to_sym.inspect}" + end + end + + def __toplevel_alias_setup_proc__(*target_list, &cmd) + target_list.each{|target| @TOPLEVEL_ALIAS_SETUP_PROC[target.to_sym] = cmd} + end + + def topobj_defined?(sym) #=> alias_filename or object or false + Object.autoload?(sym) || + (Object.const_defined?(sym) && Object.const_get(sym)) + end + def topalias_defined?(sym) #=> alias_filename or object or false + Tk::TOPLEVEL_ALIASES.autoload?(sym) || + (Tk::TOPLEVEL_ALIASES.const_defined?(sym) && + Tk::TOPLEVEL_ALIASES.const_get(sym)) + end + def define_topobj(sym, obj) + if obj.kind_of? String + # obj is an autoload path + Object.autoload(sym, obj) + unless Object.autoload?(sym) + # file is autoloaded? + if @AUTOLOAD_FILE_SYM_TABLE.has_key?(obj) && + (loaded_obj = @AUTOLOAD_FILE_SYM_TABLE[obj][sym]) + Object.const_set(sym, loaded_obj) + else + fail ArgumentError, "cannot define autoload file (already loaded?)" + end + end + else + # object + Object.const_set(sym, obj) + end + end + def define_topalias(sym, obj) + if obj.kind_of? String + # obj is an autoload path + Tk::TOPLEVEL_ALIASES.autoload(sym, obj) + unless Tk::TOPLEVEL_ALIASES.autoload?(sym) + # file is autoloaded? + if @AUTOLOAD_FILE_SYM_TABLE.has_key?(obj) && + (loaded_obj = @AUTOLOAD_FILE_SYM_TABLE[obj][sym]) + Tk::TOPLEVEL_ALIASES.const_set(sym, loaded_obj) + else + fail ArgumentError, "cannot define autoload file (already loaded?)" + end + end + else + # object + Tk::TOPLEVEL_ALIASES.const_set(sym, obj) + end + end + def replace_topobj(sym, obj) #=> old_obj (alias_filename or object) or nil + if old_obj = topobj_defined?(sym) + Object.class_eval{remove_const sym} rescue nil # ignore err + end + define_topobj(sym, obj) + old_obj + end + def replace_topalias(sym, obj) #=> old_obj (alias_filename or object) or nil + if old_obj = topalias_defined?(sym) + Tk::TOPLEVEL_ALIASES.module_eval{remove_const sym} rescue nil #ignore err + end + define_topalias(sym, obj) + old_obj + end + private :topobj_defined?, :topalias_defined? + private :define_topobj, :define_topalias + private :replace_topobj, :replace_topalias + + def __regist_toplevel_aliases__(target, obj, *symbols) + # initial regist @TOPLEVEL_ALIAS_TABLE[target = target.to_sym] ||= {} symbols.each{|sym| @TOPLEVEL_ALIAS_TABLE[target][sym = sym.to_sym] = obj - # if @current_default_widget_set == target - if @TOPLEVEL_ALIAS_OWNER[sym] == target - Object.class_eval{remove_const sym} if Object.const_defined?(sym) - Object.const_set(sym, obj) + if !topalias_defined?(sym) || target == @current_default_widget_set + @TOPLEVEL_ALIAS_OWNER[sym] = target + replace_topalias(sym, obj) + replace_topobj(sym, obj) unless obj.kind_of?(String) # NOT autoload end } end - ################################### - private - def _replace_toplevel_aliases(target) - # check already autoloaded - if (table = @TOPLEVEL_ALIAS_TABLE[current = @current_default_widget_set]) - table.each{|sym, file| - if !Object.autoload?(sym) && Object.const_defined?(sym) && - @TOPLEVEL_ALIAS_TABLE[current][sym].kind_of?(String) - # autoload -> class - @TOPLEVEL_ALIAS_TABLE[current][sym] = Object.const_get(sym) + def regist_sym_for_loaded_file(auto, obj, sym) + @AUTOLOAD_FILE_SYM_TABLE[auto][sym] = obj + + reg = /^#{Regexp.quote(auto)}(\.rb|\.so|)$/ + @TOPLEVEL_ALIAS_TABLE.each_key{|set| + if @TOPLEVEL_ALIAS_TABLE[set][sym] =~ reg + @TOPLEVEL_ALIAS_TABLE[set][sym] = obj + if @TOPLEVEL_ALIAS_OWNER[sym].nil? || @TOPLEVEL_ALIAS_OWNER[sym] == set + replace_topalias(sym, obj) + replace_topobj(sym, obj) if set == @current_default_widget_set end - } + end + } + if (f = Object.autoload?(sym)) && f =~ reg + replace_topobj(sym, obj) end + if (f = Tk::TOPLEVEL_ALIASES.autoload?(sym)) && f =~ reg + replace_topalias(sym, obj) + end + end + private :regist_sym_for_loaded_file - # setup autoloads - @TOPLEVEL_ALIAS_TABLE[target].each{|sym, file| - Object.class_eval{remove_const sym} if Object.const_defined?(sym) - if file.kind_of?(String) - # file => autoload target file - Object.autoload(sym, file) + def set_topalias(target, obj, sym) + # obj is a kind of String : define autoload path + # Class : use the class object + if target == @current_default_widget_set + case @TOPLEVEL_ALIAS_OWNER[sym] + when false + # Object::sym is out of control. --> not change + # Make ALIAS::sym under control, because target widget set is current. + # Keep OWNER[sym] + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + + when target + if current_obj = topobj_defined?(sym) + if current_obj == obj + # Make current_obj under control. + # Keep Object::sym. + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + + else # current_obj != obj + if current_obj == topalias_defined?(sym) + # Change controlled object + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + replace_topobj(sym, obj) + + else # current_obj != topalias_defined?(sym) + # Maybe current_obj is defined by user. --> OWNER[sym] = faise + # Keep Object::sym. + @TOPLEVEL_ALIAS_OWNER[sym] = false + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + end + end + + else # NOT topobj_defined?(sym) + # New definition for sym at target. + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + define_topobj(sym, obj) + end + + when nil + # New definition for sym at target. + @TOPLEVEL_ALIAS_OWNER[sym] = target + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + + else # others + # Maybe planning to make sym under control. + @TOPLEVEL_ALIAS_OWNER[sym] = target + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + replace_topobj(sym, obj) + end + + else # target != @current_default_widget_set + case @TOPLEVEL_ALIAS_OWNER[sym] + when false + # Object::sym is out of control. --> not change + if topalias_defined?(sym) + # ALIAS[sym] may be defined by other widget set. + # Keep Object::sym (even if it is not defined) + # Keep ALIAS[sym]. + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + + else # NOT topalias_defined?(sym) + # Nobody controls ALIAS[sym]. + # At leaset, current widget set doesn't control ALIAS[sym]. + # Keep Object::sym (even if it is not defined) + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + define_topalias(sym, obj) + end + + when target + # Maybe change controlled object, because Object::sym is under control. + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + replace_topobj(sym, obj) + + when nil + # New definition for sym + @TOPLEVEL_ALIAS_OWNER[sym] = target + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + replace_topobj(sym, obj) + + else # others + # An other widget set controls sym. + # Keep Object::sym (even if it is not defined) + # Keep ALIAS[sym]. + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + + end + end + + sym + end + private :set_topalias + + def __set_toplevel_aliases__(target, obj, *symbols) + # obj is a kind of String : define autoload path + # Class : use the class object + target = target.to_sym + symbols.each{|sym| set_topalias(target, obj, sym.to_sym)} + end + + def __set_loaded_toplevel_aliases__(autopath, target, obj, *symbols) + # autopath is an autoload file + # Currently, this method doesn't support that autoload loads + # different toplevels between .rb and .so extension. + shortpath = (autopath =~ /^(.*)(.rb|.so)$/)? $1: autopath + target = target.to_sym + symbols.map!{|sym| sym.to_sym} + + symbols.each{|sym| regist_sym_for_loaded_file(shortpath, obj, sym) } + symbols.each{|sym| set_topalias(target, obj, sym)} + end + + def backup_current_topdef(sym) + return if (current = @current_default_widget_set).nil? + + case @TOPLEVEL_ALIAS_OWNER[sym] + when false + # Object::sym is out of control. + if (cur_alias = topalias_defined?(sym)) && ! cur_alias.kind_of?(String) + @TOPLEVEL_ALIAS_TABLE[current][sym] = cur_alias + end + + when current + if cur_obj = topobj_defined?(sym) + if ! cur_obj.kind_of?(String) && (cur_alias = topalias_defined?(sym)) + if cur_alias.kind_of?(String) + # Mayby, user replaced Object::sym. + # Make Object::sym out of control. + @TOPLEVEL_ALIAS_OWNER[sym] = false + elsif cur_obj == cur_alias + # Possibley, defined normally. Backup it + @TOPLEVEL_ALIAS_TABLE[current][sym] = cur_alias + else + # Mayby, user replaced Object::sym. + # Make Object::sym out of control. + @TOPLEVEL_ALIAS_OWNER[sym] = false + end + end else - # file => loaded class object - Object.const_set(sym, file) + # Mayby, user replaced Object::sym. + # Make Object::sym out of control. + @TOPLEVEL_ALIAS_OWNER[sym] = false end - @TOPLEVEL_ALIAS_OWNER[sym] = target + + when nil + # Object::sym is out of control. + if (cur_alias = topalias_defined?(sym)) && ! cur_alias.kind_of?(String) + # Possibley, defined normally. Backup it. + @TOPLEVEL_ALIAS_TABLE[current][sym] = cur_alias + end + else + # No authority to control Object::sym and ALIASES::sym. + # Do nothing. + end + end + private :backup_current_topdef + + def _replace_toplevel_aliases(target) + # backup + @TOPLEVEL_ALIAS_TABLE[target].each_key{|sym| + backup_current_topdef(sym) } - # update current alias + # replace + @TOPLEVEL_ALIAS_TABLE[target].each_key{|sym| + next if (obj = @TOPLEVEL_ALIAS_TABLE[target][sym]).nil? + if @TOPLEVEL_ALIAS_OWNER[sym] == false + # Object::sym is out of control. --> not change + # Keep OWNER[sym]. + replace_topalias(sym, obj) + else + # New definition + @TOPLEVEL_ALIAS_OWNER[sym] = target + replace_topalias(sym, obj) + replace_topobj(sym, obj) + end + } + + # change default_widget_set @current_default_widget_set = target end + private :_replace_toplevel_aliases + + def __import_toplevel_aliases__(target, *symbols) + current = @current_default_widget_set + symbols.each{|sym| + sym = sym.to_sym + if (obj = @TOPLEVEL_ALIAS_TABLE[target][sym]).nil? + # remove + @TOPLEVEL_ALIAS_TABLE[current].delete(sym) + @TOPLEVEL_ALIAS_OWNER.delete(sym) + Tk::TOPLEVEL_ALIASES.module_eval{remove_const sym} if topalias_defined?(sym) + Object.class_eval{remove_const sym} if topobj_defined?(sym) + + elsif obj == false + # remove, but OWNER[sym] <- false and not treat Object::sym + @TOPLEVEL_ALIAS_TABLE[current].delete(sym) + @TOPLEVEL_ALIAS_OWNER[sym] = false + Tk::TOPLEVEL_ALIASES.module_eval{remove_const sym} if topalias_defined?(sym) + + elsif @TOPLEVEL_ALIAS_OWNER[sym] == false + # Object::sym is out of control. --> not change + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[current][sym] = obj + replace_topalias(sym, obj) + + else + # new definition under control + @TOPLEVEL_ALIAS_OWNER[sym] = current + @TOPLEVEL_ALIAS_TABLE[current][sym] = obj + replace_topalias(sym, obj) + replace_topobj(sym, obj) + end + } + end + + def __remove_toplevel_aliases__(*symbols) + # remove toplevel aliases of current widget set + current = @current_default_widget_set + symbols.each{|sym| + sym = sym.to_sym + @TOPLEVEL_ALIAS_TABLE[current].delete(sym) + @TOPLEVEL_ALIAS_OWNER.delete(sym) + Tk::TOPLEVEL_ALIASES.module_eval{remove_const sym} if topalias_defined?(sym) + Object.class_eval{remove_const sym} if topobj_defined?(sym) + } + end + + def __reset_toplevel_owner__(*symbols) + symbols.each{|sym| @TOPLEVEL_ALIAS_OWNER.delete(sym.to_sym)} + end + + def __disable_toplevel_control__(*symbols) + symbols.each{|sym| @TOPLEVEL_ALIAS_OWNER[sym.to_sym] = false} + end + + def __create_widget_set__(new_set, src_set={}) + new_set = new_set.to_sym + if @TOPLEVEL_ALIAS_TABLE[new_set] + fail RuntimeError, "A widget-set #{new_set.inspect} is already exist." + end + if src_set.kind_of?(Symbol) + # new_set is an alias name of existed widget set. + @TOPLEVEL_ALIAS_TABLE[new_set] = @TOPLEVEL_ALIAS_TABLE[src_set] + else + @TOPLEVEL_ALIAS_TABLE[new_set] = {} + src_set.each{|sym, obj| set_topalias(new_set, obj, sym.to_sym) } + end + end end + ############################################ # setup default widget set => :Tk Tk.default_widget_set = :Tk Index: ext/tk/lib/tk/canvas.rb =================================================================== --- ext/tk/lib/tk/canvas.rb (revision 23917) +++ ext/tk/lib/tk/canvas.rb (working copy) @@ -265,6 +265,12 @@ self end + def imove(tagOrId, idx, x, y) + tk_send_without_enc('imove', tagid(tagOrId), idx, x, y) + self + end + alias i_move imove + def index(tagOrId, idx) number(tk_send_without_enc('index', tagid(tagOrId), idx)) end @@ -523,11 +529,18 @@ self end - def move(tag, x, y) - tk_send_without_enc('move', tagid(tag), x, y) + def move(tag, dx, dy) + tk_send_without_enc('move', tagid(tag), dx, dy) self end + def moveto(tag, x, y) + # Tcl/Tk 8.6 or later + tk_send_without_enc('moveto', tagid(tag), x, y) + self + end + alias move_to moveto + def postscript(keys) tk_send("postscript", *hash_kv(keys)) end @@ -541,6 +554,15 @@ self end + def rchars(tag, first, last, str_or_coords) + # Tcl/Tk 8.6 or later + str_or_coords = str_or_coords.flatten if str_or_coords.kinad_of? Array + tk_send_without_enc('rchars', tagid(tag), first, last, str_or_coords) + self + end + alias replace_chars rchars + alias replace_coords rchars + def scale(tag, x, y, xs, ys) tk_send_without_enc('scale', tagid(tag), x, y, xs, ys) self @@ -581,7 +603,8 @@ end #TkCanvas = Tk::Canvas unless Object.const_defined? :TkCanvas -Tk.__set_toplevel_aliases__(:Tk, Tk::Canvas, :TkCanvas) +#Tk.__set_toplevel_aliases__(:Tk, Tk::Canvas, :TkCanvas) +Tk.__set_loaded_toplevel_aliases__('tk/canvas.rb', :Tk, Tk::Canvas, :TkCanvas) class TkcItem File.ctime(config_list_file) + old_config_list_file = config_list_file_source +else + old_config_list_file = config_list_file +end +current_configs = {'with'=>{}, 'enable'=>{}} +IO.foreach(old_config_list_file){|line| + line.chomp! + line.lstrip! + next if line.empty? || line =~ /^\#/ # + mode, key, value = line.split(/\s+/, 3) + current_configs[mode][key] = value rescue nil # ignore unknown 'mode' error +} + +update_flag = false +current_configs['with'].each_key{|key| + if (value = with_config(key).to_s) != current_configs['with'][key] + update_flag = true + current_configs['with'][key] = value end +} +current_configs['enable'].each_key{|key| + if (value = enable_config(key).to_s) != current_configs['enable'][key] + update_flag = true + current_configs['enable'][key] = value + end +} - checking_for('Tcl/Tk Framework') { - paths.find{|dir| - dir.strip! - dir.chomp!('/') - (tcl_hdr || FileTest.directory?(dir + "/Tcl.framework/") ) && - (tk_hdr || FileTest.directory?(dir + "/Tk.framework/") ) +# update current_configs +if update_flag || !File.exist?(config_list_file) + open(config_list_file, 'w'){|fobj| + ['with', 'enable'].each{|mode| + current_configs[mode].each_key{|key| + fobj.print("#{mode} #{key} #{current_configs[mode][key]}\n") + } } } end -tcl_framework_header = with_config("tcl-framework-header") -tk_framework_header = with_config("tk-framework-header") +if update_flag + puts "Configure options for Ruby/Tk may be updated." + puts "So, delete files which depend on old configs." + File.delete(*(Dir.glob(File.join(File.dirname(__FILE__), + "*.#{CONFIG['DLEXT']}")))) + File.delete(*(Dir.glob(File.join(File.dirname(__FILE__), "*.#{$OBJEXT}")))) + File.delete(File.join(File.dirname(__FILE__), 'Makefile')) rescue nil -tcltk_framework = find_framework(tcl_framework_header, tk_framework_header) +else + makefile = File.join(File.dirname(__FILE__),'Makefile') + if File.exist?(makefile) && + File.ctime(config_list_file) > File.ctime(makefile) + # no need to update Makefile + exit + end +end -unless is_win32 - have_library("nsl", "t_open") - have_library("socket", "socket") - have_library("dl", "dlopen") - have_library("m", "log") +############################################################## +# fuctions +############################################################## +def is_win32? + /mswin|mingw|cygwin|bccwin/ =~ RUBY_PLATFORM end -tk_idir, tk_ldir = dir_config("tk") -tcl_idir, tcl_ldir = dir_config("tcl") -x11_idir, x11_ldir = dir_config("X11") - -tk_ldir2 = with_config("tk-lib") -tcl_ldir2 = with_config("tcl-lib") -x11_ldir2 = with_config("X11-lib") - -tk_ldir_list = [tk_ldir2, tk_ldir] -tcl_ldir_list = [tcl_ldir2, tcl_ldir] - -tklib = with_config("tklib") -tcllib = with_config("tcllib") -stubs = enable_config("tcltk_stubs") || with_config("tcltk_stubs") - -tcltk_version = with_config("tcltkversion") - -use_X = with_config("X11", (! is_win32)) - -def parse_tclConfig(file) - # check tclConfig.sh/tkConfig.sh - tbl = {} - IO.foreach(file){|line| - line.strip! - next if line !~ /^([^\#=][^=]*)=(['"]|)(.*)\2$/ - key, val = $1, $3 - tbl[key] = val.gsub(/\$\{([^}]+)\}/){|s| tbl[$1]} rescue nil - } - tbl +def is_macosx? + /darwin/ =~ RUBY_PLATFORM end def check_tcltk_version(version) - return [nil, nil] unless version + return [nil, nil] unless version.kind_of? String version = version.strip tclver = version.dup tkver = version.dup - major = dot = minor = dot = plvl = ext = nil + dot = major = minor_dot = minor = plvl_dot = plvl = ext = nil if version =~ /^(\d)(\.?)(\d)(\.?)(\d*)(.*)$/ - major = $1; minor_dot = $2; minor = $3; plvl_dot = $4; plvl = $5; ext = $6 + major = $1; minor_dot = $2; minor = $3; plvl_dot = $4; plvl = $5; ext = $6 dot = ! minor_dot.empty? if plvl_dot.empty? && ! plvl.empty? minor << plvl @@ -111,12 +124,536 @@ [tclver, tkver] end +def get_shlib_versions(major = 8, minor_max = 9, minor_min = 0, ext = "") + if tclcfg = TkLib_Config["tclConfig_info"] + major = tclcfg['TCL_MAJOR_VERSION'].to_i + minor_min = tclcfg['TCL_MINOR_VERSION'].to_i + + elsif TkLib_Config["tcltkversion"] + tclver, tkver = TkLib_Config["tcltkversion"] + if tclver =~ /8\.?(\d)(.*)/ + minor_min = $1.to_i + ext = $2 + else + # unsupported version + return [""] + end + end + + # if disable-stubs, version is fixed. + minor_max = minor_min unless TkLib_Config["tcltk-stubs"] + + vers = [] + minor_max.downto(minor_min){|minor| + vers << "#{major}.#{minor}#{ext}" unless ext.empty? + vers << "#{major}.#{minor}" + } + + vers << "" +end + +def get_shlib_path_head + path_head = [] + path_dirs = [] + + if TkLib_Config["ActiveTcl"].kind_of?(String) # glob path + path_dirs.concat Dir.glob(TkLib_Config["ActiveTcl"]).sort.reverse + end + + if is_win32? + if TkLib_Config["ActiveTcl"] + path_head.concat ["c:/ActiveTcl", "c:/Program Files/ActiveTcl"] + end + path_head.concat [ + "c:/Tcl", "c:/Program Files/Tcl", + "/Tcl", "/Program Files/Tcl" + ] + path_head.each{|dir| path_dirs << "#{dir}"} + + else + [ + '/opt', '/pkg', '/share', + '/usr/local/opt', '/usr/local/pkg', '/usr/local/share', '/usr/local', + '/usr/opt', '/usr/pkg', '/usr/share', '/usr/contrib', '/usr' + ].each{|dir| + next unless File.directory?(dir) + + path_dirs << "#{dir}/lib" + path_dirs << "#{dir}" unless Dir.glob("#{dir}/lib*.*").empty? + + dirnames = [] + if TkLib_Config["ActiveTcl"] + dirnames.concat ["ActiveTcl","activeTcl","Activetcl","activetcl"] + end + dirnames.concat ["TclTk","Tcl_Tk","Tcl-Tk","tcltk","tcl_tk","tcl-tk"] + + dirnames.each{|name| + path_dirs << "#{dir}/#{name}" if File.directory?("#{dir}/#{name}") + path_head << "#{dir}/#{name}" unless Dir.glob("#{dir}/#{name}[-89_]*").empty? + } + } + end + + [path_head, path_dirs] +end + +def find_macosx_framework + use_framework = is_macosx? && TkLib_Config["ActiveTcl"] + + use_framework ||= (tcl_hdr = with_config("tcl-framework-header")) + use_framework ||= (tk_hdr = with_config("tk-framework-header")) + tcl_hdr = nil unless tcl_hdr.kind_of? String + tk_hdr = nil unless tk_hdr.kind_of? String + TkLib_Config["tcl-framework-header"] = tcl_hdr + TkLib_Config["tk-framework-header"] = tk_hdr + + use_framework ||= (tcl_dir = with_config("tcl-framework-dir")) + tcl_dir = nil unless tcl_dir.kind_of? String + if !tcl_dir && tcl_hdr + # e.g. /Library/Frameworks/Tcl.framework/Headers + # ==> /Library/Frameworks/Tcl.framework + tcl_dir = File.dirname(tcl_hdr.strip.chomp('/')) + end + TkLib_Config["tcl-framework-dir"] = tcl_dir + + use_framework ||= (tk_dir = with_config("tk-framework-dir")) + tk_dir = nil unless tk_dir.kind_of? String + if !tk_dir && tk_hdr + # e.g. /Library/Frameworks/Tk.framework/Headers + # ==> /Library/Frameworks/Tk.framework + tk_dir = File.dirname(tk_hdr.strip.chomp('/')) + end + TkLib_Config["tk-framework-dir"] = tk_dir + + if tcl_dir && !tk_dir + tk_dir = File.join(File.dirname(tcl_dir), 'Tk.framework') + TkLib_Config["tk-framework-dir"] = tk_dir + elsif !tcl_dir && tk_dir + tcl_dir = File.join(File.dirname(tk_dir), 'Tcl.framework') + TkLib_Config["tcl-framework-dir"] = tcl_dir + end + if tcl_dir && tk_dir + TkLib_Config["tcltk-framework"] = File.dirname(tcl_dir) unless TkLib_Config["tcltk-framework"] + return [tcl_dir, tk_dir] + end + + # framework is disabled? + if with_config("tcltk-framework") == false || + enable_config("tcltk-framework") == false + return false + end + + use_framework ||= (framework_dir = with_config("tcltk-framework")) + if framework_dir.kind_of? String + TkLib_Config["tcltk-framework"] = framework_dir.strip.chomp('/') + return [File.join(TkLib_Config["tcltk-framework"], 'Tcl.framework'), + File.join(TkLib_Config["tcltk-framework"], 'Tk.framework')] + end + + unless enable_config("tcltk-framework", use_framework) || + enable_config("mac-tcltk-framework", use_framework) + TkLib_Config["tcltk-framework"] = false + return false + end + + paths = [ + #"~/Library/Frameworks", + "/Library/Frameworks", + "/Network/Library/Frameworks", "/System/Library/Frameworks" + ] + + paths.map{|dir| dir.strip.chomp('/')}.each{|dir| + next unless File.directory?(tcldir = File.join(dir, "Tcl.framework")) + next unless File.directory?(tkdir = File.join(dir, "Tk.framework")) + TkLib_Config["tcltk-framework"] = dir + return [tcldir, tkdir] + } + + nil +end + +def collect_tcltk_defs(tcl_defs_str, tk_defs_str) + conflicts = [ + 'PACKAGE_NAME', 'PACKAGE_TARNAME', 'PACKAGE_VERSION', + 'PACKAGE_STRING', 'PACKAGE_BUGREPORT' + ] + + begin + # Ruby 1.9.x or later + arch_config_h = RbConfig.expand($arch_hdrdir + "/ruby/config.h") + if File.exist?(arch_config_h) + keys = [] + IO.foreach(arch_config_h){|line| + if line =~ /^#define +([^ ]+)/ + keys << $1 + end + } + conflicts = keys + end + rescue + # ignore, use default + end + + if tcl_defs_str + tcl_defs = tcl_defs_str.split(/ ?-D/).map{|s| + s =~ /^([^=]+)(.*)$/ + [$1, $2] + } + else + tcl_defs = [] + end + + if tk_defs_str + tk_defs = tk_defs_str.split(/ ?-D/).map{|s| + s =~ /^([^=]+)(.*)$/ + [$1, $2] + } + else + tk_defs = [] + end + + defs = tcl_defs | tk_defs + + defs.delete_if{|name,value| + conflicts.include?(name) || + ( (vtcl = tcl_defs.assoc(name)) && (vtk = tk_defs.assoc(name)) && + vtcl != vtk ) + } + + defs.map{|ary| s = ary.join(''); (s.strip.empty?)? "": "-D" << s}.join(' ') +end + +def parse_tclConfig(file) + # check tclConfig.sh/tkConfig.sh + tbl = Hash.new{|h,k| h[k] = ""} + return tbl unless file + IO.foreach(file){|line| + line.strip! + next if line !~ /^([^\#=][^=]*)=(['"]|)(.*)\2$/ + key, val = $1, $3 + tbl[key] = val.gsub(/\$\{([^}]+)\}/){|s| + subst = $1 + (tbl[subst])? tbl[subst]: s + } rescue nil + } + tbl +end + +def get_libpath(lib_flag, lib_spec) + # get libpath fro {TCL,Tk}_LIB_FLAG and {TCL,Tk}_LIB_SPEC + libpath = lib_spec.gsub(/(#{lib_flag}|-L)/, "").strip +end + +def search_tclConfig(*paths) # list of lib-dir or [tcl-libdir, tk-libdir] + TkLib_Config["tclConfig_paths"] = [] + config_dir = [] + + paths.compact! + + fixed_tclConfig = ! paths.empty? + + paths.each{|path| + if path.kind_of?(Array) + config_dir << path + else + dirs = Dir.glob(path) + config_dir.concat(dirs.zip(dirs)) + end + } + + if is_win32? + if TkLib_Config["ActiveTcl"] + dirs = [] + if TkLib_Config["ActiveTcl"].kind_of?(String) + dirs << TkLib_Config["ActiveTcl"] + end + dirs.concat [ + "c:/ActiveTcl*/lib", "c:/Activetcl*/lib", + "c:/activeTcl*/lib", "c:/activetcl*/lib", + "c:/Tcl*/lib", "c:/tcl*/lib", + "c:/Program Files/ActiveTcl*/lib", "c:/Program Files/Activetcl*/lib", + "c:/Program Files/activeTcl*/lib", "c:/Program Files/activetcl*/lib", + "c:/Program Files/Tcl*/lib", "c:/Program Files/tcl*/lib", + "/ActiveTcl*/lib", "/Activetcl*/lib", + "/activeTcl*/lib", "/activetcl*/lib", + "/Tcl*/lib", "/tcl*/lib", + "/Program Files/ActiveTcl*/lib", "/Program Files/Activetcl*/lib", + "/Program Files/activeTcl*/lib", "/Program Files/activetcl*/lib", + "/Program Files/Tcl*/lib", "/Program Files/tcl*/lib" + ] + else + dirs = [ + "c:/Tcl*/lib", "c:/tcl*/lib", + "c:/Program Files/Tcl*/lib", "c:/Program Files/tcl*/lib", + "/Tcl*/lib", "/tcl*/lib", + "/Program Files/Tcl*/lib", "/Program Files/tcl*/lib" + ] + end + dirs.collect{|d| Dir.glob(d)}.flatten! + dirs |= dirs + + ENV['PATH'].split(';').each{|dir| + dirs << File.expand_path(File.join(dir, '..', 'lib')) + dirs << dir + dirs << File.expand_path(File.join(dir, '..')) + } + + config_dir.concat(dirs.zip(dirs)) + + elsif framework = find_macosx_framework() + config_dir.unshift(framework) + + else + if activeTcl = TkLib_Config['ActiveTcl'] + # check latest version at first + config_dir.concat(Dir.glob(activeTcl).sort.reverse) + end + + config_dir.concat [ + RbConfig::CONFIG['libdir'], + File.join(RbConfig::CONFIG['exec_prefix'], 'lib'), + File.join(RbConfig::CONFIG['prefix'], 'lib'), + "/usr/local/opt/lib", "/usr/local/pkg/lib", "/usr/local/share/lib", + "/usr/local/lib", "/usr/opt/lib", "/usr/pkg/lib", + "/usr/share/lib", "/usr/contrib/lib", "/usr/lib" + ] + + config_dir.concat [ + '/opt', '/pkg', '/share', + '/usr/local/opt', '/usr/local/pkg', '/usr/local/share', '/usr/local', + '/usr/opt', '/usr/pkg', '/usr/share', '/usr/contrib', '/usr' + ].map{|dir| + Dir.glob(dir + '/{TclTk,tcltk,Tcl,tcl,Tk,tk}[87]*/lib') + Dir.glob(dir + '/{TclTk,tcltk,Tcl,tcl,Tk,tk}[87]*') + Dir.glob(dir + '/{TclTk,tcltk,Tcl,tcl,Tk,tk}/lib') + Dir.glob(dir + '/{TclTk,tcltk,Tcl,tcl,Tk,tk}') + }.flatten! + + ENV['PATH'].split(':').each{|dir| + config_dir << File.expand_path(File.join(dir, '..', 'lib')) + } + + # for MacOS X + #config_dir << "~/Library/Tcl" + #config_dir.concat(Dir.glob("~/Library/Tcl/*").sort.reverse) + config_dir << "/Library/Tcl" + config_dir.concat(Dir.glob("/Library/Tcl/*").sort.reverse) + config_dir << "/Network/Library/Tcl" + config_dir.concat(Dir.glob("/Network/Library/Tcl/*").sort.reverse) + config_dir << "/System/Library/Tcl" + config_dir.concat(Dir.glob("/System/Library/Tcl/*").sort.reverse) + [ + #"~/Library/Frameworks", + "/Library/Frameworks", + "/Network/Library/Frameworks", "/System/Library/Frameworks" + ].each{|framework| + config_dir << [File.expand_path(File.join(framework, 'Tcl.framework')), + File.expand_path(File.join(framework, 'Tk.framework'))] + } + end + + tclver, tkver = TkLib_Config['tcltkversion'] + conf = nil + + config_dir.map{|dir| + if dir.kind_of? Array + [dir[0].strip.chomp('/'), dir[1].strip.chomp('/')] + else + dir.strip.chomp('/') + end + }.each{|dir| + # print("check #{dir} ==>"); + if dir.kind_of? Array + tcldir, tkdir = dir + else + tcldir = tkdir = dir + end + + ['Config-shared.sh','config-shared.sh','Config.sh','config.sh'].each{|f| + tclpath = File.join(tcldir, 'tcl' << f) + tkpath = File.join(tkdir, 'tk' << f) + next if !File.exist?(tclpath) || !File.exist?(tkpath) + + # parse tclConfig.sh/tkConfig.sh + tclconf = parse_tclConfig(tclpath) + next if tclver && tclver !~ /^#{tclconf['TCL_MAJOR_VERSION']}(\.?)#{tclconf['TCL_MINOR_VERSION']}/ + tkconf = parse_tclConfig(tkpath) + next if tkver && tkver !~ /^#{tkconf['TK_MAJOR_VERSION']}(\.?)#{tkconf['TK_MINOR_VERSION']}/ + + # find tclConfig.sh & tkConfig.sh + conf = [tclconf, tkconf] unless conf + + # nativethread check + unless TkLib_Config["ruby_with_thread"] + tclconf['TCL_THREADS'] == '1' + puts "WARNIG: find #{tclpath.inspect}, but it WITH nativethread-support under ruby WITHOUT nativethread-support. So, ignore it." + TkLib_Config["tcltk-NG-path"] << File.dirname(tclpath) + next + end + + #return [tclpath, tkpath] + # print(" #{[tclpath, tkpath]}"); + TkLib_Config["tclConfig_paths"] << [tclpath, tkpath] + } + + # print("\n"); + } + + if TkLib_Config["tclConfig_paths"].empty? + [nil, nil] + else + # find tclConfig.sh and tkConfig.sh + TkLib_Config["tclConfig_info"], TkLib_Config["tkConfig_info"] = conf + TkLib_Config["tclConfig_paths"][0] + end +end + +def get_tclConfig(tclConfig_file, tclConfig_dir, tkConfig_dir) + use_tclConfig = (tclConfig_file != false) && + (tclConfig_dir != false) && (tkConfig_dir != false) + + tclConfig_file = nil unless tclConfig_file.kind_of? String + tclConfig_dir = nil unless tclConfig_dir.kind_of? String + tkConfig_dir = nil unless tkConfig_dir.kind_of? String + + unless tclConfig_dir + if tclConfig_file + tclConfig_dir = File.dirname(tclConfig_file) + elsif tkConfig_dir + tclConfig_dir = tkConfig_dir + end + end + tkConfig_dir ||= tclConfig_dir + + TkLib_Config["tclConfig-file"] = tclConfig_file + TkLib_Config["tclConfig-dir"] = tclConfig_dir + TkLib_Config["tkConfig-dir"] = tkConfig_dir + + unless use_tclConfig + puts("Don't use [tclConfig.sh, tkConfig.sh]") + else + puts("Search tclConfig.sh and tkConfig.sh.") + if tclConfig_dir + tclConfig, tkConfig = search_tclConfig([tclConfig_dir, tkConfig_dir]) + else + tclConfig, tkConfig = search_tclConfig() + end + # TclConfig_Info = TkLib_Config["tclConfig_info"] + # TkConfig_Info = TkLib_Config["tkConfig_info"] + + if tclConfig && tkConfig + puts("Use [tclConfig.sh,tkConfig.sh] == ['#{tclConfig}','#{tkConfig}']") + $LIBPATH |= [File.dirname(tclConfig)] + $LIBPATH |= [File.dirname(tkConfig)] + #TkLib_Config["tclConfig_paths"].each{|tclcfg, tkcfg| + # $LIBPATH |= [File.dirname(tclcfg)] | [File.dirname(tkcfg)] + #} + else + puts("Fail to find [tclConfig.sh, tkConfig.sh]") + end + end + + [tclConfig, tkConfig] +end + +def check_NG_path(path_list) + path_list.find_all{|path| not TkLib_Config["tcltk-NG-path"].include?(path) } +end + +def check_shlib_search_path(paths) + if !paths || paths.empty? + path_list = [] + + #if TkLib_Config["ActiveTcl"] + # path_list.concat Dir.glob(TkLib_Config["ActiveTcl"]).sort.reverse + #end + if TkLib_Config["ActiveTcl"].kind_of?(String) # glob path + path_list.concat Dir.glob(TkLib_Config["ActiveTcl"]).sort.reverse + end + + vers = get_shlib_versions + path_head, path_dirs = get_shlib_path_head + + path_list.concat vers.map{|ver| + path_head.map{|head| + if ver.empty? + head + "/lib" + else + dirs = [] + + if !Dir.glob(head + "-*").empty? + dirs << head + "-#{ver}/lib" if !Dir.glob(head + "-[89].*").empty? + dirs << head + "-#{ver.delete('.')}/lib" if !Dir.glob(head + "-[89][0-9]*").empty? + end + + if !Dir.glob(head + "[_-]*").empty? + dirs << head + "_#{ver}/lib" if !Dir.glob(head + "_[89].*").empty? + dirs << head + "-#{ver}/lib" if !Dir.glob(head + "-[89].*").empty? + dirs << head + "_#{ver.delete('.')}/lib" if !Dir.glob(head + "_[89][0-9]*").empty? + dirs << head + "-#{ver.delete('.')}/lib" if !Dir.glob(head + "-[89][0-9]*").empty? + end + + dirs + end + } + }.flatten! + + path_list.concat path_dirs + + else + # paths is a string with PATH environment style + path_list = paths.split((is_win32?)? ';': ':') + end + + path_list = check_NG_path(path_list) + + path_list.each{|path| $LIBPATH |= [path.strip] } +end + def find_tcl(tcllib, stubs, version, *opt_paths) - default_paths = ["/usr/local/lib", "/usr/pkg/lib", "/usr/lib"] - default_paths << "/Tcl/lib" # default for ActiveTcl + puts "Search Tcl library" + default_paths = [] + default_paths.concat [ + RbConfig::CONFIG['libdir'], + File.join(RbConfig::CONFIG['exec_prefix'], 'lib'), + File.join(RbConfig::CONFIG['prefix'], 'lib'), + "/usr/local/lib", "/usr/pkg/lib", "/usr/contrib/lib", "/usr/lib" + ].find_all{|dir| File.directory?(dir)} + + default_paths.concat [ + "c:/Tcl/lib", "c:/Program Files/Tcl/lib", + "/Tcl/lib", "/Program Files/Tcl/lib" + ].find_all{|dir| File.directory?(dir)} + if (paths = opt_paths.compact).empty? - paths = default_paths + if TclConfig_Info['config_file_path'] + # use definisions on tclConfig.sh + TclConfig_Info['TCL_LIB_SPEC'].sub(TclConfig_Info['TCL_LIB_FLAG'],"").strip.sub("-L","") =~ /("|'|)([^"']+)\1/ + $LIBPATH |= [$2] unless $2.empty? + + unless stubs + #*** Probably, TCL_LIBS is a subset of TK_LIBS. *** + # $LDFLAGS << ' ' << TclConfig_Info['TCL_LIBS'] + # $DLDFLAGS << ' ' << TclConfig_Info['TCL_LIBS'] + $LDFLAGS << ' ' << TclConfig_Info['TCL_LIB_SPEC'] + return true + end + + if TclConfig_Info['TCL_SUPPORTS_STUBS'] == '0' || + TclConfig_Info['TCL_STUB_LIB_SPEC'].strip.empty? + puts "#{TclConfig_Info['config_file_path']} tells us that your Tcl/Tk library doesn't support stub." + return false + else + #*** Probably, TCL_LIBS is a subset of TK_LIBS. *** + # $LDFLAGS << ' ' << TclConfig_Info['TCL_LIBS'] + # $DLDFLAGS << ' ' << TclConfig_Info['TCL_LIBS'] + $LDFLAGS << ' ' << TclConfig_Info['TCL_STUB_LIB_SPEC'] + return true + end + end + + paths = check_NG_path(default_paths) end if stubs @@ -130,7 +667,7 @@ if version && ! version.empty? versions = [version] else - versions = %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 7.6] + versions = TkLib_Config['search_versions'] end if tcllib @@ -154,12 +691,62 @@ st end +def parse_TK_LIBS(tklibs) + sfx = "lib|shlib|dll|so" + re = /(("|')[^"']+\.(#{sfx})\2|[^"' ]+\.(#{sfx})|-l("|')[^"']+\5|-l[^" ]+)/#' + + tklibs.scan(re).map{|lib,| + if lib =~ /^("|')([^"]+)\.(#{sfx})\1/ + "\"-l#{$2}\"" + elsif lib =~ /([^" ]+)\.(#{sfx})/ + "-l#{$1}" + else + lib + end + }.join(' ') +end + def find_tk(tklib, stubs, version, *opt_paths) - default_paths = ["/usr/local/lib", "/usr/pkg/lib", "/usr/lib"] - default_paths << "/Tcl/lib" # default for ActiveTcl + puts "Search Tk library" + default_paths = [] + default_paths.concat [ + RbConfig::CONFIG['libdir'], + File.join(RbConfig::CONFIG['exec_prefix'], 'lib'), + File.join(RbConfig::CONFIG['prefix'], 'lib'), + "/usr/local/lib", "/usr/pkg/lib", "/usr/contrib/lib", "/usr/lib" + ].find_all{|dir| File.directory?(dir)} + + default_paths.concat [ + "c:/Tcl/lib", "c:/Program Files/Tcl/lib", + "/Tcl/lib", "/Program Files/Tcl/lib" + ].find_all{|dir| File.directory?(dir)} + if (paths = opt_paths.compact).empty? - paths = default_paths + if TkConfig_Info['config_file_path'] + # use definisions on tkConfig.sh + TkConfig_Info['TK_LIB_SPEC'].sub(TkConfig_Info['TK_LIB_FLAG'],"").strip.sub("-L","") =~ /("|'|)([^"']+)\1/ + $LIBPATH |= [$2] unless $2.empty? + + unless stubs + $LDFLAGS << ' ' << parse_TK_LIBS(TkConfig_Info['TK_LIBS']) + # $DLDFLAGS << ' ' << parse_TK_LIBS(TkConfig_Info['TK_LIBS']) + $LDFLAGS << ' ' << TkConfig_Info['TK_LIB_SPEC'] + return true + end + + if TkConfig_Info['TK_STUB_LIB_SPEC'].strip.empty? + puts "#{TkConfig_Info['config_file_path']} tells us that your Tcl/Tk library doesn't support stub." + return false + else + $LDFLAGS << ' ' << parse_TK_LIBS(TkConfig_Info['TK_LIBS']) + # $DLDFLAGS << ' ' << parse_TK_LIBS(TkConfig_Info['TK_LIBS']) + $LDFLAGS << ' ' << TkConfig_Info['TK_STUB_LIB_SPEC'] + return true + end + end + + paths = check_NG_path(default_paths) end if stubs @@ -173,7 +760,7 @@ if version && ! version.empty? versions = [version] else - versions = %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 4.2] + versions = TkLib_Config['search_versions'] end if tklib @@ -198,38 +785,93 @@ end def find_tcltk_header(tclver, tkver) - base_dir = ['/usr/local/include', '/usr/pkg/include', '/usr/include'] - base_dir << '/Tcl/include' # default for ActiveTcl + base_dir = [] - unless have_tcl_h = have_header('tcl.h') + base_dir.concat [ + File.join(RbConfig::CONFIG['prefix'], 'include'), + "/usr/local/include", "/usr/pkg/include", "/usr/contrib/include", + "/usr/include" + ].find_all{|dir| File.directory?(dir)} + + base_dir.concat [ + "c:/Tcl/include", "c:/Program Files/Tcl/include", + "/Tcl/include", "/Program Files/Tcl/include" + ].find_all{|dir| File.directory?(dir)} + + if TclConfig_Info['TCL_INCLUDE_SPEC'] && + have_tcl_h = try_cpp('tcl.h', TclConfig_Info['TCL_INCLUDE_SPEC']) + $INCFLAGS << " " << TclConfig_Info['TCL_INCLUDE_SPEC'] + elsif have_tcl_h = have_header('tcl.h') + # find + else if tclver && ! tclver.empty? versions = [tclver] else - versions = %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 7.6] + versions = TkLib_Config['search_versions'] end paths = base_dir.dup - versions.each{|ver| paths.concat(base_dir.map{|dir| dir + '/tcl' + ver})} + versions.each{|ver| + paths.concat(base_dir.map{|dir| + [dir + '/tcl' + ver, dir + '/tcl' + ver.delete('.')] + }.flatten) + } have_tcl_h = find_header('tcl.h', *paths) end - unless have_tk_h = have_header("tk.h") + if TkConfig_Info['TK_INCLUDE_SPEC'] && + have_tk_h = try_cpp('tk.h', TclConfig_Info['TK_INCLUDE_SPEC']) + $INCFLAGS << " " << TkConfig_Info['TK_INCLUDE_SPEC'] + elsif have_tk_h = have_header('tk.h') + # find + else if tkver && ! tkver.empty? versions = [tkver] else - versions = %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 4.2] + versions = TkLib_Config['search_versions'] end paths = base_dir.dup - versions.each{|ver| paths.concat(base_dir.map{|dir| dir + '/tk' + ver})} + versions.each{|ver| + paths.concat(base_dir.map{|dir| + [dir + '/tk' + ver, dir + '/tk' + ver.delete('.')] + }.flatten) + } have_tk_h = find_header('tk.h', *paths) end have_tcl_h && have_tk_h end +def setup_for_macosx_framework + # search directory of header files + if File.exist?(dir = File.join(TkLib_Config["tcltk-framework"], + 'Tcl.framework', 'Headers')) + TclConfig_Info['TCL_INCLUDE_SPEC'] = "-I#{dir} " + TclConfig_Info['TK_INCLUDE_SPEC'] = "-I#{File.join(TkLib_Config['tcltk-framework'], 'Tk.framework', 'Headers')} " + else + dir = Dir.glob(File.join(TkLib_Config["tcltk-framework"], + 'Tcl.framework', '*', 'Headers')) + TclConfig_Info['TCL_INCLUDE_SPEC'] = "-I#{dir[0]} " unless dir.empty? + TclConfig_Info['TK_INCLUDE_SPEC'] = "-I#{Dir.glob(File.join(TkLib_Config['tcltk-framework'], 'Tk.framework', '*', 'Headers'))[0]} " + end + + $LDFLAGS << ' -framework Tk -framework Tcl' + + if TkLib_Config["tcl-framework-header"] + TclConfig_Info['TCL_INCLUDE_SPEC'] = + "-I#{TkLib_Config["tcl-framework-header"]} " + end + if TkLib_Config["tk-framework-header"] + TkConfig_Info['TK_INCLUDE_SPEC'] = + "-I#{TkLib_Config["tk-framework-header"]} " + end +end + def find_X11(*opt_paths) - default_paths = - [ "/usr/X11/lib", "/usr/lib/X11", "/usr/X11R6/lib", "/usr/openwin/lib" ] - paths = opt_paths.compact.concat(default_paths) + defaults = + [ "/usr/X11*/lib", "/usr/lib/X11*", "/usr/local/X11*", "/usr/openwin/lib" ] + paths = [] + opt_paths.compact.each{|path| paths.concat(Dir.glob(path.strip.chomp('/')))} + defaults.compact.each{|path| paths.concat(Dir.glob(path.strip.chomp('/')))} st = find_library("X11", "XOpenDisplay", *paths) unless st puts("Warning:: cannot find X11 library. tcltklib will not be compiled (tcltklib is disabled on your Ruby == Ruby/Tk will not work). Please check configure options. If your Tcl/Tk don't require X11, please try --without-X11.") @@ -237,6 +879,31 @@ st end +def search_X_libraries + if TkConfig_Info['config_file_path'] + # use definitions on tkConfig.sh + if TkConfig_Info['TK_XINCLUDES'] && TkConfig_Info['TK_XLIBSW'] && + !TkConfig_Info['TK_XINCLUDES'].strip.empty? && + !TkConfig_Info['TK_XLIBSW'].strip.empty? + use_X = true && with_config("X11", (! is_win32?)) + else + use_X = false || with_config("X11", false) + end + else + # depend on configure options + use_X = with_config("X11", (! is_win32?)) + end + + if use_X + puts("Use X11 libraries.") + x11_idir, x11_ldir = dir_config("X11") + x11_ldir2 = with_config("X11-lib") + exit unless find_X11(x11_ldir2, x11_ldir) + end + + use_X +end + def pthread_check() tcl_major_ver = nil tcl_minor_ver = nil @@ -251,42 +918,36 @@ tcl_enable_thread = nil end - if (tclConfig = with_config("tclConfig-file")) + if TclConfig_Info['config_file_path'] if tcl_enable_thread == true - puts("Warning: --with-tclConfig-file option is ignored, because --enable-tcl-thread option is given.") + puts("Warning: definiton of tclConfig.sh is ignored, because --enable-tcl-thread option is given.") elsif tcl_enable_thread == false - puts("Warning: --with-tclConfig-file option is ignored, because --disable-tcl-thread option is given.") + puts("Warning: definition of tclConfig.sh is ignored, because --disable-tcl-thread option is given.") else # tcl-thread is unknown and tclConfig.sh is given - begin - tbl = parse_tclConfig(tclConfig) - if tbl['TCL_THREADS'] - tcl_enable_thread = (tbl['TCL_THREADS'] == "1") - else - tcl_major_ver = tbl['TCL_MAJOR_VERSION'].to_i - tcl_minor_ver = tbl['TCL_MINOR_VERSION'].to_i - if tcl_major_ver < 8 || (tcl_major_ver == 8 && tcl_minor_ver == 0) - tcl_enable_thread = false - end + if TclConfig_Info['TCL_THREADS'] + tcl_enable_thread = (TclConfig_Info['TCL_THREADS'] == "1") + else + tcl_major_ver = TclConfig_Info['TCL_MAJOR_VERSION'].to_i + tcl_minor_ver = TclConfig_Info['TCL_MINOR_VERSION'].to_i + if tcl_major_ver < 8 || (tcl_major_ver == 8 && tcl_minor_ver == 0) + tcl_enable_thread = false end + end - if tcl_enable_thread == nil - # cannot find definition - if tcl_major_ver - puts("Warning: '#{tclConfig}' doesn't include TCL_THREADS definition.") - else - puts("Warning: '#{tclConfig}' may not be a tclConfig file.") - end - tclConfig = false + if tcl_enable_thread == nil + # cannot find definition + if tcl_major_ver + puts("Warning: '#{TclConfig_Info['config_file_path']}' doesn't include TCL_THREADS definition.") + else + puts("Warning: '#{TclConfig_Info['config_file_path']}' may not be a tclConfig file.") end - rescue Exception - puts("Warning: fail to read '#{tclConfig}'!! --> ignore the file") tclConfig = false end end end - if tcl_enable_thread == nil && !tclConfig + if tcl_enable_thread == nil && !TclConfig_Info['config_file_path'] # tcl-thread is unknown and tclConfig is unavailable begin try_run_available = try_run("int main() { exit(0); }") @@ -295,12 +956,12 @@ puts(%Q'\ ***************************************************************************** ** -** PTHREAD SUPPORT CHECK WARNING: +** NATIVETHREAD SUPPORT CHECK WARNING: ** -** We cannot check the consistency of pthread support between Ruby -** and the Tcl/Tk library in your environment (are you perhaps -** cross-compiling?). If pthread support for these 2 packages is -** inconsistent you may find you get errors when running Ruby/Tk +** We cannot check the consistency of nativethread support between +** Ruby and the Tcl/Tk library in your environment (are you perhaps +** cross-compiling?). If nativethread support for these 2 packages +** is inconsistent you may find you get errors when running Ruby/Tk ** (e.g. hangs or segmentation faults). We strongly recommend ** you to check the consistency manually. ** @@ -333,26 +994,27 @@ end # check pthread mode - if (macro_defined?('HAVE_NATIVETHREAD', '#include "ruby.h"')) + if (TkLib_Config["ruby_with_thread"]) # ruby -> enable unless tcl_enable_thread # ruby -> enable && tcl -> disable puts(%Q'\ ***************************************************************************** ** -** PTHREAD SUPPORT MODE WARNING: +** NATIVETHREAD SUPPORT MODE WARNING: ** -** Ruby is compiled with --enable-pthread, but your Tcl/Tk library -** seems to be compiled without pthread support. Although you can -** create the tcltklib library, this combination may cause errors -** (e.g. hangs or segmentation faults). If you have no reason to -** keep the current pthread support status, we recommend you reconfigure -** and recompile the libraries so that both or neither support pthreads. +** Ruby is compiled with --enable-pthread, but your Tcl/Tk library +** seems to be compiled without nativethread support. Although you can +** create the tcltklib library, this combination may cause errors (e.g. +** hangs or segmentation faults). If you have no reason to keep the +** current nativethread support status, we recommend you reconfigure and +** recompile the libraries so that both or neither support nativethreads. ** -** If you want change the status of pthread support, please recompile -** Ruby without "--enable-pthread" configure option or recompile Tcl/Tk -** with "--enable-threads" configure option (if your Tcl/Tk is later -** than or equal to Tcl/Tk 8.1). +** If you want change the status of nativethread support, please recompile +** Ruby without "--enable-pthread" configure option (If you use Ruby 1.9.x +** or later, you cannot remove this option, because it requires native- +** thread support.) or recompile Tcl/Tk with "--enable-threads" configure +** option (if your Tcl/Tk is later than or equal to Tcl/Tk 8.1). ** ***************************************************************************** ') @@ -374,13 +1036,13 @@ puts(%Q'\ ***************************************************************************** ** -** PTHREAD SUPPORT MODE ERROR: +** NATIVETHREAD SUPPORT MODE ERROR: ** ** Ruby is not compiled with --enable-pthread, but your Tcl/Tk -** library seems to be compiled with pthread support. This +** library seems to be compiled with nativethread support. This ** combination may cause frequent hang or segmentation fault ** errors when Ruby/Tk is working. We recommend that you NEVER -** create the library with such a combination of pthread support. +** create the library with such a combination of nativethread support. ** ** Please recompile Ruby with the "--enable-pthread" configure option ** or recompile Tcl/Tk with the "--disable-threads" configure option. @@ -397,44 +1059,132 @@ end end -tclver, tkver = check_tcltk_version(tcltk_version) +############################################################## +# main +############################################################## +# check header files +have_func("ruby_native_thread_p", "ruby.h") +have_func("rb_errinfo", "ruby.h") +have_func("rb_safe_level", "ruby.h") +have_func("rb_hash_lookup", "ruby.h") +have_func("rb_proc_new", "ruby.h") -if ( tcltk_framework || - ( find_tcltk_header(tclver, tkver) && - ( !use_X || find_X11(x11_ldir2, x11_ldir) ) && - find_tcl(tcllib, stubs, tclver, *tcl_ldir_list) && - find_tk(tklib, stubs, tkver, *tk_ldir_list) ) ) - $CPPFLAGS += ' -DUSE_TCL_STUBS -DUSE_TK_STUBS' if stubs - $CPPFLAGS += ' -D_WIN32' if /cygwin/ =~ RUBY_PLATFORM +have_struct_member("struct RArray", "ptr", "ruby.h") +have_struct_member("struct RArray", "len", "ruby.h") - if tcltk_framework - if tcl_framework_header - $CPPFLAGS += " -I#{tcl_framework_header}" - else - $CPPFLAGS += " -I#{tcltk_framework}/Tcl.framework/Headers" - end +# check libraries +unless is_win32? + have_library("nsl", "t_open") + have_library("socket", "socket") + have_library("dl", "dlopen") + have_library("m", "log") +end +$CPPFLAGS += ' -D_WIN32' if /cygwin/ =~ RUBY_PLATFORM - if tk_framework_header - $CPPFLAGS += " -I#{tk_framework_header}" - else - $CPPFLAGS += " -I#{tcltk_framework}/Tk.framework/Headers" - end +# Does ruby have nativethread ? +TkLib_Config["ruby_with_thread"] = + macro_defined?('HAVE_NATIVETHREAD', '#include "ruby.h"') - $LDFLAGS += ' -framework Tk -framework Tcl' +#--------------------------------------------------- +# check requirement of Tcl/tk version +tcltk_version = with_config("tcltkversion") +tclver, tkver = + TkLib_Config["tcltkversion"] = check_tcltk_version(tcltk_version) +puts("Specified Tcl/Tk version is #{[tclver, tkver]}") if tclver && tkver + +# use ActiveTcl ? +#if activeTcl = with_config("ActiveTcl") +if activeTcl = with_config("ActiveTcl", true) + puts("Use ActiveTcl libraries (if available).") + activeTcl = '/opt/ActiveTcl*/lib' unless activeTcl.kind_of? String +end +TkLib_Config["ActiveTcl"] = activeTcl + +# enable Tcl/Tk stubs? +=begin +if TclConfig_Info['TCL_STUB_LIB_SPEC'] && TkConfig_Info['TK_STUB_LIB_SPEC'] && + !TclConfig_Info['TCL_STUB_LIB_SPEC'].strip.empty? && + !TkConfig_Info['TK_STUB_LIB_SPEC'].strip.empty? + stubs = true + unless (st = enable_config("tcltk-stubs")).nil? + stubs &&= st end + unless (st = with_config("tcltk-stubs")).nil? + stubs &&= st + end +else + stubs = enable_config("tcltk-stubs") || with_config("tcltk-stubs") +end +=end +stubs = enable_config("tcltk-stubs") || with_config("tcltk-stubs") +if (TkLib_Config["tcltk-stubs"] = stubs) + puts("Compile with Tcl/Tk stubs.") + $CPPFLAGS += ' -DUSE_TCL_STUBS -DUSE_TK_STUBS' +end - if stubs or pthread_check - # create Makefile +# get tclConfig.sh/tkConfig.sh +TkLib_Config["tcltk-NG-path"] = [] +tclcfg, tkcfg = get_tclConfig(with_config("tclConfig-file", true), + with_config("tclConfig-dir", true), + with_config("tkConfig-dir", true)) +TclConfig_Info = TkLib_Config["tclConfig_info"] || {} +TkConfig_Info = TkLib_Config["tkConfig_info"] || {} +TclConfig_Info['config_file_path'] = tclcfg +TkConfig_Info['config_file_path'] = tkcfg - # for SUPPORT_STATUS - $INSTALLFILES ||= [] - $INSTALLFILES << ["lib/tkextlib/SUPPORT_STATUS", "$(RUBYLIBDIR)", "lib"] +# check tk_shlib_search_path +check_shlib_search_path(with_config('tk-shlib-search-path')) - have_func("rb_hash_lookup", "ruby.h") +# search X libraries +use_X = search_X_libraries - # create - $defs << %[-DRUBY_VERSION=\\"#{RUBY_VERSION}\\"] - $defs << %[-DRUBY_RELEASE_DATE=\\"#{RUBY_RELEASE_DATE}\\"] - create_makefile("tcltklib") - end +# set TCL_DEFS and TK_DEFS +# $CPPFLAGS += " #{TclConfig_Info['TCL_DEFS']}" +# $CPPFLAGS += " #{TkConfig_Info['TK_DEFS']}" +$CPPFLAGS += collect_tcltk_defs(TclConfig_Info['TCL_DEFS'], TkConfig_Info['TK_DEFS']) + +# MacOS X Frameworks? +if TkLib_Config["tcltk-framework"] + puts("Use MacOS X Frameworks.") + setup_for_macosx_framework end + +# search Tcl/Tk libraries +tk_idir, tk_ldir = dir_config("tk") if with_config('tk') +tcl_idir, tcl_ldir = dir_config("tcl") if with_config('tcl') + +tk_ldir2 = with_config("tk-lib") +tcl_ldir2 = with_config("tcl-lib") + +tk_ldir_list = [tk_ldir2, tk_ldir] +tcl_ldir_list = [tcl_ldir2, tcl_ldir] + +tklib = with_config("tklib") +tcllib = with_config("tcllib") + +TclConfig_Info['TCL_INCLUDE_SPEC'] = "-I#{tcl_idir.quote}" if tcl_idir +TkConfig_Info['TK_INCLUDE_SPEC'] = "-I#{tk_idir.quote}" if tk_idir + +#--------------------------------------------------- + +if (TkLib_Config["tcltk-framework"] || + ( find_tcltk_header(tclver, tkver) && + find_tcl(tcllib, stubs, tclver, *tcl_ldir_list) && + find_tk(tklib, stubs, tkver, *tk_ldir_list) ) ) && + (stubs || pthread_check()) + # create Makefile + + # for SUPPORT_STATUS + $INSTALLFILES ||= [] + $INSTALLFILES << ["lib/tkextlib/SUPPORT_STATUS", "$(RUBYLIBDIR)", "lib"] + + # create + $defs << %[-DRUBY_VERSION=\\"#{RUBY_VERSION}\\"] + $defs << %[-DRUBY_RELEASE_DATE=\\"#{RUBY_RELEASE_DATE}\\"] + + create_makefile("tcltklib") + + puts "Find Tcl/Tk libraries. Make tcltklib.so which needs for Ruby/Tk." +else + puts "Can't find proper Tcl/Tk libraries. So, can't make tcltklib.so which needs for Ruby/Tk." +end Index: ext/tk/README.ActiveTcl =================================================================== --- ext/tk/README.ActiveTcl (revision 23917) +++ ext/tk/README.ActiveTcl (working copy) @@ -3,9 +3,22 @@ # see # +First of all, please try to configure without any options. +"extconf.rb" searches ActiveTcl as default action. +If you have ActiveTcl and standard (or your own) Tcl/Tk on your +environment and don't want to use ActiveTcl on your Ruby/Tk, please +use --without-ActiveTcl option. + +When "extconf.rb" fails to find your ActiveTcl libraries, please try +the followings. + If you want to use ActiveTcl binary package as the Tcl/Tk libraries, please use the following configure options. + --with-ActiveTcl= + ( When without argument; no ; only '--with-ActiveTcl', + it same to '--with-ActiveTcl=/opt/ActiveTcl*/lib' ) + --with-tcl-dir= --with-tk-dir= Index: ext/tk/tkutil/tkutil.c =================================================================== --- ext/tk/tkutil/tkutil.c (revision 23917) +++ ext/tk/tkutil/tkutil.c (working copy) @@ -7,10 +7,16 @@ ************************************************/ -#define TKUTIL_RELEASE_DATE "2008-05-23" +#define TKUTIL_RELEASE_DATE "2009-07-01" #include "ruby.h" +#ifdef RUBY_VM +static VALUE rb_thread_critical; /* dummy */ +#else +/* On Ruby 1.8.x, use rb_thread_critical (defined at rubysig.h) */ +#include "rubysig.h" +#endif #ifdef HAVE_RUBY_ST_H #include "ruby/st.h" #else @@ -54,6 +60,9 @@ /*************************************/ +#if defined(HAVE_RB_OBJ_INSTANCE_EXEC) && !defined(RUBY_VM) +extern VALUE rb_obj_instance_exec _((int, VALUE*, VALUE)); +#endif static VALUE tk_s_new(argc, argv, klass) int argc; @@ -890,12 +899,15 @@ { int idx, size; volatile VALUE dst; + int thr_crit_bup; VALUE old_gc; if (argc < 2) { rb_raise(rb_eArgError, "too few arguments"); } + thr_crit_bup = rb_thread_critical; + rb_thread_critical = Qtrue; old_gc = rb_gc_disable(); for(size = 0, idx = 2; idx < argc; idx++) { @@ -920,6 +932,7 @@ } if (old_gc == Qfalse) rb_gc_enable(); + rb_thread_critical = thr_crit_bup; return rb_ary_plus(argv[0], dst); } @@ -1065,7 +1078,19 @@ rb_eArgError, 0); } +static VALUE +tcl2rb_num_or_nil(self, value) + VALUE self; + VALUE value; +{ + rb_check_type(value, T_STRING); + if (RSTRING_LEN(value) == 0) return Qnil; + + return tkstr_to_number(value); +} + + /*************************************/ #define CBSUBST_TBL_MAX (256) @@ -1590,8 +1615,12 @@ unsigned char type_chr; volatile VALUE dst = rb_ary_new2(vallen); volatile VALUE proc; + int thr_crit_bup; VALUE old_gc; + thr_crit_bup = rb_thread_critical; + rb_thread_critical = Qtrue; + old_gc = rb_gc_disable(); Data_Get_Struct(rb_const_get(self, ID_SUBST_INFO), @@ -1619,6 +1648,7 @@ } if (old_gc == Qfalse) rb_gc_enable(); + rb_thread_critical = thr_crit_bup; return dst; } @@ -1767,6 +1797,7 @@ rb_define_singleton_method(mTK, "number", tcl2rb_number, 1); rb_define_singleton_method(mTK, "string", tcl2rb_string, 1); rb_define_singleton_method(mTK, "num_or_str", tcl2rb_num_or_str, 1); + rb_define_singleton_method(mTK, "num_or_nil", tcl2rb_num_or_nil, 1); rb_define_method(mTK, "_toUTF8", tk_toUTF8, -1); rb_define_method(mTK, "_fromUTF8", tk_fromUTF8, -1); @@ -1780,6 +1811,7 @@ rb_define_method(mTK, "number", tcl2rb_number, 1); rb_define_method(mTK, "string", tcl2rb_string, 1); rb_define_method(mTK, "num_or_str", tcl2rb_num_or_str, 1); + rb_define_method(mTK, "num_or_nil", tcl2rb_num_or_nil, 1); /* --------------------- */ rb_global_variable(&ENCODING_NAME_UTF8); Index: ext/tk/MANUAL_tcltklib.eng =================================================================== --- ext/tk/MANUAL_tcltklib.eng (revision 23917) +++ ext/tk/MANUAL_tcltklib.eng (working copy) @@ -140,8 +140,7 @@ [module methods] get_version() : return an array of major, minor, release-type number, - : number, release-type name, and patchlevel of current - : Tcl/Tk library. + : and patchlevel of current Tcl/Tk library. mainloop(check_root = true) : Starts the eventloop. If 'check_root' is true, this method @@ -354,6 +353,11 @@ : to _eval and regist the command once, after that, the : command can be called by _invoke. + _cancel_eval(str) + _cancel_eval_unwind(str) + : (Tcl/Tk8.6 or later) + : Call Tcl_CancelEval() function, and cancel evaluation. + _toUTF8(str, encoding=nil) _fromUTF8(str, encoding=nil) : Call the function (which is internal function of Tcl/Tk) to