diff options
author | nagai <nagai@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2004-07-01 09:38:48 +0000 |
---|---|---|
committer | nagai <nagai@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2004-07-01 09:38:48 +0000 |
commit | b7a7c70c32ff503d9401b4d47263c5d5fa4e45d8 (patch) | |
tree | e864355f8eed303d9ca9c5fb7b3138fb19ed9c55 /ext | |
parent | ad0add9f08ad687cb1f25f3de65c398b19da7f21 (diff) |
* ext/tk/lib/tcltklib : bug fix
* ext/tk/lib/tk : bug fix and add Tcl/Tk extension support libraries
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@6559 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext')
31 files changed, 2206 insertions, 572 deletions
diff --git a/ext/tcltklib/MANIFEST b/ext/tcltklib/MANIFEST index e408dc3ee8..92a6ed642b 100644 --- a/ext/tcltklib/MANIFEST +++ b/ext/tcltklib/MANIFEST @@ -1,5 +1,6 @@ MANIFEST README.1st +README.ActiveTcl README.euc MANUAL.euc MANUAL.eng diff --git a/ext/tcltklib/extconf.rb b/ext/tcltklib/extconf.rb index 83b4a2ac31..ac48812d7a 100644 --- a/ext/tcltklib/extconf.rb +++ b/ext/tcltklib/extconf.rb @@ -5,6 +5,12 @@ require 'mkmf' is_win32 = (/mswin32|mingw|cygwin|bccwin32/ =~ RUBY_PLATFORM) is_macosx = (/darwin/ =~ RUBY_PLATFORM) +mac_need_framework = + is_macosx && + enable_config("mac-tcltk-framework", false) && + FileTest.directory?("/Library/Frameworks/Tcl.framework/") && + FileTest.directory?("/Library/Frameworks/Tk.framework/") + unless is_win32 have_library("nsl", "t_open") have_library("socket", "socket") @@ -210,7 +216,7 @@ EOF end end -if is_macosx || +if mac_need_framework || (have_header("tcl.h") && have_header("tk.h") && (is_win32 || find_library("X11", "XOpenDisplay", "/usr/X11/lib", "/usr/lib/X11", "/usr/X11R6/lib", "/usr/openwin/lib")) && @@ -219,7 +225,7 @@ if is_macosx || $CPPFLAGS += ' -DUSE_TCL_STUBS -DUSE_TK_STUBS' if stubs $CPPFLAGS += ' -D_WIN32' if /cygwin/ =~ RUBY_PLATFORM - if is_macosx + if mac_need_framework $CPPFLAGS += ' -I/Library/Frameworks/Tcl.framework/headers -I/Library/Frameworks/Tk.framework/Headers' $LDFLAGS += ' -framework Tk -framework Tcl' end diff --git a/ext/tcltklib/tcltklib.c b/ext/tcltklib/tcltklib.c index cb3826ba9f..c68fe661e9 100644 --- a/ext/tcltklib/tcltklib.c +++ b/ext/tcltklib/tcltklib.c @@ -1201,12 +1201,15 @@ ip_ruby_eval(clientData, interp, argc, argv) rb_thread_critical = thr_crit_bup; if (eclass == eTkCallbackReturn) { + ip_set_exc_message(interp, res); return TCL_RETURN; } else if (eclass == eTkCallbackBreak) { + ip_set_exc_message(interp, res); return TCL_BREAK; } else if (eclass == eTkCallbackContinue) { + ip_set_exc_message(interp, res); return TCL_CONTINUE; } else if (eclass == rb_eSystemExit) { @@ -1239,12 +1242,15 @@ ip_ruby_eval(clientData, interp, argc, argv) } if (SYM2ID(reason) == ID_return) { + ip_set_exc_message(interp, res); return TCL_RETURN; } else if (SYM2ID(reason) == ID_break) { + ip_set_exc_message(interp, res); return TCL_BREAK; } else if (SYM2ID(reason) == ID_next) { + ip_set_exc_message(interp, res); return TCL_CONTINUE; } else { @@ -1572,12 +1578,15 @@ ip_ruby_cmd(clientData, interp, argc, argv) rb_thread_critical = thr_crit_bup; if (eclass == eTkCallbackReturn) { + ip_set_exc_message(interp, res); return TCL_RETURN; } else if (eclass == eTkCallbackBreak) { + ip_set_exc_message(interp, res); return TCL_BREAK; } else if (eclass == eTkCallbackContinue) { + ip_set_exc_message(interp, res); return TCL_CONTINUE; } else if (eclass == rb_eSystemExit) { @@ -1609,12 +1618,15 @@ ip_ruby_cmd(clientData, interp, argc, argv) } if (SYM2ID(reason) == ID_return) { + ip_set_exc_message(interp, res); return TCL_RETURN; } else if (SYM2ID(reason) == ID_break) { + ip_set_exc_message(interp, res); return TCL_BREAK; } else if (SYM2ID(reason) == ID_next) { + ip_set_exc_message(interp, res); return TCL_CONTINUE; } else { diff --git a/ext/tk/MANIFEST b/ext/tk/MANIFEST index c2ac51eddc..fbba82daef 100644 --- a/ext/tk/MANIFEST +++ b/ext/tk/MANIFEST @@ -1,6 +1,7 @@ MANIFEST README.1st README.fork +ChangeLog.tkextlib extconf.rb depend tkutil.c @@ -44,6 +45,7 @@ lib/tk/font.rb lib/tk/frame.rb lib/tk/grid.rb lib/tk/image.rb +lib/tk/itemconfig.rb lib/tk/itemfont.rb lib/tk/kinput.rb lib/tk/label.rb @@ -58,6 +60,7 @@ lib/tk/mngfocus.rb lib/tk/msgcat.rb lib/tk/namespace.rb lib/tk/optiondb.rb +lib/tk/optionobj.rb lib/tk/pack.rb lib/tk/package.rb lib/tk/palette.rb @@ -87,6 +90,71 @@ lib/tk/winfo.rb lib/tk/winpkg.rb lib/tk/wm.rb lib/tk/xim.rb +lib/tkextlib/SUPPORT_STATUS +lib/tkextlib/pkg_checker.rb +lib/tkextlib/setup.rb +lib/tkextlib/ICONS.rb +lib/tkextlib/ICONS/icons.rb +lib/tkextlib/ICONS/setup.rb +lib/tkextlib/tcllib.rb +lib/tkextlib/tcllib/README +lib/tkextlib/tcllib/autoscroll.rb +lib/tkextlib/tcllib/ctext.rb +lib/tkextlib/tcllib/cursor.rb +lib/tkextlib/tcllib/datefield.rb +lib/tkextlib/tcllib/ip_entry.rb +lib/tkextlib/tcllib/plotchart.rb +lib/tkextlib/tcllib/setup.rb +lib/tkextlib/tcllib/style.rb +lib/tkextlib/tcllib/tkpiechart.rb +lib/tkextlib/tile.rb +lib/tkextlib/tile/setup.rb +lib/tkextlib/tile/style.rb +lib/tkextlib/tile/tbutton.rb +lib/tkextlib/tile/tcheckbutton.rb +lib/tkextlib/tile/tlabel.rb +lib/tkextlib/tile/tmenubutton.rb +lib/tkextlib/tile/tnotebook.rb +lib/tkextlib/tile/tradiobutton.rb +lib/tkextlib/tkDND.rb +lib/tkextlib/tkDND/setup.rb +lib/tkextlib/tkDND/shape.rb +lib/tkextlib/tkDND/tkdnd.rb +lib/tkextlib/tkHTML.rb +lib/tkextlib/tkHTML/htmlwidget.rb +lib/tkextlib/tkHTML/setup.rb +lib/tkextlib/tkimg.rb +lib/tkextlib/tkimg/README +lib/tkextlib/tkimg/bmp.rb +lib/tkextlib/tkimg/gif.rb +lib/tkextlib/tkimg/ico.rb +lib/tkextlib/tkimg/jpeg.rb +lib/tkextlib/tkimg/pcx.rb +lib/tkextlib/tkimg/pixmap.rb +lib/tkextlib/tkimg/png.rb +lib/tkextlib/tkimg/ppm.rb +lib/tkextlib/tkimg/ps.rb +lib/tkextlib/tkimg/setup.rb +lib/tkextlib/tkimg/sgi.rb +lib/tkextlib/tkimg/sun.rb +lib/tkextlib/tkimg/tga.rb +lib/tkextlib/tkimg/tiff.rb +lib/tkextlib/tkimg/window.rb +lib/tkextlib/tkimg/xbm.rb +lib/tkextlib/tkimg/xpm.rb +lib/tkextlib/tktrans.rb +lib/tkextlib/tktrans/setup.rb +lib/tkextlib/tktrans/tktrans.rb +lib/tkextlib/treectrl.rb +lib/tkextlib/treectrl/setup.rb +lib/tkextlib/treectrl/tktreectrl.rb +lib/tkextlib/vu.rb +lib/tkextlib/vu/bargraph.rb +lib/tkextlib/vu/charts.rb +lib/tkextlib/vu/dial.rb +lib/tkextlib/vu/pie.rb +lib/tkextlib/vu/setup.rb +lib/tkextlib/vu/spinbox.rb sample/binding_sample.rb sample/bindtag_sample.rb sample/binstr_usage.rb @@ -95,12 +163,13 @@ sample/encstr_usage.rb sample/iso2022-kr.txt sample/menubar1.rb sample/menubar2.rb +sample/optobj_sample.rb sample/propagate.rb +sample/remote-ip_sample.rb +sample/remote-ip_sample2.rb sample/resource.en sample/resource.ja sample/safe-tk.rb -sample/remote-ip_sample.rb -sample/remote-ip_sample2.rb sample/tkalignbox.rb sample/tkballoonhelp.rb sample/tkbiff.rb @@ -313,3 +382,100 @@ sample/msgs_tk/ja.msg sample/msgs_tk/nl.msg sample/msgs_tk/pl.msg sample/msgs_tk/ru.msg +sample/tkextlib/tcllib/datefield.rb +sample/tkextlib/tcllib/plotdemos1.rb +sample/tkextlib/tcllib/plotdemos2.rb +sample/tkextlib/tcllib/plotdemos3.rb +sample/tkextlib/tcllib/xyplot.rb +sample/tkextlib/tkHTML/README +sample/tkextlib/tkHTML/hv.rb +sample/tkextlib/tkHTML/ss.rb +sample/tkextlib/tkHTML/page1/image1 +sample/tkextlib/tkHTML/page1/image10 +sample/tkextlib/tkHTML/page1/image11 +sample/tkextlib/tkHTML/page1/image12 +sample/tkextlib/tkHTML/page1/image13 +sample/tkextlib/tkHTML/page1/image14 +sample/tkextlib/tkHTML/page1/image2 +sample/tkextlib/tkHTML/page1/image3 +sample/tkextlib/tkHTML/page1/image4 +sample/tkextlib/tkHTML/page1/image5 +sample/tkextlib/tkHTML/page1/image6 +sample/tkextlib/tkHTML/page1/image7 +sample/tkextlib/tkHTML/page1/image8 +sample/tkextlib/tkHTML/page1/image9 +sample/tkextlib/tkHTML/page1/index.html +sample/tkextlib/tkHTML/page2/image1 +sample/tkextlib/tkHTML/page2/image10 +sample/tkextlib/tkHTML/page2/image11 +sample/tkextlib/tkHTML/page2/image12 +sample/tkextlib/tkHTML/page2/image13 +sample/tkextlib/tkHTML/page2/image14 +sample/tkextlib/tkHTML/page2/image15 +sample/tkextlib/tkHTML/page2/image16 +sample/tkextlib/tkHTML/page2/image17 +sample/tkextlib/tkHTML/page2/image18 +sample/tkextlib/tkHTML/page2/image19 +sample/tkextlib/tkHTML/page2/image2 +sample/tkextlib/tkHTML/page2/image20 +sample/tkextlib/tkHTML/page2/image21 +sample/tkextlib/tkHTML/page2/image22 +sample/tkextlib/tkHTML/page2/image23 +sample/tkextlib/tkHTML/page2/image24 +sample/tkextlib/tkHTML/page2/image25 +sample/tkextlib/tkHTML/page2/image26 +sample/tkextlib/tkHTML/page2/image27 +sample/tkextlib/tkHTML/page2/image28 +sample/tkextlib/tkHTML/page2/image29 +sample/tkextlib/tkHTML/page2/image3 +sample/tkextlib/tkHTML/page2/image30 +sample/tkextlib/tkHTML/page2/image31 +sample/tkextlib/tkHTML/page2/image32 +sample/tkextlib/tkHTML/page2/image33 +sample/tkextlib/tkHTML/page2/image34 +sample/tkextlib/tkHTML/page2/image35 +sample/tkextlib/tkHTML/page2/image36 +sample/tkextlib/tkHTML/page2/image37 +sample/tkextlib/tkHTML/page2/image38 +sample/tkextlib/tkHTML/page2/image39 +sample/tkextlib/tkHTML/page2/image4 +sample/tkextlib/tkHTML/page2/image5 +sample/tkextlib/tkHTML/page2/image6 +sample/tkextlib/tkHTML/page2/image7 +sample/tkextlib/tkHTML/page2/image8 +sample/tkextlib/tkHTML/page2/image9 +sample/tkextlib/tkHTML/page2/index.html +sample/tkextlib/tkHTML/page3/image1 +sample/tkextlib/tkHTML/page3/image10 +sample/tkextlib/tkHTML/page3/image11 +sample/tkextlib/tkHTML/page3/image12 +sample/tkextlib/tkHTML/page3/image13 +sample/tkextlib/tkHTML/page3/image14 +sample/tkextlib/tkHTML/page3/image2 +sample/tkextlib/tkHTML/page3/image3 +sample/tkextlib/tkHTML/page3/image4 +sample/tkextlib/tkHTML/page3/image5 +sample/tkextlib/tkHTML/page3/image6 +sample/tkextlib/tkHTML/page3/image7 +sample/tkextlib/tkHTML/page3/image8 +sample/tkextlib/tkHTML/page3/image9 +sample/tkextlib/tkHTML/page3/index.html +sample/tkextlib/tkHTML/page4/image1 +sample/tkextlib/tkHTML/page4/image2 +sample/tkextlib/tkHTML/page4/image3 +sample/tkextlib/tkHTML/page4/image4 +sample/tkextlib/tkHTML/page4/image5 +sample/tkextlib/tkHTML/page4/image6 +sample/tkextlib/tkHTML/page4/image7 +sample/tkextlib/tkHTML/page4/image8 +sample/tkextlib/tkHTML/page4/image9 +sample/tkextlib/tkHTML/page4/index.html +sample/tkextlib/vu/README.txt +sample/tkextlib/vu/canvItems.rb +sample/tkextlib/vu/canvSticker.rb +sample/tkextlib/vu/canvSticker2.rb +sample/tkextlib/vu/dial.rb +sample/tkextlib/vu/m128_000.xbm +sample/tkextlib/vu/oscilloscope.rb +sample/tkextlib/vu/pie.rb +sample/tkextlib/vu/vu.rb diff --git a/ext/tk/README.1st b/ext/tk/README.1st index ff92fdd8a3..038528e553 100644 --- a/ext/tk/README.1st +++ b/ext/tk/README.1st @@ -1,6 +1,7 @@ If you want to use Ruby/Tk (tk.rb and so on), you must have tcltklib.so which is working collectry. If you fail to call 'require "tcltklib"', you may not have tcltklib.so. +( see also README files of tcltklib ) Even if there is a tcltklib.so on your Ruby library directry, it will not work without Tcl/Tk libraries (e.g. libtcl8.4.so) on your environment. You must also check that your Tcl/Tk is @@ -12,6 +13,7 @@ installed properly. Ruby/Tk (tk.rb など) を使いたい場合には,tcltklib.so が正しく 動いていなければなりません.もし require "tcltklib" に失敗する ようなら,tcltklib.so が存在していないのかもしれません. +( tcltklib の README ファイルも見てください ) たとえ Ruby のライブラリディレクトリに tcltklib.so が存在して いたとしても,実行環境に Tcl/Tk ライブラリ (libtcl8.4.so など) がなければ機能しません.Tcl/Tk が正しくインストールされているか diff --git a/ext/tk/lib/README b/ext/tk/lib/README index c003adb2c8..5918fe4bf0 100644 --- a/ext/tk/lib/README +++ b/ext/tk/lib/README @@ -1,6 +1,17 @@ README this file multi-tk.rb multiple Tk interpreter (included safe-Tk) support +remotei-tk.rb control remote Tk interpreter on the other process support tk.rb Tk interface + +tk/ library files construct Ruby/Tk + +tkextlib/ non-standard Tcl/Tk extension support libraries + +********************************************************************* +*** The followings exists for backward compatibility only. +*** The only thing which they work is that requires current +*** library files ( tk/*.rb ). +********************************************************************* tkafter.rb handles Tcl after tkbgerror.rb Tk error module tkcanvas.rb Tk canvas interface diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb index 8462c3064c..9cf2ac3e07 100644 --- a/ext/tk/lib/tk.rb +++ b/ext/tk/lib/tk.rb @@ -103,6 +103,8 @@ module TkComm gen_class_name = 'TkWidget_' + tk_class classname_def = "WidgetClassName = '#{tk_class}'.freeze" end + +=begin unless Object.const_defined? gen_class_name Object.class_eval "class #{gen_class_name}<#{ruby_class_name} #{classname_def} @@ -110,6 +112,21 @@ module TkComm end Object.class_eval "#{gen_class_name}.new('widgetname'=>'#{path}', 'without_creating'=>true)" +=end + base = Object + gen_class_name.split('::').each{|klass| + next if klass == '' + if base.const_defined?(klass) + base = base.class_eval klass + else + base = base.class_eval "class #{klass}<#{ruby_class_name} + #{classname_def} + end + #{klass}" + end + } + base.class_eval "#{gen_class_name}.new('widgetname'=>'#{path}', + 'without_creating'=>true)" end private :_genobj_for_tkwidget module_function :_genobj_for_tkwidget @@ -790,8 +807,8 @@ module TkComm } end end - private :install_bind, :tk_event_sequence, - :_bind_core, :_bind, :_bind_append, :_bind_remove, :_bindinfo + private :tk_event_sequence + private :_bind_core, :_bind, :_bind_append, :_bind_remove, :_bindinfo def bind(tagOrClass, context, cmd=Proc.new, args=nil) _bind(["bind", tagOrClass], context, cmd, args) @@ -1403,9 +1420,17 @@ module Tk TCL_VERSION = INTERP._invoke_without_enc("info", "tclversion").freeze TCL_PATCHLEVEL = INTERP._invoke_without_enc("info", "patchlevel").freeze + major, minor = TCL_VERSION.split('.') + TCL_MAJOR_VERSION = major.to_i + TCL_MINOR_VERSION = minor.to_i + TK_VERSION = INTERP._invoke_without_enc("set", "tk_version").freeze TK_PATCHLEVEL = INTERP._invoke_without_enc("set", "tk_patchLevel").freeze + major, minor = TK_VERSION.split('.') + TK_MAJOR_VERSION = major.to_i + TK_MINOR_VERSION = minor.to_i + JAPANIZED_TK = (INTERP._invoke_without_enc("info", "commands", "kanji") != "").freeze @@ -1888,281 +1913,500 @@ else end +module TkBindCore + def bind(context, cmd=Proc.new, args=nil) + Tk.bind(self, context, cmd, args) + end + + def bind_append(context, cmd=Proc.new, args=nil) + Tk.bind_append(self, context, cmd, args) + end + + def bind_remove(context) + Tk.bind_remove(self, context) + end + + def bindinfo(context=nil) + Tk.bindinfo(self, context) + end +end + + module TkTreatFont - def font_configinfo(name = nil) - ret = TkFont.used_on(self.path) - if ret == nil -=begin - if name - ret = name - else - ret = TkFont.init_widget_font(self.path, self.path, 'configure') - end -=end - ret = TkFont.init_widget_font(self.path, self.path, 'configure') + def __font_optkeys + ['font'] + end + private :__font_optkeys + + def __pathname + self.path + end + private :__pathname + + ################################ + + def font_configinfo(key = nil) + optkeys = __font_optkeys + if key && !optkeys.find{|opt| opt.to_s == key.to_s} + fail ArgumentError, "unknown font option name `#{key}'" + end + + win, tag = __pathname.split(':') + + if key + pathname = [win, tag, key].join(';') + TkFont.used_on(pathname) || + TkFont.init_widget_font(pathname, *__config_cmd) + elsif optkeys.size == 1 + pathname = [win, tag, optkeys[0]].join(';') + TkFont.used_on(pathname) || + TkFont.init_widget_font(pathname, *__config_cmd) + else + fonts = {} + optkeys.each{|key| + key = key.to_s + pathname = [win, tag, key].join(';') + fonts[key] = + TkFont.used_on(pathname) || + TkFont.init_widget_font(pathname, *__config_cmd) + } + fonts end - ret end alias fontobj font_configinfo def font_configure(slot) + pathname = __pathname + slot = _symbolkey2str(slot) - if slot.key?('font') - fnt = slot.delete('font') - if fnt.kind_of? TkFont - return fnt.call_font_configure(self.path, self.path,'configure',slot) - else - if fnt - if (slot.key?('kanjifont') || - slot.key?('latinfont') || - slot.key?('asciifont')) - fnt = TkFont.new(fnt) - - lfnt = slot.delete('latinfont') - lfnt = slot.delete('asciifont') if slot.key?('asciifont') - kfnt = slot.delete('kanjifont') - - fnt.latin_replace(lfnt) if lfnt - fnt.kanji_replace(kfnt) if kfnt - else - slot['font'] = fnt - tk_call(self.path, 'configure', *hash_kv(slot)) + __font_optkeys.each{|optkey| + optkey = optkey.to_s + l_optkey = 'latin' << optkey + a_optkey = 'ascii' << optkey + k_optkey = 'kanji' << optkey + + if slot.key?(optkey) + fnt = slot.delete(optkey) + if fnt.kind_of?(TkFont) + slot.delete(l_optkey) + slot.delete(a_optkey) + slot.delete(k_optkey) + + fnt.call_font_configure([pathname, optkey], *(__config_cmd << {})) + next + else + if fnt + if (slot.key?(l_optkey) || + slot.key?(a_optkey) || + slot.key?(k_optkey)) + fnt = TkFont.new(fnt) + + lfnt = slot.delete(l_optkey) + lfnt = slot.delete(a_optkey) if slot.key?(a_optkey) + kfnt = slot.delete(k_optkey) + + fnt.latin_replace(lfnt) if lfnt + fnt.kanji_replace(kfnt) if kfnt + + fnt.call_font_configure([pathname, optkey], + *(__config_cmd << {})) + next + else + tk_call(*(__config_cmd << "-#{optkey}" << fnt)) + end end + next end - return self end - end - - lfnt = slot.delete('latinfont') - lfnt = slot.delete('asciifont') if slot.key?('asciifont') - kfnt = slot.delete('kanjifont') - if lfnt && kfnt - return TkFont.new(lfnt, kfnt).call_font_configure(self.path, self.path, - 'configure', slot) - end + lfnt = slot.delete(l_optkey) + lfnt = slot.delete(a_optkey) if slot.key?(a_optkey) + kfnt = slot.delete(k_optkey) + + if lfnt && kfnt + TkFont.new(lfnt, kfnt).call_font_configure([pathname, optkey], + *(__config_cmd << {})) + elsif lfnt + latinfont_configure([lfnt, optkey]) + elsif kfnt + kanjifont_configure([kfnt, optkey]) + end + } - latinfont_configure(lfnt) if lfnt - kanjifont_configure(kfnt) if kfnt - - tk_call(self.path, 'configure', *hash_kv(slot)) if slot != {} + # configure other (without font) options + tk_call(*(__config_cmd.concat(hash_kv(slot)))) if slot != {} self end def latinfont_configure(ltn, keys=nil) - if (fobj = TkFont.used_on(self.path)) - fobj = TkFont.new(fobj) # create a new TkFont object - elsif Tk::JAPANIZED_TK - fobj = fontobj # create a new TkFont object + if ltn.kind_of?(Array) + key = ltn[1] + ltn = ltn[0] else - tk_call(self.path, 'configure', '-font', ltn) - return self + key = nil end - if fobj.kind_of?(TkFont) - if ltn.kind_of? TkFont - conf = {} - ltn.latin_configinfo.each{|key,val| conf[key] = val} - if keys - fobj.latin_configure(conf.update(keys)) + optkeys = __font_optkeys + if key && !optkeys.find{|opt| opt.to_s == key.to_s} + fail ArgumentError, "unknown font option name `#{key}'" + end + + win, tag = __pathname.split(':') + + optkeys = [key] if key + + optkeys.each{|optkey| + optkey = optkey.to_s + + pathname = [win, tag, optkey].join(';') + + if (fobj = TkFont.used_on(pathname)) + fobj = TkFont.new(fobj) # create a new TkFont object + elsif Tk::JAPANIZED_TK + fobj = fontobj # create a new TkFont object + else + tk_call(*(__config_cmd << "-#{optkey}" << ltn)) + next + end + + if fobj.kind_of?(TkFont) + if ltn.kind_of?(TkFont) + conf = {} + ltn.latin_configinfo.each{|key,val| conf[key] = val} + if keys + fobj.latin_configure(conf.update(keys)) + else + fobj.latin_configure(conf) + end else - fobj.latin_configure(conf) + fobj.latin_replace(ltn) end - else - fobj.latin_replace(ltn) end - end - return fobj.call_font_configure(self.path, self.path, 'configure', {}) + fobj.call_font_configure([pathname, optkey], *(__config_cmd << {})) + } + self end alias asciifont_configure latinfont_configure def kanjifont_configure(knj, keys=nil) - if (fobj = TkFont.used_on(self.path)) - fobj = TkFont.new(fobj) # create a new TkFont object - elsif Tk::JAPANIZED_TK - fobj = fontobj # create a new TkFont object + if knj.kind_of?(Array) + key = knj[1] + knj = knj[0] else - tk_call(self.path, 'configure', '-font', knj) - return self + key = nil + end + + optkeys = __font_optkeys + if key && !optkeys.find{|opt| opt.to_s == key.to_s} + fail ArgumentError, "unknown font option name `#{key}'" end - if fobj.kind_of?(TkFont) - if knj.kind_of? TkFont - conf = {} - knj.kanji_configinfo.each{|key,val| conf[key] = val} - if keys - fobj.kanji_configure(conf.update(keys)) + win, tag = __pathname.split(':') + + optkeys = [key] if key + + optkeys.each{|optkey| + optkey = optkey.to_s + + pathname = [win, tag, optkey].join(';') + + if (fobj = TkFont.used_on(pathname)) + fobj = TkFont.new(fobj) # create a new TkFont object + elsif Tk::JAPANIZED_TK + fobj = fontobj # create a new TkFont object + else + tk_call(*(__config_cmd << "-#{optkey}" << knj)) + next + end + + if fobj.kind_of?(TkFont) + if knj.kind_of?(TkFont) + conf = {} + knj.kanji_configinfo.each{|key,val| conf[key] = val} + if keys + fobj.kanji_configure(conf.update(keys)) + else + fobj.kanji_configure(conf) + end else - fobj.kanji_configure(conf) + fobj.kanji_replace(knj) end - else - fobj.kanji_replace(knj) end - end - return fobj.call_font_configure(self.path, self.path, 'configure', {}) + fobj.call_font_configure([pathname, optkey], *(__config_cmd << {})) + } + self end - def font_copy(window, tag=nil) - if tag - fnt = window.tagfontobj(tag).dup + def font_copy(window, wintag=nil, winkey=nil, targetkey=nil) + if wintag + if winkey + fnt = window.tagfontobj(wintag, winkey).dup + else + fnt = window.tagfontobj(wintag).dup + end else - fnt = window.fontobj.dup + if winkey + fnt = window.fontobj(winkey).dup + else + fnt = window.fontobj.dup + end + end + + if targetkey + fnt.call_font_configure([__pathname, targetkey], *(__config_cmd << {})) + else + fnt.call_font_configure(__pathname, *(__config_cmd << {})) end - fnt.call_font_configure(self.path, self.path, 'configure', {}) self end - def latinfont_copy(window, tag=nil) - fontobj.dup.call_font_configure(self.path, self.path, 'configure', {}) - if tag - fontobj.latin_replace(window.tagfontobj(tag).latin_font_id) + def latinfont_copy(window, wintag=nil, winkey=nil, targetkey=nil) + if targetkey + fontobj(targetkey).dup.call_font_configure([__pathname, targetkey], + *(__config_cmd << {})) + else + fontobj.dup.call_font_configure(__pathname, *(__config_cmd << {})) + end + + if wintag + if winkey + fontobj.latin_replace(window.tagfontobj(wintag, winkey).latin_font_id) + else + fontobj.latin_replace(window.tagfontobj(wintag).latin_font_id) + end else - fontobj.latin_replace(window.fontobj.latin_font_id) + if winkey + fontobj.latin_replace(window.fontobj(winkey).latin_font_id) + else + fontobj.latin_replace(window.fontobj.latin_font_id) + end end self end alias asciifont_copy latinfont_copy - def kanjifont_copy(window, tag=nil) - fontobj.dup.call_font_configure(self.path, self.path, 'configure', {}) - if tag - fontobj.kanji_replace(window.tagfontobj(tag).kanji_font_id) + def kanjifont_copy(window, wintag=nil, winkey=nil, targetkey=nil) + if targetkey + fontobj(targetkey).dup.call_font_configure([__pathname, targetkey], + *(__config_cmd << {})) else - fontobj.kanji_replace(window.fontobj.kanji_font_id) + fontobj.dup.call_font_configure(__pathname, *(__config_cmd << {})) + end + + if wintag + if winkey + fontobj.kanji_replace(window.tagfontobj(wintag, winkey).kanji_font_id) + else + fontobj.kanji_replace(window.tagfontobj(wintag).kanji_font_id) + end + else + if winkey + fontobj.kanji_replace(window.fontobj(winkey).kanji_font_id) + else + fontobj.kanji_replace(window.fontobj.kanji_font_id) + end end self end end -module TkBindCore - def bind(context, cmd=Proc.new, args=nil) - Tk.bind(self, context, cmd, args) - end +module TkConfigMethod + include TkUtil + include TkTreatFont - def bind_append(context, cmd=Proc.new, args=nil) - Tk.bind_append(self, context, cmd, args) + def __cget_cmd + [self.path, 'cget'] end + private :__cget_cmd - def bind_remove(context) - Tk.bind_remove(self, context) + def __config_cmd + [self.path, 'configure'] end + private :__config_cmd - def bindinfo(context=nil) - Tk.bindinfo(self, context) + def __configinfo_struct + {:key=>0, :alias=>1, :db_name=>1, :db_class=>2, + :default_value=>3, :current_value=>4} end -end + private :__configinfo_struct + def __numval_optkeys + [] + end + private :__numval_optkeys -class TkObject<TkKernel - include Tk - include TkTreatFont - include TkBindCore + def __numstrval_optkeys + [] + end + private :__numstrval_optkeys -### --> definition is moved to TkUtil module -# def path -# @path -# end + def __boolval_optkeys + [] + end + private :__boolval_optkeys - def epath - @path + def __strval_optkeys + ['text', 'label', 'show', 'data', 'file'] end + private :__strval_optkeys - def to_eval - @path + def __listval_optkeys + [] end + private :__listval_optkeys - def tk_send(cmd, *rest) - tk_call(path, cmd, *rest) + def __numlistval_optkeys + [] end - def tk_send_without_enc(cmd, *rest) - tk_call_without_enc(path, cmd, *rest) + private :__numlistval_optkeys + + def __methodcall_optkeys # { key=>method, ... } + {} end - def tk_send_with_enc(cmd, *rest) - tk_call_with_enc(path, cmd, *rest) + private :__methodcall_optkeys + + def __keyonly_optkeys # { def_key=>undef_key or nil, ... } + {} end - # private :tk_send, :tk_send_without_enc, :tk_send_with_enc + private :__keyonly_optkeys - def method_missing(id, *args) - name = id.id2name - case args.length - when 1 - if name[-1] == ?= - configure name[0..-2], args[0] + def __conv_keyonly_opts(keys) + return keys unless keys.kind_of?(Hash) + keyonly = __keyonly_optkeys + keys2 = {} + keys.each{|k, v| + optkey = keyonly.find{|kk,vv| kk.to_s == k.to_s} + if optkey + defkey, undefkey = optkey + if v + keys2[defkey.to_s] = None + elsif undefkey + keys2[undefkey.to_s] = None + else + # remove key + end else - configure name, args[0] + keys2[k.to_s] = v end - when 0 - begin - cget(name) - rescue - fail NameError, - "undefined local variable or method `#{name}' for #{self.to_s}", - error_at - end - else - fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at - end + } + keys2 end - def [](id) - cget(id) + def config_hash_kv(keys, enc_mode = nil, conf = nil) + hash_kv(__conv_keyonly_opts(keys), enc_mode, conf) end - def []=(id, val) - configure(id, val) - val - end + ################################ def cget(slot) - case slot.to_s - when 'text', 'label', 'show', 'data', 'file' - #tk_call(path, 'cget', "-#{slot}") - _fromUTF8(tk_call_without_enc(path, 'cget', "-#{slot}")) - when 'font', 'kanjifont' - #fnt = tk_tcl2ruby(tk_call(path, 'cget', "-#{slot}")) - #fnt = tk_tcl2ruby(tk_call(path, 'cget', "-font")) - fnt = tk_tcl2ruby(tk_call_without_enc(path, 'cget', "-font"), true) + slot = slot.to_s + + if ( method = _symbolkey2str(__methodcall_optkeys)[slot] ) + return self.__send__(method) + end + + case slot + when /^(#{__numval_optkeys.join('|')})$/ + begin + number(tk_call_without_enc(*(__cget_cmd << "-#{slot}"))) + rescue + nil + end + + when /^(#{__numstrval_optkeys.join('|')})$/ + num_or_str(tk_call_without_enc(*(__cget_cmd << "-#{slot}"))) + + when /^(#{__boolval_optkeys.join('|')})$/ + begin + bool(tk_call_without_enc(*(__cget_cmd << "-#{slot}"))) + rescue + nil + end + + when /^(#{__listval_optkeys.join('|')})$/ + simplelist(tk_call_without_enc(*(__cget_cmd << "-#{slot}"))) + + when /^(#{__numlistval_optkeys.join('|')})$/ + conf = tk_call_without_enc(*(__cget_cmd << "-#{slot}")) + if conf =~ /^[0-9+-]/ + list(conf) + else + conf + end + + when /^(#{__strval_optkeys.join('|')})$/ + _fromUTF8(tk_call_without_enc(*(__cget_cmd << "-#{slot}"))) + + when /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/ + fontcode = $1 + fontkey = $2 + fnt = tk_tcl2ruby(tk_call_without_enc(*(__cget_cmd << "-#{fontkey}")), true) unless fnt.kind_of?(TkFont) - fnt = fontobj(fnt) + fnt = fontobj(fontkey) end - if slot == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/ + if fontcode == 'kanji' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/ # obsolete; just for compatibility fnt.kanji_font else fnt end + else - tk_tcl2ruby(tk_call_without_enc(path, 'cget', "-#{slot}"), true) + tk_tcl2ruby(tk_call_without_enc(*(__cget_cmd << "-#{slot}")), true) end end def configure(slot, value=None) if slot.kind_of? Hash - if (slot['font'] || slot[:font] || - slot['kanjifont'] || slot[:kanjifont] || - slot['latinfont'] || slot[:latinfont] || - slot['asciifont'] || slot[:asciifont] ) + slot = _symbolkey2str(slot) + + __methodcall_optkeys.each{|key, method| + value = slot.delete(key.to_s) + self.__send__(method, value) if value + } + + __keyonly_optkeys.each{|defkey, undefkey| + conf = slot.find{|kk, vv| kk == defkey.to_s} + if conf + k, v = conf + if v + slot[k] = None + else + slot[undefkey.to_s] = None if undefkey + slot.delete(k) + end + end + } + + if (slot.find{|k, v| k =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/}) font_configure(slot) elsif slot.size > 0 - tk_call(path, 'configure', *hash_kv(slot)) + tk_call(*(__config_cmd.concat(hash_kv(slot)))) end else - if (slot == 'font' || slot == :font || - slot == 'kanjifont' || slot == :kanjifont || - slot == 'latinfont' || slot == :latinfont || - slot == 'asciifont' || slot == :asciifont ) + slot = slot.to_s + if ( conf = __keyonly_optkeys.find{|k, v| k.to_s == slot} ) + defkey, undefkey = conf + if value + tk_call(*(__config_cmd << "-#{defkey}")) + elsif undefkey + tk_call(*(__config_cmd << "-#{undefkey}")) + end + elsif ( method = _symbolkey2str(__methodcall_optkeys)[slot] ) + self.__send__(method, value) + elsif (slot =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/) if value == None - fontobj + fontobj($2) else font_configure({slot=>value}) end else - tk_call(path, 'configure', "-#{slot}", value) + tk_call(*(__config_cmd << "-#{slot}" << value)) end end self @@ -2174,110 +2418,528 @@ class TkObject<TkKernel def configinfo(slot = nil) if TkComm::GET_CONFIGINFO_AS_ARRAY - if slot == 'font' || slot == :font || - slot == 'kanjifont' || slot == :kanjifont - conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('configure', "-#{slot}"))) - conf[0] = conf[0][1..-1] - conf[4] = fontobj(conf[4]) + if (slot.to_s =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/) + fontkey = $2 + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{fontkey}")))) + conf[__configinfo_struct[:key]] = + conf[__configinfo_struct[:key]][1..-1] + if ( ! __configinfo_struct[:alias] \ + || conf.size > __configinfo_struct[:alias] + 1 ) + conf[__configinfo_struct[:current_value]] = fontobj(fontkey) + elsif ( __configinfo_struct[:alias] \ + && conf.size == __configinfo_struct[:alias] + 1 \ + && conf[__configinfo_struct[:alias]][0] == ?- ) + conf[__configinfo_struct[:alias]] = + conf[__configinfo_struct[:alias]][1..-1] + end conf else if slot - case slot.to_s - when 'text', 'label', 'show', 'data', 'file' - conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('configure', "-#{slot}"))) + slot = slot.to_s + case slot + when /^(#{__methodcall_optkeys.keys.join('|')})$/ + method = _symbolkey2str(__methodcall_optkeys)[slot] + return [slot, '', '', '', self.__send__(method)] + + when /^(#{__numval_optkeys.join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]]) + begin + conf[__configinfo_struct[:default_value]] = + number(conf[__configinfo_struct[:default_value]]) + rescue + conf[__configinfo_struct[:default_value]] = nil + end + end + if ( conf[__configinfo_struct[:current_value]] ) + begin + conf[__configinfo_struct[:current_value]] = + number(conf[__configinfo_struct[:current_value]]) + rescue + conf[__configinfo_struct[:current_value]] = nil + end + end + + when /^(#{__numstrval_optkeys.join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]]) + conf[__configinfo_struct[:default_value]] = + num_or_str(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] ) + conf[__configinfo_struct[:current_value]] = + num_or_str(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__boolval_optkeys.join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]]) + begin + conf[__configinfo_struct[:default_value]] = + bool(conf[__configinfo_struct[:default_value]]) + rescue + conf[__configinfo_struct[:default_value]] = nil + end + end + if ( conf[__configinfo_struct[:current_value]] ) + begin + conf[__configinfo_struct[:current_value]] = + bool(conf[__configinfo_struct[:current_value]]) + rescue + conf[__configinfo_struct[:current_value]] = nil + end + end + + when /^(#{__listval_optkeys.join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]]) + conf[__configinfo_struct[:default_value]] = + simplelist(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] ) + conf[__configinfo_struct[:current_value]] = + simplelist(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__numlistval_optkeys.join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] \ + && conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ ) + conf[__configinfo_struct[:default_value]] = + list(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] \ + && conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ ) + conf[__configinfo_struct[:current_value]] = + list(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__strval_optkeys.join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) else - conf = tk_split_list(_fromUTF8(tk_send_without_enc('configure', "-#{slot}"))) + conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) + end + conf[__configinfo_struct[:key]] = + conf[__configinfo_struct[:key]][1..-1] + + if ( __configinfo_struct[:alias] \ + && conf.size == __configinfo_struct[:alias] + 1 \ + && conf[__configinfo_struct[:alias]][0] == ?- ) + conf[__configinfo_struct[:alias]] = + conf[__configinfo_struct[:alias]][1..-1] end - conf[0] = conf[0][1..-1] + conf + else - ret = tk_split_simplelist(_fromUTF8(tk_send_without_enc('configure'))).collect{|conflist| + ret = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*__config_cmd))).collect{|conflist| conf = tk_split_simplelist(conflist) - conf[0] = conf[0][1..-1] - case conf[0] - when 'text', 'label', 'show', 'data', 'file' + conf[__configinfo_struct[:key]] = + conf[__configinfo_struct[:key]][1..-1] + + case conf[__configinfo_struct[:key]] + when /^(#{__strval_optkeys.join('|')})$/ + # do nothing + + when /^(#{__numval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + begin + conf[__configinfo_struct[:default_value]] = + number(conf[__configinfo_struct[:default_value]]) + rescue + conf[__configinfo_struct[:default_value]] = nil + end + end + if ( conf[__configinfo_struct[:current_value]] ) + begin + conf[__configinfo_struct[:current_value]] = + number(conf[__configinfo_struct[:current_value]]) + rescue + conf[__configinfo_struct[:current_value]] = nil + end + end + + when /^(#{__numstrval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + conf[__configinfo_struct[:default_value]] = + num_or_str(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] ) + conf[__configinfo_struct[:current_value]] = + num_or_str(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__boolval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + begin + conf[__configinfo_struct[:default_value]] = + bool(conf[__configinfo_struct[:default_value]]) + rescue + conf[__configinfo_struct[:default_value]] = nil + end + end + if ( conf[__configinfo_struct[:current_value]] ) + begin + conf[__configinfo_struct[:current_value]] = + bool(conf[__configinfo_struct[:current_value]]) + rescue + conf[__configinfo_struct[:current_value]] = nil + end + end + + when /^(#{__listval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + conf[__configinfo_struct[:default_value]] = + simplelist(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] ) + conf[__configinfo_struct[:current_value]] = + simplelist(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__numlistval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] \ + && conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ ) + conf[__configinfo_struct[:default_value]] = + list(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] \ + && conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ ) + conf[__configinfo_struct[:current_value]] = + list(conf[__configinfo_struct[:current_value]]) + end + else - if conf[3] - if conf[3].index('{') - conf[3] = tk_split_list(conf[3]) + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + if conf[__configinfo_struct[:default_value]].index('{') + conf[__configinfo_struct[:default_value]] = + tk_split_list(conf[__configinfo_struct[:default_value]]) else - conf[3] = tk_tcl2ruby(conf[3]) + conf[__configinfo_struct[:default_value]] = + tk_tcl2ruby(conf[__configinfo_struct[:default_value]]) end end - if conf[4] - if conf[4].index('{') - conf[4] = tk_split_list(conf[4]) + if conf[__configinfo_struct[:current_value]] + if conf[__configinfo_struct[:current_value]].index('{') + conf[__configinfo_struct[:current_value]] = + tk_split_list(conf[__configinfo_struct[:current_value]]) else - conf[4] = tk_tcl2ruby(conf[4]) + conf[__configinfo_struct[:current_value]] = + tk_tcl2ruby(conf[__configinfo_struct[:current_value]]) end end end - conf[1] = conf[1][1..-1] if conf.size == 2 # alias info + + if ( __configinfo_struct[:alias] \ + && conf.size == __configinfo_struct[:alias] + 1 \ + && conf[__configinfo_struct[:alias]][0] == ?- ) + conf[__configinfo_struct[:alias]] = + conf[__configinfo_struct[:alias]][1..-1] + end + conf } - fontconf = ret.assoc('font') - if fontconf - ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'} - fontconf[4] = fontobj(fontconf[4]) - ret.push(fontconf) - else - ret - end + + __font_optkeys.each{|optkey| + optkey = optkey.to_s + fontconf = ret.assoc(optkey) + if fontconf && fontconf.size > 2 + ret.delete_if{|inf| inf[0] =~ /^(|latin|ascii|kanji)#{optkey}$/} + fontconf[__configinfo_struct[:current_value]] = fontobj(optkey) + ret.push(fontconf) + end + } + + __methodcall_optkeys.each{|optkey, method| + ret << [optkey.to_s, '', '', '', self.__send__(method)] + } + + ret end end + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY - if slot == 'font' || slot == :font || - slot == 'kanjifont' || slot == :kanjifont - conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('configure', "-#{slot}"))) - key = conf.shift[1..-1] - conf[3] = fontobj(conf[3]) - { key => conf } + if (slot.to_s =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/) + fontkey = $2 + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{fontkey}")))) + conf[__configinfo_struct[:key]] = + conf[__configinfo_struct[:key]][1..-1] + + if ( ! __configinfo_struct[:alias] \ + || conf.size > __configinfo_struct[:alias] + 1 ) + conf[__configinfo_struct[:current_value]] = fontobj(fontkey) + { conf.shift => conf } + elsif ( __configinfo_struct[:alias] \ + && conf.size == __configinfo_struct[:alias] + 1 ) + if conf[__configinfo_struct[:alias]][0] == ?- + conf[__configinfo_struct[:alias]] = + conf[__configinfo_struct[:alias]][1..-1] + end + { conf[0] => conf[1] } + else + { conf.shift => conf } + end else if slot - case slot.to_s - when 'text', 'label', 'show', 'data', 'file' - conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('configure', "-#{slot}"))) + slot = slot.to_s + case slot + when /^(#{__methodcall_optkeys.keys.join('|')})$/ + method = _symbolkey2str(__methodcall_optkeys)[slot] + return {slot => ['', '', '', self.__send__(method)]} + + when /^(#{__numval_optkeys.join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + begin + conf[__configinfo_struct[:default_value]] = + number(conf[__configinfo_struct[:default_value]]) + rescue + conf[__configinfo_struct[:default_value]] = nil + end + end + if ( conf[__configinfo_struct[:current_value]] ) + begin + conf[__configinfo_struct[:current_value]] = + number(conf[__configinfo_struct[:current_value]]) + rescue + conf[__configinfo_struct[:current_value]] = nil + end + end + + when /^(#{__numstrval_optkeys.join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + conf[__configinfo_struct[:default_value]] = + num_or_str(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] ) + conf[__configinfo_struct[:current_value]] = + num_or_str(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__boolval_optkeys.join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + begin + conf[__configinfo_struct[:default_value]] = + bool(conf[__configinfo_struct[:default_value]]) + rescue + conf[__configinfo_struct[:default_value]] = nil + end + end + if ( conf[__configinfo_struct[:current_value]] ) + begin + conf[__configinfo_struct[:current_value]] = + bool(conf[__configinfo_struct[:current_value]]) + rescue + conf[__configinfo_struct[:current_value]] = nil + end + end + + when /^(#{__listval_optkeys.join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + conf[__configinfo_struct[:default_value]] = + simplelist(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] ) + conf[__configinfo_struct[:current_value]] = + simplelist(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__numlistval_optkeys.join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] \ + && conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ ) + conf[__configinfo_struct[:default_value]] = + list(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] \ + && conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ ) + conf[__configinfo_struct[:current_value]] = + list(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__strval_optkeys.join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) else - conf = tk_split_list(_fromUTF8(tk_send_without_enc('configure', "-#{slot}"))) + conf = tk_split_list(_fromUTF8(tk_send_without_enc(*(__config_cmd << "-#{slot}")))) end - key = conf.shift[1..-1] - { key => conf } + conf[__configinfo_struct[:key]] = + conf[__configinfo_struct[:key]][1..-1] + + if ( __configinfo_struct[:alias] \ + && conf.size == __configinfo_struct[:alias] + 1 ) + if conf[__configinfo_struct[:alias]][0] == ?- + conf[__configinfo_struct[:alias]] = + conf[__configinfo_struct[:alias]][1..-1] + end + { conf[0] => conf[1] } + else + { conf.shift => conf } + end + else ret = {} - tk_split_simplelist(_fromUTF8(tk_send_without_enc('configure'))).each{|conflist| + tk_split_simplelist(_fromUTF8(tk_call_without_enc(*__config_cmd))).each{|conflist| conf = tk_split_simplelist(conflist) - key = conf.shift[1..-1] - case key - when 'text', 'label', 'show', 'data', 'file' + conf[__configinfo_struct[:key]] = + conf[__configinfo_struct[:key]][1..-1] + + case conf[__configinfo_struct[:key]] + when /^(#{__strval_optkeys.join('|')})$/ + # do nothing + + when /^(#{__numval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + begin + conf[__configinfo_struct[:default_value]] = + number(conf[__configinfo_struct[:default_value]]) + rescue + conf[__configinfo_struct[:default_value]] = nil + end + end + if ( conf[__configinfo_struct[:current_value]] ) + begin + conf[__configinfo_struct[:current_value]] = + number(conf[__configinfo_struct[:current_value]]) + rescue + conf[__configinfo_struct[:current_value]] = nil + end + end + + when /^(#{__numstrval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + conf[__configinfo_struct[:default_value]] = + num_or_str(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] ) + conf[__configinfo_struct[:current_value]] = + num_or_str(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__boolval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + begin + conf[__configinfo_struct[:default_value]] = + bool(conf[__configinfo_struct[:default_value]]) + rescue + conf[__configinfo_struct[:default_value]] = nil + end + end + if ( conf[__configinfo_struct[:current_value]] ) + begin + conf[__configinfo_struct[:current_value]] = + bool(conf[__configinfo_struct[:current_value]]) + rescue + conf[__configinfo_struct[:current_value]] = nil + end + end + + when /^(#{__listval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + conf[__configinfo_struct[:default_value]] = + simplelist(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] ) + conf[__configinfo_struct[:current_value]] = + simplelist(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__numlistval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] \ + && conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ ) + conf[__configinfo_struct[:default_value]] = + list(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] \ + && conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ ) + conf[__configinfo_struct[:current_value]] = + list(conf[__configinfo_struct[:current_value]]) + end + else - if conf[2] - if conf[2].index('{') - conf[2] = tk_split_list(conf[2]) + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + if conf[__configinfo_struct[:default_value]].index('{') + conf[__configinfo_struct[:default_value]] = + tk_split_list(conf[__configinfo_struct[:default_value]]) else - conf[2] = tk_tcl2ruby(conf[2]) + conf[__configinfo_struct[:default_value]] = + tk_tcl2ruby(conf[__configinfo_struct[:default_value]]) end end - if conf[3] - if conf[3].index('{') - conf[3] = tk_split_list(conf[3]) + if conf[__configinfo_struct[:current_value]] + if conf[__configinfo_struct[:current_value]].index('{') + conf[__configinfo_struct[:current_value]] = + tk_split_list(conf[__configinfo_struct[:current_value]]) else - conf[3] = tk_tcl2ruby(conf[3]) + conf[__configinfo_struct[:current_value]] = + tk_tcl2ruby(conf[__configinfo_struct[:current_value]]) end end end - if conf.size == 1 - ret[key] = conf[0][1..-1] # alias info + + if ( __configinfo_struct[:alias] \ + && conf.size == __configinfo_struct[:alias] + 1 ) + if conf[__configinfo_struct[:alias]][0] == ?- + conf[__configinfo_struct[:alias]] = + conf[__configinfo_struct[:alias]][1..-1] + end + ret[conf[0]] = conf[1] else - ret[key] = conf + ret[conf.shift] = conf end } - fontconf = ret['font'] - if fontconf - ret.delete('font') - ret.delete('kanjifont') - fontconf[3] = fontobj(fontconf[3]) - ret['font'] = fontconf - end + + __font_optkeys.each{|optkey| + optkey = optkey.to_s + fontconf = ret[optkey] + if fontconf.kind_of?(Array) + ret.delete(optkey) + ret.delete('latin' << optkey) + ret.delete('ascii' << optkey) + ret.delete('kanji' << optkey) + fontconf[__configinfo_struct[:current_value]] = fontobj(optkey) + ret[optkey] = fontconf + end + } + + __methodcall_optkeys.each{|optkey, method| + ret[optkey.to_s] = ['', '', '', self.__send__(method)] + } + ret end end @@ -2287,12 +2949,24 @@ class TkObject<TkKernel def current_configinfo(slot = nil) if TkComm::GET_CONFIGINFO_AS_ARRAY if slot - conf = configinfo(slot) - {conf[0] => conf[4]} + org_slot = slot + begin + conf = configinfo(slot) + if ( ! __configinfo_struct[:alias] \ + || conf.size > __configinfo_struct[:alias] + 1 ) + return {conf[0] => conf[-1]} + end + slot = conf[__configinfo_struct[:alias]] + end while(org_slot != slot) + fail RuntimeError, + "there is a configure alias loop about '#{org_slot}'" else ret = {} configinfo().each{|conf| - ret[conf[0]] = conf[4] if conf.size > 2 + if ( ! __configinfo_struct[:alias] \ + || conf.size > __configinfo_struct[:alias] + 1 ) + ret[conf[0]] = conf[-1] + end } ret end @@ -2304,6 +2978,67 @@ class TkObject<TkKernel ret end end +end + +class TkObject<TkKernel + include Tk + include TkConfigMethod + include TkBindCore + +### --> definition is moved to TkUtil module +# def path +# @path +# end + + def epath + @path + end + + def to_eval + @path + end + + def tk_send(cmd, *rest) + tk_call(path, cmd, *rest) + end + def tk_send_without_enc(cmd, *rest) + tk_call_without_enc(path, cmd, *rest) + end + def tk_send_with_enc(cmd, *rest) + tk_call_with_enc(path, cmd, *rest) + end + # private :tk_send, :tk_send_without_enc, :tk_send_with_enc + + def method_missing(id, *args) + name = id.id2name + case args.length + when 1 + if name[-1] == ?= + configure name[0..-2], args[0] + else + configure name, args[0] + end + when 0 + begin + cget(name) + rescue + fail NameError, + "undefined local variable or method `#{name}' for #{self.to_s}", + error_at + end + else + fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at + end + end + + def [](id) + cget(id) + end + + def []=(id, val) + configure(id, val) + val + end def event_generate(context, keys=nil) if keys @@ -2337,7 +3072,12 @@ class TkWindow<TkObject include TkWinfo extend TkBindCore + TkCommandNames = [].freeze + ## ==> If TkCommandNames[0] is a string (not a null string), + ## assume the string is a Tcl/Tk's create command of the widget class. WidgetClassName = ''.freeze + # WidgetClassNames[WidgetClassName] = self + ## ==> If self is a widget class, entry to the WidgetClassNames table. def self.to_eval self::WidgetClassName end @@ -2375,22 +3115,56 @@ class TkWindow<TkObject else p 'create_self has args' if $DEBUG fontkeys = {} + methodkeys = {} if keys - ['font', 'kanjifont', 'latinfont', 'asciifont'].each{|key| - fontkeys[key] = keys.delete(key) if keys.key?(key) - } + #['font', 'kanjifont', 'latinfont', 'asciifont'].each{|key| + # fontkeys[key] = keys.delete(key) if keys.key?(key) + #} + __font_optkeys.each{|key| + fkey = key.to_s + fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) + + fkey = "kanji#{key}" + fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) + + fkey = "latin#{key}" + fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) + + fkey = "ascii#{key}" + fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) + } + + __methodcall_optkeys.each{|key| + key = key.to_s + methodkeys[key] = keys.delete(key) if keys.key?(key) + } end if without_creating && keys - configure(keys) + #configure(keys) + configure(__conv_keyonly_opts(keys)) else - create_self(keys) + #create_self(keys) + create_self(__conv_keyonly_opts(keys)) end font_configure(fontkeys) unless fontkeys.empty? + configure(methodkeys) unless methodkeys.empty? end end - def create_self - fail RuntimeError, "TkWindow is an abstract class" + def create_self(keys) + # may need to override + begin + cmd = self.class::TkCommandNames[0] + fail unless (cmd.kind_of?(String) && cmd.length > 0) + rescue + fail RuntimeError, "class #{self.class} may be an abstract class" + end + + if keys and keys != None + tk_call_without_enc(cmd, @path, *hash_kv(keys, true)) + else + tk_call_without_enc(cmd, @path) + end end private :create_self @@ -2912,3 +3686,11 @@ module Tk autoload :LIBRARY_PATH, 'tk/variable' autoload :TCL_PRECISION, 'tk/variable' end + + +# call setup script for Tk extension libraries (base configuration) +begin + require 'tkextlib/setup.rb' +rescue LoadError + # ignore +end diff --git a/ext/tk/lib/tk/autoload.rb b/ext/tk/lib/tk/autoload.rb index 0a8251af8b..e3c29e96ea 100644 --- a/ext/tk/lib/tk/autoload.rb +++ b/ext/tk/lib/tk/autoload.rb @@ -63,6 +63,8 @@ autoload :TkImage, 'tk/image' autoload :TkBitmapImage, 'tk/image' autoload :TkPhotoImage, 'tk/image' +autoload :TkItemConfigMethod, 'tk/itemconfig' + autoload :TkTreatItemFont, 'tk/itemfont' autoload :TkKinput, 'tk/kinput' @@ -150,6 +152,7 @@ autoload :TkToplevel, 'tk/toplevel' autoload :TkTextWin, 'tk/txtwin_abst' autoload :TkValidation, 'tk/validation' + autoload :TkVariable, 'tk/variable' autoload :TkVarAccess, 'tk/variable' @@ -167,9 +170,13 @@ autoload :TkXIM, 'tk/xim' # sub-module of Tk module Tk autoload :Clock, 'tk/clock' + autoload :OptionObj, 'tk/optionobj' autoload :Scrollable, 'tk/scrollable' autoload :Wm, 'tk/wm' + autoload :ValidateConfigure, 'tk/validation' + autoload :ItemValidateConfigure, 'tk/validation' + autoload :EncodedString, 'tk/encodedstr' def Tk.EncodedString(str, enc = nil); Tk::EncodedString.new(str, enc); end diff --git a/ext/tk/lib/tk/canvas.rb b/ext/tk/lib/tk/canvas.rb index b311db6e20..17a05c0ce1 100644 --- a/ext/tk/lib/tk/canvas.rb +++ b/ext/tk/lib/tk/canvas.rb @@ -7,16 +7,16 @@ # require 'tk' require 'tk/canvastag' -require 'tk/itemfont' +require 'tk/itemconfig' require 'tk/scrollable' -module TkTreatCItemFont - include TkTreatItemFont +module TkCanvasItemConfig + include TkItemConfigMethod - ItemCMD = ['itemconfigure'.freeze, TkComm::None].freeze - def __conf_cmd(idx) - ItemCMD[idx] + def __item_methodcall_optkeys(id) + {'coords'=>'coords'} end + private :__item_methodcall_optkeys def __item_pathname(tagOrId) if tagOrId.kind_of?(TkcItem) || tagOrId.kind_of?(TkcTag) @@ -25,12 +25,11 @@ module TkTreatCItemFont self.path + ';' + tagOrId.to_s end end - - private :__conf_cmd, :__item_pathname + private :__item_pathname end class TkCanvas<TkWindow - include TkTreatCItemFont + include TkCanvasItemConfig include Scrollable TkCommandNames = ['canvas'.freeze].freeze @@ -130,6 +129,7 @@ class TkCanvas<TkWindow tk_split_list(tk_send_without_enc('coords', tagid(tag))) else tk_send_without_enc('coords', tagid(tag), *(args.flatten)) + self end end @@ -217,6 +217,7 @@ class TkCanvas<TkWindow self end +=begin def itemcget(tagOrId, option) case option.to_s when 'dash', 'activedash', 'disableddash' @@ -453,6 +454,7 @@ class TkCanvas<TkWindow ret end end +=end def lower(tag, below=nil) if below @@ -523,6 +525,8 @@ end class TkcItem<TkObject extend Tk include TkcTagAccess + extend TkItemFontOptkeys + extend TkItemConfigOptkeys CItemTypeName = nil CItemTypeToClass = {} @@ -543,6 +547,7 @@ class TkcItem<TkObject ######################################## def self._parse_create_args(args) fontkeys = {} + methodkeys = {} if args[-1].kind_of? Hash keys = _symbolkey2str(args.pop) if args.size == 0 @@ -552,11 +557,30 @@ class TkcItem<TkObject end end - ['font', 'kanjifont', 'latinfont', 'asciifont'].each{|key| - fontkeys[key] = keys.delete(key) if keys.key?(key) + #['font', 'kanjifont', 'latinfont', 'asciifont'].each{|key| + # fontkeys[key] = keys.delete(key) if keys.key?(key) + #} + __item_font_optkeys(nil).each{|key| + fkey = key.to_s + fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) + + fkey = "kanji#{key}" + fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) + + fkey = "latin#{key}" + fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) + + fkey = "ascii#{key}" + fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) } - args = args.flatten.concat(hash_kv(keys)) + __item_methodcall_optkeys(nil).each{|key| + key = key.to_s + methodkeys[key] = keys.delete(key) if keys.key?(key) + } + + #args = args.flatten.concat(hash_kv(keys)) + args = args.flatten.concat(itemconfig_hash_kv(nil, keys)) else args = args.flatten end @@ -597,6 +621,14 @@ class TkcItem<TkObject @id end + def exist? + if @c.find_withtag(@id) + true + else + false + end + end + def delete @c.delete @id CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path] diff --git a/ext/tk/lib/tk/canvastag.rb b/ext/tk/lib/tk/canvastag.rb index 5a98127f6b..056bf74c05 100644 --- a/ext/tk/lib/tk/canvastag.rb +++ b/ext/tk/lib/tk/canvastag.rb @@ -204,6 +204,14 @@ class TkcTag<TkObject @id end + def exist? + if @c.find_withtag(@id) + true + else + false + end + end + def delete @c.delete @id CTagID_TBL[@cpath].delete(@id) if CTagID_TBL[@cpath] diff --git a/ext/tk/lib/tk/event.rb b/ext/tk/lib/tk/event.rb index b85c456d41..4c6c0844b2 100644 --- a/ext/tk/lib/tk/event.rb +++ b/ext/tk/lib/tk/event.rb @@ -1,7 +1,17 @@ # # tk/event.rb - module for event # -require 'tk' + +unless $LOADED_FEATURES.member?('tk.rb') + # change loading order + + $LOADED_FEATURES.delete('tk/event.rb') + + require 'tkutil' + require 'tk' + +else +################################################ module TkEvent class Event < TkUtil::CallbackSubst @@ -42,7 +52,7 @@ module TkEvent end # [ <'%' subst-key char>, <proc type char>, <instance var (accessor) name>] - key_tbl = [ + KEY_TBL = [ [ ?#, ?n, :serial ], [ ?a, ?s, :above ], [ ?b, ?n, :num ], @@ -76,7 +86,7 @@ module TkEvent ] # [ <proc type char>, <proc/method to convert tcl-str to ruby-obj>] - proc_tbl = [ + PROC_TBL = [ [ ?n, TkComm.method(:num_or_str) ], [ ?s, TkComm.method(:string) ], [ ?b, TkComm.method(:bool) ], @@ -106,13 +116,13 @@ module TkEvent # ( which are Tcl strings ) to ruby objects based on the key string # that is generated by _get_subst_key() or _get_all_subst_keys(). # - _setup_subst_table(key_tbl, proc_tbl); + _setup_subst_table(KEY_TBL, PROC_TBL); end - def install_bind(cmd, *args) + def install_bind_for_event_class(klass, cmd, *args) if args.compact.size > 0 args = args.join(' ') - keys = Event._get_subst_key(args) + keys = klass._get_subst_key(args) if cmd.kind_of?(String) id = cmd @@ -120,12 +130,12 @@ module TkEvent id = install_cmd(cmd) else id = install_cmd(proc{|*arg| - TkUtil.eval_cmd(cmd, *Event.scan_args(keys, arg)) + TkUtil.eval_cmd(cmd, *klass.scan_args(keys, arg)) }) end id + ' ' + args else - keys, args = Event._get_all_subst_keys + keys, args = klass._get_all_subst_keys if cmd.kind_of?(String) id = cmd @@ -133,10 +143,17 @@ module TkEvent id = install_cmd(cmd) else id = install_cmd(proc{|*arg| - TkUtil.eval_cmd(cmd, Event.new(*Event.scan_args(keys, arg))) + TkUtil.eval_cmd(cmd, klass.new(*klass.scan_args(keys, arg))) }) end id + ' ' + args end end + + def install_bind(cmd, *args) + install_bind_for_event_class(Event, cmd, *args) + end +end + +################################################ end diff --git a/ext/tk/lib/tk/font.rb b/ext/tk/lib/tk/font.rb index 9b38531f59..b4c5c79213 100644 --- a/ext/tk/lib/tk/font.rb +++ b/ext/tk/lib/tk/font.rb @@ -73,25 +73,18 @@ class TkFont when 'unix' ltn = {'family'=>'Helvetica'.freeze, 'size'=>-12, 'weight'=>'bold'.freeze} - #knj = 'k14' - #knj = '-misc-fixed-medium-r-normal--14-*-*-*-c-*-jisx0208.1983-0' - knj = '-*-fixed-bold-r-normal--12-*-*-*-c-*-jisx0208.1983-0' when 'windows' ltn = {'family'=>'MS Sans Serif'.freeze, 'size'=>8} - knj = 'mincho' when 'macintosh' ltn = 'system' - knj = 'mincho' else # unknown ltn = 'Helvetica' - knj = 'mincho' end rescue ltn = 'Helvetica' - knj = 'mincho' end - knj = ltn + knj = ltn.dup end DEFAULT_LATIN_FONT_NAME = ltn.freeze @@ -202,54 +195,74 @@ class TkFont end end - def TkFont.init_widget_font(path, *args) + def TkFont.init_widget_font(pathname, *args) + win, tag, key = pathname.split(';') + key = 'font' unless key + path = [win, tag, key].join(';') + case (Tk::TK_VERSION) when /^4\.*/ - conf = tk_split_simplelist(tk_call(*args)). - find_all{|prop| prop[0..5]=='-font ' || prop[0..10]=='-kanjifont '}. + regexp = /^-(|kanji)#{key} / + + conf_list = tk_split_simplelist(tk_call(*args)). + find_all{|prop| prop =~ regexp}. collect{|prop| tk_split_simplelist(prop)} - if font_inf = conf.assoc('-font') - ltn = font_inf[4] - ltn = nil if ltn == [] - else - #ltn = nil - raise RuntimeError, "unknown option '-font'" - end - if font_inf = conf.assoc('-kanjifont') - knj = font_inf[4] - knj = nil if knj == [] - else - knj = nil + + if conf_list.size == 0 + raise RuntimeError, "the widget may not support 'font' option" end - TkFont.new(ltn, knj).call_font_configure(path, *(args + [{}])) + + args << {} + + ltn_key = "-#{key}" + knj_key = "-kanji#{key}" + + ltn_info = conf_list.find{|conf| conf[0] == ltn_key} + ltn = ltn_info[-1] + ltn = nil if ltn == [] || ltn == "" + + knj_info = conf_list.find{|conf| conf[0] == knj_key} + knj = knj_info[-1] + knj = nil if knj == [] || knj == "" + + TkFont.new(ltn, knj).call_font_configure([path, key], *args) when /^8\.*/ - font_prop = tk_split_simplelist(tk_call(*args)).find{|prop| - prop[0..5] == '-font ' - } - unless font_prop - raise RuntimeError, "unknown option '-font'" + regexp = /^-#{key} / + + conf_list = tk_split_simplelist(tk_call(*args)). + find_all{|prop| prop =~ regexp}. + collect{|prop| tk_split_simplelist(prop)} + + if conf_list.size == 0 + raise RuntimeError, "the widget may not support 'font' option" end - fnt = tk_split_simplelist(font_prop)[4] - if fnt == "" - TkFont.new(nil, nil).call_font_configure(path, *(args + [{}])) + + args << {} + + optkey = "-#{key}" + + info = conf_list.find{|conf| conf[0] == optkey} + fnt = info[-1] + fnt = nil if fnt == [] || fnt == "" + + unless fnt + TkFont.new(nil, nil).call_font_configure([path, key], *args) else begin compound = tk_split_simplelist( - Hash[*tk_split_simplelist(tk_call('font', 'configure', - fnt))].collect{|key,value| - [key[1..-1], value] - }.assoc('compound')[1]) + Hash[*tk_split_simplelist(tk_call('font', 'configure', + fnt))].collect{|key,value| + [key[1..-1], value] + }.assoc('compound')[1]) rescue compound = [] end if compound == [] - #TkFont.new(fnt, DEFAULT_KANJI_FONT_NAME) \ - #.call_font_configure(path, *(args + [{}])) - TkFont.new(fnt).call_font_configure(path, *(args + [{}])) + TkFont.new(fnt).call_font_configure([path, key], *args) else - TkFont.new(compound[0], compound[1]) \ - .call_font_configure(path, *(args + [{}])) + TkFont.new(compound[0], + compound[1]).call_font_configure([path, key], *args) end end end @@ -854,15 +867,16 @@ class TkFont if self == fobj begin if w.include?(';') - win, tag = w.split(';') + win, tag, optkey = w.split(';') + optkey = 'font' unless optkey winobj = tk_tcl2ruby(win) # winobj.tagfont_configure(tag, {'font'=>@latinfont}) if winobj.kind_of? TkText - tk_call(win, 'tag', 'configure', tag, '-font', @latinfont) + tk_call(win, 'tag', 'configure', tag, "-#{optkey}", @latinfont) elsif winobj.kind_of? TkCanvas - tk_call(win, 'itemconfigure', tag, '-font', @latinfont) + tk_call(win, 'itemconfigure', tag, "-#{optkey}", @latinfont) elsif winobj.kind_of? TkMenu - tk_call(win, 'entryconfigure', tag, '-font', @latinfont) + tk_call(win, 'entryconfigure', tag, "-#{optkey}", @latinfont) else raise RuntimeError, "unknown widget type" end @@ -888,15 +902,16 @@ class TkFont if self == fobj begin if w.include?(';') - win, tag = w.split(';') + win, tag, optkey = w.split(';') + optkey = 'kanjifont' unless optkey winobj = tk_tcl2ruby(win) # winobj.tagfont_configure(tag, {'kanjifont'=>@kanjifont}) if winobj.kind_of? TkText - tk_call(win, 'tag', 'configure', tag, '-kanjifont', @kanjifont) + tk_call(win, 'tag', 'configure', tag, "-#{optkey}", @kanjifont) elsif winobj.kind_of? TkCanvas - tk_call(win, 'itemconfigure', tag, '-kanjifont', @kanjifont) + tk_call(win, 'itemconfigure', tag, "-#{optkey}", @kanjifont) elsif winobj.kind_of? TkMenu - tk_call(win, 'entryconfigure', tag, '-kanjifont', @latinfont) + tk_call(win, 'entryconfigure', tag, "-#{optkey}", @latinfont) else raise RuntimeError, "unknown widget type" end @@ -1128,36 +1143,77 @@ class TkFont end def call_font_configure(path, *args) - keys = args.pop.update(@fontslot) + if path.kind_of?(Array) + # [path, optkey] + win, tag = path[0].split(';') + optkey = path[1].to_s + else + win, tag, optkey = path.split(';') + end + + fontslot = _symbolkey2str(@fontslot) + if optkey && optkey != "" + ltn = fontslot.delete('font') + knj = fontslot.delete('kanjifont') + fontslot[optkey] = ltn if ltn + fontslot["kanji#{optkey}"] = knj if knj + end + + keys = _symbolkey2str(args.pop).update(fontslot) args.concat(hash_kv(keys)) tk_call(*args) - Tk_FontUseTBL[path] = self + Tk_FontUseTBL[[win, tag, optkey].join(';')] = self self end def used ret = [] Tk_FontUseTBL.each{|key,value| + next unless self == value if key.include?(';') - win, tag = key.split(';') + win, tag, optkey = key.split(';') winobj = tk_tcl2ruby(win) if winobj.kind_of? TkText - ret.push([winobj, winobj.tagid2obj(tag)]) + if optkey + ret.push([winobj, winobj.tagid2obj(tag), optkey]) + else + ret.push([winobj, winobj.tagid2obj(tag)]) + end elsif winobj.kind_of? TkCanvas if (tagobj = TkcTag.id2obj(winobj, tag)).kind_of? TkcTag - ret.push([winobj, tagobj]) - elsif (tagobj = TkcItem.id2obj(tag)).kind_of? TkcItem - ret.push([winobj, tagobj]) + if optkey + ret.push([winobj, tagobj, optkey]) + else + ret.push([winobj, tagobj]) + end + elsif (tagobj = TkcItem.id2obj(winobj, tag)).kind_of? TkcItem + if optkey + ret.push([winobj, tagobj, optkey]) + else + ret.push([winobj, tagobj]) + end else - ret.push([winobj, tag]) + if optkey + ret.push([winobj, tag, optkey]) + else + ret.push([winobj, tag]) + end end elsif winobj.kind_of? TkMenu - ret.push([winobj, tag]) + if optkey + ret.push([winobj, tag, optkey]) + else + ret.push([winobj, tag]) + end else - ret.push([win, tag]) + if optkey + ret.push([win, tag, optkey]) + else + ret.push([win, tag]) + end end else - ret.push(tk_tcl2ruby(key)) if value == self + ret.push(tk_tcl2ruby(key)) end } ret diff --git a/ext/tk/lib/tk/itemfont.rb b/ext/tk/lib/tk/itemfont.rb index 6e92fc001c..f653755b06 100644 --- a/ext/tk/lib/tk/itemfont.rb +++ b/ext/tk/lib/tk/itemfont.rb @@ -3,182 +3,294 @@ # require 'tk' -module TkTreatItemFont - def __conf_cmd(idx) - raise NotImplementedError, "need to define `__conf_cmd'" +module TkItemFontOptkeys + def __item_font_optkeys(id) + # maybe need to override + ['font'] end - def __item_pathname(tagOrId) - raise NotImplementedError, "need to define `__item_pathname'" + private :__item_font_optkeys +end + +module TkTreatItemFont + include TkItemFontOptkeys + + def __item_pathname(id) + # maybe need to override + [self.path, id].join(';') end - private :__conf_cmd, :__item_pathname - - def tagfont_configinfo(tagOrId, name = nil) - pathname = __item_pathname(tagOrId) - ret = TkFont.used_on(pathname) - if ret == nil -=begin - if name - ret = name - else - ret = TkFont.init_widget_font(pathname, self.path, - __conf_cmd(0), __conf_cmd(1), tagOrId) - end -=end - ret = TkFont.init_widget_font(pathname, self.path, - __conf_cmd(0), __conf_cmd(1), tagOrId) + private :__item_pathname + + ################################################ + + def tagfont_configinfo(tagOrId, key = nil) + optkeys = __item_font_optkeys(tagid(tagOrId)) + if key && !optkeys.find{|opt| opt.to_s == key.to_s} + fail ArgumentError, "unknown font option name `#{key}'" + end + + win, tag = __item_pathname(tagid(tagOrId)).split(':') + + if key + pathname = [win, tag, key].join(';') + TkFont.used_on(pathname) || + TkFont.init_widget_font(pathname, *(__item_config_cmd(tagid(tagOrId)))) + elsif optkeys.size == 1 + pathname = [win, tag, optkeys[0]].join(';') + TkFont.used_on(pathname) || + TkFont.init_widget_font(pathname, *(__item_config_cmd(tagid(tagOrId)))) + else + fonts = {} + optkeys.each{|key| + key = key.to_s + pathname = [win, tag, key].join(';') + fonts[key] = + TkFont.used_on(pathname) || + TkFont.init_widget_font(pathname, *(__item_config_cmd(tagid(tagOrId)))) + } + fonts end - ret end alias tagfontobj tagfont_configinfo def tagfont_configure(tagOrId, slot) - pathname = __item_pathname(tagOrId) + pathname = __item_pathname(tagid(tagOrId)) + slot = _symbolkey2str(slot) - if slot.key?('font') - fnt = slot.delete('font') - if fnt.kind_of? TkFont - return fnt.call_font_configure(pathname, self.path, - __conf_cmd(0), __conf_cmd(1), - tagOrId, slot) - else - if fnt - if (slot.key?('kanjifont') || - slot.key?('latinfont') || - slot.key?('asciifont')) - fnt = TkFont.new(fnt) - - lfnt = slot.delete('latinfont') - lfnt = slot.delete('asciifont') if slot.key?('asciifont') - kfnt = slot.delete('kanjifont') - - fnt.latin_replace(lfnt) if lfnt - fnt.kanji_replace(kfnt) if kfnt - end + __item_font_optkeys(tagid(tagOrId)).each{|optkey| + optkey = optkey.to_s + l_optkey = 'latin' << optkey + a_optkey = 'ascii' << optkey + k_optkey = 'kanji' << optkey + + if slot.key?(optkey) + fnt = slot.delete(optkey) + if fnt.kind_of?(TkFont) + slot.delete(l_optkey) + slot.delete(a_optkey) + slot.delete(k_optkey) + + fnt.call_font_configure([pathname, optkey], + *(__item_config_cmd(tagid(tagOrId)) << {})) + next + else + if fnt + if (slot.key?(l_optkey) || + slot.key?(a_optkey) || + slot.key?(k_optkey)) + fnt = TkFont.new(fnt) - slot['font'] = fnt - tk_call(self.path, __conf_cmd(0), __conf_cmd(1), - tagOrId, *hash_kv(slot)) + lfnt = slot.delete(l_optkey) + lfnt = slot.delete(a_optkey) if slot.key?(a_optkey) + kfnt = slot.delete(k_optkey) + + fnt.latin_replace(lfnt) if lfnt + fnt.kanji_replace(kfnt) if kfnt + + fnt.call_font_configure([pathname, optkey], + *(__item_config_cmd(tagid(tagOrId)) << {})) + next + else + tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << fnt)) + end + end + next end - return self end - end - lfnt = slot.delete('latinfont') - lfnt = slot.delete('asciifont') if slot.key?('asciifont') - kfnt = slot.delete('kanjifont') + lfnt = slot.delete(l_optkey) + lfnt = slot.delete(a_optkey) if slot.key?(a_optkey) + kfnt = slot.delete(k_optkey) - if lfnt && kfnt - return TkFont.new(lfnt, kfnt).call_font_configure(pathname, self.path, - __conf_cmd(0), - __conf_cmd(1), - tagOrId, slot) - end + if lfnt && kfnt + TkFont.new(lfnt, kfnt).call_font_configure([pathname, optkey], + *(__item_config_cmd(tagid(tagOrId)) << {})) + elsif lfnt + latintagfont_configure([lfnt, optkey]) + elsif kfnt + kanjitagfont_configure([kfnt, optkey]) + end + } - latintagfont_configure(tagOrId, lfnt) if lfnt - kanjitagfont_configure(tagOrId, kfnt) if kfnt - - tk_call(self.path, __conf_cmd(0), __conf_cmd(1), - tagOrId, *hash_kv(slot)) if slot != {} + # configure other (without font) options + tk_call(*(__item_config_cmd(tagid(tagOrId)).concat(hash_kv(slot)))) if slot != {} self end def latintagfont_configure(tagOrId, ltn, keys=nil) - pathname = __item_pathname(tagOrId) - if (fobj = TkFont.used_on(pathname)) - fobj = TkFont.new(fobj) # create a new TkFont object - elsif Tk::JAPANIZED_TK - fobj = tagfontobj(tagOrId) # create a new TkFont object + if ltn.kind_of?(Array) + key = ltn[1] + ltn = ltn[0] else - tk_call(self.path, __conf_cmd(0), __conf_cmd(1), tagOrId, '-font', ltn) - return self + key = nil + end + + optkeys = __item_font_optkeys(tagid(tagOrId)) + if key && !optkeys.find{|opt| opt.to_s == key.to_s} + fail ArgumentError, "unknown font option name `#{key}'" end - if fobj.kind_of?(TkFont) - if ltn.kind_of? TkFont - conf = {} - ltn.latin_configinfo.each{|key,val| conf[key] = val} - if keys - fobj.latin_configure(conf.update(keys)) + win, tag = __item_pathname(tagid(tagOrId)).split(':') + + optkeys = [key] if key + + optkeys.each{|optkey| + optkey = optkey.to_s + + pathname = [win, tag, optkey].join(';') + + if (fobj = TkFont.used_on(pathname)) + fobj = TkFont.new(fobj) # create a new TkFont object + elsif Tk::JAPANIZED_TK + fobj = fontobj # create a new TkFont object + else + tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << ltn)) + next + end + + if fobj.kind_of?(TkFont) + if ltn.kind_of?(TkFont) + conf = {} + ltn.latin_configinfo.each{|key,val| conf[key] = val} + if keys + fobj.latin_configure(conf.update(keys)) + else + fobj.latin_configure(conf) + end else - fobj.latin_configure(conf) + fobj.latin_replace(ltn) end - else - fobj.latin_replace(ltn) end - end - return fobj.call_font_configure(pathname, self.path, - __conf_cmd(0), __conf_cmd(1), tagOrId, {}) + fobj.call_font_configure([pathname, optkey], *(__item_config_cmd(tagid(tagOrId)) << {})) + } + self end alias asciitagfont_configure latintagfont_configure def kanjitagfont_configure(tagOrId, knj, keys=nil) - pathname = __item_pathname(tagOrId) - if (fobj = TkFont.used_on(pathname)) - fobj = TkFont.new(fobj) # create a new TkFont object - elsif Tk::JAPANIZED_TK - fobj = tagfontobj(tagOrId) # create a new TkFont object + if knj.kind_of?(Array) + key = knj[1] + knj = knj[0] else - tk_call(self.path, __conf_cmd(0), __conf_cmd(1), tagOrId, '-font', knj) - return self + key = nil + end + + optkeys = __item_font_optkeys(tagid(tagOrId)) + if key && !optkeys.find{|opt| opt.to_s == key.to_s} + fail ArgumentError, "unknown font option name `#{key}'" end - if fobj.kind_of?(TkFont) - if knj.kind_of? TkFont - conf = {} - knj.kanji_configinfo.each{|key,val| conf[key] = val} - if keys - fobj.kanji_configure(conf.update(keys)) + win, tag = __item_pathname(tagid(tagOrId)).split(':') + + optkeys = [key] if key + + optkeys.each{|optkey| + optkey = optkey.to_s + + pathname = [win, tag, optkey].join(';') + + if (fobj = TkFont.used_on(pathname)) + fobj = TkFont.new(fobj) # create a new TkFont object + elsif Tk::JAPANIZED_TK + fobj = fontobj # create a new TkFont object + else + tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << knj)) + next + end + + if fobj.kind_of?(TkFont) + if knj.kind_of?(TkFont) + conf = {} + knj.kanji_configinfo.each{|key,val| conf[key] = val} + if keys + fobj.kanji_configure(conf.update(keys)) + else + fobj.kanji_configure(conf) + end else - fobj.kanji_configure(conf) + fobj.kanji_replace(knj) end - else - fobj.kanji_replace(knj) end - end - return fobj.call_font_configure(pathname, self.path, - __conf_cmd(0), __conf_cmd(1), tagOrId, {}) + fobj.call_font_configure([pathname, optkey], *(__item_config_cmd(tagid(tagOrId)) << {})) + } + self end - def tagfont_copy(tagOrId, window, wintag=nil) - pathname = __item_pathname(tagOrId) + def tagfont_copy(tagOrId, window, wintag=nil, winkey=nil, targetkey=nil) if wintag - fnt = window.tagfontobj(wintag).dup + if winkey + fnt = window.tagfontobj(wintag, winkey).dup + else + fnt = window.tagfontobj(wintag).dup + end else - fnt = window.fontobj.dup + if winkey + fnt = window.fontobj(winkey).dup + else + fnt = window.fontobj.dup + end end - fnt.call_font_configure(pathname, self.path, - __conf_cmd(0), __conf_cmd(1), tagOrId, {}) - return self + + if targetkey + fnt.call_font_configure([__item_pathname(tagid(tagOrId)), targetkey], + *(__item_config_cmd(tagid(tagOrId)) << {})) + else + fnt.call_font_configure(__item_pathname(tagid(tagOrId)), + *(__item_config_cmd(tagid(tagOrId)) << {})) + end + self end - def latintagfont_copy(tagOrId, window, wintag=nil) - pathname = __item_pathname(tagOrId) - tagfontobj(tagOrId).dup.call_font_configure(pathname, self.path, - __conf_cmd(0), __conf_cmd(1), - tagOrId, {}) + + def latintagfont_copy(tagOrId, window, wintag=nil, winkey=nil, targetkey=nil) + if targetkey + fontobj(targetkey).dup.call_font_configure([__item_pathname(tagid(tagOrId)), targetkey], + *(__item_config_cmd(tagid(tagOrId)) << {})) + else + fontobj.dup.call_font_configure(__item_pathname(tagid(tagOrId)), + *(__item_config_cmd(tagid(tagOrId)) << {})) + end + if wintag - tagfontobj(tagOrId). - latin_replace(window.tagfontobj(wintag).latin_font_id) + if winkey + fontobj.latin_replace(window.tagfontobj(wintag, winkey).latin_font_id) + else + fontobj.latin_replace(window.tagfontobj(wintag).latin_font_id) + end else - tagfontobj(tagOrId).latin_replace(window.fontobj.latin_font_id) + if winkey + fontobj.latin_replace(window.fontobj(winkey).latin_font_id) + else + fontobj.latin_replace(window.fontobj.latin_font_id) + end end self end alias asciitagfont_copy latintagfont_copy - def kanjitagfont_copy(tagOrId, window, wintag=nil) - pathname = __item_pathname(tagOrId) - tagfontobj(tagOrId).dup.call_font_configure(pathname, self.path, - __conf_cmd(0), __conf_cmd(1), - tagOrId, {}) + def kanjifont_copy(tagOrId, window, wintag=nil, winkey=nil, targetkey=nil) + if targetkey + fontobj(targetkey).dup.call_font_configure([__item_pathname(tagid(tagOrId)), targetkey], + *(__item_config_cmd(tagid(tagOrId)) << {})) + else + fontobj.dup.call_font_configure(__item_pathname(tagid(tagOrId)), + *(__item_config_cmd(tagid(tagOrId)) << {})) + end + if wintag - tagfontobj(tagOrId). - kanji_replace(window.tagfontobj(wintag).kanji_font_id) + if winkey + fontobj.kanji_replace(window.tagfontobj(wintag, winkey).kanji_font_id) + else + fontobj.kanji_replace(window.tagfontobj(wintag).kanji_font_id) + end else - tagfontobj(tagOrId).kanji_replace(window.fontobj.kanji_font_id) + if winkey + fontobj.kanji_replace(window.fontobj(winkey).kanji_font_id) + else + fontobj.kanji_replace(window.fontobj.kanji_font_id) + end end self end diff --git a/ext/tk/lib/tk/listbox.rb b/ext/tk/lib/tk/listbox.rb index 611226682a..799d573b1d 100644 --- a/ext/tk/lib/tk/listbox.rb +++ b/ext/tk/lib/tk/listbox.rb @@ -2,27 +2,21 @@ # tk/listbox.rb : treat listbox widget # require 'tk' +require 'tk/itemconfig' require 'tk/scrollable' require 'tk/txtwin_abst' -module TkTreatListItemFont - include TkTreatItemFont +module TkListItemConfig + include TkItemConfigMethod - ItemCMD = ['itemconfigure'.freeze, TkComm::None].freeze - def __conf_cmd(idx) - ItemCMD[idx] + def __item_listval_optkeys(id) + [] end - - def __item_pathname(tagOrId) - self.path + ';' + tagOrId.to_s - end - - private :__conf_cmd, :__item_pathname + private :__item_listval_optkeys end - class TkListbox<TkTextWin - include TkTreatListItemFont + include TkListItemConfig include Scrollable TkCommandNames = ['listbox'.freeze].freeze @@ -38,6 +32,10 @@ class TkListbox<TkTextWin end private :create_self + def tagid(id) + id.to_s + end + def activate(y) tk_send_without_enc('activate', y) self @@ -78,6 +76,7 @@ class TkListbox<TkTextWin tk_send_without_enc('index', index).to_i end +=begin def itemcget(index, key) case key.to_s when 'text', 'label', 'show' @@ -249,4 +248,5 @@ class TkListbox<TkTextWin ret end end +=end end diff --git a/ext/tk/lib/tk/menu.rb b/ext/tk/lib/tk/menu.rb index 9c34741b1b..f5a16cf3cf 100644 --- a/ext/tk/lib/tk/menu.rb +++ b/ext/tk/lib/tk/menu.rb @@ -2,24 +2,37 @@ # tk/menu.rb : treat menu and menubutton # require 'tk' +require 'tk/itemconfig' -module TkTreatMenuEntryFont - include TkTreatItemFont +module TkMenuEntryConfig + include TkItemConfigMethod - ItemCMD = ['entryconfigure'.freeze, TkComm::None].freeze - def __conf_cmd(idx) - ItemCMD[idx] + def __item_cget_cmd(id) + [self.path, 'entrycget', id] end - - def __item_pathname(tagOrId) - self.path + ';' + tagOrId.to_s + private :__item_cget_cmd + + def __item_config_cmd(id) + [self.path, 'entryconfigure', id] + end + private :__item_config_cmd + + def __item_listval_optkeys(id) + [] end + private :__item_listval_optkeys + + alias entrycget itemcget + alias entryconfigure itemconfigure + alias entryconfiginfo itemconfiginfo + alias current_entryconfiginfo current_itemconfiginfo - private :__conf_cmd, :__item_pathname + private :itemcget, :itemconfigure + private :itemconfiginfo, :current_itemconfiginfo end class TkMenu<TkWindow - include TkTreatMenuEntryFont + include TkMenuEntryConfig TkCommandNames = ['menu'.freeze].freeze WidgetClassName = 'Menu'.freeze @@ -34,6 +47,10 @@ class TkMenu<TkWindow end private :create_self + def tagid(id) + id.to_s + end + def activate(index) tk_send_without_enc('activate', _get_eval_enc_str(index)) self @@ -116,6 +133,8 @@ class TkMenu<TkWindow def yposition(index) number(tk_send_without_enc('yposition', _get_eval_enc_str(index))) end + +=begin def entrycget(index, key) case key.to_s when 'text', 'label', 'show' @@ -287,6 +306,7 @@ class TkMenu<TkWindow ret end end +=end end diff --git a/ext/tk/lib/tk/package.rb b/ext/tk/lib/tk/package.rb index 8768bf1c79..dbb0ca33e8 100644 --- a/ext/tk/lib/tk/package.rb +++ b/ext/tk/lib/tk/package.rb @@ -18,6 +18,36 @@ module TkPackage nil end + def if_needed(pkg, ver, *arg, &b) + size = arg.size + + if size==0 && !b + # proc info + procedure(tk_call('package', 'ifneeded', pkg, ver)) + + elsif size==0 && b + # set proc + cmd = proc(&b) + tk_call('package', 'ifneeded', pkg, ver, cmd) + cmd + + elsif size==1 && !b + # set proc + cmd = arg[0] + if cmd + tk_call('package', 'ifneeded', pkg, ver, cmd) + cmd + else + # remove proc + tk_call('package', 'ifneeded', pkg, ver, '') + nil + end + + else + fail ArgumentError, 'too many arguments' + end + end + def names tk_split_simplelist(tk_call('package', 'names')) end @@ -25,26 +55,74 @@ module TkPackage def provide(package, version=nil) if version tk_call('package', 'provide', package, version) + end + if (ret = tk_call('package', 'provide', package)) == '' nil else - tk_call('package', 'provide', package) + ret end end def present(package, version=None) - tk_call('package', 'present', package, version) + begin + tk_call('package', 'present', package, version) + rescue => e + fail e.class, 'TkPackage ' << e.message + end end def present_exact(package, version) - tk_call('package', 'present', '-exact', package, version) + begin + tk_call('package', 'present', '-exact', package, version) + rescue => e + fail e.class, 'TkPackage ' << e.message + end end def require(package, version=None) - tk_call('package', 'require', package, version) + begin + tk_call('package', 'require', package, version) + rescue => e + fail e.class, 'TkPackage ' << e.message + end end def require_exact(package, version) - tk_call('package', 'require', '-exact', package, version) + begin + tk_call('package', 'require', '-exact', package, version) + rescue => e + fail e.class, 'TkPackage ' << e.message + end + end + + def unknown_proc(*arg, &b) + size = arg.size + + if size==0 && !b + # proc info + procedure(tk_call('package', 'unknown')) + + elsif size==0 && b + # set proc + cmd = proc(&b) + tk_call('package', 'unknown', cmd) + cmd + + elsif size==1 && !b + # set proc + cmd = arg[0] + if cmd + tk_call('package', 'unknown', cmd) + cmd + else + # remove proc + tk_call('package', 'unknown', '') + nil + end + + else + fail ArgumentError, 'too many arguments' + end end def versions(package) diff --git a/ext/tk/lib/tk/scrollable.rb b/ext/tk/lib/tk/scrollable.rb index e591a299ab..c5f4fdb70c 100644 --- a/ext/tk/lib/tk/scrollable.rb +++ b/ext/tk/lib/tk/scrollable.rb @@ -7,10 +7,15 @@ module Tk module Scrollable def xscrollcommand(cmd=Proc.new) configure_cmd 'xscrollcommand', cmd + # Tk.update # avoid scrollbar trouble + self end def yscrollcommand(cmd=Proc.new) configure_cmd 'yscrollcommand', cmd + # Tk.update # avoid scrollbar trouble + self end + def xview(*index) if index.size == 0 list(tk_send_without_enc('xview')) @@ -19,6 +24,13 @@ module Tk self end end + def xview_moveto(*index) + xview('moveto', *index) + end + def xview_scroll(*index) + xview('scroll', *index) + end + def yview(*index) if index.size == 0 list(tk_send_without_enc('yview')) @@ -27,6 +39,13 @@ module Tk self end end + def yview_moveto(*index) + yview('moveto', *index) + end + def yview_scroll(*index) + yview('scroll', *index) + end + def xscrollbar(bar=nil) if bar @xscrollbar = bar @@ -34,6 +53,7 @@ module Tk self.xscrollcommand {|*arg| @xscrollbar.set(*arg)} @xscrollbar.command {|*arg| self.xview(*arg)} end + Tk.update # avoid scrollbar trouble @xscrollbar end def yscrollbar(bar=nil) @@ -43,6 +63,7 @@ module Tk self.yscrollcommand {|*arg| @yscrollbar.set(*arg)} @yscrollbar.command {|*arg| self.yview(*arg)} end + Tk.update # avoid scrollbar trouble @yscrollbar end end diff --git a/ext/tk/lib/tk/scrollbar.rb b/ext/tk/lib/tk/scrollbar.rb index 0ee4423c9a..8d4d40322d 100644 --- a/ext/tk/lib/tk/scrollbar.rb +++ b/ext/tk/lib/tk/scrollbar.rb @@ -41,6 +41,7 @@ class TkScrollbar<TkWindow w.yscrollcommand proc{|first, last| self.set(first, last)} end } + Tk.update # avoid scrollbar trouble self end @@ -52,6 +53,12 @@ class TkScrollbar<TkWindow fail RuntimeError, "not depend on the assigned_list" end + def configure(*args) + ret = super(*args) + # Tk.update # avoid scrollbar trouble + ret + end + #def delta(deltax=None, deltay=None) def delta(deltax, deltay) number(tk_send_without_enc('delta', deltax, deltay)) diff --git a/ext/tk/lib/tk/scrollbox.rb b/ext/tk/lib/tk/scrollbox.rb index f0fdece260..5f304d377f 100644 --- a/ext/tk/lib/tk/scrollbox.rb +++ b/ext/tk/lib/tk/scrollbox.rb @@ -14,10 +14,15 @@ class TkScrollbox<TkListbox scroll = TkScrollbar.new(@frame) @path = list.path +=begin list.configure 'yscroll', scroll.path+" set" list.pack 'side'=>'left','fill'=>'both','expand'=>'yes' scroll.configure 'command', list.path+" yview" scroll.pack 'side'=>'right','fill'=>'y' +=end + list.yscrollbar(scroll) + list.pack('side'=>'left','fill'=>'both','expand'=>'yes') + scroll.pack('side'=>'right','fill'=>'y') delegate('DEFAULT', list) delegate('foreground', list) diff --git a/ext/tk/lib/tk/text.rb b/ext/tk/lib/tk/text.rb index be3f814505..7593b59368 100644 --- a/ext/tk/lib/tk/text.rb +++ b/ext/tk/lib/tk/text.rb @@ -4,32 +4,66 @@ # by Yukihiro Matsumoto <matz@caelum.co.jp> require 'tk' require 'tk/itemfont' +require 'tk/itemconfig' require 'tk/scrollable' require 'tk/txtwin_abst' -module TkTreatTextTagFont +module TkTextTagConfig include TkTreatItemFont + include TkItemConfigMethod - ItemCMD = ['tag'.freeze, 'configure'.freeze].freeze - def __conf_cmd(idx) - ItemCMD[idx] + def __item_cget_cmd(id) # id := [ type, tagOrId ] + [self.path, id[0], 'cget', id[1]] end + private :__item_cget_cmd - def __item_pathname(tagOrId) - if tagOrId.kind_of?(TkTextTag) - self.path + ';' + tagOrId.id - else - self.path + ';' + tagOrId + def __item_config_cmd(id) # id := [ type, tagOrId ] + [self.path, id[0], 'configure', id[1]] + end + private :__item_config_cmd + + def __item_pathname(id) + if id.kind_of?(Array) + id = tagid(id[1]) end + [self.path, id].join(';') end + private :__item_pathname - private :__conf_cmd, :__item_pathname -end + def tag_cget(tagOrId, option) + itemcget(['tag', tagOrId], option) + end + def tag_configure(tagOrId, slot, value=None) + itemconfigure(['tag', tagOrId], slot, value) + end + def tag_configinfo(tagOrId, slot=nil) + itemconfigure(['tag', tagOrId], slot) + end + def current_tag_configinfo(tagOrId, slot=nil) + itemconfigure(['tag', tagOrId], slot) + end + + def window_cget(tagOrId, option) + itemcget(['window', tagOrId], option) + end + def window_configure(tagOrId, slot, value=None) + itemconfigure(['window', tagOrId], slot, value) + end + def window_configinfo(tagOrId, slot=nil) + itemconfigure(['window', tagOrId], slot) + end + def current_window_configinfo(tagOrId, slot=nil) + itemconfigure(['window', tagOrId], slot) + end + private :itemcget, :itemconfigure + private :itemconfiginfo, :current_itemconfiginfo +end class TkText<TkTextWin ItemConfCMD = ['tag'.freeze, 'configure'.freeze].freeze - include TkTreatTextTagFont + #include TkTreatTextTagFont + include TkTextTagConfig include Scrollable TkCommandNames = ['text'.freeze].freeze @@ -90,6 +124,18 @@ class TkText<TkTextWin @tags[name] = obj end + def tagid(tag) + if tag.kind_of?(TkTextTag) \ + || tag.kind_of?(TkTextMark) \ + || tag.kind_of?(TkTextImage) \ + || tag.kind_of?(TkTextWindow) + tag.id + else + tag + end + end + private :tagid + def tagid2obj(tagid) if @tags[tagid] @tags[tagid] @@ -482,6 +528,7 @@ class TkText<TkTextWin _bindinfo([@path, 'tag', 'bind', tag], context) end +=begin def tag_cget(tag, key) case key.to_s when 'text', 'label', 'show', 'data', 'file' @@ -655,6 +702,7 @@ class TkText<TkTextWin ret end end +=end def tag_raise(tag, above=None) tk_send_without_enc('tag', 'raise', _get_eval_enc_str(tag), @@ -698,6 +746,7 @@ class TkText<TkTextWin _get_eval_enc_str(last))) end +=begin def window_cget(index, slot) case slot.to_s when 'text', 'label', 'show', 'data', 'file' @@ -732,7 +781,7 @@ class TkText<TkTextWin if slot['create'] p_create = slot['create'] if p_create.kind_of? Proc -=begin +#=begin slot['create'] = install_cmd(proc{ id = p_create.call if id.kind_of?(TkWindow) @@ -741,7 +790,7 @@ class TkText<TkTextWin id end }) -=end +#=end slot['create'] = install_cmd(proc{_epath(p_create.call)}) end end @@ -757,7 +806,7 @@ class TkText<TkTextWin if slot == 'create' || slot == :create p_create = value if p_create.kind_of? Proc -=begin +#=begin value = install_cmd(proc{ id = p_create.call if id.kind_of?(TkWindow) @@ -766,7 +815,7 @@ class TkText<TkTextWin id end }) -=end +#=end value = install_cmd(proc{_epath(p_create.call)}) end end @@ -879,6 +928,7 @@ class TkText<TkTextWin ret end end +=end def window_names tk_split_simplelist(_fromUTF8(tk_send_without_enc('window', 'names'))).collect{|elt| diff --git a/ext/tk/lib/tk/textmark.rb b/ext/tk/lib/tk/textmark.rb index 8b42df2f0c..18d52a5bfc 100644 --- a/ext/tk/lib/tk/textmark.rb +++ b/ext/tk/lib/tk/textmark.rb @@ -37,6 +37,14 @@ class TkTextMark<TkObject @id end + def exist? + if ( tk_split_simplelist(_fromUTF8(tk_call_without_enc(@t.path, 'mark', 'names'))).find{|id| id == @id } ) + true + else + false + end + end + def +(mod) @id + ' + ' + mod end diff --git a/ext/tk/lib/tk/texttag.rb b/ext/tk/lib/tk/texttag.rb index 561a027f08..17909bbfcf 100644 --- a/ext/tk/lib/tk/texttag.rb +++ b/ext/tk/lib/tk/texttag.rb @@ -49,6 +49,14 @@ class TkTextTag<TkObject @id end + def exist? + if ( tk_split_simplelist(_fromUTF8(tk_call_without_enc(@t.path, 'tag', 'names'))).find{|id| id == @id } ) + true + else + false + end + end + def first @id + '.first' end @@ -100,6 +108,10 @@ class TkTextTag<TkObject end def cget(key) + @t.tag_cget @id, key + end +=begin + def cget(key) case key.to_s when 'text', 'label', 'show', 'data', 'file' _fromUTF8(tk_call_without_enc(@t.path, 'tag', 'cget', @id, "-#{key}")) @@ -121,6 +133,7 @@ class TkTextTag<TkObject @id, "-#{key}"))) end end +=end def configure(key, val=None) @t.tag_configure @id, key, val diff --git a/ext/tk/lib/tk/validation.rb b/ext/tk/lib/tk/validation.rb index 70e84e6cbf..0524a43757 100644 --- a/ext/tk/lib/tk/validation.rb +++ b/ext/tk/lib/tk/validation.rb @@ -3,7 +3,106 @@ # require 'tk' +module Tk + module ValidateConfigure + def __validation_class_list + # maybe need to override + [] + end + + def __get_validate_key2class + k2c = {} + __validation_class_list.each{|klass| + klass._config_keys.each{|key| + k2c[key.to_s] = klass + } + } + k2c + end + + def configure(slot, value=TkComm::None) + key2class = __get_validate_key2class + + if slot.kind_of?(Hash) + slot = _symbolkey2str(slot) + key2class.each{|key, klass| + if slot[key].kind_of?(Array) + cmd, *args = slot[key] + slot[key] = klass.new(cmd, args.join(' ')) + elsif slot[key].kind_of? Proc + slot[key] = klass.new(slot[key]) + end + } + super(slot) + + else + slot = slot.to_s + if (klass = key2class[slot]) + if value.kind_of? Array + cmd, *args = value + value = klass.new(cmd, args.join(' ')) + elsif value.kind_of? Proc + value = klass.new(value) + end + end + super(slot, value) + end + + self + end + end + + module ItemValidateConfigure + def __item_validation_class_list(id) + # maybe need to override + [] + end + + def __get_item_validate_key2class(id) + k2c = {} + __item_validation_class_list(id).each{|klass| + klass._config_keys.each{|key| + k2c[key.to_s] = klass + } + } + end + + def itemconfigure(tagOrId, slot, value=TkComm::None) + key2class = __get_item_validate_key2class(tagid(tagOrId)) + + if slot.kind_of?(Hash) + slot = _symbolkey2str(slot) + key2class.each{|key, klass| + if slot[key].kind_of?(Array) + cmd, *args = slot[key] + slot[key] = klass.new(cmd, args.join(' ')) + elsif slot[key].kind_of? Proc + slot[key] = klass.new(slot[key]) + end + } + super(slot) + + else + slot = slot.to_s + if (klass = key2class[slot]) + if value.kind_of? Array + cmd, *args = value + value = klass.new(cmd, args.join(' ')) + elsif value.kind_of? Proc + value = klass.new(value) + end + end + super(slot, value) + end + + self + end + end +end + module TkValidation + include Tk::ValidateConfigure + class ValidateCmd include TkComm @@ -18,7 +117,7 @@ module TkValidation end class ValidateArgs < TkUtil::CallbackSubst - key_tbl = [ + KEY_TBL = [ [ ?d, ?n, :action ], [ ?i, ?x, :index ], [ ?s, ?e, :current ], @@ -30,7 +129,7 @@ module TkValidation nil ] - proc_tbl = [ + PROC_TBL = [ [ ?n, TkComm.method(:number) ], [ ?s, TkComm.method(:string) ], [ ?w, TkComm.method(:window) ], @@ -58,24 +157,31 @@ module TkValidation nil ] - _setup_subst_table(key_tbl, proc_tbl); + _setup_subst_table(KEY_TBL, PROC_TBL); end - def initialize(cmd = Proc.new, *args) + ############################## + + def self._config_keys + # array of config-option key (string or symbol) + ['vcmd', 'validatecommand', 'invcmd', 'invalidcommand'] + end + + def _initialize_for_cb_class(klass, cmd = Proc.new, *args) if args.compact.size > 0 args = args.join(' ') - keys = ValidateArgs._get_subst_key(args) + keys = klass._get_subst_key(args) if cmd.kind_of?(String) id = cmd elsif cmd.kind_of?(TkCallbackEntry) @id = install_cmd(cmd) else @id = install_cmd(proc{|*arg| - (cmd.call(*ValidateArgs.scan_args(keys, arg)))? '1':'0' + (cmd.call(*klass.scan_args(keys, arg)))? '1':'0' }) + ' ' + args end else - keys, args = ValidateArgs._get_all_subst_keys + keys, args = klass._get_all_subst_keys if cmd.kind_of?(String) id = cmd elsif cmd.kind_of?(TkCallbackEntry) @@ -83,13 +189,17 @@ module TkValidation else @id = install_cmd(proc{|*arg| (cmd.call( - ValidateArgs.new(*ValidateArgs.scan_args(keys,arg))) + klass.new(*klass.scan_args(keys,arg))) )? '1': '0' }) + ' ' + args end end end + def initialize(cmd = Proc.new, *args) + _initialize_for_cb_class(ValidateArgs, cmd, *args) + end + def to_eval @id end @@ -97,49 +207,8 @@ module TkValidation ##################################### - def configure(slot, value=TkComm::None) - if slot.kind_of? Hash - slot = _symbolkey2str(slot) - if slot['vcmd'].kind_of? Array - cmd, *args = slot['vcmd'] - slot['vcmd'] = ValidateCmd.new(cmd, args.join(' ')) - elsif slot['vcmd'].kind_of? Proc - slot['vcmd'] = ValidateCmd.new(slot['vcmd']) - end - if slot['validatecommand'].kind_of? Array - cmd, *args = slot['validatecommand'] - slot['validatecommand'] = ValidateCmd.new(cmd, args.join(' ')) - elsif slot['validatecommand'].kind_of? Proc - slot['validatecommand'] = ValidateCmd.new(slot['validatecommand']) - end - if slot['invcmd'].kind_of? Array - cmd, *args = slot['invcmd'] - slot['invcmd'] = ValidateCmd.new(cmd, args.join(' ')) - elsif slot['invcmd'].kind_of? Proc - slot['invcmd'] = ValidateCmd.new(slot['invcmd']) - end - if slot['invalidcommand'].kind_of? Array - cmd, *args = slot['invalidcommand'] - slot['invalidcommand'] = ValidateCmd.new(cmd, args.join(' ')) - elsif slot['invalidcommand'].kind_of? Proc - slot['invalidcommand'] = ValidateCmd.new(slot['invalidcommand']) - end - super(slot) - else - if (slot == 'vcmd' || slot == :vcmd || - slot == 'validatecommand' || slot == :validatecommand || - slot == 'invcmd' || slot == :invcmd || - slot == 'invalidcommand' || slot == :invalidcommand) - if value.kind_of? Array - cmd, *args = value - value = ValidateCmd.new(cmd, args.join(' ')) - elsif value.kind_of? Proc - value = ValidateCmd.new(value) - end - end - super(slot, value) - end - self + def __validation_class_list + super << ValidateCmd end def validatecommand(cmd = Proc.new, args = nil) diff --git a/ext/tk/lib/tk/variable.rb b/ext/tk/lib/tk/variable.rb index 43baac458d..61d6e8a410 100644 --- a/ext/tk/lib/tk/variable.rb +++ b/ext/tk/lib/tk/variable.rb @@ -84,6 +84,14 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL') end end + def self.new_hash(val = {}) + if val.kind_of?(Hash) + self.new(val) + else + fail ArgumentError, 'Hash is expected' + end + end + def initialize(val="") # @id = Tk_VARIABLE_ID.join('') @id = Tk_VARIABLE_ID.join(TkCore::INTERP._ip_id_) @@ -103,6 +111,12 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL') INTERP._invoke_without_enc('global', @id) #INTERP._invoke('global', @id) + # create and init + if val.kind_of?(Hash) + # assoc-array variable + self[''] = 0 + self.clear + end self.value = val =begin @@ -185,7 +199,7 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL') def is_hash? #ITNERP._eval("global #{@id}; array exist #{@id}") == '1' - ITNERP._invoke_without_enc('array', 'exist', @id) == '1' + INTERP._invoke_without_enc('array', 'exist', @id) == '1' end def is_scalar? @@ -197,7 +211,23 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL') fail RuntimeError, 'cannot get keys from a scalar variable' end #tk_split_simplelist(INTERP._eval("global #{@id}; array get #{@id}")) - tk_split_simplelist(INTERP._fromUTF8(INTERP._invoke_without_enc('array', 'get', @id))) + tk_split_simplelist(INTERP._fromUTF8(INTERP._invoke_without_enc('array', 'names', @id))) + end + + def clear + if (is_scalar?) + fail RuntimeError, 'cannot clear a scalar variable' + end + keys.each{|k| unset(k)} + self + end + + def update(hash) + if (is_scalar?) + fail RuntimeError, 'cannot update a scalar variable' + end + hash.each{|k,v| self[k] = v} + self end @@ -222,10 +252,11 @@ if USE_TCLs_SET_VARIABLE_FUNCTIONS def value=(val) if val.kind_of?(Hash) + self.clear val.each{|k, v| #INTERP._set_global_var2(@id, _toUTF8(_get_eval_string(k)), # _toUTF8(_get_eval_string(v))) - INTERP._set_global_var2(@id, __get_eval_string(k, true), + INTERP._set_global_var2(@id, _get_eval_string(k, true), _get_eval_string(v, true)) } self.value @@ -260,7 +291,7 @@ if USE_TCLs_SET_VARIABLE_FUNCTIONS def unset(elem=nil) if elem - INTERP._unset_global_var2(@id, tk_tcl2ruby(elem)) + INTERP._unset_global_var2(@id, _get_eval_string(elem, true)) else INTERP._unset_global_var(@id) end @@ -359,7 +390,7 @@ else def unset(elem=nil) if elem INTERP._eval(Kernel.format('global %s; unset %s(%s)', - @id, @id, tk_tcl2ruby(elem))) + @id, @id, _get_eval_string(elem))) #INTERP._eval(Kernel.format('unset %s(%s)', @id, tk_tcl2ruby(elem))) #INTERP._eval('unset ' + @id + '(' + _get_eval_string(elem) + ')') else @@ -387,6 +418,29 @@ end val end + def bool + # see Tcl_GetBoolean man-page + case value.downcase + when '0', 'false', 'no', 'off' + false + else + true + end + end + + def bool=(val) + if ! val + self.value = '0' + else + case val.to_s.downcase + when 'false', '0', 'no', 'off' + self.value = '0' + else + self.value = '1' + end + end + end + def to_i number(value).to_i end @@ -570,7 +624,8 @@ end def trace(opts, cmd = Proc.new) @trace_var = [] if @trace_var == nil - opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') + #opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') + opts = ['r','w','u'].find_all{|c| opts.to_s.index(c)}.join('') @trace_var.unshift([opts,cmd]) if @trace_opts == nil TkVar_CB_TBL[@id] = self @@ -619,7 +674,8 @@ end def trace_element(elem, opts, cmd = Proc.new) @trace_elem = {} if @trace_elem == nil @trace_elem[elem] = [] if @trace_elem[elem] == nil - opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') + #opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') + opts = ['r','w','u'].find_all{|c| opts.to_s.index(c)}.join('') @trace_elem[elem].unshift([opts,cmd]) if @trace_opts == nil TkVar_CB_TBL[@id] = self @@ -678,7 +734,8 @@ end def trace_vdelete(opts,cmd) return self unless @trace_var.kind_of? Array - opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') + #opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') + opts = ['r','w','u'].find_all{|c| opts.to_s.index(c)}.join('') idx = -1 newopts = '' @trace_var.each_with_index{|e,i| @@ -702,7 +759,8 @@ end } } - newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('') + #newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('') + newopts = ['r','w','u'].find_all{|c| newopts.to_s.index(c)}.join('') if newopts != @trace_opts Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts, 'rb_var') =begin @@ -739,7 +797,8 @@ end def trace_vdelete_for_element(elem,opts,cmd) return self unless @trace_elem.kind_of? Hash return self unless @trace_elem[elem].kind_of? Array - opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') + # opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') + opts = ['r','w','u'].find_all{|c| opts.to_s.index(c)}.join('') idx = -1 @trace_elem[elem].each_with_index{|e,i| if idx < 0 && e[0] == opts && e[1] == cmd @@ -765,7 +824,8 @@ end } } - newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('') + #newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('') + newopts = ['r','w','u'].find_all{|c| newopts.to_s.index(c)}.join('') if newopts != @trace_opts Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts, 'rb_var') =begin @@ -807,6 +867,15 @@ class TkVarAccess<TkVariable super(name, *args) end + def self.new_hash(name, *args) + return TkVar_ID_TBL[name] if TkVar_ID_TBL[name] + if args.empty? && INTERP._invoke_without_enc('array', 'exist', name) == '0' + self.new(name, {}) # force creating + else + self.new(name, *args) + end + end + def initialize(varname, val=nil) @id = varname TkVar_ID_TBL[@id] = self @@ -815,6 +884,11 @@ class TkVarAccess<TkVariable INTERP._invoke_without_enc('global', @id) if val + if val.kind_of?(Hash) + # assoc-array variable + self[''] = 0 + self.clear + end #s = '"' + _get_eval_string(val).gsub(/[\[\]$"]/, '\\\\\&') + '"' #" #s = '"' + _get_eval_string(val).gsub(/[\[\]$"\\]/, '\\\\\&') + '"' #" #INTERP._eval(Kernel.format('global %s; set %s %s', @id, @id, s)) diff --git a/ext/tk/sample/demos-en/paned2.rb b/ext/tk/sample/demos-en/paned2.rb index c8c5abb470..53c19c0ffa 100644 --- a/ext/tk/sample/demos-en/paned2.rb +++ b/ext/tk/sample/demos-en/paned2.rb @@ -75,7 +75,7 @@ TkPanedwindow.new($paned2_demo, :orient=>:vertical){|f| } }, - TkFrame.new(f) {|paned2_bottom| + TkFrame.new(f, :height=>120) {|paned2_bottom| # The bottom window is a text widget with scrollbar paned2_xscr = TkScrollbar.new(paned2_bottom) paned2_yscr = TkScrollbar.new(paned2_bottom) diff --git a/ext/tk/sample/demos-jp/entry3.rb b/ext/tk/sample/demos-jp/entry3.rb index f0e9bc868b..4dff97a93a 100644 --- a/ext/tk/sample/demos-jp/entry3.rb +++ b/ext/tk/sample/demos-jp/entry3.rb @@ -64,7 +64,7 @@ TkFrame.new($entry3_demo){|f| # count - Counter to control the number of times flashed def focusAndFlash(widget, fg, bg, count=5) return if count <= 0 - TkTimer.new(200, count, + TkTimer.new(100, count, proc{widget.configure(:foreground=>bg, :background=>fg)}, proc{widget.configure(:foreground=>fg, :background=>bg)} ).start diff --git a/ext/tk/sample/demos-jp/menu8x.rb b/ext/tk/sample/demos-jp/menu8x.rb index 08598f88f8..e2f477da8b 100644 --- a/ext/tk/sample/demos-jp/menu8x.rb +++ b/ext/tk/sample/demos-jp/menu8x.rb @@ -173,7 +173,8 @@ TkMenu.new($menu8x_demo, 'tearoff'=>false) {|m| TkMenu.new(m, 'tearoff'=>false) {|icon_menu| m.add('cascade', 'label'=>'Icons', 'menu'=>icon_menu, 'underline'=>0) add('command', - 'bitmap'=>'@'+[$demo_dir,'images','pattern.bmp'].join(File::Separator), + 'bitmap'=>'@'+[$demo_dir,'..', + 'images','pattern.xbm'].join(File::Separator), 'hidemargin'=>1, 'command'=>proc{TkDialog.new('title'=>'Bitmap Menu Entry', 'text'=>'今あなたが選択したメニューの項目はテキストではなくビットマップを表示していました。それ以外の点では他のメニュー項目と変わりません。', diff --git a/ext/tk/sample/demos-jp/paned2.rb b/ext/tk/sample/demos-jp/paned2.rb index b0261d50f0..c6b0f06914 100644 --- a/ext/tk/sample/demos-jp/paned2.rb +++ b/ext/tk/sample/demos-jp/paned2.rb @@ -78,7 +78,7 @@ TkPanedwindow.new($paned2_demo, :orient=>:vertical){|f| } }, - TkFrame.new(f) {|paned2_bottom| + TkFrame.new(f, :height=>120) {|paned2_bottom| # The bottom window is a text widget with scrollbar paned2_xscr = TkScrollbar.new(paned2_bottom) paned2_yscr = TkScrollbar.new(paned2_bottom) diff --git a/ext/tk/sample/tkcombobox.rb b/ext/tk/sample/tkcombobox.rb index f0cbdac3ba..61ab254691 100644 --- a/ext/tk/sample/tkcombobox.rb +++ b/ext/tk/sample/tkcombobox.rb @@ -62,6 +62,9 @@ EOD delegate('relief', @frame) delegate('borderwidth', @frame) + delegate_alias('arrowrelief', 'relief', @up_arrow, @down_arrow) + delegate_alias('arrowborderwidth', 'borderwidth', @up_arrow, @down_arrow) + scrollbar(keys.delete('scrollbar')){false} configure keys unless keys.empty? @@ -324,6 +327,9 @@ EOD delegate('relief', @frame) delegate('borderwidth', @frame) + delegate('arrowrelief', @lst) + delegate('arrowborderwidth', @lst) + if mode = keys.delete('scrollbar') scrollbar(mode) end @@ -391,6 +397,7 @@ end 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.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) diff --git a/ext/tk/sample/tkmultilistbox.rb b/ext/tk/sample/tkmultilistbox.rb index 257cf95c39..c3787a0cf0 100644 --- a/ext/tk/sample/tkmultilistbox.rb +++ b/ext/tk/sample/tkmultilistbox.rb @@ -109,9 +109,7 @@ class TkMultiListbox < TkListbox @v_scroll.set first, last } } -# @v_scroll.command proc{|*args| @lbox_list.each{|lbox| lbox.yview *args} } - @v_scroll.command proc{|*args| p "";p [@lbox_list, args]; @lbox_list.each{|lbox| lbox.yview *args} } -# @v_scroll.command proc{|*args| p "";p [@lbox_list, args]; @lbox_list.each{|lbox| lbox.yview *args}; p [@lbox_list, args] } + @v_scroll.command proc{|*args| @lbox_list.each{|lbox| lbox.yview *args} } # binding for listboxes @mode = {} diff --git a/ext/tk/tkutil.c b/ext/tk/tkutil.c index bc02b43bf2..560958df84 100644 --- a/ext/tk/tkutil.c +++ b/ext/tk/tkutil.c @@ -30,6 +30,7 @@ static ID ID_path; static ID ID_at_path; static ID ID_to_eval; static ID ID_to_s; +static ID ID_downcase; static ID ID_install_cmd; static ID ID_merge_tklist; static ID ID_call; @@ -219,13 +220,78 @@ tk_symbolkey2str(self, keys) static VALUE get_eval_string_core _((VALUE, VALUE, VALUE)); static VALUE ary2list _((VALUE, VALUE)); +static VALUE ary2list2 _((VALUE, VALUE)); static VALUE hash2list _((VALUE, VALUE)); +static VALUE hash2kv _((VALUE, VALUE, VALUE)); static VALUE ary2list(ary, self) VALUE ary; VALUE self; { + int idx, idx2, size, size2; + volatile VALUE val, val2; + volatile VALUE dst; + + /* size = RARRAY(ary)->len; */ + size = 0; + for(idx = 0; idx < RARRAY(ary)->len; idx++) { + if (TYPE(RARRAY(ary)->ptr[idx]) == T_HASH) { + size += 2 * RHASH(RARRAY(ary)->ptr[idx])->tbl->num_entries; + } else { + size++; + } + } + + dst = rb_ary_new2(size); + RARRAY(dst)->len = 0; + for(idx = 0; idx < RARRAY(ary)->len; idx++) { + val = RARRAY(ary)->ptr[idx]; + switch(TYPE(val)) { + case T_ARRAY: + RARRAY(dst)->ptr[RARRAY(dst)->len++] = ary2list(val, self); + break; + + case T_HASH: + /* RARRAY(dst)->ptr[RARRAY(dst)->len++] = hash2list(val, self); */ + val = hash2kv(val, Qnil, self); + size2 = RARRAY(val)->len; + for(idx2 = 0; idx2 < size2; idx2++) { + val2 = RARRAY(val)->ptr[idx2]; + switch(TYPE(val2)) { + case T_ARRAY: + RARRAY(dst)->ptr[RARRAY(dst)->len++] + = ary2list(val2, self); + break; + + case T_HASH: + RARRAY(dst)->ptr[RARRAY(dst)->len++] + = hash2list(val2, self); + + default: + if (val2 != TK_None) { + RARRAY(dst)->ptr[RARRAY(dst)->len++] + = get_eval_string_core(val2, Qnil, self); + } + } + } + break; + + default: + if (val != TK_None) { + RARRAY(dst)->ptr[RARRAY(dst)->len++] + = get_eval_string_core(val, Qnil, self); + } + } + } + return rb_apply(cTclTkLib, ID_merge_tklist, dst); +} + +static VALUE +ary2list2(ary, self) + VALUE ary; + VALUE self; +{ int idx, size; volatile VALUE val; volatile VALUE dst; @@ -233,7 +299,7 @@ ary2list(ary, self) size = RARRAY(ary)->len; dst = rb_ary_new2(size); RARRAY(dst)->len = 0; - for(idx = 0; idx < size; idx++) { + for(idx = 0; idx < RARRAY(ary)->len; idx++) { val = RARRAY(ary)->ptr[idx]; switch(TYPE(val)) { case T_ARRAY: @@ -377,6 +443,7 @@ push_kv(key, val, ary) if (val != TK_None) rb_ary_push(ary, val); #endif RARRAY(ary)->ptr[RARRAY(ary)->len++] = key2keyname(key); + if (val != TK_None) RARRAY(ary)->ptr[RARRAY(ary)->len++] = val; return ST_CONTINUE; @@ -455,7 +522,7 @@ hash2list(hash, self) VALUE hash; VALUE self; { - return ary2list(hash2kv(hash, Qnil, self), self); + return ary2list2(hash2kv(hash, Qnil, self), self); } @@ -464,7 +531,7 @@ hash2list_enc(hash, self) VALUE hash; VALUE self; { - return ary2list(hash2kv_enc(hash, Qnil, self), self); + return ary2list2(hash2kv_enc(hash, Qnil, self), self); } static VALUE @@ -691,9 +758,12 @@ tcl2rb_bool(self, value) rb_check_type(value, T_STRING); + value = rb_funcall(value, ID_downcase, 0); + if (RSTRING(value)->ptr[0] == '\0' || strcmp(RSTRING(value)->ptr, "0") == 0 || strcmp(RSTRING(value)->ptr, "no") == 0 + || strcmp(RSTRING(value)->ptr, "off") == 0 || strcmp(RSTRING(value)->ptr, "false") == 0) { return Qfalse; } else { @@ -1095,6 +1165,7 @@ Init_tkutil() ID_at_path = rb_intern("@path"); ID_to_eval = rb_intern("to_eval"); ID_to_s = rb_intern("to_s"); + ID_downcase = rb_intern("downcase"); ID_install_cmd = rb_intern("install_cmd"); ID_merge_tklist = rb_intern("_merge_tklist"); ID_call = rb_intern("call"); |