summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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}")