mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* 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
This commit is contained in:
parent
dc010ff515
commit
4cb164ee2a
10 changed files with 722 additions and 172 deletions
|
@ -48,20 +48,44 @@ int *tclDummyMathPtr = (int *) matherr;
|
||||||
/*---- module TclTkLib ----*/
|
/*---- module TclTkLib ----*/
|
||||||
|
|
||||||
struct invoke_queue {
|
struct invoke_queue {
|
||||||
|
Tcl_Event ev;
|
||||||
int argc;
|
int argc;
|
||||||
VALUE *argv;
|
VALUE *argv;
|
||||||
VALUE obj;
|
VALUE obj;
|
||||||
int done;
|
int done;
|
||||||
VALUE result;
|
int safe_level;
|
||||||
|
VALUE *result;
|
||||||
VALUE thread;
|
VALUE thread;
|
||||||
struct invoke_queue *next;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct invoke_queue *iqueue;
|
|
||||||
static VALUE main_thread;
|
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 */
|
/* Tk_ThreadTimer */
|
||||||
static Tcl_TimerToken timer_token;
|
static Tcl_TimerToken timer_token = (Tcl_TimerToken)NULL;
|
||||||
|
|
||||||
/* timer callback */
|
/* timer callback */
|
||||||
static void _timer_for_tcl _((ClientData));
|
static void _timer_for_tcl _((ClientData));
|
||||||
|
@ -73,44 +97,230 @@ _timer_for_tcl(clientData)
|
||||||
VALUE thread;
|
VALUE thread;
|
||||||
|
|
||||||
Tk_DeleteTimerHandler(timer_token);
|
Tk_DeleteTimerHandler(timer_token);
|
||||||
timer_token = Tk_CreateTimerHandler(100, _timer_for_tcl, (ClientData)0);
|
if (timer_tick > 0) {
|
||||||
|
timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl,
|
||||||
|
(ClientData)0);
|
||||||
|
} else {
|
||||||
|
timer_token = (Tcl_TimerToken)NULL;
|
||||||
|
}
|
||||||
|
|
||||||
CHECK_INTS;
|
/* rb_thread_schedule(); */
|
||||||
q = iqueue;
|
timer_tick += event_loop_max;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rb_thread_schedule();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TCL_MAJOR_VERSION >= 8
|
static VALUE
|
||||||
static int ip_ruby _((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST*));
|
set_eventloop_tick(self, tick)
|
||||||
#else
|
VALUE self;
|
||||||
static int ip_ruby _((ClientData, Tcl_Interp *, int, char **));
|
VALUE tick;
|
||||||
#endif
|
{
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
return Qnil;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 */
|
/* execute Tk_MainLoop */
|
||||||
static VALUE
|
static VALUE
|
||||||
lib_mainloop(self)
|
lib_mainloop(argc, argv, self)
|
||||||
|
int argc;
|
||||||
|
VALUE *argv;
|
||||||
VALUE self;
|
VALUE self;
|
||||||
{
|
{
|
||||||
timer_token = Tk_CreateTimerHandler(100, _timer_for_tcl, (ClientData)0);
|
VALUE check_rootwidget;
|
||||||
DUMP1("start Tk_Mainloop");
|
|
||||||
Tk_MainLoop();
|
if (rb_scan_args(argc, argv, "01", &check_rootwidget) == 0) {
|
||||||
DUMP1("stop Tk_Mainloop");
|
check_rootwidget = Qtrue;
|
||||||
Tk_DeleteTimerHandler(timer_token);
|
} 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;
|
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 ----*/
|
/*---- class TclTkIp ----*/
|
||||||
struct tcltkip {
|
struct tcltkip {
|
||||||
Tcl_Interp *ip; /* the interpreter */
|
Tcl_Interp *ip; /* the interpreter */
|
||||||
|
@ -245,6 +455,7 @@ ip_new(self)
|
||||||
/* from Tk_Main() */
|
/* from Tk_Main() */
|
||||||
DUMP1("Tcl_CreateInterp");
|
DUMP1("Tcl_CreateInterp");
|
||||||
ptr->ip = Tcl_CreateInterp();
|
ptr->ip = Tcl_CreateInterp();
|
||||||
|
current_interp = ptr->ip;
|
||||||
|
|
||||||
/* from Tcl_AppInit() */
|
/* from Tcl_AppInit() */
|
||||||
DUMP1("Tcl_Init");
|
DUMP1("Tcl_Init");
|
||||||
|
@ -459,48 +670,103 @@ ip_invoke_real(argc, argv, obj)
|
||||||
return rb_str_new2(ptr->ip->result);
|
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
|
static VALUE
|
||||||
ip_invoke(argc, argv, obj)
|
ip_invoke(argc, argv, obj)
|
||||||
int argc;
|
int argc;
|
||||||
VALUE *argv;
|
VALUE *argv;
|
||||||
VALUE obj;
|
VALUE obj;
|
||||||
{
|
{
|
||||||
struct invoke_queue *tmp, *p;
|
struct invoke_queue *tmp;
|
||||||
VALUE result = rb_thread_current();
|
VALUE current = rb_thread_current();
|
||||||
|
VALUE result;
|
||||||
|
VALUE *alloc_argv, *alloc_result;
|
||||||
|
Tcl_QueuePosition position;
|
||||||
|
|
||||||
if (result == main_thread) {
|
if (eventloop_thread == 0 || current == eventloop_thread) {
|
||||||
|
DUMP2("invoke from current eventloop %lx", current);
|
||||||
return ip_invoke_real(argc, argv, obj);
|
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->obj = obj;
|
||||||
tmp->argc = argc;
|
tmp->argc = argc;
|
||||||
tmp->argv = ALLOC_N(VALUE, argc);
|
tmp->argv = alloc_argv;
|
||||||
MEMCPY(tmp->argv, argv, VALUE, argc);
|
tmp->result = alloc_result;
|
||||||
tmp->thread = result;
|
tmp->thread = current;
|
||||||
tmp->done = 0;
|
tmp->safe_level = rb_safe_level();
|
||||||
|
tmp->ev.proc = invoke_queue_handler;
|
||||||
|
position = TCL_QUEUE_TAIL;
|
||||||
|
|
||||||
tmp->next = iqueue;
|
/* add the handler to Tcl event queue */
|
||||||
iqueue = tmp;
|
Tcl_QueueEvent(&tmp->ev, position);
|
||||||
|
|
||||||
|
/* wait for the handler to be processed */
|
||||||
rb_thread_stop();
|
rb_thread_stop();
|
||||||
result = tmp->result;
|
|
||||||
if (iqueue == tmp) {
|
|
||||||
iqueue = tmp->next;
|
|
||||||
free(tmp->argv);
|
|
||||||
free(tmp);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = iqueue;
|
/* get result & free allocated memory */
|
||||||
while (p->next) {
|
result = *alloc_result;
|
||||||
if (p->next == tmp) {
|
free(alloc_argv);
|
||||||
p->next = tmp->next;
|
free(alloc_result);
|
||||||
free(tmp->argv);
|
|
||||||
free(tmp);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
p = p->next;
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -533,6 +799,14 @@ Init_tcltklib()
|
||||||
VALUE lib = rb_define_module("TclTkLib");
|
VALUE lib = rb_define_module("TclTkLib");
|
||||||
VALUE ip = rb_define_class("TclTkIp", rb_cObject);
|
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
|
#if defined USE_TCL_STUBS && defined USE_TK_STUBS
|
||||||
extern int ruby_tcltk_stubs();
|
extern int ruby_tcltk_stubs();
|
||||||
int ret = ruby_tcltk_stubs();
|
int ret = ruby_tcltk_stubs();
|
||||||
|
@ -543,7 +817,16 @@ Init_tcltklib()
|
||||||
eTkCallbackBreak = rb_define_class("TkCallbackBreak", rb_eStandardError);
|
eTkCallbackBreak = rb_define_class("TkCallbackBreak", rb_eStandardError);
|
||||||
eTkCallbackContinue = rb_define_class("TkCallbackContinue",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_singleton_method(ip, "new", ip_new, 0);
|
||||||
rb_define_method(ip, "_eval", ip_eval, 1);
|
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, "_fromUTF8",ip_fromUTF8,2);
|
||||||
rb_define_method(ip, "_invoke", ip_invoke, -1);
|
rb_define_method(ip, "_invoke", ip_invoke, -1);
|
||||||
rb_define_method(ip, "_return_value", ip_retval, 0);
|
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);
|
rb_define_method(ip, "restart", lib_restart, 0);
|
||||||
|
|
||||||
main_thread = rb_thread_current();
|
main_thread = rb_thread_current();
|
||||||
|
eventloop_thread = 0;
|
||||||
|
watchdog_thread = 0;
|
||||||
|
|
||||||
#ifdef __MACOS__
|
#ifdef __MACOS__
|
||||||
_macinit();
|
_macinit();
|
||||||
#endif
|
#endif
|
||||||
|
|
276
ext/tk/lib/tk.rb
276
ext/tk/lib/tk.rb
|
@ -132,6 +132,13 @@ module TkComm
|
||||||
end
|
end
|
||||||
private :tk_tcl2ruby, :tk_split_list, :tk_split_simplelist
|
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)
|
def hash_kv(keys)
|
||||||
conf = []
|
conf = []
|
||||||
if keys and keys != None
|
if keys and keys != None
|
||||||
|
@ -204,6 +211,8 @@ module TkComm
|
||||||
return nil if str == None
|
return nil if str == None
|
||||||
if str.kind_of?(String)
|
if str.kind_of?(String)
|
||||||
# do nothing
|
# do nothing
|
||||||
|
elsif str.kind_of?(Symbol)
|
||||||
|
str = str.id2name
|
||||||
elsif str.kind_of?(Hash)
|
elsif str.kind_of?(Hash)
|
||||||
str = hash_kv(str).join(" ")
|
str = hash_kv(str).join(" ")
|
||||||
elsif str.kind_of?(Array)
|
elsif str.kind_of?(Array)
|
||||||
|
@ -259,13 +268,15 @@ module TkComm
|
||||||
end
|
end
|
||||||
private :install_cmd, :uninstall_cmd
|
private :install_cmd, :uninstall_cmd
|
||||||
|
|
||||||
def install_win(ppath)
|
def install_win(ppath,name=nil)
|
||||||
id = format("w%.4d", Tk_IDs[1])
|
if !name or name == ''
|
||||||
|
name = format("w%.4d", Tk_IDs[1])
|
||||||
Tk_IDs[1] += 1
|
Tk_IDs[1] += 1
|
||||||
|
end
|
||||||
if !ppath or ppath == "."
|
if !ppath or ppath == "."
|
||||||
@path = format(".%s", id);
|
@path = format(".%s", name);
|
||||||
else
|
else
|
||||||
@path = format("%s.%s", ppath, id)
|
@path = format("%s.%s", ppath, name)
|
||||||
end
|
end
|
||||||
Tk_WINDOWS[@path] = self
|
Tk_WINDOWS[@path] = self
|
||||||
end
|
end
|
||||||
|
@ -483,6 +494,8 @@ module TkCore
|
||||||
}
|
}
|
||||||
EOL
|
EOL
|
||||||
|
|
||||||
|
EventFlag = TclTkLib::EventFlag
|
||||||
|
|
||||||
def callback_break
|
def callback_break
|
||||||
fail TkCallbackBreak, "Tk callback returns 'break' status"
|
fail TkCallbackBreak, "Tk callback returns 'break' status"
|
||||||
end
|
end
|
||||||
|
@ -616,12 +629,42 @@ module TkCore
|
||||||
tk_call('info', *args)
|
tk_call('info', *args)
|
||||||
end
|
end
|
||||||
|
|
||||||
def mainloop
|
def mainloop(check_root = true)
|
||||||
TclTkLib.mainloop
|
TclTkLib.mainloop(check_root)
|
||||||
end
|
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
|
TkCore::INTERP.restart
|
||||||
|
TkComm::Tk_CMDTBL.clear
|
||||||
TkComm::Tk_WINDOWS.clear
|
TkComm::Tk_WINDOWS.clear
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
@ -2077,12 +2120,87 @@ module TkOption
|
||||||
tk_call 'option', 'clear'
|
tk_call 'option', 'clear'
|
||||||
end
|
end
|
||||||
def get win, name, klass
|
def get win, name, klass
|
||||||
tk_call 'option', 'get', win ,name, klass
|
tk_call('option', 'get', win ,name, klass).taint
|
||||||
end
|
end
|
||||||
def readfile file, pri=None
|
def readfile file, pri=None
|
||||||
tk_call 'option', 'readfile', file, pri
|
tk_call 'option', 'readfile', file, pri
|
||||||
end
|
end
|
||||||
module_function :add, :clear, :get, :readfile
|
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
|
end
|
||||||
|
|
||||||
module TkTreatFont
|
module TkTreatFont
|
||||||
|
@ -2096,6 +2214,7 @@ module TkTreatFont
|
||||||
alias fontobj font_configinfo
|
alias fontobj font_configinfo
|
||||||
|
|
||||||
def font_configure(slot)
|
def font_configure(slot)
|
||||||
|
slot = _symbolkey2str(slot)
|
||||||
if (fnt = slot.delete('font'))
|
if (fnt = slot.delete('font'))
|
||||||
if fnt.kind_of? TkFont
|
if fnt.kind_of? TkFont
|
||||||
return fnt.call_font_configure(self.path, self.path,'configure',slot)
|
return fnt.call_font_configure(self.path, self.path,'configure',slot)
|
||||||
|
@ -2203,6 +2322,7 @@ module TkTreatItemFont
|
||||||
|
|
||||||
def tagfont_configure(tagOrId, slot)
|
def tagfont_configure(tagOrId, slot)
|
||||||
pathname = __item_pathname(tagOrId)
|
pathname = __item_pathname(tagOrId)
|
||||||
|
slot = _symbolkey2str(slot)
|
||||||
if (fnt = slot.delete('font'))
|
if (fnt = slot.delete('font'))
|
||||||
if fnt.kind_of? TkFont
|
if fnt.kind_of? TkFont
|
||||||
return fnt.call_font_configure(pathname, self.path,
|
return fnt.call_font_configure(pathname, self.path,
|
||||||
|
@ -2345,7 +2465,7 @@ class TkObject<TkKernel
|
||||||
end
|
end
|
||||||
|
|
||||||
def cget(slot)
|
def cget(slot)
|
||||||
case slot
|
case slot.to_s
|
||||||
when 'text', 'label', 'show', 'data', 'file'
|
when 'text', 'label', 'show', 'data', 'file'
|
||||||
tk_call path, 'cget', "-#{slot}"
|
tk_call path, 'cget', "-#{slot}"
|
||||||
else
|
else
|
||||||
|
@ -2355,16 +2475,20 @@ class TkObject<TkKernel
|
||||||
|
|
||||||
def configure(slot, value=None)
|
def configure(slot, value=None)
|
||||||
if slot.kind_of? Hash
|
if slot.kind_of? Hash
|
||||||
if (slot['font'] || slot['kanjifont'] ||
|
if (slot['font'] || slot[:font] ||
|
||||||
slot['latinfont'] || slot['asciifont'] )
|
slot['kanjifont'] || slot[:kanjifont] ||
|
||||||
font_configure(slot.dup)
|
slot['latinfont'] || slot[:latinfont] ||
|
||||||
|
slot['asciifont'] || slot[:asciifont] )
|
||||||
|
font_configure(slot)
|
||||||
else
|
else
|
||||||
tk_call path, 'configure', *hash_kv(slot)
|
tk_call path, 'configure', *hash_kv(slot)
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
if (slot == 'font' || slot == 'kanjifont' ||
|
if (slot == 'font' || slot == :font ||
|
||||||
slot == 'latinfont' || slot == 'asciifont')
|
slot == 'kanjifont' || slot == :kanjifont ||
|
||||||
|
slot == 'latinfont' || slot == :latinfont ||
|
||||||
|
slot == 'asciifont' || slot == :asciifont )
|
||||||
if value == None
|
if value == None
|
||||||
fontobj
|
fontobj
|
||||||
else
|
else
|
||||||
|
@ -2381,11 +2505,12 @@ class TkObject<TkKernel
|
||||||
end
|
end
|
||||||
|
|
||||||
def configinfo(slot = nil)
|
def configinfo(slot = nil)
|
||||||
if slot == 'font' || slot == 'kanjifont'
|
if slot == 'font' || slot == :font ||
|
||||||
|
slot == 'kanjifont' || slot == :kanjifont
|
||||||
fontobj
|
fontobj
|
||||||
else
|
else
|
||||||
if slot
|
if slot
|
||||||
case slot
|
case slot.to_s
|
||||||
when 'text', 'label', 'show', 'data', 'file'
|
when 'text', 'label', 'show', 'data', 'file'
|
||||||
conf = tk_split_simplelist(tk_send('configure', "-#{slot}") )
|
conf = tk_split_simplelist(tk_send('configure', "-#{slot}") )
|
||||||
else
|
else
|
||||||
|
@ -2455,7 +2580,19 @@ class TkWindow<TkObject
|
||||||
extend TkBindCore
|
extend TkBindCore
|
||||||
|
|
||||||
def initialize(parent=nil, keys=nil)
|
def initialize(parent=nil, keys=nil)
|
||||||
|
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)
|
install_win(if parent then parent.path end)
|
||||||
|
end
|
||||||
if self.method(:create_self).arity == 0
|
if self.method(:create_self).arity == 0
|
||||||
p 'create_self has no arg' if $DEBUG
|
p 'create_self has no arg' if $DEBUG
|
||||||
create_self
|
create_self
|
||||||
|
@ -2464,10 +2601,9 @@ class TkWindow<TkObject
|
||||||
configure(keys)
|
configure(keys)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
p 'create_self has an arg' if $DEBUG
|
p 'create_self has args' if $DEBUG
|
||||||
fontkeys = {}
|
fontkeys = {}
|
||||||
if keys
|
if keys
|
||||||
keys = keys.dup
|
|
||||||
['font', 'kanjifont', 'latinfont', 'asciifont'].each{|key|
|
['font', 'kanjifont', 'latinfont', 'asciifont'].each{|key|
|
||||||
fontkeys[key] = keys.delete(key) if keys.key?(key)
|
fontkeys[key] = keys.delete(key) if keys.key?(key)
|
||||||
}
|
}
|
||||||
|
@ -2668,17 +2804,17 @@ class TkWindow<TkObject
|
||||||
tk_call 'grab', 'set', path
|
tk_call 'grab', 'set', path
|
||||||
elsif args.length == 1
|
elsif args.length == 1
|
||||||
case args[0]
|
case args[0]
|
||||||
when 'global'
|
when 'global', :global
|
||||||
return(tk_call 'grab', 'set', '-global', path)
|
return(tk_call 'grab', 'set', '-global', path)
|
||||||
when 'release'
|
when 'release', :release
|
||||||
return(tk_call 'grab', 'release', path)
|
return(tk_call 'grab', 'release', path)
|
||||||
else
|
else
|
||||||
val = tk_call('grab', args[0], path)
|
val = tk_call('grab', args[0], path)
|
||||||
end
|
end
|
||||||
case args[0]
|
case args[0]
|
||||||
when 'current'
|
when 'current', :current
|
||||||
return window(val)
|
return window(val)
|
||||||
when 'status'
|
when 'status', :status
|
||||||
return val
|
return val
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
@ -2811,15 +2947,27 @@ class TkToplevel<TkWindow
|
||||||
#################
|
#################
|
||||||
|
|
||||||
def initialize(parent=nil, screen=nil, classname=nil, keys=nil)
|
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
|
if screen.kind_of? Hash
|
||||||
keys = screen
|
keys = _symbolkey2str(screen)
|
||||||
else
|
else
|
||||||
@screen = screen
|
@screen = screen
|
||||||
end
|
end
|
||||||
@classname = classname
|
@classname = classname
|
||||||
if keys.kind_of? Hash
|
if keys.kind_of? Hash
|
||||||
if keys.key?('classname')
|
keys = _symbolkey2str(keys)
|
||||||
keys = keys.dup
|
if keys.key?(:classname) || keys.key?('classname')
|
||||||
keys['class'] = keys.delete('classname')
|
keys['class'] = keys.delete('classname')
|
||||||
end
|
end
|
||||||
@classname = keys['class']
|
@classname = keys['class']
|
||||||
|
@ -2875,17 +3023,24 @@ class TkFrame<TkWindow
|
||||||
#################
|
#################
|
||||||
|
|
||||||
def initialize(parent=nil, keys=nil)
|
def initialize(parent=nil, keys=nil)
|
||||||
if keys.kind_of? Hash
|
if parent.kind_of? Hash
|
||||||
|
keys = _symbolkey2str(parent)
|
||||||
|
else
|
||||||
|
if keys
|
||||||
|
keys = _symbolkey2str(keys)
|
||||||
|
keys['parent'] = parent
|
||||||
|
else
|
||||||
|
keys = {'parent'=>parent}
|
||||||
|
end
|
||||||
|
end
|
||||||
if keys.key?('classname')
|
if keys.key?('classname')
|
||||||
keys = keys.dup
|
|
||||||
keys['class'] = keys.delete('classname')
|
keys['class'] = keys.delete('classname')
|
||||||
end
|
end
|
||||||
@classname = keys['class']
|
@classname = keys['class']
|
||||||
@colormap = keys['colormap']
|
@colormap = keys['colormap']
|
||||||
@container = keys['container']
|
@container = keys['container']
|
||||||
@visual = keys['visual']
|
@visual = keys['visual']
|
||||||
end
|
super(keys)
|
||||||
super(parent, keys)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_self(keys)
|
def create_self(keys)
|
||||||
|
@ -3170,7 +3325,7 @@ class TkListbox<TkTextWin
|
||||||
end
|
end
|
||||||
|
|
||||||
def itemcget(index, key)
|
def itemcget(index, key)
|
||||||
case key
|
case key.to_s
|
||||||
when 'text', 'label', 'show'
|
when 'text', 'label', 'show'
|
||||||
tk_send 'itemcget', index, "-#{key}"
|
tk_send 'itemcget', index, "-#{key}"
|
||||||
else
|
else
|
||||||
|
@ -3179,16 +3334,20 @@ class TkListbox<TkTextWin
|
||||||
end
|
end
|
||||||
def itemconfigure(index, key, val=None)
|
def itemconfigure(index, key, val=None)
|
||||||
if key.kind_of? Hash
|
if key.kind_of? Hash
|
||||||
if (key['font'] || key['kanjifont'] ||
|
if (key['font'] || key[:font] ||
|
||||||
key['latinfont'] || key['asciifont'])
|
key['kanjifont'] || key[:kanjifont] ||
|
||||||
tagfont_configure(index, key.dup)
|
key['latinfont'] || key[:latinfont] ||
|
||||||
|
key['asciifont'] || key[:asciifont] )
|
||||||
|
tagfont_configure(index, _symbolkey2str(key))
|
||||||
else
|
else
|
||||||
tk_send 'itemconfigure', index, *hash_kv(key)
|
tk_send 'itemconfigure', index, *hash_kv(key)
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
if (key == 'font' || key == 'kanjifont' ||
|
if (key == 'font' || key == :font ||
|
||||||
key == 'latinfont' || key == 'asciifont' )
|
key == 'kanjifont' || key == :kanjifont ||
|
||||||
|
key == 'latinfont' || key == :latinfont ||
|
||||||
|
key == 'asciifont' || key == :asciifont )
|
||||||
tagfont_configure(index, {key=>val})
|
tagfont_configure(index, {key=>val})
|
||||||
else
|
else
|
||||||
tk_call 'itemconfigure', index, "-#{key}", val
|
tk_call 'itemconfigure', index, "-#{key}", val
|
||||||
|
@ -3198,7 +3357,7 @@ class TkListbox<TkTextWin
|
||||||
|
|
||||||
def itemconfiginfo(index, key=nil)
|
def itemconfiginfo(index, key=nil)
|
||||||
if key
|
if key
|
||||||
case key
|
case key.to_s
|
||||||
when 'text', 'label', 'show'
|
when 'text', 'label', 'show'
|
||||||
conf = tk_split_simplelist(tk_send('itemconfigure',index,"-#{key}"))
|
conf = tk_split_simplelist(tk_send('itemconfigure',index,"-#{key}"))
|
||||||
else
|
else
|
||||||
|
@ -3305,7 +3464,7 @@ class TkMenu<TkWindow
|
||||||
number(tk_send('yposition', index))
|
number(tk_send('yposition', index))
|
||||||
end
|
end
|
||||||
def entrycget(index, key)
|
def entrycget(index, key)
|
||||||
case key
|
case key.to_s
|
||||||
when 'text', 'label', 'show'
|
when 'text', 'label', 'show'
|
||||||
tk_send 'entrycget', index, "-#{key}"
|
tk_send 'entrycget', index, "-#{key}"
|
||||||
else
|
else
|
||||||
|
@ -3314,16 +3473,20 @@ class TkMenu<TkWindow
|
||||||
end
|
end
|
||||||
def entryconfigure(index, key, val=None)
|
def entryconfigure(index, key, val=None)
|
||||||
if key.kind_of? Hash
|
if key.kind_of? Hash
|
||||||
if (key['font'] || key['kanjifont'] ||
|
if (key['font'] || key[:font] ||
|
||||||
key['latinfont'] || key['asciifont'])
|
key['kanjifont'] || key[:kanjifont] ||
|
||||||
tagfont_configure(index, key.dup)
|
key['latinfont'] || key[:latinfont] ||
|
||||||
|
key['asciifont'] || key[:asciifont])
|
||||||
|
tagfont_configure(index, _symbolkey2str(key))
|
||||||
else
|
else
|
||||||
tk_send 'entryconfigure', index, *hash_kv(key)
|
tk_send 'entryconfigure', index, *hash_kv(key)
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
if (key == 'font' || key == 'kanjifont' ||
|
if (key == 'font' || key == :font ||
|
||||||
key == 'latinfont' || key == 'asciifont' )
|
key == 'kanjifont' || key == :kanjifont ||
|
||||||
|
key == 'latinfont' || key == :latinfont ||
|
||||||
|
key == 'asciifont' || key == :asciifont )
|
||||||
tagfont_configure({key=>val})
|
tagfont_configure({key=>val})
|
||||||
else
|
else
|
||||||
tk_call 'entryconfigure', index, "-#{key}", val
|
tk_call 'entryconfigure', index, "-#{key}", val
|
||||||
|
@ -3333,7 +3496,7 @@ class TkMenu<TkWindow
|
||||||
|
|
||||||
def entryconfiginfo(index, key=nil)
|
def entryconfiginfo(index, key=nil)
|
||||||
if key
|
if key
|
||||||
case key
|
case key.to_s
|
||||||
when 'text', 'label', 'show'
|
when 'text', 'label', 'show'
|
||||||
conf = tk_split_simplelist(tk_send('entryconfigure',index,"-#{key}"))
|
conf = tk_split_simplelist(tk_send('entryconfigure',index,"-#{key}"))
|
||||||
else
|
else
|
||||||
|
@ -3371,17 +3534,28 @@ end
|
||||||
|
|
||||||
class TkMenuClone<TkMenu
|
class TkMenuClone<TkMenu
|
||||||
def initialize(parent, type=None)
|
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)
|
unless parent.kind_of?(TkMenu)
|
||||||
fail ArgumentError, "parent must be TkMenu"
|
fail ArgumentError, "parent must be TkMenu"
|
||||||
end
|
end
|
||||||
@parent = parent
|
@parent = parent
|
||||||
install_win(@parent.path)
|
install_win(@parent.path, widgetname)
|
||||||
tk_call @parent.path, 'clone', @path, type
|
tk_call @parent.path, 'clone', @path, type
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
module TkSystemMenu
|
module TkSystemMenu
|
||||||
def initialize(parent, keys=nil)
|
def initialize(parent, keys=nil)
|
||||||
|
if parent.kind_of? Hash
|
||||||
|
keys = _symbolkey2str(parent)
|
||||||
|
parent = keys.delete('parent')
|
||||||
|
end
|
||||||
fail unless parent.kind_of? TkMenu
|
fail unless parent.kind_of? TkMenu
|
||||||
@path = format("%s.%s", parent.path, self.type::SYSMENU_NAME)
|
@path = format("%s.%s", parent.path, self.type::SYSMENU_NAME)
|
||||||
TkComm::Tk_WINDOWS[@path] = self
|
TkComm::Tk_WINDOWS[@path] = self
|
||||||
|
@ -3437,6 +3611,12 @@ class TkOptionMenubutton<TkMenubutton
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize(parent=nil, var=TkVariable.new, firstval=nil, *vals)
|
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
|
fail unless var.kind_of? TkVariable
|
||||||
@variable = var
|
@variable = var
|
||||||
firstval = @variable.value unless firstval
|
firstval = @variable.value unless firstval
|
||||||
|
@ -3498,10 +3678,18 @@ module TkComposite
|
||||||
extend Tk
|
extend Tk
|
||||||
|
|
||||||
def initialize(parent=nil, *args)
|
def initialize(parent=nil, *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)
|
@frame = TkFrame.new(parent)
|
||||||
@path = @epath = @frame.path
|
@path = @epath = @frame.path
|
||||||
initialize_composite(*args)
|
initialize_composite(*args)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def epath
|
def epath
|
||||||
@epath
|
@epath
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#
|
#
|
||||||
# tkafter.rb : methods for Tcl/Tk after command
|
# tkafter.rb : methods for Tcl/Tk after command
|
||||||
# 2000/08/01 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
|
#
|
||||||
|
# $Id$
|
||||||
#
|
#
|
||||||
require 'tk'
|
require 'tk'
|
||||||
|
|
||||||
|
@ -11,18 +12,16 @@ class TkAfter
|
||||||
Tk_CBID = [0]
|
Tk_CBID = [0]
|
||||||
Tk_CBTBL = {}
|
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
|
# class methods
|
||||||
###############################
|
###############################
|
||||||
def TkAfter.callback(arg)
|
def TkAfter.callback(obj_id)
|
||||||
@after_id = nil
|
@after_id = nil
|
||||||
arg = Array(tk_split_list(arg))
|
|
||||||
obj_id = arg.shift
|
|
||||||
ex_obj = Tk_CBTBL[obj_id]
|
ex_obj = Tk_CBTBL[obj_id]
|
||||||
return nil if ex_obj == nil; # canceled
|
return nil if ex_obj == nil; # canceled
|
||||||
_get_eval_string(ex_obj.do_callback(*arg))
|
_get_eval_string(ex_obj.do_callback)
|
||||||
end
|
end
|
||||||
|
|
||||||
def TkAfter.info
|
def TkAfter.info
|
||||||
|
@ -35,10 +34,10 @@ class TkAfter
|
||||||
###############################
|
###############################
|
||||||
# instance methods
|
# instance methods
|
||||||
###############################
|
###############################
|
||||||
def do_callback(*args)
|
def do_callback
|
||||||
@in_callback = true
|
@in_callback = true
|
||||||
begin
|
begin
|
||||||
ret = @current_proc.call(*args)
|
@return_value = @current_proc.call(self)
|
||||||
rescue StandardError, NameError
|
rescue StandardError, NameError
|
||||||
if @cancel_on_exception
|
if @cancel_on_exception
|
||||||
cancel
|
cancel
|
||||||
|
@ -48,21 +47,22 @@ class TkAfter
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if @set_next
|
if @set_next
|
||||||
set_next_callback(*args)
|
set_next_callback(@current_args)
|
||||||
else
|
else
|
||||||
@set_next = true
|
@set_next = true
|
||||||
end
|
end
|
||||||
@in_callback = false
|
@in_callback = false
|
||||||
ret
|
@return_value
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_callback(sleep, args=nil)
|
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)
|
@after_id = tk_call('after', sleep, @after_script)
|
||||||
|
@current_args = args
|
||||||
@current_script = [sleep, @after_script]
|
@current_script = [sleep, @after_script]
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_next_callback(*args)
|
def set_next_callback(args)
|
||||||
if @running == false || @proc_max == 0 || @do_loop == 0
|
if @running == false || @proc_max == 0 || @do_loop == 0
|
||||||
Tk_CBTBL[@id] = nil ;# for GC
|
Tk_CBTBL[@id] = nil ;# for GC
|
||||||
@running = false
|
@running = false
|
||||||
|
@ -81,7 +81,7 @@ class TkAfter
|
||||||
@current_args = args
|
@current_args = args
|
||||||
|
|
||||||
if @sleep_time.kind_of? Proc
|
if @sleep_time.kind_of? Proc
|
||||||
sleep = @sleep_time.call(*args)
|
sleep = @sleep_time.call(self)
|
||||||
else
|
else
|
||||||
sleep = @sleep_time
|
sleep = @sleep_time
|
||||||
end
|
end
|
||||||
|
@ -91,15 +91,7 @@ class TkAfter
|
||||||
@current_pos += 1
|
@current_pos += 1
|
||||||
@current_proc = cmd
|
@current_proc = cmd
|
||||||
|
|
||||||
if cmd_args[0].kind_of? Proc
|
set_callback(sleep, cmd_args)
|
||||||
#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)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize(*args)
|
def initialize(*args)
|
||||||
|
@ -115,6 +107,7 @@ class TkAfter
|
||||||
@current_script = []
|
@current_script = []
|
||||||
@current_proc = nil
|
@current_proc = nil
|
||||||
@current_args = nil
|
@current_args = nil
|
||||||
|
@return_value = nil
|
||||||
|
|
||||||
@sleep_time = 0
|
@sleep_time = 0
|
||||||
@current_sleep = 0
|
@current_sleep = 0
|
||||||
|
@ -137,7 +130,10 @@ class TkAfter
|
||||||
attr :after_id
|
attr :after_id
|
||||||
attr :after_script
|
attr :after_script
|
||||||
attr :current_proc
|
attr :current_proc
|
||||||
|
attr :current_args
|
||||||
attr :current_sleep
|
attr :current_sleep
|
||||||
|
alias :current_interval :current_sleep
|
||||||
|
attr :return_value
|
||||||
|
|
||||||
attr_accessor :loop_exec
|
attr_accessor :loop_exec
|
||||||
|
|
||||||
|
@ -257,7 +253,7 @@ class TkAfter
|
||||||
set_callback(sleep, @init_args)
|
set_callback(sleep, @init_args)
|
||||||
@set_next = false if @in_callback
|
@set_next = false if @in_callback
|
||||||
else
|
else
|
||||||
set_next_callback(*@init_args)
|
set_next_callback(@init_args)
|
||||||
end
|
end
|
||||||
|
|
||||||
self
|
self
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
|
#
|
||||||
# tkcanvas.rb - Tk canvas classes
|
# tkcanvas.rb - Tk canvas classes
|
||||||
# $Date$
|
# $Date$
|
||||||
# by Yukihiro Matsumoto <matz@caelum.co.jp>
|
# by Yukihiro Matsumoto <matz@caelum.co.jp>
|
||||||
|
@ -180,7 +180,7 @@ class TkCanvas<TkWindow
|
||||||
end
|
end
|
||||||
|
|
||||||
def itemcget(tagOrId, option)
|
def itemcget(tagOrId, option)
|
||||||
case option
|
case option.to_s
|
||||||
when 'dash', 'activedash', 'disableddash'
|
when 'dash', 'activedash', 'disableddash'
|
||||||
conf = tk_send('itemcget', tagid(tagOrId), "-#{option}")
|
conf = tk_send('itemcget', tagid(tagOrId), "-#{option}")
|
||||||
if conf =~ /^[0-9]/
|
if conf =~ /^[0-9]/
|
||||||
|
@ -197,6 +197,7 @@ class TkCanvas<TkWindow
|
||||||
|
|
||||||
def itemconfigure(tagOrId, key, value=None)
|
def itemconfigure(tagOrId, key, value=None)
|
||||||
if key.kind_of? Hash
|
if key.kind_of? Hash
|
||||||
|
key = _symbolkey2str(key)
|
||||||
if ( key['font'] || key['kanjifont'] \
|
if ( key['font'] || key['kanjifont'] \
|
||||||
|| key['latinfont'] || key['asciifont'] )
|
|| key['latinfont'] || key['asciifont'] )
|
||||||
tagfont_configure(tagOrId, key.dup)
|
tagfont_configure(tagOrId, key.dup)
|
||||||
|
@ -205,8 +206,10 @@ class TkCanvas<TkWindow
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
if ( key == 'font' || key == 'kanjifont' \
|
if ( key == 'font' || key == :font ||
|
||||||
|| key == 'latinfont' || key == 'asciifont' )
|
key == 'kanjifont' || key == :kanjifont ||
|
||||||
|
key == 'latinfont' || key == :latinfont ||
|
||||||
|
key == 'asciifont' || key == :asciifont )
|
||||||
tagfont_configure(tagid(tagOrId), {key=>value})
|
tagfont_configure(tagid(tagOrId), {key=>value})
|
||||||
else
|
else
|
||||||
tk_send 'itemconfigure', tagid(tagOrId), "-#{key}", value
|
tk_send 'itemconfigure', tagid(tagOrId), "-#{key}", value
|
||||||
|
@ -226,7 +229,7 @@ class TkCanvas<TkWindow
|
||||||
|
|
||||||
def itemconfiginfo(tagOrId, key=nil)
|
def itemconfiginfo(tagOrId, key=nil)
|
||||||
if key
|
if key
|
||||||
case key
|
case key.to_s
|
||||||
when 'dash', 'activedash', 'disableddash'
|
when 'dash', 'activedash', 'disableddash'
|
||||||
conf = tk_split_simplelist(tk_send 'itemconfigure',
|
conf = tk_split_simplelist(tk_send 'itemconfigure',
|
||||||
tagid(tagOrId), "-#{key}")
|
tagid(tagOrId), "-#{key}")
|
||||||
|
@ -433,7 +436,7 @@ module TkcTagAccess
|
||||||
@c.itemtype @id
|
@c.itemtype @id
|
||||||
end
|
end
|
||||||
|
|
||||||
# Followings operators supports logical expressions of canvas tags
|
# Following operators support logical expressions of canvas tags
|
||||||
# (for Tk8.3+).
|
# (for Tk8.3+).
|
||||||
# If tag1.path is 't1' and tag2.path is 't2', then
|
# If tag1.path is 't1' and tag2.path is 't2', then
|
||||||
# ltag = tag1 & tag2; ltag.path => "(t1)&&(t2)"
|
# ltag = tag1 & tag2; ltag.path => "(t1)&&(t2)"
|
||||||
|
@ -473,6 +476,7 @@ class TkcTag<TkObject
|
||||||
include TkcTagAccess
|
include TkcTagAccess
|
||||||
|
|
||||||
CTagID_TBL = {}
|
CTagID_TBL = {}
|
||||||
|
Tk_CanvasTag_ID = ['ctag0000']
|
||||||
|
|
||||||
def TkcTag.id2obj(canvas, id)
|
def TkcTag.id2obj(canvas, id)
|
||||||
cpath = canvas.path
|
cpath = canvas.path
|
||||||
|
@ -480,7 +484,6 @@ class TkcTag<TkObject
|
||||||
CTagID_TBL[cpath][id]? CTagID_TBL[cpath][id]: id
|
CTagID_TBL[cpath][id]? CTagID_TBL[cpath][id]: id
|
||||||
end
|
end
|
||||||
|
|
||||||
Tk_CanvasTag_ID = ['ctag0000']
|
|
||||||
def initialize(parent, mode=nil, *args)
|
def initialize(parent, mode=nil, *args)
|
||||||
if not parent.kind_of?(TkCanvas)
|
if not parent.kind_of?(TkCanvas)
|
||||||
fail format("%s need to be TkCanvas", parent.inspect)
|
fail format("%s need to be TkCanvas", parent.inspect)
|
||||||
|
@ -501,7 +504,7 @@ class TkcTag<TkObject
|
||||||
|
|
||||||
def delete
|
def delete
|
||||||
@c.delete @id
|
@c.delete @id
|
||||||
CTagID_TBL[@path][@id] = nil if CTagID_TBL[@path]
|
CTagID_TBL[@cpath][@id] = nil if CTagID_TBL[@cpath]
|
||||||
end
|
end
|
||||||
alias remove delete
|
alias remove delete
|
||||||
alias destroy delete
|
alias destroy delete
|
||||||
|
@ -565,6 +568,7 @@ class TkcTagString<TkcTag
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
TkcNamedTag = TkcTagString
|
||||||
|
|
||||||
class TkcTagAll<TkcTag
|
class TkcTagAll<TkcTag
|
||||||
def initialize(parent)
|
def initialize(parent)
|
||||||
|
@ -643,9 +647,16 @@ class TkcItem<TkObject
|
||||||
@parent = @c = parent
|
@parent = @c = parent
|
||||||
@path = parent.path
|
@path = parent.path
|
||||||
fontkeys = {}
|
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
|
if args[-1].kind_of? Hash
|
||||||
args = args.dup
|
keys = _symbolkey2str(args.pop)
|
||||||
keys = args.pop
|
|
||||||
['font', 'kanjifont', 'latinfont', 'asciifont'].each{|key|
|
['font', 'kanjifont', 'latinfont', 'asciifont'].each{|key|
|
||||||
fontkeys[key] = keys.delete(key) if keys.key?(key)
|
fontkeys[key] = keys.delete(key) if keys.key?(key)
|
||||||
}
|
}
|
||||||
|
@ -797,7 +808,7 @@ class TkPhotoImage<TkImage
|
||||||
end
|
end
|
||||||
|
|
||||||
def cget(option)
|
def cget(option)
|
||||||
case option
|
case option.to_s
|
||||||
when 'data', 'file'
|
when 'data', 'file'
|
||||||
tk_send 'cget', option
|
tk_send 'cget', option
|
||||||
else
|
else
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
#
|
#
|
||||||
# tkclass.rb - Tk classes
|
# tkclass.rb - Tk classes
|
||||||
# $Date$
|
# Date: 2000/11/27 09:23:36
|
||||||
# by Yukihiro Matsumoto <matz@caelum.co.jp>
|
# by Yukihiro Matsumoto <matz@caelum.co.jp>
|
||||||
|
#
|
||||||
|
# $Id$
|
||||||
|
|
||||||
require "tk"
|
require "tk"
|
||||||
|
|
||||||
|
@ -13,6 +15,7 @@ Radiobutton = TkRadioButton
|
||||||
Checkbutton = TkCheckButton
|
Checkbutton = TkCheckButton
|
||||||
Message = TkMessage
|
Message = TkMessage
|
||||||
Entry = TkEntry
|
Entry = TkEntry
|
||||||
|
Spinbox = TkSpinbox
|
||||||
Text = TkText
|
Text = TkText
|
||||||
Scale = TkScale
|
Scale = TkScale
|
||||||
Scrollbar = TkScrollbar
|
Scrollbar = TkScrollbar
|
||||||
|
@ -28,10 +31,16 @@ Polygon = TkcPolygon
|
||||||
Rectangle = TkcRectangle
|
Rectangle = TkcRectangle
|
||||||
TextItem = TkcText
|
TextItem = TkcText
|
||||||
WindowItem = TkcWindow
|
WindowItem = TkcWindow
|
||||||
|
BitmapImage = TkBitmapImage
|
||||||
|
PhotoImage = TkPhotoImage
|
||||||
Selection = TkSelection
|
Selection = TkSelection
|
||||||
Winfo = TkWinfo
|
Winfo = TkWinfo
|
||||||
Pack = TkPack
|
Pack = TkPack
|
||||||
|
Grid = TkGrid
|
||||||
|
Place = TkPlace
|
||||||
Variable = TkVariable
|
Variable = TkVariable
|
||||||
|
Font = TkFont
|
||||||
|
VirtualEvent = TkVirtualEvent
|
||||||
|
|
||||||
def Mainloop
|
def Mainloop
|
||||||
Tk.mainloop
|
Tk.mainloop
|
||||||
|
|
|
@ -23,6 +23,7 @@ class TkDialog < TkWindow
|
||||||
@button_configs = proc{|num| button_configs num}
|
@button_configs = proc{|num| button_configs num}
|
||||||
|
|
||||||
if keys.kind_of? Hash
|
if keys.kind_of? Hash
|
||||||
|
keys = _symbolkey2str(keys)
|
||||||
@title = keys['title'] if keys['title']
|
@title = keys['title'] if keys['title']
|
||||||
@message = keys['message'] if keys['message']
|
@message = keys['message'] if keys['message']
|
||||||
@bitmap = keys['bitmap'] if keys['bitmap']
|
@bitmap = keys['bitmap'] if keys['bitmap']
|
||||||
|
|
|
@ -73,6 +73,7 @@ class TkEntry<TkLabel
|
||||||
|
|
||||||
def configure(slot, value=None)
|
def configure(slot, value=None)
|
||||||
if slot.kind_of? Hash
|
if slot.kind_of? Hash
|
||||||
|
slot = _symbolkey2str(slot)
|
||||||
if slot['vcmd'].kind_of? Array
|
if slot['vcmd'].kind_of? Array
|
||||||
cmd, *args = slot['vcmd']
|
cmd, *args = slot['vcmd']
|
||||||
slot['vcmd'] = ValidateCmd.new(cmd, args.join(' '))
|
slot['vcmd'] = ValidateCmd.new(cmd, args.join(' '))
|
||||||
|
@ -99,8 +100,10 @@ class TkEntry<TkLabel
|
||||||
end
|
end
|
||||||
super(slot)
|
super(slot)
|
||||||
else
|
else
|
||||||
if (slot == 'vcmd' || slot == 'validatecommand' ||
|
if (slot == 'vcmd' || slot == :vcmd ||
|
||||||
slot == 'invcmd' || slot == 'invalidcommand')
|
slot == 'validatecommand' || slot == :validatecommand ||
|
||||||
|
slot == 'invcmd' || slot == :invcmd ||
|
||||||
|
slot == 'invalidcommand' !! slot == :invalidcommand)
|
||||||
if value.kind_of? Array
|
if value.kind_of? Array
|
||||||
cmd, *args = value
|
cmd, *args = value
|
||||||
value = ValidateCmd.new(cmd, args.join(' '))
|
value = ValidateCmd.new(cmd, args.join(' '))
|
||||||
|
|
|
@ -173,16 +173,18 @@ class TkFont
|
||||||
TkFont.new(nil, nil).call_font_configure(path, *(args + [{}]))
|
TkFont.new(nil, nil).call_font_configure(path, *(args + [{}]))
|
||||||
else
|
else
|
||||||
begin
|
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|
|
fnt))].collect{|key,value|
|
||||||
[key[1..-1], value]
|
[key[1..-1], value]
|
||||||
}.assoc('compound')[1]
|
}.assoc('compound')[1])
|
||||||
rescue
|
rescue
|
||||||
compound = []
|
compound = []
|
||||||
end
|
end
|
||||||
if compound == []
|
if compound == []
|
||||||
TkFont.new(fnt, DEFAULT_KANJI_FONT_NAME) \
|
#TkFont.new(fnt, DEFAULT_KANJI_FONT_NAME) \
|
||||||
.call_font_configure(path, *(args + [{}]))
|
#.call_font_configure(path, *(args + [{}]))
|
||||||
|
TkFont.new(fnt).call_font_configure(path, *(args + [{}]))
|
||||||
else
|
else
|
||||||
TkFont.new(compound[0], compound[1]) \
|
TkFont.new(compound[0], compound[1]) \
|
||||||
.call_font_configure(path, *(args + [{}]))
|
.call_font_configure(path, *(args + [{}]))
|
||||||
|
@ -220,6 +222,7 @@ class TkFont
|
||||||
end
|
end
|
||||||
|
|
||||||
def _get_font_info_from_hash(font)
|
def _get_font_info_from_hash(font)
|
||||||
|
font = _symbolkey2str(font)
|
||||||
foundry = (info = font['foundry'] .to_s)? info: '*'
|
foundry = (info = font['foundry'] .to_s)? info: '*'
|
||||||
family = (info = font['family'] .to_s)? info: '*'
|
family = (info = font['family'] .to_s)? info: '*'
|
||||||
weight = (info = font['weight'] .to_s)? info: '*'
|
weight = (info = font['weight'] .to_s)? info: '*'
|
||||||
|
@ -353,7 +356,7 @@ class TkFont
|
||||||
|
|
||||||
if JAPANIZED_TK
|
if JAPANIZED_TK
|
||||||
if font.kind_of? Hash
|
if font.kind_of? Hash
|
||||||
if font['charset']
|
if font[:charset] || font['charset']
|
||||||
tk_call('font', 'create', @latinfont, *hash_kv(font))
|
tk_call('font', 'create', @latinfont, *hash_kv(font))
|
||||||
else
|
else
|
||||||
tk_call('font', 'create', @latinfont,
|
tk_call('font', 'create', @latinfont,
|
||||||
|
@ -398,7 +401,7 @@ class TkFont
|
||||||
|
|
||||||
if JAPANIZED_TK
|
if JAPANIZED_TK
|
||||||
if font.kind_of? Hash
|
if font.kind_of? Hash
|
||||||
if font['charset']
|
if font[:charset] || font['charset']
|
||||||
tk_call('font', 'create', @kanjifont, *hash_kv(font))
|
tk_call('font', 'create', @kanjifont, *hash_kv(font))
|
||||||
else
|
else
|
||||||
tk_call('font', 'create', @kanjifont,
|
tk_call('font', 'create', @kanjifont,
|
||||||
|
|
|
@ -66,7 +66,13 @@ class TkMenubar<TkFrame
|
||||||
include TkComposite
|
include TkComposite
|
||||||
|
|
||||||
def initialize(parent = nil, spec = nil, options = nil)
|
def initialize(parent = nil, spec = nil, options = nil)
|
||||||
|
if parent.kind_of? Hash
|
||||||
|
options = _symbolkey2str(parent)
|
||||||
|
spec = options.delete('spec')
|
||||||
|
super(options)
|
||||||
|
else
|
||||||
super(parent, options)
|
super(parent, options)
|
||||||
|
end
|
||||||
|
|
||||||
@menus = []
|
@menus = []
|
||||||
|
|
||||||
|
|
|
@ -185,7 +185,7 @@ class TkText<TkTextWin
|
||||||
end
|
end
|
||||||
|
|
||||||
def tag_cget(tag, key)
|
def tag_cget(tag, key)
|
||||||
case key
|
case key.to_s
|
||||||
when 'text', 'label', 'show', 'data', 'file'
|
when 'text', 'label', 'show', 'data', 'file'
|
||||||
tk_call @path, 'tag', 'cget', tag, "-#{key}"
|
tk_call @path, 'tag', 'cget', tag, "-#{key}"
|
||||||
else
|
else
|
||||||
|
@ -195,16 +195,19 @@ class TkText<TkTextWin
|
||||||
|
|
||||||
def tag_configure(tag, key, val=None)
|
def tag_configure(tag, key, val=None)
|
||||||
if key.kind_of? Hash
|
if key.kind_of? Hash
|
||||||
|
key = _symbolkey2str(key)
|
||||||
if ( key['font'] || key['kanjifont'] \
|
if ( key['font'] || key['kanjifont'] \
|
||||||
|| key['latinfont'] || key['asciifont'] )
|
|| key['latinfont'] || key['asciifont'] )
|
||||||
tagfont_configure(tag, key.dup)
|
tagfont_configure(tag, key)
|
||||||
else
|
else
|
||||||
tk_send 'tag', 'configure', tag, *hash_kv(key)
|
tk_send 'tag', 'configure', tag, *hash_kv(key)
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
if key == 'font' || key == 'kanjifont' ||
|
if key == 'font' || key == :font ||
|
||||||
key == 'latinfont' || key == 'asciifont'
|
key == 'kanjifont' || key == :kanjifont ||
|
||||||
|
key == 'latinfont' || key == :latinfont ||
|
||||||
|
key == 'asciifont' || key == :asciifont
|
||||||
tagfont_configure(tag, {key=>val})
|
tagfont_configure(tag, {key=>val})
|
||||||
else
|
else
|
||||||
tk_send 'tag', 'configure', tag, "-#{key}", val
|
tk_send 'tag', 'configure', tag, "-#{key}", val
|
||||||
|
@ -214,7 +217,7 @@ class TkText<TkTextWin
|
||||||
|
|
||||||
def tag_configinfo(tag, key=nil)
|
def tag_configinfo(tag, key=nil)
|
||||||
if key
|
if key
|
||||||
case key
|
case key.to_s
|
||||||
when 'text', 'label', 'show', 'data', 'file'
|
when 'text', 'label', 'show', 'data', 'file'
|
||||||
conf = tk_split_simplelist(tk_send('tag','configure',tag,"-#{key}"))
|
conf = tk_split_simplelist(tk_send('tag','configure',tag,"-#{key}"))
|
||||||
else
|
else
|
||||||
|
@ -549,14 +552,25 @@ end
|
||||||
class TkTextTag<TkObject
|
class TkTextTag<TkObject
|
||||||
include TkTreatTagFont
|
include TkTreatTagFont
|
||||||
|
|
||||||
|
TTagID_TBL = {}
|
||||||
Tk_TextTag_ID = ['tag0000']
|
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)
|
def initialize(parent, *args)
|
||||||
if not parent.kind_of?(TkText)
|
if not parent.kind_of?(TkText)
|
||||||
fail format("%s need to be TkText", parent.inspect)
|
fail format("%s need to be TkText", parent.inspect)
|
||||||
end
|
end
|
||||||
@parent = @t = parent
|
@parent = @t = parent
|
||||||
|
@tpath = parent.path
|
||||||
@path = @id = Tk_TextTag_ID[0]
|
@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_TextTag_ID[0] = Tk_TextTag_ID[0].succ
|
||||||
#tk_call @t.path, "tag", "configure", @id, *hash_kv(keys)
|
#tk_call @t.path, "tag", "configure", @id, *hash_kv(keys)
|
||||||
if args != [] then
|
if args != [] then
|
||||||
|
@ -618,7 +632,7 @@ class TkTextTag<TkObject
|
||||||
end
|
end
|
||||||
|
|
||||||
def cget(key)
|
def cget(key)
|
||||||
case key
|
case key.to_s
|
||||||
when 'text', 'label', 'show', 'data', 'file'
|
when 'text', 'label', 'show', 'data', 'file'
|
||||||
tk_call @t.path, 'tag', 'cget', @id, "-#{key}"
|
tk_call @t.path, 'tag', 'cget', @id, "-#{key}"
|
||||||
else
|
else
|
||||||
|
@ -671,6 +685,31 @@ class TkTextTag<TkObject
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
tk_call @t.path, 'tag', 'delete', @id
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -792,6 +831,7 @@ class TkTextWindow<TkObject
|
||||||
end
|
end
|
||||||
@path.gravity = 'left'
|
@path.gravity = 'left'
|
||||||
@index = @path.path
|
@index = @path.path
|
||||||
|
keys = _symbolkey2str(keys)
|
||||||
@id = keys['window']
|
@id = keys['window']
|
||||||
if keys['create']
|
if keys['create']
|
||||||
@p_create = keys['create']
|
@p_create = keys['create']
|
||||||
|
@ -810,7 +850,7 @@ class TkTextWindow<TkObject
|
||||||
end
|
end
|
||||||
|
|
||||||
def cget(slot)
|
def cget(slot)
|
||||||
case slot
|
case slot.to_s
|
||||||
when 'text', 'label', 'show', 'data', 'file'
|
when 'text', 'label', 'show', 'data', 'file'
|
||||||
tk_call @t.path, 'window', 'cget', @index, "-#{slot}"
|
tk_call @t.path, 'window', 'cget', @index, "-#{slot}"
|
||||||
else
|
else
|
||||||
|
@ -820,6 +860,7 @@ class TkTextWindow<TkObject
|
||||||
|
|
||||||
def configure(slot, value=None)
|
def configure(slot, value=None)
|
||||||
if slot.kind_of? Hash
|
if slot.kind_of? Hash
|
||||||
|
slot = _symbolkey2str(slot)
|
||||||
@id = slot['window'] if slot['window']
|
@id = slot['window'] if slot['window']
|
||||||
if slot['create']
|
if slot['create']
|
||||||
self.create=value
|
self.create=value
|
||||||
|
@ -829,8 +870,8 @@ class TkTextWindow<TkObject
|
||||||
tk_call @t.path, 'window', 'configure', @index, *hash_kv(slot)
|
tk_call @t.path, 'window', 'configure', @index, *hash_kv(slot)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@id = value if slot == 'window'
|
@id = value if slot == 'window' || slot == :window
|
||||||
if slot == 'create'
|
if slot == 'create' || slot == :create
|
||||||
self.create=value
|
self.create=value
|
||||||
else
|
else
|
||||||
tk_call @t.path, 'window', 'configure', @index, "-#{slot}", value
|
tk_call @t.path, 'window', 'configure', @index, "-#{slot}", value
|
||||||
|
@ -861,7 +902,7 @@ class TkTextWindow<TkObject
|
||||||
|
|
||||||
def configinfo(slot = nil)
|
def configinfo(slot = nil)
|
||||||
if slot
|
if slot
|
||||||
case slot
|
case slot.to_s
|
||||||
when 'text', 'label', 'show', 'data', 'file'
|
when 'text', 'label', 'show', 'data', 'file'
|
||||||
conf = tk_split_simplelist(tk_call @t.path, 'window', 'configure',
|
conf = tk_split_simplelist(tk_call @t.path, 'window', 'configure',
|
||||||
@index, "-#{slot}")
|
@index, "-#{slot}")
|
||||||
|
@ -931,7 +972,7 @@ class TkTextImage<TkObject
|
||||||
end
|
end
|
||||||
|
|
||||||
def cget(slot)
|
def cget(slot)
|
||||||
case slot
|
case slot.to_s
|
||||||
when 'text', 'label', 'show', 'data', 'file'
|
when 'text', 'label', 'show', 'data', 'file'
|
||||||
tk_call @t.path, 'image', 'cget', @index, "-#{slot}"
|
tk_call @t.path, 'image', 'cget', @index, "-#{slot}"
|
||||||
else
|
else
|
||||||
|
@ -960,7 +1001,7 @@ class TkTextImage<TkObject
|
||||||
|
|
||||||
def configinfo(slot = nil)
|
def configinfo(slot = nil)
|
||||||
if slot
|
if slot
|
||||||
case slot
|
case slot.to_s
|
||||||
when 'text', 'label', 'show', 'data', 'file'
|
when 'text', 'label', 'show', 'data', 'file'
|
||||||
conf = tk_split_simplelist(tk_call @t.path, 'image', 'configure',
|
conf = tk_split_simplelist(tk_call @t.path, 'image', 'configure',
|
||||||
@index, "-#{slot}")
|
@index, "-#{slot}")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue