summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authornagai <nagai@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2002-06-04 07:03:33 +0000
committernagai <nagai@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2002-06-04 07:03:33 +0000
commit4cb164ee2a30ecb59ce93670e569f384c7da7521 (patch)
treeb72a391e53110bb8b216ef9d16741b314f148ce6 /ext
parentdc010ff5157787b80ed35410587d0b988d55dda4 (diff)
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc TkAfter#current_interval returns an interval (sleep) time value TkAfter#current_args returns an array of arguments TkAfter#return_value returns a return value of last loop-proc e.g. TkAfter.new( proc{|obj| 500 - obj.current_interval}, 10, [proc{|obj| p obj.current_args}, 'proc', 1], proc{|obj| p obj.current_args; ['return', 2]}, [proc{|obj| p obj.return_value p ['proc', obj.current_args[0].call(obj.return_value[1], obj.current_args[1])]}, proc{|*args| args[0] + args[1]}, 1], proc{p ['proc', 4]} ).start(100) * tk*.rb: Allow to use Symbols for parameters. Allow new notation of constructor (also allow old notation). e.g. TkFrame.new('classname'=>'User'){|base| pack f = TkFrame.new(base, :classname=>'ButtonFrame').pack TkButton.new( :parent => f, :text => 'Quit', :command => proc{exit} ).pack( :fill => :x, :pady => 2 ) } * tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item constructor (for new notation of constructor). e.g. c = TkCanvas.new.pack l = TkcLine.new(c, :coords=>[[0,0], [100,100]]) * tcltklib.c: New 'mainloop' and 'mainloop_watchdog'. The priority of their event-loop can be controlled. They accept an optional argument. If it false, they don't exit although the root widget is destroyed. This function is sometimes useful, if it is used with 'restart'. 'mainloop' can't treat Thread#join/value in a callback routine. (e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) ) 'mainloop_watchdog' can treat them, but watchdog thread is always running (so, a little heavier than 'mainloop'). If the purpose of using Thread#join/value is to do something under some safe-level, please use Proc object. (e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE}) * tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'. * tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter. 'app-name' specifies the name and the resource class of the application. If 'app-name' is specified to 'xxx', the application class on the resource database is set to 'Xxx' and the application name is changed by the same rule of Tk.appname method. 'use' specifies the main window for embedding the root widget instead of generating a new window. * tk.rb: Add new parameter 'widgetname' to the widget constructor to support effective use of Resource Database. For example, the resource 'Xxx*quit.text: QUIT' can set the text of the button generated by the following code. e.g. Tk.restart('Xxx') TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack Tk.mainloop * tk.rb: TkOption::get always returns a tainted string. Add TkOption::new_proc_class. It generates a class to import procedures defined on the resource database. For example, there is a following resource file. ----< resource-test >------------ *CMD.foo: {|*args| p [$SAFE, :foo, args]} *CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]} *Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)} --------------------------------- The following code is a sample of use of the resource file. e.g. require 'tk' TkOption.readfile 'resource-test' p TkOption.new_proc_class(:CMD, [:foo], 1) p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD) TkButton.new(:text=>'test').pack Tk.mainloop git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext')
-rw-r--r--ext/tcltklib/tcltklib.c410
-rw-r--r--ext/tk/lib/tk.rb296
-rw-r--r--ext/tk/lib/tkafter.rb42
-rw-r--r--ext/tk/lib/tkcanvas.rb33
-rw-r--r--ext/tk/lib/tkclass.rb11
-rw-r--r--ext/tk/lib/tkdialog.rb1
-rw-r--r--ext/tk/lib/tkentry.rb7
-rw-r--r--ext/tk/lib/tkfont.rb17
-rw-r--r--ext/tk/lib/tkmenubar.rb10
-rw-r--r--ext/tk/lib/tktext.rb65
10 files changed, 721 insertions, 171 deletions
diff --git a/ext/tcltklib/tcltklib.c b/ext/tcltklib/tcltklib.c
index 990fbc38af6..ba7fdc50000 100644
--- a/ext/tcltklib/tcltklib.c
+++ b/ext/tcltklib/tcltklib.c
@@ -48,20 +48,44 @@ int *tclDummyMathPtr = (int *) matherr;
/*---- module TclTkLib ----*/
struct invoke_queue {
+ Tcl_Event ev;
int argc;
VALUE *argv;
VALUE obj;
int done;
- VALUE result;
+ int safe_level;
+ VALUE *result;
VALUE thread;
- struct invoke_queue *next;
};
-static struct invoke_queue *iqueue;
static VALUE main_thread;
+static VALUE eventloop_thread;
+static VALUE watchdog_thread;
+Tcl_Interp *current_interp;
+
+/*
+ * 'event_loop_max' is a maximum events which the eventloop processes in one
+ * term of thread scheduling. 'no_event_tick' is the count-up value when
+ * there are no event for processing.
+ * 'timer_tick' is a limit of one term of thread scheduling.
+ * If 'timer_tick' == 0, then not use the timer for thread scheduling.
+ */
+static int tick_counter;
+#define DEFAULT_EVENT_LOOP_MAX 800
+#define DEFAULT_NO_EVENT_TICK 10
+#define DEFAULT_TIMER_TICK 0
+static int event_loop_max = DEFAULT_EVENT_LOOP_MAX;
+static int no_event_tick = DEFAULT_NO_EVENT_TICK;
+static int timer_tick = DEFAULT_TIMER_TICK;
+
+#if TCL_MAJOR_VERSION >= 8
+static int ip_ruby _((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST*));
+#else
+static int ip_ruby _((ClientData, Tcl_Interp *, int, char **));
+#endif
/* Tk_ThreadTimer */
-static Tcl_TimerToken timer_token;
+static Tcl_TimerToken timer_token = (Tcl_TimerToken)NULL;
/* timer callback */
static void _timer_for_tcl _((ClientData));
@@ -73,44 +97,230 @@ _timer_for_tcl(clientData)
VALUE thread;
Tk_DeleteTimerHandler(timer_token);
- timer_token = Tk_CreateTimerHandler(100, _timer_for_tcl, (ClientData)0);
-
- CHECK_INTS;
- q = iqueue;
- while (q) {
- tmp = q;
- q = q->next;
- if (!tmp->done) {
- tmp->done = 1;
- tmp->result = ip_invoke_real(tmp->argc, tmp->argv, tmp->obj);
- thread = tmp->thread;
- tmp = tmp->next;
- rb_thread_run(thread);
+ if (timer_tick > 0) {
+ timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl,
+ (ClientData)0);
+ } else {
+ timer_token = (Tcl_TimerToken)NULL;
+ }
+
+ /* rb_thread_schedule(); */
+ timer_tick += event_loop_max;
+}
+
+static VALUE
+set_eventloop_tick(self, tick)
+ VALUE self;
+ VALUE tick;
+{
+ int ttick = NUM2INT(tick);
+
+ if (ttick < 0) {
+ rb_raise(rb_eArgError, "timer-tick parameter must be 0 or plus number");
+ }
+
+ /* delete old timer callback */
+ Tk_DeleteTimerHandler(timer_token);
+
+ timer_tick = ttick;
+ if (timer_tick > 0) {
+ /* start timer callback */
+ timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl,
+ (ClientData)0);
+ } else {
+ timer_token = (Tcl_TimerToken)NULL;
+ }
+
+ return tick;
+}
+
+static VALUE
+get_eventloop_tick(self)
+ VALUE self;
+{
+ return INT2NUM(timer_tick);
+}
+
+static VALUE
+set_eventloop_weight(self, loop_max, no_event)
+ VALUE self;
+ VALUE loop_max;
+ VALUE no_event;
+{
+ int lpmax = NUM2INT(loop_max);
+ int no_ev = NUM2INT(no_event);
+
+ if (lpmax <= 0 || no_ev <= 0) {
+ rb_raise(rb_eArgError, "weight parameters must be plus number");
+ }
+
+ event_loop_max = lpmax;
+ no_event_tick = no_ev;
+
+ return rb_ary_new3(2, loop_max, no_event);
+}
+
+static VALUE
+get_eventloop_weight(self)
+ VALUE self;
+{
+ return rb_ary_new3(2, INT2NUM(event_loop_max), INT2NUM(no_event_tick));
+}
+
+VALUE
+lib_mainloop_core(check_root_widget)
+ VALUE check_root_widget;
+{
+ VALUE current = eventloop_thread;
+ int check = (check_root_widget == Qtrue);
+
+ Tk_DeleteTimerHandler(timer_token);
+ if (timer_tick > 0) {
+ timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl,
+ (ClientData)0);
+ } else {
+ timer_token = (Tcl_TimerToken)NULL;
+ }
+
+ for(;;) {
+ tick_counter = 0;
+ while(tick_counter < event_loop_max) {
+ if (Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT)) {
+ tick_counter++;
+ } else {
+ tick_counter += no_event_tick;
}
+ if (watchdog_thread != 0 && eventloop_thread != current) {
+ return Qnil;
+ }
+ }
+ if (check && Tk_GetNumMainWindows() == 0) {
+ break;
+ }
+ rb_thread_schedule();
}
- rb_thread_schedule();
+ return Qnil;
}
-#if TCL_MAJOR_VERSION >= 8
-static int ip_ruby _((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST*));
-#else
-static int ip_ruby _((ClientData, Tcl_Interp *, int, char **));
-#endif
+
+VALUE
+lib_mainloop_ensure(parent_evloop)
+ VALUE parent_evloop;
+{
+ if (ruby_debug) {
+ fprintf(stderr, "tcltklib: eventloop-thread : %lx -> %lx\n",
+ eventloop_thread, parent_evloop);
+ }
+
+ Tk_DeleteTimerHandler(timer_token);
+ timer_token = (Tcl_TimerToken)NULL;
+ eventloop_thread = parent_evloop;
+ return Qnil;
+}
+
+static VALUE
+lib_mainloop_launcher(check_rootwidget)
+ VALUE check_rootwidget;
+{
+ VALUE parent_evloop = eventloop_thread;
+
+ eventloop_thread = rb_thread_current();
+
+ if (ruby_debug) {
+ fprintf(stderr, "tcltklib: eventloop-thread : %lx -> %lx\n",
+ parent_evloop, eventloop_thread);
+ }
+
+ return rb_ensure(lib_mainloop_core, check_rootwidget,
+ lib_mainloop_ensure, parent_evloop);
+}
/* execute Tk_MainLoop */
static VALUE
-lib_mainloop(self)
+lib_mainloop(argc, argv, self)
+ int argc;
+ VALUE *argv;
VALUE self;
{
- timer_token = Tk_CreateTimerHandler(100, _timer_for_tcl, (ClientData)0);
- DUMP1("start Tk_Mainloop");
- Tk_MainLoop();
- DUMP1("stop Tk_Mainloop");
- Tk_DeleteTimerHandler(timer_token);
+ VALUE check_rootwidget;
+
+ if (rb_scan_args(argc, argv, "01", &check_rootwidget) == 0) {
+ check_rootwidget = Qtrue;
+ } else if (RTEST(check_rootwidget)) {
+ check_rootwidget = Qtrue;
+ } else {
+ check_rootwidget = Qfalse;
+ }
+
+ return lib_mainloop_launcher(check_rootwidget);
+}
+
+static VALUE
+lib_mainloop_watchdog(argc, argv, self)
+ int argc;
+ VALUE *argv;
+ VALUE self;
+{
+ VALUE check_rootwidget;
+ VALUE evloop;
+ int check;
+ ID stop;
+
+ if (rb_scan_args(argc, argv, "01", &check_rootwidget) == 0) {
+ check_rootwidget = Qtrue;
+ } else if (RTEST(check_rootwidget)) {
+ check_rootwidget = Qtrue;
+ } else {
+ check_rootwidget = Qfalse;
+ }
+ check = (check_rootwidget == Qtrue);
+ stop = rb_intern("stop?");
+
+ /* check other watchdog thread */
+ if (watchdog_thread != 0) {
+ if (rb_funcall(watchdog_thread, stop, 0) == Qtrue) {
+ rb_funcall(watchdog_thread, rb_intern("kill"), 0);
+ } else {
+ return Qnil;
+ }
+ }
+ watchdog_thread = rb_thread_current();
+
+ /* watchdog start */
+ do {
+ if (eventloop_thread == 0
+ || rb_funcall(eventloop_thread, stop, 0) == Qtrue) {
+ /* start new eventloop thread */
+ DUMP2("eventloop thread %lx is sleeping or dead", eventloop_thread);
+ evloop = rb_thread_create(lib_mainloop_launcher,
+ (void*)&check_rootwidget);
+ DUMP2("create new eventloop thread %lx", evloop);
+ rb_thread_run(evloop);
+ }
+ rb_thread_schedule();
+ } while(!check || Tk_GetNumMainWindows() != 0);
return Qnil;
}
+static VALUE
+lib_do_one_event(argc, argv, self)
+ int argc;
+ VALUE *argv;
+ VALUE self;
+{
+ VALUE obj, vflags;
+ int flags;
+
+ if (rb_scan_args(argc, argv, "01", &vflags) == 0) {
+ flags = 0;
+ } else {
+ Check_Type(vflags, T_FIXNUM);
+ flags = FIX2INT(vflags);
+ }
+ return INT2NUM(Tcl_DoOneEvent(flags));
+}
+
/*---- class TclTkIp ----*/
struct tcltkip {
Tcl_Interp *ip; /* the interpreter */
@@ -245,6 +455,7 @@ ip_new(self)
/* from Tk_Main() */
DUMP1("Tcl_CreateInterp");
ptr->ip = Tcl_CreateInterp();
+ current_interp = ptr->ip;
/* from Tcl_AppInit() */
DUMP1("Tcl_Init");
@@ -459,48 +670,103 @@ ip_invoke_real(argc, argv, obj)
return rb_str_new2(ptr->ip->result);
}
+VALUE
+ivq_safelevel_handler(arg, ivq)
+ VALUE arg;
+ VALUE ivq;
+{
+ struct invoke_queue *q;
+
+ Data_Get_Struct(ivq, struct invoke_queue, q);
+ DUMP2("(safe-level handler) $SAFE = %d", q->safe_level);
+ rb_set_safe_level(q->safe_level);
+ return ip_invoke_real(q->argc, q->argv, q->obj);
+}
+
+int
+invoke_queue_handler(evPtr, flags)
+ Tcl_Event *evPtr;
+ int flags;
+{
+ struct invoke_queue *tmp, *q = (struct invoke_queue *)evPtr;
+
+ DUMP1("do_invoke_queue_handler");
+ DUMP2("invoke queue_thread : %lx", rb_thread_current());
+ DUMP2("added by thread : %lx", q->thread);
+
+ if (q->done) {
+ /* processed by another event-loop */
+ return 0;
+ }
+
+ /* process it */
+ q->done = 1;
+
+ /* check safe-level */
+ if (rb_safe_level() != q->safe_level) {
+ *(q->result) = rb_funcall(rb_proc_new(ivq_safelevel_handler,
+ Data_Wrap_Struct(rb_cData,0,0,q)),
+ rb_intern("call"), 0);
+ } else {
+ *(q->result) = ip_invoke_real(q->argc, q->argv, q->obj);
+ }
+
+ /* back to caller */
+ rb_thread_run(q->thread);
+
+ /* end of handler : remove it */
+ return 1;
+}
+
static VALUE
ip_invoke(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
{
- struct invoke_queue *tmp, *p;
- VALUE result = rb_thread_current();
+ struct invoke_queue *tmp;
+ VALUE current = rb_thread_current();
+ VALUE result;
+ VALUE *alloc_argv, *alloc_result;
+ Tcl_QueuePosition position;
- if (result == main_thread) {
- return ip_invoke_real(argc, argv, obj);
+ if (eventloop_thread == 0 || current == eventloop_thread) {
+ DUMP2("invoke from current eventloop %lx", current);
+ return ip_invoke_real(argc, argv, obj);
}
- tmp = ALLOC(struct invoke_queue);
+
+ DUMP2("invoke from thread %lx (NOT current eventloop)", current);
+
+ /* allocate memory (protected from Tcl_ServiceEvent) */
+ alloc_argv = ALLOC_N(VALUE,argc);
+ MEMCPY(alloc_argv, argv, VALUE, argc);
+ alloc_result = ALLOC(VALUE);
+
+ /* allocate memory (freed by Tcl_ServiceEvent */
+ tmp = (struct invoke_queue *)Tcl_Alloc(sizeof(struct invoke_queue));
+
+ /* construct event data */
+ tmp->done = 0;
tmp->obj = obj;
tmp->argc = argc;
- tmp->argv = ALLOC_N(VALUE, argc);
- MEMCPY(tmp->argv, argv, VALUE, argc);
- tmp->thread = result;
- tmp->done = 0;
+ tmp->argv = alloc_argv;
+ tmp->result = alloc_result;
+ tmp->thread = current;
+ tmp->safe_level = rb_safe_level();
+ tmp->ev.proc = invoke_queue_handler;
+ position = TCL_QUEUE_TAIL;
- tmp->next = iqueue;
- iqueue = tmp;
+ /* add the handler to Tcl event queue */
+ Tcl_QueueEvent(&tmp->ev, position);
+ /* wait for the handler to be processed */
rb_thread_stop();
- result = tmp->result;
- if (iqueue == tmp) {
- iqueue = tmp->next;
- free(tmp->argv);
- free(tmp);
- return result;
- }
- p = iqueue;
- while (p->next) {
- if (p->next == tmp) {
- p->next = tmp->next;
- free(tmp->argv);
- free(tmp);
- break;
- }
- p = p->next;
- }
+ /* get result & free allocated memory */
+ result = *alloc_result;
+ free(alloc_argv);
+ free(alloc_result);
+
return result;
}
@@ -533,6 +799,14 @@ Init_tcltklib()
VALUE lib = rb_define_module("TclTkLib");
VALUE ip = rb_define_class("TclTkIp", rb_cObject);
+ VALUE ev_flag = rb_define_module_under(lib, "EventFlag");
+ rb_define_const(ev_flag, "WINDOW", INT2FIX(TCL_WINDOW_EVENTS));
+ rb_define_const(ev_flag, "FILE", INT2FIX(TCL_FILE_EVENTS));
+ rb_define_const(ev_flag, "TIMER", INT2FIX(TCL_TIMER_EVENTS));
+ rb_define_const(ev_flag, "IDLE", INT2FIX(TCL_IDLE_EVENTS));
+ rb_define_const(ev_flag, "ALL", INT2FIX(TCL_ALL_EVENTS));
+ rb_define_const(ev_flag, "DONT_WAIT", INT2FIX(TCL_DONT_WAIT));
+
#if defined USE_TCL_STUBS && defined USE_TK_STUBS
extern int ruby_tcltk_stubs();
int ret = ruby_tcltk_stubs();
@@ -543,7 +817,16 @@ Init_tcltklib()
eTkCallbackBreak = rb_define_class("TkCallbackBreak", rb_eStandardError);
eTkCallbackContinue = rb_define_class("TkCallbackContinue",rb_eStandardError);
- rb_define_module_function(lib, "mainloop", lib_mainloop, 0);
+ rb_define_module_function(lib, "mainloop", lib_mainloop, -1);
+ rb_define_module_function(lib, "mainloop_watchdog",
+ lib_mainloop_watchdog, -1);
+ rb_define_module_function(lib, "do_one_event", lib_do_one_event, -1);
+ rb_define_module_function(lib, "set_eventloop_tick",set_eventloop_tick,1);
+ rb_define_module_function(lib, "get_eventloop_tick",get_eventloop_tick,0);
+ rb_define_module_function(lib, "set_eventloop_weight",
+ set_eventloop_weight, 2);
+ rb_define_module_function(lib, "get_eventloop_weight",
+ get_eventloop_weight, 0);
rb_define_singleton_method(ip, "new", ip_new, 0);
rb_define_method(ip, "_eval", ip_eval, 1);
@@ -551,10 +834,19 @@ Init_tcltklib()
rb_define_method(ip, "_fromUTF8",ip_fromUTF8,2);
rb_define_method(ip, "_invoke", ip_invoke, -1);
rb_define_method(ip, "_return_value", ip_retval, 0);
- rb_define_method(ip, "mainloop", lib_mainloop, 0);
+ rb_define_method(ip, "mainloop", lib_mainloop, -1);
+ rb_define_method(ip, "mainloop_watchdog", lib_mainloop_watchdog, -1);
+ rb_define_method(ip, "do_one_event", lib_do_one_event, -1);
+ rb_define_method(ip, "set_eventloop_tick", set_eventloop_tick, 1);
+ rb_define_method(ip, "get_eventloop_tick", get_eventloop_tick, 0);
+ rb_define_method(ip, "set_eventloop_weight", set_eventloop_weight, 2);
+ rb_define_method(ip, "get_eventloop_weight", get_eventloop_weight, 0);
rb_define_method(ip, "restart", lib_restart, 0);
main_thread = rb_thread_current();
+ eventloop_thread = 0;
+ watchdog_thread = 0;
+
#ifdef __MACOS__
_macinit();
#endif
diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb
index bac2ae35f98..2e33c4294c1 100644
--- a/ext/tk/lib/tk.rb
+++ b/ext/tk/lib/tk.rb
@@ -132,6 +132,13 @@ module TkComm
end
private :tk_tcl2ruby, :tk_split_list, :tk_split_simplelist
+ def _symbolkey2str(keys)
+ h = {}
+ keys.each{|key,value| h[key.to_s] = value}
+ h
+ end
+ private :_symbolkey2str
+
def hash_kv(keys)
conf = []
if keys and keys != None
@@ -204,6 +211,8 @@ module TkComm
return nil if str == None
if str.kind_of?(String)
# do nothing
+ elsif str.kind_of?(Symbol)
+ str = str.id2name
elsif str.kind_of?(Hash)
str = hash_kv(str).join(" ")
elsif str.kind_of?(Array)
@@ -259,13 +268,15 @@ module TkComm
end
private :install_cmd, :uninstall_cmd
- def install_win(ppath)
- id = format("w%.4d", Tk_IDs[1])
- Tk_IDs[1] += 1
+ def install_win(ppath,name=nil)
+ if !name or name == ''
+ name = format("w%.4d", Tk_IDs[1])
+ Tk_IDs[1] += 1
+ end
if !ppath or ppath == "."
- @path = format(".%s", id);
+ @path = format(".%s", name);
else
- @path = format("%s.%s", ppath, id)
+ @path = format("%s.%s", ppath, name)
end
Tk_WINDOWS[@path] = self
end
@@ -483,6 +494,8 @@ module TkCore
}
EOL
+ EventFlag = TclTkLib::EventFlag
+
def callback_break
fail TkCallbackBreak, "Tk callback returns 'break' status"
end
@@ -616,12 +629,42 @@ module TkCore
tk_call('info', *args)
end
- def mainloop
- TclTkLib.mainloop
+ def mainloop(check_root = true)
+ TclTkLib.mainloop(check_root)
end
- def restart
+ def mainloop_watchdog(check_root = true)
+ TclTkLib.mainloop_watchdog(check_root)
+ end
+
+ def do_one_event(flag = 0)
+ TclTkLib.do_one_event(flag)
+ end
+
+ def set_eventloop_tick(timer_tick)
+ TclTkLib.set_eventloop_tick(timer_tick)
+ end
+
+ def get_eventloop_tick()
+ TclTkLib.get_eventloop_tick
+ end
+
+ def set_eventloop_weight(loop_max, no_event_tick)
+ TclTkLib.set_eventloop_weight(loop_max, no_event_tick)
+ end
+
+ def get_eventloop_weight()
+ TclTkLib.get_eventloop_weight
+ end
+
+ def restart(app_name = nil, use = nil)
+ tk_call('set', 'argv0', app_name) if app_name
+ if use
+ tk_call('set', 'argc', 2)
+ tk_call('set', 'argv', "-use #{use}")
+ end
TkCore::INTERP.restart
+ TkComm::Tk_CMDTBL.clear
TkComm::Tk_WINDOWS.clear
nil
end
@@ -2077,12 +2120,87 @@ module TkOption
tk_call 'option', 'clear'
end
def get win, name, klass
- tk_call 'option', 'get', win ,name, klass
+ tk_call('option', 'get', win ,name, klass).taint
end
def readfile file, pri=None
tk_call 'option', 'readfile', file, pri
end
module_function :add, :clear, :get, :readfile
+
+ # support procs on the resource database
+ @@resource_proc_class = Class.new
+ class << @@resource_proc_class
+ private :new
+
+ CARRIER = '.'.freeze
+ METHOD_TBL = {}
+ ADD_METHOD = false
+ SAFE_MODE = 4
+
+ def __check_proc_string__(str)
+ # If you want to check the proc_string, do it in this method.
+ str
+ end
+
+ def method_missing(id, *args)
+ res_proc = self::METHOD_TBL[id]
+ unless res_proc.kind_of? Proc
+ if id == :new || (!self::METHOD_TBL.has_key?(id) && !self::ADD_METHOD)
+ raise NoMethodError,
+ "not support resource-proc '#{id.id2name}' for #{self.name}"
+ end
+ proc_str = TkOption.get(self::CARRIER, id.id2name, '')
+ proc_str = '{' + proc_str + '}' unless /\A\{.*\}\Z/ =~ proc_str
+ proc_str = __check_proc_string__(proc_str)
+ res_proc = eval 'Proc.new' + proc_str
+ self::METHOD_TBL[id] = res_proc
+ end
+ proc{
+ $SAFE = self::SAFE_MODE
+ res_proc.call(*args)
+ }.call
+ end
+
+ private :__check_proc_string__, :method_missing
+ end
+
+ def new_proc_class(klass, func, safe = 4, add = false, parent = nil)
+ klass = klass.to_s if klass.kind_of? Symbol
+ unless (?A..?Z) === klass[0]
+ fail ArgumentError, "bad string '#{klass}' for class name"
+ end
+ unless func.kind_of? Array
+ fail ArgumentError, "method-list must be Array"
+ end
+ func_str = func.join(' ')
+ if parent == nil
+ install_win(parent)
+ elsif parent <= @@resource_proc_class
+ install_win(parent::CARRIER)
+ else
+ fail ArgumentError, "parent must be Resource-Proc class"
+ end
+ carrier = Tk.tk_call('frame', @path, '-class', klass)
+
+ body = <<-"EOD"
+ class #{klass} < TkOption.module_eval('@@resource_proc_class')
+ CARRIER = '#{carrier}'.freeze
+ METHOD_TBL = {}
+ ADD_METHOD = #{add}
+ SAFE_MODE = #{safe}
+ %w(#{func_str}).each{|f| METHOD_TBL[f.intern] = nil }
+ end
+ EOD
+
+ if parent.kind_of?(Class) && parent <= @@resource_proc_class
+ parent.class_eval body
+ eval parent.name + '::' + klass
+ else
+ eval body
+ eval 'TkOption::' + klass
+ end
+ end
+ module_function :new_proc_class
end
module TkTreatFont
@@ -2096,6 +2214,7 @@ module TkTreatFont
alias fontobj font_configinfo
def font_configure(slot)
+ slot = _symbolkey2str(slot)
if (fnt = slot.delete('font'))
if fnt.kind_of? TkFont
return fnt.call_font_configure(self.path, self.path,'configure',slot)
@@ -2203,6 +2322,7 @@ module TkTreatItemFont
def tagfont_configure(tagOrId, slot)
pathname = __item_pathname(tagOrId)
+ slot = _symbolkey2str(slot)
if (fnt = slot.delete('font'))
if fnt.kind_of? TkFont
return fnt.call_font_configure(pathname, self.path,
@@ -2345,7 +2465,7 @@ class TkObject<TkKernel
end
def cget(slot)
- case slot
+ case slot.to_s
when 'text', 'label', 'show', 'data', 'file'
tk_call path, 'cget', "-#{slot}"
else
@@ -2355,16 +2475,20 @@ class TkObject<TkKernel
def configure(slot, value=None)
if slot.kind_of? Hash
- if (slot['font'] || slot['kanjifont'] ||
- slot['latinfont'] || slot['asciifont'] )
- font_configure(slot.dup)
+ if (slot['font'] || slot[:font] ||
+ slot['kanjifont'] || slot[:kanjifont] ||
+ slot['latinfont'] || slot[:latinfont] ||
+ slot['asciifont'] || slot[:asciifont] )
+ font_configure(slot)
else
tk_call path, 'configure', *hash_kv(slot)
end
else
- if (slot == 'font' || slot == 'kanjifont' ||
- slot == 'latinfont' || slot == 'asciifont')
+ if (slot == 'font' || slot == :font ||
+ slot == 'kanjifont' || slot == :kanjifont ||
+ slot == 'latinfont' || slot == :latinfont ||
+ slot == 'asciifont' || slot == :asciifont )
if value == None
fontobj
else
@@ -2381,11 +2505,12 @@ class TkObject<TkKernel
end
def configinfo(slot = nil)
- if slot == 'font' || slot == 'kanjifont'
+ if slot == 'font' || slot == :font ||
+ slot == 'kanjifont' || slot == :kanjifont
fontobj
else
if slot
- case slot
+ case slot.to_s
when 'text', 'label', 'show', 'data', 'file'
conf = tk_split_simplelist(tk_send('configure', "-#{slot}") )
else
@@ -2455,7 +2580,19 @@ class TkWindow<TkObject
extend TkBindCore
def initialize(parent=nil, keys=nil)
- install_win(if parent then parent.path end)
+ if parent.kind_of? Hash
+ keys = _symbolkey2str(parent)
+ keydup = true
+ parent = keys.delete('parent')
+ widgetname = keys.delete('widgetname')
+ install_win(if parent then parent.path end, widgetname)
+ elsif keys
+ keys = _symbolkey2str(keys)
+ widgetname = keys.delete('widgetname')
+ install_win(if parent then parent.path end, widgetname)
+ else
+ install_win(if parent then parent.path end)
+ end
if self.method(:create_self).arity == 0
p 'create_self has no arg' if $DEBUG
create_self
@@ -2464,10 +2601,9 @@ class TkWindow<TkObject
configure(keys)
end
else
- p 'create_self has an arg' if $DEBUG
+ p 'create_self has args' if $DEBUG
fontkeys = {}
if keys
- keys = keys.dup
['font', 'kanjifont', 'latinfont', 'asciifont'].each{|key|
fontkeys[key] = keys.delete(key) if keys.key?(key)
}
@@ -2668,17 +2804,17 @@ class TkWindow<TkObject
tk_call 'grab', 'set', path
elsif args.length == 1
case args[0]
- when 'global'
+ when 'global', :global
return(tk_call 'grab', 'set', '-global', path)
- when 'release'
+ when 'release', :release
return(tk_call 'grab', 'release', path)
else
val = tk_call('grab', args[0], path)
end
case args[0]
- when 'current'
+ when 'current', :current
return window(val)
- when 'status'
+ when 'status', :status
return val
end
else
@@ -2811,15 +2947,27 @@ class TkToplevel<TkWindow
#################
def initialize(parent=nil, screen=nil, classname=nil, keys=nil)
+ if parent.kind_of? Hash
+ keys = _symbolkey2str(parent)
+ @screen = keys['screen']
+ @classname = keys['class']
+ @colormap = keys['colormap']
+ @container = keys['container']
+ @screen = keys['screen']
+ @use = keys['use']
+ @visual = keys['visual']
+ super(keys)
+ return
+ end
if screen.kind_of? Hash
- keys = screen
+ keys = _symbolkey2str(screen)
else
@screen = screen
end
@classname = classname
if keys.kind_of? Hash
- if keys.key?('classname')
- keys = keys.dup
+ keys = _symbolkey2str(keys)
+ if keys.key?(:classname) || keys.key?('classname')
keys['class'] = keys.delete('classname')
end
@classname = keys['class']
@@ -2875,17 +3023,24 @@ class TkFrame<TkWindow
#################
def initialize(parent=nil, keys=nil)
- if keys.kind_of? Hash
- if keys.key?('classname')
- keys = keys.dup
- keys['class'] = keys.delete('classname')
+ if parent.kind_of? Hash
+ keys = _symbolkey2str(parent)
+ else
+ if keys
+ keys = _symbolkey2str(keys)
+ keys['parent'] = parent
+ else
+ keys = {'parent'=>parent}
end
- @classname = keys['class']
- @colormap = keys['colormap']
- @container = keys['container']
- @visual = keys['visual']
end
- super(parent, keys)
+ if keys.key?('classname')
+ keys['class'] = keys.delete('classname')
+ end
+ @classname = keys['class']
+ @colormap = keys['colormap']
+ @container = keys['container']
+ @visual = keys['visual']
+ super(keys)
end
def create_self(keys)
@@ -3170,7 +3325,7 @@ class TkListbox<TkTextWin
end
def itemcget(index, key)
- case key
+ case key.to_s
when 'text', 'label', 'show'
tk_send 'itemcget', index, "-#{key}"
else
@@ -3179,16 +3334,20 @@ class TkListbox<TkTextWin
end
def itemconfigure(index, key, val=None)
if key.kind_of? Hash
- if (key['font'] || key['kanjifont'] ||
- key['latinfont'] || key['asciifont'])
- tagfont_configure(index, key.dup)
+ if (key['font'] || key[:font] ||
+ key['kanjifont'] || key[:kanjifont] ||
+ key['latinfont'] || key[:latinfont] ||
+ key['asciifont'] || key[:asciifont] )
+ tagfont_configure(index, _symbolkey2str(key))
else
tk_send 'itemconfigure', index, *hash_kv(key)
end
else
- if (key == 'font' || key == 'kanjifont' ||
- key == 'latinfont' || key == 'asciifont' )
+ if (key == 'font' || key == :font ||
+ key == 'kanjifont' || key == :kanjifont ||
+ key == 'latinfont' || key == :latinfont ||
+ key == 'asciifont' || key == :asciifont )
tagfont_configure(index, {key=>val})
else
tk_call 'itemconfigure', index, "-#{key}", val
@@ -3198,7 +3357,7 @@ class TkListbox<TkTextWin
def itemconfiginfo(index, key=nil)
if key
- case key
+ case key.to_s
when 'text', 'label', 'show'
conf = tk_split_simplelist(tk_send('itemconfigure',index,"-#{key}"))
else
@@ -3305,7 +3464,7 @@ class TkMenu<TkWindow
number(tk_send('yposition', index))
end
def entrycget(index, key)
- case key
+ case key.to_s
when 'text', 'label', 'show'
tk_send 'entrycget', index, "-#{key}"
else
@@ -3314,16 +3473,20 @@ class TkMenu<TkWindow
end
def entryconfigure(index, key, val=None)
if key.kind_of? Hash
- if (key['font'] || key['kanjifont'] ||
- key['latinfont'] || key['asciifont'])
- tagfont_configure(index, key.dup)
+ if (key['font'] || key[:font] ||
+ key['kanjifont'] || key[:kanjifont] ||
+ key['latinfont'] || key[:latinfont] ||
+ key['asciifont'] || key[:asciifont])
+ tagfont_configure(index, _symbolkey2str(key))
else
tk_send 'entryconfigure', index, *hash_kv(key)
end
else
- if (key == 'font' || key == 'kanjifont' ||
- key == 'latinfont' || key == 'asciifont' )
+ if (key == 'font' || key == :font ||
+ key == 'kanjifont' || key == :kanjifont ||
+ key == 'latinfont' || key == :latinfont ||
+ key == 'asciifont' || key == :asciifont )
tagfont_configure({key=>val})
else
tk_call 'entryconfigure', index, "-#{key}", val
@@ -3333,7 +3496,7 @@ class TkMenu<TkWindow
def entryconfiginfo(index, key=nil)
if key
- case key
+ case key.to_s
when 'text', 'label', 'show'
conf = tk_split_simplelist(tk_send('entryconfigure',index,"-#{key}"))
else
@@ -3371,17 +3534,28 @@ end
class TkMenuClone<TkMenu
def initialize(parent, type=None)
+ widgetname = nil
+ if parent.kind_of? Hash
+ keys = _symbolkey2str(parent)
+ parent = keys.delete('parent')
+ widgetname = keys.delete('widgetname')
+ type = keys.delete('type'); type = None unless type
+ end
unless parent.kind_of?(TkMenu)
fail ArgumentError, "parent must be TkMenu"
end
@parent = parent
- install_win(@parent.path)
+ install_win(@parent.path, widgetname)
tk_call @parent.path, 'clone', @path, type
end
end
module TkSystemMenu
def initialize(parent, keys=nil)
+ if parent.kind_of? Hash
+ keys = _symbolkey2str(parent)
+ parent = keys.delete('parent')
+ end
fail unless parent.kind_of? TkMenu
@path = format("%s.%s", parent.path, self.type::SYSMENU_NAME)
TkComm::Tk_WINDOWS[@path] = self
@@ -3437,6 +3611,12 @@ class TkOptionMenubutton<TkMenubutton
end
def initialize(parent=nil, var=TkVariable.new, firstval=nil, *vals)
+ if parent.kind_of Hash
+ keys = _symbolkey2str(parent)
+ parent = keys['parent']
+ var = keys['variable'] if keys['variable']
+ firstval, *vals = keys['values']
+ end
fail unless var.kind_of? TkVariable
@variable = var
firstval = @variable.value unless firstval
@@ -3498,9 +3678,17 @@ module TkComposite
extend Tk
def initialize(parent=nil, *args)
- @frame = TkFrame.new(parent)
- @path = @epath = @frame.path
- initialize_composite(*args)
+ if parent.kind_of? Hash
+ keys = _symbolkey2str(parent)
+ parent = keys['parent']
+ keys['parent'] = @frame = TkFrame.new(parent)
+ @path = @epath = @frame.path
+ initialize_composite(keys)
+ else
+ @frame = TkFrame.new(parent)
+ @path = @epath = @frame.path
+ initialize_composite(*args)
+ end
end
def epath
diff --git a/ext/tk/lib/tkafter.rb b/ext/tk/lib/tkafter.rb
index fe3ee387407..ec39d9957ff 100644
--- a/ext/tk/lib/tkafter.rb
+++ b/ext/tk/lib/tkafter.rb
@@ -1,6 +1,7 @@
#
# tkafter.rb : methods for Tcl/Tk after command
-# 2000/08/01 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+#
+# $Id$
#
require 'tk'
@@ -11,18 +12,16 @@ class TkAfter
Tk_CBID = [0]
Tk_CBTBL = {}
- INTERP._invoke("proc", "rb_after", "args", "ruby [format \"TkAfter.callback %%Q!%s!\" $args]")
+ INTERP._invoke("proc", "rb_after", "id", "ruby [format \"TkAfter.callback %%Q!%s!\" $id]")
###############################
# class methods
###############################
- def TkAfter.callback(arg)
+ def TkAfter.callback(obj_id)
@after_id = nil
- arg = Array(tk_split_list(arg))
- obj_id = arg.shift
ex_obj = Tk_CBTBL[obj_id]
return nil if ex_obj == nil; # canceled
- _get_eval_string(ex_obj.do_callback(*arg))
+ _get_eval_string(ex_obj.do_callback)
end
def TkAfter.info
@@ -35,10 +34,10 @@ class TkAfter
###############################
# instance methods
###############################
- def do_callback(*args)
+ def do_callback
@in_callback = true
begin
- ret = @current_proc.call(*args)
+ @return_value = @current_proc.call(self)
rescue StandardError, NameError
if @cancel_on_exception
cancel
@@ -48,21 +47,22 @@ class TkAfter
end
end
if @set_next
- set_next_callback(*args)
+ set_next_callback(@current_args)
else
@set_next = true
end
@in_callback = false
- ret
+ @return_value
end
def set_callback(sleep, args=nil)
- @after_script = "rb_after #{@id} #{_get_eval_string(args)}"
+ @after_script = "rb_after #{@id}"
@after_id = tk_call('after', sleep, @after_script)
+ @current_args = args
@current_script = [sleep, @after_script]
end
- def set_next_callback(*args)
+ def set_next_callback(args)
if @running == false || @proc_max == 0 || @do_loop == 0
Tk_CBTBL[@id] = nil ;# for GC
@running = false
@@ -81,7 +81,7 @@ class TkAfter
@current_args = args
if @sleep_time.kind_of? Proc
- sleep = @sleep_time.call(*args)
+ sleep = @sleep_time.call(self)
else
sleep = @sleep_time
end
@@ -91,15 +91,7 @@ class TkAfter
@current_pos += 1
@current_proc = cmd
- if cmd_args[0].kind_of? Proc
- #c = cmd_args.shift
- #cb_args = c.call(*(cmd_args + args))
- cb_args = cmd_args[0].call(*args)
- else
- cb_args = cmd_args
- end
-
- set_callback(sleep, cb_args)
+ set_callback(sleep, cmd_args)
end
def initialize(*args)
@@ -115,6 +107,7 @@ class TkAfter
@current_script = []
@current_proc = nil
@current_args = nil
+ @return_value = nil
@sleep_time = 0
@current_sleep = 0
@@ -137,7 +130,10 @@ class TkAfter
attr :after_id
attr :after_script
attr :current_proc
+ attr :current_args
attr :current_sleep
+ alias :current_interval :current_sleep
+ attr :return_value
attr_accessor :loop_exec
@@ -257,7 +253,7 @@ class TkAfter
set_callback(sleep, @init_args)
@set_next = false if @in_callback
else
- set_next_callback(*@init_args)
+ set_next_callback(@init_args)
end
self
diff --git a/ext/tk/lib/tkcanvas.rb b/ext/tk/lib/tkcanvas.rb
index 94376072d33..ac6ed5362ff 100644
--- a/ext/tk/lib/tkcanvas.rb
+++ b/ext/tk/lib/tkcanvas.rb
@@ -1,4 +1,4 @@
-
+#
# tkcanvas.rb - Tk canvas classes
# $Date$
# by Yukihiro Matsumoto <matz@caelum.co.jp>
@@ -180,7 +180,7 @@ class TkCanvas<TkWindow
end
def itemcget(tagOrId, option)
- case option
+ case option.to_s
when 'dash', 'activedash', 'disableddash'
conf = tk_send('itemcget', tagid(tagOrId), "-#{option}")
if conf =~ /^[0-9]/
@@ -197,6 +197,7 @@ class TkCanvas<TkWindow
def itemconfigure(tagOrId, key, value=None)
if key.kind_of? Hash
+ key = _symbolkey2str(key)
if ( key['font'] || key['kanjifont'] \
|| key['latinfont'] || key['asciifont'] )
tagfont_configure(tagOrId, key.dup)
@@ -205,8 +206,10 @@ class TkCanvas<TkWindow
end
else
- if ( key == 'font' || key == 'kanjifont' \
- || key == 'latinfont' || key == 'asciifont' )
+ if ( key == 'font' || key == :font ||
+ key == 'kanjifont' || key == :kanjifont ||
+ key == 'latinfont' || key == :latinfont ||
+ key == 'asciifont' || key == :asciifont )
tagfont_configure(tagid(tagOrId), {key=>value})
else
tk_send 'itemconfigure', tagid(tagOrId), "-#{key}", value
@@ -226,7 +229,7 @@ class TkCanvas<TkWindow
def itemconfiginfo(tagOrId, key=nil)
if key
- case key
+ case key.to_s
when 'dash', 'activedash', 'disableddash'
conf = tk_split_simplelist(tk_send 'itemconfigure',
tagid(tagOrId), "-#{key}")
@@ -433,7 +436,7 @@ module TkcTagAccess
@c.itemtype @id
end
- # Followings operators supports logical expressions of canvas tags
+ # Following operators support logical expressions of canvas tags
# (for Tk8.3+).
# If tag1.path is 't1' and tag2.path is 't2', then
# ltag = tag1 & tag2; ltag.path => "(t1)&&(t2)"
@@ -473,6 +476,7 @@ class TkcTag<TkObject
include TkcTagAccess
CTagID_TBL = {}
+ Tk_CanvasTag_ID = ['ctag0000']
def TkcTag.id2obj(canvas, id)
cpath = canvas.path
@@ -480,7 +484,6 @@ class TkcTag<TkObject
CTagID_TBL[cpath][id]? CTagID_TBL[cpath][id]: id
end
- Tk_CanvasTag_ID = ['ctag0000']
def initialize(parent, mode=nil, *args)
if not parent.kind_of?(TkCanvas)
fail format("%s need to be TkCanvas", parent.inspect)
@@ -501,7 +504,7 @@ class TkcTag<TkObject
def delete
@c.delete @id
- CTagID_TBL[@path][@id] = nil if CTagID_TBL[@path]
+ CTagID_TBL[@cpath][@id] = nil if CTagID_TBL[@cpath]
end
alias remove delete
alias destroy delete
@@ -565,6 +568,7 @@ class TkcTagString<TkcTag
end
end
end
+TkcNamedTag = TkcTagString
class TkcTagAll<TkcTag
def initialize(parent)
@@ -643,9 +647,16 @@ class TkcItem<TkObject
@parent = @c = parent
@path = parent.path
fontkeys = {}
+ if args.size == 1 && args[0].kind_of?(Hash)
+ args[0] = _symbolkey2str(args[0])
+ coords = args[0].delete('coords')
+ if not coords.kind_of?(Array)
+ fail "coords parameter must be given by an Array"
+ end
+ args[0,0] = coords.flatten
+ end
if args[-1].kind_of? Hash
- args = args.dup
- keys = args.pop
+ keys = _symbolkey2str(args.pop)
['font', 'kanjifont', 'latinfont', 'asciifont'].each{|key|
fontkeys[key] = keys.delete(key) if keys.key?(key)
}
@@ -797,7 +808,7 @@ class TkPhotoImage<TkImage
end
def cget(option)
- case option
+ case option.to_s
when 'data', 'file'
tk_send 'cget', option
else
diff --git a/ext/tk/lib/tkclass.rb b/ext/tk/lib/tkclass.rb
index 0b33d4ec8b8..9ea275e560a 100644
--- a/ext/tk/lib/tkclass.rb
+++ b/ext/tk/lib/tkclass.rb
@@ -1,7 +1,9 @@
#
# tkclass.rb - Tk classes
-# $Date$
+# Date: 2000/11/27 09:23:36
# by Yukihiro Matsumoto <matz@caelum.co.jp>
+#
+# $Id$
require "tk"
@@ -13,6 +15,7 @@ Radiobutton = TkRadioButton
Checkbutton = TkCheckButton
Message = TkMessage
Entry = TkEntry
+Spinbox = TkSpinbox
Text = TkText
Scale = TkScale
Scrollbar = TkScrollbar
@@ -28,10 +31,16 @@ Polygon = TkcPolygon
Rectangle = TkcRectangle
TextItem = TkcText
WindowItem = TkcWindow
+BitmapImage = TkBitmapImage
+PhotoImage = TkPhotoImage
Selection = TkSelection
Winfo = TkWinfo
Pack = TkPack
+Grid = TkGrid
+Place = TkPlace
Variable = TkVariable
+Font = TkFont
+VirtualEvent = TkVirtualEvent
def Mainloop
Tk.mainloop
diff --git a/ext/tk/lib/tkdialog.rb b/ext/tk/lib/tkdialog.rb
index 1133db6ae9f..8b8ee691281 100644
--- a/ext/tk/lib/tkdialog.rb
+++ b/ext/tk/lib/tkdialog.rb
@@ -23,6 +23,7 @@ class TkDialog < TkWindow
@button_configs = proc{|num| button_configs num}
if keys.kind_of? Hash
+ keys = _symbolkey2str(keys)
@title = keys['title'] if keys['title']
@message = keys['message'] if keys['message']
@bitmap = keys['bitmap'] if keys['bitmap']
diff --git a/ext/tk/lib/tkentry.rb b/ext/tk/lib/tkentry.rb
index f301bbdaced..f2706125cba 100644
--- a/ext/tk/lib/tkentry.rb
+++ b/ext/tk/lib/tkentry.rb
@@ -73,6 +73,7 @@ class TkEntry<TkLabel
def configure(slot, value=None)
if slot.kind_of? Hash
+ slot = _symbolkey2str(slot)
if slot['vcmd'].kind_of? Array
cmd, *args = slot['vcmd']
slot['vcmd'] = ValidateCmd.new(cmd, args.join(' '))
@@ -99,8 +100,10 @@ class TkEntry<TkLabel
end
super(slot)
else
- if (slot == 'vcmd' || slot == 'validatecommand' ||
- slot == 'invcmd' || slot == 'invalidcommand')
+ if (slot == 'vcmd' || slot == :vcmd ||
+ slot == 'validatecommand' || slot == :validatecommand ||
+ slot == 'invcmd' || slot == :invcmd ||
+ slot == 'invalidcommand' !! slot == :invalidcommand)
if value.kind_of? Array
cmd, *args = value
value = ValidateCmd.new(cmd, args.join(' '))
diff --git a/ext/tk/lib/tkfont.rb b/ext/tk/lib/tkfont.rb
index c84d0960ede..c56a8df5066 100644
--- a/ext/tk/lib/tkfont.rb
+++ b/ext/tk/lib/tkfont.rb
@@ -173,16 +173,18 @@ class TkFont
TkFont.new(nil, nil).call_font_configure(path, *(args + [{}]))
else
begin
- compound = Hash[*tk_split_simplelist(tk_call('font', 'configure',
+ compound = tk_split_simplelist(
+ Hash[*tk_split_simplelist(tk_call('font', 'configure',
fnt))].collect{|key,value|
- [key[1..-1], value]
- }.assoc('compound')[1]
+ [key[1..-1], value]
+ }.assoc('compound')[1])
rescue
compound = []
end
if compound == []
- TkFont.new(fnt, DEFAULT_KANJI_FONT_NAME) \
- .call_font_configure(path, *(args + [{}]))
+ #TkFont.new(fnt, DEFAULT_KANJI_FONT_NAME) \
+ #.call_font_configure(path, *(args + [{}]))
+ TkFont.new(fnt).call_font_configure(path, *(args + [{}]))
else
TkFont.new(compound[0], compound[1]) \
.call_font_configure(path, *(args + [{}]))
@@ -220,6 +222,7 @@ class TkFont
end
def _get_font_info_from_hash(font)
+ font = _symbolkey2str(font)
foundry = (info = font['foundry'] .to_s)? info: '*'
family = (info = font['family'] .to_s)? info: '*'
weight = (info = font['weight'] .to_s)? info: '*'
@@ -353,7 +356,7 @@ class TkFont
if JAPANIZED_TK
if font.kind_of? Hash
- if font['charset']
+ if font[:charset] || font['charset']
tk_call('font', 'create', @latinfont, *hash_kv(font))
else
tk_call('font', 'create', @latinfont,
@@ -398,7 +401,7 @@ class TkFont
if JAPANIZED_TK
if font.kind_of? Hash
- if font['charset']
+ if font[:charset] || font['charset']
tk_call('font', 'create', @kanjifont, *hash_kv(font))
else
tk_call('font', 'create', @kanjifont,
diff --git a/ext/tk/lib/tkmenubar.rb b/ext/tk/lib/tkmenubar.rb
index 441f3f5c032..0d29571eb73 100644
--- a/ext/tk/lib/tkmenubar.rb
+++ b/ext/tk/lib/tkmenubar.rb
@@ -66,8 +66,14 @@ class TkMenubar<TkFrame
include TkComposite
def initialize(parent = nil, spec = nil, options = nil)
- super(parent, options)
-
+ if parent.kind_of? Hash
+ options = _symbolkey2str(parent)
+ spec = options.delete('spec')
+ super(options)
+ else
+ super(parent, options)
+ end
+
@menus = []
if spec
diff --git a/ext/tk/lib/tktext.rb b/ext/tk/lib/tktext.rb
index 75b28d8477d..9eb70dcd61d 100644
--- a/ext/tk/lib/tktext.rb
+++ b/ext/tk/lib/tktext.rb
@@ -185,7 +185,7 @@ class TkText<TkTextWin
end
def tag_cget(tag, key)
- case key
+ case key.to_s
when 'text', 'label', 'show', 'data', 'file'
tk_call @path, 'tag', 'cget', tag, "-#{key}"
else
@@ -195,16 +195,19 @@ class TkText<TkTextWin
def tag_configure(tag, key, val=None)
if key.kind_of? Hash
+ key = _symbolkey2str(key)
if ( key['font'] || key['kanjifont'] \
|| key['latinfont'] || key['asciifont'] )
- tagfont_configure(tag, key.dup)
+ tagfont_configure(tag, key)
else
tk_send 'tag', 'configure', tag, *hash_kv(key)
end
else
- if key == 'font' || key == 'kanjifont' ||
- key == 'latinfont' || key == 'asciifont'
+ if key == 'font' || key == :font ||
+ key == 'kanjifont' || key == :kanjifont ||
+ key == 'latinfont' || key == :latinfont ||
+ key == 'asciifont' || key == :asciifont
tagfont_configure(tag, {key=>val})
else
tk_send 'tag', 'configure', tag, "-#{key}", val
@@ -214,7 +217,7 @@ class TkText<TkTextWin
def tag_configinfo(tag, key=nil)
if key
- case key
+ case key.to_s
when 'text', 'label', 'show', 'data', 'file'
conf = tk_split_simplelist(tk_send('tag','configure',tag,"-#{key}"))
else
@@ -549,14 +552,25 @@ end
class TkTextTag<TkObject
include TkTreatTagFont
+ TTagID_TBL = {}
Tk_TextTag_ID = ['tag0000']
+ def TkTextTag.id2obj(text, id)
+ tpath = text.path
+ return id unless TTagID_TBL[tpath]
+ TTagID_TBL[tpath][id]? TTagID_TBL[tpath][id]: id
+ end
+
def initialize(parent, *args)
if not parent.kind_of?(TkText)
fail format("%s need to be TkText", parent.inspect)
end
@parent = @t = parent
+ @tpath = parent.path
@path = @id = Tk_TextTag_ID[0]
+ TTagID_TBL[@id] = self
+ TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath]
+ TTagID_TBL[@tpath][@id] = self
Tk_TextTag_ID[0] = Tk_TextTag_ID[0].succ
#tk_call @t.path, "tag", "configure", @id, *hash_kv(keys)
if args != [] then
@@ -618,7 +632,7 @@ class TkTextTag<TkObject
end
def cget(key)
- case key
+ case key.to_s
when 'text', 'label', 'show', 'data', 'file'
tk_call @t.path, 'tag', 'cget', @id, "-#{key}"
else
@@ -671,6 +685,31 @@ class TkTextTag<TkObject
def destroy
tk_call @t.path, 'tag', 'delete', @id
+ TTagID_TBL[@tpath][@id] = nil if CTagID_TBL[@tpath]
+ end
+end
+
+class TkTextNamedTag<TkTextTag
+ def self.new(parent, name, *args)
+ if TTagID_TBL[parent.path] && TTagID_TBL[parent.path][name]
+ return TTagID_TBL[parent.path][name]
+ else
+ super(parent, name, *args)
+ end
+ end
+
+ def initialize(parent, name, *args)
+ if not parent.kind_of?(TkText)
+ fail format("%s need to be TkText", parent.inspect)
+ end
+ @t = parent
+ @tpath = parent.path
+ @path = @id = name
+ TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath]
+ TTagID_TBL[@tpath][@id] = self
+ if mode
+ tk_call @t.path, "addtag", @id, *args
+ end
end
end
@@ -792,6 +831,7 @@ class TkTextWindow<TkObject
end
@path.gravity = 'left'
@index = @path.path
+ keys = _symbolkey2str(keys)
@id = keys['window']
if keys['create']
@p_create = keys['create']
@@ -810,7 +850,7 @@ class TkTextWindow<TkObject
end
def cget(slot)
- case slot
+ case slot.to_s
when 'text', 'label', 'show', 'data', 'file'
tk_call @t.path, 'window', 'cget', @index, "-#{slot}"
else
@@ -820,6 +860,7 @@ class TkTextWindow<TkObject
def configure(slot, value=None)
if slot.kind_of? Hash
+ slot = _symbolkey2str(slot)
@id = slot['window'] if slot['window']
if slot['create']
self.create=value
@@ -829,8 +870,8 @@ class TkTextWindow<TkObject
tk_call @t.path, 'window', 'configure', @index, *hash_kv(slot)
end
else
- @id = value if slot == 'window'
- if slot == 'create'
+ @id = value if slot == 'window' || slot == :window
+ if slot == 'create' || slot == :create
self.create=value
else
tk_call @t.path, 'window', 'configure', @index, "-#{slot}", value
@@ -861,7 +902,7 @@ class TkTextWindow<TkObject
def configinfo(slot = nil)
if slot
- case slot
+ case slot.to_s
when 'text', 'label', 'show', 'data', 'file'
conf = tk_split_simplelist(tk_call @t.path, 'window', 'configure',
@index, "-#{slot}")
@@ -931,7 +972,7 @@ class TkTextImage<TkObject
end
def cget(slot)
- case slot
+ case slot.to_s
when 'text', 'label', 'show', 'data', 'file'
tk_call @t.path, 'image', 'cget', @index, "-#{slot}"
else
@@ -960,7 +1001,7 @@ class TkTextImage<TkObject
def configinfo(slot = nil)
if slot
- case slot
+ case slot.to_s
when 'text', 'label', 'show', 'data', 'file'
conf = tk_split_simplelist(tk_call @t.path, 'image', 'configure',
@index, "-#{slot}")