summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog19
-rw-r--r--ext/tcltklib/extconf.rb11
-rw-r--r--ext/tcltklib/tcltklib.c65
-rw-r--r--ext/tk/MANIFEST3
-rw-r--r--ext/tk/lib/multi-tk.rb3
-rw-r--r--ext/tk/lib/tk.rb89
-rw-r--r--ext/tk/lib/tk/grid.rb48
-rw-r--r--ext/tk/lib/tk/menubar.rb127
-rw-r--r--ext/tk/lib/tk/menuspec.rb243
-rw-r--r--ext/tk/lib/tk/optiondb.rb3
-rw-r--r--ext/tk/lib/tk/place.rb39
-rw-r--r--ext/tk/lib/tk/root.rb21
-rw-r--r--ext/tk/lib/tk/text.rb80
-rw-r--r--ext/tk/lib/tk/toplevel.rb21
-rw-r--r--ext/tk/lib/tk/variable.rb18
-rw-r--r--ext/tk/sample/menubar1.rb51
-rw-r--r--ext/tk/sample/menubar2.rb56
-rw-r--r--ext/tk/tkutil.c4
18 files changed, 724 insertions, 177 deletions
diff --git a/ChangeLog b/ChangeLog
index fa36d54d46..6b02c86804 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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");