diff options
author | nagai <nagai@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2004-06-12 15:25:49 +0000 |
---|---|---|
committer | nagai <nagai@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2004-06-12 15:25:49 +0000 |
commit | c0271cadd7c49f2c3304e93f6190da0b8623c1f3 (patch) | |
tree | ae877225c9d33c23865c14f81a6cf6252f10e590 | |
parent | 82593c058f0a61d8d4bcf7279fed496022330246 (diff) | |
download | ruby-c0271cadd7c49f2c3304e93f6190da0b8623c1f3.tar.gz |
* ext/tcltklib/extconf.rb: [EXPERIMENTAL] MacOS X (darwin) support
* ext/tcltklib/tcltklib.c: fix thread trouble on callback proc, and
eliminate warning about instance variable access
* ext/tk/lib/tk/menubar.rb: improve supported menu_spec
* ext/tk/lib/tk/menuspec.rb: [add] menu_spec support library
* ext/tk/lib/tk/root.rb: add menu_spec support
* ext/tk/lib/tk/text.rb: bug fix
* ext/tk/lib/tk/toplevel.rb: add menu_spec support
* ext/tk/sample/menubar?.rb: [add] sample of menu_spec usage
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@6454 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 19 | ||||
-rw-r--r-- | ext/tcltklib/extconf.rb | 11 | ||||
-rw-r--r-- | ext/tcltklib/tcltklib.c | 65 | ||||
-rw-r--r-- | ext/tk/MANIFEST | 3 | ||||
-rw-r--r-- | ext/tk/lib/multi-tk.rb | 3 | ||||
-rw-r--r-- | ext/tk/lib/tk.rb | 89 | ||||
-rw-r--r-- | ext/tk/lib/tk/grid.rb | 48 | ||||
-rw-r--r-- | ext/tk/lib/tk/menubar.rb | 127 | ||||
-rw-r--r-- | ext/tk/lib/tk/menuspec.rb | 243 | ||||
-rw-r--r-- | ext/tk/lib/tk/optiondb.rb | 3 | ||||
-rw-r--r-- | ext/tk/lib/tk/place.rb | 39 | ||||
-rw-r--r-- | ext/tk/lib/tk/root.rb | 21 | ||||
-rw-r--r-- | ext/tk/lib/tk/text.rb | 80 | ||||
-rw-r--r-- | ext/tk/lib/tk/toplevel.rb | 21 | ||||
-rw-r--r-- | ext/tk/lib/tk/variable.rb | 18 | ||||
-rw-r--r-- | ext/tk/sample/menubar1.rb | 51 | ||||
-rw-r--r-- | ext/tk/sample/menubar2.rb | 56 | ||||
-rw-r--r-- | ext/tk/tkutil.c | 4 |
18 files changed, 724 insertions, 177 deletions
@@ -1,3 +1,22 @@ +Sun Jun 13 00:23:04 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tcltklib/extconf.rb: [EXPERIMENTAL] MacOS X (darwin) support + + * ext/tcltklib/tcltklib.c: fix thread trouble on callback proc, and + eliminate warning about instance variable access + + * ext/tk/lib/tk/menubar.rb: improve supported menu_spec + + * ext/tk/lib/tk/menuspec.rb: [add] menu_spec support library + + * ext/tk/lib/tk/root.rb: add menu_spec support + + * ext/tk/lib/tk/text.rb: bug fix + + * ext/tk/lib/tk/toplevel.rb: add menu_spec support + + * ext/tk/sample/menubar?.rb: [add] sample of menu_spec usage + Sat Jun 12 14:15:20 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp> * dir.c: RDOC for File::FNM_CASEFOLD was missed. diff --git a/ext/tcltklib/extconf.rb b/ext/tcltklib/extconf.rb index ac3c68e926..83b4a2ac31 100644 --- a/ext/tcltklib/extconf.rb +++ b/ext/tcltklib/extconf.rb @@ -3,6 +3,7 @@ require 'mkmf' is_win32 = (/mswin32|mingw|cygwin|bccwin32/ =~ RUBY_PLATFORM) +is_macosx = (/darwin/ =~ RUBY_PLATFORM) unless is_win32 have_library("nsl", "t_open") @@ -209,13 +210,19 @@ EOF end end -if have_header("tcl.h") && have_header("tk.h") && +if is_macosx || + (have_header("tcl.h") && have_header("tk.h") && (is_win32 || find_library("X11", "XOpenDisplay", "/usr/X11/lib", "/usr/lib/X11", "/usr/X11R6/lib", "/usr/openwin/lib")) && find_tcl(tcllib, stubs) && - find_tk(tklib, stubs) + find_tk(tklib, stubs)) $CPPFLAGS += ' -DUSE_TCL_STUBS -DUSE_TK_STUBS' if stubs $CPPFLAGS += ' -D_WIN32' if /cygwin/ =~ RUBY_PLATFORM + if is_macosx + $CPPFLAGS += ' -I/Library/Frameworks/Tcl.framework/headers -I/Library/Frameworks/Tk.framework/Headers' + $LDFLAGS += ' -framework Tk -framework Tcl' + end + create_makefile("tcltklib") if pthread_check end diff --git a/ext/tcltklib/tcltklib.c b/ext/tcltklib/tcltklib.c index eea7ace7fa..cb3826ba9f 100644 --- a/ext/tcltklib/tcltklib.c +++ b/ext/tcltklib/tcltklib.c @@ -909,17 +909,20 @@ ip_set_exc_message(interp, exc) msg = rb_funcall(exc, ID_message, 0, 0); #if TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION > 0) - enc = rb_ivar_get(exc, ID_at_enc); - if (NIL_P(enc)) { - enc = rb_ivar_get(msg, ID_at_enc); + enc = Qnil; + if (RTEST(rb_ivar_defined(exc, ID_at_enc))) { + enc = rb_ivar_get(exc, ID_at_enc); + } + if (NIL_P(enc) && RTEST(rb_ivar_defined(msg, ID_at_enc))) { + enc = rb_ivar_get(msg, ID_at_enc); } if (NIL_P(enc)) { - encoding = (Tcl_Encoding)NULL; + encoding = (Tcl_Encoding)NULL; } else if (TYPE(enc) == T_STRING) { - encoding = Tcl_GetEncoding(interp, RSTRING(enc)->ptr); + encoding = Tcl_GetEncoding(interp, RSTRING(enc)->ptr); } else { - enc = rb_funcall(enc, ID_to_s, 0, 0); - encoding = Tcl_GetEncoding(interp, RSTRING(enc)->ptr); + enc = rb_funcall(enc, ID_to_s, 0, 0); + encoding = Tcl_GetEncoding(interp, RSTRING(enc)->ptr); } /* to avoid a garbled error message dialog */ @@ -1008,7 +1011,9 @@ ip_ruby_eval_body(arg) (VALUE)0); #else + rb_thread_critical = Qfalse; ret = rb_eval_string_protect(arg->string, &status); + rb_thread_critical = Qtrue; if (status) { char *errtype, *buf; int errtype_len, len; @@ -1288,9 +1293,13 @@ ip_ruby_cmd_core(arg) struct cmd_body_arg *arg; { VALUE ret; + int thr_crit_bup; DUMP1("call ip_ruby_cmd_core"); + thr_crit_bup = rb_thread_critical; + rb_thread_critical = Qfalse; ret = rb_apply(arg->receiver, arg->method, arg->args); + rb_thread_critical = thr_crit_bup; DUMP1("finish ip_ruby_cmd_core"); return ret; @@ -3464,12 +3473,17 @@ lib_toUTF8_core(ip_obj, src, encodename) if (TYPE(str) == T_STRING) { volatile VALUE enc; - enc = rb_ivar_get(str, ID_at_enc); + enc = Qnil; + if (RTEST(rb_ivar_defined(str, ID_at_enc))) { + enc = rb_ivar_get(str, ID_at_enc); + } if (NIL_P(enc)) { if (NIL_P(ip_obj)) { encoding = (Tcl_Encoding)NULL; } else { - enc = rb_ivar_get(ip_obj, ID_at_enc); + if (RTEST(rb_ivar_defined(ip_obj, ID_at_enc))) { + enc = rb_ivar_get(ip_obj, ID_at_enc); + } if (NIL_P(enc)) { encoding = (Tcl_Encoding)NULL; } else { @@ -3592,7 +3606,10 @@ lib_fromUTF8_core(ip_obj, src, encodename) volatile VALUE enc; if (TYPE(str) == T_STRING) { - enc = rb_ivar_get(str, ID_at_enc); + enc = Qnil; + if (RTEST(rb_ivar_defined(str, ID_at_enc))) { + enc = rb_ivar_get(str, ID_at_enc); + } if (!NIL_P(enc) && strcmp(StringValuePtr(enc), "binary") == 0) { rb_thread_critical = thr_crit_bup; return str; @@ -3602,7 +3619,10 @@ lib_fromUTF8_core(ip_obj, src, encodename) if (NIL_P(ip_obj)) { encoding = (Tcl_Encoding)NULL; } else { - enc = rb_ivar_get(ip_obj, ID_at_enc); + enc = Qnil; + if (RTEST(rb_ivar_defined(ip_obj, ID_at_enc))) { + enc = rb_ivar_get(ip_obj, ID_at_enc); + } if (NIL_P(enc)) { encoding = (Tcl_Encoding)NULL; } else { @@ -3947,7 +3967,10 @@ alloc_invoke_arguments(argc, argv) # if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0 av[i] = Tcl_NewStringObj(s, RSTRING(v)->len); # else /* TCL_VERSION >= 8.1 */ - enc = rb_ivar_get(v, ID_at_enc); + enc = Qnil; + if (RTEST(rb_ivar_defined(v, ID_at_enc))) { + enc = rb_ivar_get(v, ID_at_enc); + } if (!NIL_P(enc) && strcmp(StringValuePtr(enc), "binary") == 0) { /* binary string */ av[i] = Tcl_NewByteArrayObj(s, RSTRING(v)->len); @@ -4461,7 +4484,11 @@ ip_set_variable(self, varname_arg, value_arg, flag_arg) Tcl_IncrRefCount(valobj); # else /* TCL_VERSION >= 8.1 */ { - VALUE enc = rb_ivar_get(value, ID_at_enc); + VALUE enc = Qnil; + + if (RTEST(rb_ivar_defined(value, ID_at_enc))) { + enc = rb_ivar_get(value, ID_at_enc); + } if (!NIL_P(enc) && strcmp(StringValuePtr(enc), "binary") == 0) { /* binary string */ @@ -4581,7 +4608,11 @@ ip_set_variable2(self, varname_arg, index_arg, value_arg, flag_arg) RSTRING(value)->len); # else /* TCL_VERSION >= 8.1 */ { - VALUE enc = rb_ivar_get(value, ID_at_enc); + VALUE enc = Qnil; + + if (RTEST(rb_ivar_defined(value, ID_at_enc))) { + enc = rb_ivar_get(value, ID_at_enc); + } if (!NIL_P(enc) && strcmp(StringValuePtr(enc), "binary") == 0) { /* binary string */ @@ -4820,7 +4851,11 @@ lib_split_tklist_core(ip_obj, list_str) rb_thread_critical = Qtrue; { - VALUE enc = rb_ivar_get(list_str, ID_at_enc); + VALUE enc = Qnil; + + if (RTEST(rb_ivar_defined(list_str, ID_at_enc))) { + enc = rb_ivar_get(list_str, ID_at_enc); + } if (!NIL_P(enc) && strcmp(StringValuePtr(enc), "binary") == 0) { /* binary string */ diff --git a/ext/tk/MANIFEST b/ext/tk/MANIFEST index fe0ab01696..c2ac51eddc 100644 --- a/ext/tk/MANIFEST +++ b/ext/tk/MANIFEST @@ -52,6 +52,7 @@ lib/tk/listbox.rb lib/tk/macpkg.rb lib/tk/menu.rb lib/tk/menubar.rb +lib/tk/menuspec.rb lib/tk/message.rb lib/tk/mngfocus.rb lib/tk/msgcat.rb @@ -92,6 +93,8 @@ sample/binstr_usage.rb sample/btn_with_frame.rb sample/encstr_usage.rb sample/iso2022-kr.txt +sample/menubar1.rb +sample/menubar2.rb sample/propagate.rb sample/resource.en sample/resource.ja diff --git a/ext/tk/lib/multi-tk.rb b/ext/tk/lib/multi-tk.rb index ba1dc733ca..7957e0b3c7 100644 --- a/ext/tk/lib/multi-tk.rb +++ b/ext/tk/lib/multi-tk.rb @@ -1324,7 +1324,8 @@ class MultiTkIp else list.push str[0..i-1] end - list += _lst2ary(str[i+1..-1]) + #list += _lst2ary(str[i+1..-1]) + list.concat(_lst2ary(str[i+1..-1])) list end private :_lst2ary diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb index 12d60245e7..5ac6724b84 100644 --- a/ext/tk/lib/tk.rb +++ b/ext/tk/lib/tk.rb @@ -114,7 +114,7 @@ module TkComm private :_genobj_for_tkwidget module_function :_genobj_for_tkwidget - def tk_tcl2ruby(val, enc_mode = nil) + def tk_tcl2ruby(val, enc_mode = nil, listobj = true) if val =~ /^rb_out\S* (c(_\d+_)?\d+)/ #return Tk_CMDTBL[$1] return TkCore::INTERP.tk_cmd_tbl[$1] @@ -141,12 +141,18 @@ module TkComm TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val when /^-?\d+\.?\d*(e[-+]?\d+)?$/ val.to_f - when /[^\\] / - tk_split_escstr(val).collect{|elt| - tk_tcl2ruby(elt) - } when /\\ / val.gsub(/\\ /, ' ') + when /[^\\] / + if listobj + tk_split_escstr(val).collect{|elt| + tk_tcl2ruby(elt, enc_mode, listobj) + } + elsif enc_mode + _fromUTF8(val) + else + val + end else if enc_mode _fromUTF8(val) @@ -157,6 +163,8 @@ module TkComm end private :tk_tcl2ruby + module_function :tk_tcl2ruby + private_class_method :tk_tcl2ruby unless const_defined?(:USE_TCLs_LIST_FUNCTIONS) USE_TCLs_LIST_FUNCTIONS = true @@ -171,19 +179,28 @@ if USE_TCLs_LIST_FUNCTIONS TkCore::INTERP._split_tklist(str) end - def tk_split_sublist(str) - return [] if str == "" - list = TkCore::INTERP._split_tklist(str) + def tk_split_sublist(str, depth=-1) + # return [] if str == "" + # list = TkCore::INTERP._split_tklist(str) + if depth == 0 + return "" if str == "" + list = [str] + else + return [] if str == "" + list = TkCore::INTERP._split_tklist(str) + end if list.size == 1 - tk_tcl2ruby(list[0]) + tk_tcl2ruby(list[0], nil, false) else - list.collect{|token| tk_split_sublist(token)} + list.collect{|token| tk_split_sublist(token, depth - 1)} end end - def tk_split_list(str) + def tk_split_list(str, depth=0) return [] if str == "" - TkCore::INTERP._split_tklist(str).collect{|token| tk_split_sublist(token)} + TkCore::INTERP._split_tklist(str).collect{|token| + tk_split_sublist(token, depth - 1) + } end def tk_split_simplelist(str) @@ -239,20 +256,29 @@ else list end - def tk_split_sublist(str) - return [] if str == "" - return [tk_split_sublist(str[1..-2])] if str =~ /^\{.*\}$/ - list = tk_split_escstr(str) + def tk_split_sublist(str, depth=-1) + #return [] if str == "" + #return [tk_split_sublist(str[1..-2])] if str =~ /^\{.*\}$/ + #list = tk_split_escstr(str) + if depth == 0 + return "" if str == "" + str = str[1..-2] if str =~ /^\{.*\}$/ + list = [str] + else + return [] if str == [] + return [tk_split_sublist(str[1..-2], depth - 1)] if str =~ /^\{.*\}$/ + list = tk_split_escstr(str) + end if list.size == 1 - tk_tcl2ruby(list[0]) + tk_tcl2ruby(list[0], nil, false) else - list.collect{|token| tk_split_sublist(token)} + list.collect{|token| tk_split_sublist(token, depth - 1)} end end - def tk_split_list(str) + def tk_split_list(str, depth=0) return [] if str == "" - tk_split_escstr(str).collect{|token| tk_split_sublist(token)} + tk_split_escstr(str).collect{|token| tk_split_sublist(token, depth - 1)} end =begin def tk_split_list(str) @@ -425,8 +451,8 @@ end end =end - def list(val) - tk_split_list(val) + def list(val, depth=0) + tk_split_list(val, depth) end def simplelist(val) tk_split_simplelist(val) @@ -457,9 +483,10 @@ end val end end - private :bool, :number, :string, :list, :simplelist, :window, :procedure - module_function :bool, :number, :num_or_str, :string, :list, :simplelist - module_function :window, :image_obj, :procedure + private :bool, :number, :string, :num_or_str + private :list, :simplelist, :window, :procedure + module_function :bool, :number, :num_or_str, :string + module_function :list, :simplelist, :window, :image_obj, :procedure def _toUTF8(str, encoding = nil) TkCore::INTERP._toUTF8(str, encoding) @@ -2035,9 +2062,10 @@ class TkObject<TkKernel include TkTreatFont include TkBindCore - def path - @path - end +### --> definition is moved to TkUtil module +# def path +# @path +# end def epath @path @@ -2433,6 +2461,7 @@ class TkWindow<TkObject TkPack.configure(self, slot=>value) end end + alias pack_configure pack_config def pack_info() #ilist = list(tk_call('pack', 'info', epath)) @@ -2510,6 +2539,7 @@ class TkWindow<TkObject TkGrid.configure(self, slot=>value) end end + alias grid_configure grid_config def grid_columnconfig(index, keys) #tk_call('grid', 'columnconfigure', epath, index, *hash_kv(keys)) @@ -2625,6 +2655,7 @@ class TkWindow<TkObject #end TkPlace.configure(self, slot, value) end + alias place_configure place_config def place_configinfo(slot = nil) # for >= Tk8.4a2 ? @@ -2640,7 +2671,7 @@ class TkWindow<TkObject # conf # } #end - TkPlace.configinfo(slot) + TkPlace.configinfo(self, slot) end def place_info() diff --git a/ext/tk/lib/tk/grid.rb b/ext/tk/lib/tk/grid.rb index 1516aef4bf..91f3b32072 100644 --- a/ext/tk/lib/tk/grid.rb +++ b/ext/tk/lib/tk/grid.rb @@ -62,13 +62,26 @@ module TkGrid # master = master.epath if master.kind_of?(TkObject) master = _epath(master) if slot - num_or_str(tk_call_without_enc('grid', 'columnconfigure', - master, index, "-#{slot}")) + case slot + when 'uniform', :uniform + tk_call_without_enc('grid', 'columnconfigure', + master, index, "-#{slot}") + else + num_or_str(tk_call_without_enc('grid', 'columnconfigure', + master, index, "-#{slot}")) + end else - ilist = list(tk_call_without_enc('grid','columnconfigure',master,index)) + #ilist = list(tk_call_without_enc('grid','columnconfigure',master,index)) + ilist = simplelist(tk_call_without_enc('grid', 'columnconfigure', + master, index)) info = {} while key = ilist.shift - info[key[1..-1]] = ilist.shift + case key + when 'uniform' + info[key[1..-1]] = ilist.shift + else + info[key[1..-1]] = tk_tcl2ruby(ilist.shift) + end end info end @@ -78,13 +91,26 @@ module TkGrid # master = master.epath if master.kind_of?(TkObject) master = _epath(master) if slot - num_or_str(tk_call_without_enc('grid', 'rowconfigure', - master, index, "-#{slot}")) + case slot + when 'uniform', :uniform + tk_call_without_enc('grid', 'rowconfigure', + master, index, "-#{slot}") + else + num_or_str(tk_call_without_enc('grid', 'rowconfigure', + master, index, "-#{slot}")) + end else - ilist = list(tk_call_without_enc('grid', 'rowconfigure', master, index)) + #ilist = list(tk_call_without_enc('grid', 'rowconfigure', master, index)) + ilist = simplelist(tk_call_without_enc('grid', 'rowconfigure', + master, index)) info = {} while key = ilist.shift - info[key[1..-1]] = ilist.shift + case key + when 'uniform' + info[key[1..-1]] = ilist.shift + else + info[key[1..-1]] = tk_tcl2ruby(ilist.shift) + end end info end @@ -106,10 +132,12 @@ module TkGrid def info(slave) # slave = slave.epath if slave.kind_of?(TkObject) slave = _epath(slave) - ilist = list(tk_call_without_enc('grid', 'info', slave)) + #ilist = list(tk_call_without_enc('grid', 'info', slave)) + ilist = simplelist(tk_call_without_enc('grid', 'info', slave)) info = {} while key = ilist.shift - info[key[1..-1]] = ilist.shift + #info[key[1..-1]] = ilist.shift + info[key[1..-1]] = tk_tcl2ruby(ilist.shift) end return info end diff --git a/ext/tk/lib/tk/menubar.rb b/ext/tk/lib/tk/menubar.rb index 2c2846e9b6..f29c40ff38 100644 --- a/ext/tk/lib/tk/menubar.rb +++ b/ext/tk/lib/tk/menubar.rb @@ -1,8 +1,9 @@ # # tk/menubar.rb # -# Copyright (C) 1998 maeda shugo. All rights reserved. -# This file can be distributed under the terms of the Ruby. +# Original version: +# Copyright (C) 1998 maeda shugo. All rights reserved. +# This file can be distributed under the terms of the Ruby. # Usage: # @@ -41,30 +42,56 @@ # menubar.configure('activeforeground', 'red') # menubar.configure('font', '-adobe-helvetica-bold-r-*--12-*-iso8859-1') # menubar.pack('side'=>'top', 'fill'=>'x') - -# The format of the menu_spec is: -# [ -# [ -# [button text, underline, accelerator], -# [menu label, command, underline, accelerator], -# '---', # separator -# ... -# ], -# ... +# +# +# OR +# +# radio_var = TkVariable.new('y') +# menu_spec = [ +# [['File', 0], +# {: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'], 6], +# ['Radio_Y', [radio_var, 'y'], 6], +# ['Radio_Z', [radio_var, 'z'], 6], +# '---', +# ['cascade', [ +# ['sss', proc{p 'sss'}, 0], +# ['ttt', proc{p 'ttt'}, 0], +# ['uuu', proc{p 'uuu'}, 0], +# ['vvv', proc{p 'vvv'}, 0], +# ], 0], +# '---', +# ['Quit', proc{exit}, 0]], +# [['Edit', 0], +# ['Cut', proc{puts('Cut clicked')}, 2], +# ['Copy', proc{puts('Copy clicked')}, 0], +# ['Paste', proc{puts('Paste clicked')}, 0]] # ] +# menubar = TkMenubar.new(nil, menu_spec, +# 'tearoff'=>false, +# 'foreground'=>'grey40', +# 'activeforeground'=>'red', +# 'font'=>'Helvetia 12 bold') +# menubar.pack('side'=>'top', 'fill'=>'x') -# underline and accelerator are optional parameters. -# Hashes are OK instead of Arrays. +# See tk/menuspce.rb about the format of the menu_spec # To use add_menu, configuration must be done by calling configure after # adding all menus by add_menu, not by the constructor arguments. require 'tk' require 'tk/frame' +require 'tk/composite' +require 'tk/menuspec' class TkMenubar<TkFrame - include TkComposite + include TkMenuSpec def initialize(parent = nil, spec = nil, options = nil) if parent.kind_of? Hash @@ -77,65 +104,25 @@ class TkMenubar<TkFrame @menus = [] - if spec - for menu_info in spec - add_menu(menu_info) - end - end - - if options - for key, value in options - configure(key, value) - end - end + spec.each{|info| add_menu(info)} if spec + + options.each{|key, value| configure(key, value)} if options end def add_menu(menu_info) - btn_info = menu_info.shift - mbtn = TkMenubutton.new(@frame) - - if btn_info.kind_of?(Hash) - for key, value in btn_info - mbtn.configure(key, value) - end - elsif btn_info.kind_of?(Array) - 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] - else - mbtn.configure('text', btn_info) - end - - menu = TkMenu.new(mbtn) - - for item_info in menu_info - if item_info.kind_of?(Hash) - menu.add('command', item_info) - elsif item_info.kind_of?(Array) - options = {} - options['label'] = item_info[0] if item_info[0] - options['command'] = item_info[1] if item_info[1] - options['underline'] = item_info[2] if item_info[2] - options['accelerator'] = item_info[3] if item_info[3] - menu.add('command', options) - elsif /^-+$/ =~ item_info - menu.add('sep') - else - menu.add('command', 'label' => item_info) - end - end - - mbtn.menu(menu) + mbtn, menu = _create_menubutton(@frame, menu_info) + + submenus = _get_cascade_menus(menu).flatten + @menus.push([mbtn, menu]) - delegate('tearoff', menu) - delegate('foreground', mbtn, menu) - delegate('background', mbtn, menu) - delegate('disabledforeground', mbtn, menu) - delegate('activeforeground', mbtn, menu) - delegate('activebackground', mbtn, menu) - delegate('font', mbtn, menu) - delegate('kanjifont', mbtn, menu) - mbtn.pack('side' => 'left') + delegate('tearoff', menu, *submenus) + delegate('foreground', mbtn, menu, *submenus) + delegate('background', mbtn, menu, *submenus) + delegate('disabledforeground', mbtn, menu, *submenus) + delegate('activeforeground', mbtn, menu, *submenus) + delegate('activebackground', mbtn, menu, *submenus) + delegate('font', mbtn, menu, *submenus) + delegate('kanjifont', mbtn, menu, *submenus) end def [](index) diff --git a/ext/tk/lib/tk/menuspec.rb b/ext/tk/lib/tk/menuspec.rb new file mode 100644 index 0000000000..b2d66befa7 --- /dev/null +++ b/ext/tk/lib/tk/menuspec.rb @@ -0,0 +1,243 @@ +# +# tk/menuspec.rb +# Hidethoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# based on tkmenubar.rb : +# Copyright (C) 1998 maeda shugo. All rights reserved. +# This file can be distributed under the terms of the Ruby. +# +# The format of the menu_spec is: +# [ menu_info, menu_info, ... ] +# +# And the format of the menu_info is: +# [ +# [text, underline, configs], # menu button/entry (*1) +# [label, command, underline, accelerator, configs], # command entry +# [label, TkVar_obj, underline, accelerator, configs], # checkbutton entry +# [label, [TkVar_obj, value], +# underline, accelerator, configs], # radiobutton entry +# [label, [[...menu_info...], [...menu_info...], ...], +# underline, accelerator, configs], # cascade entry +# '---', # separator +# ... +# ] +# +# underline, accelerator, and configs are optional pearameters. +# Hashes are OK instead of Arrays. Then the entry type ('command', +# 'checkbutton', 'radiobutton' or 'cascade') is given by 'type' key +# (e.g. :type=>'cascade'). When type is 'cascade', an array of menu_info +# is acceptable for 'menu' key (then, create sub-menu). +# +# 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, +# 'system' for Win, and 'apple' for Mac) option to the configs hash of +# menu button/entry information. + +module TkMenuSpec + def _create_menu(parent, menu_info, menu_name = nil, + tearoff = false, default_opts = nil) + if tearoff.kind_of?(Hash) + default_opts = tearoff + tearoff = false + end + + if menu_name.kind_of?(Hash) + default_opts = menu_name + menu_name = nil + tearoff = false + end + + if default_opts.kind_of?(Hash) + orig_opts = _symbolkey2str(default_opts) + else + orig_opts = {} + end + + tearoff = orig_opts.delete('tearoff') if orig_opts.key?('tearoff') + + if menu_name + menu = TkMenu.new(parent, :widgetname=>menu_name, :tearoff=>tearoff) + else + menu = TkMenu.new(parent, :tearoff=>tearoff) + end + + for item_info in menu_info + if item_info.kind_of?(Hash) + options = orig_opts.dup + options.update(_symbolkey2str(item_info)) + item_type = (options.delete('type') || 'command').to_s + menu_name = options.delete('menu_name') + menu_opts = orig_opts.dup + menu_opts.update(_symbolkey2str(options.delete('menu_config') || {})) + if item_type == 'cascade' && options['menu'].kind_of?(Array) + # create cascade menu + submenu = _create_menu(menu, options['menu'], menu_name, + tearoff, menu_opts) + options['menu'] = submenu + end + menu.add(item_type, options) + + elsif item_info.kind_of?(Array) + options = orig_opts.dup + + options['label'] = item_info[0] if item_info[0] + + case item_info[1] + when TkVariable + # checkbutton + item_type = 'checkbutton' + options['variable'] = item_info[1] + options['onvalue'] = true + options['offvalue'] = false + + when Array + # radiobutton or cascade + if item_info[1][0].kind_of?(TkVariable) + # radiobutton + item_type = 'radiobutton' + options['variable'] = item_info[1][0] + options['value'] = item_info[1][1] if item_info[1][1] + + else + # cascade + item_type = 'cascade' + menu_opts = orig_opts.dup + if item_info[4] && item_info[4].kind_of?(Hash) + opts = _symbolkey2str(item_info[4]) + menu_name = opts.delete('menu_name') + menu_config = opts.delete('menu_config') || {} + menu_opts.update(_symbolkey2str(menu_config)) + end + submenu = _create_menu(menu, item_info[1], menu_name, + tearoff, menu_opts) + options['menu'] = submenu + end + + else + # command + item_type = 'command' + options['command'] = item_info[1] if item_info[1] + end + + options['underline'] = item_info[2] if item_info[2] + options['accelerator'] = item_info[3] if item_info[3] + if item_info[4] && item_info[4].kind_of?(Hash) + opts = _symbolkey2str(item_info[4]) + if item_type == 'cascade' + opts.delete('menu_name') + opts.delete('menu_config') + end + options.update(opts) + end + menu.add(item_type, options) + + elsif /^-+$/ =~ item_info + menu.add('separator') + + else + menu.add('command', 'label' => item_info) + end + end + + menu + end + private :_create_menu + + def _create_menubutton(parent, menu_info, tearoff=false, default_opts = nil) + btn_info = menu_info[0] + + if tearoff.kind_of?(Hash) + default_opts = tearoff + tearoff = false + end + + if default_opts.kind_of?(Hash) + keys = _symbolkey2str(default_opts) + else + keys = {} + end + + tearoff = keys.delete('tearoff') if keys.key?('tearoff') + + if parent.kind_of?(TkRoot) || parent.kind_of?(TkToplevel) + # menubar by menu entries + unless (mbar = parent.menu).kind_of?(TkMenu) + mbar = TkMenu.new(parent, :tearoff=>false) + parent.menu(mbar) + end + + menu_name = nil + + 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') + elsif btn_info.kind_of?(Array) + keys['label'] = btn_info[0] if btn_info[0] + keys['underline'] = btn_info[1] if btn_info[1] + 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 + + menu = _create_menu(mbar, menu_info[1..-1], menu_name, + tearoff, default_opts) + menu.tearoff(tearoff) + + keys['menu'] = menu + mbar.add('cascade', keys) + + [mbar, menu] + + else + # menubar by menubuttons + mbtn = TkMenubutton.new(parent) + + menu_name = nil + + 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') + mbtn.configure(keys) + elsif btn_info.kind_of?(Array) + 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] + if btn_info[2]&&btn_info[2].kind_of?(Hash) + keys.update(_symbolkey2str(btn_info[2])) + 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) + + [mbtn, menu] + end + end + private :_create_menubutton + + def _get_cascade_menus(menu) + menus = [] + (0..(menu.index('last'))).each{|idx| + if menu.menutype(idx) == 'cascade' + submenu = menu.entrycget(idx, 'menu') + menus << [submenu, _get_cascade_menus(submenu)] + end + } + menus + end + private :_get_cascade_menus +end diff --git a/ext/tk/lib/tk/optiondb.rb b/ext/tk/lib/tk/optiondb.rb index 588c946440..46d17a2020 100644 --- a/ext/tk/lib/tk/optiondb.rb +++ b/ext/tk/lib/tk/optiondb.rb @@ -52,7 +52,8 @@ module TkOptionDB cline = '' open(file, 'r') {|f| while line = f.gets - cline += line.chomp! + #cline += line.chomp! + cline.concat(line.chomp!) case cline when /\\$/ # continue cline.chop! diff --git a/ext/tk/lib/tk/place.rb b/ext/tk/lib/tk/place.rb index 5c2f890e07..433c1077ee 100644 --- a/ext/tk/lib/tk/place.rb +++ b/ext/tk/lib/tk/place.rb @@ -34,14 +34,21 @@ module TkPlace # win = win.epath if win.kind_of?(TkObject) win = _epath(win) if slot - conf = tk_split_list(tk_call_without_enc('place', 'configure', - win, "-#{slot}") ) + #conf = tk_split_list(tk_call_without_enc('place', 'configure', + # win, "-#{slot}") ) + conf = tk_split_simplelist(tk_call_without_enc('place', 'configure', + win, "-#{slot}") ) conf[0] = conf[0][1..-1] + conf[1] = tk_tcl2ruby(conf[1]) + conf[2] = tk_tcl2ruby(conf[1]) + conf[3] = tk_tcl2ruby(conf[1]) + conf[4] = tk_tcl2ruby(conf[1]) conf else tk_split_simplelist(tk_call_without_enc('place', 'configure', win)).collect{|conflist| - conf = list(conflist) + #conf = list(conflist) + conf = simplelist(conflist).collect!{|inf| tk_tcl2ruby(inf)} conf[0] = conf[0][1..-1] conf } @@ -55,13 +62,20 @@ module TkPlace # win = win.epath if win.kind_of?(TkObject) win = _epath(win) if slot - conf = tk_split_list(tk_call_without_enc('place', 'configure', - win, "-#{slot}") ) - { conf[0][1..-1] => conf[1] } + #conf = tk_split_list(tk_call_without_enc('place', 'configure', + # win, "-#{slot}") ) + conf = tk_split_simplelist(tk_call_without_enc('place', 'configure', + win, "-#{slot}") ) + # { conf[0][1..-1] => conf[1] } + { conf[0][1..-1] => tk_tcl2ruby(conf[4]) } else ret = {} - tk_split_list(tk_call_without_enc('place','configure',win)).each{|conf| - ret[conf[0][1..-1]] = conf[1] + #tk_split_list(tk_call_without_enc('place','configure',win)).each{|conf| + tk_split_simplelist(tk_call_without_enc('place', 'configure', + win)).each{|conf_list| + #ret[conf[0][1..-1]] = conf[1] + conf = simplelist(conf_list) + ret[conf[0][1..-1]] = tk_tcl2ruby(conf[4]) } ret end @@ -76,10 +90,12 @@ module TkPlace def info(win) # win = win.epath if win.kind_of?(TkObject) win = _epath(win) - ilist = list(tk_call_without_enc('place', 'info', win)) + #ilist = list(tk_call_without_enc('place', 'info', win)) + ilist = simplelist(tk_call_without_enc('place', 'info', win)) info = {} while key = ilist.shift - info[key[1..-1]] = ilist.shift + #info[key[1..-1]] = ilist.shift + info[key[1..-1]] = tk_tcl2ruby(ilist.shift) end return info end @@ -90,7 +106,8 @@ module TkPlace list(tk_call('place', 'slaves', master)) end - module_function :configure, :configinfo, :forget, :info, :slaves + module_function :configure, :configinfo, :current_configinfo + module_function :forget, :info, :slaves end =begin def TkPlace(win, slot, value=None) diff --git a/ext/tk/lib/tk/root.rb b/ext/tk/lib/tk/root.rb index a32972561c..6e16fb1989 100644 --- a/ext/tk/lib/tk/root.rb +++ b/ext/tk/lib/tk/root.rb @@ -3,9 +3,11 @@ # require 'tk' require 'tk/wm' +require 'tk/menuspec' class TkRoot<TkWindow include Wm + include TkMenuSpec =begin ROOT = [] @@ -59,6 +61,25 @@ class TkRoot<TkWindow "." end + def add_menu(menu_info, tearoff=false, opts=nil) + # See tk/menuspec.rb for menu_info. + # opts is a hash of default configs for all of cascade menus. + # Configs of menu_info can override it. + if tearoff.kind_of?(Hash) + opts = tearoff + tearoff = false + end + _create_menubutton(self, menu_info, tearoff, opts) + end + + def add_menubar(menu_spec, tearoff=false, opts=nil) + # See tk/menuspec.rb for menu_spec. + # opts is a hash of default configs for all of cascade menus. + # Configs of menu_spec can override it. + menu_spec.each{|info| add_menu(info, tearoff, opts)} + self.menu + end + def TkRoot.destroy TkCore::INTERP._invoke('destroy', '.') end diff --git a/ext/tk/lib/tk/text.rb b/ext/tk/lib/tk/text.rb index b1e671e1e0..be3f814505 100644 --- a/ext/tk/lib/tk/text.rb +++ b/ext/tk/lib/tk/text.rb @@ -67,6 +67,11 @@ class TkText<TkTextWin tk_send_without_enc('index', _get_eval_enc_str(index)) end + def get_displaychars(*index) + # Tk8.5 feature + get('-displaychars', *index) + end + def value _fromUTF8(tk_send_without_enc('get', "1.0", "end - 1 char")) end @@ -326,9 +331,35 @@ class TkText<TkTextWin end def count(idx1, idx2, *opts) - opts = opts.collect{|opt| '-' + opt.to_s} - number(tk_send_without_enc('count', _get_eval_enc_str(idx1), - _get_eval_enc_str(idx2), *opts)) + # opts are Tk8.5 feature + cnt = 0 + args = opts.collect{|opt| + str = opt.to_s + cnt += 1 if str != 'update' + '-' + str + } + args << _get_eval_enc_str(idx1) << _get_eval_enc_str(idx2) + if cnt <= 1 + number(tk_send_without_enc('count', *opts)) + else + list(tk_send_without_enc('count', *opts)) + end + end + + def count_info(idx1, idx2, update=true) + # Tk8.5 feature + opts = [ + :chars, :displaychars, :displayindices, :displaylines, + :indices, :lines, :xpixels, :ypixels + ] + if update + lst = count(idx1, idx2, :update, *opts) + else + lst = count(idx1, idx2, *opts) + end + info = {} + opts.each_with_index{|key, idx| info[key] = lst[idx]} + info end def replace(idx1, idx2, *opts) @@ -879,53 +910,40 @@ class TkText<TkTextWin def tksearch(*args) # call 'search' subcommand of text widget # args ::= [<array_of_opts>] <pattern> <start_index> [<stop_index>] - # <pattern> must be a regular expression of Tcl - all_mode = false - opts = args.shift - if opts.kind_of?(Array) - opts = opts.collect{|opt| - opt = opt.to_s - all_mode = true if opt == 'all' - opt - } + # If <pattern> is regexp, then it must be a regular expression of Tcl + if args[0].kind_of?(Array) + opts = args.shift.collect{|opt| '-' + opt.to_s } else - args.unshift(opts) opts = [] end opts << '--' - if all_mode - tk_split_simplelist(tk_send(*(opts + args))) + ret = tk_send('search', *(opts + args)) + if ret == "" + nil else - tk_send(*(opts + args)) + ret end end def tksearch_with_count(*args) # call 'search' subcommand of text widget # args ::= [<array_of_opts>] <var> <pattern> <start_index> [<stop_index>] - # <pattern> must be a regular expression of Tcl - all_mode = false - opts = args.shift - if opts.kind_of?(Array) - opts = opts.collect{|opt| - opt = opt.to_s - all_mode = true if opt == 'all' - opt - } - var = args.shift + # If <pattern> is regexp, then it must be a regular expression of Tcl + if args[0].kind_of?(Array) + opts = args.shift.collect{|opt| '-' + opt.to_s } else - var = opts opts = [] end - opts << '-count' << var << '--' + opts << '-count' << args.shift << '--' - if all_mode - tk_split_simplelist(tk_send(*(opts + args))) + ret = tk_send('search', *(opts + args)) + if ret == "" + nil else - tk_send(*(opts + args)) + ret end end diff --git a/ext/tk/lib/tk/toplevel.rb b/ext/tk/lib/tk/toplevel.rb index b7f9bed740..c95002dbeb 100644 --- a/ext/tk/lib/tk/toplevel.rb +++ b/ext/tk/lib/tk/toplevel.rb @@ -3,9 +3,11 @@ # require 'tk' require 'tk/wm' +require 'tk/menuspec' class TkToplevel<TkWindow include Wm + include TkMenuSpec TkCommandNames = ['toplevel'.freeze].freeze WidgetClassName = 'Toplevel'.freeze @@ -169,6 +171,25 @@ class TkToplevel<TkWindow @classname end + def add_menu(menu_info, tearoff=false, opts=nil) + # See tk/menuspec.rb for menu_info. + # opts is a hash of default configs for all of cascade menus. + # Configs of menu_info can override it. + if tearoff.kind_of?(Hash) + opts = tearoff + tearoff = false + end + _create_menubutton(self, menu_info, tearoff, opts) + end + + def add_menubar(menu_spec, tearoff=false, opts=nil) + # See tk/menuspec.rb for menu_spec. + # opts is a hash of default configs for all of cascade menus. + # Configs of menu_spec can override it. + menu_spec.each{|info| add_menu(info, tearoff, opts)} + self.menu + end + def self.database_class if self == WidgetClassNames[WidgetClassName] || self.name == '' self diff --git a/ext/tk/lib/tk/variable.rb b/ext/tk/lib/tk/variable.rb index f50fca5697..43baac458d 100644 --- a/ext/tk/lib/tk/variable.rb +++ b/ext/tk/lib/tk/variable.rb @@ -588,7 +588,8 @@ end =end else newopts = @trace_opts.dup - opts.each_byte{|c| newopts += c.chr unless newopts.index(c)} + #opts.each_byte{|c| newopts += c.chr unless newopts.index(c)} + opts.each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)} if newopts != @trace_opts Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts, 'rb_var') @trace_opts.replace(newopts) @@ -637,7 +638,8 @@ end =end else newopts = @trace_opts.dup - opts.each_byte{|c| newopts += c.chr unless newopts.index(c)} + # opts.each_byte{|c| newopts += c.chr unless newopts.index(c)} + opts.each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)} if newopts != @trace_opts Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts, 'rb_var') @trace_opts.replace(newopts) @@ -684,7 +686,8 @@ end idx = i next end - e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)} + # e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)} + e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)} } if idx >= 0 @trace_var.delete_at(idx) @@ -694,7 +697,8 @@ end @trace_elem.each{|elem| @trace_elem[elem].each{|e| - e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)} + # e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)} + e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)} } } @@ -751,11 +755,13 @@ end newopts = '' @trace_var.each{|e| - e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)} + # e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)} + e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)} } @trace_elem.each{|elem| @trace_elem[elem].each{|e| - e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)} + # e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)} + e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)} } } diff --git a/ext/tk/sample/menubar1.rb b/ext/tk/sample/menubar1.rb new file mode 100644 index 0000000000..9fa1201d41 --- /dev/null +++ b/ext/tk/sample/menubar1.rb @@ -0,0 +1,51 @@ +# +# menubar sample 1 : use frame and menubuttons +# + +require 'tk' + +radio_var = TkVariable.new('y') + +menu_spec = [ + [['File', 0], + {: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'], 6, '', {:foreground=>'black'}], + ['Radio_Y', [radio_var, 'y'], 6], + ['Radio_Z', [radio_var, 'z'], 6], + '---', + ['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 1')}, 6]] +] + +menubar = TkMenubar.new(nil, menu_spec, + 'tearoff'=>false, + 'foreground'=>'grey40', + 'activeforeground'=>'red', + 'font'=>'Helvetia 12 bold') +menubar.pack('side'=>'top', 'fill'=>'x') + +TkText.new(:wrap=>'word').pack.insert('1.0', '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/menubar2.rb).') + +Tk.mainloop diff --git a/ext/tk/sample/menubar2.rb b/ext/tk/sample/menubar2.rb new file mode 100644 index 0000000000..6ca58e45a4 --- /dev/null +++ b/ext/tk/sample/menubar2.rb @@ -0,0 +1,56 @@ +# +# menubar sample 2 : use 'menu' option of root/toplevel widget +# + +require 'tk' + +radio_var = TkVariable.new('y') + +menu_spec = [ + [['File', 0], + {: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'], 6, '', {:foreground=>'black'}], + ['Radio_Y', [radio_var, 'y'], 6], + ['Radio_Z', [radio_var, 'z'], 6], + '---', + ['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 2')}, 6]] +] + +mbar = Tk.root.add_menubar(menu_spec, + # followings are default configure options + 'tearoff'=>'false', + 'foreground'=>'grey40', + 'activeforeground'=>'red', + 'font'=>'Helvetia 12 bold') +# This (default configure options) is NOT same the following. +# +# mbar = Tk.root.add_menubar(menu_spec) +# mbar.configure('foreground'=>'grey40', 'activeforeground'=>'red', +# 'font'=>'Helvetia 12 bold') + +TkText.new(:wrap=>'word').pack.insert('1.0', 'Please read the sample source, and check how to override default configure options of menu entries on a menu_spec.') + +Tk.mainloop diff --git a/ext/tk/tkutil.c b/ext/tk/tkutil.c index 78e666d1b1..bc02b43bf2 100644 --- a/ext/tk/tkutil.c +++ b/ext/tk/tkutil.c @@ -27,6 +27,7 @@ static ID ID_split_tklist; static ID ID_toUTF8; static ID ID_fromUTF8; static ID ID_path; +static ID ID_at_path; static ID ID_to_eval; static ID ID_to_s; static ID ID_install_cmd; @@ -1073,7 +1074,7 @@ static VALUE tkobj_path(self) VALUE self; { - return rb_ivar_get(self, ID_path); + return rb_ivar_get(self, ID_at_path); } /*************************************/ @@ -1091,6 +1092,7 @@ Init_tkutil() cMethod = rb_const_get(rb_cObject, rb_intern("Method")); ID_path = rb_intern("path"); + ID_at_path = rb_intern("@path"); ID_to_eval = rb_intern("to_eval"); ID_to_s = rb_intern("to_s"); ID_install_cmd = rb_intern("install_cmd"); |