From ed6ce8b43b6f25df1d4809ac799de4dd1c85c1f3 Mon Sep 17 00:00:00 2001 From: nagai Date: Sun, 12 Jul 2009 23:08:32 +0000 Subject: * ext/tk/extconf.rb: New strategy for searching Tcl/Tk libraries. * ext/tk/*: Support new features of Tcl/Tk8.6b1 and minor bug fixes. ( [KNOWN BUG] Ruby/Tk on Ruby 1.9 will not work on Cygwin. ) * ext/tk/*: Unify sources between Ruby 1.8 & 1.9. Improve default_widget_set handling. * ext/tk/*: Multi-TkInterpreter (multi-tk.rb) works on Ruby 1.8 & 1.9. ( [KNOWN BUG] On Ruby 1.8, join to a long term Thread on Tk callbacks may freeze. On Ruby 1.9, cannot create a second master interpreter (creating slaves are OK); supported master interpreter is the default master interpreter only. ) * ext/tk/lib/tkextlib/*: Update supported versions of Tk extensions. Tcllib 1.8/Tklib 0.4.1 ==> Tcllib 1.11.1/Tklib 0.5 BWidgets 1.7 ==> BWidgets 1.8 TkTable 2.9 ==> TkTable 2.10 TkTreeCtrl 2005-12-02 ==> TkTreeCtrl 2.2.9 Tile 0.8.0/8.5.1 ==> Tile 0.8.3/8.6b1 IncrTcl 2005-02-14 ==> IncrTcl 2008-12-15 TclX 2005-02-07 ==> TclX 2008-12-15 Trofs 0.4.3 ==> Trofs 0.4.4 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@24063 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/tk/ChangeLog.tkextlib | 14 + ext/tk/MANUAL_tcltklib.eng | 8 +- ext/tk/MANUAL_tcltklib.eucj | 9 +- ext/tk/README.ActiveTcl | 13 + ext/tk/README.tcltklib | 43 +- ext/tk/config_list.in | 35 + ext/tk/extconf.rb | 1087 +++++++++++++++++--- ext/tk/lib/multi-tk.rb | 343 ++++-- ext/tk/lib/remote-tk.rb | 18 +- ext/tk/lib/tk.rb | 255 +++-- ext/tk/lib/tk/autoload.rb | 398 ++++++- ext/tk/lib/tk/bindtag.rb | 2 +- ext/tk/lib/tk/busy.rb | 118 +++ ext/tk/lib/tk/button.rb | 5 +- ext/tk/lib/tk/canvas.rb | 31 +- ext/tk/lib/tk/canvastag.rb | 29 +- ext/tk/lib/tk/checkbutton.rb | 8 +- ext/tk/lib/tk/composite.rb | 42 +- ext/tk/lib/tk/entry.rb | 5 +- ext/tk/lib/tk/event.rb | 22 +- ext/tk/lib/tk/font.rb | 15 +- ext/tk/lib/tk/fontchooser.rb | 166 +++ ext/tk/lib/tk/frame.rb | 5 +- ext/tk/lib/tk/image.rb | 2 +- ext/tk/lib/tk/itemconfig.rb | 7 + ext/tk/lib/tk/label.rb | 5 +- ext/tk/lib/tk/labelframe.rb | 6 +- ext/tk/lib/tk/listbox.rb | 6 +- ext/tk/lib/tk/macpkg.rb | 4 +- ext/tk/lib/tk/menu.rb | 59 +- ext/tk/lib/tk/menubar.rb | 24 +- ext/tk/lib/tk/menuspec.rb | 207 +++- ext/tk/lib/tk/message.rb | 6 +- ext/tk/lib/tk/msgcat.rb | 2 +- ext/tk/lib/tk/namespace.rb | 2 +- ext/tk/lib/tk/optiondb.rb | 2 +- ext/tk/lib/tk/panedwindow.rb | 8 +- ext/tk/lib/tk/radiobutton.rb | 8 +- ext/tk/lib/tk/root.rb | 2 +- ext/tk/lib/tk/scale.rb | 5 +- ext/tk/lib/tk/scrollbar.rb | 14 +- ext/tk/lib/tk/spinbox.rb | 33 +- ext/tk/lib/tk/text.rb | 16 +- ext/tk/lib/tk/textmark.rb | 2 +- ext/tk/lib/tk/texttag.rb | 5 +- ext/tk/lib/tk/timer.rb | 4 +- ext/tk/lib/tk/toplevel.rb | 6 +- ext/tk/lib/tk/ttk_selector.rb | 34 +- ext/tk/lib/tk/variable.rb | 10 +- ext/tk/lib/tk/virtevent.rb | 2 +- ext/tk/lib/tk/winpkg.rb | 7 +- ext/tk/lib/tkextlib/SUPPORT_STATUS | 24 +- ext/tk/lib/tkextlib/blt.rb | 2 + ext/tk/lib/tkextlib/blt/barchart.rb | 4 +- ext/tk/lib/tkextlib/blt/bitmap.rb | 2 +- ext/tk/lib/tkextlib/blt/busy.rb | 1 + ext/tk/lib/tkextlib/blt/component.rb | 81 +- ext/tk/lib/tkextlib/blt/container.rb | 2 +- ext/tk/lib/tkextlib/blt/dragdrop.rb | 3 +- ext/tk/lib/tkextlib/blt/graph.rb | 4 +- ext/tk/lib/tkextlib/blt/htext.rb | 3 +- ext/tk/lib/tkextlib/blt/stripchart.rb | 4 +- ext/tk/lib/tkextlib/blt/table.rb | 15 +- ext/tk/lib/tkextlib/blt/tabnotebook.rb | 2 +- ext/tk/lib/tkextlib/blt/tabset.rb | 8 +- ext/tk/lib/tkextlib/blt/ted.rb | 5 +- ext/tk/lib/tkextlib/blt/tile.rb | 4 + ext/tk/lib/tkextlib/blt/tree.rb | 4 +- ext/tk/lib/tkextlib/blt/treeview.rb | 25 +- ext/tk/lib/tkextlib/blt/unix_dnd.rb | 8 +- ext/tk/lib/tkextlib/blt/watch.rb | 2 +- ext/tk/lib/tkextlib/bwidget.rb | 2 + ext/tk/lib/tkextlib/bwidget/arrowbutton.rb | 2 +- ext/tk/lib/tkextlib/bwidget/button.rb | 2 +- ext/tk/lib/tkextlib/bwidget/buttonbox.rb | 2 +- ext/tk/lib/tkextlib/bwidget/combobox.rb | 13 +- ext/tk/lib/tkextlib/bwidget/dialog.rb | 16 +- ext/tk/lib/tkextlib/bwidget/entry.rb | 2 +- ext/tk/lib/tkextlib/bwidget/label.rb | 2 +- ext/tk/lib/tkextlib/bwidget/labelentry.rb | 2 +- ext/tk/lib/tkextlib/bwidget/labelframe.rb | 2 +- ext/tk/lib/tkextlib/bwidget/listbox.rb | 7 +- ext/tk/lib/tkextlib/bwidget/mainframe.rb | 6 +- ext/tk/lib/tkextlib/bwidget/messagedlg.rb | 2 +- ext/tk/lib/tkextlib/bwidget/notebook.rb | 2 +- ext/tk/lib/tkextlib/bwidget/pagesmanager.rb | 2 +- ext/tk/lib/tkextlib/bwidget/panedwindow.rb | 7 +- ext/tk/lib/tkextlib/bwidget/panelframe.rb | 14 +- ext/tk/lib/tkextlib/bwidget/passwddlg.rb | 2 +- ext/tk/lib/tkextlib/bwidget/progressbar.rb | 2 +- ext/tk/lib/tkextlib/bwidget/progressdlg.rb | 2 +- ext/tk/lib/tkextlib/bwidget/scrollableframe.rb | 2 +- ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb | 12 +- ext/tk/lib/tkextlib/bwidget/scrollview.rb | 2 +- ext/tk/lib/tkextlib/bwidget/selectcolor.rb | 2 +- ext/tk/lib/tkextlib/bwidget/selectfont.rb | 7 +- ext/tk/lib/tkextlib/bwidget/separator.rb | 2 +- ext/tk/lib/tkextlib/bwidget/spinbox.rb | 2 +- ext/tk/lib/tkextlib/bwidget/statusbar.rb | 18 +- ext/tk/lib/tkextlib/bwidget/titleframe.rb | 2 +- ext/tk/lib/tkextlib/bwidget/tree.rb | 55 +- ext/tk/lib/tkextlib/itcl/incr_tcl.rb | 4 +- ext/tk/lib/tkextlib/itk/incr_tk.rb | 6 +- ext/tk/lib/tkextlib/iwidgets/buttonbox.rb | 5 +- ext/tk/lib/tkextlib/iwidgets/calendar.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/canvasprintbox.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/canvasprintdialog.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/checkbox.rb | 5 +- ext/tk/lib/tkextlib/iwidgets/combobox.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/dateentry.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/datefield.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/dialog.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/dialogshell.rb | 5 +- ext/tk/lib/tkextlib/iwidgets/disjointlistbox.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/entryfield.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/extbutton.rb | 2 +- .../lib/tkextlib/iwidgets/extfileselectionbox.rb | 2 +- .../tkextlib/iwidgets/extfileselectiondialog.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/feedback.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/fileselectionbox.rb | 2 +- .../lib/tkextlib/iwidgets/fileselectiondialog.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/finddialog.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/hierarchy.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/hyperhelp.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/labeledframe.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/labeledwidget.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/mainwindow.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/menubar.rb | 5 +- ext/tk/lib/tkextlib/iwidgets/messagebox.rb | 5 +- ext/tk/lib/tkextlib/iwidgets/messagedialog.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/notebook.rb | 5 +- ext/tk/lib/tkextlib/iwidgets/optionmenu.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/panedwindow.rb | 5 +- ext/tk/lib/tkextlib/iwidgets/promptdialog.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/pushbutton.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/radiobox.rb | 5 +- ext/tk/lib/tkextlib/iwidgets/scopedobject.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/scrolledframe.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/scrolledhtml.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb | 6 +- ext/tk/lib/tkextlib/iwidgets/scrolledwidget.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/selectionbox.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/selectiondialog.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/shell.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/spindate.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/spinint.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/spinner.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/spintime.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/tabnotebook.rb | 5 +- ext/tk/lib/tkextlib/iwidgets/tabset.rb | 5 +- ext/tk/lib/tkextlib/iwidgets/timeentry.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/timefield.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/toolbar.rb | 2 +- ext/tk/lib/tkextlib/iwidgets/watch.rb | 2 +- ext/tk/lib/tkextlib/tcllib.rb | 29 +- ext/tk/lib/tkextlib/tcllib/calendar.rb | 55 + ext/tk/lib/tkextlib/tcllib/canvas_sqmap.rb | 36 + ext/tk/lib/tkextlib/tcllib/canvas_zoom.rb | 21 + ext/tk/lib/tkextlib/tcllib/chatwidget.rb | 151 +++ ext/tk/lib/tkextlib/tcllib/crosshair.rb | 117 +++ ext/tk/lib/tkextlib/tcllib/ctext.rb | 2 +- ext/tk/lib/tkextlib/tcllib/dateentry.rb | 62 ++ ext/tk/lib/tkextlib/tcllib/diagrams.rb | 224 ++++ ext/tk/lib/tkextlib/tcllib/getstring.rb | 2 +- ext/tk/lib/tkextlib/tcllib/ico.rb | 32 +- ext/tk/lib/tkextlib/tcllib/ip_entry.rb | 11 +- ext/tk/lib/tkextlib/tcllib/khim.rb | 68 ++ ext/tk/lib/tkextlib/tcllib/menuentry.rb | 47 + ext/tk/lib/tkextlib/tcllib/ntext.rb | 146 +++ ext/tk/lib/tkextlib/tcllib/panelframe.rb | 8 +- ext/tk/lib/tkextlib/tcllib/plotchart.rb | 616 ++++++++++- ext/tk/lib/tkextlib/tcllib/scrolledwindow.rb | 57 + ext/tk/lib/tkextlib/tcllib/statusbar.rb | 79 ++ ext/tk/lib/tkextlib/tcllib/swaplist.rb | 2 +- ext/tk/lib/tkextlib/tcllib/tablelist.rb | 7 +- ext/tk/lib/tkextlib/tcllib/tablelist_core.rb | 308 +++++- ext/tk/lib/tkextlib/tcllib/tablelist_tile.rb | 20 +- ext/tk/lib/tkextlib/tcllib/toolbar.rb | 175 ++++ ext/tk/lib/tkextlib/tcllib/tooltip.rb | 11 +- ext/tk/lib/tkextlib/tcllib/widget.rb | 34 + ext/tk/lib/tkextlib/tile.rb | 36 +- ext/tk/lib/tkextlib/tile/dialog.rb | 6 + ext/tk/lib/tkextlib/tile/sizegrip.rb | 11 +- ext/tk/lib/tkextlib/tile/style.rb | 20 + ext/tk/lib/tkextlib/tile/tbutton.rb | 9 +- ext/tk/lib/tkextlib/tile/tcheckbutton.rb | 12 +- ext/tk/lib/tkextlib/tile/tcombobox.rb | 9 +- ext/tk/lib/tkextlib/tile/tentry.rb | 9 +- ext/tk/lib/tkextlib/tile/tframe.rb | 9 +- ext/tk/lib/tkextlib/tile/tlabel.rb | 9 +- ext/tk/lib/tkextlib/tile/tlabelframe.rb | 12 +- ext/tk/lib/tkextlib/tile/tmenubutton.rb | 12 +- ext/tk/lib/tkextlib/tile/tnotebook.rb | 18 +- ext/tk/lib/tkextlib/tile/tpaned.rb | 26 +- ext/tk/lib/tkextlib/tile/tprogressbar.rb | 9 +- ext/tk/lib/tkextlib/tile/tradiobutton.rb | 12 +- ext/tk/lib/tkextlib/tile/treeview.rb | 79 +- ext/tk/lib/tkextlib/tile/tscale.rb | 13 +- ext/tk/lib/tkextlib/tile/tscrollbar.rb | 21 +- ext/tk/lib/tkextlib/tile/tseparator.rb | 9 +- ext/tk/lib/tkextlib/tile/tspinbox.rb | 107 ++ ext/tk/lib/tkextlib/tile/tsquare.rb | 2 +- ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb | 4 +- ext/tk/lib/tkextlib/tktable/tktable.rb | 15 +- ext/tk/lib/tkextlib/treectrl/tktreectrl.rb | 87 +- ext/tk/lib/tkextlib/version.rb | 2 +- ext/tk/lib/tkextlib/vu/bargraph.rb | 2 +- ext/tk/lib/tkextlib/vu/dial.rb | 2 +- ext/tk/lib/tkextlib/vu/pie.rb | 8 +- ext/tk/old-extconf.rb | 440 ++++++++ ext/tk/sample/demos-en/widget | 7 +- ext/tk/sample/demos-jp/widget | 8 +- ext/tk/sample/editable_listbox.rb | 131 ++- ext/tk/sample/menubar3.rb | 72 ++ ext/tk/sample/multi-ip_sample.rb | 3 +- ext/tk/sample/safe-tk.rb | 23 +- ext/tk/sample/scrollframe.rb | 20 +- ext/tk/sample/tkalignbox.rb | 44 +- ext/tk/sample/tkballoonhelp.rb | 90 +- ext/tk/sample/tkcombobox.rb | 121 ++- ext/tk/sample/tktextframe.rb | 251 +++-- ext/tk/stubs.c | 33 + ext/tk/tcltklib.c | 373 +++++-- ext/tk/tkutil/extconf.rb | 4 + ext/tk/tkutil/tkutil.c | 60 +- 227 files changed, 7234 insertions(+), 1043 deletions(-) create mode 100644 ext/tk/config_list.in create mode 100644 ext/tk/lib/tk/busy.rb create mode 100644 ext/tk/lib/tk/fontchooser.rb create mode 100644 ext/tk/lib/tkextlib/tcllib/calendar.rb create mode 100644 ext/tk/lib/tkextlib/tcllib/canvas_sqmap.rb create mode 100644 ext/tk/lib/tkextlib/tcllib/canvas_zoom.rb create mode 100644 ext/tk/lib/tkextlib/tcllib/chatwidget.rb create mode 100644 ext/tk/lib/tkextlib/tcllib/crosshair.rb create mode 100644 ext/tk/lib/tkextlib/tcllib/dateentry.rb create mode 100644 ext/tk/lib/tkextlib/tcllib/diagrams.rb create mode 100644 ext/tk/lib/tkextlib/tcllib/khim.rb create mode 100644 ext/tk/lib/tkextlib/tcllib/menuentry.rb create mode 100644 ext/tk/lib/tkextlib/tcllib/ntext.rb create mode 100644 ext/tk/lib/tkextlib/tcllib/scrolledwindow.rb create mode 100644 ext/tk/lib/tkextlib/tcllib/statusbar.rb create mode 100644 ext/tk/lib/tkextlib/tcllib/toolbar.rb create mode 100644 ext/tk/lib/tkextlib/tile/tspinbox.rb create mode 100644 ext/tk/old-extconf.rb create mode 100644 ext/tk/sample/menubar3.rb (limited to 'ext/tk') diff --git a/ext/tk/ChangeLog.tkextlib b/ext/tk/ChangeLog.tkextlib index fc919a5eb5..4aa9cb61d6 100644 --- a/ext/tk/ChangeLog.tkextlib +++ b/ext/tk/ChangeLog.tkextlib @@ -1,3 +1,17 @@ +2009-07-12 Hidetoshi NAGAI + + * ext/tk/lib/tkextlib/*: update release. + Tcllib 1.8/Tklib 0.4.1 ==> Tcllib 1.11.1/Tklib 0.5 + BWidgets 1.7 ==> BWidgets 1.8 + TkTable 2.9 ==> TkTable 2.10 + TkTreeCtrl 2005-12-02 ==> TkTreeCtrl 2.2.9 + Tile 0.8.0/8.5.1 ==> Tile 0.8.3/8.6b1 + IncrTcl 2005-02-14 ==> IncrTcl 2008-12-15 + TclX 2005-02-07 ==> TclX 2008-12-15 + Trofs 0.4.3 ==> Trofs 0.4.4 + +--------------< ... some bug fixes ... >------------------ + Tue Nov 25 03:37:42 2008 Hidetoshi NAGAI * ext/tk/lib/tkextlib/blt/tabset.rb, diff --git a/ext/tk/MANUAL_tcltklib.eng b/ext/tk/MANUAL_tcltklib.eng index 6fa775b7de..c139947da4 100644 --- a/ext/tk/MANUAL_tcltklib.eng +++ b/ext/tk/MANUAL_tcltklib.eng @@ -140,8 +140,7 @@ module TclTklib [module methods] get_version() : return an array of major, minor, release-type number, - : number, release-type name, and patchlevel of current - : Tcl/Tk library. + : and patchlevel of current Tcl/Tk library. mainloop(check_root = true) : Starts the eventloop. If 'check_root' is true, this method @@ -354,6 +353,11 @@ class TclTkIp : to _eval and regist the command once, after that, the : command can be called by _invoke. + _cancel_eval(str) + _cancel_eval_unwind(str) + : (Tcl/Tk8.6 or later) + : Call Tcl_CancelEval() function, and cancel evaluation. + _toUTF8(str, encoding=nil) _fromUTF8(str, encoding=nil) : Call the function (which is internal function of Tcl/Tk) to diff --git a/ext/tk/MANUAL_tcltklib.eucj b/ext/tk/MANUAL_tcltklib.eucj index 7df42997b4..26b39f7943 100644 --- a/ext/tk/MANUAL_tcltklib.eucj +++ b/ext/tk/MANUAL_tcltklib.eucj @@ -235,8 +235,8 @@ require "tcltklib" モジュールメソッド get_version() - : Tcl/Tk の major, minor, release-type 番号, release-type 名, - : patchlevel を配列にして返す. + : Tcl/Tk の major, minor, release-type 番号, patchlevel を + : 配列にして返す. mainloop(check_root = true) : イベントループを起動する.check_root が true であれば, @@ -464,6 +464,11 @@ require "tcltklib" : して登録に成功しさえすれば,以降は _invoke でも利用で : きるようになる. + _cancel_eval(str) + _cancel_eval_unwind(str) + : (Tcl/Tk8.6 or later) + : Tcl_CancelEval() 関数を呼び出し,eval の実行を打ち切る. + _toUTF8(str, encoding=nil) _fromUTF8(str, encoding=nil) : Tcl/Tk が内蔵している UTF8 変換処理を呼び出す. diff --git a/ext/tk/README.ActiveTcl b/ext/tk/README.ActiveTcl index 3afb3f4cf6..c0f9ef8fe4 100644 --- a/ext/tk/README.ActiveTcl +++ b/ext/tk/README.ActiveTcl @@ -3,9 +3,22 @@ ActiveTcl is ActiveState's quality-assured distribution of Tcl. # see # +First of all, please try to configure without any options. +"extconf.rb" searches ActiveTcl as default action. +If you have ActiveTcl and standard (or your own) Tcl/Tk on your +environment and don't want to use ActiveTcl on your Ruby/Tk, please +use --without-ActiveTcl option. + +When "extconf.rb" fails to find your ActiveTcl libraries, please try +the followings. + If you want to use ActiveTcl binary package as the Tcl/Tk libraries, please use the following configure options. + --with-ActiveTcl= + ( When without argument; no ; only '--with-ActiveTcl', + it same to '--with-ActiveTcl=/opt/ActiveTcl*/lib' ) + --with-tcl-dir= --with-tk-dir= diff --git a/ext/tk/README.tcltklib b/ext/tk/README.tcltklib index 8c6dd5178f..0db2758f26 100644 --- a/ext/tk/README.tcltklib +++ b/ext/tk/README.tcltklib @@ -1,18 +1,53 @@ To compile 'tcltklib', you must have Tcl/Tk libraries on your environment. -Although 'extconf.rb' script searches Tcl/Tk libraries and header files, +Although 'extconf.rb' script searches Tcl/Tk libraries and header files +(as default, searches tclConfig.sh/tkConfig.sh and use the defintions on +those; ActiveTcl has high priority on searching unless --without-ActiveTcl), sometimes fails to find them. And then, 'tcltklib' cannot be compiled. If Tcl/Tk libraries or header files are installed but are not found, you can give the information by arguments of the 'configure' script. Please give some or all of the following options. + --with-tk-old-extconf use old "extconf.rb" (default: false). + If current extconf.rb doesn't work properly + (or your install process is based on old + documant about Ruby/Tk install), please try + this option. + + --with-ActiveTcl / --without-ActiveTcl + --with-ActiveTcl= search ActiveTcl libraries (default: true). + When true, try to find installed ActiveTcl. + When is given, use it as the ActiveTcl's + top directory (use /lib, and so on). + Old "extconf.rb" doesn't support this option. + + --with-tk-shlib-search-path= + teach the paths for loading shared-libraries + to linker. + is a path list with the same format + as PATH environment variable. + This option may be experimental. + Old "extconf.rb" doesn't support this option. + --with-tcltkversion= force version of Tcl/Tk libaray (e.g. libtcl8.4g.so ==> --with-tcltkversion=8.4g) + --without-tcl-config / --without-tk-config + --with-tclConfig-dir= + --with-tkConfig-dir= the directory contains 'tclConfig.sh' and + 'tkConfig.sh'. + Current "extconf.rb" uses the information + on tclConfig.sh/tkConfig.rb, if possible. + Old "extconf.rb" doesn't support this option. + --with-tcllib= (e.g. libtcl8.4.so ==> --with-tcllib=tcl8.4) --with-tklib= (e.g. libtk8.4.so ==> --with-tklib=tk8.4) --enable-tcltk-stubs (if you force to enable stubs) + On old "extconf.rb", default is false. + On current "extconf.rb", default is true when + tclConfig.sh/tkConfig.sh have TCL_STUB_LIB_SPEC + /TK_STUB_LIB_SPEC, else default is false. --with-tcl-dir= equal to "--with-tcl-include=/include --with-tcl-lib=/lib" @@ -36,6 +71,12 @@ some or all of the following options. When this option is given, it is assumed that --enable-tcltk-framework option is given also. + --with-tcl-framework-dir= + Tcl framework directory (e.g. "/Library/Frameworks/Tcl.framework") + + --with-tk-framework-dir= + Tk framework directory (e.g. "/Library/Frameworks/Tk.framework") + --with-tcl-framework-header= Tcl framework headers directory (e.g. "/Library/Frameworks/Tcl.framework/Headers") diff --git a/ext/tk/config_list.in b/ext/tk/config_list.in new file mode 100644 index 0000000000..ba0a963bb0 --- /dev/null +++ b/ext/tk/config_list.in @@ -0,0 +1,35 @@ +############################################## +# configure options for Ruby/Tk +# release date: 2009-07-12 +############################################## +with tk-old-extconf +with ActiveTcl +with tk-shlib-search-path +with tcltkversion +with tcl-config +with tk-config +with tclConfig-dir +with tkConfig-dir +with tcllib +with tklib +enable tcltk-stubs +with tcl-dir +with tk-dir +with tcl-include +with tcl-lib +with tcl-lib +with tk-lib +enable mac-tcltk-framework +enable tcltk-framework +with tcltk-framework +with tcl-framework-dir +with tk-framework-dir +with tcl-framework-header +with tk-framework-header +with X11 +with X11-dir +with X11-include +with X11-lib +enable pthread +enable tcl-thread +with tclConfig-file diff --git a/ext/tk/extconf.rb b/ext/tk/extconf.rb index ebc83a0c0b..7d2853a37b 100644 --- a/ext/tk/extconf.rb +++ b/ext/tk/extconf.rb @@ -1,93 +1,126 @@ +############################################################## # extconf.rb for tcltklib - +# release date: 2009-07-12 +############################################################## require 'mkmf' -is_win32 = (/mswin|mingw|cygwin|bccwin/ =~ RUBY_PLATFORM) -#is_macosx = (/darwin/ =~ RUBY_PLATFORM) +TkLib_Config = {} +TkLib_Config['search_versions'] = + %w[8.9 8.8 8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 4.2] -have_func("ruby_native_thread_p", "ruby.h") -have_func("rb_errinfo", "ruby.h") -have_func("rb_safe_level", "ruby.h") -have_struct_member("struct RArray", "ptr", "ruby.h") -have_struct_member("struct RArray", "len", "ruby.h") -def find_framework(tcl_hdr, tk_hdr) - if framework_dir = with_config("tcltk-framework") - paths = [framework_dir] - else - unless tcl_hdr || tk_hdr || - enable_config("tcltk-framework", false) || - enable_config("mac-tcltk-framework", false) - return false - end - paths = ["/Library/Frameworks", "/System/Library/Frameworks"] - end - - checking_for('Tcl/Tk Framework') { - paths.find{|dir| - dir.strip! - dir.chomp!('/') - (tcl_hdr || FileTest.directory?(dir + "/Tcl.framework/") ) && - (tk_hdr || FileTest.directory?(dir + "/Tk.framework/") ) - } - } +############################################################## +# use old extconf.rb ? +############################################################## +if with_config('tk-old-extconf') + require File.join(File.dirname(__FILE__), 'old-extconf.rb') + exit end -tcl_framework_header = with_config("tcl-framework-header") -tk_framework_header = with_config("tk-framework-header") -tcltk_framework = find_framework(tcl_framework_header, tk_framework_header) - -unless is_win32 - have_library("nsl", "t_open") - have_library("socket", "socket") - have_library("dl", "dlopen") - have_library("m", "log") +############################################################## +# check configs +############################################################## +$cleanfiles << 'config_list' +config_list_file = File.join(File.dirname(__FILE__),'config_list') +config_list_file_source = config_list_file + '.in' +if !File.exist?(config_list_file) || + File.ctime(config_list_file_source) > File.ctime(config_list_file) + old_config_list_file = config_list_file_source +else + old_config_list_file = config_list_file end -tk_idir, tk_ldir = dir_config("tk") -tcl_idir, tcl_ldir = dir_config("tcl") -x11_idir, x11_ldir = dir_config("X11") +current_configs = {'with'=>{}, 'enable'=>{}} -tk_ldir2 = with_config("tk-lib") -tcl_ldir2 = with_config("tcl-lib") -x11_ldir2 = with_config("X11-lib") +# setup keys by config_list.in +IO.foreach(config_list_file_source){|line| + line.chomp! + line.lstrip! + next if line.empty? || line =~ /^\#/ # + mode, key, value = line.split(/\s+/, 3) + value ||= "" + current_configs[mode][key] = value rescue nil +} -tk_ldir_list = [tk_ldir2, tk_ldir] -tcl_ldir_list = [tcl_ldir2, tcl_ldir] +# define current value of keys +IO.foreach(old_config_list_file){|line| + line.chomp! + line.lstrip! + next if line.empty? || line =~ /^\#/ # + mode, key, value = line.split(/\s+/, 3) + value ||= "" + if current_configs[mode] && current_configs[mode].has_key?(key) + current_configs[mode][key] = value + end +} -tklib = with_config("tklib") -tcllib = with_config("tcllib") -stubs = enable_config("tcltk_stubs") || with_config("tcltk_stubs") +update_flag = false +current_configs['with'].each_key{|key| + if (value = with_config(key).to_s) != current_configs['with'][key] + update_flag = true + current_configs['with'][key] = value + end +} +current_configs['enable'].each_key{|key| + if (value = enable_config(key).to_s) != current_configs['enable'][key] + update_flag = true + current_configs['enable'][key] = value + end +} -tcltk_version = with_config("tcltkversion") +# update current_configs +if update_flag || !File.exist?(config_list_file) + open(config_list_file, 'w'){|fobj| + fobj.print("# values of current configure options (generated by extconf.rb)\n"); + ['with', 'enable'].each{|mode| + current_configs[mode].each_key{|key| + fobj.print("#{mode} #{key} #{current_configs[mode][key]}\n") + } + } + } +end -use_X = with_config("X11", (! is_win32)) +if update_flag + puts "Configure options for Ruby/Tk may be updated." + puts "So, delete files which depend on old configs." + File.delete(*(Dir.glob(File.join(File.dirname(__FILE__), + "*.#{CONFIG['DLEXT']}")))) + File.delete(*(Dir.glob(File.join(File.dirname(__FILE__), "*.#{$OBJEXT}")))) + File.delete(File.join(File.dirname(__FILE__), 'Makefile')) rescue nil -def parse_tclConfig(file) - # check tclConfig.sh/tkConfig.sh - tbl = {} - IO.foreach(file){|line| - line.strip! - next if line !~ /^([^\#=][^=]*)=(['"]|)(.*)\2$/ - key, val = $1, $3 - tbl[key] = val.gsub(/\$\{([^}]+)\}/){|s| tbl[$1]} rescue nil - } - tbl +else + makefile = File.join(File.dirname(__FILE__),'Makefile') + if File.exist?(makefile) && + File.ctime(config_list_file) > File.ctime(makefile) + # no need to update Makefile + exit + end +end + +############################################################## +# fuctions +############################################################## +def is_win32? + /mswin|mingw|cygwin|bccwin/ =~ RUBY_PLATFORM +end + +def is_macosx? + /darwin/ =~ RUBY_PLATFORM end def check_tcltk_version(version) - return [nil, nil] unless version + return [nil, nil] unless version.kind_of? String version = version.strip tclver = version.dup tkver = version.dup - major = dot = minor = dot = plvl = ext = nil + dot = major = minor_dot = minor = plvl_dot = plvl = ext = nil if version =~ /^(\d)(\.?)(\d)(\.?)(\d*)(.*)$/ - major = $1; minor_dot = $2; minor = $3; plvl_dot = $4; plvl = $5; ext = $6 + major = $1; minor_dot = $2; minor = $3; plvl_dot = $4; plvl = $5; ext = $6 dot = ! minor_dot.empty? if plvl_dot.empty? && ! plvl.empty? minor << plvl @@ -111,12 +144,536 @@ def check_tcltk_version(version) [tclver, tkver] end +def get_shlib_versions(major = 8, minor_max = 9, minor_min = 0, ext = "") + if tclcfg = TkLib_Config["tclConfig_info"] + major = tclcfg['TCL_MAJOR_VERSION'].to_i + minor_min = tclcfg['TCL_MINOR_VERSION'].to_i + + elsif TkLib_Config["tcltkversion"] + tclver, tkver = TkLib_Config["tcltkversion"] + if tclver =~ /8\.?(\d)(.*)/ + minor_min = $1.to_i + ext = $2 + else + # unsupported version + return [""] + end + end + + # if disable-stubs, version is fixed. + minor_max = minor_min unless TkLib_Config["tcltk-stubs"] + + vers = [] + minor_max.downto(minor_min){|minor| + vers << "#{major}.#{minor}#{ext}" unless ext.empty? + vers << "#{major}.#{minor}" + } + + vers << "" +end + +def get_shlib_path_head + path_head = [] + path_dirs = [] + + if TkLib_Config["ActiveTcl"].kind_of?(String) # glob path + path_dirs.concat Dir.glob(TkLib_Config["ActiveTcl"]).sort.reverse + end + + if is_win32? + if TkLib_Config["ActiveTcl"] + path_head.concat ["c:/ActiveTcl", "c:/Program Files/ActiveTcl"] + end + path_head.concat [ + "c:/Tcl", "c:/Program Files/Tcl", + "/Tcl", "/Program Files/Tcl" + ] + path_head.each{|dir| path_dirs << "#{dir}"} + + else + [ + '/opt', '/pkg', '/share', + '/usr/local/opt', '/usr/local/pkg', '/usr/local/share', '/usr/local', + '/usr/opt', '/usr/pkg', '/usr/share', '/usr/contrib', '/usr' + ].each{|dir| + next unless File.directory?(dir) + + path_dirs << "#{dir}/lib" + path_dirs << "#{dir}" unless Dir.glob("#{dir}/lib*.*").empty? + + dirnames = [] + if TkLib_Config["ActiveTcl"] + dirnames.concat ["ActiveTcl","activeTcl","Activetcl","activetcl"] + end + dirnames.concat ["TclTk","Tcl_Tk","Tcl-Tk","tcltk","tcl_tk","tcl-tk"] + + dirnames.each{|name| + path_dirs << "#{dir}/#{name}" if File.directory?("#{dir}/#{name}") + path_head << "#{dir}/#{name}" unless Dir.glob("#{dir}/#{name}[-89_]*").empty? + } + } + end + + [path_head, path_dirs] +end + +def find_macosx_framework + use_framework = is_macosx? && TkLib_Config["ActiveTcl"] + + use_framework ||= (tcl_hdr = with_config("tcl-framework-header")) + use_framework ||= (tk_hdr = with_config("tk-framework-header")) + tcl_hdr = nil unless tcl_hdr.kind_of? String + tk_hdr = nil unless tk_hdr.kind_of? String + TkLib_Config["tcl-framework-header"] = tcl_hdr + TkLib_Config["tk-framework-header"] = tk_hdr + + use_framework ||= (tcl_dir = with_config("tcl-framework-dir")) + tcl_dir = nil unless tcl_dir.kind_of? String + if !tcl_dir && tcl_hdr + # e.g. /Library/Frameworks/Tcl.framework/Headers + # ==> /Library/Frameworks/Tcl.framework + tcl_dir = File.dirname(tcl_hdr.strip.chomp('/')) + end + TkLib_Config["tcl-framework-dir"] = tcl_dir + + use_framework ||= (tk_dir = with_config("tk-framework-dir")) + tk_dir = nil unless tk_dir.kind_of? String + if !tk_dir && tk_hdr + # e.g. /Library/Frameworks/Tk.framework/Headers + # ==> /Library/Frameworks/Tk.framework + tk_dir = File.dirname(tk_hdr.strip.chomp('/')) + end + TkLib_Config["tk-framework-dir"] = tk_dir + + if tcl_dir && !tk_dir + tk_dir = File.join(File.dirname(tcl_dir), 'Tk.framework') + TkLib_Config["tk-framework-dir"] = tk_dir + elsif !tcl_dir && tk_dir + tcl_dir = File.join(File.dirname(tk_dir), 'Tcl.framework') + TkLib_Config["tcl-framework-dir"] = tcl_dir + end + if tcl_dir && tk_dir + TkLib_Config["tcltk-framework"] = File.dirname(tcl_dir) unless TkLib_Config["tcltk-framework"] + return [tcl_dir, tk_dir] + end + + # framework is disabled? + if with_config("tcltk-framework") == false || + enable_config("tcltk-framework") == false + return false + end + + use_framework ||= (framework_dir = with_config("tcltk-framework")) + if framework_dir.kind_of? String + TkLib_Config["tcltk-framework"] = framework_dir.strip.chomp('/') + return [File.join(TkLib_Config["tcltk-framework"], 'Tcl.framework'), + File.join(TkLib_Config["tcltk-framework"], 'Tk.framework')] + end + + unless enable_config("tcltk-framework", use_framework) || + enable_config("mac-tcltk-framework", use_framework) + TkLib_Config["tcltk-framework"] = false + return false + end + + paths = [ + #"~/Library/Frameworks", + "/Library/Frameworks", + "/Network/Library/Frameworks", "/System/Library/Frameworks" + ] + + paths.map{|dir| dir.strip.chomp('/')}.each{|dir| + next unless File.directory?(tcldir = File.join(dir, "Tcl.framework")) + next unless File.directory?(tkdir = File.join(dir, "Tk.framework")) + TkLib_Config["tcltk-framework"] = dir + return [tcldir, tkdir] + } + + nil +end + +def collect_tcltk_defs(tcl_defs_str, tk_defs_str) + conflicts = [ + 'PACKAGE_NAME', 'PACKAGE_TARNAME', 'PACKAGE_VERSION', + 'PACKAGE_STRING', 'PACKAGE_BUGREPORT' + ] + + begin + # Ruby 1.9.x or later + arch_config_h = RbConfig.expand($arch_hdrdir + "/ruby/config.h") + if File.exist?(arch_config_h) + keys = [] + IO.foreach(arch_config_h){|line| + if line =~ /^#define +([^ ]+)/ + keys << $1 + end + } + conflicts = keys + end + rescue + # ignore, use default + end + + if tcl_defs_str + tcl_defs = tcl_defs_str.split(/ ?-D/).map{|s| + s =~ /^([^=]+)(.*)$/ + [$1, $2] + } + else + tcl_defs = [] + end + + if tk_defs_str + tk_defs = tk_defs_str.split(/ ?-D/).map{|s| + s =~ /^([^=]+)(.*)$/ + [$1, $2] + } + else + tk_defs = [] + end + + defs = tcl_defs | tk_defs + + defs.delete_if{|name,value| + conflicts.include?(name) || + ( (vtcl = tcl_defs.assoc(name)) && (vtk = tk_defs.assoc(name)) && + vtcl != vtk ) + } + + defs.map{|ary| s = ary.join(''); (s.strip.empty?)? "": "-D" << s}.join(' ') +end + +def parse_tclConfig(file) + # check tclConfig.sh/tkConfig.sh + tbl = Hash.new{|h,k| h[k] = ""} + return tbl unless file + IO.foreach(file){|line| + line.strip! + next if line !~ /^([^\#=][^=]*)=(['"]|)(.*)\2$/ + key, val = $1, $3 + tbl[key] = val.gsub(/\$\{([^}]+)\}/){|s| + subst = $1 + (tbl[subst])? tbl[subst]: s + } rescue nil + } + tbl +end + +def get_libpath(lib_flag, lib_spec) + # get libpath fro {TCL,Tk}_LIB_FLAG and {TCL,Tk}_LIB_SPEC + libpath = lib_spec.gsub(/(#{lib_flag}|-L)/, "").strip +end + +def search_tclConfig(*paths) # list of lib-dir or [tcl-libdir, tk-libdir] + TkLib_Config["tclConfig_paths"] = [] + config_dir = [] + + paths.compact! + + fixed_tclConfig = ! paths.empty? + + paths.each{|path| + if path.kind_of?(Array) + config_dir << path + else + dirs = Dir.glob(path) + config_dir.concat(dirs.zip(dirs)) + end + } + + if is_win32? + if TkLib_Config["ActiveTcl"] + dirs = [] + if TkLib_Config["ActiveTcl"].kind_of?(String) + dirs << TkLib_Config["ActiveTcl"] + end + dirs.concat [ + "c:/ActiveTcl*/lib", "c:/Activetcl*/lib", + "c:/activeTcl*/lib", "c:/activetcl*/lib", + "c:/Tcl*/lib", "c:/tcl*/lib", + "c:/Program Files/ActiveTcl*/lib", "c:/Program Files/Activetcl*/lib", + "c:/Program Files/activeTcl*/lib", "c:/Program Files/activetcl*/lib", + "c:/Program Files/Tcl*/lib", "c:/Program Files/tcl*/lib", + "/ActiveTcl*/lib", "/Activetcl*/lib", + "/activeTcl*/lib", "/activetcl*/lib", + "/Tcl*/lib", "/tcl*/lib", + "/Program Files/ActiveTcl*/lib", "/Program Files/Activetcl*/lib", + "/Program Files/activeTcl*/lib", "/Program Files/activetcl*/lib", + "/Program Files/Tcl*/lib", "/Program Files/tcl*/lib" + ] + else + dirs = [ + "c:/Tcl*/lib", "c:/tcl*/lib", + "c:/Program Files/Tcl*/lib", "c:/Program Files/tcl*/lib", + "/Tcl*/lib", "/tcl*/lib", + "/Program Files/Tcl*/lib", "/Program Files/tcl*/lib" + ] + end + dirs.collect{|d| Dir.glob(d)}.flatten! + dirs |= dirs + + ENV['PATH'].split(';').each{|dir| + dirs << File.expand_path(File.join(dir, '..', 'lib')) + dirs << dir + dirs << File.expand_path(File.join(dir, '..')) + } + + config_dir.concat(dirs.zip(dirs)) + + elsif framework = find_macosx_framework() + config_dir.unshift(framework) + + else + if activeTcl = TkLib_Config['ActiveTcl'] + # check latest version at first + config_dir.concat(Dir.glob(activeTcl).sort.reverse) + end + + config_dir.concat [ + RbConfig::CONFIG['libdir'], + File.join(RbConfig::CONFIG['exec_prefix'], 'lib'), + File.join(RbConfig::CONFIG['prefix'], 'lib'), + "/usr/local/opt/lib", "/usr/local/pkg/lib", "/usr/local/share/lib", + "/usr/local/lib", "/usr/opt/lib", "/usr/pkg/lib", + "/usr/share/lib", "/usr/contrib/lib", "/usr/lib" + ] + + config_dir.concat [ + '/opt', '/pkg', '/share', + '/usr/local/opt', '/usr/local/pkg', '/usr/local/share', '/usr/local', + '/usr/opt', '/usr/pkg', '/usr/share', '/usr/contrib', '/usr' + ].map{|dir| + Dir.glob(dir + '/{TclTk,tcltk,Tcl,tcl,Tk,tk}[87]*/lib') + Dir.glob(dir + '/{TclTk,tcltk,Tcl,tcl,Tk,tk}[87]*') + Dir.glob(dir + '/{TclTk,tcltk,Tcl,tcl,Tk,tk}/lib') + Dir.glob(dir + '/{TclTk,tcltk,Tcl,tcl,Tk,tk}') + }.flatten! + + ENV['PATH'].split(':').each{|dir| + config_dir << File.expand_path(File.join(dir, '..', 'lib')) + } + + # for MacOS X + #config_dir << "~/Library/Tcl" + #config_dir.concat(Dir.glob("~/Library/Tcl/*").sort.reverse) + config_dir << "/Library/Tcl" + config_dir.concat(Dir.glob("/Library/Tcl/*").sort.reverse) + config_dir << "/Network/Library/Tcl" + config_dir.concat(Dir.glob("/Network/Library/Tcl/*").sort.reverse) + config_dir << "/System/Library/Tcl" + config_dir.concat(Dir.glob("/System/Library/Tcl/*").sort.reverse) + [ + #"~/Library/Frameworks", + "/Library/Frameworks", + "/Network/Library/Frameworks", "/System/Library/Frameworks" + ].each{|framework| + config_dir << [File.expand_path(File.join(framework, 'Tcl.framework')), + File.expand_path(File.join(framework, 'Tk.framework'))] + } + end + + tclver, tkver = TkLib_Config['tcltkversion'] + conf = nil + + config_dir.map{|dir| + if dir.kind_of? Array + [dir[0].strip.chomp('/'), dir[1].strip.chomp('/')] + else + dir.strip.chomp('/') + end + }.each{|dir| + # print("check #{dir} ==>"); + if dir.kind_of? Array + tcldir, tkdir = dir + else + tcldir = tkdir = dir + end + + ['Config-shared.sh','config-shared.sh','Config.sh','config.sh'].each{|f| + tclpath = File.join(tcldir, 'tcl' << f) + tkpath = File.join(tkdir, 'tk' << f) + next if !File.exist?(tclpath) || !File.exist?(tkpath) + + # parse tclConfig.sh/tkConfig.sh + tclconf = parse_tclConfig(tclpath) + next if tclver && tclver !~ /^#{tclconf['TCL_MAJOR_VERSION']}(\.?)#{tclconf['TCL_MINOR_VERSION']}/ + tkconf = parse_tclConfig(tkpath) + next if tkver && tkver !~ /^#{tkconf['TK_MAJOR_VERSION']}(\.?)#{tkconf['TK_MINOR_VERSION']}/ + + # find tclConfig.sh & tkConfig.sh + conf = [tclconf, tkconf] unless conf + + # nativethread check + unless TkLib_Config["ruby_with_thread"] + tclconf['TCL_THREADS'] == '1' + puts "WARNIG: find #{tclpath.inspect}, but it WITH nativethread-support under ruby WITHOUT nativethread-support. So, ignore it." + TkLib_Config["tcltk-NG-path"] << File.dirname(tclpath) + next + end + + #return [tclpath, tkpath] + # print(" #{[tclpath, tkpath]}"); + TkLib_Config["tclConfig_paths"] << [tclpath, tkpath] + } + + # print("\n"); + } + + if TkLib_Config["tclConfig_paths"].empty? + [nil, nil] + else + # find tclConfig.sh and tkConfig.sh + TkLib_Config["tclConfig_info"], TkLib_Config["tkConfig_info"] = conf + TkLib_Config["tclConfig_paths"][0] + end +end + +def get_tclConfig(tclConfig_file, tclConfig_dir, tkConfig_dir) + use_tclConfig = (tclConfig_file != false) && + (tclConfig_dir != false) && (tkConfig_dir != false) + + tclConfig_file = nil unless tclConfig_file.kind_of? String + tclConfig_dir = nil unless tclConfig_dir.kind_of? String + tkConfig_dir = nil unless tkConfig_dir.kind_of? String + + unless tclConfig_dir + if tclConfig_file + tclConfig_dir = File.dirname(tclConfig_file) + elsif tkConfig_dir + tclConfig_dir = tkConfig_dir + end + end + tkConfig_dir ||= tclConfig_dir + + TkLib_Config["tclConfig-file"] = tclConfig_file + TkLib_Config["tclConfig-dir"] = tclConfig_dir + TkLib_Config["tkConfig-dir"] = tkConfig_dir + + unless use_tclConfig + puts("Don't use [tclConfig.sh, tkConfig.sh]") + else + puts("Search tclConfig.sh and tkConfig.sh.") + if tclConfig_dir + tclConfig, tkConfig = search_tclConfig([tclConfig_dir, tkConfig_dir]) + else + tclConfig, tkConfig = search_tclConfig() + end + # TclConfig_Info = TkLib_Config["tclConfig_info"] + # TkConfig_Info = TkLib_Config["tkConfig_info"] + + if tclConfig && tkConfig + puts("Use [tclConfig.sh,tkConfig.sh] == ['#{tclConfig}','#{tkConfig}']") + $LIBPATH |= [File.dirname(tclConfig)] + $LIBPATH |= [File.dirname(tkConfig)] + #TkLib_Config["tclConfig_paths"].each{|tclcfg, tkcfg| + # $LIBPATH |= [File.dirname(tclcfg)] | [File.dirname(tkcfg)] + #} + else + puts("Fail to find [tclConfig.sh, tkConfig.sh]") + end + end + + [tclConfig, tkConfig] +end + +def check_NG_path(path_list) + path_list.find_all{|path| not TkLib_Config["tcltk-NG-path"].include?(path) } +end + +def check_shlib_search_path(paths) + if !paths || paths.empty? + path_list = [] + + #if TkLib_Config["ActiveTcl"] + # path_list.concat Dir.glob(TkLib_Config["ActiveTcl"]).sort.reverse + #end + if TkLib_Config["ActiveTcl"].kind_of?(String) # glob path + path_list.concat Dir.glob(TkLib_Config["ActiveTcl"]).sort.reverse + end + + vers = get_shlib_versions + path_head, path_dirs = get_shlib_path_head + + path_list.concat vers.map{|ver| + path_head.map{|head| + if ver.empty? + head + "/lib" + else + dirs = [] + + if !Dir.glob(head + "-*").empty? + dirs << head + "-#{ver}/lib" if !Dir.glob(head + "-[89].*").empty? + dirs << head + "-#{ver.delete('.')}/lib" if !Dir.glob(head + "-[89][0-9]*").empty? + end + + if !Dir.glob(head + "[_-]*").empty? + dirs << head + "_#{ver}/lib" if !Dir.glob(head + "_[89].*").empty? + dirs << head + "-#{ver}/lib" if !Dir.glob(head + "-[89].*").empty? + dirs << head + "_#{ver.delete('.')}/lib" if !Dir.glob(head + "_[89][0-9]*").empty? + dirs << head + "-#{ver.delete('.')}/lib" if !Dir.glob(head + "-[89][0-9]*").empty? + end + + dirs + end + } + }.flatten! + + path_list.concat path_dirs + + else + # paths is a string with PATH environment style + path_list = paths.split((is_win32?)? ';': ':') + end + + path_list = check_NG_path(path_list) + + path_list.each{|path| $LIBPATH |= [path.strip] } +end + def find_tcl(tcllib, stubs, version, *opt_paths) - default_paths = ["/usr/local/lib", "/usr/pkg/lib", "/usr/lib"] - default_paths << "/Tcl/lib" # default for ActiveTcl + puts "Search Tcl library" + default_paths = [] + + default_paths.concat [ + RbConfig::CONFIG['libdir'], + File.join(RbConfig::CONFIG['exec_prefix'], 'lib'), + File.join(RbConfig::CONFIG['prefix'], 'lib'), + "/usr/local/lib", "/usr/pkg/lib", "/usr/contrib/lib", "/usr/lib" + ].find_all{|dir| File.directory?(dir)} + + default_paths.concat [ + "c:/Tcl/lib", "c:/Program Files/Tcl/lib", + "/Tcl/lib", "/Program Files/Tcl/lib" + ].find_all{|dir| File.directory?(dir)} if (paths = opt_paths.compact).empty? - paths = default_paths + if TclConfig_Info['config_file_path'] + # use definisions on tclConfig.sh + TclConfig_Info['TCL_LIB_SPEC'].sub(TclConfig_Info['TCL_LIB_FLAG'],"").strip.sub("-L","") =~ /("|'|)([^"']+)\1/ + $LIBPATH |= [$2] unless $2.empty? + + unless stubs + #*** Probably, TCL_LIBS is a subset of TK_LIBS. *** + # $LDFLAGS << ' ' << TclConfig_Info['TCL_LIBS'] + # $DLDFLAGS << ' ' << TclConfig_Info['TCL_LIBS'] + $LDFLAGS << ' ' << TclConfig_Info['TCL_LIB_SPEC'] + return true + end + + if TclConfig_Info['TCL_SUPPORTS_STUBS'] == '0' || + TclConfig_Info['TCL_STUB_LIB_SPEC'].strip.empty? + puts "#{TclConfig_Info['config_file_path']} tells us that your Tcl/Tk library doesn't support stub." + return false + else + #*** Probably, TCL_LIBS is a subset of TK_LIBS. *** + # $LDFLAGS << ' ' << TclConfig_Info['TCL_LIBS'] + # $DLDFLAGS << ' ' << TclConfig_Info['TCL_LIBS'] + $LDFLAGS << ' ' << TclConfig_Info['TCL_STUB_LIB_SPEC'] + return true + end + end + + paths = check_NG_path(default_paths) end if stubs @@ -130,7 +687,7 @@ def find_tcl(tcllib, stubs, version, *opt_paths) if version && ! version.empty? versions = [version] else - versions = %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 7.6] + versions = TkLib_Config['search_versions'] end if tcllib @@ -154,12 +711,62 @@ def find_tcl(tcllib, stubs, version, *opt_paths) st end +def parse_TK_LIBS(tklibs) + sfx = "lib|shlib|dll|so" + re = /(("|')[^"']+\.(#{sfx})\2|[^"' ]+\.(#{sfx})|-l("|')[^"']+\5|-l[^" ]+)/#' + + tklibs.scan(re).map{|lib,| + if lib =~ /^("|')([^"]+)\.(#{sfx})\1/ + "\"-l#{$2}\"" + elsif lib =~ /([^" ]+)\.(#{sfx})/ + "-l#{$1}" + else + lib + end + }.join(' ') +end + def find_tk(tklib, stubs, version, *opt_paths) - default_paths = ["/usr/local/lib", "/usr/pkg/lib", "/usr/lib"] - default_paths << "/Tcl/lib" # default for ActiveTcl + puts "Search Tk library" + default_paths = [] + + default_paths.concat [ + RbConfig::CONFIG['libdir'], + File.join(RbConfig::CONFIG['exec_prefix'], 'lib'), + File.join(RbConfig::CONFIG['prefix'], 'lib'), + "/usr/local/lib", "/usr/pkg/lib", "/usr/contrib/lib", "/usr/lib" + ].find_all{|dir| File.directory?(dir)} + + default_paths.concat [ + "c:/Tcl/lib", "c:/Program Files/Tcl/lib", + "/Tcl/lib", "/Program Files/Tcl/lib" + ].find_all{|dir| File.directory?(dir)} if (paths = opt_paths.compact).empty? - paths = default_paths + if TkConfig_Info['config_file_path'] + # use definisions on tkConfig.sh + TkConfig_Info['TK_LIB_SPEC'].sub(TkConfig_Info['TK_LIB_FLAG'],"").strip.sub("-L","") =~ /("|'|)([^"']+)\1/ + $LIBPATH |= [$2] unless $2.empty? + + unless stubs + $LDFLAGS << ' ' << parse_TK_LIBS(TkConfig_Info['TK_LIBS']) + # $DLDFLAGS << ' ' << parse_TK_LIBS(TkConfig_Info['TK_LIBS']) + $LDFLAGS << ' ' << TkConfig_Info['TK_LIB_SPEC'] + return true + end + + if TkConfig_Info['TK_STUB_LIB_SPEC'].strip.empty? + puts "#{TkConfig_Info['config_file_path']} tells us that your Tcl/Tk library doesn't support stub." + return false + else + $LDFLAGS << ' ' << parse_TK_LIBS(TkConfig_Info['TK_LIBS']) + # $DLDFLAGS << ' ' << parse_TK_LIBS(TkConfig_Info['TK_LIBS']) + $LDFLAGS << ' ' << TkConfig_Info['TK_STUB_LIB_SPEC'] + return true + end + end + + paths = check_NG_path(default_paths) end if stubs @@ -173,7 +780,7 @@ def find_tk(tklib, stubs, version, *opt_paths) if version && ! version.empty? versions = [version] else - versions = %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 4.2] + versions = TkLib_Config['search_versions'] end if tklib @@ -198,38 +805,93 @@ def find_tk(tklib, stubs, version, *opt_paths) end def find_tcltk_header(tclver, tkver) - base_dir = ['/usr/local/include', '/usr/pkg/include', '/usr/include'] - base_dir << '/Tcl/include' # default for ActiveTcl + base_dir = [] + + base_dir.concat [ + File.join(RbConfig::CONFIG['prefix'], 'include'), + "/usr/local/include", "/usr/pkg/include", "/usr/contrib/include", + "/usr/include" + ].find_all{|dir| File.directory?(dir)} - unless have_tcl_h = have_header('tcl.h') + base_dir.concat [ + "c:/Tcl/include", "c:/Program Files/Tcl/include", + "/Tcl/include", "/Program Files/Tcl/include" + ].find_all{|dir| File.directory?(dir)} + + if TclConfig_Info['TCL_INCLUDE_SPEC'] && + have_tcl_h = try_cpp('tcl.h', TclConfig_Info['TCL_INCLUDE_SPEC']) + $INCFLAGS << " " << TclConfig_Info['TCL_INCLUDE_SPEC'] + elsif have_tcl_h = have_header('tcl.h') + # find + else if tclver && ! tclver.empty? versions = [tclver] else - versions = %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 7.6] + versions = TkLib_Config['search_versions'] end paths = base_dir.dup - versions.each{|ver| paths.concat(base_dir.map{|dir| dir + '/tcl' + ver})} + versions.each{|ver| + paths.concat(base_dir.map{|dir| + [dir + '/tcl' + ver, dir + '/tcl' + ver.delete('.')] + }.flatten) + } have_tcl_h = find_header('tcl.h', *paths) end - unless have_tk_h = have_header("tk.h") + if TkConfig_Info['TK_INCLUDE_SPEC'] && + have_tk_h = try_cpp('tk.h', TclConfig_Info['TK_INCLUDE_SPEC']) + $INCFLAGS << " " << TkConfig_Info['TK_INCLUDE_SPEC'] + elsif have_tk_h = have_header('tk.h') + # find + else if tkver && ! tkver.empty? versions = [tkver] else - versions = %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 4.2] + versions = TkLib_Config['search_versions'] end paths = base_dir.dup - versions.each{|ver| paths.concat(base_dir.map{|dir| dir + '/tk' + ver})} + versions.each{|ver| + paths.concat(base_dir.map{|dir| + [dir + '/tk' + ver, dir + '/tk' + ver.delete('.')] + }.flatten) + } have_tk_h = find_header('tk.h', *paths) end have_tcl_h && have_tk_h end +def setup_for_macosx_framework + # search directory of header files + if File.exist?(dir = File.join(TkLib_Config["tcltk-framework"], + 'Tcl.framework', 'Headers')) + TclConfig_Info['TCL_INCLUDE_SPEC'] = "-I#{dir} " + TclConfig_Info['TK_INCLUDE_SPEC'] = "-I#{File.join(TkLib_Config['tcltk-framework'], 'Tk.framework', 'Headers')} " + else + dir = Dir.glob(File.join(TkLib_Config["tcltk-framework"], + 'Tcl.framework', '*', 'Headers')) + TclConfig_Info['TCL_INCLUDE_SPEC'] = "-I#{dir[0]} " unless dir.empty? + TclConfig_Info['TK_INCLUDE_SPEC'] = "-I#{Dir.glob(File.join(TkLib_Config['tcltk-framework'], 'Tk.framework', '*', 'Headers'))[0]} " + end + + $LDFLAGS << ' -framework Tk -framework Tcl' + + if TkLib_Config["tcl-framework-header"] + TclConfig_Info['TCL_INCLUDE_SPEC'] = + "-I#{TkLib_Config["tcl-framework-header"]} " + end + if TkLib_Config["tk-framework-header"] + TkConfig_Info['TK_INCLUDE_SPEC'] = + "-I#{TkLib_Config["tk-framework-header"]} " + end +end + def find_X11(*opt_paths) - default_paths = - [ "/usr/X11/lib", "/usr/lib/X11", "/usr/X11R6/lib", "/usr/openwin/lib" ] - paths = opt_paths.compact.concat(default_paths) + defaults = + [ "/usr/X11*/lib", "/usr/lib/X11*", "/usr/local/X11*", "/usr/openwin/lib" ] + paths = [] + opt_paths.compact.each{|path| paths.concat(Dir.glob(path.strip.chomp('/')))} + defaults.compact.each{|path| paths.concat(Dir.glob(path.strip.chomp('/')))} st = find_library("X11", "XOpenDisplay", *paths) unless st puts("Warning:: cannot find X11 library. tcltklib will not be compiled (tcltklib is disabled on your Ruby == Ruby/Tk will not work). Please check configure options. If your Tcl/Tk don't require X11, please try --without-X11.") @@ -237,6 +899,31 @@ def find_X11(*opt_paths) st end +def search_X_libraries + if TkConfig_Info['config_file_path'] + # use definitions on tkConfig.sh + if TkConfig_Info['TK_XINCLUDES'] && TkConfig_Info['TK_XLIBSW'] && + !TkConfig_Info['TK_XINCLUDES'].strip.empty? && + !TkConfig_Info['TK_XLIBSW'].strip.empty? + use_X = true && with_config("X11", (! is_win32?)) + else + use_X = false || with_config("X11", false) + end + else + # depend on configure options + use_X = with_config("X11", (! is_win32?)) + end + + if use_X + puts("Use X11 libraries.") + x11_idir, x11_ldir = dir_config("X11") + x11_ldir2 = with_config("X11-lib") + exit unless find_X11(x11_ldir2, x11_ldir) + end + + use_X +end + def pthread_check() tcl_major_ver = nil tcl_minor_ver = nil @@ -251,42 +938,36 @@ def pthread_check() tcl_enable_thread = nil end - if (tclConfig = with_config("tclConfig-file")) + if TclConfig_Info['config_file_path'] if tcl_enable_thread == true - puts("Warning: --with-tclConfig-file option is ignored, because --enable-tcl-thread option is given.") + puts("Warning: definiton of tclConfig.sh is ignored, because --enable-tcl-thread option is given.") elsif tcl_enable_thread == false - puts("Warning: --with-tclConfig-file option is ignored, because --disable-tcl-thread option is given.") + puts("Warning: definition of tclConfig.sh is ignored, because --disable-tcl-thread option is given.") else # tcl-thread is unknown and tclConfig.sh is given - begin - tbl = parse_tclConfig(tclConfig) - if tbl['TCL_THREADS'] - tcl_enable_thread = (tbl['TCL_THREADS'] == "1") - else - tcl_major_ver = tbl['TCL_MAJOR_VERSION'].to_i - tcl_minor_ver = tbl['TCL_MINOR_VERSION'].to_i - if tcl_major_ver < 8 || (tcl_major_ver == 8 && tcl_minor_ver == 0) - tcl_enable_thread = false - end + if TclConfig_Info['TCL_THREADS'] + tcl_enable_thread = (TclConfig_Info['TCL_THREADS'] == "1") + else + tcl_major_ver = TclConfig_Info['TCL_MAJOR_VERSION'].to_i + tcl_minor_ver = TclConfig_Info['TCL_MINOR_VERSION'].to_i + if tcl_major_ver < 8 || (tcl_major_ver == 8 && tcl_minor_ver == 0) + tcl_enable_thread = false end + end - if tcl_enable_thread == nil - # cannot find definition - if tcl_major_ver - puts("Warning: '#{tclConfig}' doesn't include TCL_THREADS definition.") - else - puts("Warning: '#{tclConfig}' may not be a tclConfig file.") - end - tclConfig = false + if tcl_enable_thread == nil + # cannot find definition + if tcl_major_ver + puts("Warning: '#{TclConfig_Info['config_file_path']}' doesn't include TCL_THREADS definition.") + else + puts("Warning: '#{TclConfig_Info['config_file_path']}' may not be a tclConfig file.") end - rescue Exception - puts("Warning: fail to read '#{tclConfig}'!! --> ignore the file") tclConfig = false end end end - if tcl_enable_thread == nil && !tclConfig + if tcl_enable_thread == nil && !TclConfig_Info['config_file_path'] # tcl-thread is unknown and tclConfig is unavailable begin try_run_available = try_run("int main() { exit(0); }") @@ -295,12 +976,12 @@ def pthread_check() puts(%Q'\ ***************************************************************************** ** -** PTHREAD SUPPORT CHECK WARNING: +** NATIVETHREAD SUPPORT CHECK WARNING: ** -** We cannot check the consistency of pthread support between Ruby -** and the Tcl/Tk library in your environment (are you perhaps -** cross-compiling?). If pthread support for these 2 packages is -** inconsistent you may find you get errors when running Ruby/Tk +** We cannot check the consistency of nativethread support between +** Ruby and the Tcl/Tk library in your environment (are you perhaps +** cross-compiling?). If nativethread support for these 2 packages +** is inconsistent you may find you get errors when running Ruby/Tk ** (e.g. hangs or segmentation faults). We strongly recommend ** you to check the consistency manually. ** @@ -333,26 +1014,27 @@ EOF end # check pthread mode - if (macro_defined?('HAVE_NATIVETHREAD', '#include "ruby.h"')) + if (TkLib_Config["ruby_with_thread"]) # ruby -> enable unless tcl_enable_thread # ruby -> enable && tcl -> disable puts(%Q'\ ***************************************************************************** ** -** PTHREAD SUPPORT MODE WARNING: +** NATIVETHREAD SUPPORT MODE WARNING: ** -** Ruby is compiled with --enable-pthread, but your Tcl/Tk library -** seems to be compiled without pthread support. Although you can -** create the tcltklib library, this combination may cause errors -** (e.g. hangs or segmentation faults). If you have no reason to -** keep the current pthread support status, we recommend you reconfigure -** and recompile the libraries so that both or neither support pthreads. +** Ruby is compiled with --enable-pthread, but your Tcl/Tk library +** seems to be compiled without nativethread support. Although you can +** create the tcltklib library, this combination may cause errors (e.g. +** hangs or segmentation faults). If you have no reason to keep the +** current nativethread support status, we recommend you reconfigure and +** recompile the libraries so that both or neither support nativethreads. ** -** If you want change the status of pthread support, please recompile -** Ruby without "--enable-pthread" configure option or recompile Tcl/Tk -** with "--enable-threads" configure option (if your Tcl/Tk is later -** than or equal to Tcl/Tk 8.1). +** If you want change the status of nativethread support, please recompile +** Ruby without "--enable-pthread" configure option (If you use Ruby 1.9.x +** or later, you cannot remove this option, because it requires native- +** thread support.) or recompile Tcl/Tk with "--enable-threads" configure +** option (if your Tcl/Tk is later than or equal to Tcl/Tk 8.1). ** ***************************************************************************** ') @@ -374,13 +1056,13 @@ EOF puts(%Q'\ ***************************************************************************** ** -** PTHREAD SUPPORT MODE ERROR: +** NATIVETHREAD SUPPORT MODE ERROR: ** ** Ruby is not compiled with --enable-pthread, but your Tcl/Tk -** library seems to be compiled with pthread support. This +** library seems to be compiled with nativethread support. This ** combination may cause frequent hang or segmentation fault ** errors when Ruby/Tk is working. We recommend that you NEVER -** create the library with such a combination of pthread support. +** create the library with such a combination of nativethread support. ** ** Please recompile Ruby with the "--enable-pthread" configure option ** or recompile Tcl/Tk with the "--disable-threads" configure option. @@ -397,44 +1079,135 @@ EOF end end -tclver, tkver = check_tcltk_version(tcltk_version) +############################################################## +# main +############################################################## +# check header files +have_func("ruby_native_thread_p", "ruby.h") +have_func("rb_errinfo", "ruby.h") +have_func("rb_safe_level", "ruby.h") +have_func("rb_hash_lookup", "ruby.h") +have_func("rb_proc_new", "ruby.h") +have_func("rb_obj_untrust", "ruby.h") +have_func("rb_obj_taint", "ruby.h") +have_func("rb_set_safe_level_force", "ruby.h") -if ( tcltk_framework || - ( find_tcltk_header(tclver, tkver) && - ( !use_X || find_X11(x11_ldir2, x11_ldir) ) && - find_tcl(tcllib, stubs, tclver, *tcl_ldir_list) && - find_tk(tklib, stubs, tkver, *tk_ldir_list) ) ) - $CPPFLAGS += ' -DUSE_TCL_STUBS -DUSE_TK_STUBS' if stubs - $CPPFLAGS += ' -D_WIN32' if /cygwin/ =~ RUBY_PLATFORM +have_struct_member("struct RArray", "ptr", "ruby.h") +have_struct_member("struct RArray", "len", "ruby.h") - if tcltk_framework - if tcl_framework_header - $CPPFLAGS += " -I#{tcl_framework_header}" - else - $CPPFLAGS += " -I#{tcltk_framework}/Tcl.framework/Headers" - end +# check libraries +unless is_win32? + have_library("nsl", "t_open") + have_library("socket", "socket") + have_library("dl", "dlopen") + have_library("m", "log") +end +$CPPFLAGS += ' -D_WIN32' if /cygwin/ =~ RUBY_PLATFORM - if tk_framework_header - $CPPFLAGS += " -I#{tk_framework_header}" - else - $CPPFLAGS += " -I#{tcltk_framework}/Tk.framework/Headers" - end +# Does ruby have nativethread ? +TkLib_Config["ruby_with_thread"] = + macro_defined?('HAVE_NATIVETHREAD', '#include "ruby.h"') - $LDFLAGS += ' -framework Tk -framework Tcl' +#--------------------------------------------------- +# check requirement of Tcl/tk version +tcltk_version = with_config("tcltkversion") +tclver, tkver = + TkLib_Config["tcltkversion"] = check_tcltk_version(tcltk_version) +puts("Specified Tcl/Tk version is #{[tclver, tkver]}") if tclver && tkver + +# use ActiveTcl ? +#if activeTcl = with_config("ActiveTcl") +if activeTcl = with_config("ActiveTcl", true) + puts("Use ActiveTcl libraries (if available).") + activeTcl = '/opt/ActiveTcl*/lib' unless activeTcl.kind_of? String +end +TkLib_Config["ActiveTcl"] = activeTcl + +# enable Tcl/Tk stubs? +=begin +if TclConfig_Info['TCL_STUB_LIB_SPEC'] && TkConfig_Info['TK_STUB_LIB_SPEC'] && + !TclConfig_Info['TCL_STUB_LIB_SPEC'].strip.empty? && + !TkConfig_Info['TK_STUB_LIB_SPEC'].strip.empty? + stubs = true + unless (st = enable_config("tcltk-stubs")).nil? + stubs &&= st + end + unless (st = with_config("tcltk-stubs")).nil? + stubs &&= st end +else + stubs = enable_config("tcltk-stubs") || with_config("tcltk-stubs") +end +=end +stubs = enable_config("tcltk-stubs") || with_config("tcltk-stubs") +if (TkLib_Config["tcltk-stubs"] = stubs) + puts("Compile with Tcl/Tk stubs.") + $CPPFLAGS += ' -DUSE_TCL_STUBS -DUSE_TK_STUBS' +end - if stubs or pthread_check - # create Makefile +# get tclConfig.sh/tkConfig.sh +TkLib_Config["tcltk-NG-path"] = [] +tclcfg, tkcfg = get_tclConfig(with_config("tclConfig-file", true), + with_config("tclConfig-dir", true), + with_config("tkConfig-dir", true)) +TclConfig_Info = TkLib_Config["tclConfig_info"] || {} +TkConfig_Info = TkLib_Config["tkConfig_info"] || {} +TclConfig_Info['config_file_path'] = tclcfg +TkConfig_Info['config_file_path'] = tkcfg - # for SUPPORT_STATUS - $INSTALLFILES ||= [] - $INSTALLFILES << ["lib/tkextlib/SUPPORT_STATUS", "$(RUBYLIBDIR)", "lib"] +# check tk_shlib_search_path +check_shlib_search_path(with_config('tk-shlib-search-path')) - have_func("rb_hash_lookup", "ruby.h") +# search X libraries +use_X = search_X_libraries - # create - $defs << %[-DRUBY_VERSION=\\"#{RUBY_VERSION}\\"] - $defs << %[-DRUBY_RELEASE_DATE=\\"#{RUBY_RELEASE_DATE}\\"] - create_makefile("tcltklib") - end +# set TCL_DEFS and TK_DEFS +# $CPPFLAGS += " #{TclConfig_Info['TCL_DEFS']}" +# $CPPFLAGS += " #{TkConfig_Info['TK_DEFS']}" +$CPPFLAGS += collect_tcltk_defs(TclConfig_Info['TCL_DEFS'], TkConfig_Info['TK_DEFS']) + +# MacOS X Frameworks? +if TkLib_Config["tcltk-framework"] + puts("Use MacOS X Frameworks.") + setup_for_macosx_framework +end + +# search Tcl/Tk libraries +tk_idir, tk_ldir = dir_config("tk") if with_config('tk') +tcl_idir, tcl_ldir = dir_config("tcl") if with_config('tcl') + +tk_ldir2 = with_config("tk-lib") +tcl_ldir2 = with_config("tcl-lib") + +tk_ldir_list = [tk_ldir2, tk_ldir] +tcl_ldir_list = [tcl_ldir2, tcl_ldir] + +tklib = with_config("tklib") +tcllib = with_config("tcllib") + +TclConfig_Info['TCL_INCLUDE_SPEC'] = "-I#{tcl_idir.quote}" if tcl_idir +TkConfig_Info['TK_INCLUDE_SPEC'] = "-I#{tk_idir.quote}" if tk_idir + +#--------------------------------------------------- + +if (TkLib_Config["tcltk-framework"] || + ( find_tcltk_header(tclver, tkver) && + find_tcl(tcllib, stubs, tclver, *tcl_ldir_list) && + find_tk(tklib, stubs, tkver, *tk_ldir_list) ) ) && + (stubs || pthread_check()) + # create Makefile + + # for SUPPORT_STATUS + $INSTALLFILES ||= [] + $INSTALLFILES << ["lib/tkextlib/SUPPORT_STATUS", "$(RUBYLIBDIR)", "lib"] + + # create + $defs << %[-DRUBY_VERSION=\\"#{RUBY_VERSION}\\"] + $defs << %[-DRUBY_RELEASE_DATE=\\"#{RUBY_RELEASE_DATE}\\"] + + create_makefile("tcltklib") + + puts "Find Tcl/Tk libraries. Make tcltklib.so which is required by Ruby/Tk." +else + puts "Can't find proper Tcl/Tk libraries. So, can't make tcltklib.so which is required by Ruby/Tk." end diff --git a/ext/tk/lib/multi-tk.rb b/ext/tk/lib/multi-tk.rb index 32aaa2099c..c10c349d05 100644 --- a/ext/tk/lib/multi-tk.rb +++ b/ext/tk/lib/multi-tk.rb @@ -30,8 +30,8 @@ class << TclTkIp end obj = __new__(*args) obj.instance_eval{ - @force_default_encoding ||= [false].taint - @encoding ||= [nil].taint + @force_default_encoding ||= TkUtil.untrust([false]) + @encoding ||= TkUtil.untrust([nil]) def @encoding.to_s; self.join(nil); end } obj @@ -120,31 +120,31 @@ MultiTkIp_OK.freeze class MultiTkIp BASE_DIR = File.dirname(__FILE__) - WITH_RUBY_VM = Object.const_defined?(:VM) && ::VM.class == Class + WITH_RUBY_VM = Object.const_defined?(:RubyVM) && ::RubyVM.class == Class WITH_ENCODING = defined?(::Encoding.default_external) #WITH_ENCODING = Object.const_defined?(:Encoding) && ::Encoding.class == Class - (@@SLAVE_IP_ID = ['slave'.freeze, '0'.taint]).instance_eval{ + (@@SLAVE_IP_ID = ['slave'.freeze, TkUtil.untrust('0')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze } - @@IP_TABLE = {}.taint unless defined?(@@IP_TABLE) + @@IP_TABLE = TkUtil.untrust({}) unless defined?(@@IP_TABLE) - @@INIT_IP_ENV = [].taint unless defined?(@@INIT_IP_ENV) # table of Procs - @@ADD_TK_PROCS = [].taint unless defined?(@@ADD_TK_PROCS) # table of [name, args, body] + @@INIT_IP_ENV = TkUtil.untrust([]) unless defined?(@@INIT_IP_ENV) # table of Procs + @@ADD_TK_PROCS = TkUtil.untrust([]) unless defined?(@@ADD_TK_PROCS) # table of [name, args, body] - @@TK_TABLE_LIST = [].taint unless defined?(@@TK_TABLE_LIST) + @@TK_TABLE_LIST = TkUtil.untrust([]) unless defined?(@@TK_TABLE_LIST) unless defined?(@@TK_CMD_TBL) - @@TK_CMD_TBL = Object.new.taint + @@TK_CMD_TBL = TkUtil.untrust(Object.new) # @@TK_CMD_TBL.instance_variable_set('@tbl', {}.taint) - @@TK_CMD_TBL.instance_variable_set('@tbl', Hash.new{|hash,key| - fail IndexError, - "unknown command ID '#{key}'" - }.taint) + tbl_obj = TkUtil.untrust(Hash.new{|hash,key| + fail IndexError, "unknown command ID '#{key}'" + }) + @@TK_CMD_TBL.instance_variable_set('@tbl', tbl_obj) class << @@TK_CMD_TBL allow = [ @@ -223,7 +223,10 @@ class MultiTkIp @@CB_ENTRY_CLASS = Class.new(TkCallbackEntry){ def initialize(ip, cmd) @ip = ip - @cmd = cmd + @safe = safe = $SAFE + # @cmd = cmd + cmd = MultiTkIp._proc_on_safelevel(&cmd) + @cmd = proc{|*args| cmd.call(safe, *args)} self.freeze end attr_reader :ip, :cmd @@ -736,15 +739,15 @@ class MultiTkIp @@DEFAULT_MASTER = self.allocate @@DEFAULT_MASTER.instance_eval{ - @tk_windows = {}.taint + @tk_windows = TkUtil.untrust({}) - @tk_table_list = [].taint + @tk_table_list = TkUtil.untrust([]) - @slave_ip_tbl = {}.taint + @slave_ip_tbl = TkUtil.untrust({}) - @slave_ip_top = {}.taint + @slave_ip_top = TkUtil.untrust({}) - @evloop_thread = [].taint + @evloop_thread = TkUtil.untrust([]) unless keys.kind_of? Hash fail ArgumentError, "expecting a Hash object for the 2nd argument" @@ -755,7 +758,12 @@ class MultiTkIp else ### Ruby 1.9 !!!!!!!!!!! @interp_thread = Thread.new{ current = Thread.current - current[:interp] = interp = TclTkIp.new(name, _keys2opts(keys)) + begin + current[:interp] = interp = TclTkIp.new(name, _keys2opts(keys)) + rescue e + current[:interp] = e + raise e + end #sleep current[:mutex] = mutex = Mutex.new current[:root_check] = cond_var = ConditionVariable.new @@ -770,13 +778,29 @@ class MultiTkIp current[:status] = status begin - current[:status].value = interp.mainloop(true) - rescue Exception=>e - current[:status].value = e + begin + #TclTkLib.mainloop_abort_on_exception = false + #Thread.current[:status].value = TclTkLib.mainloop(true) + interp.mainloop_abort_on_exception = true + current[:status].value = interp.mainloop(true) + rescue SystemExit=>e + current[:status].value = e + rescue Exception=>e + current[:status].value = e + retry if interp.has_mainwindow? + ensure + mutex.synchronize{ cond_var.broadcast } + end + + #Thread.current[:status].value = TclTkLib.mainloop(false) + current[:status].value = interp.mainloop(false) + ensure - mutex.synchronize{ cond_var.broadcast } + # interp must be deleted before the thread for interp is dead. + # If not, raise Tcl_Panic on Tcl_AsyncDelete because async handler + # deleted by the wrong thread. + interp.delete end - current[:status].value = interp.mainloop(false) } until @interp_thread[:interp] Thread.pass @@ -795,18 +819,18 @@ class MultiTkIp end @interp.instance_eval{ - @force_default_encoding ||= [false].taint - @encoding ||= [nil].taint + @force_default_encoding ||= TkUtil.untrust([false]) + @encoding ||= TkUtil.untrust([nil]) def @encoding.to_s; self.join(nil); end } @ip_name = nil - @callback_status = [].taint + @callback_status = TkUtil.untrust([]) @system = Object.new - @wait_on_mainloop = [true, 0].taint + @wait_on_mainloop = TkUtil.untrust([true, 0]) @threadgroup = Thread.current.group @@ -1181,8 +1205,8 @@ class MultiTkIp ip_name = _create_slave_ip_name slave_ip = @interp.create_slave(ip_name, true) slave_ip.instance_eval{ - @force_default_encoding ||= [false].taint - @encoding ||= [nil].taint + @force_default_encoding ||= TkUtil.untrust([false]) + @encoding ||= TkUtil.untrust([nil]) def @encoding.to_s; self.join(nil); end } @slave_ip_tbl[ip_name] = slave_ip @@ -1228,8 +1252,8 @@ class MultiTkIp ip_name = _create_slave_ip_name slave_ip = @interp.create_slave(ip_name, false) slave_ip.instance_eval{ - @force_default_encoding ||= [false].taint - @encoding ||= [nil].taint + @force_default_encoding ||= TkUtil.untrust([false]) + @encoding ||= TkUtil.untrust([nil]) def @encoding.to_s; self.join(nil); end } slave_ip._invoke('set', 'argv0', name) if name.kind_of?(String) @@ -1282,12 +1306,12 @@ class MultiTkIp @cb_error_proc = [] @evloop_thread = [] - @tk_windows.taint unless @tk_windows.tainted? - @tk_table_list.taint unless @tk_table_list.tainted? - @slave_ip_tbl.taint unless @slave_ip_tbl.tainted? - @slave_ip_top.taint unless @slave_ip_top.tainted? - @cb_error_proc.taint unless @cb_error_proc.tainted? - @evloop_thread.taint unless @evloop_thread.tainted? + TkUtil.untrust(@tk_windows) unless @tk_windows.tainted? + TkUtil.untrust(@tk_table_list) unless @tk_table_list.tainted? + TkUtil.untrust(@slave_ip_tbl) unless @slave_ip_tbl.tainted? + TkUtil.untrust(@slave_ip_top) unless @slave_ip_top.tainted? + TkUtil.untrust(@cb_error_proc) unless @cb_error_proc.tainted? + TkUtil.untrust(@evloop_thread) unless @evloop_thread.tainted? @callback_status = [] @@ -1302,17 +1326,18 @@ class MultiTkIp unless WITH_RUBY_VM @interp = TclTkIp.new(name, _keys2opts(tk_opts)) @interp.instance_eval{ - @force_default_encoding ||= [false].taint - @encoding ||= [nil].taint + @force_default_encoding ||= TkUtil.untrust([false]) + @encoding ||= TkUtil.untrust([nil]) def @encoding.to_s; self.join(nil); end } else ### Ruby 1.9 !!!!!!!!!!! +=begin @interp_thread = Thread.new{ Thread.current[:interp] = interp = TclTkIp.new(name, _keys2opts(tk_opts)) interp.instance_eval{ - @force_default_encoding ||= [false].taint - @encoding ||= [nil].taint + @force_default_encoding ||= TkUtil.untrust([false]) + @encoding ||= TkUtil.untrust([nil]) def @encoding.to_s; self.join(nil); end } @@ -1324,15 +1349,74 @@ class MultiTkIp end # INTERP_THREAD.run @interp = @interp_thread[:interp] +=end + @interp_thread = Thread.new{ + current = Thread.current + begin + current[:interp] = interp = TclTkIp.new(name, _keys2opts(tk_opts)) + rescue e + current[:interp] = e + raise e + end + #sleep + #TclTkLib.mainloop(true) + current[:mutex] = mutex = Mutex.new + current[:root_check] = cond_ver = ConditionVariable.new + + status = [nil] + def status.value + self[0] + end + def status.value=(val) + self[0] = val + end + current[:status] = status + + begin + current[:status].value = interp.mainloop(true) + rescue SystemExit=>e + current[:status].value = e + rescue Exception=>e + current[:status].value = e + retry if interp.has_mainwindow? + ensure + mutex.synchronize{ cond_var.broadcast } + end + current[:status].value = interp.mainloop(false) + } + until @interp_thread[:interp] + Thread.pass + end + # INTERP_THREAD.run + @interp = @interp_thread[:interp] + + @evloop_thread[0] = @interp_thread + + def self.mainloop(check_root = true) + begin + TclTkLib.set_eventloop_window_mode(true) + @interp_thread.value + ensure + TclTkLib.set_eventloop_window_mode(false) + end + end end + @interp.instance_eval{ + @force_default_encoding ||= TkUtil.untrust([false]) + @encoding ||= TkUtil.untrust([nil]) + def @encoding.to_s; self.join(nil); end + } + @ip_name = nil + if safe safe = $SAFE if safe < $SAFE @safe_level = [safe] else @safe_level = [$SAFE] end + else # create slave-ip if safeip || master.safe? @@ -1365,8 +1449,8 @@ class MultiTkIp @system = Object.new - @wait_on_mainloop = [true, 0].taint - # @wait_on_mainloop = [false, 0].taint + @wait_on_mainloop = TkUtil.untrust([true, 0]) + # @wait_on_mainloop = TkUtil.untrust([false, 0]) @threadgroup = ThreadGroup.new @@ -1386,8 +1470,7 @@ class MultiTkIp @@IP_TABLE[@threadgroup] = self @@TK_TABLE_LIST.size.times{ - (tbl = {}).tainted? || tbl.taint - @tk_table_list << tbl + @tk_table_list << TkUtil.untrust({}) } _init_ip_internal(@@INIT_IP_ENV, @@ADD_TK_PROCS) @@ -1435,6 +1518,17 @@ end # get target IP class MultiTkIp + @@CALLBACK_SUBTHREAD = Class.new(Thread){ + def self.new(interp, &blk) + super(interp){|ip| Thread.current[:callback_ip] = ip; blk.call} + end + + @table = TkUtil.untrust(Hash.new{|h,k| h[k] = TkUtil.untrust([])}) + def self.table + @table + end + } + def self._ip_id_ __getip._ip_id_ end @@ -1445,6 +1539,9 @@ class MultiTkIp def self.__getip current = Thread.current + if current.kind_of?(@@CALLBACK_SUBTHREAD) + return current[:callback_ip] + end if TclTkLib.mainloop_thread? != false && current[:callback_ip] return current[:callback_ip] end @@ -1467,11 +1564,11 @@ class << MultiTkIp alias __new new private :__new - def new_master(safe=nil, keys={}) + def new_master(safe=nil, keys={}, &blk) if MultiTkIp::WITH_RUBY_VM #### TODO !!!!!! fail RuntimeError, - 'sorry, still not support multiple master-interpreters on Ruby VM' + 'sorry, still not support multiple master-interpreters on RubyVM' end if safe.kind_of?(Hash) @@ -1489,15 +1586,17 @@ class << MultiTkIp ip = __new(__getip, nil, keys) #ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call) if block_given? - if block_given? - Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call)} - end + if block_given? + #Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call)} + #Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; yield}.call)} + ip._proc_on_safelevel(&blk).call(ip.safe_level) + end ip end alias new new_master - def new_slave(safe=nil, keys={}) + def new_slave(safe=nil, keys={}, &blk) if safe.kind_of?(Hash) keys = safe elsif safe.kind_of?(Integer) @@ -1514,13 +1613,15 @@ class << MultiTkIp ip = __new(__getip, false, keys) # ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call) if block_given? if block_given? - Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call)} + #Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call)} + #Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; yield}.call)} + ip._proc_on_safelevel(&blk).call(ip.safe_level) end ip end alias new_trusted_slave new_slave - def new_safe_slave(safe=4, keys={}) + def new_safe_slave(safe=4, keys={}, &blk) if safe.kind_of?(Hash) keys = safe elsif safe.kind_of?(Integer) @@ -1535,7 +1636,9 @@ class << MultiTkIp ip = __new(__getip, true, keys) # ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call) if block_given? if block_given? - Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call)} + #Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call)} + #Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; yield}.call)} + ip._proc_on_safelevel(&blk).call(ip.safe_level) end ip end @@ -1669,8 +1772,7 @@ class MultiTkIp def _add_new_tables (@@TK_TABLE_LIST.size - @tk_table_list.size).times{ - (tbl = {}).tainted? || tbl.taint - @tk_table_list << tbl + @tk_table_list << TkUtil.untrust({}) } end @@ -1813,7 +1915,6 @@ class MultiTkIp end end - # for callback operation class MultiTkIp def self.cb_entry_class @@ -1837,6 +1938,13 @@ class MultiTkIp ret end =end + def cb_eval(cmd, *args) + self.eval_callback(*args, + &_proc_on_safelevel{|*params| + TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *params)) + }) + end +=begin def cb_eval(cmd, *args) self.eval_callback(*args){|safe, *params| $SAFE=safe if $SAFE < safe @@ -1844,6 +1952,7 @@ class MultiTkIp TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *params)) } end +=end =begin def cb_eval(cmd, *args) @callback_status[0] ||= TkVariable.new @@ -1938,6 +2047,48 @@ end # evaluate a procedure on the proper interpreter class MultiTkIp + # instance & class method + def _proc_on_safelevel(cmd=nil, &blk) # require a block for eval + if cmd + if cmd.kind_of?(Method) + _proc_on_safelevel{|*args| cmd.call(*args)} + else + _proc_on_safelevel(&cmd) + end + else + #Proc.new{|safe, *args| $SAFE=safe if $SAFE < safe; yield(*args)} + Proc.new{|safe, *args| + # avoid security error on Exception objects + untrust_proc = proc{|err| + begin + err.untrust if err.respond_to?(:untrust) + rescue SecurityError + end + err + } + $SAFE=safe if $SAFE < safe; + begin + yield(*args) + rescue Exception => e + fail untrust_proc.call(e) + end + } + end + end + def MultiTkIp._proc_on_safelevel(cmd=nil, &blk) + MultiTkIp.__getip._proc_on_safelevel(cmd, &blk) + end + + def _proc_on_current_safelevel(cmd=nil, &blk) # require a block for eval + safe = $SAFE + cmd = _proc_on_safelevel(cmd, &blk) + Proc.new{|*args| cmd.call(safe, *args)} + end + def MultiTkIp._proc_on_current_safelevel(cmd=nil, &blk) + MultiTkIp.__getip._proc_on_current_safelevel(cmd, &blk) + end + + ###################################### # instance method def eval_proc_core(req_val, cmd, *args) # check @@ -1953,10 +2104,10 @@ class MultiTkIp ret = cmd.call(safe_level, *args) rescue SystemExit => e # exit IP - warn("Warning: "+ $! + " on " + self.inspect) if $DEBUG + warn("Warning: "+ e.inspect + " on " + self.inspect) if $DEBUG begin self._eval_without_enc('exit') - rescue Exception + rescue Exception => e end self.delete ret = nil @@ -2008,7 +2159,7 @@ class MultiTkIp return ret.value rescue SystemExit => e # exit IP - warn("Warning: " + $! + " on " + self.inspect) if $DEBUG + warn("Warning: " + e.inspect + " on " + self.inspect) if $DEBUG begin self._eval_without_enc('exit') rescue Exception @@ -2031,22 +2182,76 @@ class MultiTkIp end private :eval_proc_core +if WITH_RUBY_VM ### Ruby 1.9 + def eval_callback(*args) + if block_given? + cmd = Proc.new + else + cmd = args.shift + end + begin + if @@CALLBACK_SUBTHREAD.table[self].index(Thread.current) + last_th = nil + else + last_th = @@CALLBACK_SUBTHREAD.table[self][-1] + end + @@CALLBACK_SUBTHREAD.new(self){ + @@CALLBACK_SUBTHREAD.table[self] << Thread.current + begin + last_th.join if last_th + eval_proc_core(false, cmd, *args) + rescue Exception=>e + e + ensure + @@CALLBACK_SUBTHREAD.table[self].delete(Thread.current) + end + } + end + end +else ### Ruby 1.8 def eval_callback(*args) if block_given? cmd = Proc.new else cmd = args.shift end - current = Thread.current - backup_ip = current[:callback_ip] - current[:callback_ip] = self begin eval_proc_core(false, cmd, *args) + rescue Exception=>e + e ensure - current[:callback_ip] = backup_ip end end +end + def eval_proc(*args, &blk) + if block_given? + cmd = _proc_on_safelevel(&blk) + else + unless (cmd = args.shift) + fail ArgumentError, "A Proc or Method object is expected for 1st argument" + end + cmd = _proc_on_safelevel(&cmd) + end + if TclTkLib.mainloop_thread? == true + # call from eventloop + current = Thread.current + backup_ip = current[:callback_ip] + current[:callback_ip] = self + begin + eval_proc_core(false, cmd, *args) + ensure + current[:callback_ip] = backup_ip + end + else + eval_proc_core(true, + proc{|safe, *params| + Thread.new{cmd.call(safe, *params)}.value + }, + *args) + end + end +=begin def eval_proc(*args) # The scope of the eval-block of 'eval_proc' method is different from # the external. If you want to pass local values to the eval-block, @@ -2081,6 +2286,7 @@ class MultiTkIp *args) end end +=end alias call eval_proc def bg_eval_proc(*args) @@ -2478,7 +2684,8 @@ end # depend on TclTkIp class MultiTkIp - def mainloop(check_root = true, restart_on_dead = true) +# def mainloop(check_root = true, restart_on_dead = true) + def mainloop(check_root = true, restart_on_dead = false) raise SecurityError, "no permission to manipulate" unless self.manipulable? if WITH_RUBY_VM ### Ruby 1.9 !!!!!!!!!!! @@ -2507,7 +2714,7 @@ class MultiTkIp end rescue SystemExit => e # exit IP - warn("Warning: " + $! + " on " + self.inspect) if $DEBUG + warn("Warning: " + e.inspect + " on " + self.inspect) if $DEBUG begin self._eval_without_enc('exit') rescue Exception diff --git a/ext/tk/lib/remote-tk.rb b/ext/tk/lib/remote-tk.rb index f56864687e..0fa713359e 100644 --- a/ext/tk/lib/remote-tk.rb +++ b/ext/tk/lib/remote-tk.rb @@ -10,8 +10,8 @@ class MultiTkIp; end class RemoteTkIp < MultiTkIp; end class MultiTkIp - @@IP_TABLE = {}.taint unless defined?(@@IP_TABLE) - @@TK_TABLE_LIST = [].taint unless defined?(@@TK_TABLE_LIST) + @@IP_TABLE = TkUtil.untrust({}) unless defined?(@@IP_TABLE) + @@TK_TABLE_LIST = TkUtil.untrust([]) unless defined?(@@TK_TABLE_LIST) def self._IP_TABLE; @@IP_TABLE; end def self._TK_TABLE_LIST; @@TK_TABLE_LIST; end @@ -88,14 +88,14 @@ class RemoteTkIp @slave_ip_tbl = {} @slave_ip_top = {} - @force_default_encoding ||= [false].taint - @encoding ||= [nil].taint + @force_default_encoding ||= TkUtil.untrust([false]) + @encoding ||= TkUtil.untrust([nil]) def @encoding.to_s; self.join(nil); end - @tk_windows.taint unless @tk_windows.tainted? - @tk_table_list.taint unless @tk_table_list.tainted? - @slave_ip_tbl.taint unless @slave_ip_tbl.tainted? - @slave_ip_top.taint unless @slave_ip_top.tainted? + TkUtil.untrust(@tk_windows) unless @tk_windows.tainted? + TkUtil.untrust(@tk_table_list) unless @tk_table_list.tainted? + TkUtil.untrust(@slave_ip_tbl) unless @slave_ip_tbl.tainted? + TkUtil.untrust(@slave_ip_top) unless @slave_ip_top.tainted? @system = Object.new @@ -119,7 +119,7 @@ class RemoteTkIp @@IP_TABLE[@threadgroup] = self @@TK_TABLE_LIST.size.times{ - (tbl = {}).tainted? || tbl.taint + (tbl = {}).tainted? || TkUtil.untrust(tbl) @tk_table_list << tbl } diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb index 49e4ca2564..b071bf5be8 100644 --- a/ext/tk/lib/tk.rb +++ b/ext/tk/lib/tk.rb @@ -15,7 +15,9 @@ require 'thread' class TclTkIp # backup original (without encoding) _eval and _invoke alias _eval_without_enc _eval + alias __eval__ _eval alias _invoke_without_enc _invoke + alias __invoke__ _invoke def _ip_id_ # for RemoteTkIp @@ -28,8 +30,8 @@ class TclTkIp def initialize(*args) __initialize__(*args) - @force_default_encoding ||= [false].taint - @encoding ||= [nil].taint + @force_default_encoding ||= TkUtil.untrust([false]) + @encoding ||= TkUtil.untrust([nil]) def @encoding.to_s; self.join(nil); end end end @@ -39,8 +41,8 @@ module TkComm include TkUtil extend TkUtil - WidgetClassNames = {}.taint - TkExtlibAutoloadModule = [].taint + WidgetClassNames = TkUtil.untrust({}) + TkExtlibAutoloadModule = TkUtil.untrust([]) # None = Object.new ### --> definition is moved to TkUtil module # def None.to_s @@ -50,7 +52,10 @@ module TkComm #Tk_CMDTBL = {} #Tk_WINDOWS = {} - Tk_IDs = ["00000".taint, "00000".taint] # [0]-cmdid, [1]-winid + Tk_IDs = [ + TkUtil.untrust("00000"), # [0]-cmdid + TkUtil.untrust("00000") # [1]-winid + ] Tk_IDs.instance_eval{ @mutex = Mutex.new def mutex; @mutex; end @@ -70,7 +75,7 @@ module TkComm Tk_WINDOWS.freeze self.instance_eval{ - @cmdtbl = [].taint + @cmdtbl = TkUtil.untrust([]) } unless const_defined?(:GET_CONFIGINFO_AS_ARRAY) @@ -113,15 +118,22 @@ module TkComm gen_class_name = ruby_class_name classname_def = '' else # ruby_class == nil - mods = TkExtlibAutoloadModule.find_all{|m| m.const_defined?(tk_class)} - mods.each{|mod| - begin - mod.const_get(tk_class) # auto_load - break if (ruby_class = WidgetClassNames[tk_class]) - rescue LoadError - # ignore load error - end - } + if Tk.const_defined?(tk_class) + mod.const_get(tk_class) # auto_load + ruby_class = WidgetClassNames[tk_class] + end + + unless ruby_class + mods = TkExtlibAutoloadModule.find_all{|m| m.const_defined?(tk_class)} + mods.each{|mod| + begin + mod.const_get(tk_class) # auto_load + break if (ruby_class = WidgetClassNames[tk_class]) + rescue LoadError + # ignore load error + end + } + end unless ruby_class std_class = 'Tk' << tk_class @@ -131,6 +143,14 @@ module TkComm end end + unless ruby_class + if Tk.const_defined?('TOPLEVEL_ALIASES') && + Tk::TOPLEVEL_ALIASES.const_defined?(std_class) + Tk::TOPLEVEL_ALIASES.const_get(std_class) # auto_load + ruby_class = WidgetClassNames[tk_class] + end + end + if ruby_class # found ruby_class_name = ruby_class.name @@ -613,11 +633,35 @@ end val end end - private :bool, :number, :string, :num_or_str - private :list, :simplelist, :window, :procedure - module_function :bool, :number, :num_or_str, :string + private :bool, :number, :num_or_str, :num_or_nil, :string + private :list, :simplelist, :window, :image_obj, :procedure + module_function :bool, :number, :num_or_str, :num_or_nil, :string module_function :list, :simplelist, :window, :image_obj, :procedure + if (RUBY_VERSION.split('.').map{|n| n.to_i} <=> [1,8,7]) < 0 + def slice_ary(ary, size) + sliced = [] + wk_ary = ary.dup + until wk_ary.size.zero? + sub_ary = [] + size.times{ sub_ary << wk_ary.shift } + yield(sub_ary) if block_given? + sliced << sub_ary + end + (block_given?)? ary: sliced + end + else + def slice_ary(ary, size, &b) + if b + ary.each_slice(size, &b) + else + ary.each_slice(size).to_a + end + end + end + private :slice_ary + module_function :slice_ary + def subst(str, *opts) # opts := :nobackslashes | :nocommands | novariables tk_call('subst', @@ -803,7 +847,7 @@ end TkCore::INTERP.tk_cmd_tbl[id] = TkCore::INTERP.get_cb_entry(cmd) end @cmdtbl = [] unless defined? @cmdtbl - @cmdtbl.taint unless @cmdtbl.tainted? + TkUtil.untrust(@cmdtbl) unless @cmdtbl.tainted? @cmdtbl.push id if local_cmdtbl && local_cmdtbl.kind_of?(Array) @@ -1130,30 +1174,42 @@ module TkCore opts = '' end - if WITH_RUBY_VM ### check Ruby 1.9 !!!!!!! - # *** NEED TO FIX *** - ip = TclTkIp.new(name, opts) - if ip._invoke_without_enc('tk', 'windowingsystem') == 'aqua' && - (TclTkLib.get_version <=> [8,4,TclTkLib::RELEASE_TYPE::FINAL,9]) > 0 - # *** KNOWN BUG *** - # Main event loop thread of TkAqua (> Tk8.4.9) must be the main - # application thread. So, ruby1.9 users must call Tk.mainloop on - # the main application thread. - RUN_EVENTLOOP_ON_MAIN_THREAD = true - INTERP = ip - else - unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD - RUN_EVENTLOOP_ON_MAIN_THREAD = false - end - if RUN_EVENTLOOP_ON_MAIN_THREAD + unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD + if WITH_RUBY_VM ### check Ruby 1.9 !!!!!!! + # *** NEED TO FIX *** + ip = TclTkIp.new(name, opts) + if ip._invoke_without_enc('tk', 'windowingsystem') == 'aqua' && + (TclTkLib.get_version<=>[8,4,TclTkLib::RELEASE_TYPE::FINAL,6]) > 0 + # *** KNOWN BUG *** + # Main event loop thread of TkAqua (> Tk8.4.9) must be the main + # application thread. So, ruby1.9 users must call Tk.mainloop on + # the main application thread. + # + # *** ADD (2009/05/10) *** + # In some cases (I don't know the description of conditions), + # TkAqua 8.4.7 has a same kind of hang-up trouble. + # So, if 8.4.7 or later, set RUN_EVENTLOOP_ON_MAIN_THREAD to true. + # When you want to control this mode, please call the following + # (set true/false as you want) before "require 'tk'". + # ---------------------------------------------------------- + # module TkCore; RUN_EVENTLOOP_ON_MAIN_THREAD = true; end + # ---------------------------------------------------------- + # + RUN_EVENTLOOP_ON_MAIN_THREAD = true INTERP = ip else - ip.delete + unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD + RUN_EVENTLOOP_ON_MAIN_THREAD = false + end + if RUN_EVENTLOOP_ON_MAIN_THREAD + INTERP = ip + else + ip.delete + end end - end - ip = nil - else - unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD + ip = nil + + else # Ruby 1.8.x RUN_EVENTLOOP_ON_MAIN_THREAD = false end end @@ -1183,13 +1239,29 @@ module TkCore #sleep begin - Thread.current[:status].value = TclTkLib.mainloop(true) - rescue Exception=>e - Thread.current[:status].value = e + begin + #TclTkLib.mainloop_abort_on_exception = false + #Thread.current[:status].value = TclTkLib.mainloop(true) + interp.mainloop_abort_on_exception = true + Thread.current[:status].value = interp.mainloop(true) + rescue SystemExit=>e + Thread.current[:status].value = e + rescue Exception=>e + Thread.current[:status].value = e + retry if interp.has_mainwindow? + ensure + INTERP_MUTEX.synchronize{ INTERP_ROOT_CHECK.broadcast } + end + + #Thread.current[:status].value = TclTkLib.mainloop(false) + Thread.current[:status].value = interp.mainloop(false) + ensure - INTERP_MUTEX.synchronize{ INTERP_ROOT_CHECK.broadcast } + # interp must be deleted before the thread for interp is dead. + # If not, raise Tcl_Panic on Tcl_AsyncDelete because async handler + # deleted by the wrong thread. + interp.delete end - Thread.current[:status].value = TclTkLib.mainloop(false) } until INTERP_THREAD[:interp] @@ -1210,10 +1282,11 @@ module TkCore end INTERP.instance_eval{ - # @tk_cmd_tbl = {}.taint - @tk_cmd_tbl = Hash.new{|hash, key| - fail IndexError, "unknown command ID '#{key}'" - }.taint + # @tk_cmd_tbl = TkUtil.untrust({}) + @tk_cmd_tbl = + TkUtil.untrust(Hash.new{|hash, key| + fail IndexError, "unknown command ID '#{key}'" + }) def @tk_cmd_tbl.[]=(idx,val) if self.has_key?(idx) && Thread.current.group != ThreadGroup::Default fail SecurityError,"cannot change the entried command" @@ -1221,15 +1294,15 @@ module TkCore super(idx,val) end - @tk_windows = {}.taint + @tk_windows = TkUtil.untrust({}) - @tk_table_list = [].taint + @tk_table_list = TkUtil.untrust([]) - @init_ip_env = [].taint # table of Procs - @add_tk_procs = [].taint # table of [name, args, body] + @init_ip_env = TkUtil.untrust([]) # table of Procs + @add_tk_procs = TkUtil.untrust([]) # table of [name, args, body] - @force_default_encoding ||= [false].taint - @encoding ||= [nil].taint + @force_default_encoding ||= TkUtil.untrust([false]) + @encoding ||= TkUtil.untrust([nil]) def @encoding.to_s; self.join(nil); end @cb_entry_class = Class.new(TkCallbackEntry){ @@ -1283,7 +1356,7 @@ module TkCore end def INTERP.create_table id = @tk_table_list.size - (tbl = {}).tainted? || tbl.taint + (tbl = {}).tainted? || TkUtil.untrust(tbl) @tk_table_list << tbl # obj = Object.new # obj.instance_eval <<-EOD @@ -1321,7 +1394,8 @@ module TkCore @add_tk_procs.delete_if{|elem| elem.kind_of?(Array) && elem[0].to_s == name } - self._invoke('rename', name, '') + #self._invoke('rename', name, '') + self.__invoke__('rename', name, '') } end def INTERP.init_ip_internal @@ -1704,11 +1778,14 @@ module TkCore elsif TkCore::RUN_EVENTLOOP_ON_MAIN_THREAD # if TclTkLib::WINDOWING_SYSTEM == 'aqua' && - if TkCore::INTERP._invoke_without_enc('tk','windowingsystem')=='aqua' && - Thread.current != Thread.main && - (TclTkLib.get_version <=> [8,4,TclTkLib::RELEASE_TYPE::FINAL,9]) > 0 - raise RuntimeError, - "eventloop on TkAqua ( > Tk8.4.9 ) works on the main thread only" + #if TkCore::INTERP._invoke_without_enc('tk','windowingsystem')=='aqua' && + # Thread.current != Thread.main && + # (TclTkLib.get_version <=> [8,4,TclTkLib::RELEASE_TYPE::FINAL,9]) > 0 + # raise RuntimeError, + # "eventloop on TkAqua ( > Tk8.4.9 ) works on the main thread only" + #end + if Thread.current != Thread.main + raise RuntimeError, "Tk.mainloop is allowed on the main thread only" end TclTkLib.mainloop(check_root) @@ -1911,7 +1988,7 @@ module TkCore puts 'invoke args => ' + args.inspect if $DEBUG ### print "=> ", args.join(" ").inspect, "\n" if $DEBUG begin - # res = INTERP._invoke(*args).taint + # res = TkUtil.untrust(INTERP._invoke(*args)) # res = INTERP._invoke(enc_mode, *args) res = _ip_invoke_core(enc_mode, *args) # >>>>> _invoke returns a TAINTED string <<<<< @@ -1919,7 +1996,7 @@ module TkCore # err = $! begin args.unshift "unknown" - #res = INTERP._invoke(*args).taint + #res = TkUtil.untrust(INTERP._invoke(*args)) #res = INTERP._invoke(enc_mode, *args) res = _ip_invoke_core(enc_mode, *args) # >>>>> _invoke returns a TAINTED string <<<<< @@ -3028,7 +3105,7 @@ if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK) =begin if ext_enc_obj == Tk::Encoding::UNKNOWN - if defind? DEFAULT_TK_ENCODING + if defined? DEFAULT_TK_ENCODING if DEFAULT_TK_ENCODING.kind_of?(::Encoding) tk_enc_name = DEFAULT_TK_ENCODING.name tksys_enc_name = DEFAULT_TK_ENCODING.name @@ -3126,7 +3203,7 @@ if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK) #if ext_enc_name && ext_enc_name != tksys_enc_name int_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(int_enc_obj) if int_enc_name - # use default_external + # use default_internal enc_name = int_enc_name else # use Tk.encoding_system @@ -3279,10 +3356,10 @@ module TkTreatFont TkFont.init_widget_font(pathname, *__confinfo_cmd) else fonts = {} - optkeys.each{|key| - key = key.to_s - pathname = [win, tag, key].join(';') - fonts[key] = + optkeys.each{|k| + k = k.to_s + pathname = [win, tag, k].join(';') + fonts[k] = TkFont.used_on(pathname) || TkFont.init_widget_font(pathname, *__confinfo_cmd) } @@ -3407,7 +3484,7 @@ module TkTreatFont if fobj.kind_of?(TkFont) if ltn.kind_of?(TkFont) conf = {} - ltn.latin_configinfo.each{|key,val| conf[key] = val} + ltn.latin_configinfo.each{|k,val| conf[k] = val} if keys fobj.latin_configure(conf.update(keys)) else @@ -3467,7 +3544,7 @@ module TkTreatFont if fobj.kind_of?(TkFont) if knj.kind_of?(TkFont) conf = {} - knj.kanji_configinfo.each{|key,val| conf[key] = val} + knj.kanji_configinfo.each{|k,val| conf[k] = val} if keys fobj.kanji_configure(conf.update(keys)) else @@ -3701,11 +3778,17 @@ module TkConfigMethod val end + def cget_tkstring(option) + opt = option.to_s + fail ArgumentError, "Invalid option `#{option.inspect}'" if opt.length == 0 + tk_call_without_enc(*(__cget_cmd << "-#{opt}")) + end + def __cget_core(slot) orig_slot = slot slot = slot.to_s - if slot.length == 0 + if slot.length == 0 fail ArgumentError, "Invalid option `#{orig_slot.inspect}'" end @@ -4106,7 +4189,8 @@ module TkConfigMethod else # conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) - conf = tk_split_list(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), 0, false, true) + # conf = tk_split_list(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), 0, false, true) + conf = tk_split_list(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), 1, false, true) end conf[__configinfo_struct[:key]] = conf[__configinfo_struct[:key]][1..-1] @@ -4296,8 +4380,8 @@ module TkConfigMethod end } - __methodcall_optkeys.each{|optkey, method| - ret << [optkey.to_s, '', '', '', self.__send__(method)] + __methodcall_optkeys.each{|optkey, m| + ret << [optkey.to_s, '', '', '', self.__send__(m)] } ret @@ -4335,7 +4419,7 @@ module TkConfigMethod if slot slot = slot.to_s - alias_name, real_name = __optkey_aliases.find{|k, v| k.to_s == slot} + alias_name, real_name = __optkey_aliases.find{|k,var| k.to_s == slot} if real_name slot = real_name.to_s end @@ -4682,8 +4766,8 @@ module TkConfigMethod end } - __methodcall_optkeys.each{|optkey, method| - ret[optkey.to_s] = ['', '', '', self.__send__(method)] + __methodcall_optkeys.each{|optkey, m| + ret[optkey.to_s] = ['', '', '', self.__send__(m)] } ret @@ -4721,18 +4805,18 @@ module TkConfigMethod "there is a configure alias loop about '#{org_slot}'" else ret = {} - configinfo().each{|conf| + configinfo().each{|cnf| if ( ! __configinfo_struct[:alias] \ - || conf.size > __configinfo_struct[:alias] + 1 ) - ret[conf[0]] = conf[-1] + || cnf.size > __configinfo_struct[:alias] + 1 ) + ret[cnf[0]] = cnf[-1] end } ret end else # ! TkComm::GET_CONFIGINFO_AS_ARRAY ret = {} - configinfo(slot).each{|key, conf| - ret[key] = conf[-1] if conf.kind_of?(Array) + configinfo(slot).each{|key, cnf| + ret[key] = cnf[-1] if cnf.kind_of?(Array) } ret end @@ -4864,6 +4948,7 @@ class TkWindow obj + @current_default_widget_set = nil + + module TOPLEVEL_ALIASES; end end +class Object + include Tk::TOPLEVEL_ALIASES +end ############################################ # methods to control default widget set @@ -343,50 +352,387 @@ class << Tk _replace_toplevel_aliases(target) end - def __set_toplevel_aliases__(target, obj, *symbols) + def widget_set_symbols + @TOPLEVEL_ALIAS_TABLE.keys + end + + def toplevel_aliases_on_widget_set(widget_set) + if (tbl = @TOPLEVEL_ALIAS_TABLE[widget_set.to_sym]) + tbl.collect{|k, v| (v.nil?)? nil: k}.compact + else + fail ArgumentError, "unknown widget_set #{widget_set.to_sym.inspect}" + end + end + + def __toplevel_alias_setup_proc__(*target_list, &cmd) + target_list.each{|target| @TOPLEVEL_ALIAS_SETUP_PROC[target.to_sym] = cmd} + end + + def topobj_defined?(sym) #=> alias_filename or object or false + Object.autoload?(sym) || + (Object.const_defined?(sym) && Object.const_get(sym)) + end + def topalias_defined?(sym) #=> alias_filename or object or false + Tk::TOPLEVEL_ALIASES.autoload?(sym) || + (Tk::TOPLEVEL_ALIASES.const_defined?(sym) && + Tk::TOPLEVEL_ALIASES.const_get(sym)) + end + def define_topobj(sym, obj) + if obj.kind_of? String + # obj is an autoload path + Object.autoload(sym, obj) + unless Object.autoload?(sym) + # file is autoloaded? + if @AUTOLOAD_FILE_SYM_TABLE.has_key?(obj) && + (loaded_obj = @AUTOLOAD_FILE_SYM_TABLE[obj][sym]) + Object.const_set(sym, loaded_obj) + else + fail ArgumentError, "cannot define autoload file (already loaded?)" + end + end + else + # object + Object.const_set(sym, obj) + end + end + def define_topalias(sym, obj) + if obj.kind_of? String + # obj is an autoload path + Tk::TOPLEVEL_ALIASES.autoload(sym, obj) + unless Tk::TOPLEVEL_ALIASES.autoload?(sym) + # file is autoloaded? + if @AUTOLOAD_FILE_SYM_TABLE.has_key?(obj) && + (loaded_obj = @AUTOLOAD_FILE_SYM_TABLE[obj][sym]) + Tk::TOPLEVEL_ALIASES.const_set(sym, loaded_obj) + else + fail ArgumentError, "cannot define autoload file (already loaded?)" + end + end + else + # object + Tk::TOPLEVEL_ALIASES.const_set(sym, obj) + end + end + def replace_topobj(sym, obj) #=> old_obj (alias_filename or object) or nil + if old_obj = topobj_defined?(sym) + Object.class_eval{remove_const sym} rescue nil # ignore err + end + define_topobj(sym, obj) + old_obj + end + def replace_topalias(sym, obj) #=> old_obj (alias_filename or object) or nil + if old_obj = topalias_defined?(sym) + Tk::TOPLEVEL_ALIASES.module_eval{remove_const sym} rescue nil #ignore err + end + define_topalias(sym, obj) + old_obj + end + private :topobj_defined?, :topalias_defined? + private :define_topobj, :define_topalias + private :replace_topobj, :replace_topalias + + def __regist_toplevel_aliases__(target, obj, *symbols) + # initial regist @TOPLEVEL_ALIAS_TABLE[target = target.to_sym] ||= {} symbols.each{|sym| @TOPLEVEL_ALIAS_TABLE[target][sym = sym.to_sym] = obj - # if @current_default_widget_set == target - if @TOPLEVEL_ALIAS_OWNER[sym] == target - Object.class_eval{remove_const sym} if Object.const_defined?(sym) - Object.const_set(sym, obj) + if !topalias_defined?(sym) || target == @current_default_widget_set + @TOPLEVEL_ALIAS_OWNER[sym] = target + replace_topalias(sym, obj) + replace_topobj(sym, obj) unless obj.kind_of?(String) # NOT autoload end } end - ################################### - private - def _replace_toplevel_aliases(target) - # check already autoloaded - if (table = @TOPLEVEL_ALIAS_TABLE[current = @current_default_widget_set]) - table.each{|sym, file| - if !Object.autoload?(sym) && Object.const_defined?(sym) && - @TOPLEVEL_ALIAS_TABLE[current][sym].kind_of?(String) - # autoload -> class - @TOPLEVEL_ALIAS_TABLE[current][sym] = Object.const_get(sym) + def regist_sym_for_loaded_file(auto, obj, sym) + @AUTOLOAD_FILE_SYM_TABLE[auto][sym] = obj + + reg = /^#{Regexp.quote(auto)}(\.rb|\.so|)$/ + @TOPLEVEL_ALIAS_TABLE.each_key{|set| + if @TOPLEVEL_ALIAS_TABLE[set][sym] =~ reg + @TOPLEVEL_ALIAS_TABLE[set][sym] = obj + if @TOPLEVEL_ALIAS_OWNER[sym].nil? || @TOPLEVEL_ALIAS_OWNER[sym] == set + replace_topalias(sym, obj) + replace_topobj(sym, obj) if set == @current_default_widget_set end - } + end + } + if (f = Object.autoload?(sym)) && f =~ reg + replace_topobj(sym, obj) end + if (f = Tk::TOPLEVEL_ALIASES.autoload?(sym)) && f =~ reg + replace_topalias(sym, obj) + end + end + private :regist_sym_for_loaded_file + + def set_topalias(target, obj, sym) + # obj is a kind of String : define autoload path + # Class : use the class object + if target == @current_default_widget_set + case @TOPLEVEL_ALIAS_OWNER[sym] + when false + # Object::sym is out of control. --> not change + # Make ALIAS::sym under control, because target widget set is current. + # Keep OWNER[sym] + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + + when target + if current_obj = topobj_defined?(sym) + if current_obj == obj + # Make current_obj under control. + # Keep Object::sym. + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + + else # current_obj != obj + if current_obj == topalias_defined?(sym) + # Change controlled object + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + replace_topobj(sym, obj) + + else # current_obj != topalias_defined?(sym) + # Maybe current_obj is defined by user. --> OWNER[sym] = faise + # Keep Object::sym. + @TOPLEVEL_ALIAS_OWNER[sym] = false + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + end + end + + else # NOT topobj_defined?(sym) + # New definition for sym at target. + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + define_topobj(sym, obj) + end + + when nil + # New definition for sym at target. + @TOPLEVEL_ALIAS_OWNER[sym] = target + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + + else # others + # Maybe planning to make sym under control. + @TOPLEVEL_ALIAS_OWNER[sym] = target + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + replace_topobj(sym, obj) + end + + else # target != @current_default_widget_set + case @TOPLEVEL_ALIAS_OWNER[sym] + when false + # Object::sym is out of control. --> not change + if topalias_defined?(sym) + # ALIAS[sym] may be defined by other widget set. + # Keep Object::sym (even if it is not defined) + # Keep ALIAS[sym]. + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + + else # NOT topalias_defined?(sym) + # Nobody controls ALIAS[sym]. + # At leaset, current widget set doesn't control ALIAS[sym]. + # Keep Object::sym (even if it is not defined) + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + define_topalias(sym, obj) + end + + when target + # Maybe change controlled object, because Object::sym is under control. + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + replace_topobj(sym, obj) + + when nil + # New definition for sym + @TOPLEVEL_ALIAS_OWNER[sym] = target + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + replace_topobj(sym, obj) + + else # others + # An other widget set controls sym. + # Keep Object::sym (even if it is not defined) + # Keep ALIAS[sym]. + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + + end + end + + sym + end + private :set_topalias - # setup autoloads - @TOPLEVEL_ALIAS_TABLE[target].each{|sym, file| - Object.class_eval{remove_const sym} if Object.const_defined?(sym) - if file.kind_of?(String) - # file => autoload target file - Object.autoload(sym, file) + def __set_toplevel_aliases__(target, obj, *symbols) + # obj is a kind of String : define autoload path + # Class : use the class object + target = target.to_sym + symbols.each{|sym| set_topalias(target, obj, sym.to_sym)} + end + + def __set_loaded_toplevel_aliases__(autopath, target, obj, *symbols) + # autopath is an autoload file + # Currently, this method doesn't support that autoload loads + # different toplevels between .rb and .so extension. + shortpath = (autopath =~ /^(.*)(.rb|.so)$/)? $1: autopath + target = target.to_sym + symbols.map!{|sym| sym.to_sym} + + symbols.each{|sym| regist_sym_for_loaded_file(shortpath, obj, sym) } + symbols.each{|sym| set_topalias(target, obj, sym)} + end + + def backup_current_topdef(sym) + return if (current = @current_default_widget_set).nil? + + case @TOPLEVEL_ALIAS_OWNER[sym] + when false + # Object::sym is out of control. + if (cur_alias = topalias_defined?(sym)) && ! cur_alias.kind_of?(String) + @TOPLEVEL_ALIAS_TABLE[current][sym] = cur_alias + end + + when current + if cur_obj = topobj_defined?(sym) + if ! cur_obj.kind_of?(String) && (cur_alias = topalias_defined?(sym)) + if cur_alias.kind_of?(String) + # Mayby, user replaced Object::sym. + # Make Object::sym out of control. + @TOPLEVEL_ALIAS_OWNER[sym] = false + elsif cur_obj == cur_alias + # Possibley, defined normally. Backup it + @TOPLEVEL_ALIAS_TABLE[current][sym] = cur_alias + else + # Mayby, user replaced Object::sym. + # Make Object::sym out of control. + @TOPLEVEL_ALIAS_OWNER[sym] = false + end + end + else + # Mayby, user replaced Object::sym. + # Make Object::sym out of control. + @TOPLEVEL_ALIAS_OWNER[sym] = false + end + + when nil + # Object::sym is out of control. + if (cur_alias = topalias_defined?(sym)) && ! cur_alias.kind_of?(String) + # Possibley, defined normally. Backup it. + @TOPLEVEL_ALIAS_TABLE[current][sym] = cur_alias + end + else + # No authority to control Object::sym and ALIASES::sym. + # Do nothing. + end + end + private :backup_current_topdef + + def _replace_toplevel_aliases(target) + # backup + @TOPLEVEL_ALIAS_TABLE[target].each_key{|sym| + backup_current_topdef(sym) + } + + # replace + @TOPLEVEL_ALIAS_TABLE[target].each_key{|sym| + next if (obj = @TOPLEVEL_ALIAS_TABLE[target][sym]).nil? + if @TOPLEVEL_ALIAS_OWNER[sym] == false + # Object::sym is out of control. --> not change + # Keep OWNER[sym]. + replace_topalias(sym, obj) else - # file => loaded class object - Object.const_set(sym, file) + # New definition + @TOPLEVEL_ALIAS_OWNER[sym] = target + replace_topalias(sym, obj) + replace_topobj(sym, obj) end - @TOPLEVEL_ALIAS_OWNER[sym] = target } - # update current alias + # change default_widget_set @current_default_widget_set = target end + private :_replace_toplevel_aliases + + def __import_toplevel_aliases__(target, *symbols) + current = @current_default_widget_set + symbols.each{|sym| + sym = sym.to_sym + if (obj = @TOPLEVEL_ALIAS_TABLE[target][sym]).nil? + # remove + @TOPLEVEL_ALIAS_TABLE[current].delete(sym) + @TOPLEVEL_ALIAS_OWNER.delete(sym) + Tk::TOPLEVEL_ALIASES.module_eval{remove_const sym} if topalias_defined?(sym) + Object.class_eval{remove_const sym} if topobj_defined?(sym) + + elsif obj == false + # remove, but OWNER[sym] <- false and not treat Object::sym + @TOPLEVEL_ALIAS_TABLE[current].delete(sym) + @TOPLEVEL_ALIAS_OWNER[sym] = false + Tk::TOPLEVEL_ALIASES.module_eval{remove_const sym} if topalias_defined?(sym) + + elsif @TOPLEVEL_ALIAS_OWNER[sym] == false + # Object::sym is out of control. --> not change + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[current][sym] = obj + replace_topalias(sym, obj) + + else + # new definition under control + @TOPLEVEL_ALIAS_OWNER[sym] = current + @TOPLEVEL_ALIAS_TABLE[current][sym] = obj + replace_topalias(sym, obj) + replace_topobj(sym, obj) + end + } + end + + def __remove_toplevel_aliases__(*symbols) + # remove toplevel aliases of current widget set + current = @current_default_widget_set + symbols.each{|sym| + sym = sym.to_sym + @TOPLEVEL_ALIAS_TABLE[current].delete(sym) + @TOPLEVEL_ALIAS_OWNER.delete(sym) + Tk::TOPLEVEL_ALIASES.module_eval{remove_const sym} if topalias_defined?(sym) + Object.class_eval{remove_const sym} if topobj_defined?(sym) + } + end + + def __reset_toplevel_owner__(*symbols) + symbols.each{|sym| @TOPLEVEL_ALIAS_OWNER.delete(sym.to_sym)} + end + + def __disable_toplevel_control__(*symbols) + symbols.each{|sym| @TOPLEVEL_ALIAS_OWNER[sym.to_sym] = false} + end + + def __create_widget_set__(new_set, src_set={}) + new_set = new_set.to_sym + if @TOPLEVEL_ALIAS_TABLE[new_set] + fail RuntimeError, "A widget-set #{new_set.inspect} is already exist." + end + if src_set.kind_of?(Symbol) + # new_set is an alias name of existed widget set. + @TOPLEVEL_ALIAS_TABLE[new_set] = @TOPLEVEL_ALIAS_TABLE[src_set] + else + @TOPLEVEL_ALIAS_TABLE[new_set] = {} + src_set.each{|sym, obj| set_topalias(new_set, obj, sym.to_sym) } + end + end end + ############################################ # setup default widget set => :Tk Tk.default_widget_set = :Tk diff --git a/ext/tk/lib/tk/bindtag.rb b/ext/tk/lib/tk/bindtag.rb index 88c8367a88..23b4e0b7c3 100644 --- a/ext/tk/lib/tk/bindtag.rb +++ b/ext/tk/lib/tk/bindtag.rb @@ -9,7 +9,7 @@ class TkBindTag #BTagID_TBL = {} BTagID_TBL = TkCore::INTERP.create_table - (Tk_BINDTAG_ID = ["btag".freeze, "00000".taint]).instance_eval{ + (Tk_BINDTAG_ID = ["btag".freeze, TkUtil.untrust("00000")]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze diff --git a/ext/tk/lib/tk/busy.rb b/ext/tk/lib/tk/busy.rb new file mode 100644 index 0000000000..7f4f89f524 --- /dev/null +++ b/ext/tk/lib/tk/busy.rb @@ -0,0 +1,118 @@ +# +# tk/busy.rb: support 'tk busy' command (Tcl/Tk8.6 or later) +# +require 'tk' + +module Tk::Busy + include TkCore + extend TkCore + extend TkItemConfigMethod +end + +class << Tk::Busy + def __item_cget_cmd(win) + # maybe need to override + ['tk', 'busy', 'cget', win.path] + end + private :__item_cget_cmd + + def __item_config_cmd(win) + # maybe need to override + ['tk', 'busy', 'configure', win.path] + end + private :__item_config_cmd + + def __item_confinfo_cmd(win) + # maybe need to override + __item_config_cmd(win) + end + private :__item_confinfo_cmd + + alias cget_tkstring itemcget_tkstring + alias cget itemcget + alias cget_strict itemcget_strict + alias configure itemconfigure + alias configinfo itemconfiginfo + alias current_configinfo current_itemconfiginfo + + private :itemcget_tkstring, :itemcget, :itemcget_strict + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo + + def method_missing(id, *args) + name = id.id2name + case args.length + when 1 + if name[-1] == ?= + configure name[0..-2], args[0] + args[0] + else + configure name, args[0] + self + end + when 0 + begin + cget(name) + rescue + super(id, *args) + end + else + super(id, *args) + end + end + + def hold(win, keys={}) + tk_call_without_enc('tk', 'busy', 'hold', win, *hash_kv(keys)) + win + end + + def forget(*wins) + tk_call_without_enc('tk', 'busy', 'forget', *wins) + self + end + + def current(pat=None) + list(tk_call('tk', 'busy', 'current', pat)) + end + + def status(win) + bool(tk_call_without_enc('tk', 'busy', 'status', win)) + end +end + +module Tk::Busy + def busy_configinfo(option=nil) + Tk::Busy.configinfo(self, option) + end + + def busy_current_configinfo(option=nil) + Tk::Busy.current_configinfo(self, option) + end + + def busy_configure(option, value=None) + Tk::Busy.configure(self, option, value) + self + end + + def busy_cget(option) + Tk::Busy.configure(self, option) + end + + def busy(keys={}) + Tk::Busy.hold(self, keys) + self + end + alias busy_hold busy + + def busy_forget + Tk::Busy.forget(self) + self + end + + def busy_current? + ! Tk::Busy.current(self.path).empty? + end + + def busy_status + Tk::Busy.status(self) + end +end diff --git a/ext/tk/lib/tk/button.rb b/ext/tk/lib/tk/button.rb index 770a5785bb..65233c91b6 100644 --- a/ext/tk/lib/tk/button.rb +++ b/ext/tk/lib/tk/button.rb @@ -7,7 +7,7 @@ require 'tk/label' class Tk::Button' end + def _get_opt_method_list(arg) + m_set, m_cget, m_info = arg + m_set = m_set.to_s + m_cget = m_set if !m_cget && self.method(m_set).arity == -1 + m_cget = m_cget.to_s if m_cget + m_info = m_info.to_s if m_info + [m_set, m_cget, m_info] + end + private :_get_opt_method_list + def option_methods(*opts) - opts.each{|m_set, m_cget, m_info| - m_set = m_set.to_s - m_cget = m_set if !m_cget && self.method(m_set).arity == -1 - m_cget = m_cget.to_s if m_cget - m_info = m_info.to_s if m_info - @option_methods[m_set] = { - :set => m_set, :cget => m_cget, :info => m_info + if opts.size == 1 && opts[0].kind_of?(Hash) + # {name => [m_set, m_cget, m_info], name => method} style + opts[0].each{|name, arg| + m_set, m_cget, m_info = _get_opt_method_list(arg) + @option_methods[name.to_s] = { + :set => m_set, :cget => m_cget, :info => m_info + } } - } + else + # [m_set, m_cget, m_info] or method style + opts.each{|arg| + m_set, m_cget, m_info = _get_opt_method_list(arg) + @option_methods[m_set] = { + :set => m_set, :cget => m_cget, :info => m_info + } + } + end end def delegate_alias(alias_opt, option, *wins) @@ -215,6 +233,14 @@ module TkComposite end private :__cget_delegates + def cget_tkstring(slot) + if (ret = __cget_delegates(slot)) == None + super(slot) + else + _get_eval_string(ret) + end + end + def cget(slot) if (ret = __cget_delegates(slot)) == None super(slot) diff --git a/ext/tk/lib/tk/entry.rb b/ext/tk/lib/tk/entry.rb index 8ce8def1e7..d4aa03f2b6 100644 --- a/ext/tk/lib/tk/entry.rb +++ b/ext/tk/lib/tk/entry.rb @@ -13,7 +13,7 @@ class Tk::Entrye + if TkCore::INTERP.kind_of?(TclTkIp) + fail e + else + # MultiTkIp + fail Exception, "#{e.class}: #{e.message.dup}" + end + end + }) + end else keys, args = klass._get_all_subst_keys diff --git a/ext/tk/lib/tk/font.rb b/ext/tk/lib/tk/font.rb index da6482c122..03db850f96 100644 --- a/ext/tk/lib/tk/font.rb +++ b/ext/tk/lib/tk/font.rb @@ -11,7 +11,7 @@ class TkFont TkCommandNames = ['font'.freeze].freeze - (Tk_FontID = ["@font".freeze, "00000".taint]).instance_eval{ + (Tk_FontID = ["@font".freeze, TkUtil.untrust("00000")]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze @@ -211,7 +211,7 @@ class TkFont end end def TkFont.actual_hash(fnt, option=nil) - Hash[TkFont.actual_hash(fnt, option)] + Hash[TkFont.actual(fnt, option)] end def TkFont.actual_displayof(fnt, win, option=nil) @@ -224,7 +224,7 @@ class TkFont end end def TkFont.actual_hash_displayof(fnt, option=nil) - Hash[TkFont.actual_hash_displayof(fnt, option)] + Hash[TkFont.actual_displayof(fnt, option)] end def TkFont.configure(fnt, slot, value=None) @@ -2199,7 +2199,7 @@ module TkFont::CoreMethods alias measure_core measure_core_tk4x alias metrics_core metrics_core_tk4x - when /^8\.[0-5]/ + when /^8\.[0-9]/ alias actual_core actual_core_tk8x alias configure_core configure_core_tk8x alias configinfo_core configinfo_core_tk8x @@ -2342,3 +2342,10 @@ if Tk::TCL_MAJOR_VERSION > 8 || 'systemDetailSystemFont', 'systemDetailEmphasizedSystemFont' ] end + +####################################### +# autoload +####################################### +class TkFont + autoload :Chooser, 'tk/fontchooser' +end diff --git a/ext/tk/lib/tk/fontchooser.rb b/ext/tk/lib/tk/fontchooser.rb new file mode 100644 index 0000000000..f9f816be59 --- /dev/null +++ b/ext/tk/lib/tk/fontchooser.rb @@ -0,0 +1,166 @@ +# +# tk/fontchooser.rb -- "tk fontchooser" support (Tcl/Tk8.6 or later) +# +require 'tk' +require 'tk/font' + +module TkFont::Chooser + extend TkCore +end + +class << TkFont::Chooser + def method_missing(id, *args) + name = id.id2name + case args.length + when 1 + if name[-1] == ?= + configure name[0..-2], args[0] + args[0] + else + configure name, args[0] + self + end + when 0 + begin + cget(name) + rescue + super(id, *args) + end + else + super(id, *args) + end + end + + def __conviginfo_value(key, val) + case key + when 'parent' + window(val) + when 'title' + val + when 'font' + if (lst = tk_split_simplelist(val)).size == 1 + lst[0] + else + lst.map{|elem| num_or_str(elem)} + end + when 'command' + tk_tcl2ruby(val) + when 'visible' + bool(val) + else # unkown + val + end + end + private :__conviginfo_value + + def configinfo(option=nil) + if !option && TkComm::GET_CONFIGINFOwoRES_AS_ARRAY + lst = tk_split_simplelist(tk_call('tk', 'fontchooser', 'configure')) + ret = [] + TkComm.slice_ary(lst, 2){|k, v| + k = k[1..-1] + ret << [k, __conviginfo_value(k, v)] + } + ret + else + current_configinfo(option) + end + end + + def current_configinfo(option=nil) + if option + opt = option.to_s + fail ArgumentError, "Invalid option `#{option.inspect}'" if opt.empty? + __conviginfo_value(option.to_s, tk_call('tk','fontchooser', + 'configure',"-#{opt}")) + else + lst = tk_split_simplelist(tk_call('tk', 'fontchooser', 'configure')) + ret = {} + TkComm.slice_ary(lst, 2){|k, v| + k = k[1..-1] + ret[k] = __conviginfo_value(k, v) + } + ret + end + end + + def configure(option, value=None) + if option.kind_of? Hash + tk_call('tk', 'fontchooser', 'configure', + *hash_kv(_symbolkey2str(option))) + else + opt = option.to_s + fail ArgumentError, "Invalid option `#{option.inspect}'" if opt.empty? + tk_call('tk', 'fontchooser', 'configure', "-#{opt}", value) + end + self + end + + def configure_cmd(slot, value) + configure(slot, install_cmd(value)) + end + + def command(cmd=nil, &b) + if cmd + configure_cmd('command', cmd) + elsif b + configure_cmd('command', Proc.new(&b)) + else + cget('command') + end + end + + def cget(slot) + configinfo slot + end + + def [](slot) + cget slot + end + + def []=(slot, val) + configure slot, val + val + end + + def show + tk_call('tk', 'fontchooser', 'show') + self + end + + def hide + tk_call('tk', 'fontchooser', 'hide') + self + end + + def toggle + cget(:visible) ? hide: show + self + end + + def set_for(target, title="Font") + if target.kind_of? TkFont + configs = { + :font=>target.actual_hash, + :command=>proc{|fnt, *args| + target.configure(TkFont.actual_hash(fnt)) + } + } + else + configs = { + :font=>target.cget_tkstring(:font), + :command=>proc{|fnt, *args| + target.font = TkFont.actual_hash_displayof(fnt, target) + } + } + end + + configs[:title] = title if title + configure(configs) + target + end + + def unset + configure(:command, nil) + end +end diff --git a/ext/tk/lib/tk/frame.rb b/ext/tk/lib/tk/frame.rb index 263b160f29..5118939732 100644 --- a/ext/tk/lib/tk/frame.rb +++ b/ext/tk/lib/tk/frame.rb @@ -6,7 +6,7 @@ require 'tk' class Tk::Frame'cascade'). When type is 'cascade', an array of menu_info # is acceptable for 'menu' key (then, create sub-menu). # +# If the value of underline is true instead of an integer, +# check whether the text/label string contains a '&' character. +# When includes, the first '&' is removed and its following character is +# converted the corresponding 'underline' option (first '&' is removed). +# Else if the value of underline is a String or a Regexp, +# use the result of label.index(underline) as the index of underline +# (don't remove matched substring). +# # NOTE: (*1) # If you want to make special menus (*.help for UNIX, *.system for Win, # and *.apple for Mac), append 'menu_name'=>name (name is 'help' for UNIX, @@ -39,6 +54,10 @@ # to the configs of the cascade entry. module TkMenuSpec + extend TkMenuSpec + + MENUSPEC_OPTKEYS = [ 'layout_proc' ] + def _create_menu(parent, menu_info, menu_name = nil, tearoff = false, default_opts = nil) if tearoff.kind_of?(Hash) @@ -59,6 +78,7 @@ module TkMenuSpec end tearoff = orig_opts.delete('tearoff') if orig_opts.key?('tearoff') + tearoff = false unless tearoff # nil --> false if menu_name #menu = Tk::Menu.new(parent, :widgetname=>menu_name, :tearoff=>tearoff) @@ -84,6 +104,23 @@ module TkMenuSpec tearoff, menu_opts) options['menu'] = submenu end + case options['underline'] + when String, Regexp + if options['label'] && + (idx = options['label'].index(options['underline'])) + options['underline'] = idx + else + options['underline'] = -1 + end + when true + if options['label'] && (idx = options['label'].index('&')) + options['label'] = options['label'].dup + options['label'][idx] = '' + options['underline'] = idx + else + options['underline'] = -1 + end + end menu.add(item_type, options) elsif item_info.kind_of?(Array) @@ -138,6 +175,25 @@ module TkMenuSpec end options.update(opts) end + + case options['underline'] + when String, Regexp + if options['label'] && + (idx = options['label'].index(options['underline'])) + options['underline'] = idx + else + options['underline'] = -1 + end + when true + if options['label'] && (idx = options['label'].index('&')) + options['label'] = options['label'].dup + options['label'][idx] = '' + options['underline'] = idx + else + options['underline'] = -1 + end + end + menu.add(item_type, options) elsif /^-+$/ =~ item_info @@ -177,7 +233,7 @@ module TkMenuSpec end private :_create_menu_for_menubar - def _create_menubutton(parent, menu_info, tearoff=false, default_opts = nil) + def _create_menubutton(parent, menu_info, tearoff=false, default_opts = {}) btn_info = menu_info[0] if tearoff.kind_of?(Hash) @@ -186,14 +242,49 @@ module TkMenuSpec end if default_opts.kind_of?(Hash) - keys = _symbolkey2str(default_opts) - else - keys = {} + default_opts = _symbolkey2str(default_opts) + + if default_opts.has_key?('layout_proc') + layout_proc = default_opts.delete('layout_proc') + end + + _vertical_mbar_bind_proc = proc{|m, dir| + Tk::Menu::TkInternalFunction.next_menu(m, dir) rescue nil + # ignore error when the internal function doesn't exist + } + + case layout_proc + when :vertical, 'vertical', :vertical_left, 'vertical_left' + layout_proc = proc{|_parent, _mbtn| + _mbtn.direction :right + _mbtn.pack(:side=>:top, :fill=>:x) + + menu = _mbtn.menu + menu.bind('Tab', _vertical_mbar_bind_proc, :widget, 'forward') + menu.bind('Alt-Tab', _vertical_mbar_bind_proc, :widget, 'backward') + } + when :vertical_right, 'vertical_right' + layout_proc = proc{|_parent, _mbtn| + _mbtn.direction :left + _mbtn.pack(:side=>:top, :fill=>:x) + + menu = _mbtn.menu + menu.bind('Tab', _vertical_mbar_bind_proc, :widget, 'forward') + menu.bind('Alt-Tab', _vertical_mbar_bind_proc, :widget, 'backward') + } + when :horizontal, 'horizontal' + layout_proc = proc{|_parent, _mbtn| _mbtn.pack(:side=>:left)} + else + # do nothing + end end + keys = default_opts.dup + tearoff = keys.delete('tearoff') if keys.key?('tearoff') + tearoff = false unless tearoff # nil --> false - if _use_menubar?(parent) + if _use_menubar?(parent) && ! layout_proc # menubar by menu entries mbar = _create_menu_for_menubar(parent) @@ -202,14 +293,52 @@ module TkMenuSpec if btn_info.kind_of?(Hash) keys.update(_symbolkey2str(btn_info)) menu_name = keys.delete('menu_name') - keys['label'] = keys.delete('text') if keys.key?('text') + keys['label'] = keys.delete('text') || '' + + case keys['underline'] + when String, Regexp + if idx = keys['label'].index(keys['underline']) + keys['underline'] = idx + else + keys['underline'] = -1 + end + when true + if idx = keys['label'].index('&') + keys['label'] = keys['label'].dup + keys['label'][idx] = '' + keys['underline'] = idx + else + keys['underline'] = -1 + end + end + elsif btn_info.kind_of?(Array) keys['label'] = btn_info[0] if btn_info[0] - keys['underline'] = btn_info[1] if btn_info[1] + + case btn_info[1] + when Integer + keys['underline'] = btn_info[1] + when String, Regexp + if idx = keys['label'].index(btn_info[1]) + keys['underline'] = idx + else + keys['underline'] = -1 + end + when true + if idx = keys['label'].index('&') + keys['label'] = keys['label'].dup + keys['label'][idx] = '' + keys['underline'] = idx + else + keys['underline'] = -1 + end + end + if btn_info[2]&&btn_info[2].kind_of?(Hash) keys.update(_symbolkey2str(btn_info[2])) menu_name = keys.delete('menu_name') end + else keys = {:label=>btn_info} end @@ -234,9 +363,42 @@ module TkMenuSpec if btn_info.kind_of?(Hash) keys.update(_symbolkey2str(btn_info)) menu_name = keys.delete('menu_name') - keys['text'] = keys.delete('label') if keys.key?('label') + keys['text'] = keys.delete('label') || '' + case keys['underline'] + when String, Regexp + if idx = keys['text'].index(keys['underline']) + keys['underline'] = idx + else + keys['underline'] = -1 + end + when true + if idx = keys['text'].index('&') + keys['text'] = keys['text'].dup + keys['text'][idx] = '' + keys['underline'] = idx + else + keys['underline'] = -1 + end + end mbtn.configure(keys) + elsif btn_info.kind_of?(Array) + case btn_info[1] + when String, Regexp + if btn_info[0] && (idx = btn_info[0].index(btn_info[1])) + btn_info[1] = idx + else + btn_info[1] = -1 + end + when true + if btn_info[0] && (idx = btn_info[0].index('&')) + btn_info[0] = btn_info[0].dup + btn_info[0][idx] = '' + btn_info[1] = idx + else + btn_info[1] = -1 + end + end mbtn.configure('text', btn_info[0]) if btn_info[0] mbtn.configure('underline', btn_info[1]) if btn_info[1] # mbtn.configure('accelerator', btn_info[2]) if btn_info[2] @@ -245,22 +407,41 @@ module TkMenuSpec menu_name = keys.delete('menu_name') mbtn.configure(keys) end + else mbtn.configure('text', btn_info) end - mbtn.pack('side' => 'left') - menu = _create_menu(mbtn, menu_info[1..-1], menu_name, tearoff, default_opts) - mbtn.menu(menu) + if layout_proc.kind_of?(Proc) || layout_proc.kind_of?(Method) + # e.g. make a vertical menubar + # :layout_proc => proc{|parent, btn| btn.pack(:side=>:top, :fill=>:x)} + layout_proc.call(parent, mbtn) + else + mbtn.pack('side' => 'left') + end + [mbtn, menu] end end private :_create_menubutton + def _create_menubar(parent, menu_spec, tearoff = false, opts = nil) + if tearoff.kind_of?(Hash) + opts = tearoff + tearoff = false + end + tearoff = false unless tearoff # nil --> false + menu_spec.each{|menu_info| + _create_menubutton(parent, menu_info, tearoff, opts) + } + parent + end + private :_create_menubar + def _get_cascade_menus(menu) menus = [] (0..(menu.index('last'))).each{|idx| diff --git a/ext/tk/lib/tk/message.rb b/ext/tk/lib/tk/message.rb index 946b68c704..5f73b3066f 100644 --- a/ext/tk/lib/tk/message.rb +++ b/ext/tk/lib/tk/message.rb @@ -7,7 +7,7 @@ require 'tk/label' class Tk::Message e + # old version of element? + begin + tk_send_without_enc('invoke', 'spinup') + rescue + fail e + end + end self end def spindown - tk_send_without_enc('invoke', 'spindown') + begin + tk_send_without_enc('invoke', 'buttondown') + rescue RuntimeError => e + # old version of element? + begin + tk_send_without_enc('invoke', 'spinup') + rescue + fail e + end + end self end @@ -116,4 +139,6 @@ class Tk::Spinbox 'tkextlib/tile/treeview', } - @TOPLEVEL_ALIAS_TABLE[:Tile] = @TOPLEVEL_ALIAS_TABLE[:Ttk] + + # @TOPLEVEL_ALIAS_TABLE[:Tile] = @TOPLEVEL_ALIAS_TABLE[:Ttk] + Tk.__create_widget_set__(:Tile, :Ttk) + + ############################################ + # depend on the version of Tcl/Tk + major, minor, type, patchlevel = TclTkLib.get_version + + # ttk::spinbox is supported on Tcl/Tk8.6b1 or later + if ([major,minor,type,patchlevel] <=> + [8,6,TclTkLib::RELEASE_TYPE::BETA,1]) >= 0 + @TOPLEVEL_ALIAS_TABLE[:Ttk].update( + :TkSpinbox => 'tkextlib/tile/tspinbox' + ) + end ################################################ # register some Ttk widgets as default # (Ttk is a standard library on Tcl/Tk8.5+) @TOPLEVEL_ALIAS_TABLE[:Ttk].each{|sym, file| - unless Object.autoload?(sym) || Object.const_defined?(sym) - Object.autoload(sym, file) - end + #unless Tk::TOPLEVEL_ALIASES.autoload?(sym) || Tk::TOPLEVEL_ALIASES.const_defined?(sym) + # @TOPLEVEL_ALIAS_OWNER[sym] = :Ttk + # Tk::TOPLEVEL_ALIASES.autoload(sym, file) + #end + Tk.__regist_toplevel_aliases__(:Ttk, file, sym) } ################################################ - @TOPLEVEL_ALIAS_SETUP_PROC[:Tile] = - @TOPLEVEL_ALIAS_SETUP_PROC[:Ttk] = proc{|mod| + # @TOPLEVEL_ALIAS_SETUP_PROC[:Tile] = + # @TOPLEVEL_ALIAS_SETUP_PROC[:Ttk] = proc{|mod| + # unless Tk.autoload?(:Tile) || Tk.const_defined?(:Tile) + # Object.autoload :Ttk, 'tkextlib/tile' + # Tk.autoload :Tile, 'tkextlib/tile' + # end + # } + Tk.__toplevel_alias_setup_proc__(:Ttk, :Tile){|mod| unless Tk.autoload?(:Tile) || Tk.const_defined?(:Tile) Object.autoload :Ttk, 'tkextlib/tile' Tk.autoload :Tile, 'tkextlib/tile' diff --git a/ext/tk/lib/tk/variable.rb b/ext/tk/lib/tk/variable.rb index bdd441705b..6fc2ffdf2f 100644 --- a/ext/tk/lib/tk/variable.rb +++ b/ext/tk/lib/tk/variable.rb @@ -16,7 +16,7 @@ class TkVariable #TkVar_ID_TBL = {} TkVar_CB_TBL = TkCore::INTERP.create_table TkVar_ID_TBL = TkCore::INTERP.create_table - (Tk_VARIABLE_ID = ["v".freeze, "00000".taint]).instance_eval{ + (Tk_VARIABLE_ID = ["v".freeze, TkUtil.untrust("00000")]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze @@ -1239,6 +1239,14 @@ end end end + def ===(other) + if other.kind_of?(TkVariable) + self.id == other.id + else + super + end + end + def zero? numeric.zero? end diff --git a/ext/tk/lib/tk/virtevent.rb b/ext/tk/lib/tk/virtevent.rb index ba771da647..19c0dac380 100644 --- a/ext/tk/lib/tk/virtevent.rb +++ b/ext/tk/lib/tk/virtevent.rb @@ -9,7 +9,7 @@ class TkVirtualEvent======================= -Tcllib 1.8 -Tklib 0.4.1 http://sourceforge.net/projects/tcllib ==> tcllib +Tcllib 1.11.1 +Tklib 0.5 http://sourceforge.net/projects/tcllib ==> tcllib + ( partial support; primary support target is Tklib) IWidgets 4.0.2 http://sourceforge.net/projects/incrtcl ==> iwidgets -BWidgets 1.7 http://sourceforge.net/projects/tcllib ==> bwidget +BWidget 1.8 [ CVS/Hd(2009-07-02) ] + http://sourceforge.net/projects/tcllib ==> bwidget -TkTable 2.9 http://sourceforge.net/projects/tktable ==> tktable +TkTable 2.10 http://sourceforge.net/projects/tktable ==> tktable * see also written by Ferenc Engard (ferenc@engard.hu) -vu 2.3.0 http://sourceforge.net/projects/tktable ==> vu +Vu widgets 2.3.0 http://sourceforge.net/projects/tktable ==> vu TkHTML 2.0 http://www.hwaci.com/sw/tkhtml/ ==> tkHTML @@ -80,25 +82,25 @@ BLT 2.4z http://sourceforge.net/projects/blt (http://raa.ruby-lang.org/) ==> blt -TkTreeCtrl CVS/Hd(2005-12-02) - http://sourceforge.net/projects/tktreectrl ==> treectrl +TkTreeCtrl 2.2.9 + http://tktreectrl.sourceforge.net/ ==> treectrl -Tile 0.8.0/8.5.1 +Tile 0.8.3/8.6b1 http://sourceforge.net/projects/tktable ==> tile ===< support (may be alpha or beta quality) >================================= -IncrTcl CVS/Hd(2005-02-14) +IncrTcl CVS/Hd(2008-12-15) http://sourceforge.net/projects/incrtcl ==> itcl, itk -TclX CVS/Hd(2005-02-07) +TclX CVS/Hd(2008-12-15) http://sourceforge.net/projects/tclx ==> tclx (partial support; infox command and XPG/3 message catalogs only) -Trofs 0.4.3 http://math.nist.gov/~DPorter/tcltk/trofs/ +Trofs 0.4.4 http://math.nist.gov/~DPorter/tcltk/trofs/ diff --git a/ext/tk/lib/tkextlib/blt.rb b/ext/tk/lib/tkextlib/blt.rb index 8d58c1f1bc..8b132e41a7 100644 --- a/ext/tk/lib/tkextlib/blt.rb +++ b/ext/tk/lib/tkextlib/blt.rb @@ -19,6 +19,8 @@ TkPackage.require('BLT') module Tk module BLT TkComm::TkExtlibAutoloadModule.unshift(self) + # Require autoload-symbols which is a same name as widget classname. + # Those are used at TkComm._genobj_for_tkwidget method. extend TkCore diff --git a/ext/tk/lib/tkextlib/blt/barchart.rb b/ext/tk/lib/tkextlib/blt/barchart.rb index 8e71c3f5e0..a86b91c959 100644 --- a/ext/tk/lib/tkextlib/blt/barchart.rb +++ b/ext/tk/lib/tkextlib/blt/barchart.rb @@ -11,7 +11,7 @@ module Tk::BLT class Barchart < TkWindow TkCommandNames = ['::blt::barchart'.freeze].freeze WidgetClassName = 'Barchart'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self include PlotComponent include GraphCommand @@ -33,7 +33,7 @@ module Tk::BLT private :__tkvariable_optkeys =begin - BarElement_ID = ['blt_barchart_bar'.freeze, '00000'.taint].freeze + BarElement_ID = ['blt_barchart_bar'.freeze, TkUtil.untrust('00000')].freeze def bar(elem=nil, keys={}) if elem.kind_of?(Hash) diff --git a/ext/tk/lib/tkextlib/blt/bitmap.rb b/ext/tk/lib/tkextlib/blt/bitmap.rb index 23c6d2d064..3254b63116 100644 --- a/ext/tk/lib/tkextlib/blt/bitmap.rb +++ b/ext/tk/lib/tkextlib/blt/bitmap.rb @@ -14,7 +14,7 @@ module Tk::BLT BITMAP_ID_TBL = TkCore::INTERP.create_table - (BITMAP_ID = ['blt_bitmap_id'.freeze, '00000'.taint]).instance_eval{ + (BITMAP_ID = ['blt_bitmap_id'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze diff --git a/ext/tk/lib/tkextlib/blt/busy.rb b/ext/tk/lib/tkextlib/blt/busy.rb index 2f807fcd9c..b5287fb5b7 100644 --- a/ext/tk/lib/tkextlib/blt/busy.rb +++ b/ext/tk/lib/tkextlib/blt/busy.rb @@ -44,6 +44,7 @@ class << Tk::BLT::Busy private :__item_config_cmd undef itemcget + undef itemcget_tkstring alias configure itemconfigure alias configinfo itemconfiginfo alias current_configinfo current_itemconfiginfo diff --git a/ext/tk/lib/tkextlib/blt/component.rb b/ext/tk/lib/tkextlib/blt/component.rb index 74cbcb56ae..20db035fdd 100644 --- a/ext/tk/lib/tkextlib/blt/component.rb +++ b/ext/tk/lib/tkextlib/blt/component.rb @@ -82,6 +82,9 @@ module Tk::BLT end private :__item_pathname + def axis_cget_tkstring(id, option) + ret = itemcget_tkstring(['axis', tagid(id)], option) + end def axis_cget(id, option) ret = itemcget(['axis', tagid(id)], option) end @@ -118,6 +121,9 @@ module Tk::BLT current_itemconfiginfo(['axis', tagid(id)], slot) end + def crosshairs_cget_tkstring(option) + itemcget_tkstring('crosshairs', option) + end def crosshairs_cget(option) itemcget('crosshairs', option) end @@ -134,6 +140,9 @@ module Tk::BLT current_itemconfiginfo('crosshairs', slot) end + def element_cget_tkstring(id, option) + itemcget_tkstring(['element', tagid(id)], option) + end def element_cget(id, option) itemcget(['element', tagid(id)], option) end @@ -158,6 +167,9 @@ module Tk::BLT current_itemconfiginfo(['element', tagid(id)], slot) end + def bar_cget_tkstring(id, option) + itemcget_tkstring(['bar', tagid(id)], option) + end def bar_cget(id, option) itemcget(['bar', tagid(id)], option) end @@ -182,6 +194,9 @@ module Tk::BLT current_itemconfiginfo(['bar', tagid(id)], slot) end + def line_cget_tkstring(id, option) + itemcget_tkstring(['line', tagid(id)], option) + end def line_cget(id, option) itemcget(['line', tagid(id)], option) end @@ -206,6 +221,9 @@ module Tk::BLT current_itemconfiginfo(['line', tagid(id)], slot) end + def gridline_cget_tkstring(option) + itemcget_tkstring('grid', option) + end def gridline_cget(option) itemcget('grid', option) end @@ -222,6 +240,9 @@ module Tk::BLT current_itemconfiginfo('grid', slot) end + def legend_cget_tkstring(option) + itemcget_tkstring('legend', option) + end def legend_cget(option) itemcget('legend', option) end @@ -238,6 +259,9 @@ module Tk::BLT current_itemconfiginfo('legend', slot) end + def pen_cget_tkstring(id, option) + itemcget_tkstring(['pen', tagid(id)], option) + end def pen_cget(id, option) itemcget(['pen', tagid(id)], option) end @@ -262,6 +286,9 @@ module Tk::BLT current_itemconfiginfo(['pen', tagid(id)], slot) end + def postscript_cget_tkstring(option) + itemcget_tkstring('postscript', option) + end def postscript_cget(option) itemcget('postscript', option) end @@ -278,6 +305,9 @@ module Tk::BLT current_itemconfiginfo('postscript', slot) end + def marker_cget_tkstring(id, option) + itemcget_tkstring(['marker', tagid(id)], option) + end def marker_cget(id, option) itemcget(['marker', tagid(id)], option) end @@ -302,12 +332,16 @@ module Tk::BLT current_itemconfiginfo(['marker', tagid(id)], slot) end + alias __itemcget_tkstring itemcget_tkstring alias __itemcget itemcget alias __itemcget_strict itemcget_strict alias __itemconfiginfo itemconfiginfo alias __current_itemconfiginfo current_itemconfiginfo - private :__itemcget, :__itemconfiginfo, :__current_itemconfiginfo + private :__itemcget_tkstring, :__itemcget, :__itemconfiginfo, :__current_itemconfiginfo + def itemcget_tkstring(tagOrId, option) + __itemcget_tkstring(tagid(tagOrId), option) + end def itemcget_strict(tagOrId, option) ret = __itemcget(tagid(tagOrId), option) if option == 'bindtags' || option == :bindtags @@ -373,13 +407,13 @@ module Tk::BLT ret end - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo ################# class Axis < TkObject - (OBJ_ID = ['blt_chart_axis'.freeze, '00000'.taint]).instance_eval{ + (OBJ_ID = ['blt_chart_axis'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze @@ -477,6 +511,9 @@ module Tk::BLT @id end + def cget_tkstring(option) + @chart.axis_cget_tkstring(@id, option) + end def cget(option) @chart.axis_cget(@id, option) end @@ -582,6 +619,9 @@ module Tk::BLT @id end + def cget_tkstring(option) + @chart.crosshair_cget_tkstring(option) + end def cget(option) @chart.crosshair_cget(option) end @@ -631,7 +671,7 @@ module Tk::BLT ElementID_TBL.mutex.synchronize{ ElementID_TBL.clear } } - (OBJ_ID = ['blt_chart_element'.freeze, '00000'.taint]).instance_eval{ + (OBJ_ID = ['blt_chart_element'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze @@ -729,6 +769,10 @@ module Tk::BLT @id end + def cget_tkstring(option) + # @chart.element_cget(@id, option) + @chart.__send__(@typename + '_cget_tkstring', @id, option) + end def cget(option) # @chart.element_cget(@id, option) @chart.__send__(@typename + '_cget', @id, option) @@ -833,6 +877,9 @@ module Tk::BLT @id end + def cget_tkstring(option) + @chart.gridline_cget_tkstring(option) + end def cget(option) @chart.gridline_cget(option) end @@ -907,6 +954,9 @@ module Tk::BLT @id end + def cget_tkstring(option) + @chart.legend_cget_tkstring(option) + end def cget(option) @chart.legend_cget(option) end @@ -940,7 +990,7 @@ module Tk::BLT ################# class Pen < TkObject - (OBJ_ID = ['blt_chart_pen'.freeze, '00000'.taint]).instance_eval{ + (OBJ_ID = ['blt_chart_pen'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze @@ -1036,6 +1086,9 @@ module Tk::BLT @id end + def cget_tkstring(option) + @chart.pen_cget_tkstring(@id, option) + end def cget(option) @chart.pen_cget(@id, option) end @@ -1106,6 +1159,9 @@ module Tk::BLT @id end + def cget_tkstring(option) + @chart.postscript_cget_tkstring(option) + end def cget(option) @chart.postscript_cget(option) end @@ -1269,6 +1325,9 @@ module Tk::BLT @id end + def cget_tkstring(option) + @chart.marker_cget_tkstring(@id, option) + end def cget(option) @chart.marker_cget(@id, option) end @@ -1854,6 +1913,9 @@ module Tk::BLT ################### + def xaxis_cget_tkstring(option) + itemcget_tkstring('xaxis', option) + end def xaxis_cget(option) itemcget('xaxis', option) end @@ -1926,6 +1988,9 @@ module Tk::BLT end end + def x2axis_cget_tkstring(option) + itemcget_tkstring('x2axis', option) + end def x2axis_cget(option) itemcget('x2axis', option) end @@ -1998,6 +2063,9 @@ module Tk::BLT end end + def yaxis_cget_tkstring(option) + itemcget_tkstring('yaxis', option) + end def yaxis_cget(option) itemcget('yaxis', option) end @@ -2070,6 +2138,9 @@ module Tk::BLT end end + def y2axis_cget_tkstring(option) + itemcget_tkstring('y2axis', option) + end def y2axis_cget(option) itemcget('y2axis', option) end diff --git a/ext/tk/lib/tkextlib/blt/container.rb b/ext/tk/lib/tkextlib/blt/container.rb index cdbec21f25..be05828d95 100644 --- a/ext/tk/lib/tkextlib/blt/container.rb +++ b/ext/tk/lib/tkextlib/blt/container.rb @@ -10,7 +10,7 @@ module Tk::BLT class Container < TkWindow TkCommandNames = ['::blt::container'.freeze].freeze WidgetClassName = 'Container'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() << 'name' diff --git a/ext/tk/lib/tkextlib/blt/dragdrop.rb b/ext/tk/lib/tkextlib/blt/dragdrop.rb index d11d8bc41a..aa5c5654c2 100644 --- a/ext/tk/lib/tkextlib/blt/dragdrop.rb +++ b/ext/tk/lib/tkextlib/blt/dragdrop.rb @@ -15,7 +15,7 @@ module Tk::BLT class Token < TkWindow WidgetClassName = 'DragDropToken'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def initialize(arg) if arg.kind_of?(Hash) # arg is a hash includes the widgetpath of token @@ -55,6 +55,7 @@ module Tk::BLT private :__item_strval_optkeys undef itemcget + undef itemcget_tkstring private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo def source_configure(win, slot, value=None) diff --git a/ext/tk/lib/tkextlib/blt/graph.rb b/ext/tk/lib/tkextlib/blt/graph.rb index 9ae99bff5c..6bd4424065 100644 --- a/ext/tk/lib/tkextlib/blt/graph.rb +++ b/ext/tk/lib/tkextlib/blt/graph.rb @@ -11,7 +11,7 @@ module Tk::BLT class Graph < TkWindow TkCommandNames = ['::blt::graph'.freeze].freeze WidgetClassName = 'Graph'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self include PlotComponent include GraphCommand @@ -27,7 +27,7 @@ module Tk::BLT private :__strval_optkeys =begin - BarElement_ID = ['blt_graph_bar'.freeze, '00000'.taint].freeze + BarElement_ID = ['blt_graph_bar'.freeze, TkUtil.untrust('00000')].freeze def bar(elem=nil, keys={}) if elem.kind_of?(Hash) diff --git a/ext/tk/lib/tkextlib/blt/htext.rb b/ext/tk/lib/tkextlib/blt/htext.rb index 0d9cb30185..878bd9982d 100644 --- a/ext/tk/lib/tkextlib/blt/htext.rb +++ b/ext/tk/lib/tkextlib/blt/htext.rb @@ -19,8 +19,9 @@ module Tk::BLT TkCommandNames = ['::blt::htext'.freeze].freeze WidgetClassName = 'Htext'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self + alias window_cget_tkstring itemcget_tkstring alias window_cget itemcget alias window_cget_strict itemcget_strict alias window_configure itemconfigure diff --git a/ext/tk/lib/tkextlib/blt/stripchart.rb b/ext/tk/lib/tkextlib/blt/stripchart.rb index a6b0f354e2..74093f1868 100644 --- a/ext/tk/lib/tkextlib/blt/stripchart.rb +++ b/ext/tk/lib/tkextlib/blt/stripchart.rb @@ -11,7 +11,7 @@ module Tk::BLT class Stripchart < TkWindow TkCommandNames = ['::blt::stripchart'.freeze].freeze WidgetClassName = 'Stripchart'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self include PlotComponent include GraphCommand @@ -28,7 +28,7 @@ module Tk::BLT private :__strval_optkeys =begin - BarElement_ID = ['blt_stripchart_bar'.freeze, '00000'.taint].freeze + BarElement_ID = ['blt_stripchart_bar'.freeze, TkUtil.untrust('00000')].freeze def bar(elem=nil, keys={}) if elem.kind_of?(Hash) diff --git a/ext/tk/lib/tkextlib/blt/table.rb b/ext/tk/lib/tkextlib/blt/table.rb index dfa10269ed..205e29e6c5 100644 --- a/ext/tk/lib/tkextlib/blt/table.rb +++ b/ext/tk/lib/tkextlib/blt/table.rb @@ -26,6 +26,9 @@ module Tk::BLT self end + def blt_table_cget_tkstring(*args) + Tk::BLT::Table.cget_tkstring(self, *args) + end def blt_table_cget(*args) Tk::BLT::Table.cget(self, *args) end @@ -92,6 +95,9 @@ module Tk::BLT self end + def blt_table_itemcget_tkstring(*args) + Tk::BLT::Table.itemcget_tkstring(self, *args) + end def blt_table_itemcget(*args) Tk::BLT::Table.itemcget(self, *args) end @@ -141,13 +147,14 @@ class << Tk::BLT::Table end private :__item_pathname + alias __itemcget_tkstring itemcget_tkstring alias __itemcget itemcget alias __itemcget_strict itemcget_strict alias __itemconfigure itemconfigure alias __itemconfiginfo itemconfiginfo alias __current_itemconfiginfo current_itemconfiginfo - private :__itemcget, :__itemcget_strict + private :__itemcget_tkstring, :__itemcget, :__itemcget_strict private :__itemconfigure, :__itemconfiginfo, :__current_itemconfiginfo def __boolval_optkeys @@ -180,6 +187,9 @@ class << Tk::BLT::Table ############################################ + def cget_tkstring(container, option) + __itemcget_tkstring([container], option) + end def cget(container, option) __itemcget([container], option) end @@ -199,6 +209,9 @@ class << Tk::BLT::Table __current_itemconfiginfo([container], *args) end + def itemcget_tkstring(container, item, option) + __itemcget_tkstring([container, tagid(item)], option) + end def itemcget(container, item, option) __itemcget([container, tagid(item)], option) end diff --git a/ext/tk/lib/tkextlib/blt/tabnotebook.rb b/ext/tk/lib/tkextlib/blt/tabnotebook.rb index 738ba7c601..82936c67d3 100644 --- a/ext/tk/lib/tkextlib/blt/tabnotebook.rb +++ b/ext/tk/lib/tkextlib/blt/tabnotebook.rb @@ -11,7 +11,7 @@ module Tk::BLT class Tabnotebook < Tabset TkCommandNames = ['::blt::tabnotebook'.freeze].freeze WidgetClassName = 'Tabnotebook'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self class Tab < Tk::BLT::Tabset::Tab def self.new(parent, pos=nil, name=nil, keys={}) diff --git a/ext/tk/lib/tkextlib/blt/tabset.rb b/ext/tk/lib/tkextlib/blt/tabset.rb index b5e076db3a..c4716c7304 100644 --- a/ext/tk/lib/tkextlib/blt/tabset.rb +++ b/ext/tk/lib/tkextlib/blt/tabset.rb @@ -13,7 +13,7 @@ module Tk::BLT TabID_TBL = TkCore::INTERP.create_table - (TabsetTab_ID = ['blt_tabset_tab'.freeze, '00000'.taint]).instance_eval{ + (TabsetTab_ID = ['blt_tabset_tab'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze @@ -132,6 +132,9 @@ module Tk::BLT @t.tab_bindinfo(@id, context) end + def cget_tkstring(*args) + @t.tab_cget_tkstring(@id, *args) + end def cget(*args) @t.tab_cget(@id, *args) end @@ -210,7 +213,7 @@ module Tk::BLT TkCommandNames = ['::blt::tabset'.freeze].freeze WidgetClassName = 'Tabset'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __destroy_hook__ Tk::BLT::Tabset::Tab::TabID_TBL.mutex.synchronize{ @@ -249,6 +252,7 @@ module Tk::BLT end private :__item_pathname + alias tab_cget_tkstring itemcget_tkstring alias tab_cget itemcget alias tab_cget_strict itemcget_strict alias tab_configure itemconfigure diff --git a/ext/tk/lib/tkextlib/blt/ted.rb b/ext/tk/lib/tkextlib/blt/ted.rb index 670265fc78..53ab9acdaa 100644 --- a/ext/tk/lib/tkextlib/blt/ted.rb +++ b/ext/tk/lib/tkextlib/blt/ted.rb @@ -30,9 +30,12 @@ module Tk::BLT end private :__item_config_cmd - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo + def cget_tkstring(master, option) + itemcget_tkstring(master, option) + end def cget(master, option) itemcget(master, option) end diff --git a/ext/tk/lib/tkextlib/blt/tile.rb b/ext/tk/lib/tkextlib/blt/tile.rb index 5f5242f299..c67cafd8d6 100644 --- a/ext/tk/lib/tkextlib/blt/tile.rb +++ b/ext/tk/lib/tkextlib/blt/tile.rb @@ -8,6 +8,10 @@ require 'tkextlib/blt.rb' module Tk::BLT module Tile + TkComm::TkExtlibAutoloadModule.unshift(self) + # Require autoload-symbols which is a same name as widget classname. + # Those are used at TkComm._genobj_for_tkwidget method. + autoload :Button, 'tkextlib/blt/tile/button.rb' autoload :CheckButton, 'tkextlib/blt/tile/checkbutton.rb' autoload :Checkbutton, 'tkextlib/blt/tile/checkbutton.rb' diff --git a/ext/tk/lib/tkextlib/blt/tree.rb b/ext/tk/lib/tkextlib/blt/tree.rb index 605a64daa6..da53a6ed04 100644 --- a/ext/tk/lib/tkextlib/blt/tree.rb +++ b/ext/tk/lib/tkextlib/blt/tree.rb @@ -272,7 +272,7 @@ module Tk::BLT TreeTagID_TBL.mutex.synchronize{ TreeTagID_TBL.clear } } - (TreeTag_ID = ['blt_tree_tag'.freeze, '00000'.taint]).instance_eval{ + (TreeTag_ID = ['blt_tree_tag'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze @@ -578,7 +578,7 @@ module Tk::BLT TreeID_TBL = TkCore::INTERP.create_table - (Tree_ID = ['blt_tree'.freeze, '00000'.taint]).instance_eval{ + (Tree_ID = ['blt_tree'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze diff --git a/ext/tk/lib/tkextlib/blt/treeview.rb b/ext/tk/lib/tkextlib/blt/treeview.rb index 550422ee2e..046cf7f837 100644 --- a/ext/tk/lib/tkextlib/blt/treeview.rb +++ b/ext/tk/lib/tkextlib/blt/treeview.rb @@ -95,6 +95,9 @@ module Tk::BLT::Treeview::ConfigMethod end private :__item_pathname + def column_cget_tkstring(name, option) + itemcget_tkstring(['column', name], option) + end def column_cget(name, option) itemcget(['column', name], option) end @@ -111,6 +114,9 @@ module Tk::BLT::Treeview::ConfigMethod current_itemconfiginfo(['column', name], slot) end + def button_cget_tkstring(option) + itemcget_tkstring('button', option) + end def button_cget(option) itemcget('button', option) end @@ -127,6 +133,9 @@ module Tk::BLT::Treeview::ConfigMethod current_itemconfiginfo('button', slot) end + def entry_cget_tkstring(option) + itemcget_tkstring('entry', option) + end def entry_cget(option) ret = itemcget('entry', option) if option == 'bindtags' || option == :bindtags @@ -181,6 +190,9 @@ module Tk::BLT::Treeview::ConfigMethod ret end + def sort_cget_tkstring(option) + itemcget_tkstring('sort', option) + end def sort_cget(option) itemcget('sort', option) end @@ -197,6 +209,9 @@ module Tk::BLT::Treeview::ConfigMethod current_itemconfiginfo('sort', slot) end + def text_cget_tkstring(option) + itemcget_tkstring('text', option) + end def text_cget(option) itemcget('text', option) end @@ -213,14 +228,14 @@ module Tk::BLT::Treeview::ConfigMethod current_itemconfiginfo('text', slot) end - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo end class Tk::BLT::Treeview TkCommandNames = ['::blt::treeview'.freeze].freeze WidgetClassName = 'TreeView'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self include Scrollable include ValidateConfigure @@ -1029,7 +1044,7 @@ class Tk::BLT::Treeview::Node < TkObject TreeNodeID_TBL = TkCore::INTERP.create_table - (TreeNode_ID = ['blt_treeview_node'.freeze, '00000'.taint]).instance_eval{ + (TreeNode_ID = ['blt_treeview_node'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze @@ -1150,7 +1165,7 @@ class Tk::BLT::Treeview::Tag < TkObject TreeTagID_TBL = TkCore::INTERP.create_table - (TreeTag_ID = ['blt_treeview_tag'.freeze, '00000'.taint]).instance_eval{ + (TreeTag_ID = ['blt_treeview_tag'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze @@ -1268,5 +1283,5 @@ end class Tk::BLT::Hiertable TkCommandNames = ['::blt::hiertable'.freeze].freeze WidgetClassName = 'Hiertable'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self end diff --git a/ext/tk/lib/tkextlib/blt/unix_dnd.rb b/ext/tk/lib/tkextlib/blt/unix_dnd.rb index 445002d7a5..8996f7c891 100644 --- a/ext/tk/lib/tkextlib/blt/unix_dnd.rb +++ b/ext/tk/lib/tkextlib/blt/unix_dnd.rb @@ -30,9 +30,12 @@ module Tk::BLT end private :__item_config_cmd - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo + def cget_tkstring(win, option) + itemcget_tkstring(['cget', win], option) + end def cget(win, option) itemcget(['cget', win], option) end @@ -49,6 +52,9 @@ module Tk::BLT current_itemconfiginfo(['configure', win], slot) end + def token_cget_tkstring(win, option) + itemcget_tkstring(['token', 'cget', win], option) + end def token_cget(win, option) itemcget(['token', 'cget', win], option) end diff --git a/ext/tk/lib/tkextlib/blt/watch.rb b/ext/tk/lib/tkextlib/blt/watch.rb index 219ff78e97..292623ff58 100644 --- a/ext/tk/lib/tkextlib/blt/watch.rb +++ b/ext/tk/lib/tkextlib/blt/watch.rb @@ -14,7 +14,7 @@ module Tk::BLT WATCH_ID_TBL = TkCore::INTERP.create_table - (BLT_WATCH_ID = ['blt_watch_id'.freeze, '00000'.taint]).instance_eval{ + (BLT_WATCH_ID = ['blt_watch_id'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze diff --git a/ext/tk/lib/tkextlib/bwidget.rb b/ext/tk/lib/tkextlib/bwidget.rb index 62631d8b54..7a1eff51d8 100644 --- a/ext/tk/lib/tkextlib/bwidget.rb +++ b/ext/tk/lib/tkextlib/bwidget.rb @@ -18,6 +18,8 @@ TkPackage.require('BWidget') module Tk module BWidget TkComm::TkExtlibAutoloadModule.unshift(self) + # Require autoload-symbols which is a same name as widget classname. + # Those are used at TkComm._genobj_for_tkwidget method. extend TkCore diff --git a/ext/tk/lib/tkextlib/bwidget/arrowbutton.rb b/ext/tk/lib/tkextlib/bwidget/arrowbutton.rb index 770e5e9ef1..13fe9e59bf 100644 --- a/ext/tk/lib/tkextlib/bwidget/arrowbutton.rb +++ b/ext/tk/lib/tkextlib/bwidget/arrowbutton.rb @@ -17,5 +17,5 @@ end class Tk::BWidget::ArrowButton TkCommandNames = ['ArrowButton'.freeze].freeze WidgetClassName = 'ArrowButton'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self end diff --git a/ext/tk/lib/tkextlib/bwidget/button.rb b/ext/tk/lib/tkextlib/bwidget/button.rb index 8f3087d098..e139fb6708 100644 --- a/ext/tk/lib/tkextlib/bwidget/button.rb +++ b/ext/tk/lib/tkextlib/bwidget/button.rb @@ -17,7 +17,7 @@ end class Tk::BWidget::Button TkCommandNames = ['Button'.freeze].freeze WidgetClassName = 'Button'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() << 'helptext' diff --git a/ext/tk/lib/tkextlib/bwidget/buttonbox.rb b/ext/tk/lib/tkextlib/bwidget/buttonbox.rb index 8d6d212189..a6de33c40c 100644 --- a/ext/tk/lib/tkextlib/bwidget/buttonbox.rb +++ b/ext/tk/lib/tkextlib/bwidget/buttonbox.rb @@ -17,7 +17,7 @@ end class Tk::BWidget::ButtonBox TkCommandNames = ['ButtonBox'.freeze].freeze WidgetClassName = 'ButtonBox'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self include TkItemConfigMethod diff --git a/ext/tk/lib/tkextlib/bwidget/combobox.rb b/ext/tk/lib/tkextlib/bwidget/combobox.rb index 1c58a4ccb0..16143dfbc6 100644 --- a/ext/tk/lib/tkextlib/bwidget/combobox.rb +++ b/ext/tk/lib/tkextlib/bwidget/combobox.rb @@ -21,7 +21,12 @@ class Tk::BWidget::ComboBox TkCommandNames = ['ComboBox'.freeze].freeze WidgetClassName = 'ComboBox'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self + + def __boolval_optkeys + super() << 'autocomplete' << 'autopost' + end + private :__boolval_optkeys def get_listbox(&b) win = window(tk_send_without_enc('getlistbox')) @@ -35,6 +40,12 @@ class Tk::BWidget::ComboBox win end + def clear_value + tk_send_without_enc('clearvalue') + self + end + alias clearvalue clear_value + def icursor(idx) tk_send_without_enc('icursor', idx) end diff --git a/ext/tk/lib/tkextlib/bwidget/dialog.rb b/ext/tk/lib/tkextlib/bwidget/dialog.rb index 13527f96ad..3b0656f021 100644 --- a/ext/tk/lib/tkextlib/bwidget/dialog.rb +++ b/ext/tk/lib/tkextlib/bwidget/dialog.rb @@ -18,12 +18,17 @@ end class Tk::BWidget::Dialog TkCommandNames = ['Dialog'.freeze].freeze WidgetClassName = 'Dialog'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self include TkItemConfigMethod + def __numstrval_optkeys + super() << 'buttonwidth' + end + private :__numstrval_optkeys + def __strval_optkeys - super() << 'title' + super() << 'title' << 'geometry' end private :__strval_optkeys @@ -59,6 +64,13 @@ class Tk::BWidget::Dialog end end + def cget_tkstring(slot) + if slot.to_s == 'relative' + super('parent') + else + super(slot) + end + end def cget_strict(slot) if slot.to_s == 'relative' super('parent') diff --git a/ext/tk/lib/tkextlib/bwidget/entry.rb b/ext/tk/lib/tkextlib/bwidget/entry.rb index a56890f4e3..8dc4496123 100644 --- a/ext/tk/lib/tkextlib/bwidget/entry.rb +++ b/ext/tk/lib/tkextlib/bwidget/entry.rb @@ -19,7 +19,7 @@ class Tk::BWidget::Entry TkCommandNames = ['Entry'.freeze].freeze WidgetClassName = 'Entry'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() << 'helptext' << 'insertbackground' diff --git a/ext/tk/lib/tkextlib/bwidget/label.rb b/ext/tk/lib/tkextlib/bwidget/label.rb index 88a504aa50..e8d9352c62 100644 --- a/ext/tk/lib/tkextlib/bwidget/label.rb +++ b/ext/tk/lib/tkextlib/bwidget/label.rb @@ -17,7 +17,7 @@ end class Tk::BWidget::Label TkCommandNames = ['Label'.freeze].freeze WidgetClassName = 'Label'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() << 'helptext' diff --git a/ext/tk/lib/tkextlib/bwidget/labelentry.rb b/ext/tk/lib/tkextlib/bwidget/labelentry.rb index 95b40946a6..16e7b46933 100644 --- a/ext/tk/lib/tkextlib/bwidget/labelentry.rb +++ b/ext/tk/lib/tkextlib/bwidget/labelentry.rb @@ -21,7 +21,7 @@ class Tk::BWidget::LabelEntry TkCommandNames = ['LabelEntry'.freeze].freeze WidgetClassName = 'LabelEntry'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() << 'helptext' << 'insertbackground' << 'entryfg' << 'entrybg' diff --git a/ext/tk/lib/tkextlib/bwidget/labelframe.rb b/ext/tk/lib/tkextlib/bwidget/labelframe.rb index dc221806e4..0710f213f0 100644 --- a/ext/tk/lib/tkextlib/bwidget/labelframe.rb +++ b/ext/tk/lib/tkextlib/bwidget/labelframe.rb @@ -18,7 +18,7 @@ end class Tk::BWidget::LabelFrame TkCommandNames = ['LabelFrame'.freeze].freeze WidgetClassName = 'LabelFrame'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() << 'helptext' diff --git a/ext/tk/lib/tkextlib/bwidget/listbox.rb b/ext/tk/lib/tkextlib/bwidget/listbox.rb index 33b69b408a..930491c869 100644 --- a/ext/tk/lib/tkextlib/bwidget/listbox.rb +++ b/ext/tk/lib/tkextlib/bwidget/listbox.rb @@ -25,7 +25,7 @@ class Tk::BWidget::ListBox TkCommandNames = ['ListBox'.freeze].freeze WidgetClassName = 'ListBox'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self class Event_for_Items < TkEvent::Event def self._get_extra_args_tbl @@ -212,7 +212,7 @@ class Tk::BWidget::ListBox::Item ListItem_TBL = TkCore::INTERP.create_table - (ListItem_ID = ['bw:item'.freeze, '00000'.taint]).instance_eval{ + (ListItem_ID = ['bw:item'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze @@ -294,6 +294,9 @@ class Tk::BWidget::ListBox::Item val end + def cget_tkstring(key) + @listbox.itemcget_tkstring(@id, key) + end def cget(key) @listbox.itemcget(@id, key) end diff --git a/ext/tk/lib/tkextlib/bwidget/mainframe.rb b/ext/tk/lib/tkextlib/bwidget/mainframe.rb index de66eaf81e..92253bd8d3 100644 --- a/ext/tk/lib/tkextlib/bwidget/mainframe.rb +++ b/ext/tk/lib/tkextlib/bwidget/mainframe.rb @@ -18,7 +18,7 @@ end class Tk::BWidget::MainFrame TkCommandNames = ['MainFrame'.freeze].freeze WidgetClassName = 'MainFrame'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() << 'progressfg' @@ -111,6 +111,10 @@ class Tk::BWidget::MainFrame win end + def get_menustate(tag) + tk_send('getmenustate', tag) # return state name string + end + def set_menustate(tag, state) tk_send('setmenustate', tag, state) self diff --git a/ext/tk/lib/tkextlib/bwidget/messagedlg.rb b/ext/tk/lib/tkextlib/bwidget/messagedlg.rb index 9b46532934..7b62614737 100644 --- a/ext/tk/lib/tkextlib/bwidget/messagedlg.rb +++ b/ext/tk/lib/tkextlib/bwidget/messagedlg.rb @@ -17,7 +17,7 @@ end class Tk::BWidget::MessageDlg TkCommandNames = ['MessageDlg'.freeze].freeze WidgetClassName = 'MessageDlg'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def initialize(parent=nil, keys=nil) @relative = '' diff --git a/ext/tk/lib/tkextlib/bwidget/notebook.rb b/ext/tk/lib/tkextlib/bwidget/notebook.rb index 6101fa93e5..ed28bcd86a 100644 --- a/ext/tk/lib/tkextlib/bwidget/notebook.rb +++ b/ext/tk/lib/tkextlib/bwidget/notebook.rb @@ -19,7 +19,7 @@ class Tk::BWidget::NoteBook TkCommandNames = ['NoteBook'.freeze].freeze WidgetClassName = 'NoteBook'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self class Event_for_Tabs < TkEvent::Event def self._get_extra_args_tbl diff --git a/ext/tk/lib/tkextlib/bwidget/pagesmanager.rb b/ext/tk/lib/tkextlib/bwidget/pagesmanager.rb index fbc2c11255..31bbf1fb8b 100644 --- a/ext/tk/lib/tkextlib/bwidget/pagesmanager.rb +++ b/ext/tk/lib/tkextlib/bwidget/pagesmanager.rb @@ -17,7 +17,7 @@ end class Tk::BWidget::PagesManager TkCommandNames = ['PagesManager'.freeze].freeze WidgetClassName = 'PagesManager'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def tagid(id) # id.to_s diff --git a/ext/tk/lib/tkextlib/bwidget/panedwindow.rb b/ext/tk/lib/tkextlib/bwidget/panedwindow.rb index 4d979fd523..54cf06cbde 100644 --- a/ext/tk/lib/tkextlib/bwidget/panedwindow.rb +++ b/ext/tk/lib/tkextlib/bwidget/panedwindow.rb @@ -17,7 +17,12 @@ end class Tk::BWidget::PanedWindow TkCommandNames = ['PanedWindow'.freeze].freeze WidgetClassName = 'PanedWindow'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() << 'activator' + end + private :__strval_optkeys def add(keys={}) window(tk_send('add', *hash_kv(keys))) diff --git a/ext/tk/lib/tkextlib/bwidget/panelframe.rb b/ext/tk/lib/tkextlib/bwidget/panelframe.rb index 84bae0768b..1cbf914425 100644 --- a/ext/tk/lib/tkextlib/bwidget/panelframe.rb +++ b/ext/tk/lib/tkextlib/bwidget/panelframe.rb @@ -17,7 +17,7 @@ end class Tk::BWidget::PanelFrame TkCommandNames = ['PanelFrame'.freeze].freeze WidgetClassName = 'PanelFrame'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() + ['panelforeground', 'panelbackground'] @@ -47,11 +47,21 @@ class Tk::BWidget::PanelFrame end def items - list(tk_send('items')) + simplelist(tk_send('items')).map{|w| window(w)} end def remove(*wins) tk_send('remove', *wins) self end + + def remove_with_destroy(*wins) + tk_send('remove', '-destroy', *wins) + self + end + + def delete(*wins) # same to 'remove_with_destroy' + tk_send('delete', *wins) + self + end end diff --git a/ext/tk/lib/tkextlib/bwidget/passwddlg.rb b/ext/tk/lib/tkextlib/bwidget/passwddlg.rb index 2c7153333c..ea50c87cef 100644 --- a/ext/tk/lib/tkextlib/bwidget/passwddlg.rb +++ b/ext/tk/lib/tkextlib/bwidget/passwddlg.rb @@ -17,7 +17,7 @@ end class Tk::BWidget::PasswdDlg TkCommandNames = ['PasswdDlg'.freeze].freeze WidgetClassName = 'PasswdDlg'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() << 'loginhelptext' << 'loginlabel' << 'logintext' << diff --git a/ext/tk/lib/tkextlib/bwidget/progressbar.rb b/ext/tk/lib/tkextlib/bwidget/progressbar.rb index 0253ce2ada..18eb67349b 100644 --- a/ext/tk/lib/tkextlib/bwidget/progressbar.rb +++ b/ext/tk/lib/tkextlib/bwidget/progressbar.rb @@ -16,5 +16,5 @@ end class Tk::BWidget::ProgressBar TkCommandNames = ['ProgressBar'.freeze].freeze WidgetClassName = 'ProgressBar'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self end diff --git a/ext/tk/lib/tkextlib/bwidget/progressdlg.rb b/ext/tk/lib/tkextlib/bwidget/progressdlg.rb index 32600255d5..0c0c4540bc 100644 --- a/ext/tk/lib/tkextlib/bwidget/progressdlg.rb +++ b/ext/tk/lib/tkextlib/bwidget/progressdlg.rb @@ -19,7 +19,7 @@ end class Tk::BWidget::ProgressDlg TkCommandNames = ['ProgressDlg'.freeze].freeze WidgetClassName = 'ProgressDlg'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def create_self(keys) # NOT create widget for reusing the object diff --git a/ext/tk/lib/tkextlib/bwidget/scrollableframe.rb b/ext/tk/lib/tkextlib/bwidget/scrollableframe.rb index 010c960ec5..5bd00d6870 100644 --- a/ext/tk/lib/tkextlib/bwidget/scrollableframe.rb +++ b/ext/tk/lib/tkextlib/bwidget/scrollableframe.rb @@ -19,7 +19,7 @@ class Tk::BWidget::ScrollableFrame TkCommandNames = ['ScrollableFrame'.freeze].freeze WidgetClassName = 'ScrollableFrame'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def get_frame(&b) win = window(tk_send_without_enc('getframe')) diff --git a/ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb b/ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb index 3599fd8459..ea5a18cc66 100644 --- a/ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb +++ b/ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb @@ -17,7 +17,17 @@ end class Tk::BWidget::ScrolledWindow TkCommandNames = ['ScrolledWindow'.freeze].freeze WidgetClassName = 'ScrolledWindow'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() << 'sides' + end + private :__strval_optkeys + + def __boolval_optkeys + super() << 'managed' + end + private :__boolval_optkeys def get_frame(&b) win = window(tk_send_without_enc('getframe')) diff --git a/ext/tk/lib/tkextlib/bwidget/scrollview.rb b/ext/tk/lib/tkextlib/bwidget/scrollview.rb index 0546af2c43..ab27bc91cf 100644 --- a/ext/tk/lib/tkextlib/bwidget/scrollview.rb +++ b/ext/tk/lib/tkextlib/bwidget/scrollview.rb @@ -16,7 +16,7 @@ end class Tk::BWidget::ScrollView TkCommandNames = ['ScrollView'.freeze].freeze WidgetClassName = 'ScrollView'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() << 'fill' diff --git a/ext/tk/lib/tkextlib/bwidget/selectcolor.rb b/ext/tk/lib/tkextlib/bwidget/selectcolor.rb index 82bd05eb13..456175e87e 100644 --- a/ext/tk/lib/tkextlib/bwidget/selectcolor.rb +++ b/ext/tk/lib/tkextlib/bwidget/selectcolor.rb @@ -24,7 +24,7 @@ class Tk::BWidget::SelectColor TkCommandNames = ['SelectColor'.freeze].freeze WidgetClassName = 'SelectColor'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def dialog(keys={}) newkeys = @keys.dup diff --git a/ext/tk/lib/tkextlib/bwidget/selectfont.rb b/ext/tk/lib/tkextlib/bwidget/selectfont.rb index 71b1afded3..23419cb0fa 100644 --- a/ext/tk/lib/tkextlib/bwidget/selectfont.rb +++ b/ext/tk/lib/tkextlib/bwidget/selectfont.rb @@ -23,13 +23,18 @@ class Tk::BWidget::SelectFont TkCommandNames = ['SelectFont'.freeze].freeze WidgetClassName = 'SelectFont'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() << 'sampletext' << 'title' end private :__strval_optkeys + def __boolval_optkeys + super() << 'nosizes' + end + private :__boolval_optkeys + def __font_optkeys [] # without fontobj operation end diff --git a/ext/tk/lib/tkextlib/bwidget/separator.rb b/ext/tk/lib/tkextlib/bwidget/separator.rb index d9c3458e51..6d92321210 100644 --- a/ext/tk/lib/tkextlib/bwidget/separator.rb +++ b/ext/tk/lib/tkextlib/bwidget/separator.rb @@ -16,5 +16,5 @@ end class Tk::BWidget::Separator TkCommandNames = ['Separator'.freeze].freeze WidgetClassName = 'Separator'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self end diff --git a/ext/tk/lib/tkextlib/bwidget/spinbox.rb b/ext/tk/lib/tkextlib/bwidget/spinbox.rb index 48358baa5c..0a45b045fb 100644 --- a/ext/tk/lib/tkextlib/bwidget/spinbox.rb +++ b/ext/tk/lib/tkextlib/bwidget/spinbox.rb @@ -20,7 +20,7 @@ class Tk::BWidget::SpinBox TkCommandNames = ['SpinBox'.freeze].freeze WidgetClassName = 'SpinBox'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() << 'helptext' << 'insertbackground' << 'entryfg' << 'entrybg' diff --git a/ext/tk/lib/tkextlib/bwidget/statusbar.rb b/ext/tk/lib/tkextlib/bwidget/statusbar.rb index 39c678d37e..5c5dd43fe4 100644 --- a/ext/tk/lib/tkextlib/bwidget/statusbar.rb +++ b/ext/tk/lib/tkextlib/bwidget/statusbar.rb @@ -17,10 +17,10 @@ end class Tk::BWidget::StatusBar TkCommandNames = ['StatusBar'.freeze].freeze WidgetClassName = 'StatusBar'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __boolval_optkeys - super() << 'showresize' + super() << 'showresize' << 'showseparator' << 'showresizesep' end private :__boolval_optkeys @@ -29,7 +29,17 @@ class Tk::BWidget::StatusBar self end - def delete(*wins) + def remove(*wins) + tk_send('remove', *wins) + self + end + + def remove_with_destroy(*wins) + tk_send('remove', '-destroy', *wins) + self + end + + def delete(*wins) # same to 'remove_with_destroy' tk_send('delete', *wins) self end @@ -47,6 +57,6 @@ class Tk::BWidget::StatusBar end def items - list(tk_send('items')) + simplelist(tk_send('items')).map{|w| window(w)} end end diff --git a/ext/tk/lib/tkextlib/bwidget/titleframe.rb b/ext/tk/lib/tkextlib/bwidget/titleframe.rb index 68534e66e9..71879111c1 100644 --- a/ext/tk/lib/tkextlib/bwidget/titleframe.rb +++ b/ext/tk/lib/tkextlib/bwidget/titleframe.rb @@ -17,7 +17,7 @@ end class Tk::BWidget::TitleFrame TkCommandNames = ['TitleFrame'.freeze].freeze WidgetClassName = 'TitleFrame'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def get_frame(&b) win = window(tk_send_without_enc('getframe')) diff --git a/ext/tk/lib/tkextlib/bwidget/tree.rb b/ext/tk/lib/tkextlib/bwidget/tree.rb index 86074ab6f4..089c482fe8 100644 --- a/ext/tk/lib/tkextlib/bwidget/tree.rb +++ b/ext/tk/lib/tkextlib/bwidget/tree.rb @@ -22,7 +22,7 @@ class Tk::BWidget::Tree TkCommandNames = ['Tree'.freeze].freeze WidgetClassName = 'Tree'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self class Event_for_Items < TkEvent::Event def self._get_extra_args_tbl @@ -57,6 +57,37 @@ class Tk::BWidget::Tree end end + def areabind(context, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_for_event_class(Event_for_Items, [path, 'bindArea'], + context, cmd, *args) + self + end + + def areabind_append(context, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append_for_event_class(Event_for_Items, [path, 'bindArea'], + context, cmd, *args) + self + end + + def areabind_remove(*args) + _bind_remove_for_event_class(Event_for_Items, [path, 'bindArea'], *args) + self + end + + def areabindinfo(*args) + _bindinfo_for_event_class(Event_for_Items, [path, 'bindArea'], *args) + end + #def imagebind(*args) # _bind_for_event_class(Event_for_Items, [path, 'bindImage'], *args) # self @@ -158,6 +189,16 @@ class Tk::BWidget::Tree bool(tk_send('exists', tagid(node))) end + def find(findinfo, confine=None) + Tk::BWidget::Tree::Node.id2obj(self, tk_send(findinfo, confine)) + end + def find_position(x, y, confine=None) + self.find(_at(x,y), confine) + end + def find_line(linenum) + self.find(linenum) + end + def index(node) num_or_str(tk_send('index', tagid(node))) end @@ -167,6 +208,10 @@ class Tk::BWidget::Tree self end + def line(node) + number(tk_send('line', tagid(node))) + end + def move(parent, node, idx) tk_send('move', tagid(parent), tagid(node), idx) self @@ -183,7 +228,7 @@ class Tk::BWidget::Tree end def open?(node) - bool(@tree.itemcget(tagid(node), 'open')) + bool(self.itemcget(tagid(node), 'open')) end def open_tree(node, recurse=None) @@ -264,7 +309,7 @@ class Tk::BWidget::Tree::Node TreeNode_TBL = TkCore::INTERP.create_table - (TreeNode_ID = ['bw:node'.freeze, '00000'.taint]).instance_eval{ + (TreeNode_ID = ['bw:node'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze @@ -355,6 +400,9 @@ class Tk::BWidget::Tree::Node val end + def cget_tkstring(key) + @tree.itemcget_tkstring(@id, key) + end def cget(key) @tree.itemcget(@id, key) end @@ -450,4 +498,3 @@ class Tk::BWidget::Tree::Node @tree.visible(@id) end end - diff --git a/ext/tk/lib/tkextlib/itcl/incr_tcl.rb b/ext/tk/lib/tkextlib/itcl/incr_tcl.rb index 2b75d62eb9..8f6bb33abe 100644 --- a/ext/tk/lib/tkextlib/itcl/incr_tcl.rb +++ b/ext/tk/lib/tkextlib/itcl/incr_tcl.rb @@ -40,12 +40,12 @@ module Tk class ItclObject < TkObject ITCL_CLASSNAME = ''.freeze - (ITCL_OBJ_ID = ['itclobj'.freeze, '00000'.taint]).instance_eval{ + (ITCL_OBJ_ID = ['itclobj'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze } - ITCL_OBJ_TBL = {}.taint + ITCL_OBJ_TBL = TkUtil.untrust({}) def initialize(*args) if (@klass = self.class::ITCL_CLASSNAME).empty? diff --git a/ext/tk/lib/tkextlib/itk/incr_tk.rb b/ext/tk/lib/tkextlib/itk/incr_tk.rb index 8772f21b49..989585e33b 100644 --- a/ext/tk/lib/tkextlib/itk/incr_tk.rb +++ b/ext/tk/lib/tkextlib/itk/incr_tk.rb @@ -111,7 +111,7 @@ module Tk class Toplevel < Archetype TkCommandNames = ['::itk::Toplevel'].freeze WidgetClassName = 'Toplevel'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self include Wm include TkMenuSpec @@ -127,7 +127,7 @@ module Tk class Widget < Archetype TkCommandNames = ['::itk::Widget'].freeze WidgetClassName = 'Widget'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self end @@ -146,7 +146,7 @@ module Tk ComponentID_TBL = TkCore::INTERP.create_table - (Itk_Component_ID = ['itk:component'.freeze, '00000'.taint]).instance_eval{ + (Itk_Component_ID = ['itk:component'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze diff --git a/ext/tk/lib/tkextlib/iwidgets/buttonbox.rb b/ext/tk/lib/tkextlib/iwidgets/buttonbox.rb index 05d58c386f..91e06d1b52 100644 --- a/ext/tk/lib/tkextlib/iwidgets/buttonbox.rb +++ b/ext/tk/lib/tkextlib/iwidgets/buttonbox.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Buttonbox TkCommandNames = ['::iwidgets::buttonbox'.freeze].freeze WidgetClassName = 'Buttonbox'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self #################################### @@ -46,13 +46,14 @@ class Tk::Iwidgets::Buttonbox end end + alias buttoncget_tkstring itemcget_tkstring alias buttoncget itemcget alias buttoncget_strict itemcget_strict alias buttonconfigure itemconfigure alias buttonconfiginfo itemconfiginfo alias current_buttonconfiginfo current_itemconfiginfo - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo #################################### diff --git a/ext/tk/lib/tkextlib/iwidgets/calendar.rb b/ext/tk/lib/tkextlib/iwidgets/calendar.rb index e85d6e4e51..a5478c7cc6 100644 --- a/ext/tk/lib/tkextlib/iwidgets/calendar.rb +++ b/ext/tk/lib/tkextlib/iwidgets/calendar.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Calendar TkCommandNames = ['::iwidgets::calendar'.freeze].freeze WidgetClassName = 'Calendar'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() + [ diff --git a/ext/tk/lib/tkextlib/iwidgets/canvasprintbox.rb b/ext/tk/lib/tkextlib/iwidgets/canvasprintbox.rb index fa5e90ad05..398eec3f1a 100644 --- a/ext/tk/lib/tkextlib/iwidgets/canvasprintbox.rb +++ b/ext/tk/lib/tkextlib/iwidgets/canvasprintbox.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Canvasprintbox TkCommandNames = ['::iwidgets::canvasprintbox'.freeze].freeze WidgetClassName = 'Canvasprintbox'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() << 'filename' diff --git a/ext/tk/lib/tkextlib/iwidgets/canvasprintdialog.rb b/ext/tk/lib/tkextlib/iwidgets/canvasprintdialog.rb index bbf507677c..e64d8154ca 100644 --- a/ext/tk/lib/tkextlib/iwidgets/canvasprintdialog.rb +++ b/ext/tk/lib/tkextlib/iwidgets/canvasprintdialog.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Canvasprintdialog TkCommandNames = ['::iwidgets::canvasprintdialog'.freeze].freeze WidgetClassName = 'Canvasprintdialog'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def get_output tk_call(@path, 'getoutput') diff --git a/ext/tk/lib/tkextlib/iwidgets/checkbox.rb b/ext/tk/lib/tkextlib/iwidgets/checkbox.rb index c85d356c55..a7476c824e 100644 --- a/ext/tk/lib/tkextlib/iwidgets/checkbox.rb +++ b/ext/tk/lib/tkextlib/iwidgets/checkbox.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Checkbox TkCommandNames = ['::iwidgets::checkbox'.freeze].freeze WidgetClassName = 'Checkbox'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self #################################### @@ -46,13 +46,14 @@ class Tk::Iwidgets::Checkbox end end + alias buttoncget_tkstring itemcget_tkstring alias buttoncget itemcget alias buttoncget_strict itemcget_strict alias buttonconfigure itemconfigure alias buttonconfiginfo itemconfiginfo alias current_buttonconfiginfo current_itemconfiginfo - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo #################################### diff --git a/ext/tk/lib/tkextlib/iwidgets/combobox.rb b/ext/tk/lib/tkextlib/iwidgets/combobox.rb index a6d54d78fa..82dcf25d0b 100644 --- a/ext/tk/lib/tkextlib/iwidgets/combobox.rb +++ b/ext/tk/lib/tkextlib/iwidgets/combobox.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Combobox TkCommandNames = ['::iwidgets::combobox'.freeze].freeze WidgetClassName = 'Combobox'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __boolval_optkeys super() << 'completion' << 'dropdown' << 'editable' << 'unique' diff --git a/ext/tk/lib/tkextlib/iwidgets/dateentry.rb b/ext/tk/lib/tkextlib/iwidgets/dateentry.rb index 0a8897f50d..98a0051e55 100644 --- a/ext/tk/lib/tkextlib/iwidgets/dateentry.rb +++ b/ext/tk/lib/tkextlib/iwidgets/dateentry.rb @@ -16,5 +16,5 @@ end class Tk::Iwidgets::Dateentry TkCommandNames = ['::iwidgets::dateentry'.freeze].freeze WidgetClassName = 'Dateentry'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self end diff --git a/ext/tk/lib/tkextlib/iwidgets/datefield.rb b/ext/tk/lib/tkextlib/iwidgets/datefield.rb index 632f3334dc..50d5405a3b 100644 --- a/ext/tk/lib/tkextlib/iwidgets/datefield.rb +++ b/ext/tk/lib/tkextlib/iwidgets/datefield.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Datefield TkCommandNames = ['::iwidgets::datefield'.freeze].freeze WidgetClassName = 'Datefield'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __boolval_optkeys super() << 'gmt' diff --git a/ext/tk/lib/tkextlib/iwidgets/dialog.rb b/ext/tk/lib/tkextlib/iwidgets/dialog.rb index 8540eae1b5..2d554ca7b5 100644 --- a/ext/tk/lib/tkextlib/iwidgets/dialog.rb +++ b/ext/tk/lib/tkextlib/iwidgets/dialog.rb @@ -16,5 +16,5 @@ end class Tk::Iwidgets::Dialog TkCommandNames = ['::iwidgets::dialog'.freeze].freeze WidgetClassName = 'Dialog'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self end diff --git a/ext/tk/lib/tkextlib/iwidgets/dialogshell.rb b/ext/tk/lib/tkextlib/iwidgets/dialogshell.rb index 8d43cc07ab..e880594532 100644 --- a/ext/tk/lib/tkextlib/iwidgets/dialogshell.rb +++ b/ext/tk/lib/tkextlib/iwidgets/dialogshell.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Dialogshell TkCommandNames = ['::iwidgets::dialogshell'.freeze].freeze WidgetClassName = 'Dialogshell'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self #################################### @@ -46,13 +46,14 @@ class Tk::Iwidgets::Dialogshell end end + alias buttoncget_tkstring itemcget_tkstring alias buttoncget itemcget alias buttoncget_strict itemcget_strict alias buttonconfigure itemconfigure alias buttonconfiginfo itemconfiginfo alias current_buttonconfiginfo current_itemconfiginfo - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo #################################### diff --git a/ext/tk/lib/tkextlib/iwidgets/disjointlistbox.rb b/ext/tk/lib/tkextlib/iwidgets/disjointlistbox.rb index 9bc063ba69..07ab025cdf 100644 --- a/ext/tk/lib/tkextlib/iwidgets/disjointlistbox.rb +++ b/ext/tk/lib/tkextlib/iwidgets/disjointlistbox.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Disjointlistbox TkCommandNames = ['::iwidgets::disjointlistbox'.freeze].freeze WidgetClassName = 'Disjointlistbox'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() << 'lhslabeltext' << 'rhslabeltext' << 'lhsbuttonlabel' << 'rhsbuttonlabel' diff --git a/ext/tk/lib/tkextlib/iwidgets/entryfield.rb b/ext/tk/lib/tkextlib/iwidgets/entryfield.rb index 6e1cd0053b..3e7149a662 100644 --- a/ext/tk/lib/tkextlib/iwidgets/entryfield.rb +++ b/ext/tk/lib/tkextlib/iwidgets/entryfield.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Entryfield TkCommandNames = ['::iwidgets::entryfield'.freeze].freeze WidgetClassName = 'Entryfield'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __font_optkeys super() << 'textfont' diff --git a/ext/tk/lib/tkextlib/iwidgets/extbutton.rb b/ext/tk/lib/tkextlib/iwidgets/extbutton.rb index 158d9d474a..e744fba91a 100644 --- a/ext/tk/lib/tkextlib/iwidgets/extbutton.rb +++ b/ext/tk/lib/tkextlib/iwidgets/extbutton.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Extbutton TkCommandNames = ['::iwidgets::extbutton'.freeze].freeze WidgetClassName = 'Extbutton'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() << 'bitmapforeground' << 'ringbackground' diff --git a/ext/tk/lib/tkextlib/iwidgets/extfileselectionbox.rb b/ext/tk/lib/tkextlib/iwidgets/extfileselectionbox.rb index 526dae1123..2ff15bb509 100644 --- a/ext/tk/lib/tkextlib/iwidgets/extfileselectionbox.rb +++ b/ext/tk/lib/tkextlib/iwidgets/extfileselectionbox.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Extfileselectionbox TkCommandNames = ['::iwidgets::extfileselectionbox'.freeze].freeze WidgetClassName = 'Extfileselectionbox'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() + [ diff --git a/ext/tk/lib/tkextlib/iwidgets/extfileselectiondialog.rb b/ext/tk/lib/tkextlib/iwidgets/extfileselectiondialog.rb index 14388be7c4..509fdcf636 100644 --- a/ext/tk/lib/tkextlib/iwidgets/extfileselectiondialog.rb +++ b/ext/tk/lib/tkextlib/iwidgets/extfileselectiondialog.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Extfileselectiondialog TkCommandNames = ['::iwidgets::extfileselectiondialog'.freeze].freeze WidgetClassName = 'Extfileselectiondialog'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def child_site window(tk_call(@path, 'childsite')) diff --git a/ext/tk/lib/tkextlib/iwidgets/feedback.rb b/ext/tk/lib/tkextlib/iwidgets/feedback.rb index 0a25237a24..29d04c8a5d 100644 --- a/ext/tk/lib/tkextlib/iwidgets/feedback.rb +++ b/ext/tk/lib/tkextlib/iwidgets/feedback.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Feedback TkCommandNames = ['::iwidgets::feedback'.freeze].freeze WidgetClassName = 'Feedback'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() << 'barcolor' diff --git a/ext/tk/lib/tkextlib/iwidgets/fileselectionbox.rb b/ext/tk/lib/tkextlib/iwidgets/fileselectionbox.rb index eb4dde484f..a425b53b5f 100644 --- a/ext/tk/lib/tkextlib/iwidgets/fileselectionbox.rb +++ b/ext/tk/lib/tkextlib/iwidgets/fileselectionbox.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Fileselectionbox TkCommandNames = ['::iwidgets::fileselectionbox'.freeze].freeze WidgetClassName = 'Fileselectionbox'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() + [ diff --git a/ext/tk/lib/tkextlib/iwidgets/fileselectiondialog.rb b/ext/tk/lib/tkextlib/iwidgets/fileselectiondialog.rb index 50f459e56d..ebcdaf8c0b 100644 --- a/ext/tk/lib/tkextlib/iwidgets/fileselectiondialog.rb +++ b/ext/tk/lib/tkextlib/iwidgets/fileselectiondialog.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Fileselectiondialog TkCommandNames = ['::iwidgets::fileselectiondialog'.freeze].freeze WidgetClassName = 'Fileselectiondialog'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def child_site window(tk_call(@path, 'childsite')) diff --git a/ext/tk/lib/tkextlib/iwidgets/finddialog.rb b/ext/tk/lib/tkextlib/iwidgets/finddialog.rb index c46b972214..3d522e07c8 100644 --- a/ext/tk/lib/tkextlib/iwidgets/finddialog.rb +++ b/ext/tk/lib/tkextlib/iwidgets/finddialog.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Finddialog TkCommandNames = ['::iwidgets::finddialog'.freeze].freeze WidgetClassName = 'Finddialog'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() + [ diff --git a/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb b/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb index fa16d9aad8..cb9301d0c9 100644 --- a/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb +++ b/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb @@ -20,7 +20,7 @@ class Tk::Iwidgets::Hierarchy TkCommandNames = ['::iwidgets::hierarchy'.freeze].freeze WidgetClassName = 'Hierarchy'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self #################################### diff --git a/ext/tk/lib/tkextlib/iwidgets/hyperhelp.rb b/ext/tk/lib/tkextlib/iwidgets/hyperhelp.rb index 77b0e090cd..d4ea1aac65 100644 --- a/ext/tk/lib/tkextlib/iwidgets/hyperhelp.rb +++ b/ext/tk/lib/tkextlib/iwidgets/hyperhelp.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Hyperhelp TkCommandNames = ['::iwidgets::hyperhelp'.freeze].freeze WidgetClassName = 'Hyperhelp'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() << 'helpdir' diff --git a/ext/tk/lib/tkextlib/iwidgets/labeledframe.rb b/ext/tk/lib/tkextlib/iwidgets/labeledframe.rb index e77e85045d..6595398427 100644 --- a/ext/tk/lib/tkextlib/iwidgets/labeledframe.rb +++ b/ext/tk/lib/tkextlib/iwidgets/labeledframe.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Labeledframe TkCommandNames = ['::iwidgets::labeledframe'.freeze].freeze WidgetClassName = 'Labeledframe'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() << 'labeltext' diff --git a/ext/tk/lib/tkextlib/iwidgets/labeledwidget.rb b/ext/tk/lib/tkextlib/iwidgets/labeledwidget.rb index 99387710cb..d36d42878d 100644 --- a/ext/tk/lib/tkextlib/iwidgets/labeledwidget.rb +++ b/ext/tk/lib/tkextlib/iwidgets/labeledwidget.rb @@ -18,7 +18,7 @@ class Tk::Iwidgets::Labeledwidget TkCommandNames = ['::iwidgets::labeledwidget'.freeze].freeze WidgetClassName = 'Labeledwidget'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() << 'labeltext' diff --git a/ext/tk/lib/tkextlib/iwidgets/mainwindow.rb b/ext/tk/lib/tkextlib/iwidgets/mainwindow.rb index 4b2541b997..ebf48021db 100644 --- a/ext/tk/lib/tkextlib/iwidgets/mainwindow.rb +++ b/ext/tk/lib/tkextlib/iwidgets/mainwindow.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Mainwindow TkCommandNames = ['::iwidgets::mainwindow'.freeze].freeze WidgetClassName = 'Mainwindow'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __boolval_optkeys super() << 'helpline' << 'statusline' diff --git a/ext/tk/lib/tkextlib/iwidgets/menubar.rb b/ext/tk/lib/tkextlib/iwidgets/menubar.rb index 5aaefbe50d..f9a17d0b55 100644 --- a/ext/tk/lib/tkextlib/iwidgets/menubar.rb +++ b/ext/tk/lib/tkextlib/iwidgets/menubar.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Menubar TkCommandNames = ['::iwidgets::menubar'.freeze].freeze WidgetClassName = 'Menubar'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() << 'menubuttons' @@ -61,13 +61,14 @@ class Tk::Iwidgets::Menubar end end + alias menucget_tkstring itemcget_tkstring alias menucget itemcget alias menucget_strict itemcget_strict alias menuconfigure itemconfigure alias menuconfiginfo itemconfiginfo alias current_menuconfiginfo current_itemconfiginfo - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo #################################### diff --git a/ext/tk/lib/tkextlib/iwidgets/messagebox.rb b/ext/tk/lib/tkextlib/iwidgets/messagebox.rb index 98ac32900c..6adb53d941 100644 --- a/ext/tk/lib/tkextlib/iwidgets/messagebox.rb +++ b/ext/tk/lib/tkextlib/iwidgets/messagebox.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Messagebox TkCommandNames = ['::iwidgets::messagebox'.freeze].freeze WidgetClassName = 'Messagebox'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self #################################### @@ -46,13 +46,14 @@ class Tk::Iwidgets::Messagebox end private :__item_boolval_optkeys + alias typecget_tkstring itemcget_tkstring alias typecget itemcget alias typecget_strict itemcget_strict alias typeconfigure itemconfigure alias typeconfiginfo itemconfiginfo alias current_typeconfiginfo current_itemconfiginfo - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo #################################### diff --git a/ext/tk/lib/tkextlib/iwidgets/messagedialog.rb b/ext/tk/lib/tkextlib/iwidgets/messagedialog.rb index c19b83e517..9aa590056f 100644 --- a/ext/tk/lib/tkextlib/iwidgets/messagedialog.rb +++ b/ext/tk/lib/tkextlib/iwidgets/messagedialog.rb @@ -16,5 +16,5 @@ end class Tk::Iwidgets::Messagedialog TkCommandNames = ['::iwidgets::messagedialog'.freeze].freeze WidgetClassName = 'Messagedialog'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self end diff --git a/ext/tk/lib/tkextlib/iwidgets/notebook.rb b/ext/tk/lib/tkextlib/iwidgets/notebook.rb index 03b50633df..7ed4126a4d 100644 --- a/ext/tk/lib/tkextlib/iwidgets/notebook.rb +++ b/ext/tk/lib/tkextlib/iwidgets/notebook.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Notebook TkCommandNames = ['::iwidgets::notebook'.freeze].freeze WidgetClassName = 'Notebook'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self #################################### @@ -41,13 +41,14 @@ class Tk::Iwidgets::Notebook end end + alias pagecget_tkstring itemcget_tkstring alias pagecget itemcget alias pagecget_strict itemcget_strict alias pageconfigure itemconfigure alias pageconfiginfo itemconfiginfo alias current_pageconfiginfo current_itemconfiginfo - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo #################################### diff --git a/ext/tk/lib/tkextlib/iwidgets/optionmenu.rb b/ext/tk/lib/tkextlib/iwidgets/optionmenu.rb index 0c74440be7..57a3cc7d2b 100644 --- a/ext/tk/lib/tkextlib/iwidgets/optionmenu.rb +++ b/ext/tk/lib/tkextlib/iwidgets/optionmenu.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Optionmenu TkCommandNames = ['::iwidgets::optionmenu'.freeze].freeze WidgetClassName = 'Optionmenu'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __boolval_optkeys super() << 'cyclicon' diff --git a/ext/tk/lib/tkextlib/iwidgets/panedwindow.rb b/ext/tk/lib/tkextlib/iwidgets/panedwindow.rb index 3bf73d69fe..65463cc85a 100644 --- a/ext/tk/lib/tkextlib/iwidgets/panedwindow.rb +++ b/ext/tk/lib/tkextlib/iwidgets/panedwindow.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Panedwindow TkCommandNames = ['::iwidgets::panedwindow'.freeze].freeze WidgetClassName = 'Panedwindow'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self #################################### @@ -41,13 +41,14 @@ class Tk::Iwidgets::Panedwindow end end + alias panecget_tkstring itemcget_tkstring alias panecget itemcget alias panecget_strict itemcget_strict alias paneconfigure itemconfigure alias paneconfiginfo itemconfiginfo alias current_paneconfiginfo current_itemconfiginfo - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo #################################### diff --git a/ext/tk/lib/tkextlib/iwidgets/promptdialog.rb b/ext/tk/lib/tkextlib/iwidgets/promptdialog.rb index 620b14b5d5..7c7ff7ad62 100644 --- a/ext/tk/lib/tkextlib/iwidgets/promptdialog.rb +++ b/ext/tk/lib/tkextlib/iwidgets/promptdialog.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Promptdialog TkCommandNames = ['::iwidgets::promptdialog'.freeze].freeze WidgetClassName = 'Promptdialog'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self # index method is not available, because it shows index of the entry field def default(name) diff --git a/ext/tk/lib/tkextlib/iwidgets/pushbutton.rb b/ext/tk/lib/tkextlib/iwidgets/pushbutton.rb index c21007ca6c..ae56788289 100644 --- a/ext/tk/lib/tkextlib/iwidgets/pushbutton.rb +++ b/ext/tk/lib/tkextlib/iwidgets/pushbutton.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Pushbutton TkCommandNames = ['::iwidgets::pushbutton'.freeze].freeze WidgetClassName = 'Pushbutton'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __boolval_optkeys super() << 'defaultring' diff --git a/ext/tk/lib/tkextlib/iwidgets/radiobox.rb b/ext/tk/lib/tkextlib/iwidgets/radiobox.rb index e9d9521252..21181777b5 100644 --- a/ext/tk/lib/tkextlib/iwidgets/radiobox.rb +++ b/ext/tk/lib/tkextlib/iwidgets/radiobox.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Radiobox TkCommandNames = ['::iwidgets::radiobox'.freeze].freeze WidgetClassName = 'Radiobox'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self #################################### @@ -46,13 +46,14 @@ class Tk::Iwidgets::Radiobox end end + alias buttoncget_tkstring itemcget_tkstring alias buttoncget itemcget alias buttoncget_strict itemcget_strict alias buttonconfigure itemconfigure alias buttonconfiginfo itemconfiginfo alias current_buttonconfiginfo current_itemconfiginfo - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo #################################### diff --git a/ext/tk/lib/tkextlib/iwidgets/scopedobject.rb b/ext/tk/lib/tkextlib/iwidgets/scopedobject.rb index bddef50841..056cd85322 100644 --- a/ext/tk/lib/tkextlib/iwidgets/scopedobject.rb +++ b/ext/tk/lib/tkextlib/iwidgets/scopedobject.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Scopedobject TkCommandNames = ['::iwidgets::scopedobject'.freeze].freeze WidgetClassName = 'Scopedobject'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def initialize(obj_name, keys={}) @path = tk_call(self.class::TkCommandNames[0], obj_name, *hash_kv(keys)) diff --git a/ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb b/ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb index 42368f5a56..935e04bbcc 100644 --- a/ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb +++ b/ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb @@ -17,7 +17,7 @@ end class Tk::Iwidgets::Scrolledcanvas TkCommandNames = ['::iwidgets::scrolledcanvas'.freeze].freeze WidgetClassName = 'Scrolledcanvas'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self ################################ diff --git a/ext/tk/lib/tkextlib/iwidgets/scrolledframe.rb b/ext/tk/lib/tkextlib/iwidgets/scrolledframe.rb index 8b47460357..7b7b95df1c 100644 --- a/ext/tk/lib/tkextlib/iwidgets/scrolledframe.rb +++ b/ext/tk/lib/tkextlib/iwidgets/scrolledframe.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Scrolledframe TkCommandNames = ['::iwidgets::scrolledframe'.freeze].freeze WidgetClassName = 'Scrolledframe'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def child_site window(tk_call(@path, 'childsite')) diff --git a/ext/tk/lib/tkextlib/iwidgets/scrolledhtml.rb b/ext/tk/lib/tkextlib/iwidgets/scrolledhtml.rb index 9b69ef07fe..dc2966bd48 100644 --- a/ext/tk/lib/tkextlib/iwidgets/scrolledhtml.rb +++ b/ext/tk/lib/tkextlib/iwidgets/scrolledhtml.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Scrolledhtml TkCommandNames = ['::iwidgets::scrolledhtml'.freeze].freeze WidgetClassName = 'Scrolledhtml'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __boolval_optkeys super() << 'update' diff --git a/ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb b/ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb index 7e63633a1d..20a4cd1d36 100644 --- a/ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb +++ b/ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb @@ -17,7 +17,7 @@ end class Tk::Iwidgets::Scrolledlistbox TkCommandNames = ['::iwidgets::scrolledlistbox'.freeze].freeze WidgetClassName = 'Scrolledlistbox'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() << 'textbackground' diff --git a/ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb b/ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb index 674298ff80..69b7d314fd 100644 --- a/ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb +++ b/ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb @@ -17,7 +17,7 @@ end class Tk::Iwidgets::Scrolledtext TkCommandNames = ['::iwidgets::scrolledtext'.freeze].freeze WidgetClassName = 'Scrolledtext'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() << 'textbackground' @@ -116,6 +116,10 @@ class Tk::Iwidgets::Scrolledtext get('-displaychars', *index) end + def image_cget_tkstring(index, slot) + _fromUTF8(tk_send_without_enc('image', 'cget', + _get_eval_enc_str(index), "-#{slot.to_s}")) + end def image_cget_strict(index, slot) case slot.to_s when 'text', 'label', 'show', 'data', 'file' diff --git a/ext/tk/lib/tkextlib/iwidgets/scrolledwidget.rb b/ext/tk/lib/tkextlib/iwidgets/scrolledwidget.rb index eef093d314..5ecd2d72d2 100644 --- a/ext/tk/lib/tkextlib/iwidgets/scrolledwidget.rb +++ b/ext/tk/lib/tkextlib/iwidgets/scrolledwidget.rb @@ -16,5 +16,5 @@ end class Tk::Iwidgets::Scrolledwidget TkCommandNames = ['::iwidgets::scrolledwidget'.freeze].freeze WidgetClassName = 'Scrolledwidget'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self end diff --git a/ext/tk/lib/tkextlib/iwidgets/selectionbox.rb b/ext/tk/lib/tkextlib/iwidgets/selectionbox.rb index bf9b5ec30a..eb8fe3ad52 100644 --- a/ext/tk/lib/tkextlib/iwidgets/selectionbox.rb +++ b/ext/tk/lib/tkextlib/iwidgets/selectionbox.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Selectionbox TkCommandNames = ['::iwidgets::selectionbox'.freeze].freeze WidgetClassName = 'Selectionbox'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __boolval_optkeys super() << 'itemson' << 'selectionon' diff --git a/ext/tk/lib/tkextlib/iwidgets/selectiondialog.rb b/ext/tk/lib/tkextlib/iwidgets/selectiondialog.rb index f772ecf8c2..45aecf3266 100644 --- a/ext/tk/lib/tkextlib/iwidgets/selectiondialog.rb +++ b/ext/tk/lib/tkextlib/iwidgets/selectiondialog.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Selectiondialog TkCommandNames = ['::iwidgets::selectiondialog'.freeze].freeze WidgetClassName = 'Selectiondialog'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def child_site window(tk_call(@path, 'childsite')) diff --git a/ext/tk/lib/tkextlib/iwidgets/shell.rb b/ext/tk/lib/tkextlib/iwidgets/shell.rb index dabf2e6f25..c560e3ac29 100644 --- a/ext/tk/lib/tkextlib/iwidgets/shell.rb +++ b/ext/tk/lib/tkextlib/iwidgets/shell.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Shell TkCommandNames = ['::iwidgets::shell'.freeze].freeze WidgetClassName = 'Shell'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def activate tk_call(@path, 'activate') # may return val of deactibate method diff --git a/ext/tk/lib/tkextlib/iwidgets/spindate.rb b/ext/tk/lib/tkextlib/iwidgets/spindate.rb index 2c98eb4629..b3de9ed989 100644 --- a/ext/tk/lib/tkextlib/iwidgets/spindate.rb +++ b/ext/tk/lib/tkextlib/iwidgets/spindate.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Spindate TkCommandNames = ['::iwidgets::spindate'.freeze].freeze WidgetClassName = 'Spindate'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __boolval_optkeys super() << 'dayon' << 'monthon' << 'yearon' diff --git a/ext/tk/lib/tkextlib/iwidgets/spinint.rb b/ext/tk/lib/tkextlib/iwidgets/spinint.rb index 5eb944d081..bede3bb1bf 100644 --- a/ext/tk/lib/tkextlib/iwidgets/spinint.rb +++ b/ext/tk/lib/tkextlib/iwidgets/spinint.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Spinint TkCommandNames = ['::iwidgets::spinint'.freeze].freeze WidgetClassName = 'Spinint'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __boolval_optkeys super() << 'wrap' diff --git a/ext/tk/lib/tkextlib/iwidgets/spinner.rb b/ext/tk/lib/tkextlib/iwidgets/spinner.rb index f2d9caae21..d960996e22 100644 --- a/ext/tk/lib/tkextlib/iwidgets/spinner.rb +++ b/ext/tk/lib/tkextlib/iwidgets/spinner.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Spinner TkCommandNames = ['::iwidgets::spinner'.freeze].freeze WidgetClassName = 'Spinner'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self #################################### diff --git a/ext/tk/lib/tkextlib/iwidgets/spintime.rb b/ext/tk/lib/tkextlib/iwidgets/spintime.rb index 0ff683ab56..20f8197a09 100644 --- a/ext/tk/lib/tkextlib/iwidgets/spintime.rb +++ b/ext/tk/lib/tkextlib/iwidgets/spintime.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Spintime TkCommandNames = ['::iwidgets::spintime'.freeze].freeze WidgetClassName = 'Spintime'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __boolval_optkeys super() << 'houron' << 'militaryon' << 'minutelabel' << 'secondlabel' diff --git a/ext/tk/lib/tkextlib/iwidgets/tabnotebook.rb b/ext/tk/lib/tkextlib/iwidgets/tabnotebook.rb index dbb90e5102..f56efa9aaf 100644 --- a/ext/tk/lib/tkextlib/iwidgets/tabnotebook.rb +++ b/ext/tk/lib/tkextlib/iwidgets/tabnotebook.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Tabnotebook TkCommandNames = ['::iwidgets::tabnotebook'.freeze].freeze WidgetClassName = 'Tabnotebook'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self #################################### @@ -46,13 +46,14 @@ class Tk::Iwidgets::Tabnotebook end end + alias pagecget_tkstring itemcget_tkstring alias pagecget itemcget alias pagecget_strict itemcget_strict alias pageconfigure itemconfigure alias pageconfiginfo itemconfiginfo alias current_pageconfiginfo current_itemconfiginfo - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo #################################### diff --git a/ext/tk/lib/tkextlib/iwidgets/tabset.rb b/ext/tk/lib/tkextlib/iwidgets/tabset.rb index c1a1b29268..501ead4964 100644 --- a/ext/tk/lib/tkextlib/iwidgets/tabset.rb +++ b/ext/tk/lib/tkextlib/iwidgets/tabset.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Tabset TkCommandNames = ['::iwidgets::tabset'.freeze].freeze WidgetClassName = 'Tabset'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self #################################### @@ -41,13 +41,14 @@ class Tk::Iwidgets::Tabset end end + alias tabcget_tkstring itemcget_tkstring alias tabcget itemcget alias tabcget_strict itemcget_strict alias tabconfigure itemconfigure alias tabconfiginfo itemconfiginfo alias current_tabconfiginfo current_itemconfiginfo - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo #################################### diff --git a/ext/tk/lib/tkextlib/iwidgets/timeentry.rb b/ext/tk/lib/tkextlib/iwidgets/timeentry.rb index 588da77dc8..b0afb3afd9 100644 --- a/ext/tk/lib/tkextlib/iwidgets/timeentry.rb +++ b/ext/tk/lib/tkextlib/iwidgets/timeentry.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Timeentry TkCommandNames = ['::iwidgets::timeentry'.freeze].freeze WidgetClassName = 'Timeentry'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __strval_optkeys super() << 'closetext' diff --git a/ext/tk/lib/tkextlib/iwidgets/timefield.rb b/ext/tk/lib/tkextlib/iwidgets/timefield.rb index 28e1504797..c34281d4ff 100644 --- a/ext/tk/lib/tkextlib/iwidgets/timefield.rb +++ b/ext/tk/lib/tkextlib/iwidgets/timefield.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Timefield TkCommandNames = ['::iwidgets::timefield'.freeze].freeze WidgetClassName = 'Timefield'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __boolval_optkeys super() << 'gmt' diff --git a/ext/tk/lib/tkextlib/iwidgets/toolbar.rb b/ext/tk/lib/tkextlib/iwidgets/toolbar.rb index c9f1753c70..5b474c3816 100644 --- a/ext/tk/lib/tkextlib/iwidgets/toolbar.rb +++ b/ext/tk/lib/tkextlib/iwidgets/toolbar.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Toolbar TkCommandNames = ['::iwidgets::toolbar'.freeze].freeze WidgetClassName = 'Toolbar'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __tkvariable_optkeys super() << 'helpvariable' diff --git a/ext/tk/lib/tkextlib/iwidgets/watch.rb b/ext/tk/lib/tkextlib/iwidgets/watch.rb index dd96d4f953..f10ec54cb2 100644 --- a/ext/tk/lib/tkextlib/iwidgets/watch.rb +++ b/ext/tk/lib/tkextlib/iwidgets/watch.rb @@ -16,7 +16,7 @@ end class Tk::Iwidgets::Watch TkCommandNames = ['::iwidgets::watch'.freeze].freeze WidgetClassName = 'Watch'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __boolval_optkeys super() << 'showampm' diff --git a/ext/tk/lib/tkextlib/tcllib.rb b/ext/tk/lib/tkextlib/tcllib.rb index c6138f4275..2831989759 100644 --- a/ext/tk/lib/tkextlib/tcllib.rb +++ b/ext/tk/lib/tkextlib/tcllib.rb @@ -42,19 +42,25 @@ module Tk module Tcllib TkComm::TkExtlibAutoloadModule.unshift(self) + # package:: autoscroll + autoload :Autoscroll, 'tkextlib/tcllib/autoscroll' + # package:: ctext autoload :CText, 'tkextlib/tcllib/ctext' + # package:: cursor + autoload :Cursor, 'tkextlib/tcllib/cursor' + + # package:: datefield + autoload :Datefield, 'tkextlib/tcllib/datefield' + autoload :DateField, 'tkextlib/tcllib/datefield' + # package:: getstring autoload :GetString_Dialog, 'tkextlib/tcllib/getstring' # package:: history autoload :History, 'tkextlib/tcllib/history' - # package:: datefield - autoload :Datefield, 'tkextlib/tcllib/datefield' - autoload :DateField, 'tkextlib/tcllib/datefield' - # package:: ico autoload :ICO, 'tkextlib/tcllib/ico' @@ -62,12 +68,21 @@ module Tk autoload :IP_Entry, 'tkextlib/tcllib/ip_entry' autoload :IPEntry, 'tkextlib/tcllib/ip_entry' - # package:: swaplist - autoload :Swaplist_Dialog, 'tkextlib/tcllib/swaplist' + # package:: khim + autoload :KHIM, 'tkextlib/tcllib/khim' + + # package:: ntext + autoload :Ntext, 'tkextlib/tcllib/ntext' # package:: Plotchart autoload :Plotchart, 'tkextlib/tcllib/plotchart' + # package:: style + autoload :Style, 'tkextlib/tcllib/style' + + # package:: swaplist + autoload :Swaplist_Dialog, 'tkextlib/tcllib/swaplist' + # package:: tablelist autoload :Tablelist, 'tkextlib/tcllib/tablelist' autoload :TableList, 'tkextlib/tcllib/tablelist' @@ -81,7 +96,7 @@ module Tk autoload :Tooltip, 'tkextlib/tcllib/tooltip' # package:: widget - autoload :Wdiget, 'tkextlib/tcllib/widget' + autoload :Widget, 'tkextlib/tcllib/widget' end end diff --git a/ext/tk/lib/tkextlib/tcllib/calendar.rb b/ext/tk/lib/tkextlib/tcllib/calendar.rb new file mode 100644 index 0000000000..b6843df176 --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/calendar.rb @@ -0,0 +1,55 @@ +# +# tkextlib/tcllib/calendar.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * calendar widget +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('widget::calendar', '0.9') +TkPackage.require('widget::calendar') + +module Tk::Tcllib + module Widget + class Calendar < TkCanvas + PACKAGE_NAME = 'widget::calendar'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('widget::calendar') + rescue + '' + end + end + end + end +end + +class Tk::Tcllib::Widget::Calendar + TkCommandNames = ['::widget::calendar'.freeze].freeze + + def __boolval_optkeys + super() << 'showpast' + end + private :__boolval_optkeys + + def create_self(keys) + if keys and keys != None + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self + + def get(what = 'all') + tk_send('get', what) + end +end diff --git a/ext/tk/lib/tkextlib/tcllib/canvas_sqmap.rb b/ext/tk/lib/tkextlib/tcllib/canvas_sqmap.rb new file mode 100644 index 0000000000..0bd59511c1 --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/canvas_sqmap.rb @@ -0,0 +1,36 @@ +# +# tkextlib/tcllib/canvas.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('widget::canvas_sqmap', '0.2') +TkPackage.require('widget::canvas_sqmap') + +module Tk::Tcllib + module Widget + class Canvas_Sqmap < Canvas + TkCommandNames = ['::widget::canvas_sqmap'.freeze].freeze + + def image_set(cell, img) + tk_send('image', 'set', cell, img) + self + end + + def image_unset(cell) + tk_send('image', 'unset', cell) + self + end + + def flush + tk_send('flush') + self + end + end + end +end diff --git a/ext/tk/lib/tkextlib/tcllib/canvas_zoom.rb b/ext/tk/lib/tkextlib/tcllib/canvas_zoom.rb new file mode 100644 index 0000000000..e2a5061112 --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/canvas_zoom.rb @@ -0,0 +1,21 @@ +# +# tkextlib/tcllib/canvas.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('widget::canvas_zoom', '0.1') +TkPackage.require('widget::canvas_zoom') + +module Tk::Tcllib + module Widget + class Canvas_Zoom < Canvas + TkCommandNames = ['::widget::canvas_zoom'.freeze].freeze + end + end +end diff --git a/ext/tk/lib/tkextlib/tcllib/chatwidget.rb b/ext/tk/lib/tkextlib/tcllib/chatwidget.rb new file mode 100644 index 0000000000..860b9e899b --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/chatwidget.rb @@ -0,0 +1,151 @@ +# +# tkextlib/tcllib/chatwidget.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * chatwidget - Provides a multi-paned view suitable for display of +# chat room or irc channel information +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('chatwidget', '1.1.0') +TkPackage.require('chatwidget') + +module Tk::Tcllib + class ChatWidget < TkText + PACKAGE_NAME = 'chatwidget'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('chatwidget') + rescue + '' + end + end + end +end + +class Tk::Tcllib::ChatWidget + TkCommandNames = ['::chatwidget::chatwidget'.freeze].freeze + + def show_topic + tk_send_without_enc('topic', 'show') + self + end + + def hide_topic + tk_send_without_enc('topic', 'hide') + self + end + + def set_topic(topic) + tk_send('topic', 'set', topic) + end + + def list_name + tk_split_simplelist(tk_send('name', 'list')) + end + + def list_name_full + tk_split_simplelist(tk_send('name', 'list')).map{|lst| + nick, *opts = tk_split_simplelist(lst) + h_opt = {} + opts.slice(2){|k, v| h_opt[k[1..-1]] = tk_tcl2ruby(v)} + [nick, h_opt] + } + end + + def add_name(nick, opts={}) + tk_send('name', 'add', nick, *(hash_kv(opts))) + end + + def delete_name(nick) + tk_send('name', 'delete', nick) + end + + def get_name(nick) + lst = tk_send('name', 'get', nick) + return nil if lst.empty? + nick, *opts = tk_split_simplelist(lst) + h_opt = {} + opts.slice(2){|k, v| h_opt[k[1..-1]] = tk_tcl2ruby(v)} + [nick, h_opt] + end + + def message(msg, opts={}) + tk_send('message', msg, *(hash_kv(opts))) + self + end + + def _parse_hook_list(lst) + tk_split_simplelist(lst).map{|hook| + cmd, prior = tk_split_simplelist(hook) + [procedure(cmd), number(prior)] + } + end + private :_parse_hook_list + + def hook_add(type, *args, &blk) # args -> [prior, cmd], [prior], [cmd] + #type -> 'message', 'post', 'names_group', 'names_nick', 'chatstate', 'url' + + if prior = args.shift + if !prior.kind_of?(Numeric) + cmd = prior + if (prior = args.shift) && !prior.kind_of?(Numeric) # error + args.unshift(prior) + end + args.unshift(cmd) + end + prior ||= 50 # default priority + end + + cmd = args.shift || blk + + fail ArgumentError, "invalid arguments" unless args.empty? + fail ArgumentError, "no callback is given" unless cmd + + _parse_hook_list(tk_send('hook', 'add', type, cmd, prior)) + end + + def hook_remove(type, cmd) + #type -> 'message', 'post', 'names_group', 'names_nick', 'chatstate', 'url' + _parse_hook_list(tk_send('hook', 'remove', type, cmd)) + end + + def hook_run(type, *cmd_args) + #type -> 'message', 'post', 'names_group', 'names_nick', 'chatstate', 'url' + tk_send('hook', 'run', type, *cmd_args) + end + + def hook_list(type) + #type -> 'message', 'post', 'names_group', 'names_nick', 'chatstate', 'url' + _parse_hook_list(tk_send('hook', 'list', type)) + end + + def show_names + tk_send('names', 'show') + self + end + + def hide_names + tk_send('names', 'hide') + self + end + + def names_widget + window(tk_send('names')) + end + + def entry_widget + window(tk_send('entry')) + end + + def chat_widget + window(tk_send('chat')) + end +end diff --git a/ext/tk/lib/tkextlib/tcllib/crosshair.rb b/ext/tk/lib/tkextlib/tcllib/crosshair.rb new file mode 100644 index 0000000000..49b5361e4f --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/crosshair.rb @@ -0,0 +1,117 @@ +# +# tkextlib/tcllib/crosshair.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Crosshairs for Tk canvas +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('crosshair', '1.0.2') +TkPackage.require('crosshair') + +module Tk::Tcllib + module Crosshair + PACKAGE_NAME = 'crosshair'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('crosshair') + rescue + '' + end + end + end +end + +module Tk::Tcllib::Crosshair + include TkCore + TkCommandNames = ['::crosshair::crosshair'.freeze].freeze + + def self.crosshair(w, keys={}) + Tk.tk_call('::crosshair::crosshair', w, *hash_kv(keys)) + w + end + def self.on(w, keys={}) + self.crosshair(w, keys) + end + + def self.off(w) + Tk.tk_call('::crosshair::off', w) + w + end + + def self.track_on(w, &b) + Tk.tk_call('::crosshair::track_on', w, b) + w + end + + def self.track_off(w) + Tk.tk_call('::crosshair::track_off', w) + w + end +end + +class << Tk::Tcllib::Crosshair + include TkComm + include TkCanvasItemConfig + + def __item_methodcall_optkeys(id) + {} + end + private :__item_methodcall_optkeys + + def __item_config_cmd(id) + # maybe need to override + ['::crosshair::configure', id] + end + private :__item_config_cmd + + private :itemcget_tkstring, :itemcget, :itemcget_strict + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo + + def confugure(w, slot, value=None) + itemconfigure(w, slot, value) + end + def confuginfo(w, slot = nil) + itemconfiginfo(w, slot) + end + def current_configinfo(w, slot = nil) + current_itemconfiginfo(w, slot) + end + def cget(w, slot) + current_itemconfiginfo(w, slot).values[0] + end +end + +module Tk::Tcllib::Crosshair + def crosshair_on(keys={}) + Tk::Tcllib::Crosshair.on(self, keys) + end + def crosshair_off + Tk::Tcllib::Crosshair.off(self) + end + def crosshair_track_on(&b) + Tk::Tcllib::Crosshair.track_on(self, &b) + end + def crosshair_track_off + Tk::Tcllib::Crosshair.track_off(self) + end + def crosshair_configure(*args) + Tk::Tcllib::Crosshair.configure(self, *args) + end + def crosshair_configinfo(slot = nil) + Tk::Tcllib::Crosshair.configinfo(self, slot) + end + def crosshair_current_configinfo(slot = nil) + Tk::Tcllib::Crosshair.current_configinfo(self, slot) + end + def crosshair_cget(slot) + Tk::Tcllib::Crosshair.cget(self, slot) + end +end diff --git a/ext/tk/lib/tkextlib/tcllib/ctext.rb b/ext/tk/lib/tkextlib/tcllib/ctext.rb index 21d6438b48..308847c233 100644 --- a/ext/tk/lib/tkextlib/tcllib/ctext.rb +++ b/ext/tk/lib/tkextlib/tcllib/ctext.rb @@ -35,7 +35,7 @@ end class Tk::Tcllib::CText TkCommandNames = ['ctext'.freeze].freeze WidgetClassName = 'Ctext'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def create_self(keys) if keys and keys != None diff --git a/ext/tk/lib/tkextlib/tcllib/dateentry.rb b/ext/tk/lib/tkextlib/tcllib/dateentry.rb new file mode 100644 index 0000000000..77038d95bc --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/dateentry.rb @@ -0,0 +1,62 @@ +# +# tkextlib/tcllib/dateentry.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * dateentry widget +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('widget::dateentry', '0.91') +TkPackage.require('widget::dateentry') + +module Tk::Tcllib + module Widget + class Dateentry < Tk::Tile::TEntry + PACKAGE_NAME = 'widget::dateentry'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('widget::dateentry') + rescue + '' + end + end + end + DateEntry = Dateentry + end +end + +class Tk::Tcllib::Widget::Dateentry + TkCommandNames = ['::widget::dateentry'.freeze].freeze + + def __strval_optkeys + super() << ['dateformat'] + end + private :__strval_optkeys + + def create_self(keys) + if keys and keys != None + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self + + def post + tk_send('post') + self + end + + def unpost + tk_send('unpost') + self + end +end diff --git a/ext/tk/lib/tkextlib/tcllib/diagrams.rb b/ext/tk/lib/tkextlib/tcllib/diagrams.rb new file mode 100644 index 0000000000..d24ba9d232 --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/diagrams.rb @@ -0,0 +1,224 @@ +# +# tkextlib/tcllib/diagrams.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Draw diagrams +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('Diagrams', '0.3') +TkPackage.require('Diagrams') + +module Tk::Tcllib + module Diagrams + PACKAGE_NAME = 'Diagrams'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('Diagrams') + rescue + '' + end + end + end +end + +class << Tk::Tcllib::Diagrams + include TkCore + + def drawin(canvas) + tk_call('::Diagrams::drawin', canvas) + canvas + end + alias draw_in drawin + + def saveps(filename) + tk_call('::Diagrams::saveps', filename) + filename + end + alias save_ps saveps + + def direction(dir) + tk_call('::Diagrams::direction', dir) + dir + end + + def currentpos(pos) + list(tk_call('::Diagrams::currentpos', pos)) + end + alias current_pos currentpos + alias currentpos= currentpos + alias current_pos= currentpos + + def getpos(anchor, obj) + list(tk_call('::Diagrams::getpos', anchor, obj)) + end + alias get_pos getpos + + def position(x, y) + list(tk_call('::Diagrams::position', x, y)) + end + + def box(text, width=nil, height=nil) + if width || height + width = '' unless width + height = '' unless height + list(tk_call('::Diagrams::box', text, width, height)) + else + list(tk_call('::Diagrams::box', text)) + end + end + + def plaintext(text, width=nil, height=nil) + if width || height + width = '' unless width + height = '' unless height + list(tk_call('::Diagrams::plaintext', text, width, height)) + else + list(tk_call('::Diagrams::plaintext', text)) + end + end + + def circle(text, radius=nil) + if radius + list(tk_call('::Diagrams::circle', text, radius)) + else + list(tk_call('::Diagrams::circle', text)) + end + end + + def slanted(text, width=nil, height=nil, angle=nil) + if width || height || angle + width = '' unless width + height = '' unless height + if angle + list(tk_call('::Diagrams::slanted', text, width, height, angle)) + else + list(tk_call('::Diagrams::slanted', text, width, height)) + end + else + list(tk_call('::Diagrams::slanted', text)) + end + end + + def diamond(text, width=nil, height=nil) + if width || height + width = '' unless width + height = '' unless height + list(tk_call('::Diagrams::diamond', text, width, height)) + else + list(tk_call('::Diagrams::diamond', text)) + end + end + + def drum(text, width=nil, height=nil) + if width || height + width = '' unless width + height = '' unless height + list(tk_call('::Diagrams::drum', text, width, height)) + else + list(tk_call('::Diagrams::drum', text)) + end + end + + def arrow(text=nil, length=nil, head=nil) + if length || head + text = '' unless text + length = '' unless length + list(tk_call('::Diagrams::arrow', text, length, head)) + else + if text + list(tk_call('::Diagrams::arrow', text)) + else + list(tk_call('::Diagrams::arrow')) + end + end + end + + def line(*args) + ary = [] + args.each{|arg| + if arg.kind_of?(Array) && arg.length == 2 # [length, angle] + ary.concat arg + else # ["POSITION", x, y] or length or angle + ary << arg + end + } + list(tk_call('::Diagrams::line', *ary)) + end + + def bracket(dir, dist, from_pos, to_pos) + list(tk_call('::Diagrams::bracket', dir, dist, from_pos, to_pos)) + end + + def attach(anchor=None) + tk_call('::Diagrams::attach', anchor) + end + + def color(name=None) + tk_call('::Diagrams::color', name) + end + + def fillcolor(name=None) + tk_call('::Diagrams::fillcolor', name) + end + + def textcolor(name=None) + tk_call('::Diagrams::textcolor', name) + end + + def usegap(mode=None) + bool(tk_call('::Diagrams::usegap', mode)) + end + alias use_gap usegap + + def xgap(val=None) + number(tk_call('::Diagrams::xgap', val)) + end + + def ygap(val=None) + number(tk_call('::Diagrams::ygap', val)) + end + + def textfont(fnt=None) + tk_call('::Diagrams::textfont', fnt) + end + + def linewidth(pixels=None) + number(tk_call('::Diagrams::linewidth', pixels)) + end + + def linestyle(style=None) + tk_call('::Diagrams::linestyle', style) + end + + def pushstate + tk_call('::Diagrams::pushstate') + end + alias push_state pushstate + + def popstate + tk_call('::Diagrams::popstate') + end + alias pop_state popstate + + def computepos + list(tk_call('::Diagrams::computepos')) + end + alias compute_pos computepos + + def boxcoords(x1, y1, x2, y2) + list(tk_call('::Diagrams::boxcoords', x1, y1, x2, y2)) + end + + def moveobject(obj) + list(tk_call('::Diagrams::moveobject', obj)) + end + alias move_object moveobject +end diff --git a/ext/tk/lib/tkextlib/tcllib/getstring.rb b/ext/tk/lib/tkextlib/tcllib/getstring.rb index ab45c9b1ea..48711d3b66 100644 --- a/ext/tk/lib/tkextlib/tcllib/getstring.rb +++ b/ext/tk/lib/tkextlib/tcllib/getstring.rb @@ -34,7 +34,7 @@ end class Tk::Tcllib::GetString_Dialog TkCommandNames = ['::getstring::tk_getString'.freeze].freeze WidgetClassName = 'TkSDialog'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def self.show(*args) dialog = self.new(*args) diff --git a/ext/tk/lib/tkextlib/tcllib/ico.rb b/ext/tk/lib/tkextlib/tcllib/ico.rb index 538f7b5408..36a32c6b09 100644 --- a/ext/tk/lib/tkextlib/tcllib/ico.rb +++ b/ext/tk/lib/tkextlib/tcllib/ico.rb @@ -8,7 +8,7 @@ require 'tk' require 'tk/image' -require 'tkextlib/tcllib.rb' +#require 'tkextlib/tcllib.rb' # TkPackage.require('ico', '0.3') TkPackage.require('ico') @@ -38,9 +38,39 @@ class Tk::Tcllib::ICO *hash_kv(keys, true))) end + def self.icons(file, keys=nil) + tk_split_simplelist(tk_call_without_enc('::ico::icons', file, + *hash_kv(keys, true))).map{|elem| + num_or_str(elem) + } + end + + def self.get_members(file, name, keys=nil) + tk_split_simplelist(tk_call_without_enc('::ico::getMembers', file, name, + *hash_kv(keys, true))).map{|elem| + name, width, height, bpp = tk_split_simplelist(elem) + [name, number(width), number(height), number(bpp)] + } + end + def self.get(file, index, keys=nil) tk_call_without_enc('::ico::getIcon', file, index, *hash_kv(keys, true)) end + def self.get_icon(*args) + get(*args) + end + + def self.get_by_name(file, name, keys=nil) + tk_call_without_enc('::ico::getIconByName', file, name, + *hash_kv(keys, true)) + end + def self.get_icon_by_name(*args) + get_by_name(*args) + end + + def self.get_fileicon(file, keys=nil) + tk_call_without_enc('::ico::getFileIcon', file, *hash_kv(keys, true)) + end def self.get_image(file, index, keys={}) keys = _symbolkey2str(keys) diff --git a/ext/tk/lib/tkextlib/tcllib/ip_entry.rb b/ext/tk/lib/tkextlib/tcllib/ip_entry.rb index a8a33f1cad..e5e0f8d42d 100644 --- a/ext/tk/lib/tkextlib/tcllib/ip_entry.rb +++ b/ext/tk/lib/tkextlib/tcllib/ip_entry.rb @@ -33,13 +33,18 @@ module Tk end end IPEntry = IP_Entry + + class IP_Entry6 < IP_Entry + end + IPEntry6 = IP_Entry6 + IP6_Entry = IP_Entry6 end end class Tk::Tcllib::IP_Entry TkCommandNames = ['::ipentry::ipentry'.freeze].freeze WidgetClassName = 'IPEntry'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def create_self(keys) if keys and keys != None @@ -64,3 +69,7 @@ class Tk::Tcllib::IP_Entry tk_send_without_enc('insert', array2tk_list(ip.flatten)) end end + +class Tk::Tcllib::IP_Entry6 < Tk::Tcllib::IP_Entry + TkCommandNames = ['::ipentry::ipentry6'.freeze].freeze +end diff --git a/ext/tk/lib/tkextlib/tcllib/khim.rb b/ext/tk/lib/tkextlib/tcllib/khim.rb new file mode 100644 index 0000000000..00acff91d9 --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/khim.rb @@ -0,0 +1,68 @@ +# +# tkextlib/tcllib/khim.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Kevin's Hacky Input Method +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('khim', '1.0') +TkPackage.require('khim') + +module Tk::Tcllib + class KHIM < TkToplevel + PACKAGE_NAME = 'khim'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('khim') + rescue + '' + end + end + end +end + +class Tk::Tcllib::KHIM + TkCommandNames = ['::khim::getOptions'.freeze].freeze + + def self.get_options(parent='') + path = parent + '.tcllib_widget_khim_dialog' + self.new(:widgetname => path) + end + + def self.get_config #=> cmd_string + Tk.tk_call_without_enc('::khim::getConfig') + end + + def self.set_config(*args) + if args.length == 1 + # cmd_string generated by + #Tk.ip_eval_without_enc(cmd_string) + Tk.ip_eval(cmd_string) + else + # args for setConfig command + #Tk.tk_call_without_enc('::khim::setConfig', *args) + Tk.tk_call('::khim::setConfig', *args) + end + end + + def self.showHelp + Tk::Tcllib::KHIM::Help.new + end + + def create_self(keys=None) + @db_class = @classname = nil + super(None) # ignore keys + end +end + +class Tk::Tcllib::KHIM::Help < TkToplevel + TkCommandNames = ['::khim::showHelp'.freeze].freeze +end diff --git a/ext/tk/lib/tkextlib/tcllib/menuentry.rb b/ext/tk/lib/tkextlib/tcllib/menuentry.rb new file mode 100644 index 0000000000..f1eb2f295c --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/menuentry.rb @@ -0,0 +1,47 @@ +# +# tkextlib/tcllib/menuentry.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * menuentry widget +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('widget::menuentry', '1.0') +TkPackage.require('widget::menuentry') + +module Tk::Tcllib + module Widget + class Menuentry < Tk::Tile::TEntry + PACKAGE_NAME = 'widget::menuentry'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('widget::menuentry') + rescue + '' + end + end + end + MenuEntry = Menuentry + end +end + +class Tk::Tcllib::Widget::Menuentry + TkCommandNames = ['::widget::menuentry'.freeze].freeze + + def create_self(keys) + if keys and keys != None + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self +end diff --git a/ext/tk/lib/tkextlib/tcllib/ntext.rb b/ext/tk/lib/tkextlib/tcllib/ntext.rb new file mode 100644 index 0000000000..7888ed4871 --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/ntext.rb @@ -0,0 +1,146 @@ +# +# tkextlib/tcllib/ntext.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Ntext bindtag +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('ntext', '0.81') +TkPackage.require('ntext') + +module Tk::Tcllib + Ntext = TkBindTag.new_by_name('Ntext') +end + +# variables +Tk::Tcllib::Ntext.instance_eval{ + # boolean + @classicAnchor = TkVarAccess.new('::ntext::classicAnchor') + @classicExtras = TkVarAccess.new('::ntext::classicExtras') + @classicMouseSelect = TkVarAccess.new('::ntext::classicMouseSelect') + @classicWordBreak = TkVarAccess.new('::ntext::classicWordBreak') + @classicWrap = TkVarAccess.new('::ntext::classicWrap') + @overwrite = TkVarAccess.new('::ntext::overwrite') + + # regexp + @newWrapRegexp = TkVarAccess.new('::ntext::newWrapRegexp') + + # variables (advanced use) + @tcl_match_wordBreakAfter = TkVarAccess.new('::ntext::tcl_match_wordBreakAfter') + @tcl_match_wordBreakBefore = TkVarAccess.new('::ntext::tcl_match_wordBreakBefore') + @tcl_match_endOfWord = TkVarAccess.new('::ntext::tcl_match_endOfWord') + @tcl_match_startOfNextWord = TkVarAccess.new('::ntext::tcl_match_startOfNextWord') + @tcl_match_startOfPreviousWord = TkVarAccess.new('::ntext::tcl_match_startOfPreviousWord') +} + +class << Tk::Tcllib::Ntext + def wrapIndent(txt, *args) + TK.tk_call('::next::wrapIndent', txt, *args) + end + + def initializeMatchPatterns + TK.tk_call('::next::initializeMatchPatterns') + self + end + + def createMatchPatterns(*args) + TK.tk_call('::next::createMatchPatterns', *args) + self + end + + # functions (advanced use) + #ntext::new_wordBreakAfter + #ntext::new_wordBreakBefore + #ntext::new_endOfWord + #ntext::new_startOfNextWord + #ntext::new_startOfPreviousWord + + # accessor + def classicAnchor + @classicAnchor.bool + end + def classicAnchor=(mode) + @classicAnchor.bool = mode + end + + def classicExtras + @classicExtras.bool + end + def classicExtras=(mode) + @classicExtras.bool = mode + end + + def classicMouseSelect + @classicMouseSelect.bool + end + def classicMouseSelect=(mode) + @classicMouseSelect.bool = mode + end + + def classicWordBreak + @classicWordBreak.bool + end + def classicWordBreak=(mode) + @classicWordBreak.bool = mode + end + + def classicWrap + @classicWrap.bool + end + def classicWrap=(mode) + @classicWrap.bool = mode + end + + def overwrite + @overwrite.bool + end + def overwrite=(mode) + @classic.bool = mode + end + + def newWrapRegexp + @newWrapRegexp.value + end + def newWrapRegexp=(val) + @newWrapRegexp.value = val + end + + def tcl_match_wordBreakAfter + @tcl_match_wordBreakAfter.value + end + def tcl_match_wordBreakAfter=(val) + @tcl_match_wordBreakAfter.value = val + end + + def tcl_match_wordBreakBefore + @tcl_match_wordBreakBefore.value + end + def tcl_match_wordBreakBefore=(val) + @tcl_match_wordBreakBefore.value = val + end + + def tcl_match_endOfWord + @tcl_match_endOfWord.value + end + def tcl_match_endOfWord=(val) + @tcl_match_endOfWord.value = val + end + + def tcl_match_startOfNextWord + @tcl_match_startOfNextWord.value + end + def tcl_match_startOfNextWord=(val) + @tcl_match_startOfNextWord.value = val + end + + def tcl_match_startOfPreviousWord + @tcl_match_startOfPreviousWord.value + end + def tcl_match_startOfPreviousWord=(val) + @tcl_match_startOfPreviousWord.value = val + end +end diff --git a/ext/tk/lib/tkextlib/tcllib/panelframe.rb b/ext/tk/lib/tkextlib/tcllib/panelframe.rb index 9086ad78d2..020c51cbd1 100644 --- a/ext/tk/lib/tkextlib/tcllib/panelframe.rb +++ b/ext/tk/lib/tkextlib/tcllib/panelframe.rb @@ -60,11 +60,17 @@ class Tk::Tcllib::Widget::PanelFrame def remove(*wins) tk_send('remove', *wins) + self end def remove_destroy(*wins) tk_send('remove', '-destroy', *wins) + self + end + + def delete(*wins) + tk_send('delete', *wins) + self end - alias delete remove_destroy def items simplelist(tk_send('items')).collect!{|w| window(w)} diff --git a/ext/tk/lib/tkextlib/tcllib/plotchart.rb b/ext/tk/lib/tkextlib/tcllib/plotchart.rb index 25a574efbc..6b7a526b75 100644 --- a/ext/tk/lib/tkextlib/tcllib/plotchart.rb +++ b/ext/tk/lib/tkextlib/tcllib/plotchart.rb @@ -62,6 +62,7 @@ require 'tkextlib/tcllib.rb' # TkPackage.require('Plotchart', '0.9') # TkPackage.require('Plotchart', '1.1') +# TkPackage.require('Plotchart', '1.6.3') TkPackage.require('Plotchart') module Tk @@ -109,6 +110,29 @@ module Tk::Tcllib::Plotchart list(tk_call_without_enc('::Plotchart::coords3DToPixel', w.path, x, y, z)) end + def self.plotconfig(*args) + case args.length + when 0, 1, 2 + # 0: (no args) --> list of chat types + # 1: charttype --> list of components + # 2: charttype, component --> list of properties + simplelist(tk_call('::Plotchart::plotconfig', *args)) + when 3 + # 3: charttype, component, property --> current value + tk_call('::Plotchart::plotconfig', *args) + else + # 4: charttype, component, property, value : set new value + # 5+: Error on Tcl/Tk + tk_call('::Plotchart::plotconfig', *args) + nil + end + end + + def self.plotpack(w, dir, *plots) + tk_call_without_enc('::Plotchart::plotpack', w.path, dir, *plots) + w + end + def self.polar_coordinates(w, radmax) tk_call_without_enc('::Plotchart::polarCoordinates', w.path, radmax) end @@ -157,8 +181,7 @@ module Tk::Tcllib::Plotchart if key.kind_of?(Hash) tk_call_without_enc(@chart, 'xconfig', *hash_kv(key, true)) else - tk_call_without_enc(@chart, 'xconfig', - "-#{key}", _get_eval_enc_str(value)) + tk_call(@chart, 'xconfig', "-#{key}",value) end self end @@ -167,13 +190,86 @@ module Tk::Tcllib::Plotchart if key.kind_of?(Hash) tk_call_without_enc(@chart, 'yconfig', *hash_kv(key, true)) else - tk_call_without_enc(@chart, 'yconfig', - "-#{key}", _get_eval_enc_str(value)) + tk_call(@chart, 'yconfig', "-#{key}", value) + end + self + end + + def background(part, color_or_image, dir) + tk_call_without_enc(@chart, 'background', + part, color_or_image, dir) + self + end + + def xticklines(color=None) + tk_call(@chart, 'xticklines', color) + self + end + + def yticklines(color=None) + tk_call(@chart, 'yticklines', color) + self + end + + def legendconfig(key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'legendconfig', *hash_kv(key, true)) + else + tk_call(@chart, 'legendconfig', "-#{key}", value) + end + self + end + + def legend(series, text) + tk_call_without_enc(@chart, 'legend', + _get_eval_enc_str(series), _get_eval_enc_str(text)) + self + end + + def balloon(*args) # args => (x, y, text, dir) or ([x, y], text, dir) + if args[0].kind_of?(Array) + # args => ([x, y], text, dir) + x, y = args.shift + else + # args => (x, y, text, dir) + x = args.shift + y = args.shift end + + text, dir = args + + tk_call_without_enc(@chart, 'balloon', x, y, + _get_eval_enc_str(text), dir) + self + end + + def balloonconfig(key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'balloonconfig', *hash_kv(key, true)) + else + tk_call(@chart, 'balloonconfig', "-#{key}", value) + end + end + + def plaintext(*args) # args => (x, y, text, dir) or ([x, y], text, dir) + if args[0].kind_of?(Array) + # args => ([x, y], text, dir) + x, y = args.shift + else + # args => (x, y, text, dir) + x = args.shift + y = args.shift + end + + text, dir = args + + tk_call_without_enc(@chart, 'plaintext', x, y, + _get_eval_enc_str(text), dir) self end ############################ + def view_port(*args) # args := pxmin, pymin, pxmax, pymax tk_call_without_enc('::Plotchart::viewPort', @path, *(args.flatten)) self @@ -200,6 +296,11 @@ module Tk::Tcllib::Plotchart list(tk_call_without_enc('::Plotchart::coords3DToPixel', @path, x, y, z)) end + def plotpack(dir, *plots) + tk_call_without_enc('::Plotchart::plotpack', @path, dir, *plots) + self + end + def polar_coordinates(radmax) tk_call_without_enc('::Plotchart::polarCoordinates', @path, radmax) self @@ -281,27 +382,27 @@ module Tk::Tcllib::Plotchart vals = array2tk_list(vals) if vals.kind_of?(Array) clss = array2tk_list(clss) if clss.kind_of?(Array) - tk_call_without_enc(@chart, 'contourlines', xcrd, ycrd, vals, clss) + tk_call(@chart, 'contourlines', xcrd, ycrd, vals, clss) self end - def contourfill(xcrd, ycrd, vals, klasses=None) + def contourfill(xcrd, ycrd, vals, clss=None) xcrd = array2tk_list(xcrd) if xcrd.kind_of?(Array) ycrd = array2tk_list(ycrd) if ycrd.kind_of?(Array) vals = array2tk_list(vals) if vals.kind_of?(Array) clss = array2tk_list(clss) if clss.kind_of?(Array) - tk_call_without_enc(@chart, 'contourfill', xcrd, ycrd, vals, clss) + tk_call(@chart, 'contourfill', xcrd, ycrd, vals, clss) self end - def contourbox(xcrd, ycrd, vals, klasses=None) + def contourbox(xcrd, ycrd, vals, clss=None) xcrd = array2tk_list(xcrd) if xcrd.kind_of?(Array) ycrd = array2tk_list(ycrd) if ycrd.kind_of?(Array) vals = array2tk_list(vals) if vals.kind_of?(Array) clss = array2tk_list(clss) if clss.kind_of?(Array) - tk_call_without_enc(@chart, 'contourbox', xcrd, ycrd, vals, clss) + tk_call(@chart, 'contourbox', xcrd, ycrd, vals, clss) self end @@ -324,10 +425,70 @@ module Tk::Tcllib::Plotchart if key.kind_of?(Hash) tk_call_without_enc(@chart, 'dataconfig', series, *hash_kv(key, true)) else - tk_call_without_enc(@chart, 'dataconfig', series, - "-#{key}", _get_eval_enc_str(value)) + tk_call(@chart, 'dataconfig', series, "-#{key}", value) end end + + def rescale(xscale, yscale) # xscale|yscale => [newmin, newmax, newstep] + tk_call_without_enc(@chart, 'rescale', xscale, yscale) + self + end + + def trend(series, xcrd, ycrd) + tk_call_without_enc(@chart, 'trend', + _get_eval_enc_str(series), xcrd, ycrd) + self + end + + def rchart(series, xcrd, ycrd) + tk_call_without_enc(@chart, 'rchart', + _get_eval_enc_str(series), xcrd, ycrd) + self + end + + def interval(series, xcrd, ymin, ymax, ycenter=None) + tk_call(@chart, 'interval', series, xcrd, ymin, ymax, ycenter) + self + end + + def box_and_whiskers(series, xcrd, ycrd) + tk_call_without_enc(@chart, 'box-and-whiskers', + _get_eval_enc_str(series), xcrd, ycrd) + self + end + alias box_whiskers box_and_whiskers + + def vectorconfig(series, key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'vectorconfig', + _get_eval_enc_str(series), *hash_kv(key, true)) + else + tk_call(@chart, 'vectorconfig', series, "-#{key}", value) + end + self + end + + def vector(series, xcrd, ycrd, ucmp, vcmp) + tk_call_without_enc(@chart, 'vector', _get_eval_enc_str(series), + xcrd, ycrd, ucmp, vcmp) + self + end + + def dotconfig(series, key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'dotconfig', + _get_eval_enc_str(series), *hash_kv(key, true)) + else + tk_call(@chart, 'dotconfig', series, "-#{key}", value) + end + self + end + + def dot(series, xcrd, ycrd, value) + tk_call_without_enc(@chart, 'dot', _get_eval_enc_str(series), + xcrd, ycrd, value) + self + end end ############################ @@ -338,6 +499,30 @@ module Tk::Tcllib::Plotchart ].freeze end + ############################ + class TXPlot < XYPlot + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createTXPlot'.freeze + ].freeze + end + + ############################ + class XLogYPlot < XYPlot + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createXLogYPlot'.freeze + ].freeze + end + + ############################ + class Histogram < XYPlot + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createHistgram'.freeze + ].freeze + end + ############################ class PolarPlot < Tk::Canvas include ChartMethod @@ -389,10 +574,10 @@ module Tk::Tcllib::Plotchart def dataconfig(series, key, value=None) if key.kind_of?(Hash) - tk_call_without_enc(@chart, 'dataconfig', series, *hash_kv(key, true)) + tk_call_without_enc(@chart, 'dataconfig', _get_eval_enc_str(series), + *hash_kv(key, true)) else - tk_call_without_enc(@chart, 'dataconfig', series, - "-#{key}", _get_eval_enc_str(value)) + tk_call(@chart, 'dataconfig', series, "-#{key}", value) end end end @@ -541,6 +726,15 @@ module Tk::Tcllib::Plotchart self end + def plot_line(dat, color) + # dat has to be provided as a 2 level array. + # 1st level contains rows, drawn in y-direction, + # and each row is an array whose elements are drawn in x-direction, + # for the columns. + tk_call_without_enc(@chart, 'plotline', dat, color) + self + end + def plot_data(dat) # dat has to be provided as a 2 level array. # 1st level contains rows, drawn in y-direction, @@ -550,6 +744,15 @@ module Tk::Tcllib::Plotchart self end + def zconfig(key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'zconfig', *hash_kv(key, true)) + else + tk_call(@chart, 'zconfig', "-#{key}", value) + end + self + end + def colour(fill, border) # configure the colours to use for polygon borders and inner area tk_call_without_enc(@chart, 'colour', fill, border) @@ -560,6 +763,132 @@ module Tk::Tcllib::Plotchart alias color colour end + ############################ + class Barchart3D < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::create3DBarchart'.freeze + ].freeze + + def initialize(*args) # args := ([parent,] yaxis, nobars [, keys]) + # yaxis := Array of [minimum, maximum, stepsize] + # nobars := number of bars + if args[0].kind_of?(Array) + @yaxis = args.shift + @nobars = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @yaxis = args.shift + @nobars = args.shift + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + array2tk_list(@yaxis), @nobars) + end + private :_create_chart + + def plot(label, yvalue, color) + tk_call_without_enc(@chart, 'plot', _get_eval_enc_str(label), + _get_eval_enc_str(yvalue), color) + self + end + + def config(key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'config', *hash_kv(key, true)) + else + tk_call(@chart, 'config', "-#{key}", value) + end + self + end + end + + ############################ + class RibbonChart3D < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::create3DRibbonChart'.freeze + ].freeze + + def initialize(*args) # args := ([parent,] names, yaxis, zaxis [, keys]) + # names := Array of the series + # yaxis := Array of [minimum, maximum, stepsize] + # zaxis := Array of [minimum, maximum, stepsize] + if args[0].kind_of?(Array) + @names = args.shift + @yaxis = args.shift + @zaxis = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @names = args.shift + @yaxis = args.shift + @zaxis = args.shift + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + array2tk_list(@names), + array2tk_list(@yaxis), + array2tk_list(@zaxis)) + end + private :_create_chart + + def line(*args) # xypairs, color + color = args.pop # last argument is a color + xypairs = TkComm.slice_ary(args.flatten, 2) # regenerate xypairs + tk_call_without_enc(@chart, 'line', xypairs, color) + self + end + + def area(*args) # xypairs, color + color = args.pop # last argument is a color + xypairs = TkComm.slice_ary(args.flatten, 2) # regenerate xypairs + tk_call_without_enc(@chart, 'area', xypairs, color) + self + end + + def zconfig(key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'zconfig', *hash_kv(key, true)) + else + tk_call(@chart, 'zconfig',"-#{key}", value) + end + self + end + end + + ############################ class Piechart < Tk::Canvas include ChartMethod @@ -586,9 +915,76 @@ module Tk::Tcllib::Plotchart private :_create_chart def plot(*dat) # argument is a list of [label, value] - tk_call_without_enc(@chart, 'plot', dat.flatten) + tk_call(@chart, 'plot', dat.flatten) + self + end + + def colours(*list) + tk_call_without_enc(@chart, 'colours', *list) self end + alias colors colours + end + + + ############################ + class Radialchart < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createRadialchart'.freeze + ].freeze + + def initialize(*args) # args := ([parent,] names, scale, style [, keys]) + # radius_data := Array of [maximum_radius, stepsize] + if args[0].kind_of?(Array) + @names = args.shift + @scale = args.shift + @style = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @names = args.shift + @scale = args.shift + @style = args.shift + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + array2tk_list(@names), @scale, @style) + end + private :_create_chart + + def __destroy_hook__ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path) + } + end + + def plot(data, color, thickness) + tk_call_without_enc(@chart, 'plot', _get_eval_enc_str(data), + color, thickness) + self + end + + def colours(*list) + tk_call_without_enc(@chart, 'colours', *list) + self + end + alias colors colours end ############################ @@ -655,13 +1051,13 @@ module Tk::Tcllib::Plotchart end def plot(series, dat, col=None) - tk_call_without_enc(@chart, 'plot', series, dat, col) + tk_call(@chart, 'plot', series, dat, col) self end def colours(*cols) # set the colours to be used - tk_call_without_enc(@chart, 'colours', *cols) + tk_call(@chart, 'colours', *cols) self end alias colour colours @@ -677,6 +1073,102 @@ module Tk::Tcllib::Plotchart ].freeze end + ############################ + class Boxplot < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createBoxplot'.freeze + ].freeze + + def initialize(*args) # args := ([parent,] xaxis, ylabels [, keys]) + # xaxis := Array of [minimum, maximum, stepsize] + # yaxis := List of labels for the y-axis + if args[0].kind_of?(Array) + @xaxis = args.shift + @ylabels = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @xaxis = args.shift + @ylabels = args.shift + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + array2tk_list(@xaxis), array2tk_list(@ylabels)) + end + private :_create_chart + + def __destroy_hook__ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path) + } + end + + def plot(label, *values) + tk_call(@chart, 'plot', label, values.flatten) + self + end + end + + ############################ + class RightAxis < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createRightAxis'.freeze + ].freeze + + def initialize(*args) # args := ([parent,] yaxis [, keys]) + # yaxis := Array of [minimum, maximum, stepsize] + if args[0].kind_of?(Array) + @yaxis = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @yaxis = args.shift + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + array2tk_list(@yaxis)) + end + private :_create_chart + + def __destroy_hook__ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path) + } + end + end + ############################ class Timechart < Tk::Canvas include ChartMethod @@ -723,46 +1215,60 @@ module Tk::Tcllib::Plotchart private :_create_chart def period(txt, time_begin, time_end, col=None) - tk_call_without_enc(@chart, 'period', txt, time_begin, time_end, col) + tk_call(@chart, 'period', txt, time_begin, time_end, col) self end def milestone(txt, time, col=None) - tk_call_without_enc(@chart, 'milestone', txt, time, col) + tk_call(@chart, 'milestone', txt, time, col) self end def vertline(txt, time) - tk_call_without_enc(@chart, 'vertline', txt, time) + tk_call(@chart, 'vertline', txt, time) + self + end + + def hscroll=(scr) + tk_call_without_enc(@chart, 'hscroll', scr) + scr + end + def hscroll(scr) + tk_call_without_enc(@chart, 'hscroll', scr) + self + end + + def vscroll=(scr) + tk_call_without_enc(@chart, 'vscroll', scr) + scr + end + def vscroll(scr) + tk_call_without_enc(@chart, 'vscroll', scr) self end end ############################ - class Gnattchart < Tk::Canvas + class Ganttchart < Tk::Canvas include ChartMethod TkCommandNames = [ 'canvas'.freeze, - '::Plotchart::createGnattchart'.freeze + '::Plotchart::createGanttchart'.freeze ].freeze def initialize(*args) # args := ([parent,] time_begin, time_end, items [, text_width] [, keys]) # time_begin := String of time format (e.g. "1 january 2004") # time_end := String of time format (e.g. "1 january 2004") - # items := Expected/maximum number of items - # ( This determines the vertical spacing. ) + # args := Expected/maximum number of items + # ( This determines the vertical spacing. ), + # Expected/maximum width of items, + # Option Hash ( { key=>value, ... } ) if args[0].kind_of?(String) @time_begin = args.shift @time_end = args.shift - @items = args.shift - - if args[0].kind_of?(Fixnum) - @text_width = args.shift - else - @text_width = None - end + @args = args super(*args) # create canvas widget else @@ -770,13 +1276,7 @@ module Tk::Tcllib::Plotchart @time_begin = args.shift @time_end = args.shift - @items = args.shift - - if args[0].kind_of?(Fixnum) - @text_width = args.shift - else - @text_width = None - end + @args = args if parent.kind_of?(Tk::Canvas) @path = parent.path @@ -790,25 +1290,25 @@ module Tk::Tcllib::Plotchart def _create_chart p self.class::TkCommandNames[1] if $DEBUG - tk_call_without_enc(self.class::TkCommandNames[1], @path, - @time_begin, @time_end, @items, @text_width) + tk_call(self.class::TkCommandNames[1], @path, + @time_begin, @time_end, *args) end private :_create_chart def task(txt, time_begin, time_end, completed=0.0) - list(tk_call_without_enc(@chart, 'task', txt, time_begin, time_end, - completed)).collect!{|id| + list(tk_call(@chart, 'task', txt, time_begin, time_end, + completed)).collect!{|id| TkcItem.id2obj(self, id) } end def milestone(txt, time, col=None) - tk_call_without_enc(@chart, 'milestone', txt, time, col) + tk_call(@chart, 'milestone', txt, time, col) self end def vertline(txt, time) - tk_call_without_enc(@chart, 'vertline', txt, time) + tk_call(@chart, 'vertline', txt, time) self end @@ -816,23 +1316,41 @@ module Tk::Tcllib::Plotchart from_task = array2tk_list(from_task) if from_task.kind_of?(Array) to_task = array2tk_list(to_task) if to_task.kind_of?(Array) - tk_call_without_enc(@chart, 'connect', from_task, to_task) + tk_call(@chart, 'connect', from_task, to_task) self end def summary(txt, tasks) tasks = array2tk_list(tasks) if tasks.kind_of?(Array) - tk_call_without_enc(@chart, 'summary', tasks) + tk_call(@chart, 'summary', tasks) self end def color_of_part(keyword, newcolor) - tk_call_without_enc(@chart, 'color', keyword, newcolor) + tk_call(@chart, 'color', keyword, newcolor) self end def font_of_part(keyword, newfont) - tk_call_without_enc(@chart, 'font', keyword, newfont) + tk_call(@chart, 'font', keyword, newfont) + self + end + + def hscroll=(scr) + tk_call_without_enc(@chart, 'hscroll', scr) + scr + end + def hscroll(scr) + tk_call_without_enc(@chart, 'hscroll', scr) + self + end + + def vscroll=(scr) + tk_call_without_enc(@chart, 'vscroll', scr) + scr + end + def vscroll(scr) + tk_call_without_enc(@chart, 'vscroll', scr) self end end @@ -841,7 +1359,7 @@ module Tk::Tcllib::Plotchart class PlotSeries < TkObject SeriesID_TBL = TkCore::INTERP.create_table - (Series_ID = ['series'.freeze, '00000'.taint]).instance_eval{ + (Series_ID = ['series'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze diff --git a/ext/tk/lib/tkextlib/tcllib/scrolledwindow.rb b/ext/tk/lib/tkextlib/tcllib/scrolledwindow.rb new file mode 100644 index 0000000000..c9488b4686 --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/scrolledwindow.rb @@ -0,0 +1,57 @@ +# +# tkextlib/tcllib/scrolledwindow.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * scrolledwindow widget +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('widget::scrolledwindow', '1.2') +TkPackage.require('widget::scrolledwindow') + +module Tk::Tcllib + module Widget + class Scrolledwindow < Tk::Tile::TFrame + PACKAGE_NAME = 'widget::scrolledwindow'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('widget::scrolledwindow') + rescue + '' + end + end + end + ScrolledWindow = Scrolledwindow + end +end + +class Tk::Tcllib::Widget::ScrolledWindow + TkCommandNames = ['::widget::scrolledwindow'.freeze].freeze + + def create_self(keys) + if keys and keys != None + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self + + def getframe + window(tk_send_without_enc('getframe')) + end + alias get_frame getframe + + def setwidget(w) + window(tk_send_without_enc('setwidget', w)) + end + alias set_widget setwidget +end diff --git a/ext/tk/lib/tkextlib/tcllib/statusbar.rb b/ext/tk/lib/tkextlib/tcllib/statusbar.rb new file mode 100644 index 0000000000..46a4b9d8b6 --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/statusbar.rb @@ -0,0 +1,79 @@ +# +# tkextlib/tcllib/statusbar.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * statusbar widget +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('widget::statusbar', '1.2') +TkPackage.require('widget::statusbar') + +module Tk::Tcllib + module Widget + class Statusbar < Tk::Tile::TFrame + PACKAGE_NAME = 'widget::statusbar'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('widget::statusbar') + rescue + '' + end + end + end + end +end + +class Tk::Tcllib::Widget::Statusbar + TkCommandNames = ['::widget::statusbar'.freeze].freeze + + def __boolval_optkeys + super() << 'separator' << 'resize' << 'resizeseparator' + end + private :__boolval_optkeys + + def create_self(keys) + if keys and keys != None + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self + + def getframe + window(tk_send_without_enc('getframe')) + end + alias get_frame getframe + + def add(w, keys={}) + window(tk_send_without_enc('setwidget', *(hash_kv(keys)))) + end + + def remove(*wins) + tk_send_without_enc('remove', *wins) + self + end + + def remove_with_destroy(*wins) + tk_send_without_enc('remove', '-destroy', *wins) + self + end + + def delete(*wins) + tk_send_without_enc('delete', *wins) + self + end + + def items(pat=None) + tk_split_list(tk_send('items', pat)) + end +end diff --git a/ext/tk/lib/tkextlib/tcllib/swaplist.rb b/ext/tk/lib/tkextlib/tcllib/swaplist.rb index bb4c71cd5f..7698640534 100644 --- a/ext/tk/lib/tkextlib/tcllib/swaplist.rb +++ b/ext/tk/lib/tkextlib/tcllib/swaplist.rb @@ -33,7 +33,7 @@ end class Tk::Tcllib::Swaplist_Dialog TkCommandNames = ['::swaplist::swaplist'.freeze].freeze WidgetClassName = 'Swaplist'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def self.show(*args) dialog = self.new(*args) diff --git a/ext/tk/lib/tkextlib/tcllib/tablelist.rb b/ext/tk/lib/tkextlib/tcllib/tablelist.rb index efeb8fbbac..b40f7a5b8b 100644 --- a/ext/tk/lib/tkextlib/tcllib/tablelist.rb +++ b/ext/tk/lib/tkextlib/tcllib/tablelist.rb @@ -10,7 +10,8 @@ require 'tkextlib/tcllib.rb' # check Tile extension :: If already loaded, use tablelist_tile. unless defined? Tk::Tcllib::Tablelist_usingTile - Tk::Tcllib::Tablelist_usingTile = TkPackage.provide('tile') + Tk::Tcllib::Tablelist_usingTile = + TkPackage.provide('tile') || TkPackage.provide('Ttk') end if Tk::Tcllib::Tablelist_usingTile @@ -20,8 +21,8 @@ if Tk::Tcllib::Tablelist_usingTile else # without Tile - # TkPackage.require('Tablelist', '4.2') - TkPackage.require('Tablelist') + # TkPackage.require('tablelist', '4.2') + TkPackage.require('tablelist') require 'tkextlib/tcllib/tablelist_core' end diff --git a/ext/tk/lib/tkextlib/tcllib/tablelist_core.rb b/ext/tk/lib/tkextlib/tcllib/tablelist_core.rb index c99f62f2dc..850e75d845 100644 --- a/ext/tk/lib/tkextlib/tcllib/tablelist_core.rb +++ b/ext/tk/lib/tkextlib/tcllib/tablelist_core.rb @@ -67,6 +67,9 @@ module Tk::Tcllib::TablelistItemConfig [self.path, mixed_id[0] + 'configure', _to_idx(mixed_id[1])] end + def cell_cget_tkstring(tagOrId, option) + itemcget_tkstring(['cell', tagOrId], option) + end def cell_cget(tagOrId, option) itemcget(['cell', tagOrId], option) end @@ -82,12 +85,16 @@ module Tk::Tcllib::TablelistItemConfig def current_cell_configinfo(tagOrId, slot=nil) current_itemconfiginfo(['cell', tagOrId], slot) end + alias cellcget_tkstring cell_cget_tkstring alias cellcget cell_cget alias cellcget_strict cell_cget_strict alias cellconfigure cell_configure alias cellconfiginfo cell_configinfo alias current_cellconfiginfo current_cell_configinfo + def column_cget_tkstring(tagOrId, option) + itemcget_tkstring(['column', tagOrId], option) + end def column_cget(tagOrId, option) itemcget(['column', tagOrId], option) end @@ -103,12 +110,16 @@ module Tk::Tcllib::TablelistItemConfig def current_column_configinfo(tagOrId, slot=nil) current_itemconfiginfo(['column', tagOrId], slot) end + alias columncget_tkstring column_cget_tkstring alias columncget column_cget alias columncget_strict column_cget_strict alias columnconfigure column_configure alias columnconfiginfo column_configinfo alias current_columnconfiginfo current_column_configinfo + def row_cget_tkstring(tagOrId, option) + itemcget_tkstring(['row', tagOrId], option) + end def row_cget(tagOrId, option) itemcget(['row', tagOrId], option) end @@ -124,13 +135,14 @@ module Tk::Tcllib::TablelistItemConfig def current_row_configinfo(tagOrId, slot=nil) current_itemconfiginfo(['row', tagOrId], slot) end + alias rowcget_tkstring row_cget_tkstring alias rowcget row_cget alias rowcget_strict row_cget_strict alias rowconfigure row_configure alias rowconfiginfo row_configinfo alias current_rowconfiginfo current_row_configinfo - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo end @@ -140,7 +152,7 @@ class Tk::Tcllib::Tablelist TkCommandNames = ['::tablelist::tablelist'.freeze].freeze WidgetClassName = 'Tablelist'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def create_self(keys) if keys and keys != None @@ -165,16 +177,16 @@ class Tk::Tcllib::Tablelist private :__strval_optkeys def __boolval_optkeys - super() + [ + super() - ['takefocus'] + [ 'forceeditendcommand', 'movablecolumns', 'movablerows', - 'protecttitlecolumns', 'resizablecolumns', + 'protecttitlecolumns', 'resizablecolumns', 'setfocus', 'showarrow', 'showlabels', 'showseparators' ] end private :__boolval_optkeys def __listval_optkeys - super() + ['columns'] + super() + ['columns', 'columntitles'] end private :__listval_optkeys @@ -186,7 +198,21 @@ class Tk::Tcllib::Tablelist def __val2ruby_optkeys # { key=>proc, ... } # The method is used to convert a opt-value to a ruby's object. # When get the value of the option "key", "proc.call(value)" is called. - super().update('stretch'=>proc{|v| (v == 'all')? v: simplelist(v)}) + super().update('stretch'=>proc{|v| + (v == 'all')? v: simplelist(v) + }, + 'takefocus'=>proc{|v| + case v + when '1' + true + when '0' + false + when '' + nil + else # cmd + tk_tcl2ruby(cmd) + end + }) end private :__val2ruby_optkeys @@ -196,6 +222,18 @@ class Tk::Tcllib::Tablelist # That is, "-#{key} #{proc.call(value)}". super().update('stretch'=>proc{|v| (v.kind_of?(Array))? v.collect{|e| _to_idx(e)}: v + }, + 'takefocus'=>proc{|v| + case v + when true + '1' + when false + '0' + when nil + '' + else + _get_eval_string(v) + end }) end private :__ruby2val_optkeys @@ -211,14 +249,15 @@ class Tk::Tcllib::Tablelist if id[0] == 'cell' super(id) + ['title'] else - super(id) - ['text'] + ['title'] + super(id) - ['text'] + ['title', 'name'] end end private :__item_strval_optkeys def __item_boolval_optkeys(id) super(id) + [ - 'editable', 'hide', 'resizable', 'showarrow', 'stretchable', + 'changesnipside', 'editable', 'hide', 'resizable', 'selectable', + 'showarrow', 'showlinenumbers', 'stretchable', 'stretchwindow', 'wrap' ] end private :__item_boolval_optkeys @@ -286,6 +325,23 @@ class Tk::Tcllib::Tablelist end alias cancelediting cancel_editing + def get_cellattrib(name=nil) + if name && name != None + tk_send('cellattrib', name) + else + ret = [] + lst = simplelist(tk_send('cellattrib')) + until lst.empty? + ret << ( [lst.shift] << lst.shift ) + end + ret + end + end + def set_cellattrib(*args) + tk_send('cellattrib', *(args.flatten)) + self + end + def cellindex(idx) _from_idx(tk_send('cellindex', _to_idx(idx))) end @@ -321,6 +377,23 @@ class Tk::Tcllib::Tablelist self end + def get_columnattrib(name=nil) + if name && name != None + tk_send('columnattrib', name) + else + ret = [] + lst = simplelist(tk_send('columnattrib')) + until lst.empty? + ret << ( [lst.shift] << lst.shift ) + end + ret + end + end + def set_columnattrib(*args) + tk_send('columnattrib', *(args.flatten)) + self + end + def columncount number(tk_send('columncount')) end @@ -329,6 +402,83 @@ class Tk::Tcllib::Tablelist number(tk_send('columnindex', _to_idx(idx))) end + def columnwidth(idx, opt=nil) + if opt + number(tk_send('columnwidth', _to_idx(idx), "-#{opt}")) + else + number(tk_send('columnwidth', _to_idx(idx))) + end + end + def requested_columnwidth(idx) + columnwidth(idx, 'requested') + end + def stretched_columnwidth(idx) + columnwidth(idx, 'stretched') + end + def total_columnwidth(idx) + columnwidth(idx, 'total') + end + + def configcelllist(lst) # lst ==> [idx, opt, val, idx, opt, val, ...] + ary = [] + lst.slice(3){|idx, opt, val| + ary << _to_idx(idx) << "-#{opt}" << val + } + tk_send('configcelllist', ary) + self + end + alias config_celllist configcelllist + + def configcells(*args) # args ==> idx, opt, val, idx, opt, val, ... + ary = [] + args.slice(3){|idx, opt, val| + ary << _to_idx(idx) << "-#{opt}" << val + } + tk_send('configcells', *ary) + self + end + alias config_cells configcells + + def configcolumnlist(lst) # lst ==> [idx, opt, val, idx, opt, val, ...] + ary = [] + lst.slice(3){|idx, opt, val| + ary << _to_idx(idx) << "-#{opt}" << val + } + tk_send('configcolumnlist', ary) + self + end + alias config_columnlist configcolumnlist + + def configcolumns(*args) # args ==> idx, opt, val, idx, opt, val, ... + ary = [] + args.slice(3){|idx, opt, val| + ary << _to_idx(idx) << "-#{opt}" << val + } + tk_send('configcolumns', *ary) + self + end + alias config_columns configcolumns + + def configrowlist(lst) # lst ==> [idx, opt, val, idx, opt, val, ...] + ary = [] + lst.slice(3){|idx, opt, val| + ary << _to_idx(idx) << "-#{opt}" << val + } + tk_send('configrowlist', ary) + self + end + alias config_rowlist configrowlist + + def configrows(*args) # args ==> idx, opt, val, idx, opt, val, ... + ary = [] + args.slice(3){|idx, opt, val| + ary << _to_idx(idx) << "-#{opt}" << val + } + tk_send('configrows', *ary) + self + end + alias config_rows configrows + def containing(y) idx = num_or_str(tk_send('containing', y)) (idx.kind_of?(Fixnum) && idx < 0)? nil: idx @@ -392,6 +542,10 @@ class Tk::Tcllib::Tablelist end alias editcell edit_cell + def editwintag + TkBindTag.new_by_name(tk_send('editwintag')) + end + def editwinpath window(tk_send('editwinpath')) end @@ -412,6 +566,11 @@ class Tk::Tcllib::Tablelist end alias finishediting finish_editing + def formatinfo + key, row, col = simplelist(tk_send('formatinfo')) + [key, number(row), number(col)] + end + def get(first, last=nil) if first.kind_of?(Array) simplelist(tk_send('get', first.collect{|idx| _to_idx(idx)})).collect!{|elem| simplelist(elem) } @@ -455,6 +614,22 @@ class Tk::Tcllib::Tablelist end alias getkeys get_keys + def has_attrib?(name) + bool(tk_send('hasattrib', name)) + end + + def has_cellattrib?(idx, name) + bool(tk_send('hascellattrib', _to_idx(idx), name)) + end + + def has_columnattrib?(idx, name) + bool(tk_send('hascolumnattrib', _to_idx(idx), name)) + end + + def has_rowattrib?(idx, name) + bool(tk_send('hasrowattrib', _to_idx(idx), name)) + end + def imagelabelpath(idx) window(tk_send('imagelabelpath', _to_idx(idx))) end @@ -486,6 +661,16 @@ class Tk::Tcllib::Tablelist end alias insertlist insert_list + def is_elem_snipped?(cellidx, tkvar) + bool(tk_send('iselemsnipped', _to_idx(cellidx), tkvar)) + end + alias elem_snipped? is_elem_snipped? + + def is_title_snipped?(colidx, tkvar) + bool(tk_send('istitlesnipped', _to_idx(colidx), tkvar)) + end + alias title_snipped? is_title_snipped? + def itemlistvar TkVarAccess.new(tk_send('itemlistvar')) end @@ -498,6 +683,10 @@ class Tk::Tcllib::Tablelist simplelist(tk_send('labels')) end + def labeltag + TkBindTag.new_by_name(tk_send('labeltag')) + end + def move(src, target) tk_send('move', _to_idx(src), _to_idx(target)) self @@ -535,6 +724,23 @@ class Tk::Tcllib::Tablelist end alias resetsortinfo reset_sortinfo + def get_rowattrib(name=nil) + if name && name != None + tk_send('rowattrib', name) + else + ret = [] + lst = simplelist(tk_send('rowattrib')) + until lst.empty? + ret << ( [lst.shift] << lst.shift ) + end + ret + end + end + def set_rowattrib(*args) + tk_send('rowattrib', *(args.flatten)) + self + end + def scan_mark(x, y) tk_send('scan', 'mark', x, y) self @@ -633,7 +839,22 @@ class Tk::Tcllib::Tablelist self end - DEFAULT_sortByColumn_cmd = '::tablelist::sortByColumn' + + # default of 'labelcommand' option + DEFAULT_labelcommand_value = + DEFAULT_sortByColumn_cmd = '::tablelist::sortByColumn' + + # default of 'labelcommand2' option + DEFAULT_labelcommand2_value = + DEFAULT_addToSortColumns_cmd = '::tablelist::addToSortColumns' + + def sortByColumn_with_event_generate(idx) + tk_call('::tablelist::sortByColumn', @path, _to_idx(idx)) + end + + def addToSortColumns_with_event_generate(idx) + tk_call('::tablelist::addToSortColumns', @path, _to_idx(idx)) + end def sort_by_column(idx, order=nil) if order @@ -659,15 +880,49 @@ class Tk::Tcllib::Tablelist self end + def sort_by_columnlist(idxlist, orderlist=None) + # orderlist :: list of 'increasing' or 'decreasing' + tk_send('sortbycolumnlist', idxlist.map{|idx| _to_idx(idx)}, orderlist) + self + end + def sortcolumn idx = num_or_str(tk_send('sortcolum')) (idx.kind_of?(Fixnum) && idx < 0)? nil: idx end + def sortcolumnlist + simplelist(tk_send('sortcolumlist')).map{|col| num_or_str(col)} + end + def sortorder tk_send('sortorder') end + def sortorderlist + simplelist(tk_send('sortorderlist')) + end + + def toggle_columnhide(first, last=nil) + if first.kind_of?(Array) + tk_send('togglecolumnhide', first.collect{|idx| _to_idx(idx)}) + else + first = _to_idx(first) + last = (last)? _to_idx(last): first + tk_send('togglecolumnhide', first, last) + end + end + + def toggle_rowhide(first, last=nil) + if first.kind_of?(Array) + tk_send('togglerowhide', first.collect{|idx| _to_idx(idx)}) + else + first = _to_idx(first) + last = (last)? _to_idx(last): first + tk_send('togglerowhide', first, last) + end + end + def toggle_visibility(first, last=nil) if first.kind_of?(Array) tk_send('togglevisibility', first.collect{|idx| _to_idx(idx)}) @@ -680,6 +935,26 @@ class Tk::Tcllib::Tablelist end alias togglevisibility toggle_visibility + def unset_attrib(name) + tk_send('unsetattrib', name) + self + end + + def unset_cellattrib(idx, name) + tk_send('unsetcellattrib', _to_idx(idx), name) + self + end + + def unset_columnattrib(idx, name) + tk_send('unsetcolumnattrib', _to_idx(idx), name) + self + end + + def unset_rowattrib(idx, name) + tk_send('unsetrowattrib', _to_idx(idx), name) + self + end + def windowpath(idx) window(tk_send('windowpath', _to_idx(idx))) end @@ -692,6 +967,11 @@ class << Tk::Tcllib::Tablelist window(Tk.tk_call('::tablelist::getTablelistPath', descendant)) end + def getTablelistColumn(descendant) + num_or_str(Tk.tk_call('::tablelist::getTablelistColumn', headerlabel)) + end + + def convEventFields(descendant, x, y) window(Tk.tk_call('::tablelist::convEventFields', descendant, x, y)) end @@ -767,6 +1047,16 @@ class << Tk::Tcllib::Tablelist Tk.tk_call('::tablelist::addTimeMentry', format, separator, gmt, name) end + def addDateTimeMentry(format, date_sep, time_sep, gmt=false, name=None) + if gmt && gmt != None + gmt = '-gmt' + else + gmt = None + end + Tk.tk_call('::tablelist::addDateTimeMentry', + format, date_sep, time_sep, gmt, name) + end + def addFixedPointMentry(count1, count2, comma=false, name=None) if comma && comma != None comma = '-comma' diff --git a/ext/tk/lib/tkextlib/tcllib/tablelist_tile.rb b/ext/tk/lib/tkextlib/tcllib/tablelist_tile.rb index 0cb4eb735d..0a1458415e 100644 --- a/ext/tk/lib/tkextlib/tcllib/tablelist_tile.rb +++ b/ext/tk/lib/tkextlib/tcllib/tablelist_tile.rb @@ -9,7 +9,7 @@ require 'tk' require 'tkextlib/tcllib.rb' # TkPackage.require('tablelist_tile', '4.2') -TkPackage.require('Tablelist_tile') +TkPackage.require('tablelist_tile') unless defined? Tk::Tcllib::Tablelist_usingTile Tk::Tcllib::Tablelist_usingTile = true @@ -19,6 +19,24 @@ requrie 'tkextlib/tcllib/tablelist_core' module Tk module Tcllib + class Tablelist + # commands related to tile Themems + def self.set_theme(theme) + Tk.tk_call('::tablelist::setTheme', theme) + end + + def self.get_current_theme + Tk.tk_call('::tablelist::getCurrentTheme') + end + + def self.get_theme_list + TkComm.simplelist(Tk.tk_call('::tablelist::getThemes')) + end + def self.set_theme_defaults + Tk.tk_call('::tablelist::setThemeDefaults') + end + end + Tablelist_Tile = Tablelist TableList_Tile = Tablelist end diff --git a/ext/tk/lib/tkextlib/tcllib/toolbar.rb b/ext/tk/lib/tkextlib/tcllib/toolbar.rb new file mode 100644 index 0000000000..6eae4eb3e1 --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/toolbar.rb @@ -0,0 +1,175 @@ +# +# tkextlib/tcllib/toolbar.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * toolbar widget +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('widget::toolbar', '1.2') +TkPackage.require('widget::toolbar') + +module Tk::Tcllib + module Widget + class Toolbar < TkWindow + PACKAGE_NAME = 'widget::toolbar'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('widget::toolbar') + rescue + '' + end + end + end + + module ToolbarItemConfig + include TkItemConfigMethod + end + end +end + + +class Tk::Tcllib::Widget::ToolbarItem < TkObject + include TkTreatTagFont + + ToolbarItemID_TBL = TkCore::INTERP.create_table + + TkCore::INTERP.init_ip_env{ + TTagID_TBL.mutex.synchronize{ TTagID_TBL.clear } + } + + def ToolbarItem.id2obj(tbar, id) + tpath = tbar.path + ToolbarItemID_TBL.mutex.synchronize{ + if ToolbarItemID_TBL[tpath] + ToolbarItemID_TBL[tpath][id]? ToolbarItemID_TBL[tpath][id]: id + else + id + end + } + end + + def initaialize(parent, *args) + @parent = @t = parent + @tpath = parent.path + + @path = @id = @t.tk_send('add', *args) + # A same id is rejected by the Tcl function. + + ToolbarItemID_TBL.mutex.synchronize{ + ToolbarItemID_TBL[@id] = self + ToolbarItemID_TBL[@tpath] = {} unless ToolbarItemID_TBL[@tpath] + ToolbarItemID_TBL[@tpath][@id] = self + } + end + + def [](key) + cget key + end + + def []=(key,val) + configure key, val + val + end + + def cget_tkstring(option) + @t.itemcget_tkstring(@id, option) + end + def cget(option) + @t.itemcget(@id, option) + end + def cget_strict(option) + @t.itemcget_strict(@id, option) + end + + def configure(key, value=None) + @t.itemconfigure(@id, key, value) + self + end + + def configinfo(key=nil) + @t.itemconfiginfo(@id, key) + end + + def current_configinfo(key=nil) + @t.current_itemconfiginfo(@id, key) + end + + def delete + @t.delete(@id) + end + + def itemid + @t.itemid(@id) + end + + def remove + @t.remove(@id) + end + def remove_with_destroy + @t.remove_with_destroy(@id) + end +end + +class Tk::Tcllib::Widget::Toolbar + include Tk::Tcllib::Widget::ToolbarItemConfig + + TkCommandNames = ['::widget::toolbar'.freeze].freeze + + def __destroy_hook__ + Tk::Tcllib::Widget::ToolbarItem::ToolbarItemID_TBL.mutex.synchronize{ + Tk::Tcllib::Widget::ToolbarItem::ToolbarItemID_TBL.delete(@path) + } + end + + def create_self(keys) + if keys and keys != None + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self + + def getframe + window(tk_send('getframe')) + end + alias get_frame getframe + + def add(*args) + Tk::Tcllib::Widget::Toolbar.new(self, *args) + end + + def itemid(item) + window(tk_send('itemid')) + end + + def items(pattern) + tk_split_simplelist(tk_send('items', pattern)).map{|id| + Tk::Tcllib::Widget::ToolbarItem.id2obj(self, id) + } + end + + def remove(*items) + tk_send('remove', *items) + self + end + + def remove_with_destroy(*items) + tk_send('remove', '-destroy', *items) + self + end + + def delete(*items) + tk_send('delete', *items) + self + end +end diff --git a/ext/tk/lib/tkextlib/tcllib/tooltip.rb b/ext/tk/lib/tkextlib/tcllib/tooltip.rb index 73b7df0c22..070e63a7b5 100644 --- a/ext/tk/lib/tkextlib/tcllib/tooltip.rb +++ b/ext/tk/lib/tkextlib/tcllib/tooltip.rb @@ -34,6 +34,8 @@ module Tk::Tcllib::Tooltip extend TkCore WidgetClassName = 'Tooltip'.freeze + WidgetClassNames[WidgetClassName] ||= self + def self.database_classname self::WidgetClassName end @@ -64,6 +66,13 @@ module Tk::Tcllib::Tooltip self.delay(millisecs) end + def self.fade? + bool(tk_call_without_enc('::tooltip::tooltip', 'fade')) + end + def self.fade(mode) + tk_call_without_enc('::tooltip::tooltip', 'fade', mode) + end + def self.disable tk_call_without_enc('::tooltip::tooltip', 'disable') false @@ -86,7 +95,7 @@ module Tk::Tcllib::Tooltip else args = msg end - tk_call_without_enc('::tooltip::tooltip', widget.path, *args) + tk_call('::tooltip::tooltip', widget.path, *args) end def self.erase(widget) diff --git a/ext/tk/lib/tkextlib/tcllib/widget.rb b/ext/tk/lib/tkextlib/tcllib/widget.rb index ed69f67ce6..57fdf7a575 100644 --- a/ext/tk/lib/tkextlib/tcllib/widget.rb +++ b/ext/tk/lib/tkextlib/tcllib/widget.rb @@ -26,10 +26,41 @@ module Tk::Tcllib '' end end + + #--- followings may be private functions of tklib + def self.isa(compare_as, *args) + begin + return Tk.tk_call('::widget::isa', compare_as, *args) + rescue => e + if TkComm.bool(Tk.tk_call('info','command','::widget::isa')) || + ! TkComm.bool(Tk.tk_call('info','command','::widget::validate')) + fail e + end + end + Tk.tk_call('::widget::validate', compare_as, *args) + end + def self.validate(compare_as, *args) + begin + return Tk.tk_call('::widget::validate', compare_as, *args) + rescue => e + if TkComm.bool(Tk.tk_call('info','command','::widget::validate')) || + ! TkComm.bool(Tk.tk_call('info','command','::widget::isa')) + fail e + end + end + Tk.tk_call('::widget::isa', compare_as, *args) + end end end module Tk::Tcllib::Widget + TkComm::TkExtlibAutoloadModule.unshift(self) + + autoload :Calendar, 'tkextlib/tcllib/calendar' + + autoload :Canvas_Sqmap, 'tkextlib/tcllib/canvas_sqmap' + autoload :Canvas_Zoom, 'tkextlib/tcllib/canvas_zoom' + autoload :Dialog, 'tkextlib/tcllib/dialog' autoload :Panelframe, 'tkextlib/tcllib/panelframe' @@ -45,4 +76,7 @@ module Tk::Tcllib::Widget autoload :Superframe, 'tkextlib/tcllib/superframe' autoload :SuperFrame, 'tkextlib/tcllib/superframe' + + autoload :Toolbar, 'tkextlib/tcllib/toolbar' + autoload :ToolbarItem, 'tkextlib/tcllib/toolbar' end diff --git a/ext/tk/lib/tkextlib/tile.rb b/ext/tk/lib/tkextlib/tile.rb index 09cf49faa6..6c11e212ae 100644 --- a/ext/tk/lib/tkextlib/tile.rb +++ b/ext/tk/lib/tkextlib/tile.rb @@ -18,10 +18,37 @@ require 'tkextlib/tile/setup.rb' # TkPackage.require('tile', '0.7') if Tk::TK_MAJOR_VERSION > 8 || (Tk::TK_MAJOR_VERSION == 8 && Tk::TK_MINOR_VERSION >= 5) - TkPackage.require('tile') # for compatibility (version check of 'tile') - verstr = TkPackage.require('Ttk') + begin + TkPackage.require('tile') # for compatibility (version check of 'tile') + rescue RuntimeError + # ignore, even if cannot find package 'tile' + end + pkgname = 'Ttk' else - verstr = TkPackage.require('tile') + pkgname = 'tile' +end + +begin + verstr = TkPackage.require(pkgname) +rescue RuntimeError + # define dummy methods + module Tk + module Tile + CANNOT_FIND_PACKAGE = true + def self.const_missing(sym) + TkPackage.require(PACKAGE_NAME) + end + def self.method_missing(*args) + TkPackage.require(PACKAGE_NAME) + end + end + end + Tk.__cannot_find_tk_package_for_widget_set__(:Ttk, pkgname) + if pkgname == 'Ttk' + verstr = Tk::TK_PATCHLEVEL # dummy + else + verstr = '0.7' # dummy + end end ver = verstr.split('.') @@ -404,6 +431,9 @@ module Tk autoload :TSeparator, 'tkextlib/tile/tseparator' autoload :Separator, 'tkextlib/tile/tseparator' + autoload :TSpinbox, 'tkextlib/tile/tspinbox' + autoload :Spinbox, 'tkextlib/tile/tspinbox' + autoload :TSquare, 'tkextlib/tile/tsquare' autoload :Square, 'tkextlib/tile/tsquare' diff --git a/ext/tk/lib/tkextlib/tile/dialog.rb b/ext/tk/lib/tkextlib/tile/dialog.rb index ef2d1fe577..b112e6152b 100644 --- a/ext/tk/lib/tkextlib/tile/dialog.rb +++ b/ext/tk/lib/tkextlib/tile/dialog.rb @@ -12,6 +12,12 @@ module Tk end end +begin + TkPackage.require('ttk::dialog') # this may be required. +rescue RuntimeError + # ignore +end + class Tk::Tile::Dialog TkCommandNames = ['::ttk::dialog'.freeze].freeze diff --git a/ext/tk/lib/tkextlib/tile/sizegrip.rb b/ext/tk/lib/tkextlib/tile/sizegrip.rb index c5068919a4..d7da0a4075 100644 --- a/ext/tk/lib/tkextlib/tile/sizegrip.rb +++ b/ext/tk/lib/tkextlib/tile/sizegrip.rb @@ -13,17 +13,20 @@ module Tk end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Sizegrip, :TkSizegrip, :TkSizeGrip) - - class Tk::Tile::SizeGrip < TkWindow include Tk::Tile::TileWidget TkCommandNames = ['::ttk::sizegrip'.freeze].freeze WidgetClassName = 'TSizegrip'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def self.style(*args) [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Sizegrip, +# :TkSizegrip, :TkSizeGrip) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/sizegrip.rb', + :Ttk, Tk::Tile::Sizegrip, + :TkSizegrip, :TkSizeGrip) diff --git a/ext/tk/lib/tkextlib/tile/style.rb b/ext/tk/lib/tkextlib/tile/style.rb index 26d79d378b..f38deda503 100644 --- a/ext/tk/lib/tkextlib/tile/style.rb +++ b/ext/tk/lib/tkextlib/tile/style.rb @@ -233,6 +233,8 @@ class << Tk::Tile::Style def element_create(name, type, *args) if type == 'image' || type == :image element_create_image(name, *args) + elsif type == 'vsapi' || type == :vsapi + element_create_vsapi(name, *args) else tk_call(TkCommandNames[0], 'element', 'create', name, type, *args) end @@ -279,6 +281,24 @@ class << Tk::Tile::Style end end + def element_create_vsapi(name, class_name, part_id, *args) + # supported on Tcl/Tk 8.6 or later + + # argument check + if (state_map = args.shift || None) + if state_map.kind_of?(Hash) + opts = _symbolkey2str(state_map) + state_map = None + end + end + opts = args.shift || None + fail ArgumentError, "too many arguments" unless args.empty? + + # define a Microsoft Visual Styles element + tk_call(TkCommandNames[0], 'element', 'create', name, 'vsapi', + class_name, part_id, state_map, opts) + end + def element_names() list(tk_call(TkCommandNames[0], 'element', 'names')) end diff --git a/ext/tk/lib/tkextlib/tile/tbutton.rb b/ext/tk/lib/tkextlib/tile/tbutton.rb index 5d7db10fe9..c852024842 100644 --- a/ext/tk/lib/tkextlib/tile/tbutton.rb +++ b/ext/tk/lib/tkextlib/tile/tbutton.rb @@ -13,9 +13,6 @@ module Tk end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Button, :TkButton) - - class Tk::Tile::TButton < Tk::Button include Tk::Tile::TileWidget @@ -25,9 +22,13 @@ class Tk::Tile::TButton < Tk::Button TkCommandNames = ['::tbutton'.freeze].freeze end WidgetClassName = 'TButton'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def self.style(*args) [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Button, :TkButton) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tbutton.rb', + :Ttk, Tk::Tile::Button, :TkButton) diff --git a/ext/tk/lib/tkextlib/tile/tcheckbutton.rb b/ext/tk/lib/tkextlib/tile/tcheckbutton.rb index ca79d89e58..01751ede0f 100644 --- a/ext/tk/lib/tkextlib/tile/tcheckbutton.rb +++ b/ext/tk/lib/tkextlib/tile/tcheckbutton.rb @@ -15,10 +15,6 @@ module Tk end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Checkbutton, - :TkCheckbutton, :TkCheckButton) - - class Tk::Tile::TCheckButton < Tk::CheckButton include Tk::Tile::TileWidget @@ -28,9 +24,15 @@ class Tk::Tile::TCheckButton < Tk::CheckButton TkCommandNames = ['::tcheckbutton'.freeze].freeze end WidgetClassName = 'TCheckbutton'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def self.style(*args) [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Checkbutton, +# :TkCheckbutton, :TkCheckButton) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tcheckbutton.rb', + :Ttk, Tk::Tile::Checkbutton, + :TkCheckbutton, :TkCheckButton) diff --git a/ext/tk/lib/tkextlib/tile/tcombobox.rb b/ext/tk/lib/tkextlib/tile/tcombobox.rb index b64372f1c9..b5ab827e2d 100644 --- a/ext/tk/lib/tkextlib/tile/tcombobox.rb +++ b/ext/tk/lib/tkextlib/tile/tcombobox.rb @@ -13,9 +13,6 @@ module Tk end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Combobox, :TkCombobox) - - class Tk::Tile::TCombobox < Tk::Tile::TEntry include Tk::Tile::TileWidget @@ -25,7 +22,7 @@ class Tk::Tile::TCombobox < Tk::Tile::TEntry TkCommandNames = ['::tcombobox'.freeze].freeze end WidgetClassName = 'TCombobox'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __boolval_optkeys super() << 'exportselection' @@ -52,3 +49,7 @@ class Tk::Tile::TCombobox < Tk::Tile::TEntry tk_send('set', val) end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Combobox, :TkCombobox) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tcombobox.rb', + :Ttk, Tk::Tile::Combobox, :TkCombobox) diff --git a/ext/tk/lib/tkextlib/tile/tentry.rb b/ext/tk/lib/tkextlib/tile/tentry.rb index 0bea98dcd9..8d2633a774 100644 --- a/ext/tk/lib/tkextlib/tile/tentry.rb +++ b/ext/tk/lib/tkextlib/tile/tentry.rb @@ -13,9 +13,6 @@ module Tk end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Entry, :TkEntry) - - class Tk::Tile::TEntry < Tk::Entry include Tk::Tile::TileWidget @@ -25,7 +22,7 @@ class Tk::Tile::TEntry < Tk::Entry TkCommandNames = ['::tentry'.freeze].freeze end WidgetClassName = 'TEntry'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __optkey_aliases {:vcmd=>:validatecommand, :invcmd=>:invalidcommand} @@ -46,3 +43,7 @@ class Tk::Tile::TEntry < Tk::Entry [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Entry, :TkEntry) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tentry.rb', + :Ttk, Tk::Tile::Entry, :TkEntry) diff --git a/ext/tk/lib/tkextlib/tile/tframe.rb b/ext/tk/lib/tkextlib/tile/tframe.rb index 3b5f98bb6e..d6d4312628 100644 --- a/ext/tk/lib/tkextlib/tile/tframe.rb +++ b/ext/tk/lib/tkextlib/tile/tframe.rb @@ -13,9 +13,6 @@ module Tk end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Frame, :TkFrame) - - class Tk::Tile::TFrame < Tk::Frame include Tk::Tile::TileWidget @@ -25,9 +22,13 @@ class Tk::Tile::TFrame < Tk::Frame TkCommandNames = ['::tframe'.freeze].freeze end WidgetClassName = 'TFrame'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def self.style(*args) [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Frame, :TkFrame) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tframe.rb', + :Ttk, Tk::Tile::Frame, :TkFrame) diff --git a/ext/tk/lib/tkextlib/tile/tlabel.rb b/ext/tk/lib/tkextlib/tile/tlabel.rb index 7d074d3842..55b98acc68 100644 --- a/ext/tk/lib/tkextlib/tile/tlabel.rb +++ b/ext/tk/lib/tkextlib/tile/tlabel.rb @@ -13,9 +13,6 @@ module Tk end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Label, :TkLabel) - - class Tk::Tile::TLabel < Tk::Label include Tk::Tile::TileWidget @@ -25,9 +22,13 @@ class Tk::Tile::TLabel < Tk::Label TkCommandNames = ['::tlabel'.freeze].freeze end WidgetClassName = 'TLabel'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def self.style(*args) [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Label, :TkLabel) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tlabel.rb', + :Ttk, Tk::Tile::Label, :TkLabel) diff --git a/ext/tk/lib/tkextlib/tile/tlabelframe.rb b/ext/tk/lib/tkextlib/tile/tlabelframe.rb index 9f4a11990c..a34c98583f 100644 --- a/ext/tk/lib/tkextlib/tile/tlabelframe.rb +++ b/ext/tk/lib/tkextlib/tile/tlabelframe.rb @@ -15,10 +15,6 @@ module Tk end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Labelframe, - :TkLabelframe, :TkLabelFrame) - - class Tk::Tile::TLabelframe < Tk::Tile::TFrame include Tk::Tile::TileWidget @@ -28,9 +24,15 @@ class Tk::Tile::TLabelframe < Tk::Tile::TFrame TkCommandNames = ['::tlabelframe'.freeze].freeze end WidgetClassName = 'TLabelframe'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def self.style(*args) [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Labelframe, +# :TkLabelframe, :TkLabelFrame) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tlabelframe.rb', + :Ttk, Tk::Tile::Labelframe, + :TkLabelframe, :TkLabelFrame) diff --git a/ext/tk/lib/tkextlib/tile/tmenubutton.rb b/ext/tk/lib/tkextlib/tile/tmenubutton.rb index 5612fb47eb..1cf553ec8c 100644 --- a/ext/tk/lib/tkextlib/tile/tmenubutton.rb +++ b/ext/tk/lib/tkextlib/tile/tmenubutton.rb @@ -15,10 +15,6 @@ module Tk end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Menubutton, - :TkMenubutton, :TkMenuButton) - - class Tk::Tile::TMenubutton < Tk::Menubutton include Tk::Tile::TileWidget @@ -28,9 +24,15 @@ class Tk::Tile::TMenubutton < Tk::Menubutton TkCommandNames = ['::tmenubutton'.freeze].freeze end WidgetClassName = 'TMenubutton'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def self.style(*args) [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Menubutton, +# :TkMenubutton, :TkMenuButton) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tmenubutton.rb', + :Ttk, Tk::Tile::Menubutton, + :TkMenubutton, :TkMenuButton) diff --git a/ext/tk/lib/tkextlib/tile/tnotebook.rb b/ext/tk/lib/tkextlib/tile/tnotebook.rb index d02e05b211..9e27e2c1fd 100644 --- a/ext/tk/lib/tkextlib/tile/tnotebook.rb +++ b/ext/tk/lib/tkextlib/tile/tnotebook.rb @@ -13,9 +13,6 @@ module Tk end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Notebook, :TkNotebook) - - class Tk::Tile::TNotebook < TkWindow ################################ include TkItemConfigMethod @@ -46,8 +43,11 @@ class Tk::Tile::TNotebook < TkWindow alias tabconfiginfo itemconfiginfo alias current_tabconfiginfo current_itemconfiginfo + def tabcget_tkstring(tagOrId, option) + tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{option}")), false, true)[-1] + end def tabcget_strict(tagOrId, option) - tabconfigure(tagOrId, option)[-1] + tabconfiginfo(tagOrId, option)[-1] end def tabcget(tagOrId, option) unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ @@ -80,7 +80,7 @@ class Tk::Tile::TNotebook < TkWindow TkCommandNames = ['::tnotebook'.freeze].freeze end WidgetClassName = 'TNotebook'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def self.style(*args) [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') @@ -111,6 +111,10 @@ class Tk::Tile::TNotebook < TkWindow self end + def hide(idx) + tk_send('hide', idx) + end + def index(idx) number(tk_send('index', idx)) end @@ -137,3 +141,7 @@ class Tk::Tile::TNotebook < TkWindow list(tk_send('tabs')) end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Notebook, :TkNotebook) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tnotebook.rb', + :Ttk, Tk::Tile::Notebook, :TkNotebook) diff --git a/ext/tk/lib/tkextlib/tile/tpaned.rb b/ext/tk/lib/tkextlib/tile/tpaned.rb index aff6cac4bb..d6ad234559 100644 --- a/ext/tk/lib/tkextlib/tile/tpaned.rb +++ b/ext/tk/lib/tkextlib/tile/tpaned.rb @@ -13,10 +13,6 @@ module Tk end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Panedwindow, - :TkPanedwindow, :TkPanedWindow) - - class Tk::Tile::TPaned < TkWindow include Tk::Tile::TileWidget @@ -30,7 +26,7 @@ class Tk::Tile::TPaned < TkWindow TkCommandNames = ['::tpaned'.freeze].freeze end WidgetClassName = 'TPaned'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def self.style(*args) [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') @@ -66,6 +62,12 @@ class Tk::Tile::TPaned < TkWindow self end + def panecget_tkstring(pane, slot) + pane = _epath(pane) + tk_send_without_enc('pane', pane, "-#{slot}") + end + alias pane_cget_tkstring panecget_tkstring + def panecget_strict(pane, slot) pane = _epath(pane) tk_tcl2ruby(tk_send_without_enc('pane', pane, "-#{slot}")) @@ -221,11 +223,23 @@ class Tk::Tile::TPaned < TkWindow end alias current_pane_configinfo current_paneconfiginfo + def panes + tk_split_simplelist(tk_send_without_enc('panes')).map{|w| + (obj = window(w))? obj: w + } + end + def identify(x, y) - list(tk_send_without_enc('identify', x, y)) + num_or_nil(tk_send_without_enc('identify', x, y)) end def sashpos(idx, newpos=None) num_or_str(tk_send_without_enc('sashpos', idx, newpos)) end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Panedwindow, +# :TkPanedwindow, :TkPanedWindow) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tpaned.rb', + :Ttk, Tk::Tile::Panedwindow, + :TkPanedwindow, :TkPanedWindow) diff --git a/ext/tk/lib/tkextlib/tile/tprogressbar.rb b/ext/tk/lib/tkextlib/tile/tprogressbar.rb index f786d370dd..0c9d15e1b9 100644 --- a/ext/tk/lib/tkextlib/tile/tprogressbar.rb +++ b/ext/tk/lib/tkextlib/tile/tprogressbar.rb @@ -13,9 +13,6 @@ module Tk end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Progressbar, :TkProgressbar) - - class Tk::Tile::TProgressbar include Tk::Tile::TileWidget @@ -25,7 +22,7 @@ class Tk::Tile::TProgressbar TkCommandNames = ['::tprogressbar'.freeze].freeze end WidgetClassName = 'TProgressbar'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def self.style(*args) [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') @@ -54,3 +51,7 @@ class Tk::Tile::TProgressbar end end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Progressbar, :TkProgressbar) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tprogressbar.rb', + :Ttk, Tk::Tile::Progressbar, :TkProgressbar) diff --git a/ext/tk/lib/tkextlib/tile/tradiobutton.rb b/ext/tk/lib/tkextlib/tile/tradiobutton.rb index 72e72170cb..5dbf260666 100644 --- a/ext/tk/lib/tkextlib/tile/tradiobutton.rb +++ b/ext/tk/lib/tkextlib/tile/tradiobutton.rb @@ -15,10 +15,6 @@ module Tk end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Radiobutton, - :TkRadiobutton, :TkRadioButton) - - class Tk::Tile::TRadioButton < Tk::RadioButton include Tk::Tile::TileWidget @@ -28,9 +24,15 @@ class Tk::Tile::TRadioButton < Tk::RadioButton TkCommandNames = ['::tradiobutton'.freeze].freeze end WidgetClassName = 'TRadiobutton'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def self.style(*args) [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Radiobutton, +# :TkRadiobutton, :TkRadioButton) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tradiobutton.rb', + :Ttk, Tk::Tile::Radiobutton, + :TkRadiobutton, :TkRadioButton) diff --git a/ext/tk/lib/tkextlib/tile/treeview.rb b/ext/tk/lib/tkextlib/tile/treeview.rb index 2046be8a69..70db3d6d78 100644 --- a/ext/tk/lib/tkextlib/tile/treeview.rb +++ b/ext/tk/lib/tkextlib/tile/treeview.rb @@ -12,9 +12,6 @@ module Tk end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Treeview, :TkTreeview) - - module Tk::Tile::TreeviewConfig include TkItemConfigMethod @@ -519,16 +516,20 @@ module Tk::Tile::TreeviewConfig end end + alias __itemcget_tkstring itemcget_tkstring alias __itemcget itemcget alias __itemcget_strict itemcget_strict alias __itemconfigure itemconfigure alias __itemconfiginfo itemconfiginfo alias __current_itemconfiginfo current_itemconfiginfo - private :__itemcget, :__itemcget_strict + private :__itemcget_tkstring, :__itemcget, :__itemcget_strict private :__itemconfigure, :__itemconfiginfo, :__current_itemconfiginfo # Treeview Item + def itemcget_tkstring(tagOrId, option) + __itemcget_tkstring([:item, tagOrId], option) + end def itemcget(tagOrId, option) __itemcget([:item, tagOrId], option) end @@ -546,6 +547,9 @@ module Tk::Tile::TreeviewConfig end # Treeview Column + def columncget_tkstring(tagOrId, option) + __itemcget_tkstring([:column, tagOrId], option) + end def columncget(tagOrId, option) __itemcget([:column, tagOrId], option) end @@ -561,6 +565,7 @@ module Tk::Tile::TreeviewConfig def current_columnconfiginfo(tagOrId, slot=nil) __current_itemconfiginfo([:column, tagOrId], slot) end + alias column_cget_tkstring columncget_tkstring alias column_cget columncget alias column_cget_strict columncget_strict alias column_configure columnconfigure @@ -568,6 +573,19 @@ module Tk::Tile::TreeviewConfig alias current_column_configinfo current_columnconfiginfo # Treeview Heading + def headingcget_tkstring(tagOrId, option) + if __tile_specific_item_optkeys([:heading, tagOrId]).index(option.to_s) + begin + # On tile-0.7.{2-8}, 'state' options has no '-' at its head. + tk_call(*(__item_cget_cmd([:heading, tagOrId]) << option.to_s)) + rescue + # Maybe, 'state' option has '-' in future. + tk_call(*(__item_cget_cmd([:heading, tagOrId]) << "-#{option}")) + end + else + __itemcget_tkstring([:heading, tagOrId], option) + end + end def headingcget_strict(tagOrId, option) if __tile_specific_item_optkeys([:heading, tagOrId]).index(option.to_s) begin @@ -630,6 +648,7 @@ module Tk::Tile::TreeviewConfig def current_headingconfiginfo(tagOrId, slot=nil) __current_itemconfiginfo([:heading, tagOrId], slot) end + alias heading_cget_tkstring headingcget_tkstring alias heading_cget headingcget alias heading_cget_strict headingcget_strict alias heading_configure headingconfigure @@ -637,6 +656,9 @@ module Tk::Tile::TreeviewConfig alias current_heading_configinfo current_headingconfiginfo # Treeview Tag + def tagcget_tkstring(tagOrId, option) + __itemcget_tkstring([:tag, :configure, tagOrId], option) + end def tagcget(tagOrId, option) __itemcget([:tag, :configure, tagOrId], option) end @@ -652,6 +674,7 @@ module Tk::Tile::TreeviewConfig def current_tagconfiginfo(tagOrId, slot=nil) __current_itemconfiginfo([:tag, :configure, tagOrId], slot) end + alias tag_cget_tkstring tagcget_tkstring alias tag_cget tagcget alias tag_cget_strict tagcget_strict alias tag_configure tagconfigure @@ -737,6 +760,9 @@ class Tk::Tile::Treeview::Item < TkObject @id end + def cget_tkstring(option) + @t.itemcget_tkstring(@id, option) + end def cget(option) @t.itemcget(@id, option) end @@ -769,6 +795,11 @@ class Tk::Tile::Treeview::Item < TkObject self end + def tag_has?(tag) + @t.tag_has?(tag, @id) + end + alias has_tag? tag_has? + def bbox(column=None) @t.bbox(@id, column) end @@ -907,7 +938,7 @@ class Tk::Tile::Treeview::Tag < TkObject TagID_TBL = TkCore::INTERP.create_table - (Tag_ID = ['tile_treeview_tag'.freeze, '00000'.taint]).instance_eval{ + (Tag_ID = ['tile_treeview_tag'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze @@ -950,6 +981,11 @@ class Tk::Tile::Treeview::Tag < TkObject @id end + def tag_has?(item) + @t.tag_has?(@id, item) + end + alias added? tag_has? + def bind(seq, *args) if TkComm._callback_entry?(args[0]) || !block_given? cmd = args.shift @@ -979,6 +1015,9 @@ class Tk::Tile::Treeview::Tag < TkObject @t.tag_bindinfo(@id, seq) end + def cget_tkstring(option) + @t.tagcget_tkstring(@id, option) + end def cget(option) @t.tagcget(@id, option) end @@ -1014,7 +1053,7 @@ class Tk::Tile::Treeview < TkWindow TkCommandNames = ['::treeview'.freeze].freeze end WidgetClassName = 'Treeview'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __destroy_hook__ Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{ @@ -1098,14 +1137,29 @@ class Tk::Tile::Treeview < TkWindow end end + def identify_region(x, y) + tk_send('identify', 'region', x, y) + end + + def identify_item(x, y) + id = tk_send('identify', 'item', x, y) + (id.empty?)? nil: Tk::Tile::Treeview::Item.id2obj(self, id) + end + + def identify_element(x, y) + tk_send('identify', 'element', x, y) + end + def row_identify(x, y) id = tk_send('identify', 'row', x, y) (id.empty?)? nil: Tk::Tile::Treeview::Item.id2obj(self, id) end + alias identify_row row_identify def column_identify(x, y) tk_send('identify', 'column', x, y) end + alias identify_column column_identify def index(item) number(tk_send('index', item)) @@ -1204,6 +1258,15 @@ class Tk::Tile::Treeview < TkWindow self end + def tag_has?(tag, item) + bool(tk_send('tag', 'has', tagid(tag), tagid(item))) + end + def tag_has(tag) + tk_split_simplelist(tk_send('tag', 'has', tagid(tag))).collect{|id| + Tk::Tile::Treeview::Item.id2obj(self, id) + } + end + def tag_bind(tag, seq, *args) if TkComm._callback_entry?(args[0]) || !block_given? cmd = args.shift @@ -1237,3 +1300,7 @@ class Tk::Tile::Treeview < TkWindow end alias tagbindinfo tag_bindinfo end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Treeview, :TkTreeview) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/treeview.rb', + :Ttk, Tk::Tile::Treeview, :TkTreeview) diff --git a/ext/tk/lib/tkextlib/tile/tscale.rb b/ext/tk/lib/tkextlib/tile/tscale.rb index 2c46fd9bd4..7eefcef731 100644 --- a/ext/tk/lib/tkextlib/tile/tscale.rb +++ b/ext/tk/lib/tkextlib/tile/tscale.rb @@ -17,9 +17,6 @@ module Tk end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Scale, :TkScale) - - class Tk::Tile::TScale < Tk::Scale include Tk::Tile::TileWidget @@ -29,11 +26,13 @@ class Tk::Tile::TScale < Tk::Scale TkCommandNames = ['::tscale'.freeze].freeze end WidgetClassName = 'TScale'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def self.style(*args) [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') end + + alias identify ttk_identify end class Tk::Tile::TProgress < Tk::Tile::TScale @@ -45,9 +44,13 @@ class Tk::Tile::TProgress < Tk::Tile::TScale TkCommandNames = ['::tprogress'.freeze].freeze end WidgetClassName = 'TProgress'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def self.style(*args) [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Scale, :TkScale) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tscale.rb', + :Ttk, Tk::Tile::Scale, :TkScale) diff --git a/ext/tk/lib/tkextlib/tile/tscrollbar.rb b/ext/tk/lib/tkextlib/tile/tscrollbar.rb index 163b8f4713..c6bba5810b 100644 --- a/ext/tk/lib/tkextlib/tile/tscrollbar.rb +++ b/ext/tk/lib/tkextlib/tile/tscrollbar.rb @@ -13,9 +13,6 @@ module Tk end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Scrollbar, :TkScrollbar) - - class Tk::Tile::TScrollbar < Tk::Scrollbar include Tk::Tile::TileWidget @@ -25,13 +22,21 @@ class Tk::Tile::TScrollbar < Tk::Scrollbar TkCommandNames = ['::tscrollbar'.freeze].freeze end WidgetClassName = 'TScrollbar'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def self.style(*args) [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') end + + alias identify ttk_identify end +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Scrollbar, :TkScrollbar) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tscrollbar.rb', + :Ttk, Tk::Tile::Scrollbar, :TkScrollbar) + +####################################################################### + class Tk::Tile::XScrollbar < Tk::Tile::TScrollbar def create_self(keys) keys = {} unless keys @@ -50,5 +55,9 @@ class Tk::Tile::YScrollbar < Tk::Tile::TScrollbar private :create_self end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::XScrollbar, :TkXScrollbar) -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::YScrollbar, :TkYScrollbar) +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::XScrollbar, :TkXScrollbar) +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::YScrollbar, :TkYScrollbar) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tscrollbar.rb', + :Ttk, Tk::Tile::XScrollbar, :TkXScrollbar) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tscrollbar.rb', + :Ttk, Tk::Tile::YScrollbar, :TkYScrollbar) diff --git a/ext/tk/lib/tkextlib/tile/tseparator.rb b/ext/tk/lib/tkextlib/tile/tseparator.rb index 30fae2c525..ffd2f6f89f 100644 --- a/ext/tk/lib/tkextlib/tile/tseparator.rb +++ b/ext/tk/lib/tkextlib/tile/tseparator.rb @@ -13,9 +13,6 @@ module Tk end end -Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Separator, :TkSeparator) - - class Tk::Tile::TSeparator < TkWindow include Tk::Tile::TileWidget @@ -25,9 +22,13 @@ class Tk::Tile::TSeparator < TkWindow TkCommandNames = ['::tseparator'.freeze].freeze end WidgetClassName = 'TSeparator'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def self.style(*args) [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') end end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Separator, :TkSeparator) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tseparator.rb', + :Ttk, Tk::Tile::Separator, :TkSeparator) diff --git a/ext/tk/lib/tkextlib/tile/tspinbox.rb b/ext/tk/lib/tkextlib/tile/tspinbox.rb new file mode 100644 index 0000000000..2f2d73c5ab --- /dev/null +++ b/ext/tk/lib/tkextlib/tile/tspinbox.rb @@ -0,0 +1,107 @@ +# +# ttk::spinbox widget (Tcl/Tk 8.6b1 or later) +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' +require 'tkextlib/tile.rb' + +module Tk + module Tile + class TSpinbox < Tk::Tile::TEntry + end + Spinbox = TSpinbox + end +end + +class Tk::Tile::TSpinbox < Tk::Tile::TEntry + include Tk::Tile::TileWidget + + if Tk::Tile::USE_TTK_NAMESPACE + TkCommandNames = ['::ttk::spinbox'.freeze].freeze + else + TkCommandNames = ['::tspinbox'.freeze].freeze + end + WidgetClassName = 'TSpinbox'.freeze + WidgetClassNames[WidgetClassName] ||= self + + class SpinCommand < TkValidateCommand + class ValidateArgs < TkUtil::CallbackSubst + KEY_TBL = [ + [ ?d, ?s, :direction ], + [ ?s, ?e, :current ], + [ ?W, ?w, :widget ], + nil + ] + + PROC_TBL = [ + [ ?s, TkComm.method(:string) ], + [ ?w, TkComm.method(:window) ], + + [ ?e, proc{|val| + #enc = Tk.encoding + enc = ((Tk.encoding)? Tk.encoding : Tk.encoding_system) + if enc + Tk.fromUTF8(TkComm::string(val), enc) + else + TkComm::string(val) + end + } + ], + + nil + ] + + _setup_subst_table(KEY_TBL, PROC_TBL); + + def self.ret_val(val) + (val)? '1': '0' + end + end + + def self._config_keys + ['command'] + end + end + + def __validation_class_list + super() << SpinCommand + end + + Tk::ValidateConfigure.__def_validcmd(binding, SpinCommand) + + def __boolval_optkeys + super() << 'wrap' + end + private :__boolval_optkeys + + def __strval_optkeys + super() << 'buttonbackground' << 'format' + end + private :__strval_optkeys + + def __listval_optkeys + super() << 'values' + end + private :__listval_optkeys + + def self.style(*args) + [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') + end + + def current + number(tk_send_without_enc('current')) + end + def current=(idx) + tk_send('current', idx) + end + + def set(val) + tk_send('set', val) + end + + alias identify ttk_identify +end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Spinbox, :TkSpinbox) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tspinbox.rb', + :Ttk, Tk::Tile::Spinbox, :TkSpinbox) diff --git a/ext/tk/lib/tkextlib/tile/tsquare.rb b/ext/tk/lib/tkextlib/tile/tsquare.rb index 600b55e4e7..a81cd7b98a 100644 --- a/ext/tk/lib/tkextlib/tile/tsquare.rb +++ b/ext/tk/lib/tkextlib/tile/tsquare.rb @@ -22,7 +22,7 @@ class Tk::Tile::TSquare < TkWindow TkCommandNames = ['::tsquare'.freeze].freeze end WidgetClassName = 'TSquare'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def self.style(*args) [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') diff --git a/ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb b/ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb index 522ebfb92c..b9ee90aace 100644 --- a/ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb +++ b/ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb @@ -36,7 +36,7 @@ end class Tk::HTML_Widget::ClippingWindow WidgetClassName = 'HtmlClip'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self HtmlClip_TBL = TkCore::INTERP.create_table @@ -101,7 +101,7 @@ class Tk::HTML_Widget TkCommandNames = ['html'.freeze].freeze WidgetClassName = 'Html'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def create_self(keys) if keys and keys != None diff --git a/ext/tk/lib/tkextlib/tktable/tktable.rb b/ext/tk/lib/tkextlib/tktable/tktable.rb index 12a2dd75bf..bc7a6c9a2e 100644 --- a/ext/tk/lib/tkextlib/tktable/tktable.rb +++ b/ext/tk/lib/tkextlib/tktable/tktable.rb @@ -74,6 +74,9 @@ module Tk::TkTable::ConfigMethod end private :__item_val2ruby_optkeys + def tag_cget_tkstring(tagOrId, option) + itemcget_tkstring(['tag', tagid(tagOrId)], option) + end def tag_cget(tagOrId, option) itemcget(['tag', tagid(tagOrId)], option) end @@ -90,6 +93,9 @@ module Tk::TkTable::ConfigMethod current_itemconfiginfo(['tag', tagid(tagOrId)], slot) end + def window_cget_tkstring(tagOrId, option) + itemcget_tkstring(['window', tagid(tagOrId)], option) + end def window_cget(tagOrId, option) itemcget(['window', tagid(tagOrId)], option) end @@ -114,7 +120,7 @@ module Tk::TkTable::ConfigMethod current_itemconfiginfo(['window', tagid(tagOrId)], slot) end - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo end @@ -125,7 +131,7 @@ class Tk::TkTable::CellTag CellTagID_TBL = TkCore::INTERP.create_table - (CellTag_ID = ['tktbl:celltag'.freeze, '00000'.taint]).instance_eval{ + (CellTag_ID = ['tktbl:celltag'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze @@ -197,6 +203,9 @@ class Tk::TkTable::CellTag @t.tag_lower(@id, target) end + def cget_tkstring(key) + @t.tag_cget_tkstring(@id, key) + end def cget(key) @t.tag_cget(@id, key) end @@ -253,7 +262,7 @@ end class Tk::TkTable TkCommandNames = ['table'.freeze].freeze WidgetClassName = 'Table'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self include Scrollable include Tk::TkTable::ConfigMethod diff --git a/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb b/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb index 0c3de94baa..1879a531ae 100644 --- a/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb +++ b/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb @@ -322,7 +322,7 @@ module Tk::TreeCtrl::ConfigMethod def __item_boolval_optkeys(id) if id == 'debug' - ['data', 'display', 'enable'] + ['data', 'display', 'enable', 'span', 'textlayout'] elsif id == 'dragimage' ['visible'] elsif id == 'marquee' @@ -330,7 +330,7 @@ module Tk::TreeCtrl::ConfigMethod elsif id.kind_of?(Array) case id[0] when 'item' - ['button', 'visible'] + ['visible', 'wrap', 'open', 'returnid', 'visible'] when 'column' if id[1] == 'drag' ['enable'] @@ -339,11 +339,11 @@ module Tk::TreeCtrl::ConfigMethod 'visible', 'widthhack'] end when 'element' - ['draw', 'filled', 'showfocus', 'destroy'] + ['draw', 'filled', 'showfocus', 'clip', 'destroy'] when 'notify' ['active'] when 'style' - ['detach'] + ['detach', 'indent', 'visible'] else if id[0].kind_of?(Array) && id[0][1] == 'element' ['filled', 'showfocus'] @@ -401,6 +401,20 @@ module Tk::TreeCtrl::ConfigMethod end private :__item_listval_optkeys + def __item_val2ruby_optkeys(id) + if id.kind_of?(Array) + case id[0] + when 'item' + { 'button' => proc{|id,val| (val == 'auto')? val: TkComm.bool(val)} } + else + [] + end + else + [] + end + end + private :__item_val2ruby_optkeys + def __item_keyonly_optkeys(id) # { def_key=>(undef_key|nil), ... } { 'notreally'=>nil, @@ -414,6 +428,9 @@ module Tk::TreeCtrl::ConfigMethod end private :__item_keyonly_optkeys + def column_cget_tkstring(tagOrId, option) + itemcget_tkstring(['column', tagOrId], option) + end def column_cget(tagOrId, option) itemcget(['column', tagOrId], option) end @@ -430,6 +447,9 @@ module Tk::TreeCtrl::ConfigMethod current_itemconfiginfo(['column', tagOrId], slot) end + def column_dragcget_tkstring(option) + itemcget_tkstring(['column', 'drag'], option) + end def column_dragcget(option) itemcget(['column', 'drag'], option) end @@ -446,6 +466,9 @@ module Tk::TreeCtrl::ConfigMethod current_itemconfiginfo(['column', 'drag'], slot) end + def debug_cget_tkstring(option) + itemcget_tkstring('debug', option) + end def debug_cget(option) itemcget('debug', option) end @@ -462,6 +485,9 @@ module Tk::TreeCtrl::ConfigMethod current_itemconfiginfo('debug', slot) end + def dragimage_cget_tkstring(option) + itemcget_tkstring('dragimage', option) + end def dragimage_cget(option) itemcget('dragimage', option) end @@ -478,6 +504,9 @@ module Tk::TreeCtrl::ConfigMethod current_itemconfiginfo('dragimage', slot) end + def element_cget_tkstring(tagOrId, option) + itemcget_tkstring(['element', tagOrId], option) + end def element_cget(tagOrId, option) itemcget(['element', tagOrId], option) end @@ -494,6 +523,9 @@ module Tk::TreeCtrl::ConfigMethod current_itemconfiginfo(['element', tagOrId], slot) end + def item_cget_tkstring(tagOrId, option) + itemcget_tkstring(['item', tagOrId], option) + end def item_cget(tagOrId, option) itemcget(['item', tagOrId], option) end @@ -510,6 +542,9 @@ module Tk::TreeCtrl::ConfigMethod current_itemconfiginfo(['item', tagOrId], slot) end + def item_element_cget_tkstring(item, column, elem, option) + itemcget_tkstring([['item', 'element'], [item, column, elem]], option) + end def item_element_cget(item, column, elem, option) itemcget([['item', 'element'], [item, column, elem]], option) end @@ -526,6 +561,9 @@ module Tk::TreeCtrl::ConfigMethod current_itemconfiginfo([['item', 'element'], [item, column, elem]], slot) end + def marquee_cget_tkstring(option) + itemcget_tkstring('marquee', option) + end def marquee_cget(option) itemcget('marquee', option) end @@ -542,6 +580,11 @@ module Tk::TreeCtrl::ConfigMethod current_itemconfiginfo('marquee', slot) end + def notify_cget_tkstring(win, pattern, option) + pattern = "<#{pattern}>" + # "notify" doesn't have cget subcommand. + tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(['notify', [win, pattern]])) << "-#{option}")), false, true)[-1] + end def notify_cget(win, pattern, option) pattern = "<#{pattern}>" # "notify" doesn't have cget subcommand. @@ -571,6 +614,9 @@ module Tk::TreeCtrl::ConfigMethod current_itemconfiginfo(['notify', [win, pattern]], slot) end + def style_cget_tkstring(tagOrId, option) + itemcget_tkstring(['style', tagOrId], option) + end def style_cget(tagOrId, option) itemcget(['style', tagOrId], option) end @@ -587,7 +633,7 @@ module Tk::TreeCtrl::ConfigMethod current_itemconfiginfo(['style', tagOrId], slot) end - private :itemcget, :itemcget_strict + private :itemcget_tkstring, :itemcget, :itemcget_strict private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo end @@ -599,7 +645,7 @@ class Tk::TreeCtrl TkCommandNames = ['treectrl'.freeze].freeze WidgetClassName = 'TreeCtrl'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self ######################### @@ -631,7 +677,7 @@ class Tk::TreeCtrl [ 'itemwidthequal', 'usetheme', 'showbuttons', 'showheader', 'showlines', 'showroot', - 'showrootbutton', 'showrootlines', + 'showrootbutton', 'showrootlines', 'showrootchildbuttons' ] end private :__boolval_optkeys @@ -1547,8 +1593,8 @@ class Tk::TreeCtrl self end - def see(item) - tk_send('see', item) + def see(item, column=None, keys={}) + tk_send('see', item, column, *hash_kv(keys)) self end @@ -1686,7 +1732,7 @@ end class Tk::TreeCtrl::Column < TkObject TreeCtrlColumnID_TBL = TkCore::INTERP.create_table - (TreeCtrlColumnID = ['treectrl_column'.freeze, '00000'.taint]).instance_eval{ + (TreeCtrlColumnID = ['treectrl_column'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze @@ -1741,6 +1787,9 @@ class Tk::TreeCtrl::Column < TkObject @id.to_s.dup end + def cget_tkstring(opt) + @tree.column_cget_tkstring(@tree.column_index(@id), opt) + end def cget(opt) @tree.column_cget(@tree.column_index(@id), opt) end @@ -1789,7 +1838,7 @@ end class Tk::TreeCtrl::Element < TkObject TreeCtrlElementID_TBL = TkCore::INTERP.create_table - (TreeCtrlElementID = ['treectrl_element'.freeze, '00000'.taint]).instance_eval{ + (TreeCtrlElementID = ['treectrl_element'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze @@ -1844,6 +1893,9 @@ class Tk::TreeCtrl::Element < TkObject @id.dup end + def cget_tkstring(opt) + @tree.element_cget_tkstring(@id, opt) + end def cget(opt) @tree.element_cget(@id, opt) end @@ -1978,6 +2030,9 @@ class Tk::TreeCtrl::Item < TkObject self end + def cget_tkstring(opt) + @tree.item_cget_tkstring(@id, opt) + end def cget(opt) @tree.item_cget(@id, opt) end @@ -2014,7 +2069,10 @@ class Tk::TreeCtrl::Item < TkObject @tree.item_element_actual(@id, column, elem, key) end - def element_cget(opt) + def element_cget_tkstring(opt) + @tree.item_element_cget(@id, opt) + end + def element_cget_tkstring(opt) @tree.item_element_cget(@id, opt) end def element_cget_strict(opt) @@ -2218,7 +2276,7 @@ end class Tk::TreeCtrl::Style < TkObject TreeCtrlStyleID_TBL = TkCore::INTERP.create_table - (TreeCtrlStyleID = ['treectrl_style'.freeze, '00000'.taint]).instance_eval{ + (TreeCtrlStyleID = ['treectrl_style'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze @@ -2268,6 +2326,9 @@ class Tk::TreeCtrl::Style < TkObject @id.dup end + def cget_tkstring(opt) + @tree.style_cget_tkstring(@id, opt) + end def cget(opt) @tree.style_cget(@id, opt) end diff --git a/ext/tk/lib/tkextlib/version.rb b/ext/tk/lib/tkextlib/version.rb index 82ed7ef542..3bc3ec5ae2 100644 --- a/ext/tk/lib/tkextlib/version.rb +++ b/ext/tk/lib/tkextlib/version.rb @@ -2,5 +2,5 @@ # release date of tkextlib # module Tk - Tkextlib_RELEASE_DATE = '2008-11-25'.freeze + Tkextlib_RELEASE_DATE = '2009-07-12'.freeze end diff --git a/ext/tk/lib/tkextlib/vu/bargraph.rb b/ext/tk/lib/tkextlib/vu/bargraph.rb index 1bcafc2887..b9fcf925f3 100644 --- a/ext/tk/lib/tkextlib/vu/bargraph.rb +++ b/ext/tk/lib/tkextlib/vu/bargraph.rb @@ -19,7 +19,7 @@ require 'tkextlib/vu.rb' class Tk::Vu::Bargraph < TkWindow TkCommandNames = ['::vu::bargraph'.freeze].freeze WidgetClassName = 'Bargraph'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self ############################### diff --git a/ext/tk/lib/tkextlib/vu/dial.rb b/ext/tk/lib/tkextlib/vu/dial.rb index e27a38ae42..eca0bbb67c 100644 --- a/ext/tk/lib/tkextlib/vu/dial.rb +++ b/ext/tk/lib/tkextlib/vu/dial.rb @@ -19,7 +19,7 @@ require 'tkextlib/vu.rb' class Tk::Vu::Dial < TkWindow TkCommandNames = ['::vu::dial'.freeze].freeze WidgetClassName = 'Dial'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self ############################### diff --git a/ext/tk/lib/tkextlib/vu/pie.rb b/ext/tk/lib/tkextlib/vu/pie.rb index c1fb6857bf..6b0c485d8a 100644 --- a/ext/tk/lib/tkextlib/vu/pie.rb +++ b/ext/tk/lib/tkextlib/vu/pie.rb @@ -37,7 +37,7 @@ end class Tk::Vu::Pie < TkWindow TkCommandNames = ['::vu::pie'.freeze].freeze WidgetClassName = 'Pie'.freeze - WidgetClassNames[WidgetClassName] = self + WidgetClassNames[WidgetClassName] ||= self def __destroy_hook__ Tk::Vu::PieSlice::SliceID_TBL.delete(@path) @@ -117,7 +117,7 @@ end class Tk::Vu::PieSlice SliceID_TBL = TkCore::INTERP.create_table - (Pie_Slice_ID = ['vu:pie'.freeze, '00000'.taint]).instance_eval{ + (Pie_Slice_ID = ['vu:pie'.freeze, TkUtil.untrust('00000')]).instance_eval{ @mutex = Mutex.new def mutex; @mutex; end freeze @@ -173,6 +173,10 @@ class Tk::Vu::PieSlice val end + def cget_tkstring(slot) + @pie.itemcget_tkstring(@id, slot) + end + def cget(slot) @pie.itemcget(@id, slot) end diff --git a/ext/tk/old-extconf.rb b/ext/tk/old-extconf.rb new file mode 100644 index 0000000000..ebc83a0c0b --- /dev/null +++ b/ext/tk/old-extconf.rb @@ -0,0 +1,440 @@ +# extconf.rb for tcltklib + +require 'mkmf' + +is_win32 = (/mswin|mingw|cygwin|bccwin/ =~ RUBY_PLATFORM) +#is_macosx = (/darwin/ =~ RUBY_PLATFORM) + +have_func("ruby_native_thread_p", "ruby.h") +have_func("rb_errinfo", "ruby.h") +have_func("rb_safe_level", "ruby.h") +have_struct_member("struct RArray", "ptr", "ruby.h") +have_struct_member("struct RArray", "len", "ruby.h") + +def find_framework(tcl_hdr, tk_hdr) + if framework_dir = with_config("tcltk-framework") + paths = [framework_dir] + else + unless tcl_hdr || tk_hdr || + enable_config("tcltk-framework", false) || + enable_config("mac-tcltk-framework", false) + return false + end + paths = ["/Library/Frameworks", "/System/Library/Frameworks"] + end + + checking_for('Tcl/Tk Framework') { + paths.find{|dir| + dir.strip! + dir.chomp!('/') + (tcl_hdr || FileTest.directory?(dir + "/Tcl.framework/") ) && + (tk_hdr || FileTest.directory?(dir + "/Tk.framework/") ) + } + } +end + +tcl_framework_header = with_config("tcl-framework-header") +tk_framework_header = with_config("tk-framework-header") + +tcltk_framework = find_framework(tcl_framework_header, tk_framework_header) + +unless is_win32 + have_library("nsl", "t_open") + have_library("socket", "socket") + have_library("dl", "dlopen") + have_library("m", "log") +end + +tk_idir, tk_ldir = dir_config("tk") +tcl_idir, tcl_ldir = dir_config("tcl") +x11_idir, x11_ldir = dir_config("X11") + +tk_ldir2 = with_config("tk-lib") +tcl_ldir2 = with_config("tcl-lib") +x11_ldir2 = with_config("X11-lib") + +tk_ldir_list = [tk_ldir2, tk_ldir] +tcl_ldir_list = [tcl_ldir2, tcl_ldir] + +tklib = with_config("tklib") +tcllib = with_config("tcllib") +stubs = enable_config("tcltk_stubs") || with_config("tcltk_stubs") + +tcltk_version = with_config("tcltkversion") + +use_X = with_config("X11", (! is_win32)) + +def parse_tclConfig(file) + # check tclConfig.sh/tkConfig.sh + tbl = {} + IO.foreach(file){|line| + line.strip! + next if line !~ /^([^\#=][^=]*)=(['"]|)(.*)\2$/ + key, val = $1, $3 + tbl[key] = val.gsub(/\$\{([^}]+)\}/){|s| tbl[$1]} rescue nil + } + tbl +end + +def check_tcltk_version(version) + return [nil, nil] unless version + + version = version.strip + + tclver = version.dup + tkver = version.dup + + major = dot = minor = dot = plvl = ext = nil + + if version =~ /^(\d)(\.?)(\d)(\.?)(\d*)(.*)$/ + major = $1; minor_dot = $2; minor = $3; plvl_dot = $4; plvl = $5; ext = $6 + dot = ! minor_dot.empty? + if plvl_dot.empty? && ! plvl.empty? + minor << plvl + end + elsif version =~ /^(\d)(\.?)(\d?)(.*)$/ + major = $1; minor_dot = $2; minor = $3; ext = $4 + dot = ! minor_dot.empty? + else # unknown -> believe user + return [tclver, tkver] + end + + # check Tcl7.6 / Tk4.2 ? + if major == "7" # Tcl7.6 ( not support Tclversion < 7.6 ) + # Tk4.2 + tkver = "4" + ((dot)? ".": "") + ((minor.empty)? "": "2") + ext + elsif major == "4" # Tk4.2 ( not support Tkversion < 4.2 ) + # Tcl7.6 + tclver = "7" + ((dot)? ".": "") + ((minor.empty)? "": "6") + ext + end + + [tclver, tkver] +end + +def find_tcl(tcllib, stubs, version, *opt_paths) + default_paths = ["/usr/local/lib", "/usr/pkg/lib", "/usr/lib"] + default_paths << "/Tcl/lib" # default for ActiveTcl + + if (paths = opt_paths.compact).empty? + paths = default_paths + end + + if stubs + func = "Tcl_InitStubs" + lib = "tclstub" + else + func = "Tcl_FindExecutable" + lib = "tcl" + end + + if version && ! version.empty? + versions = [version] + else + versions = %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 7.6] + end + + if tcllib + st = find_library(tcllib, func, *paths) + else + st = versions.find { |ver| + find_library("#{lib}#{ver}", func, *paths) or + find_library("#{lib}#{ver.delete('.')}", func, *paths) or + find_library("#{lib}#{ver}g", func, *paths) or + find_library("#{lib}#{ver.delete('.')}g", func, *paths) or + find_library("tcl#{ver}", func, *paths) or + find_library("tcl#{ver.delete('.')}", func, *paths) or + find_library("tcl#{ver}g", func, *paths) or + find_library("tcl#{ver.delete('.')}g", func, *paths) + } || (!version && find_library(lib, func, *paths)) + end + + unless st + puts("Warning:: cannot find Tcl library. tcltklib will not be compiled (tcltklib is disabled on your Ruby == Ruby/Tk will not work). Please check configure options.") + end + st +end + +def find_tk(tklib, stubs, version, *opt_paths) + default_paths = ["/usr/local/lib", "/usr/pkg/lib", "/usr/lib"] + default_paths << "/Tcl/lib" # default for ActiveTcl + + if (paths = opt_paths.compact).empty? + paths = default_paths + end + + if stubs + func = "Tk_InitStubs" + lib = "tkstub" + else + func = "Tk_Init" + lib = "tk" + end + + if version && ! version.empty? + versions = [version] + else + versions = %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 4.2] + end + + if tklib + st = find_library(tklib, func, *paths) + else + st = versions.find { |ver| + find_library("#{lib}#{ver}", func, *paths) or + find_library("#{lib}#{ver.delete('.')}", func, *paths) or + find_library("#{lib}#{ver}g", func, *paths) or + find_library("#{lib}#{ver.delete('.')}g", func, *paths) or + find_library("tk#{ver}", func, *paths) or + find_library("tk#{ver.delete('.')}", func, *paths) or + find_library("tk#{ver}g", func, *paths) or + find_library("tk#{ver.delete('.')}g", func, *paths) + } || (!version && find_library(lib, func, *paths)) + end + + unless st + puts("Warning:: cannot find Tk library. tcltklib will not be compiled (tcltklib is disabled on your Ruby == Ruby/Tk will not work). Please check configure options.") + end + st +end + +def find_tcltk_header(tclver, tkver) + base_dir = ['/usr/local/include', '/usr/pkg/include', '/usr/include'] + base_dir << '/Tcl/include' # default for ActiveTcl + + unless have_tcl_h = have_header('tcl.h') + if tclver && ! tclver.empty? + versions = [tclver] + else + versions = %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 7.6] + end + paths = base_dir.dup + versions.each{|ver| paths.concat(base_dir.map{|dir| dir + '/tcl' + ver})} + have_tcl_h = find_header('tcl.h', *paths) + end + + unless have_tk_h = have_header("tk.h") + if tkver && ! tkver.empty? + versions = [tkver] + else + versions = %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 4.2] + end + paths = base_dir.dup + versions.each{|ver| paths.concat(base_dir.map{|dir| dir + '/tk' + ver})} + have_tk_h = find_header('tk.h', *paths) + end + + have_tcl_h && have_tk_h +end + +def find_X11(*opt_paths) + default_paths = + [ "/usr/X11/lib", "/usr/lib/X11", "/usr/X11R6/lib", "/usr/openwin/lib" ] + paths = opt_paths.compact.concat(default_paths) + st = find_library("X11", "XOpenDisplay", *paths) + unless st + puts("Warning:: cannot find X11 library. tcltklib will not be compiled (tcltklib is disabled on your Ruby == Ruby/Tk will not work). Please check configure options. If your Tcl/Tk don't require X11, please try --without-X11.") + end + st +end + +def pthread_check() + tcl_major_ver = nil + tcl_minor_ver = nil + + # Is tcl-thread given by user ? + case enable_config("tcl-thread") + when true + tcl_enable_thread = true + when false + tcl_enable_thread = false + else + tcl_enable_thread = nil + end + + if (tclConfig = with_config("tclConfig-file")) + if tcl_enable_thread == true + puts("Warning: --with-tclConfig-file option is ignored, because --enable-tcl-thread option is given.") + elsif tcl_enable_thread == false + puts("Warning: --with-tclConfig-file option is ignored, because --disable-tcl-thread option is given.") + else + # tcl-thread is unknown and tclConfig.sh is given + begin + tbl = parse_tclConfig(tclConfig) + if tbl['TCL_THREADS'] + tcl_enable_thread = (tbl['TCL_THREADS'] == "1") + else + tcl_major_ver = tbl['TCL_MAJOR_VERSION'].to_i + tcl_minor_ver = tbl['TCL_MINOR_VERSION'].to_i + if tcl_major_ver < 8 || (tcl_major_ver == 8 && tcl_minor_ver == 0) + tcl_enable_thread = false + end + end + + if tcl_enable_thread == nil + # cannot find definition + if tcl_major_ver + puts("Warning: '#{tclConfig}' doesn't include TCL_THREADS definition.") + else + puts("Warning: '#{tclConfig}' may not be a tclConfig file.") + end + tclConfig = false + end + rescue Exception + puts("Warning: fail to read '#{tclConfig}'!! --> ignore the file") + tclConfig = false + end + end + end + + if tcl_enable_thread == nil && !tclConfig + # tcl-thread is unknown and tclConfig is unavailable + begin + try_run_available = try_run("int main() { exit(0); }") + rescue Exception + # cannot try_run. Is CROSS-COMPILE environment? + puts(%Q'\ +***************************************************************************** +** +** PTHREAD SUPPORT CHECK WARNING: +** +** We cannot check the consistency of pthread support between Ruby +** and the Tcl/Tk library in your environment (are you perhaps +** cross-compiling?). If pthread support for these 2 packages is +** inconsistent you may find you get errors when running Ruby/Tk +** (e.g. hangs or segmentation faults). We strongly recommend +** you to check the consistency manually. +** +***************************************************************************** +') + return true + end + end + + if tcl_enable_thread == nil + # tcl-thread is unknown + if try_run(< +int main() { + Tcl_Interp *ip; + ip = Tcl_CreateInterp(); + exit((Tcl_Eval(ip, "set tcl_platform(threaded)") == TCL_OK)? 0: 1); +} +EOF + tcl_enable_thread = true + elsif try_run(< +static Tcl_ThreadDataKey dataKey; +int main() { exit((Tcl_GetThreadData(&dataKey, 1) == dataKey)? 1: 0); } +EOF + tcl_enable_thread = true + else + tcl_enable_thread = false + end + end + + # check pthread mode + if (macro_defined?('HAVE_NATIVETHREAD', '#include "ruby.h"')) + # ruby -> enable + unless tcl_enable_thread + # ruby -> enable && tcl -> disable + puts(%Q'\ +***************************************************************************** +** +** PTHREAD SUPPORT MODE WARNING: +** +** Ruby is compiled with --enable-pthread, but your Tcl/Tk library +** seems to be compiled without pthread support. Although you can +** create the tcltklib library, this combination may cause errors +** (e.g. hangs or segmentation faults). If you have no reason to +** keep the current pthread support status, we recommend you reconfigure +** and recompile the libraries so that both or neither support pthreads. +** +** If you want change the status of pthread support, please recompile +** Ruby without "--enable-pthread" configure option or recompile Tcl/Tk +** with "--enable-threads" configure option (if your Tcl/Tk is later +** than or equal to Tcl/Tk 8.1). +** +***************************************************************************** +') + end + + # ruby -> enable && tcl -> enable/disable + if tcl_enable_thread + $CPPFLAGS += ' -DWITH_TCL_ENABLE_THREAD=1' + else + $CPPFLAGS += ' -DWITH_TCL_ENABLE_THREAD=0' + end + + return true + + else + # ruby -> disable + if tcl_enable_thread + # ruby -> disable && tcl -> enable + puts(%Q'\ +***************************************************************************** +** +** PTHREAD SUPPORT MODE ERROR: +** +** Ruby is not compiled with --enable-pthread, but your Tcl/Tk +** library seems to be compiled with pthread support. This +** combination may cause frequent hang or segmentation fault +** errors when Ruby/Tk is working. We recommend that you NEVER +** create the library with such a combination of pthread support. +** +** Please recompile Ruby with the "--enable-pthread" configure option +** or recompile Tcl/Tk with the "--disable-threads" configure option. +** +***************************************************************************** +') + $CPPFLAGS += ' -DWITH_TCL_ENABLE_THREAD=1' + return false + else + # ruby -> disable && tcl -> disable + $CPPFLAGS += ' -DWITH_TCL_ENABLE_THREAD=0' + return true + end + end +end + +tclver, tkver = check_tcltk_version(tcltk_version) + +if ( tcltk_framework || + ( find_tcltk_header(tclver, tkver) && + ( !use_X || find_X11(x11_ldir2, x11_ldir) ) && + find_tcl(tcllib, stubs, tclver, *tcl_ldir_list) && + find_tk(tklib, stubs, tkver, *tk_ldir_list) ) ) + $CPPFLAGS += ' -DUSE_TCL_STUBS -DUSE_TK_STUBS' if stubs + $CPPFLAGS += ' -D_WIN32' if /cygwin/ =~ RUBY_PLATFORM + + if tcltk_framework + if tcl_framework_header + $CPPFLAGS += " -I#{tcl_framework_header}" + else + $CPPFLAGS += " -I#{tcltk_framework}/Tcl.framework/Headers" + end + + if tk_framework_header + $CPPFLAGS += " -I#{tk_framework_header}" + else + $CPPFLAGS += " -I#{tcltk_framework}/Tk.framework/Headers" + end + + $LDFLAGS += ' -framework Tk -framework Tcl' + end + + if stubs or pthread_check + # create Makefile + + # for SUPPORT_STATUS + $INSTALLFILES ||= [] + $INSTALLFILES << ["lib/tkextlib/SUPPORT_STATUS", "$(RUBYLIBDIR)", "lib"] + + have_func("rb_hash_lookup", "ruby.h") + + # create + $defs << %[-DRUBY_VERSION=\\"#{RUBY_VERSION}\\"] + $defs << %[-DRUBY_RELEASE_DATE=\\"#{RUBY_RELEASE_DATE}\\"] + create_makefile("tcltklib") + end +end diff --git a/ext/tk/sample/demos-en/widget b/ext/tk/sample/demos-en/widget index 9a0605d8b9..250c589116 100644 --- a/ext/tk/sample/demos-en/widget +++ b/ext/tk/sample/demos-en/widget @@ -170,9 +170,12 @@ else } scr.command(proc{|*args| txt.yview(*args)}) # txt.pack('in'=>textFrame, 'expand'=>'yes', 'fill'=>'both', 'padx'=>1) - txt.pack('in'=>textFrame, 'expand'=>'yes', 'fill'=>'both') +# txt.pack('in'=>textFrame, 'expand'=>'yes', 'fill'=>'both') # textFrame.pack('expand'=>'yes', 'fill'=>'both', 'padx'=>1, 'pady'=>2) textFrame.pack('expand'=>'yes', 'fill'=>'both') + # $root.withdraw.deiconify + Tk.update_idletasks + txt.pack('in'=>textFrame, 'expand'=>'yes', 'fill'=>'both') statusBar = TkFrame.new($root) {|f| if $tk_version =~ /^4.*/ @@ -1035,7 +1038,7 @@ end # def aboutBox Tk.messageBox('icon'=>'info', 'type'=>'ok', 'title'=>'About Widget Demo', - 'message'=>"Ruby/Tk widget demonstration Ver.1.7.0-en\n\n" + + 'message'=>"Ruby/Tk widget demonstration Ver.1.7.1-en\n\n" + "based on demos of Tk8.1 -- 8.5 " + "( Copyright of Tcl/Tk demos:: " + "(c) 1996-1997 Sun Microsystems, Inc. / " + diff --git a/ext/tk/sample/demos-jp/widget b/ext/tk/sample/demos-jp/widget index 132953f32d..dfaa9c004e 100644 --- a/ext/tk/sample/demos-jp/widget +++ b/ext/tk/sample/demos-jp/widget @@ -190,10 +190,14 @@ else yscrollcommand proc{|first,last| scr.set first,last} } scr.command(proc{|*args| txt.yview(*args)}) + # txt.pack('in'=>textFrame, 'expand'=>'yes', 'fill'=>'both', 'padx'=>1) - txt.pack('in'=>textFrame, 'expand'=>'yes', 'fill'=>'both') +# txt.pack('in'=>textFrame, 'expand'=>'yes', 'fill'=>'both') # textFrame.pack('expand'=>'yes', 'fill'=>'both', 'padx'=>1, 'pady'=>2) textFrame.pack('expand'=>'yes', 'fill'=>'both') + # $root.withdraw.deiconify + Tk.update_idletasks + txt.pack('in'=>textFrame, 'expand'=>'yes', 'fill'=>'both') statusBar = TkFrame.new($root) {|f| if $tk_version =~ /^4.*/ @@ -1070,7 +1074,7 @@ end # def aboutBox Tk.messageBox('icon'=>'info', 'type'=>'ok', 'title'=>'About Widget Demo', - 'message'=>"Ruby/Tk ウィジェットデモ Ver.1.7.0-jp\n\n" + + 'message'=>"Ruby/Tk ウィジェットデモ Ver.1.7.1-jp\n\n" + "based on demos of Tk8.1 -- 8.5 " + "( Copyright of Tcl/Tk demos:: " + "(c) 1996-1997 Sun Microsystems, Inc. / " + diff --git a/ext/tk/sample/editable_listbox.rb b/ext/tk/sample/editable_listbox.rb index 553d400e24..7a9ad4450b 100644 --- a/ext/tk/sample/editable_listbox.rb +++ b/ext/tk/sample/editable_listbox.rb @@ -1,5 +1,5 @@ # -# Editable_TkListbox class +# Tk::RbWidget::Editable_Listbox class # # When "DoubleClick-1" on a listbox item, the entry box is opend on the # item. And when hit "Return" key on the entry box after modifying the @@ -10,19 +10,106 @@ # require 'tk' -class Editable_TkListbox < TkListbox - def _ebox_placer(coord_y) - idx = self.nearest(coord_y) - x, y, w, h = self.bbox(idx) +module Tk + module RbWidget + class Editable_Listbox < TkListbox + end + end +end + + +class Tk::RbWidget::Editable_Listbox < TkListbox + #------------------------------------ + BindTag = TkBindTag.new_by_name(self.to_s.gsub(/::/, '#')) + + BindTag.bind('FocusIn', :widget){|w| + w.instance_eval{ + if idx = @ebox.pos + see(idx) if bbox(idx).empty? + @ebox.focus(true) + end + } + } + + BindTag.bind('Double-1', :widget, :y){|w, y| + w.instance_eval{ _ebox_placer(nearest(y)) } + } + + BindTag.bind('Return', :widget){|w| + w.instance_eval{ + if idx = index(:active) + _ebox_placer(idx) + end + } + } + #------------------------------------ + + def configure(*args) + ret = super + + case cget(:state) + when 'normal' + # do nothing + when 'disabled' + _ebox_erase + else # unknown + # do nothing + + end + + ret + end + + def _ebox_move(idx) + return nil if cget(:state) == 'disabled' + x, y, w, h = bbox(idx) + return nil unless y && h @ebox.place(:x => 0, :relwidth => 1.0, - :y => y - self.selectborderwidth, - :height => h + 2 * self.selectborderwidth) + :y => y - selectborderwidth, + :height => h + 2 * selectborderwidth) @ebox.pos = idx - @ebox.value = self.listvariable.list[idx] @ebox.focus end - private :_ebox_placer + def _ebox_placer(idx) + return nil unless _ebox_move(idx) + @ebox.value = listvariable.list[idx] + @ebox.xview_moveto(self.xview[0]) + end + + def _ebox_erase + @ebox.place_forget + @ebox.pos = nil + end + private :_ebox_move, :_ebox_placer, :_ebox_erase + + def _setup_ebox_bindings + # bindings for entry + @ebox.bind('Return'){ + list = listvariable.list + list[@ebox.pos] = @ebox.value if @ebox.pos + listvariable.value = list + _ebox_erase + focus + } + + @ebox.bind('Escape'){ _ebox_erase } + end + def _setup_listbox_bindings + # bindings for listbox + tags = bindtags + bindtags(tags.insert(tags.index(self) + 1, self.class::BindTag)) + end + private :_setup_ebox_bindings, :_setup_listbox_bindings + + def yview(*args) + if !@ebox.pos || bbox(@ebox.pos).empty? + @ebox.place_forget + else + _ebox_move(@ebox.pos) + end + super + end def create_self(keys) super(keys) @@ -32,38 +119,30 @@ class Editable_TkListbox < TkListbox end @ebox = TkEntry.new(self){ - @pos = -1 + @pos = nil def self.pos; @pos; end def self.pos=(idx); @pos = idx; end } - @ebox.bind('Return'){ - list = self.listvariable.list - list[@ebox.pos] = @ebox.value - self.listvariable.value = list - @ebox.place_forget - @ebox.pos = -1 - } - - @ebox.bind('Escape'){ - @ebox.place_forget - @ebox.pos = -1 - } - - self.bind('Double-1', '%y'){|y| _ebox_placer(y) } + _setup_ebox_bindings + _setup_listbox_bindings end end if $0 == __FILE__ + #lbox0 = TkListbox.new.pack(:side=>:left) + #lbox0.insert(:end, 0,1,2,3,4,5,6,7,8,9,0,1,2,3) + scr = TkScrollbar.new.pack(:side=>:right, :fill=>:y) - lbox1 = Editable_TkListbox.new.pack(:side=>:left) - lbox2 = Editable_TkListbox.new.pack(:side=>:left) + lbox1 = Tk::RbWidget::Editable_Listbox.new.pack(:side=>:left) + lbox2 = Tk::RbWidget::Editable_Listbox.new.pack(:side=>:left) scr.assign(lbox1, lbox2) lbox1.insert(:end, *%w(a b c d e f g h i j k l m n)) lbox2.insert(:end, 0,1,2,3,4,5,6,7,8,9,0,1,2,3) + Tk.mainloop end diff --git a/ext/tk/sample/menubar3.rb b/ext/tk/sample/menubar3.rb new file mode 100644 index 0000000000..129cfd779b --- /dev/null +++ b/ext/tk/sample/menubar3.rb @@ -0,0 +1,72 @@ +# +# menubar sample 3 : vertical layout menubar; use frame and menubuttons +# + +require 'tk' + +radio_var = TkVariable.new('y') + +menu_spec = [ + [['&File', true], # when underline option is ture, '&' index is the position + {:label=>'Open', :command=>proc{puts('Open clicked')}, :underline=>0}, + '---', + ['Check_A', TkVariable.new(true), 6], + {:type=>'checkbutton', :label=>'Check_B', + :variable=>TkVariable.new, :underline=>6}, + '---', + ['Radio_X', [radio_var, 'x'], /[XYZ]/, '', {:foreground=>'black'}], + ['Radio_Y', [radio_var, 'y'], /[XYZ]/], + ['Radio_Z', [radio_var, 'z'], /[XYZ]/], # use Regexp for underline position + '---', + ['cascade', [ + ['sss', proc{p 'sss'}, 0], + ['ttt', proc{p 'ttt'}, 0], + ['uuu', proc{p 'uuu'}, 0], + ['vvv', proc{p 'vvv'}, 0], + ], + 0, '', + {:font=>'Courier 16 italic', + :menu_config=>{:font=>'Times -18 bold', :foreground=>'black'}}], + '---', + ['Quit', proc{exit}, 0]], + + [['Edit', 0], + ['Cut', proc{puts('Cut clicked')}, 2], + ['Copy', proc{puts('Copy clicked')}, 0], + ['Paste', proc{puts('Paste clicked')}, 0]], + + [['Help', 0, {:menu_name=>'help'}], + ['About This', proc{puts('Ruby/Tk menubar sample 3')}, "This"]] + # use string index for underline position +] + +layout_proc = 'vertical' +# The following procedure is same to 'layout_proc'=>'vertical' +=begin +layout_proc = proc{|parent, mbtn| + mbtn.direction :right + mbtn.pack(:side=>:top, :fill=>:x) + + menu = mbtn.menu + cmd = proc{|m, dir| + Tk::Menu::TkInternalFunction.next_menu(m, dir) rescue nil + # ignore error when the internal function doesn't exist + } + menu.bind('Tab', cmd, :widget, 'forward') + menu.bind('Alt-Tab', cmd, :widget, 'backward') +} +=end + +menubar = TkMenubar.new(nil, menu_spec, + 'layout_proc'=>layout_proc, + 'tearoff'=>false, + 'foreground'=>'grey40', + 'activeforeground'=>'red', + 'font'=>'Helvetia 12 bold') +menubar.pack('side'=>'left', 'fill'=>'y') + +TkText.new(:wrap=>'word').pack.insert('1.0', 'This sample script generates "Menu Sidebar". +If "::tk::MenuNextMenuon" function is available your Tcl/Tk library, you will be able to move to the next menu by Tab key on the posted menu, or the previous menu by Alt + Tab key. +Please read the sample source, and check how to override default configure options of menu entries on a menu_spec. Maybe, on windows, this menubar does not work properly about keyboard shortcuts. Then, please use "menu" option of root/toplevel widget (see sample/menubar3.rb).') + +Tk.mainloop diff --git a/ext/tk/sample/multi-ip_sample.rb b/ext/tk/sample/multi-ip_sample.rb index 8150e69c73..eccf0201f8 100644 --- a/ext/tk/sample/multi-ip_sample.rb +++ b/ext/tk/sample/multi-ip_sample.rb @@ -19,7 +19,6 @@ cmd = Proc.new{|txt| else root = TkRoot.new(:title=>'timer sample') end - label = TkLabel.new(:parent=>root, :relief=>:raised, :width=>10) \ .pack(:side=>:bottom, :fill=>:both) @@ -48,6 +47,7 @@ cmd = Proc.new{|txt| b_start = TkButton.new(:text=>'Start', :state=>:disabled) { pack(:side=>:left, :fill=>:both, :expand=>true) } + b_stop = TkButton.new(:text=>'Stop', :state=>:normal) { pack('side'=>'left', 'fill'=>'both', 'expand'=>'yes') } @@ -80,6 +80,7 @@ safe_slave2.eval_proc(cmd, 'safe2') # label -> .w00020 cmd.call('master') # label -> .w00024 #second_master = MultiTkIp.new(&cmd) +#second_master = MultiTkIp.new(:safe=>2){p [:second_master, $SAFE]} TkTimer.new(2000, -1, proc{p ['safe1', safe_slave1.deleted?]}).start TkTimer.new(2000, -1, proc{p ['safe2', safe_slave2.deleted?]}).start diff --git a/ext/tk/sample/safe-tk.rb b/ext/tk/sample/safe-tk.rb index e2408480d1..148548efb2 100644 --- a/ext/tk/sample/safe-tk.rb +++ b/ext/tk/sample/safe-tk.rb @@ -11,13 +11,16 @@ TkFrame.new(:borderwidth=>2, :height=>3, :relief=>:sunken).pack(:fill=>:x, :expand=>true, :padx=>10, :pady=>7) +safe0_p = proc{|*args| p args} + ############################### puts "---- create a safe slave IP with Ruby's safe-level == 1 ----------" -ip = MultiTkIp.new_safe_slave(1) +ip = MultiTkIp.new_safe_slave(1){|*args| safe0_p["safe_slave safe_level == #{$SAFE}", args]} puts "\n---- create procs ----------" puts 'x = proc{p [\'proc x\', "$SAFE==#{$SAFE}"]; exit}' +#x = proc{p ['proc x', "$SAFE==#{$SAFE}"]; exit} x = proc{p ['proc x', "$SAFE==#{$SAFE}"]; exit} TkLabel.new(:text=>'x = proc{p [\'proc x\', "$SAFE==#{$SAFE}"]; exit}', :anchor=>:w).pack(:fill=>:x) @@ -46,7 +49,9 @@ p lbl = ip.eval_proc{ :command=>proc{l.text($SAFE)}).pack(:fill=>:x, :padx=>5) TkButton.new(:text=>':command=>x', :command=>x).pack(:fill=>:x, :padx=>5) TkButton.new(:text=>':command=>proc{exit}', - :command=>proc{exit}).pack(:fill=>:x, :padx=>5) + :command=>proc{ + safe0_p["'exit' is called at $SAFE=#{$SAFE}"];exit} + ).pack(:fill=>:x, :padx=>5) TkFrame.new(:borderwidth=>2, :height=>3, :relief=>:sunken).pack(:fill=>:x, :expand=>true, :padx=>10, :pady=>7) @@ -68,10 +73,24 @@ p ip.eval_proc(proc{ TkButton.new(:text=>':command=>proc{y.call(l)}', :command=>proc{y.call(l)}).pack(:fill=>:x, :padx=>5) + TkButton.new(:text=>':command=>proc{Proc.new(&y).call(l)}', + :command=>proc{ + Proc.new(&y).call(l) + }).pack(:fill=>:x, :padx=>5) + TkButton.new(:text=>':command=>proc{MultiTkIp._proc_on_current_safelevel(y).call(l)}', + :command=>proc{ + MultiTkIp._proc_on_current_safelevel(y).call(l) + }).pack(:fill=>:x, :padx=>5) +if Object.const_defined?(:RubyVM) && ::RubyVM.class == Class TkButton.new(:text=>':command=>proc{Thread.new(l, &y).value}', :command=>proc{ Thread.new(l, &y).value }).pack(:fill=>:x, :padx=>5) +else + # KNOWN BUG:: + # Current multi-tk.rb cannot support long term threads on callbacks. + # Such a thread freezes the Ruby/Tk process. +end TkButton.new(:text=>':command=>proc{z.call}', :command=>proc{z.call}).pack(:fill=>:x, :padx=>5) TkFrame.new(:borderwidth=>2, :height=>3, diff --git a/ext/tk/sample/scrollframe.rb b/ext/tk/sample/scrollframe.rb index ab7a9ce24b..6a9381d465 100644 --- a/ext/tk/sample/scrollframe.rb +++ b/ext/tk/sample/scrollframe.rb @@ -1,11 +1,11 @@ # -# Tk::ScrollFrame class +# Tk::RbWidget::ScrollFrame class # # This widget class is a frame widget with scrollbars. # The ScrollFrame doesn't propagate the size of embedded widgets. # When it is configured, scrollregion of the container is changed. # -# Scrollbars can be toggled by Tk::ScrollFrame#vscroll & hscroll. +# Scrollbars can be toggled by Tk::RbWidget::ScrollFrame#vscroll & hscroll. # If horizontal or virtical scrollbar is turned off, the horizontal # or virtical size of embedded widgets is propagated. # @@ -13,7 +13,7 @@ # require 'tk' -class Tk::ScrollFrame < TkFrame +class Tk::RbWidget::ScrollFrame < TkFrame include TkComposite DEFAULT_WIDTH = 200 @@ -209,7 +209,8 @@ end # test if __FILE__ == $0 - f = Tk::ScrollFrame.new(:scrollbarwidth=>10, :width=>300, :height=>200) + f = Tk::RbWidget::ScrollFrame.new(:scrollbarwidth=>10, + :width=>300, :height=>200) f.pack(:expand=>true, :fill=>:both) TkButton.new(f, :text=>'foo button', :command=>proc{puts 'foo'}).pack @@ -220,17 +221,26 @@ if __FILE__ == $0 # f.hscroll(false) + # add a text widget Tk.after(3000){ t = TkText.new(f).pack(:expand=>true, :fill=>:both) - t.insert(:end, 'Here is a text widget') + t.insert(:end, "An example of Tk::RbWidget::ScrollFrame widget.\n\n") + t.insert(:end, "Here is a text widget.\n") + t.insert(:end, "Please resize the application window, ") + t.insert(:end, "and try the scrollbars ") + t.insert(:end, "to move the view of packed widgets.\n") } + # remove a vertical scrollbar, and then the scrollframe is not scrollable. Tk.after(6000){ f.vscroll(false) } + # add a vertical scrollbar, and make the scrollframe scrollable. Tk.after(9000){ f.vscroll(true) } + # remove a horizontal scrollbar, and then the scrollframe is not scrollable. Tk.after(12000){ f.hscroll(false) } + # add a horizontal scrollbar, and make the scrollframe scrollable. Tk.after(15000){ f.hscroll(true) } Tk.mainloop diff --git a/ext/tk/sample/tkalignbox.rb b/ext/tk/sample/tkalignbox.rb index dd82b50360..fb1b58f458 100644 --- a/ext/tk/sample/tkalignbox.rb +++ b/ext/tk/sample/tkalignbox.rb @@ -10,10 +10,17 @@ require 'tk' -class TkAlignBox < TkFrame +module Tk + module RbWidget + class AlignBox < TkFrame + end + end +end + +class Tk::RbWidget::AlignBox < TkFrame def initialize(*args) - if self.class == TkAlignBox - fail RuntimeError, "TkAlignBox is an abstract class" + if self.class == Tk::RbWidget::AlignBox + fail RuntimeError, "Tk::AlignBox is an abstract class" end @padx = 0 @pady = 0 @@ -31,12 +38,12 @@ class TkAlignBox < TkFrame end def _set_framesize - fail RuntimeError, "TkAlignBox is an abstract class" + fail RuntimeError, "Tk::AlignBox is an abstract class" end private :_set_framesize def _place_config(widget, idx, cnt) - fail RuntimeError, "TkAlignBox is an abstract class" + fail RuntimeError, "Tk::AlignBox is an abstract class" end private :_place_config @@ -117,7 +124,7 @@ class TkAlignBox < TkFrame attr_accessor :propagate end -class TkHBox < TkAlignBox +class Tk::RbWidget::HBox < Tk::RbWidget::AlignBox def _set_framesize bd = self.borderwidth self.width((@max_width + 2*@padx) * @widgets.size + 2*bd) @@ -134,9 +141,9 @@ class TkHBox < TkAlignBox end private :_place_config end -TkHLBox = TkHBox +Tk::RbWidget::HLBox = Tk::RbWidget::HBox -class TkHRBox < TkHBox +class Tk::RbWidget::HRBox < Tk::RbWidget::HBox def _place_config(widget, idx, cnt) widget.place_in(self, 'relx'=>(cnt - idx - 1)/cnt, 'x'=>@padx, @@ -147,7 +154,7 @@ class TkHRBox < TkHBox private :_place_config end -class TkVBox < TkAlignBox +class Tk::RbWidget::VBox < Tk::RbWidget::AlignBox def _set_framesize bd = self.borderwidth self.width(@max_width + 2*@padx + 2*bd) @@ -164,9 +171,9 @@ class TkVBox < TkAlignBox end private :_place_config end -TkVTBox = TkVBox +Tk::RbWidget::VTBox = Tk::RbWidget::VBox -class TkVBBox < TkVBox +class Tk::RbWidget::VBBox < Tk::RbWidget::VBox def _place_config(widget, idx, cnt) widget.place_in(self, 'relx'=>0, 'x'=>@padx, @@ -181,31 +188,34 @@ end # test ################################################ if __FILE__ == $0 - f = TkHBox.new(:borderwidth=>3, :relief=>'ridge').pack + f = Tk::RbWidget::HBox.new(:borderwidth=>3, :relief=>'ridge').pack f.add(TkButton.new(f, :text=>'a'), TkButton.new(f, :text=>'aa', :font=>'Helvetica 16'), TkButton.new(f, :text=>'aaa'), TkButton.new(f, :text=>'aaaa')) - f = TkHBox.new(:borderwidth=>3, :relief=>'ridge', - :padx=>7, :pady=>3, :background=>'yellow').pack + f = Tk::RbWidget::HBox.new(:borderwidth=>3, :relief=>'ridge', + :padx=>7, :pady=>3, :background=>'yellow').pack f.add(TkButton.new(f, :text=>'a'), TkButton.new(f, :text=>'aa', :font=>'Helvetica 16'), TkButton.new(f, :text=>'aaa'), TkButton.new(f, :text=>'aaaa')) - f = TkVBox.new(:borderwidth=>5, :relief=>'groove').pack + f = Tk::RbWidget::VBox.new(:borderwidth=>5, + :relief=>'groove').pack(:fill=>:y, :expand=>true) f.add(TkButton.new(f, :text=>'a'), TkButton.new(f, :text=>'aa', :font=>'Helvetica 30'), TkButton.new(f, :text=>'aaa'), TkButton.new(f, :text=>'aaaa')) - f = TkHRBox.new(:borderwidth=>3, :relief=>'raised').pack(:fill=>:x) + f = Tk::RbWidget::HRBox.new(:borderwidth=>3, + :relief=>'raised').pack(:fill=>:x) f.add(TkButton.new(f, :text=>'a'), TkButton.new(f, :text=>'aa'), TkButton.new(f, :text=>'aaa')) - f = TkVBBox.new(:borderwidth=>3, :relief=>'ridge').pack(:fill=>:x) + f = Tk::RbWidget::VBBox.new(:borderwidth=>3, + :relief=>'ridge').pack(:fill=>:x) f.propagate = false f.height 100 f.add(TkFrame.new(f){|ff| diff --git a/ext/tk/sample/tkballoonhelp.rb b/ext/tk/sample/tkballoonhelp.rb index fc99753b81..a9bd371db6 100644 --- a/ext/tk/sample/tkballoonhelp.rb +++ b/ext/tk/sample/tkballoonhelp.rb @@ -7,11 +7,21 @@ # please try to use the Tix extension of Tcl/Tk under Ruby/Tk. # # The interval time to display a balloon help is defined 'interval' option -# (default is 1000ms). +# (default is 750ms). # require 'tk' -class TkBalloonHelp'bisque').pack + # @label = TkLabel.new(@frame, 'background'=>'bisque').pack + @label = TkLabel.new(@frame, + 'foreground'=>DEFAULT_FOREGROUND, + 'background'=>DEFAULT_BACKGROUND).pack @label.configure(_symbolkey2str(keys)) unless keys.empty? @path = @label end @@ -118,41 +131,42 @@ end if __FILE__ == $0 TkButton.new('text'=>'This button has a balloon help') {|b| pack('fill'=>'x') - TkBalloonHelp.new(b, 'text'=>' Message ') + Tk::RbWidget::BalloonHelp.new(b, 'text'=>' Message ') } TkButton.new('text'=>'This button has another balloon help') {|b| pack('fill'=>'x') - TkBalloonHelp.new(b, 'text'=>'configured message', - 'interval'=>200, 'font'=>'courier', - 'background'=>'gray', 'foreground'=>'red') + Tk::RbWidget::BalloonHelp.new(b, + 'text'=>"CONFIGURED MESSAGE\nchange colors, and so on", + 'interval'=>200, 'font'=>'courier', + 'background'=>'gray', 'foreground'=>'red') } sb = TkScrollbox.new.pack(:fill=>:x) sb.insert(:end, *%w(aaa bbb ccc ddd eee fff ggg hhh iii jjj kkk lll mmm)) =begin # CASE1 : command takes no arguemnt - bh = TkBalloonHelp.new(sb, :interval=>500, - :relief=>:ridge, :background=>'white', - :command=>proc{ - y = TkWinfo.pointery(sb) - TkWinfo.rooty(sb) - bh.text "current index == #{sb.nearest(y)}" - }) + bh = Tk::RbWidget::BalloonHelp.new(sb, :interval=>500, + :relief=>:ridge, :background=>'white', + :command=>proc{ + y = TkWinfo.pointery(sb) - TkWinfo.rooty(sb) + bh.text "current index == #{sb.nearest(y)}" + }) =end =begin # CASE2 : command takes 2 arguemnts - bh = TkBalloonHelp.new(sb, :interval=>500, - :relief=>:ridge, :background=>'white', - :command=>proc{|x, y| - bh.text "current index == #{sb.nearest(y)}" - }) + bh = Tk::RbWidget::BalloonHelp.new(sb, :interval=>500, + :relief=>:ridge, :background=>'white', + :command=>proc{|x, y| + bh.text "current index == #{sb.nearest(y)}" + }) =end =begin # CASE3 : command takes 3 arguemnts - TkBalloonHelp.new(sb, :interval=>500, - :relief=>:ridge, :background=>'white', - :command=>proc{|x, y, bhelp| - bhelp.text "current index == #{sb.nearest(y)}" - }) + Tk::RbWidget::BalloonHelp.new(sb, :interval=>500, + :relief=>:ridge, :background=>'white', + :command=>proc{|x, y, bhelp| + bhelp.text "current index == #{sb.nearest(y)}" + }) =end =begin # CASE4a : command is a Proc object and takes 4 arguemnts @@ -160,16 +174,16 @@ if __FILE__ == $0 bhelp.text "current index == #{parent.nearest(y)}" } - TkBalloonHelp.new(sb, :interval=>500, - :relief=>:ridge, :background=>'white', - :command=>cmd) + Tk::RbWidget::BalloonHelp.new(sb, :interval=>500, + :relief=>:ridge, :background=>'white', + :command=>cmd) sb2 = TkScrollbox.new.pack(:fill=>:x) sb2.insert(:end, *%w(AAA BBB CCC DDD EEE FFF GGG HHH III JJJ KKK LLL MMM)) - TkBalloonHelp.new(sb2, :interval=>500, - :padx=>5, :relief=>:raised, - :background=>'gray25', :foreground=>'white', - :command=>cmd) + Tk::RbWidget::BalloonHelp.new(sb2, :interval=>500, + :padx=>5, :relief=>:raised, + :background=>'gray25', :foreground=>'white', + :command=>cmd) =end #=begin # CASE4b : command is a Method object and takes 4 arguemnts @@ -178,16 +192,16 @@ if __FILE__ == $0 end cmd = self.method(:set_msg) - TkBalloonHelp.new(sb, :interval=>500, - :relief=>:ridge, :background=>'white', - :command=>cmd) + Tk::RbWidget::BalloonHelp.new(sb, :interval=>500, + :relief=>:ridge, :background=>'white', + :command=>cmd) sb2 = TkScrollbox.new.pack(:fill=>:x) sb2.insert(:end, *%w(AAA BBB CCC DDD EEE FFF GGG HHH III JJJ KKK LLL MMM)) - TkBalloonHelp.new(sb2, :interval=>500, - :padx=>5, :relief=>:raised, - :background=>'gray25', :foreground=>'white', - :command=>cmd) + Tk::RbWidget::BalloonHelp.new(sb2, :interval=>500, + :padx=>5, :relief=>:raised, + :background=>'gray25', :foreground=>'white', + :command=>cmd) #=end Tk.mainloop diff --git a/ext/tk/sample/tkcombobox.rb b/ext/tk/sample/tkcombobox.rb index 941f7cc4cb..59db565f06 100644 --- a/ext/tk/sample/tkcombobox.rb +++ b/ext/tk/sample/tkcombobox.rb @@ -1,11 +1,20 @@ # -# tkcombobox.rb : TkAutoScrollbox & TkCombobox +# tkcombobox.rb : auto scrollbox & combobox # # by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) # require 'tk' -class TkAutoScrollbox < TkListbox +module Tk + module RbWidget + class AutoScrollListbox < TkListbox + end + class Combobox < TkEntry + end + end +end + +class Tk::RbWidget::AutoScrollListbox include TkComposite @@up_bmp = TkBitmapImage.new(:data=><<= 0 - @ent.value = @lst.get(idx) + @wait_var.tkwait + if (idx = @wait_var.to_i) >= 0 + # @ent.value = @lst.get(idx) + _set_entry_value(@lst.get(idx)) end @top.withdraw @btn.relief(:raised) @@ -297,18 +298,65 @@ EOD @btn.bind('1', proc{_button_proc(true)}) @btn.bind('3', proc{_button_proc(false)}) - @lst.bind('1', proc{|y| @var.value = @lst.nearest(y)}, '%y') - @lst.bind('Return', proc{@var.value = @lst.curselection[0]}) + @lst.bind('1', proc{|y| @wait_var.value = @lst.nearest(y)}, '%y') + @lst.bind('Return', proc{@wait_var.value = @lst.curselection[0]}) cancel = TkVirtualEvent.new('2', '3', 'Escape') - @lst.bind(cancel, proc{@var.value = -1}) + @lst.bind(cancel, proc{@wait_var.value = -1}) end private :_init_bindings + def _set_entry_value(val) + @ent.textvariable.value = val + end + private :_set_entry_value + + #---------------------------------------------------- + + def _state_control(value = None) + if value == None + # get + @ent.state + else + # set + @ent.state(value.to_s) + case value = @ent.state # regulate 'state' string + when 'normal', 'readonly' + @btn.state 'normal' + when 'disabled' + @btn.state 'disabled' + else + # unknown : do nothing + end + end + end + private :_state_control + + def __methodcall_optkeys # { key=>method, ... } + {'state' => :_state_control} + end + private :__methodcall_optkeys + + #---------------------------------------------------- + + def _textvariable_control(var = None) + if var == None + # get + ((var = @ent.textvariable) === @default_var)? nil: var + else + # set + @var = var + tk_send('configure', '-textvariable', (@var)? var: @default_var) + end + end + private :_textvariable_control + + #---------------------------------------------------- + def initialize_composite(keys={}) keys = _symbolkey2str(keys) - @btn = TkLabel.new(@frame, :relief=>:raised, :borderwidth=>3, + @btn = TkLabel.new(@frame, :relief=>:raised, :borderwidth=>2, :image=>@@down_btn_bmp).pack(:side=>:right, :ipadx=>2, :fill=>:y) @ent = TkEntry.new(@frame).pack(:side=>:left) @@ -322,16 +370,21 @@ EOD startwait = keys.delete('startwait'){300} interval = keys.delete('interval'){150} - @lst = TkAutoScrollbox.new(@top, - :startwait=>startwait, - :interval=>interval).pack(:fill=>:both, - :expand=>true) + @lst = Tk::RbWidget::AutoScrollListbox.new(@top, :scrollbar=>true, + :startwait=>startwait, + :interval=>interval) + @lst.pack(:fill=>:both, :expand=>true) @ent_list = [] - @var = TkVariable.new + @wait_var = TkVariable.new + @var = @default_var = TkVariable.new + + @ent.textvariable @default_var _init_bindings + option_methods('textvariable' => :_textvariable_control) + delegate('DEFAULT', @ent) delegate('height', @lst) delegate('relief', @frame) @@ -340,6 +393,8 @@ EOD delegate('arrowrelief', @lst) delegate('arrowborderwidth', @lst) + delegate('state', false) + if mode = keys.delete('scrollbar') scrollbar(mode) end @@ -405,10 +460,14 @@ end # test ################################################ if __FILE__ == $0 +# e0 = Tk::RbWidget::Combobox.new.pack +# e0.values(%w(aa bb cc dd ee ff gg hh ii jj kk ll mm nn oo pp qq rr ss tt uu)) + v = TkVariable.new - e = TkCombobox.new(:height=>7, :scrollbar=>true, :textvariable=>v, - :arrowrelief=>:flat, :arrowborderwidth=>0, - :startwait=>400, :interval=>200).pack + e = Tk::RbWidget::Combobox.new(:height=>7, :scrollbar=>true, + :textvariable=>v, + :arrowrelief=>:flat, :arrowborderwidth=>0, + :startwait=>400, :interval=>200).pack e.values(%w(aa bb cc dd ee ff gg hh ii jj kk ll mm nn oo pp qq rr ss tt uu)) #e.see(e.list_index('end') - 2) e.value = 'cc' @@ -421,8 +480,10 @@ if __FILE__ == $0 TkFrame.new(:relief=>:raised, :borderwidth=>2, :height=>3).pack(:fill=>:x, :expand=>true, :padx=>5, :pady=>3) - l = TkAutoScrollbox.new(nil, :relief=>:groove, :borderwidth=>4, - :width=>20).pack(:fill=>:both, :expand=>true) + l = Tk::RbWidget::AutoScrollListbox.new(nil, :relief=>:groove, + :borderwidth=>4,:height=>7, + :width=>20).pack(:fill=>:both, + :expand=>true) (0..20).each{|i| l.insert('end', "line #{i}")} TkFrame.new(:relief=>:ridge, :borderwidth=>3){ diff --git a/ext/tk/sample/tktextframe.rb b/ext/tk/sample/tktextframe.rb index d50f2e5d88..b2b40c9138 100644 --- a/ext/tk/sample/tktextframe.rb +++ b/ext/tk/sample/tktextframe.rb @@ -5,9 +5,53 @@ # require 'tk' -class TkTextFrame < TkText +module Tk::ScrollbarComposite include TkComposite + def component_construct_keys + # If a component requires options for construction, + # return an Array of option-keys. + [] + end + private :component_construct_keys + + def create_component(keys={}) + # This method must return the created component widget. + end + private :create_component + + def component_delegates + # if want to override defalut option-methods or delegates, + # please define here. + end + private :component_delegates + + def define_delegates + # option methods for scrollbars + option_methods([:scrollbarwidth, :get_scrollbarwidth]) + + # set receiver widgets for configure methods (with alias) + delegate_alias('scrollbarrelief', 'relief', @h_scroll, @v_scroll) + delegate_alias('framebackground', 'background', + @frame, @h_scroll, @v_scroll) + delegate_alias('activeframebackground', 'activebackground', + @h_scroll, @v_scroll) + + # set receiver widgets for configure methods + delegate('DEFAULT', @component) + delegate('troughcolor', @h_scroll, @v_scroll) + delegate('repeatdelay', @h_scroll, @v_scroll) + delegate('repeatinterval', @h_scroll, @v_scroll) + delegate('borderwidth', @frame) + delegate('relief', @frame) + + component_delegates + end + private :define_delegates + + DEFAULT_VSCROLL = true + DEFAULT_HSCROLL = true + def initialize_composite(keys={}) keys = _symbolkey2str(keys) @@ -15,55 +59,123 @@ class TkTextFrame < TkText @v_scroll = TkScrollbar.new(@frame, 'orient'=>'vertical') @h_scroll = TkScrollbar.new(@frame, 'orient'=>'horizontal') - # create a text widget - @text = TkText.new(@frame, 'wrap'=>'none') + # create a component + construct_keys = {} + ((component_construct_keys.map{|k| k.to_s}) & keys.keys).each{|k| + construct_keys[k] = keys.delete(k) + } + + # create a component (the component must be scrollable) + @component = create_component(construct_keys) # set default receiver of method calls - @path = @text.path + @path = @component.path # assign scrollbars - @text.xscrollbar(@h_scroll) - @text.yscrollbar(@v_scroll) + @component.xscrollbar(@h_scroll) + @component.yscrollbar(@v_scroll) # allignment TkGrid.rowconfigure(@frame, 0, 'weight'=>1, 'minsize'=>0) TkGrid.columnconfigure(@frame, 0, 'weight'=>1, 'minsize'=>0) - @text.grid('row'=>0, 'column'=>0, 'sticky'=>'news') + @component.grid('row'=>0, 'column'=>0, 'sticky'=>'news') # scrollbars ON - vscroll(keys.delete('vscroll'){true}) - hscroll(keys.delete('hscroll'){true}) - - # set background of the text widget -=begin - color = keys.delete('textbackground') - textbackground(color) if color -=end - # please check the differences of the following definitions + vscroll(keys.delete('vscroll'){self.class::DEFAULT_VSCROLL}) + hscroll(keys.delete('hscroll'){self.class::DEFAULT_HSCROLL}) + + # do configure + define_delegates + + # do configure + configure keys unless keys.empty? + end + private :initialize_composite + + # get/set width of scrollbar + def get_scrollbarwidth + @v_scroll.width + end + def set_scrollbarwidth(width) + @v_scroll.width(width) + @h_scroll.width(width) + end + alias :scrollbarwidth :set_scrollbarwidth + + def hook_vscroll_on(*args); end + def hook_vscroll_off(*args); end + def hook_hscroll_on(*args); end + def hook_hscroll_off(*args); end + private :hook_vscroll_on,:hook_vscroll_off,:hook_hscroll_on,:hook_hscroll_off + + # vertical scrollbar : ON/OFF + def vscroll(mode, *args) + st = TkGrid.info(@v_scroll) + if mode && st.size == 0 then + @v_scroll.grid('row'=>0, 'column'=>1, 'sticky'=>'ns') + hook_vscroll_on(*args) + elsif !mode && st.size != 0 then + @v_scroll.ungrid + hook_vscroll_off(*args) + end + self + end + + # horizontal scrollbar : ON/OFF + def hscroll(mode, *args) + st = TkGrid.info(@h_scroll) + if mode && st.size == 0 then + @h_scroll.grid('row'=>1, 'column'=>0, 'sticky'=>'ew') + hook_hscroll_on(*args) + elsif !mode && st.size != 0 then + @h_scroll.ungrid + hook_hscroll_off(*args) + end + self + end +end + +################################################ + +class TkTextFrame < TkText + include Tk::ScrollbarComposite + + # def component_construct_keys; []; end + # private :component_construct_keys + + def create_component(keys={}) + # keys has options which are listed by component_construct_keys method. + @text = TkText.new(@frame, 'wrap'=>'none') + @text.configure(keys) unless keys.empty? + + # option methods for component option_methods( - [:scrollbarwidth, :get_scrollbarwidth], [:textbackground, nil, :textbg_info], :textborderwidth, :textrelief ) - # set receiver widgets for configure methods (with alias) - delegate_alias('scrollbarrelief', 'relief', @h_scroll, @v_scroll) + # return the created componet + @text + end + private :create_component - # set receiver widgets for configure methods - delegate('DEFAULT', @text) - delegate('background', @frame, @h_scroll, @v_scroll) - delegate('activebackground', @h_scroll, @v_scroll) - delegate('troughcolor', @h_scroll, @v_scroll) - delegate('repeatdelay', @h_scroll, @v_scroll) - delegate('repeatinterval', @h_scroll, @v_scroll) - delegate('borderwidth', @frame) - delegate('relief', @frame) + # def component_delegates; end + # private :component_delegates - # do configure - configure keys unless keys.empty? + def hook_hscroll_on(wrap_mode=nil) + if wrap_mode + wrap wrap_mode + else + wrap 'none' # => self.wrap('none') + end + end + def hook_hscroll_off(wrap_mode) + wrap wrap_mode # => self.wrap(wrap_mode) + end + def hscroll(mode, wrap_mode="char") + super end - private :initialize_composite # set background color of text widget def textbackground(color = nil) @@ -103,47 +215,13 @@ class TkTextFrame < TkText def textrelief(type) @text.relief(type) end - - # get/set width of scrollbar - def get_scrollbarwidth - @v_scroll.width - end - def set_scrollbarwidth(width) - @v_scroll.width(width) - @h_scroll.width(width) - end - alias :scrollbarwidth :set_scrollbarwidth - - # vertical scrollbar : ON/OFF - def vscroll(mode) - st = TkGrid.info(@v_scroll) - if mode && st.size == 0 then - @v_scroll.grid('row'=>0, 'column'=>1, 'sticky'=>'ns') - elsif !mode && st.size != 0 then - @v_scroll.ungrid - end - self - end - - # horizontal scrollbar : ON/OFF - def hscroll(mode, wrap_mode="char") - st = TkGrid.info(@h_scroll) - if mode && st.size == 0 then - @h_scroll.grid('row'=>1, 'column'=>0, 'sticky'=>'ew') - wrap 'none' # => self.wrap('none') - elsif !mode && st.size != 0 then - @h_scroll.ungrid - wrap wrap_mode # => self.wrap(wrap_mode) - end - self - end end - ################################################ # test ################################################ if __FILE__ == $0 + TkLabel.new(:text=>'TkTextFrame is an example of Tk::ScrollbarComposite module.').pack f = TkFrame.new.pack('fill'=>'x') #t = TkTextFrame.new.pack t = TkTextFrame.new(:textborderwidth=>3, @@ -158,5 +236,46 @@ if __FILE__ == $0 'command'=>proc{t.hscroll(true)}).pack('side'=>'left') TkButton.new(f, 'text'=>'hscr OFF', 'command'=>proc{t.hscroll(false)}).pack('side'=>'left') + + ############################################ + + # Tk.default_widget_set = :Ttk + + TkFrame.new.pack(:pady=>10) + TkLabel.new(:text=>'The following is another example of Tk::ScrollbarComposite module.').pack + + #---------------------------------- + class ScrListbox < TkListbox + include Tk::ScrollbarComposite + + DEFAULT_HSCROLL = false + + def create_component(keys={}) + TkListbox.new(@frame, keys) + end + private :create_component + end + #---------------------------------- + + f = TkFrame.new.pack(:pady=>5) + lbox = ScrListbox.new(f).pack(:side=>:left) + lbox.value = %w(aa bb cc dd eeeeeeeeeeeeeeeeeeeeeeeeee ffffffffff gg hh ii jj kk ll mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm nn oo pp qq) + fb = TkFrame.new(f).pack(:expand=>true, :fill=>:y, :padx=>5) + TkButton.new(fb, 'text'=>'lbox hscr OFF', + 'command'=>proc{lbox.hscroll(false)}).pack(:side=>:bottom, + :fill=>:x) + TkButton.new(fb, 'text'=>'lbox hscr ON', + 'command'=>proc{lbox.hscroll(true)}).pack(:side=>:bottom, + :fill=>:x) + TkFrame.new(fb).pack(:pady=>5, :side=>:bottom) + TkButton.new(fb, 'text'=>'lbox vscr OFF', + 'command'=>proc{lbox.vscroll(false)}).pack(:side=>:bottom, + :fill=>:x) + TkButton.new(fb, 'text'=>'lbox vscr ON', + 'command'=>proc{lbox.vscroll(true)}).pack(:side=>:bottom, + :fill=>:x) + + ############################################ + Tk.mainloop end diff --git a/ext/tk/stubs.c b/ext/tk/stubs.c index e7ef79dda8..4388fb294d 100644 --- a/ext/tk/stubs.c +++ b/ext/tk/stubs.c @@ -11,6 +11,25 @@ /*------------------------------*/ +#ifdef __MACOS__ +# include +# include + +static int call_macinit = 0; + +static void +_macinit() +{ + if (!call_macinit) { + tcl_macQdPtr = &qd; /* setup QuickDraw globals */ + Tcl_MacSetEventProc(TkMacConvertEvent); /* setup event handler */ + call_macinit = 1; + } +} +#endif + +/*------------------------------*/ + static int nativethread_checked = 0; static void @@ -301,6 +320,10 @@ ruby_tk_stubs_init(tcl_ip) if (!Tk_InitStubs(tcl_ip, (char *)"8.1", 0)) return FAIL_Tk_InitStubs; + +#ifdef __MACOS__ + _macinit(); +#endif } return TCLTK_STUBS_OK; @@ -336,6 +359,10 @@ ruby_tk_stubs_safeinit(tcl_ip) if (!Tk_InitStubs(tcl_ip, (char *)"8.1", 0)) return FAIL_Tk_InitStubs; + +#ifdef __MACOS__ + _macinit(); +#endif } return TCLTK_STUBS_OK; @@ -490,6 +517,9 @@ ruby_tk_stubs_init(tcl_ip) return FAIL_Tk_Init; if (!call_tk_stubs_init) { +#ifdef __MACOS__ + _macinit(); +#endif call_tk_stubs_init = 1; } @@ -509,6 +539,9 @@ ruby_tk_stubs_safeinit(tcl_ip) return FAIL_Tk_Init; if (!call_tk_stubs_init) { +#ifdef __MACOS__ + _macinit(); +#endif call_tk_stubs_init = 1; } diff --git a/ext/tk/tcltklib.c b/ext/tk/tcltklib.c index 39c85da72d..cc3c0e9b8d 100644 --- a/ext/tk/tcltklib.c +++ b/ext/tk/tcltklib.c @@ -4,7 +4,7 @@ * Oct. 24, 1997 Y. Matsumoto */ -#define TCLTKLIB_RELEASE_DATE "2008-12-22" +#define TCLTKLIB_RELEASE_DATE "2009-07-12" #include "ruby.h" @@ -15,6 +15,25 @@ #include "version.h" #endif +#ifdef RUBY_VM +static VALUE rb_thread_critical; /* dummy */ +int rb_thread_check_trap_pending(); +#else +/* use rb_thread_critical on Ruby 1.8.x */ +#include "rubysig.h" +#endif + +#ifdef OBJ_UNTRUST +#define RbTk_OBJ_UNTRUST(x) do {OBJ_TAINT(x); OBJ_UNTRUST(x);} while (0) +#else +#define RbTk_OBJ_UNTRUST(x) OBJ_TAINT(x) +#endif + +#if defined(HAVE_RB_PROC_NEW) && !defined(RUBY_VM) +/* Ruby 1.8 :: rb_proc_new() was hidden from intern.h at 2008/04/22 */ +extern VALUE rb_proc_new _((VALUE (*)(ANYARGS/* VALUE yieldarg[, VALUE procarg] */), VALUE)); +#endif + #undef EXTERN /* avoid conflict with tcl.h of tcl8.2 or before */ #include #ifdef HAVE_STDARG_PROTOTYPES @@ -34,6 +53,7 @@ #else #define RUBY_USE_NATIVE_THREAD 1 #endif + #ifndef HAVE_RB_ERRINFO #define rb_errinfo() (ruby_errinfo+0) /* cannot be l-value */ #endif @@ -49,9 +69,6 @@ #define TCL_FINAL_RELEASE 2 /* "final" */ #endif -static VALUE rb_thread_critical; /* dummy */ -int rb_thread_check_trap_pending(); - static struct { int major; int minor; @@ -91,6 +108,14 @@ set_tcltk_version() # endif #endif +#ifndef CONST86 +# if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION <= 5 /* Tcl8.0.x -- 8.5.x */ +# define CONST86 +# else +# define CONST86 CONST84 +# endif +#endif + /* copied from eval.c */ #define TAG_RETURN 0x1 #define TAG_BREAK 0x2 @@ -191,10 +216,10 @@ static VALUE callq_safelevel_handler _((VALUE, VALUE)); /* Tcl's object type */ #if TCL_MAJOR_VERSION >= 8 static const char Tcl_ObjTypeName_ByteArray[] = "bytearray"; -static Tcl_ObjType *Tcl_ObjType_ByteArray; +static CONST86 Tcl_ObjType *Tcl_ObjType_ByteArray; static const char Tcl_ObjTypeName_String[] = "string"; -static Tcl_ObjType *Tcl_ObjType_String; +static CONST86 Tcl_ObjType *Tcl_ObjType_String; #if TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION >= 1) #define IS_TCL_BYTEARRAY(obj) ((obj)->typePtr == Tcl_ObjType_ByteArray) @@ -407,6 +432,7 @@ call_queue_mark(struct call_queue *q) static VALUE eventloop_thread; +static Tcl_Interp *eventloop_interp; #ifdef RUBY_USE_NATIVE_THREAD Tcl_ThreadId tk_eventloop_thread_id; /* native thread ID of Tcl interpreter */ #endif @@ -460,6 +486,8 @@ static int have_rb_thread_waiting_for_value = 0; #define NO_THREAD_INTERRUPT_TIME 100/*milliseconds ( 1 -- 999 ) */ #endif +#define EVENT_HANDLER_TIMEOUT 100/*milliseconds*/ + static int event_loop_max = DEFAULT_EVENT_LOOP_MAX; static int no_event_tick = DEFAULT_NO_EVENT_TICK; static int no_event_wait = DEFAULT_NO_EVENT_WAIT; @@ -1630,6 +1658,7 @@ trap_check(int *check_var) { DUMP1("trap check"); +#ifdef RUBY_VM if (rb_thread_check_trap_pending()) { if (check_var != (int*)NULL) { /* wait command */ @@ -1639,10 +1668,34 @@ trap_check(int *check_var) rb_thread_check_ints(); } } +#else + if (rb_trap_pending) { + run_timer_flag = 0; + if (rb_prohibit_interrupt || check_var != (int*)NULL) { + /* pending or on wait command */ + return 0; + } else { + rb_trap_exec(); + } + } +#endif return 1; } +static int +check_eventloop_interp() +{ + DUMP1("check eventloop_interp"); + if (eventloop_interp != (Tcl_Interp*)NULL + && Tcl_InterpDeleted(eventloop_interp)) { + DUMP2("eventloop_interp(%p) was deleted", eventloop_interp); + return 1; + } + + return 0; +} + static int lib_eventloop_core(check_root, update_flag, check_var, interp) int check_root; @@ -1684,6 +1737,8 @@ lib_eventloop_core(check_root, update_flag, check_var, interp) #endif for(;;) { + if (check_eventloop_interp()) return 0; + #if USE_EVLOOP_THREAD_ALONE_CHECK_FLAG if (thread_alone_check_flag && rb_thread_alone()) { #else @@ -1776,6 +1831,7 @@ lib_eventloop_core(check_root, update_flag, check_var, interp) } TRAP_CHECK(); + if (check_eventloop_interp()) return 0; DUMP1("check Root Widget"); if (check_root && tk_stubs_init_p() && Tk_GetNumMainWindows() == 0) { @@ -1962,6 +2018,7 @@ lib_eventloop_core(check_root, update_flag, check_var, interp) } TRAP_CHECK(); + if (check_eventloop_interp()) return 0; DUMP1("check Root Widget"); if (check_root && tk_stubs_init_p() && Tk_GetNumMainWindows() == 0) { @@ -2205,6 +2262,7 @@ ip_mainloop(argc, argv, self) VALUE *argv; VALUE self; { + volatile VALUE ret; struct tcltkip *ptr = get_ip(self); /* ip is deleted? */ @@ -2216,7 +2274,11 @@ ip_mainloop(argc, argv, self) /* slave IP */ return Qnil; } - return lib_mainloop(argc, argv, self); + + eventloop_interp = ptr->ip; + ret = lib_mainloop(argc, argv, self); + eventloop_interp = (Tcl_Interp*)NULL; + return ret; } @@ -2306,7 +2368,7 @@ lib_mainloop_watchdog(argc, argv, self) { VALUE check_rootwidget; -#ifdef RUBY_USE_NATIVE_THREAD +#ifdef RUBY_VM rb_raise(rb_eNotImpError, "eventloop_watchdog is not implemented on Ruby VM."); #endif @@ -2812,7 +2874,17 @@ tcl_protect(interp, proc, data) #endif #endif +#ifdef RUBY_VM code = tcl_protect_core(interp, proc, data); +#else + do { + int old_trapflag = rb_trap_immediate; + rb_trap_immediate = 0; + code = tcl_protect_core(interp, proc, data); + rb_trap_immediate = old_trapflag; + } while (0); +#endif + return code; } @@ -2906,6 +2978,7 @@ ip_ruby_cmd_core(arg) thr_crit_bup = rb_thread_critical; rb_thread_critical = Qfalse; ret = rb_apply(arg->receiver, arg->method, arg->args); + DUMP2("rb_apply return:%lx", ret); rb_thread_critical = thr_crit_bup; DUMP1("finish ip_ruby_cmd_core"); @@ -3374,7 +3447,11 @@ ip_rbUpdateCommand(clientData, interp, objc, objv) } /* trap check */ +#ifdef RUBY_VM if (rb_thread_check_trap_pending()) { +#else + if (rb_trap_pending) { +#endif Tcl_Release(interp); return TCL_RETURN; @@ -3442,6 +3519,7 @@ ip_rb_threadUpdateCommand(clientData, interp, objc, objv) static CONST char *updateOptions[] = {"idletasks", (char *) NULL}; enum updateOptions {REGEXP_IDLETASKS}; volatile VALUE current_thread = rb_thread_current(); + struct timeval t; DUMP1("Ruby's 'thread_update' is called"); if (interp == (Tcl_Interp*)NULL) { @@ -3529,10 +3607,17 @@ ip_rb_threadUpdateCommand(clientData, interp, objc, objv) DUMP1("set idle proc"); Tcl_DoWhenIdle(rb_threadUpdateProc, (ClientData) param); + t.tv_sec = (time_t)0; + t.tv_usec = (long)((EVENT_HANDLER_TIMEOUT)*1000.0); + while(!param->done) { - DUMP1("wait for complete idle proc"); - /* rb_thread_stop(); */ - rb_thread_sleep_forever(); + DUMP1("wait for complete idle proc"); + /* rb_thread_stop(); */ + /* rb_thread_sleep_forever(); */ + rb_thread_wait_for(t); + if (NIL_P(eventloop_thread)) { + break; + } } #if 0 /* use Tcl_EventuallyFree */ @@ -3740,7 +3825,11 @@ ip_rbVwaitCommand(clientData, interp, objc, objv) } /* trap check */ +#ifdef RUBY_VM if (rb_thread_check_trap_pending()) { +#else + if (rb_trap_pending) { +#endif #if TCL_MAJOR_VERSION >= 8 Tcl_DecrRefCount(objv[1]); #endif @@ -4029,7 +4118,11 @@ ip_rbTkWaitCommand(clientData, interp, objc, objv) } /* trap check */ - if (rb_thread_check_trap_pending()) { +#ifdef RUBY_VM + if (rb_thread_check_trap_pending()) { +#else + if (rb_trap_pending) { +#endif Tcl_Release(interp); return TCL_RETURN; @@ -4089,7 +4182,11 @@ ip_rbTkWaitCommand(clientData, interp, objc, objv) } /* trap check */ - if (rb_thread_check_trap_pending()) { +#ifdef RUBY_VM + if (rb_thread_check_trap_pending()) { +#else + if (rb_trap_pending) { +#endif #if TCL_MAJOR_VERSION >= 8 Tcl_DecrRefCount(objv[2]); #endif @@ -4184,7 +4281,11 @@ ip_rbTkWaitCommand(clientData, interp, objc, objv) } /* trap check */ - if (rb_thread_check_trap_pending()) { +#ifdef RUBY_VM + if (rb_thread_check_trap_pending()) { +#else + if (rb_trap_pending) { +#endif Tcl_Release(interp); return TCL_RETURN; @@ -4304,6 +4405,7 @@ ip_rb_threadVwaitCommand(clientData, interp, objc, objv) int ret, dummy; int thr_crit_bup; volatile VALUE current_thread = rb_thread_current(); + struct timeval t; DUMP1("Ruby's 'thread_vwait' is called"); if (interp == (Tcl_Interp*)NULL) { @@ -4398,9 +4500,16 @@ ip_rb_threadVwaitCommand(clientData, interp, objc, objv) return TCL_ERROR; } + t.tv_sec = (time_t)0; + t.tv_usec = (long)((EVENT_HANDLER_TIMEOUT)*1000.0); + while(!param->done) { - /* rb_thread_stop(); */ - rb_thread_sleep_forever(); + /* rb_thread_stop(); */ + /* rb_thread_sleep_forever(); */ + rb_thread_wait_for(t); + if (NIL_P(eventloop_thread)) { + break; + } } thr_crit_bup = rb_thread_critical; @@ -4459,6 +4568,7 @@ ip_rb_threadTkWaitCommand(clientData, interp, objc, objv) int ret, dummy; int thr_crit_bup; volatile VALUE current_thread = rb_thread_current(); + struct timeval t; DUMP1("Ruby's 'thread_tkwait' is called"); if (interp == (Tcl_Interp*)NULL) { @@ -4612,9 +4722,16 @@ ip_rb_threadTkWaitCommand(clientData, interp, objc, objv) return TCL_ERROR; } + t.tv_sec = (time_t)0; + t.tv_usec = (long)((EVENT_HANDLER_TIMEOUT)*1000.0); + while(!param->done) { - /* rb_thread_stop(); */ - rb_thread_sleep_forever(); + /* rb_thread_stop(); */ + /* rb_thread_sleep_forever(); */ + rb_thread_wait_for(t); + if (NIL_P(eventloop_thread)) { + break; + } } thr_crit_bup = rb_thread_critical; @@ -4691,10 +4808,17 @@ ip_rb_threadTkWaitCommand(clientData, interp, objc, objv) rb_thread_critical = thr_crit_bup; + t.tv_sec = (time_t)0; + t.tv_usec = (long)((EVENT_HANDLER_TIMEOUT)*1000.0); + while(param->done != TKWAIT_MODE_VISIBILITY) { - if (param->done == TKWAIT_MODE_DESTROY) break; - /* rb_thread_stop(); */ - rb_thread_sleep_forever(); + if (param->done == TKWAIT_MODE_DESTROY) break; + /* rb_thread_stop(); */ + /* rb_thread_sleep_forever(); */ + rb_thread_wait_for(t); + if (NIL_P(eventloop_thread)) { + break; + } } thr_crit_bup = rb_thread_critical; @@ -4806,9 +4930,16 @@ ip_rb_threadTkWaitCommand(clientData, interp, objc, objv) rb_thread_critical = thr_crit_bup; + t.tv_sec = (time_t)0; + t.tv_usec = (long)((EVENT_HANDLER_TIMEOUT)*1000.0); + while(param->done != TKWAIT_MODE_DESTROY) { - /* rb_thread_stop(); */ - rb_thread_sleep_forever(); + /* rb_thread_stop(); */ + /* rb_thread_sleep_forever(); */ + rb_thread_wait_for(t); + if (NIL_P(eventloop_thread)) { + break; + } } Tcl_Release(window); @@ -5073,7 +5204,9 @@ ip_finalize(ip) } /* delete root widget */ -#if 0 /* cause SEGV on Ruby 1.9 */ +#ifdef RUBY_VM + /* cause SEGV on Ruby 1.9 */ +#else DUMP1("check `destroy'"); if (Tcl_GetCommandInfo(ip, "destroy", &info)) { DUMP1("call `destroy .'"); @@ -5292,7 +5425,7 @@ ip_rbNamespaceObjCmd(clientData, interp, objc, objv) } rbtk_eventloop_depth++; - DUMP2("namespace wrapper enter depth == %d", rbtk_eventloop_depth); + /* DUMP2("namespace wrapper enter depth == %d", rbtk_eventloop_depth); */ if (info.isNativeObjectProc) { ret = (*(info.objProc))(info.objClientData, interp, objc, objv); @@ -5328,7 +5461,7 @@ ip_rbNamespaceObjCmd(clientData, interp, objc, objv) #endif } - DUMP2("namespace wrapper exit depth == %d", rbtk_eventloop_depth); + /* DUMP2("namespace wrapper exit depth == %d", rbtk_eventloop_depth); */ rbtk_eventloop_depth--; return ret; @@ -5490,6 +5623,7 @@ ip_init(argc, argv, self) ; } + st = ruby_tcl_stubs_init(); /* from Tcl_AppInit() */ if (with_tk) { DUMP1("Tk_Init"); @@ -6154,7 +6288,7 @@ ip_get_result_string_obj(interp) retObj = Tcl_GetObjResult(interp); Tcl_IncrRefCount(retObj); strval = get_str_from_obj(retObj); - OBJ_TAINT(strval); + RbTk_OBJ_UNTRUST(strval); Tcl_ResetResult(interp); Tcl_DecrRefCount(retObj); return strval; @@ -6297,6 +6431,7 @@ tk_funcall(func, argc, argv, obj) volatile VALUE ip_obj = obj; volatile VALUE result; volatile VALUE ret; + struct timeval t; if (!NIL_P(ip_obj) && rb_obj_is_kind_of(ip_obj, tcltkip_class)) { ptr = get_ip(ip_obj); @@ -6406,12 +6541,21 @@ tk_funcall(func, argc, argv, obj) rb_thread_critical = thr_crit_bup; /* wait for the handler to be processed */ - DUMP2("wait for handler (current thread:%lx)", current); + t.tv_sec = (time_t)0; + t.tv_usec = (long)((EVENT_HANDLER_TIMEOUT)*1000.0); + + DUMP2("callq wait for handler (current thread:%lx)", current); while(*alloc_done >= 0) { - DUMP2("*** wait for handler (current thread:%lx)", current); + DUMP2("*** callq wait for handler (current thread:%lx)", current); /* rb_thread_stop(); */ - rb_thread_sleep_forever(); - DUMP2("*** wakeup (current thread:%lx)", current); + /* rb_thread_sleep_forever(); */ + rb_thread_wait_for(t); + DUMP2("*** callq wakeup (current thread:%lx)", current); + DUMP2("*** (eventloop thread:%lx)", eventloop_thread); + if (NIL_P(eventloop_thread)) { + DUMP1("*** callq lost eventloop thread"); + break; + } } DUMP2("back from handler (current thread:%lx)", current); @@ -6784,6 +6928,7 @@ ip_eval(self, str) volatile VALUE result; volatile VALUE ret; Tcl_QueuePosition position; + struct timeval t; thr_crit_bup = rb_thread_critical; rb_thread_critical = Qtrue; @@ -6792,7 +6937,12 @@ ip_eval(self, str) #ifdef RUBY_USE_NATIVE_THREAD ptr = get_ip(ip_obj); + DUMP2("eval status: ptr->tk_thread_id %p", ptr->tk_thread_id); + DUMP2("eval status: Tcl_GetCurrentThread %p", Tcl_GetCurrentThread()); +#else + DUMP2("status: Tcl_GetCurrentThread %p", Tcl_GetCurrentThread()); #endif + DUMP2("status: eventloopt_thread %lx", eventloop_thread); if ( #ifdef RUBY_USE_NATIVE_THREAD @@ -6880,12 +7030,21 @@ ip_eval(self, str) rb_thread_critical = thr_crit_bup; /* wait for the handler to be processed */ - DUMP2("wait for handler (current thread:%lx)", current); + t.tv_sec = (time_t)0; + t.tv_usec = (long)((EVENT_HANDLER_TIMEOUT)*1000.0); + + DUMP2("evq wait for handler (current thread:%lx)", current); while(*alloc_done >= 0) { - DUMP2("*** wait for handler (current thread:%lx)", current); + DUMP2("*** evq wait for handler (current thread:%lx)", current); /* rb_thread_stop(); */ - rb_thread_sleep_forever(); - DUMP2("*** wakeup (current thread:%lx)", current); + /* rb_thread_sleep_forever(); */ + rb_thread_wait_for(t); + DUMP2("*** evq wakeup (current thread:%lx)", current); + DUMP2("*** (eventloop thread:%lx)", eventloop_thread); + if (NIL_P(eventloop_thread)) { + DUMP1("*** evq lost eventloop thread"); + break; + } } DUMP2("back from handler (current thread:%lx)", current); @@ -6931,6 +7090,71 @@ ip_eval(self, str) } +static int +ip_cancel_eval_core(interp, msg, flag) + Tcl_Interp *interp; + VALUE msg; + int flag; +{ +#if TCL_MAJOR_VERSION < 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION < 6) + rb_raise(rb_eNotImpError, + "cancel_eval is supported Tcl/Tk8.6 or later."); +#else + Tcl_Obj *msg_obj; + + if (NIL_P(msg)) { + msg_obj = NULL; + } else { + msg_obj = Tcl_NewStringObj(RSTRING_PTR(msg), RSTRING_LEN(msg)); + Tcl_IncrRefCount(msg_obj); + } + + return Tcl_CancelEval(interp, msg_obj, 0, flag); +#endif +} + +static VALUE +ip_cancel_eval(argc, argv, self) + int argc; + VALUE *argv; + VALUE self; +{ + VALUE retval; + + if (rb_scan_args(argc, argv, "01", &retval) == 0) { + retval = Qnil; + } + if (ip_cancel_eval_core(get_ip(self)->ip, retval, 0) == TCL_OK) { + return Qtrue; + } else { + return Qfalse; + } +} + +#ifndef TCL_CANCEL_UNWIND +#define TCL_CANCEL_UNWIND 0x100000 +#endif +static VALUE +ip_cancel_eval_unwind(argc, argv, self) + int argc; + VALUE *argv; + VALUE self; +{ + int flag = 0; + VALUE retval; + + if (rb_scan_args(argc, argv, "01", &retval) == 0) { + retval = Qnil; + } + + flag |= TCL_CANCEL_UNWIND; + if (ip_cancel_eval_core(get_ip(self)->ip, retval, flag) == TCL_OK) { + return Qtrue; + } else { + return Qfalse; + } +} + /* restart Tk */ static VALUE lib_restart_core(interp, argc, argv) @@ -7170,8 +7394,8 @@ lib_toUTF8_core(ip_obj, src, encodename) #ifdef HAVE_RUBY_ENCODING_H rb_enc_associate_index(str, ENCODING_INDEX_UTF8); #endif + if (taint_flag) RbTk_OBJ_UNTRUST(str); rb_ivar_set(str, ID_at_enc, ENCODING_NAME_UTF8); - if (taint_flag) OBJ_TAINT(str); /* if (encoding != (Tcl_Encoding)NULL) { @@ -7371,9 +7595,9 @@ lib_fromUTF8_core(ip_obj, src, encodename) rb_enc_associate_index(str, rb_enc_find_index(RSTRING_PTR(encodename))); } #endif - rb_ivar_set(str, ID_at_enc, encodename); - if (taint_flag) OBJ_TAINT(str); + if (taint_flag) RbTk_OBJ_UNTRUST(str); + rb_ivar_set(str, ID_at_enc, encodename); /* if (encoding != (Tcl_Encoding)NULL) { @@ -7466,7 +7690,7 @@ lib_UTF_backslash_core(self, str, all_bs) } str = rb_str_new(dst_buf, dst_len); - if (taint_flag) OBJ_TAINT(str); + if (taint_flag) RbTk_OBJ_UNTRUST(str); #ifdef HAVE_RUBY_ENCODING_H rb_enc_associate_index(str, ENCODING_INDEX_UTF8); #endif @@ -8185,6 +8409,7 @@ ip_invoke_with_position(argc, argv, obj, position) volatile VALUE ip_obj = obj; volatile VALUE result; volatile VALUE ret; + struct timeval t; #if TCL_MAJOR_VERSION >= 8 Tcl_Obj **av = (Tcl_Obj **)NULL; @@ -8198,10 +8423,10 @@ ip_invoke_with_position(argc, argv, obj, position) #ifdef RUBY_USE_NATIVE_THREAD ptr = get_ip(ip_obj); - DUMP2("status: ptr->tk_thread_id %p", ptr->tk_thread_id); - DUMP2("status: Tcl_GetCurrentThread %p", Tcl_GetCurrentThread()); + DUMP2("invoke status: ptr->tk_thread_id %p", ptr->tk_thread_id); + DUMP2("invoke status: Tcl_GetCurrentThread %p", Tcl_GetCurrentThread()); #else - DUMP2("status: Tcl_GetCurrentThread %lx", Tcl_GetCurrentThread()); + DUMP2("status: Tcl_GetCurrentThread %p", Tcl_GetCurrentThread()); #endif DUMP2("status: eventloopt_thread %lx", eventloop_thread); @@ -8285,10 +8510,20 @@ ip_invoke_with_position(argc, argv, obj, position) rb_thread_critical = thr_crit_bup; /* wait for the handler to be processed */ - DUMP2("wait for handler (current thread:%lx)", current); + t.tv_sec = (time_t)0; + t.tv_usec = (long)((EVENT_HANDLER_TIMEOUT)*1000.0); + + DUMP2("ivq wait for handler (current thread:%lx)", current); while(*alloc_done >= 0) { - /* rb_thread_stop(); */ - rb_thread_sleep_forever(); + /* rb_thread_stop(); */ + /* rb_thread_sleep_forever(); */ + rb_thread_wait_for(t); + DUMP2("*** ivq wakeup (current thread:%lx)", current); + DUMP2("*** (eventloop thread:%lx)", eventloop_thread); + if (NIL_P(eventloop_thread)) { + DUMP1("*** ivq lost eventloop thread"); + break; + } } DUMP2("back from handler (current thread:%lx)", current); @@ -8426,7 +8661,7 @@ ip_get_variable2_core(interp, argc, argv) Tcl_IncrRefCount(ret); strval = get_str_from_obj(ret); - OBJ_TAINT(strval); + RbTk_OBJ_UNTRUST(strval); Tcl_DecrRefCount(ret); /* Tcl_Release(ptr->ip); */ @@ -8565,7 +8800,7 @@ ip_set_variable2_core(interp, argc, argv) Tcl_IncrRefCount(ret); strval = get_str_from_obj(ret); - OBJ_TAINT(strval); + RbTk_OBJ_UNTRUST(strval); Tcl_DecrRefCount(ret); /* Tcl_Release(ptr->ip); */ @@ -8842,12 +9077,14 @@ lib_split_tklist_core(ip_obj, list_str) rb_thread_critical = Qtrue; ary = rb_ary_new2(objc); - if (taint_flag) OBJ_TAINT(ary); + if (taint_flag) RbTk_OBJ_UNTRUST(ary); old_gc = rb_gc_disable(); for(idx = 0; idx < objc; idx++) { elem = get_str_from_obj(objv[idx]); + if (taint_flag) RbTk_OBJ_UNTRUST(elem); + #ifdef HAVE_RUBY_ENCODING_H if (rb_enc_get_index(elem) == ENCODING_INDEX_BINARY) { rb_enc_associate_index(elem, ENCODING_INDEX_BINARY); @@ -8857,7 +9094,6 @@ lib_split_tklist_core(ip_obj, list_str) rb_ivar_set(elem, ID_at_enc, list_ivar_enc); } #endif - if (taint_flag) OBJ_TAINT(elem); /* RARRAY(ary)->ptr[idx] = elem; */ rb_ary_push(ary, elem); } @@ -8889,7 +9125,7 @@ lib_split_tklist_core(ip_obj, list_str) } ary = rb_ary_new2(argc); - if (taint_flag) OBJ_TAINT(ary); + if (taint_flag) RbTk_OBJ_UNTRUST(ary); old_gc = rb_gc_disable(); @@ -9009,7 +9245,7 @@ lib_merge_tklist(argc, argv, obj) /* create object */ str = rb_str_new(result, dst - result - 1); - if (taint_flag) OBJ_TAINT(str); + if (taint_flag) RbTk_OBJ_UNTRUST(str); #if 0 /* use Tcl_EventuallyFree */ Tcl_EventuallyFree((ClientData)result, TCL_DYNAMIC); /* XXXXXXXX */ #else @@ -9057,7 +9293,7 @@ lib_conv_listelement(self, src) #endif rb_str_resize(dst, len); - if (taint_flag) OBJ_TAINT(dst); + if (taint_flag) RbTk_OBJ_UNTRUST(dst); rb_thread_critical = thr_crit_bup; @@ -9400,11 +9636,10 @@ update_encoding_table(table, interp, error_mode) { struct tcltkip *ptr; int retry = 0; - int i, idx, objc; + int i, objc; Tcl_Obj **objv; Tcl_Obj *enc_list; volatile VALUE encname = Qnil; - volatile VALUE encobj = Qnil; /* interpreter check */ if (NIL_P(interp)) return 0; @@ -9446,7 +9681,6 @@ encoding_table_get_name_core(table, enc, error_mode) VALUE error_mode; { volatile VALUE name = Qnil; - int retry = 0; enc = rb_funcall(enc, ID_to_s, 0, 0); name = rb_hash_lookup(table, enc); @@ -9519,7 +9753,8 @@ encoding_table_get_obj(table, enc) #ifdef HAVE_RUBY_ENCODING_H static VALUE -create_encoding_table(interp) +create_encoding_table_core(arg, interp) + VALUE arg; VALUE interp; { struct tcltkip *ptr = get_ip(interp); @@ -9530,7 +9765,11 @@ create_encoding_table(interp) Tcl_Obj **objv; Tcl_Obj *enc_list; - rb_secure(4); +#ifdef HAVE_RB_SET_SAFE_LEVEL_FORCE + rb_set_safe_level_force(0); +#else + rb_set_safe_level(0); +#endif /* set 'binary' encoding */ encobj = rb_enc_from_encoding(rb_enc_from_index(ENCODING_INDEX_BINARY)); @@ -9610,7 +9849,8 @@ create_encoding_table(interp) #else /* ! HAVE_RUBY_ENCODING_H */ #if TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION >= 1) static VALUE -create_encoding_table(interp) +create_encoding_table_core(arg, interp) + VALUE arg; VALUE interp; { struct tcltkip *ptr = get_ip(interp); @@ -9651,7 +9891,8 @@ create_encoding_table(interp) #else /* Tcl/Tk 7.x or 8.0 */ static VALUE -create_encoding_table(interp) +create_encoding_table_core(arg, interp) + VALUE arg; VALUE interp; { volatile VALUE table = rb_hash_new(); @@ -9662,6 +9903,14 @@ create_encoding_table(interp) #endif #endif +static VALUE +create_encoding_table(interp) + VALUE interp; +{ + return rb_funcall(rb_proc_new(create_encoding_table_core, interp), + ID_call, 0); +} + static VALUE ip_get_encoding_table(interp) VALUE interp; @@ -10041,6 +10290,8 @@ Init_tcltklib() rb_define_method(ip, "has_mainwindow?", ip_has_mainwindow_p, 0); rb_define_method(ip, "invalid_namespace?", ip_has_invalid_namespace_p, 0); rb_define_method(ip, "_eval", ip_eval, 1); + rb_define_method(ip, "_cancel_eval", ip_cancel_eval, -1); + rb_define_method(ip, "_cancel_eval_unwind", ip_cancel_eval_unwind, -1); rb_define_method(ip, "_toUTF8", ip_toUTF8, -1); rb_define_method(ip, "_fromUTF8", ip_fromUTF8, -1); rb_define_method(ip, "_thread_vwait", ip_thread_vwait, 1); @@ -10103,12 +10354,13 @@ Init_tcltklib() /* --------------------------------------------------------------- */ eventloop_thread = Qnil; + eventloop_interp = (Tcl_Interp*)NULL; #ifndef DEFAULT_EVENTLOOP_DEPTH #define DEFAULT_EVENTLOOP_DEPTH 7 #endif eventloop_stack = rb_ary_new2(DEFAULT_EVENTLOOP_DEPTH); - OBJ_TAINT(eventloop_stack); + RbTk_OBJ_UNTRUST(eventloop_stack); watchdog_thread = Qnil; @@ -10152,4 +10404,3 @@ Init_tcltklib() } /* eof */ - diff --git a/ext/tk/tkutil/extconf.rb b/ext/tk/tkutil/extconf.rb index 34b91632eb..57de973c0a 100644 --- a/ext/tk/tkutil/extconf.rb +++ b/ext/tk/tkutil/extconf.rb @@ -7,8 +7,12 @@ end if has_tk require 'mkmf' + have_func("rb_obj_instance_exec", "ruby.h") + have_func("rb_obj_untrust", "ruby.h") + have_func("rb_obj_taint", "ruby.h") have_func("rb_sym_to_s", "ruby.h") have_func("strndup", "string.h") + create_makefile('tkutil') end diff --git a/ext/tk/tkutil/tkutil.c b/ext/tk/tkutil/tkutil.c index 42c9330766..25011bb473 100644 --- a/ext/tk/tkutil/tkutil.c +++ b/ext/tk/tkutil/tkutil.c @@ -7,10 +7,16 @@ ************************************************/ -#define TKUTIL_RELEASE_DATE "2008-05-23" +#define TKUTIL_RELEASE_DATE "2009-07-12" #include "ruby.h" +#ifdef RUBY_VM +static VALUE rb_thread_critical; /* dummy */ +#else +/* On Ruby 1.8.x, use rb_thread_critical (defined at rubysig.h) */ +#include "rubysig.h" +#endif #ifdef HAVE_RUBY_ST_H #include "ruby/st.h" #else @@ -54,6 +60,9 @@ static unsigned long CALLBACK_ID_NUM = 0; /*************************************/ +#if defined(HAVE_RB_OBJ_INSTANCE_EXEC) && !defined(RUBY_VM) +extern VALUE rb_obj_instance_exec _((int, VALUE*, VALUE)); +#endif static VALUE tk_s_new(argc, argv, klass) int argc; @@ -77,12 +86,34 @@ tk_s_new(argc, argv, klass) static VALUE tkNone_to_s(self) VALUE self; +{ + return rb_str_new2(""); +} + +static VALUE +tkNone_inspect(self) + VALUE self; { return rb_str_new2("None"); } /*************************************/ +static VALUE +tk_obj_untrust(self, obj) + VALUE self; + VALUE obj; +{ +#ifdef HAVE_RB_OBJ_TAINT + rb_obj_taint(obj); +#endif +#ifdef HAVE_RB_OBJ_UNTRUST + rb_obj_untrust(obj); +#endif + + return obj; +} + static VALUE tk_eval_cmd(argc, argv, self) int argc; @@ -890,12 +921,15 @@ tk_conv_args(argc, argv, self) { int idx, size; volatile VALUE dst; + int thr_crit_bup; VALUE old_gc; if (argc < 2) { rb_raise(rb_eArgError, "too few arguments"); } + thr_crit_bup = rb_thread_critical; + rb_thread_critical = Qtrue; old_gc = rb_gc_disable(); for(size = 0, idx = 2; idx < argc; idx++) { @@ -920,6 +954,7 @@ tk_conv_args(argc, argv, self) } if (old_gc == Qfalse) rb_gc_enable(); + rb_thread_critical = thr_crit_bup; return rb_ary_plus(argv[0], dst); } @@ -1065,6 +1100,18 @@ tcl2rb_num_or_str(self, value) rb_eArgError, 0); } +static VALUE +tcl2rb_num_or_nil(self, value) + VALUE self; + VALUE value; +{ + rb_check_type(value, T_STRING); + + if (RSTRING_LEN(value) == 0) return Qnil; + + return tkstr_to_number(value); +} + /*************************************/ @@ -1590,8 +1637,12 @@ cbsubst_scan_args(self, arg_key, val_ary) unsigned char type_chr; volatile VALUE dst = rb_ary_new2(vallen); volatile VALUE proc; + int thr_crit_bup; VALUE old_gc; + thr_crit_bup = rb_thread_critical; + rb_thread_critical = Qtrue; + old_gc = rb_gc_disable(); Data_Get_Struct(rb_const_get(self, ID_SUBST_INFO), @@ -1619,6 +1670,7 @@ cbsubst_scan_args(self, arg_key, val_ary) } if (old_gc == Qfalse) rb_gc_enable(); + rb_thread_critical = thr_crit_bup; return dst; } @@ -1743,7 +1795,7 @@ Init_tkutil() TK_None = rb_obj_alloc(rb_cObject); rb_define_const(mTK, "None", TK_None); rb_define_singleton_method(TK_None, "to_s", tkNone_to_s, 0); - rb_define_singleton_method(TK_None, "inspect", tkNone_to_s, 0); + rb_define_singleton_method(TK_None, "inspect", tkNone_inspect, 0); OBJ_FREEZE(TK_None); /* --------------------- */ @@ -1751,6 +1803,8 @@ Init_tkutil() CALLBACK_TABLE = rb_hash_new(); /* --------------------- */ + rb_define_singleton_method(mTK, "untrust", tk_obj_untrust, 1); + rb_define_singleton_method(mTK, "eval_cmd", tk_eval_cmd, -1); rb_define_singleton_method(mTK, "callback", tk_do_callback, -1); rb_define_singleton_method(mTK, "install_cmd", tk_install_cmd, -1); @@ -1767,6 +1821,7 @@ Init_tkutil() rb_define_singleton_method(mTK, "number", tcl2rb_number, 1); rb_define_singleton_method(mTK, "string", tcl2rb_string, 1); rb_define_singleton_method(mTK, "num_or_str", tcl2rb_num_or_str, 1); + rb_define_singleton_method(mTK, "num_or_nil", tcl2rb_num_or_nil, 1); rb_define_method(mTK, "_toUTF8", tk_toUTF8, -1); rb_define_method(mTK, "_fromUTF8", tk_fromUTF8, -1); @@ -1780,6 +1835,7 @@ Init_tkutil() rb_define_method(mTK, "number", tcl2rb_number, 1); rb_define_method(mTK, "string", tcl2rb_string, 1); rb_define_method(mTK, "num_or_str", tcl2rb_num_or_str, 1); + rb_define_method(mTK, "num_or_nil", tcl2rb_num_or_nil, 1); /* --------------------- */ rb_global_variable(&ENCODING_NAME_UTF8); -- cgit v1.2.3