* renewal Ruby/Tk

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@6237 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nagai 2004-05-01 16:09:54 +00:00
parent ce23680755
commit 4c4631c2da
247 changed files with 27219 additions and 11144 deletions

View File

@ -1,3 +1,7 @@
Sun May 2 01:04:38 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
* ext/tcltklib, ext/tk: renewal Ruby/Tk
Fri Apr 30 20:08:41 2004 WATANABE Hirofumi <eban@ruby-lang.org>
* time.c (SIZEOF_TIME_T): support SIZEOF_TIME_T == SIZEOF_INT.

View File

@ -11,6 +11,8 @@ lib/tcltk.rb
demo/lines0.tcl
demo/lines1.rb
demo/lines2.rb
demo/lines3.rb
demo/lines4.rb
demo/safeTk.rb
sample/sample0.rb
sample/sample1.rb

View File

@ -1,5 +1,5 @@
(tof)
2003/10/17 Hidetoshi NAGAI
2004/03/28 Hidetoshi NAGAI
This document discribes about the 'tcltklib' library. Although there
is the 'tcltk' library (tcltk.rb) under this directory, no description
@ -41,224 +41,367 @@ module TclTklib
: a target event. With this flag, doesn't wait and returns
: false if there is no target event for processing.
[module methods]
mainloop(check_root = true)
: Starts the eventloop. If 'check_root' is true, this method
: doesn't return when a root widget exists.
: If 'check_root' is false, doen't return by the other
: reasons than exceptions.
module TclTkLib::VarAccessFlag
: Defines flags to give '_get_variable' and so on. When to give,
: please use bit-operator (e.g. GLOBAL_ONLY | LEAVE_ERR_MSG ).
mainloop_watchdog(check_root = true)
: On the normal eventloop, some kinds of callback operations
: cause deadlock. To avoid some of such deadlocks, this
: method starts an eventloop and a watchdog-thread.
[constants]
NONE
: Is 0. It means "set no flag".
do_one_event(flag = TclTkLib::EventFlag::ALL |
TclTkLib::EventFlag::DONT_WAIT)
: Do one event for processing. When processed an event,
: returns true.
: If NOT set DONT_WAIT flag, this method waits occurrence of
: a target event.
: If set DONT_WAIT flag and no event for processing, returns
: false immediately.
: If $SAFE >= 4, or $SAFE >= 1 and the flag is tainted,
: force to set DONT_WAIT flag.
GLOBAL_ONLY
: (site Tcl/Tk's man page)
: Under normal circumstances the procedures look up
: variables as follows: If a procedure call is active
: in interp, a variable is looked up at the current
: level of procedure call. Otherwise, a variable is
: looked up first in the current namespace, then in
: the global namespace. However, if this bit is set
: in flags then the variable is looked up only in the
: global namespace even if there is a procedure call
: active. If both GLOBAL_ONLY and NAMESPACE_ONLY are
: given, GLOBAL_ONLY is ignored.
:
: *** ATTENTION ***
: Tcl7.6 doesn't have namespaces. So NAMESPACE_ONLY
: is defined as 0, and then GLOBAL_ONLY is available
: even if flag is (GLOBAL_ONLY | NAMESPACE_ONLY).
set_eventloop_tick(timer_tick)
: Define the interval of thread-switching with an integer
: value of mili-seconds.
: Default timer_tick is 0. It means that thread-switching
: is based on the count of processed events.
: ( see 'set_eventloop_weight' method )
: However, if the eventloop thread is the only thread,
: timer_tick cannt be set to 0. If 0, then is set to 100 ms
: automatically (see NO_THREAD_INTERRUPT_TIME on tcltklib.c).
: On $SAFE >= 4, cannot call this method.
NAMESPACE_ONLY
: (site Tcl/Tk's man page)
: Under normal circumstances the procedures look up
: variables as follows: If a procedure call is active
: in interp, a variable is looked up at the current
: level of procedure call. Otherwise, a variable is
: looked up first in the current namespace, then in
: the global namespace. However, if this bit is set
: in flags then the variable is looked up only in the
: current namespace even if there is a procedure call
: active.
:
: *** ATTENTION ***
: Tcl7.6 doesn't have namespaces. So NAMESPACE_ONLY
: is defined as 0.
get_eventloop_tick
: Get current value of 'timer_tick'
LEAVE_ERR_MSG
: (site Tcl/Tk's man page)
: If an error is returned and this bit is set in flags,
: then an error message will be left in the interpreter's
: result, where it can be retrieved with Tcl_GetObjResult
: or Tcl_GetStringResult. If this flag bit isn't set then
: no error message is left and the interpreter's result
: will not be modified.
set_no_event_wait(no_event_wait)
: Define sleeping time of the eventloop when two or more
: thread are running and there is no event for processing.
: Default value is 20 (ms).
: If the eventloop thread is the only thread, this value is
: invalid.
: On $SAFE >= 4, cannot call this method.
APPEND_VALUE
: (site Tcl/Tk's man page)
: If this bit is set then newValue is appended to the
: current value, instead of replacing it. If the variable
: is currently undefined, then this bit is ignored.
get_no_event_wait
: Get current value of 'no_event_wait'.
LIST_ELEMENT
: (site Tcl/Tk's man page)
: If this bit is set, then newValue is converted to a
: valid Tcl list element before setting (or appending
: to) the variable. A separator space is appended before
: the new list element unless the list element is going
: to be the first element in a list or sublist (i.e. the
: variable's current value is empty, or contains the
: single character ``{'', or ends in `` }'').
set_eventloop_weight(loop_max, no_event_tick)
: Define the weight parameters for the eventloop thread.
: That is invalid when the eventloop is the only thread.
: 'loop_max' is the max events for thread-switching.
: 'no_event_tick' is the increment value of the event count
: when no event for processing (And then, the eventloop thead
: sleeps 'no_event_wait' mili-seconds).
: 'loop_max == 800' and 'no_event_tick == 10' are defalut.
: On $SAFE >= 4, cannot call this method.
PARSE_VARNAME
: (site Tcl/Tk's man page)
: If this bit is set when calling _set_variable and so
: on, var_name argument may contain both an array and an
: element name: if the name contains an open parenthesis
: and ends with a close parenthesis, then the value
: between the parentheses is treated as an element name
: (which can have any string value) and the characters
: before the first open parenthesis are treated as the
: name of an array variable. If the flag PARSE_VARNAME
: is given, index_name argument should be 'nil' since the
: array and element names are taken from var_name.
:
: *** ATTENTION ***
: Tcl7.6 doesn't have this flag. So PARSE_VARNAME is
: defined as 0.
get_eventloop_weight
: Get current values of 'loop_max' and 'no_event_tick'.
[module methods]
mainloop(check_root = true)
: Starts the eventloop. If 'check_root' is true, this method
: doesn't return when a root widget exists.
: If 'check_root' is false, doen't return by the other
: reasons than exceptions.
mainloop_abort_on_exception=(bool)
: Define whether the eventloop stops on exception or not.
: If true (default value), stops on exception.
: If false, show a warinig message but ignore the exception.
: If nil, no warning message and ignore the excepsion.
: This parameter is sometimes useful when multiple Tk
: interpreters are working. Because the only one eventloop
: admins all Tk interpreters, sometimes exception on a
: interpreter kills the eventloop thread. Even if such
: situation, when abort_on_exception == false or nil,
: the eventloop ignores the exception and continue to working.
: On $SAFE >= 4, cannot call this method.
mainloop_watchdog(check_root = true)
: On the normal eventloop, some kinds of callback operations
: cause deadlock. To avoid some of such deadlocks, this
: method starts an eventloop and a watchdog-thread.
mainloop_abort_on_exception
: Get current status of that.
do_one_event(flag = TclTkLib::EventFlag::ALL |
TclTkLib::EventFlag::DONT_WAIT)
: Do one event for processing. When processed an event,
: returns true.
: If NOT set DONT_WAIT flag, this method waits occurrence of
: a target event.
: If set DONT_WAIT flag and no event for processing, returns
: false immediately.
: If $SAFE >= 4, or $SAFE >= 1 and the flag is tainted,
: force to set DONT_WAIT flag.
num_of_mainwindows
: Returns the number of main-windows (root-widget).
: Because there is only one main-window for one Tk interpreter,
: the value is same to the number of interpreters which has
: available Tk functions.
set_eventloop_tick(timer_tick)
: Define the interval of thread-switching with an integer
: value of mili-seconds.
: Default timer_tick is 0. It means that thread-switching
: is based on the count of processed events.
: ( see 'set_eventloop_weight' method )
: However, if the eventloop thread is the only thread,
: timer_tick cannt be set to 0. If 0, then is set to 100 ms
: automatically (see NO_THREAD_INTERRUPT_TIME on tcltklib.c).
: On $SAFE >= 4, cannot call this method.
get_eventloop_tick
: Get current value of 'timer_tick'
set_no_event_wait(no_event_wait)
: Define sleeping time of the eventloop when two or more
: thread are running and there is no event for processing.
: Default value is 20 (ms).
: If the eventloop thread is the only thread, this value is
: invalid.
: On $SAFE >= 4, cannot call this method.
get_no_event_wait
: Get current value of 'no_event_wait'.
set_eventloop_weight(loop_max, no_event_tick)
: Define the weight parameters for the eventloop thread.
: That is invalid when the eventloop is the only thread.
: 'loop_max' is the max events for thread-switching.
: 'no_event_tick' is the increment value of the event count
: when no event for processing (And then, the eventloop thead
: sleeps 'no_event_wait' mili-seconds).
: 'loop_max == 800' and 'no_event_tick == 10' are defalut.
: On $SAFE >= 4, cannot call this method.
get_eventloop_weight
: Get current values of 'loop_max' and 'no_event_tick'.
mainloop_abort_on_exception=(bool)
: Define whether the eventloop stops on exception or not.
: If true (default value), stops on exception.
: If false, show a warinig message but ignore the exception.
: If nil, no warning message and ignore the excepsion.
: This parameter is sometimes useful when multiple Tk
: interpreters are working. Because the only one eventloop
: admins all Tk interpreters, sometimes exception on a
: interpreter kills the eventloop thread. Even if such
: situation, when abort_on_exception == false or nil,
: the eventloop ignores the exception and continue to working.
: On $SAFE >= 4, cannot call this method.
mainloop_abort_on_exception
: Get current status of that.
num_of_mainwindows
: Returns the number of main-windows (root-widget).
: Because there is only one main-window for one Tk interpreter,
: the value is same to the number of interpreters which has
: available Tk functions.
_merge_tklist(str, str, ... )
: Get a Tcl's list string from arguments with a Tcl/Tk's
: library function. Each arguemnt is converted to a valid
: Tcl list element.
_conv_listelement(str)
: Convert the argument to a valid Tcl list element with
: Tcl/Tk's library function.
_toUTF8(str, encoding)
_fromUTF8(str, encoding)
: Call the function (which is internal function of Tcl/Tk) to
: convert to/from a UTF8 string.
_subst_UTF_backslash(str)
_subst_Tcl_backslash(str)
: Substitute backslash sequence with Tcl's rule (include \uhhhh;
: give a sixteen-bit hexadecimal value for Unicode character).
: _subst_Tcl_backslash method parses all backslash sequence.
: _subst_UTF_backslash method parses \uhhhh only.
class TclTkIp
[class methods]
new(ip_name=nil, options='')
: Generate an instance of TclTkIp class.
: If 'ip_name' argument is given as a string, it is the name
: of the Tk interpreter which is shown by 'winfo interps'
: command.
: 'options' argument accepts a string which is the command
: line options of wish; such as '-geometry' or '-use'.
: The information is used to generate the root widget of the
: interpreter.
: ( e.g. TclTkIp.new('FOO', '-geometry 500x200 -use 0x2200009') )
: If is given nil or falsr for the 'option' argument, generates
: the Tcl interpreter without Tk library. Then the interpreter
: doesn't need GUI environment. Therefore, even if a window
: system doesn't exist or cannot be used, Ruby can control the
: Tcl interpreter and the extention libraries loaded on the
: interpreter.
new(ip_name=nil, options='')
: Generate an instance of TclTkIp class.
: If 'ip_name' argument is given as a string, it is the name
: of the Tk interpreter which is shown by 'winfo interps'
: command.
: 'options' argument accepts a string which is the command
: line options of wish; such as '-geometry' or '-use'.
: The information is used to generate the root widget of the
: interpreter.
: ( e.g. TclTkIp.new('FOO', '-geometry 500x200 -use 0x2200009') )
: If is given nil or falsr for the 'option' argument, generates
: the Tcl interpreter without Tk library. Then the interpreter
: doesn't need GUI environment. Therefore, even if a window
: system doesn't exist or cannot be used, Ruby can control the
: Tcl interpreter and the extention libraries loaded on the
: interpreter.
[instance methods]
create_slave(name, safe=false)
: Create a slave interpreter.
: The parent of the interpreter is the receiver of this method.
: The name of the slave interpreter is given by 'name' argument.
: The 'safe' argument decides whether the slave interpreter is
: created as a safe interpreter or not. If true, create a safe
: interpreter. Default is false. However, if the parent
: interpreter is a safe interpreter, the created interpreter is
: a safe interpreter (ignore 'safe' argument value).
: If $SAFE >= 4, can create a safe interpreter only.
[instance methods]
create_slave(name, safe=false)
: Create a slave interpreter.
: The parent of the interpreter is the receiver of this method.
: The name of the slave interpreter is given by 'name' argument.
: The 'safe' argument decides whether the slave interpreter is
: created as a safe interpreter or not. If true, create a safe
: interpreter. Default is false. However, if the parent
: interpreter is a safe interpreter, the created interpreter is
: a safe interpreter (ignore 'safe' argument value).
: If $SAFE >= 4, can create a safe interpreter only.
make_safe
: Make the interpreter to the safe interpreter, and returns
: self. If fail, raise RuntimeError.
make_safe
: Make the interpreter to the safe interpreter, and returns
: self. If fail, raise RuntimeError.
safe?
: Check whether the interpreter is the safe interpreter.
: If is the safe interpreter, returns true.
safe?
: Check whether the interpreter is the safe interpreter.
: If is the safe interpreter, returns true.
delete
: Delete the interpreter.
: The deleted interpreter doesn't accept command and then
: raise an exception.
delete
: Delete the interpreter.
: The deleted interpreter doesn't accept command and then
: raise an exception.
deleted?
: Check whether the interpreter is already deleted.
: If deleted, returns true.
deleted?
: Check whether the interpreter is already deleted.
: If deleted, returns true.
restart
: Restart Tk part of the interpreter.
: Use this when you need Tk functions after destroying the
: root widget.
: On $SAFE >= 4, cannot call this method.
restart
: Restart Tk part of the interpreter.
: Use this when you need Tk functions after destroying the
: root widget.
: On $SAFE >= 4, cannot call this method.
_eval(str)
_invoke(*args)
: Estimates the arguments as a command on the Tk interpreter.
: The argument of _eval is a script of Tcl/Tk.
: Each argument of _invoke is a token of one command line of
: Tcl/Tk.
: Because the operation of _invoke doesn't through the
: command line parser of Tk interpreter, the cost of
: estimation is smaller than _eval. However, auto_load
: mechanism of the Tk interpreter doesn't work on _invoke.
: So _invoke can call only the command which already
: registered on the interpreter by 'load' command and so on.
: On _eval command, auto_load mechanism words. So if succeed
: to _eval and regist the command once, after that, the
: command can be called by _invoke.
_eval(str)
_invoke(*args)
: Estimates the arguments as a command on the Tk interpreter.
: The argument of _eval is a script of Tcl/Tk.
: Each argument of _invoke is a token of one command line of
: Tcl/Tk.
: Because the operation of _invoke doesn't through the
: command line parser of Tk interpreter, the cost of
: estimation is smaller than _eval. However, auto_load
: mechanism of the Tk interpreter doesn't work on _invoke.
: So _invoke can call only the command which already
: registered on the interpreter by 'load' command and so on.
: On _eval command, auto_load mechanism words. So if succeed
: to _eval and regist the command once, after that, the
: command can be called by _invoke.
_toUTF8(str, encoding)
_fromUTF8(str, encoding)
: Call the function (which is internal function of Tcl/Tk) to
: convert to/from a UTF8 string.
_toUTF8(str, encoding)
_fromUTF8(str, encoding)
: Call the function (which is internal function of Tcl/Tk) to
: convert to/from a UTF8 string.
_thread_vwait(var_name)
_thread_tkwait(mode, target)
: 'vwait' or 'tkwait' with thread support.
: The difference from normal 'vwait' or 'tkwait' command is
: doing independent wait from the vwait stack when they are
: called on the other thread than the eventloop thread.
: In the case of Tcl/Tk's vwait / tkwait, if 2nd vwait /
: tkwait is called on waiting for 1st vwait / tkwait,
: returns the order of [2nd]->[1st] regardless of the order
: of when the wait condition was fulfilled.
: If _thread_vwait / _thread_tkwait is called on the
: eventloop thread, there is no difference from vwait /
: tkwait. But if called on the other thread than the
: eventloop, stops the thread. And when the wait condition
: is fulfilled, the thread restarts. The meaning of
: "independent from the vwait stack" is that the timing of
: restarting is independent from the waiting status of the
: other threads. That is, even if the eventloop thread is
: waiting by vwait and is not fulfilled the condition,
: _thread_vwait completes the waiting when its waiting
: condition is fulfilled and the thread which stopped by
: _thread_vwait can continue the operation.
_thread_vwait(var_name)
_thread_tkwait(mode, target)
: 'vwait' or 'tkwait' with thread support.
: The difference from normal 'vwait' or 'tkwait' command is
: doing independent wait from the vwait stack when they are
: called on the other thread than the eventloop thread.
: In the case of Tcl/Tk's vwait / tkwait, if 2nd vwait /
: tkwait is called on waiting for 1st vwait / tkwait,
: returns the order of [2nd]->[1st] regardless of the order
: of when the wait condition was fulfilled.
: If _thread_vwait / _thread_tkwait is called on the
: eventloop thread, there is no difference from vwait /
: tkwait. But if called on the other thread than the
: eventloop, stops the thread. And when the wait condition
: is fulfilled, the thread restarts. The meaning of
: "independent from the vwait stack" is that the timing of
: restarting is independent from the waiting status of the
: other threads. That is, even if the eventloop thread is
: waiting by vwait and is not fulfilled the condition,
: _thread_vwait completes the waiting when its waiting
: condition is fulfilled and the thread which stopped by
: _thread_vwait can continue the operation.
_return_value
: Get the last result value on the interpreter.
_return_value
: Get the last result value on the interpreter.
mainloop
mainloop_watchdog
: If on the slave interpreter, never start an eventloop and
: returns nil.
: With the exception that, same to the TclTkLib module method
: with the same name.
_get_variable(var_name, flag)
_get_variable2(var_name, index_name, flag)
: Get the current value of a variable. If specified a
: index_name (see also the PARSE_VARNAME flag), get the
: value of the index_name element.
do_one_event
: With the exception that the argument is forced to set
: DONT_WAIT flag on the slave interpreter, same to
: TclTkLib#do_one_event.
_set_variable(var_name, value, flag)
_set_variable2(var_name, index_name, value, flag)
: Create or modify a variable. If specified a index_name
: (see also the PARSE_VARNAME flag), create or modify the
: index_name element.
set_eventloop_tick
get_eventloop_tick
set_no_event_wait
get_no_event_wait
set_eventloop_weight
get_eventloop_weight
mainloop_abort_on_exception
mainloop_abort_on_exception=
: With the exception that it is ignored to set value on the
: slave interpreter, same to the TclTkLib module method with
: the same name.
_unset_variable(var_name)
_unset_variable2(var_name, index_name)
: Remove a variable. If specified a index_name (see also
: the PARSE_VARNAME flag), remove the index_name element.
_get_global_var(var_name)
_get_global_var2(var_name, index_name)
_set_global_var(var_name, value)
_set_global_var2(var_name, index_name, value)
_unset_global_var(var_name)
_unset_global_var2(var_name, index_name)
: Call the associated method with the flag argument
: (GLOBAL_ONLY | LEAVE_ERR_MSG).
_split_tklist(str)
: Split the argument with Tcl/Tk's library function and
: get an array as a list of Tcl list elements.
_merge_tklist(str, str, ... )
: Get a Tcl's list string from arguments with a Tcl/Tk's
: library function. Each arguemnt is converted to a valid
: Tcl list element.
_conv_listelement(str)
: Convert the argument to a valid Tcl list element with
: Tcl/Tk's library function.
mainloop
mainloop_watchdog
: If on the slave interpreter, never start an eventloop and
: returns nil.
: With the exception that, same to the TclTkLib module method
: with the same name.
do_one_event
: With the exception that the argument is forced to set
: DONT_WAIT flag on the slave interpreter, same to
: TclTkLib#do_one_event.
set_eventloop_tick
get_eventloop_tick
set_no_event_wait
get_no_event_wait
set_eventloop_weight
get_eventloop_weight
mainloop_abort_on_exception
mainloop_abort_on_exception=
: With the exception that it is ignored to set value on the
: slave interpreter, same to the TclTkLib module method with
: the same name.
class TkCallbackBreak < StandardError
class TkCallbackContinue < StandardError
: They are exception classes to break or continue the Tk callback
: operation.
: If raise TkCallbackBreak on the callback procedure, Ruby returns
: 'break' code to Tk interpreter (Then the Tk interpreter will
: break the operation for the current event).
: If raise TkCallbackContinue, returns 'continue' code (Then the Tk
: interpreter will break the operateion for the current bindtag and
: starts the operation for the next buindtag for the current event).
: They are exception classes to break or continue the Tk callback
: operation.
: If raise TkCallbackBreak on the callback procedure, Ruby returns
: 'break' code to Tk interpreter (Then the Tk interpreter will
: break the operation for the current event).
: If raise TkCallbackContinue, returns 'continue' code (Then the Tk
: interpreter will break the operateion for the current bindtag and
: starts the operation for the next buindtag for the current event).
(eof)

View File

@ -1,5 +1,5 @@
(tof)
2003/10/17 Hidetoshi NAGAI
2004/03/28 Hidetoshi NAGAI
本ドキュメントには古い tcltk ライブラリtcltklib ライブラリの説明
が含まれていますが,その記述内容は古いものとなっています.
@ -175,6 +175,52 @@ require "tcltklib"
: 処理対象イベントが存在しない場合に,イベント発生を待たず
: に do_one_event を終了 ( false を返す ) する
モジュール TclTkLib::VarAccessFlag
: _get_variable などでのフラグを指定するためのもの.フラグに
: は以下の定数を OR で連結して与える.
定数 NONE
: 値は 0 で,何もフラグを指定していないのに等しい.
定数 GLOBAL_ONLY
: 通常,変数の検索はまず手続き呼び出しを行ったレベルで検
: 索し,次に現在の名前空間で検索,最後にグローバル空間で
: 検索を行う.しかし,このフラグが指定された場合には,グ
: ローバル空間でのみ検索する.
: もし GLOBAL_ONLY と NAMESPACE_ONLY とが両方指定された場
: 合にはGLOBAL_ONLY の指定は無視される.
定数 NAMESPACE_ONLY
: このフラグが指定された場合には,現在の名前空間でのみ変
: 数の検索を行うGLOBAL_ONLY の説明も参照すること.
定数 LEAVE_ERR_MSG
: 変数アクセスにおいてエラーが発生した場合,このフラグが
: 指定されていれば,実行結果として Tcl インタープリタにエ
: ラーメッセージが残される.このフラグが指定されていなけ
: れば,エラーメッセージは一切残されない.
定数 APPEND_VALUE
: このフラグが指定されていた場合,変数の値を置き換えので
: はなく,現在の値に代入値が追加 (append; 文字列連結) さ
: れる.変数が未定義あった場合,このフラグは無視される.
定数 LIST_ELEMENT
: このフラグが指定されていた場合,代入値はまず Tcl のリス
: ト要素として適切となるように変換される.代入値がリスト
: (またはサブリスト) の最初の要素となるのでない限り,代入
: 値の直前には空白文字が追加される.
定数 PARSE_VARNAME
: _set_variable などの呼び出しにおいてこのフラグが指定さ
: れていた場合var_name 引数が連想配列名と要素名とを両方
: 含む可能性がある (開き括弧を含み,閉じ括弧で終わる) こ
: とを示す.その場合,括弧の間が要素名指定,最初の開き括
: 弧までが連想配列名として扱われる_set_variable2 などで
: このフラグを指定する場合,連想配列名と要素名は var_name
: から抽出されるはずであるからindex_name 引数は nil と
: せねばならない.
モジュールメソッド
mainloop(check_root = true)
: イベントループを起動するcheck_root が true であれば,
@ -277,6 +323,26 @@ require "tcltklib"
: ので,この値は現在 Tk の機能が有効であるインタープリタの総
: 数に等しい.
_merge_tklist(str, str, ... )
: Tcl/Tk のライブラリ関数を使って,引数の文字列がそれぞれ
: 正しく一つのリスト要素となるように連結した文字列を返す.
_conv_listelement(str)
: Tcl/Tk のライブラリ関数を使って,引数の文字列が Tcl の
: 一つのリスト要素として適切な表現になるように変換した文
: 字列を返す.
_toUTF8(str, encoding)
_fromUTF8(str, encoding)
: Tcl/Tk が内蔵している UTF8 変換処理を呼び出す.
_subst_UTF_backslash(str)
_subst_Tcl_backslash(str)
: Tcl のルールでバックスラッシュ記法 ( \uhhhh による
: Unicode 文字表現を含む ) を解析する.
: _subst_Tcl_backslash はすべてのバックスラッシュ記法を
: 置き換えるのに対し_subst_UTF_backslash は \uhhhh
: による Unicode 文字表現だけを置き換える.
クラス TclTkIp
クラスメソッド
@ -373,6 +439,52 @@ require "tcltklib"
_return_value
: 直前の Tcl/Tk 上での評価の実行結果としての戻り値を返す.
_get_variable(var_name, flag)
_get_variable2(var_name, index_name, flag)
: Tcl/Tk 上の var という変数名の変数の値を返す.
: もし index_name が指定 (PARSE_VARNAME フラグの説明も参照)
: された場合は連想配列 var_name の index_name の要素を返す.
: flag には変数を検索する際の条件を指定するflag に与える
: 値はモジュール TclTkLib::VarAccessFlag を参照すること.
_set_variable(var_name, value, flag)
_set_variable2(var_name, index_name, value, flag)
: Tcl/Tk 上の var という変数名の変数に値を設定する.
: もし index_name が指定 (PARSE_VARNAME フラグの説明も参照)
: された場合は連想配列 var_name の index_name の要素を設定
: する.
: flag には変数を検索する際の条件を指定するflag に与える
: 値はモジュール TclTkLib::VarAccessFlag を参照すること.
_unset_variable(var_name)
_unset_variable2(var_name, index_name)
: Tcl/Tk 上の var_name という変数名の変数を消去する.
: もし index_name が指定 (PARSE_VARNAME フラグの説明も参照)
: された場合は連想配列 var_name から index_name の要素だけ
: を消去する.
_get_global_var(var_name)
_get_global_var2(var_name, index_name)
_set_global_var(var_name, value)
_set_global_var2(var_name, index_name, value)
_unset_global_var(var_name)
_unset_global_var2(var_name, index_name)
: それぞれ,対応する変数アクセスメソッドの flag に対して
: (GLOBAL_ONLY | LEAVE_ERR_MSG) を与えたもの.
_split_tklist(str)
: Tcl/Tk のライブラリ関数を使って,文字列 str をリストに
: 分割する (文字列の配列として返す)
_merge_tklist(str, str, ... )
: Tcl/Tk のライブラリ関数を使って,引数の文字列がそれぞれ
: 正しく一つのリスト要素となるように連結した文字列を返す.
_conv_listelement(str)
: Tcl/Tk のライブラリ関数を使って,引数の文字列が Tcl の
: 一つのリスト要素として適切な表現になるように変換した文
: 字列を返す.
mainloop
mainloop_watchdog
: スレーブ IP の場合にはイベントループを起動せずに nil を返す.

View File

@ -8,7 +8,7 @@ some or all of the following options.
--with-tcllib=<libname> (e.g. libtcl8.3.so ==> --with-tcllib=tcl8.3)
--with-tklib=<libname> (e.g. libtk8.3.so ==> --with-tklib=tk8.3)
--enable_tcltk_stubs (if you force to enable stubs)
--enable-tcltk_stubs (if you force to enable stubs)
--with-tcl-dir=<path>
equal to "--with-tcl-include=<path>/include --with-tcl-lib=<path>/lib"

View File

@ -0,0 +1,54 @@
#! /usr/local/bin/ruby
require "tk"
def drawlines()
print Time.now, "\n"
for j in 0 .. 99
print "*"
$stdout.flush
if (j & 1) != 0
col = "blue"
else
col = "red"
end
for i in 0 .. 99
# $a.create(TkcLine, i, 0, 0, 500 - i, "fill"=>col)
end
end
print Time.now, "\n"
for j in 0 .. 99
print "*"
$stdout.flush
if (j & 1) != 0
col = "blue"
else
col = "red"
end
for i in 0 .. 99
$a.create(TkcLine, i, 0, 0, 500 - i, "fill"=>col)
end
end
print Time.now, "\n"
# Tk.root.destroy
end
$a = TkCanvas.new{
height(500)
width(500)
}
$b = TkButton.new{
text("draw")
command(proc{drawlines()})
}
TkPack.configure($a, $b, {"side"=>"left"})
Tk.mainloop
# eof

View File

@ -0,0 +1,54 @@
#! /usr/local/bin/ruby
require "tk"
def drawlines()
print Time.now, "\n"
for j in 0 .. 99
print "*"
$stdout.flush
if (j & 1) != 0
col = "blue"
else
col = "red"
end
for i in 0 .. 99
# TkCore::INTERP.__invoke($a.path, "create", "line", i.to_s, '0', '0', (500 - i).to_s, "-fill", col)
end
end
print Time.now, "\n"
for j in 0 .. 99
print "*"
$stdout.flush
if (j & 1) != 0
col = "blue"
else
col = "red"
end
for i in 0 .. 99
TkCore::INTERP.__invoke($a.path, "create", "line", i.to_s, '0', '0', (500 - i).to_s, "-fill", col)
end
end
print Time.now, "\n"
# Tk.root.destroy
end
$a = TkCanvas.new{
height(500)
width(500)
}
$b = TkButton.new{
text("draw")
command(proc{drawlines()})
}
TkPack.configure($a, $b, {"side"=>"left"})
Tk.mainloop
# eof

View File

@ -2,7 +2,9 @@
require 'mkmf'
if RUBY_PLATFORM !~ /mswin32|mingw|cygwin|bccwin32/
is_win32 = (/mswin32|mingw|cygwin|bccwin32/ =~ RUBY_PLATFORM)
unless is_win32
have_library("nsl", "t_open")
have_library("socket", "socket")
have_library("dl", "dlopen")
@ -25,7 +27,7 @@ def find_tcl(tcllib, stubs)
elsif find_library("tcl", func, *paths)
true
else
%w[8.4 8.3 8.2 8.0 7.6].find { |ver|
%w[8.5 8.4 8.3 8.2 8.1 8.0 7.6].find { |ver|
find_library("tcl#{ver}", func, *paths) or
find_library("tcl#{ver.delete('.')}", func, *paths)
}
@ -40,7 +42,7 @@ def find_tk(tklib, stubs)
elsif find_library("tk", func, *paths)
true
else
%w[8.4 8.3 8.2 8.0 4.2].find { |ver|
%w[8.5 8.4 8.3 8.2 8.1 8.0 4.2].find { |ver|
find_library("tk#{ver}", func, *paths) or
find_library("tk#{ver.delete('.')}", func, *paths)
}
@ -48,11 +50,73 @@ def find_tk(tklib, stubs)
end
if have_header("tcl.h") && have_header("tk.h") &&
(/mswin32|mingw|cygwin|bccwin32/ =~ RUBY_PLATFORM || find_library("X11", "XOpenDisplay",
"/usr/X11/lib", "/usr/lib/X11", "/usr/X11R6/lib", "/usr/openwin/lib")) &&
(is_win32 || find_library("X11", "XOpenDisplay",
"/usr/X11/lib", "/usr/lib/X11", "/usr/X11R6/lib", "/usr/openwin/lib")) &&
find_tcl(tcllib, stubs) &&
find_tk(tklib, stubs)
$CPPFLAGS += ' -DUSE_TCL_STUBS -DUSE_TK_STUBS' if stubs
$CPPFLAGS += ' -D_WIN32' if /cygwin/ =~ RUBY_PLATFORM
create_makefile("tcltklib")
pthread_enabled = macro_defined?('HAVE_LIBPTHREAD', '#include "ruby.h"')
if try_run(<<EOF)
#include <tcl.h>
static Tcl_ThreadDataKey dataKey;
int main() { exit((Tcl_GetThreadData(&dataKey, 1) == dataKey)? 1: 0); }
EOF
tcl_enable_thread = true
else
tcl_enable_thread = false
end
unless pthread_enabled
if tcl_enable_thread
# ruby -> disable && tcl -> enable
puts(%Q'\
*****************************************************************************
**
** PTHREAD SUPPORT MODE ERRROR:
**
** Ruby is not compiled with --enable-pthread, but your Tcl/Tk
** libararies seems to be compiled with "pthread support". This
** combination possibly cause "Hang-up" or "Segmentation Fault"
** frequently when Ruby/Tk is working. We NEVER recommend you to
** create the library under such combination of pthread support.
**
** Please recompile Ruby with "--enable-pthread" configure option
** or recompile Tcl/Tk with "--disable-threads" configure option.
**
*****************************************************************************
')
else
# ruby -> disable && tcl -> disable
create_makefile("tcltklib")
end
else
unless tcl_enable_thread
# ruby -> enable && tcl -> disable
puts(%Q'\
*****************************************************************************
**
** PTHREAD SUPPORT MODE WARNING:
**
** Ruby is compiled with --enable-pthread, but your Tcl/Tk libraries
** seems to be compiled without "pthread support". Although You can
** create tcltklib library, this combination may cause memory trouble
** (e.g. "Hang-up" or "Segmentation Fault"). If you have no reason you
** must have to keep current pthread support status, we recommend you
** to make both or neither libraries to support pthread.
**
** If you want change the status of pthread support, please recompile
** Ruby without "--enable-pthread" configure option or recompile Tcl/Tk
** with "--enable-threads" configure option (if your Tcl/Tk is later
** than Tcl/Tk8.1).
**
*****************************************************************************
')
end
# ruby -> enable && tcl -> enable/disable
create_makefile("tcltklib")
end
end

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
MANIFEST
README.1st
README.fork
extconf.rb
depend
tkutil.c
@ -22,6 +23,77 @@ lib/tkscrollbox.rb
lib/tktext.rb
lib/tkvirtevent.rb
lib/tkwinpkg.rb
lib/tk/after.rb
lib/tk/autoload.rb
lib/tk/bgerror.rb
lib/tk/bindtag.rb
lib/tk/button.rb
lib/tk/canvas.rb
lib/tk/canvastag.rb
lib/tk/checkbutton.rb
lib/tk/clipboard.rb
lib/tk/clock.rb
lib/tk/composite.rb
lib/tk/console.rb
lib/tk/dialog.rb
lib/tk/encodedstr.rb
lib/tk/entry.rb
lib/tk/event.rb
lib/tk/font.rb
lib/tk/frame.rb
lib/tk/grid.rb
lib/tk/image.rb
lib/tk/itemfont.rb
lib/tk/kinput.rb
lib/tk/label.rb
lib/tk/labelframe.rb
lib/tk/listbox.rb
lib/tk/macpkg.rb
lib/tk/menu.rb
lib/tk/menubar.rb
lib/tk/message.rb
lib/tk/mngfocus.rb
lib/tk/msgcat.rb
lib/tk/namespace.rb
lib/tk/optiondb.rb
lib/tk/pack.rb
lib/tk/package.rb
lib/tk/palette.rb
lib/tk/panedwindow.rb
lib/tk/place.rb
lib/tk/radiobutton.rb
lib/tk/root.rb
lib/tk/scale.rb
lib/tk/scrollable.rb
lib/tk/scrollbar.rb
lib/tk/scrollbox.rb
lib/tk/selection.rb
lib/tk/spinbox.rb
lib/tk/tagfont.rb
lib/tk/text.rb
lib/tk/textimage.rb
lib/tk/textmark.rb
lib/tk/texttag.rb
lib/tk/textwindow.rb
lib/tk/timer.rb
lib/tk/toplevel.rb
lib/tk/txtwin_abst.rb
lib/tk/validation.rb
lib/tk/variable.rb
lib/tk/virtevent.rb
lib/tk/winfo.rb
lib/tk/winpkg.rb
lib/tk/wm.rb
lib/tk/xim.rb
sample/binding_sample.rb
sample/bindtag_sample.rb
sample/binstr_usage.rb
sample/btn_with_frame.rb
sample/encstr_usage.rb
sample/iso2022-kr.txt
sample/propagate.rb
sample/resource.en
sample/resource.ja
sample/safe-tk.rb
sample/tkalignbox.rb
sample/tkballoonhelp.rb
@ -33,20 +105,22 @@ sample/tkfrom.rb
sample/tkhello.rb
sample/tkline.rb
sample/tkmenubutton.rb
sample/tkmsgcat-load_rb.rb
sample/tkmsgcat-load_rb2.rb
sample/tkmsgcat-load_tk.rb
sample/tkmulticolumnlist.rb
sample/tkmultilistbox.rb
sample/tkmultilistframe.rb
sample/tkoptdb-safeTk.rb
sample/tkoptdb.rb
sample/tktextframe.rb
sample/resource.ja
sample/resource.en
sample/tktimer.rb
sample/tktimer2.rb
sample/tktimer3.rb
sample/demos-en/ChangeLog
sample/demos-en/ChangeLog.prev
sample/demos-en/README
sample/demos-en/README.1st
sample/demos-en/README.tkencoding
sample/demos-en/arrow.rb
sample/demos-en/bind.rb
@ -55,6 +129,7 @@ sample/demos-en/browse1
sample/demos-en/browse2
sample/demos-en/button.rb
sample/demos-en/check.rb
sample/demos-en/check2.rb
sample/demos-en/clrpick.rb
sample/demos-en/colors.rb
sample/demos-en/cscroll.rb
@ -71,6 +146,7 @@ sample/demos-en/entry2.rb
sample/demos-en/entry3.rb
sample/demos-en/filebox.rb
sample/demos-en/floor.rb
sample/demos-en/floor2.rb
sample/demos-en/form.rb
sample/demos-en/hello
sample/demos-en/hscale.rb
@ -78,19 +154,6 @@ sample/demos-en/icon.rb
sample/demos-en/image1.rb
sample/demos-en/image2.rb
sample/demos-en/image3.rb
sample/demos-en/images/earth.gif
sample/demos-en/images/earthris.gif
sample/demos-en/images/face.xbm
sample/demos-en/images/flagdown.xbm
sample/demos-en/images/flagup.xbm
sample/demos-en/images/gray25.xbm
sample/demos-en/images/grey.25
sample/demos-en/images/grey.5
sample/demos-en/images/letters.xbm
sample/demos-en/images/noletter.xbm
sample/demos-en/images/pattern.xbm
sample/demos-en/images/tcllogo.gif
sample/demos-en/images/teapot.ppm
sample/demos-en/items.rb
sample/demos-en/ixset
sample/demos-en/ixset2
@ -107,6 +170,7 @@ sample/demos-en/plot.rb
sample/demos-en/puzzle.rb
sample/demos-en/radio.rb
sample/demos-en/radio2.rb
sample/demos-en/radio3.rb
sample/demos-en/rmt
sample/demos-en/rolodex
sample/demos-en/rolodex-j
@ -123,6 +187,7 @@ sample/demos-en/text.rb
sample/demos-en/timer
sample/demos-en/tkencoding.rb
sample/demos-en/twind.rb
sample/demos-en/twind2.rb
sample/demos-en/unicodeout.rb
sample/demos-en/vscale.rb
sample/demos-en/widget
@ -134,6 +199,7 @@ sample/demos-jp/browse1
sample/demos-jp/browse2
sample/demos-jp/button.rb
sample/demos-jp/check.rb
sample/demos-jp/check2.rb
sample/demos-jp/clrpick.rb
sample/demos-jp/colors.rb
sample/demos-jp/cscroll.rb
@ -150,6 +216,7 @@ sample/demos-jp/entry2.rb
sample/demos-jp/entry3.rb
sample/demos-jp/filebox.rb
sample/demos-jp/floor.rb
sample/demos-jp/floor2.rb
sample/demos-jp/form.rb
sample/demos-jp/hello
sample/demos-jp/hscale.rb
@ -157,19 +224,6 @@ sample/demos-jp/icon.rb
sample/demos-jp/image1.rb
sample/demos-jp/image2.rb
sample/demos-jp/image3.rb
sample/demos-jp/images/earth.gif
sample/demos-jp/images/earthris.gif
sample/demos-jp/images/face.bmp
sample/demos-jp/images/flagdown.bmp
sample/demos-jp/images/flagup.bmp
sample/demos-jp/images/gray25.bmp
sample/demos-jp/images/grey.25
sample/demos-jp/images/grey.5
sample/demos-jp/images/letters.bmp
sample/demos-jp/images/noletter.bmp
sample/demos-jp/images/pattern.bmp
sample/demos-jp/images/tcllogo.gif
sample/demos-jp/images/teapot.ppm
sample/demos-jp/items.rb
sample/demos-jp/ixset
sample/demos-jp/ixset2
@ -186,6 +240,7 @@ sample/demos-jp/plot.rb
sample/demos-jp/puzzle.rb
sample/demos-jp/radio.rb
sample/demos-jp/radio2.rb
sample/demos-jp/radio3.rb
sample/demos-jp/rmt
sample/demos-jp/rolodex
sample/demos-jp/rolodex-j
@ -200,6 +255,51 @@ sample/demos-jp/tcolor
sample/demos-jp/text.rb
sample/demos-jp/timer
sample/demos-jp/twind.rb
sample/demos-jp/twind2.rb
sample/demos-jp/unicodeout.rb
sample/demos-jp/vscale.rb
sample/demos-jp/widget
sample/images/earth.gif
sample/images/earthris.gif
sample/images/face.xbm
sample/images/flagdown.xbm
sample/images/flagup.xbm
sample/images/gray25.xbm
sample/images/grey.25
sample/images/grey.5
sample/images/letters.xbm
sample/images/noletter.xbm
sample/images/pattern.xbm
sample/images/tcllogo.gif
sample/images/teapot.ppm
sample/msgs_rb/README
sample/msgs_rb/cs.msg
sample/msgs_rb/de.msg
sample/msgs_rb/el.msg
sample/msgs_rb/en.msg
sample/msgs_rb/en_gb.msg
sample/msgs_rb/eo.msg
sample/msgs_rb/es.msg
sample/msgs_rb/fr.msg
sample/msgs_rb/it.msg
sample/msgs_rb/ja.msg
sample/msgs_rb/nl.msg
sample/msgs_rb/pl.msg
sample/msgs_rb/ru.msg
sample/msgs_rb2/README
sample/msgs_rb2/de.msg
sample/msgs_rb2/ja.msg
sample/msgs_tk/README
sample/msgs_tk/cs.msg
sample/msgs_tk/de.msg
sample/msgs_tk/el.msg
sample/msgs_tk/en.msg
sample/msgs_tk/en_gb.msg
sample/msgs_tk/eo.msg
sample/msgs_tk/es.msg
sample/msgs_tk/fr.msg
sample/msgs_tk/it.msg
sample/msgs_tk/ja.msg
sample/msgs_tk/nl.msg
sample/msgs_tk/pl.msg
sample/msgs_tk/ru.msg

29
ext/tk/README.fork Normal file
View File

@ -0,0 +1,29 @@
Ruby/Tk does NOT support forking the process on which Tk interpreter
is running (unless NEVER control Tk interpreter under the forked child
process). In the library 'tk.rb', a Tk interpreter is initialized.
Therefore, if you want running Tk under a child process, please call
"require 'tk'" in the child process.
For example, the following sample1 will NOT work, and sample2 will
work properly.
---<sample1: NOT work>---------------------------------------
require 'tk' ## init Tk interpreter under parent process
exit! if fork ## exit parent process
## child process
TkButton.new(:text=>'QUIT', :command=>proc{exit}).pack
Tk.mainloop
-------------------------------------------------------------
---<sample2: will work>--------------------------------------
exit! if fork ## exit main process
## child process
require 'tk' ## init Tk interpreter under child process
TkButton.new(:text=>'QUIT', :command=>proc{exit}).pack
Tk.mainloop
-------------------------------------------------------------
2004/04/20 Hidetoshi NAGAI

View File

@ -1,2 +1,3 @@
require 'mkmf'
$preload = ["tcltklib"]
create_makefile("tkutil")

View File

@ -3,6 +3,7 @@
# by Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
require 'tcltklib'
require 'tkutil'
require 'thread'
################################################
@ -13,7 +14,6 @@ TclTkLib.mainloop_abort_on_exception = true
# TclTkLib.mainloop_abort_on_exception = nil
################################################
# exceptiopn to treat the return value from IP
class MultiTkIp_OK < Exception
@ -48,12 +48,15 @@ class MultiTkIp
######################################
@@CB_ENTRY_CLASS = Class.new{|c|
@@CB_ENTRY_CLASS = Class.new(TkCallbackEntry){|c|
def initialize(ip, cmd)
@ip = ip
@cmd = cmd
end
attr_reader :ip, :cmd
def inspect
cmd.inspect
end
def call(*args)
begin
unless @ip.deleted?
@ -68,8 +71,11 @@ class MultiTkIp
######################################
def _keys2opts(keys)
keys.collect{|k,v| "-#{k} #{v}"}.join(' ')
def _keys2opts(src_keys)
return nil if src_keys == nil
keys = {}; src_keys.each{|k, v| keys[k.to_s] = v}
#keys.collect{|k,v| "-#{k} #{v}"}.join(' ')
keys.collect{|k,v| "-#{k} #{TclTkLib._conv_listelement(TkComm::_get_eval_string(v))}"}.join(' ')
end
private :_keys2opts
@ -136,10 +142,11 @@ class MultiTkIp
rescue SystemExit
# delete IP
unless @interp.deleted?
if @interp._invoke('info', 'command', '.') != ""
@interp._invoke('destroy', '.')
end
@interp.delete
# if @interp._invoke('info', 'command', '.') != ""
# @interp._invoke('destroy', '.')
# end
# @interp.delete
@interp._eval_without_enc('exit')
end
_check_and_return(thread, MultiTkIp_OK.new(nil))
break
@ -200,14 +207,14 @@ class MultiTkIp
@@DEFAULT_MASTER = self.allocate
@@DEFAULT_MASTER.instance_eval{
@encoding = [].taint
@tk_windows = {}.taint
@tk_table_list = [].taint
@slave_ip_tbl = {}.taint
@slave_ip_top = {}.taint
unless keys.kind_of? Hash
fail ArgumentError, "expecting a Hash object for the 2nd argument"
end
@ -274,23 +281,28 @@ class MultiTkIp
tk_opts = {}
keys.each{|k,v|
if k.to_s == 'name'
k_str = k.to_s
if k_str == 'name'
name = v
elsif k.to_s == 'safe'
elsif k_str == 'safe'
safe = v
elsif SAFE_OPT_LIST.member?(k.to_s)
safe_opts[k] = v
elsif SAFE_OPT_LIST.member?(k_str)
safe_opts[k_str] = v
else
tk_opts[k] = v
tk_opts[k_str] = v
end
}
[name, safe, safe_opts, tk_opts]
if keys['without_tk'] || keys[:without_tk]
[name, safe, safe_opts, nil]
else
[name, safe, safe_opts, tk_opts]
end
end
private :_parse_slaveopts
def _create_slave_ip_name
name = SLAVE_IP_ID.join
name = SLAVE_IP_ID.join('')
SLAVE_IP_ID[1].succ!
name
end
@ -388,14 +400,18 @@ class MultiTkIp
# procedure to delete slave interpreter
slave_delete_proc = proc{
unless slave_ip.deleted?
if slave_ip._invoke('info', 'command', '.') != ""
slave_ip._invoke('destroy', '.')
end
slave_ip.delete
#if slave_ip._invoke('info', 'command', '.') != ""
# slave_ip._invoke('destroy', '.')
#end
#slave_ip.delete
slave_ip._eval_without_enc('exit')
end
top.destroy if top.winfo_exist?
}
tag = TkBindTag.new.bind('Destroy', slave_delete_proc)
top.bindtags = top.bindtags.unshift(tag)
# create control frame
TkFrame.new(top, :bg=>'red', :borderwidth=>3, :relief=>'ridge') {|fc|
fc.bindtags = fc.bindtags.unshift(tag)
@ -421,23 +437,45 @@ class MultiTkIp
# return keys
loadTk_keys['use'] = TkWinfo.id(c)
loadTk_keys
[loadTk_keys, top.path]
end
private :__create_safetk_frame
def __create_safe_slave_obj(safe_opts, app_name, tk_opts)
# safe interpreter
# at present, not enough support for '-deleteHook' option
ip_name = _create_slave_ip_name
slave_ip = @interp.create_slave(ip_name, true)
@interp._eval("::safe::interpInit #{ip_name} "+_keys2opts(safe_opts))
tk_opts = __check_safetk_optkeys(tk_opts)
unless tk_opts.key?('use')
tk_opts = __create_safetk_frame(slave_ip, ip_name, app_name, tk_opts)
end
slave_ip._invoke('set', 'argv0', app_name) if app_name.kind_of?(String)
@interp._eval("::safe::loadTk #{ip_name} #{_keys2opts(tk_opts)}")
@slave_ip_tbl[ip_name] = slave_ip
@interp._eval("::safe::interpInit #{ip_name}")
slave_ip._invoke('set', 'argv0', app_name) if app_name.kind_of?(String)
if tk_opts
tk_opts = __check_safetk_optkeys(tk_opts)
if tk_opts.key?('use')
@slave_ip_top[ip_name] = ''
else
tk_opts, top_path = __create_safetk_frame(slave_ip, ip_name, app_name,
tk_opts)
@slave_ip_top[ip_name] = top_path
end
@interp._eval("::safe::loadTk #{ip_name} #{_keys2opts(tk_opts)}")
else
@slave_ip_top[ip_name] = nil
end
if safe_opts.key?('deleteHook') || safe_opts.key?(:deleteHook)
@interp._eval("::safe::interpConfigure #{ip_name} " +
_keys2opts(safe_opts))
else
@interp._eval("::safe::interpConfigure #{ip_name} " +
_keys2opts(safe_opts) + '-deleteHook {' +
TkComm._get_eval_string(proc{|slave|
self._default_delete_hook(slave)
}) + '}')
end
[slave_ip, ip_name]
end
@ -481,15 +519,15 @@ class MultiTkIp
fail ArgumentError, "expecting a Hash object for the 2nd argument"
end
@encoding = []
@tk_windows = {}
@tk_table_list = []
@slave_ip_tbl = {}
@slave_ip_top = {}
@encoding.taint unless @encoding.tainted?
@tk_windows.taint unless @tk_windows.tainted?
@tk_table_list.taint unless @tk_table_list.tainted?
@slave_ip_tbl.taint unless @slave_ip_tbl.tainted?
@slave_ip_top.taint unless @slave_ip_top.tainted?
name, safe, safe_opts, tk_opts = _parse_slaveopts(keys)
@ -532,6 +570,34 @@ class MultiTkIp
self.freeze # defend against modification
end
######################################
def _default_delete_hook(slave)
if @slave_ip_top[slave].kind_of?(String)
# call default hook of safetk.tcl (ignore exceptions)
if @slave_ip_top[slave] == ''
begin
@interp._eval("::safe::disallowTk #{slave}")
rescue
warn("Waring: fail to call '::safe::disallowTk'") if $DEBUG
end
else # toplevel path
begin
@interp._eval("::safe::tkDelete {} #{@slave_ip_top[slave]} #{slave}")
rescue
warn("Waring: fail to call '::safe::tkDelete'") if $DEBUG
begin
@interp._eval("destroy #{@slave_ip_top[slave]}")
rescue
warn("Waring: fail to destroy toplevel") if $DEBUG
end
end
end
end
@slave_ip_tbl.delete(slave)
@slave_ip_top.delete(slave)
end
end
@ -796,6 +862,10 @@ class MultiTkIp
rescue SystemExit
# exit IP
warn("Warning: "+ $! + " on " + self.inspect) if $DEBUG
begin
self._eval_without_enc('exit')
rescue Exception
end
self.delete
ret = nil
rescue Exception => e
@ -823,6 +893,10 @@ class MultiTkIp
rescue SystemExit
# exit IP
warn("Warning: " + $! + " on " + self.inspect) if $DEBUG
begin
self._eval_without_enc('exit')
rescue Exception
end
self.delete
rescue Exception => e
# others --> warning
@ -868,10 +942,12 @@ class << MultiTkIp
__getip.do_one_event(flag)
end
def mainloop_abort_on_exception
__getip.mainloop_abort_on_exception
# __getip.mainloop_abort_on_exception
TclTkLib.mainloop_abort_on_exception
end
def mainloop_abort_on_exception=(mode)
__getip.mainloop_abort_on_exception=(mode)
# __getip.mainloop_abort_on_exception=(mode)
TclTkLib.mainloop_abort_on_exception=(mode)
end
def set_eventloop_tick(tick)
__getip.set_eventloop_tick(tick)
@ -919,6 +995,22 @@ class << MultiTkIp
__getip._invoke(*args)
end
def _eval_without_enc(str)
__getip._eval_without_enc(str)
end
def _invoke_without_enc(*args)
__getip._invoke_without_enc(*args)
end
def _eval_with_enc(str)
__getip._eval_with_enc(str)
end
def _invoke_with_enc(*args)
__getip._invoke_with_enc(*args)
end
def _toUTF8(str, encoding)
__getip._toUTF8(str, encoding)
end
@ -938,6 +1030,54 @@ class << MultiTkIp
def _return_value
__getip._return_value
end
def _get_variable(var, flag)
__getip._get_variable(var, flag)
end
def _get_variable2(var, idx, flag)
__getip._get_variable2(var, idx, flag)
end
def _set_variable(var, value, flag)
__getip._set_variable(var, value, flag)
end
def _set_variable2(var, idx, value, flag)
__getip._set_variable2(var, idx, value, flag)
end
def _unset_variable(var, flag)
__getip._unset_variable(var, flag)
end
def _unset_variable2(var, idx, flag)
__getip._unset_variable2(var, idx, flag)
end
def _get_global_var(var)
__getip._get_global_var(var)
end
def _get_global_var2(var, idx)
__getip._get_global_var2(var, idx)
end
def _set_global_var(var, value)
__getip._set_global_var(var, value)
end
def _set_global_var2(var, idx, value)
__getip._set_global_var2(var, idx, value)
end
def _unset_global_var(var)
__getip._unset_global_var(var)
end
def _unset_global_var2(var, idx)
__getip._unset_global_var2(var, idx)
end
def _split_tklist(str)
__getip._split_tklist(str)
end
def _merge_tklist(*args)
__getip._merge_tklist(*args)
end
def _conv_listelement(arg)
__getip._conv_listelement(arg)
end
end
@ -952,12 +1092,12 @@ class << TclTkLib
def do_one_event(flag = TclTkLib::EventFlag::ALL)
MultiTkIp.do_one_event(flag)
end
def mainloop_abort_on_exception
MultiTkIp.mainloop_abort_on_exception
end
def mainloop_abort_on_exception=(mode)
MultiTkIp.mainloop_abort_on_exception=(mode)
end
#def mainloop_abort_on_exception
# MultiTkIp.mainloop_abort_on_exception
#end
#def mainloop_abort_on_exception=(mode)
# MultiTkIp.mainloop_abort_on_exception=(mode)
#end
def set_eventloop_tick(tick)
MultiTkIp.set_eventloop_tick(tick)
end
@ -979,12 +1119,19 @@ class << TclTkLib
def restart
MultiTkIp.restart
end
def _merge_tklist(*args)
MultiTkIp._merge_tklist(*args)
end
def _conv_listelement(arg)
MultiTkIp._conv_listelement(arg)
end
end
# depend on TclTkIp
class MultiTkIp
def mainloop(check_root = true, restart_on_dead = true)
def mainloop(check_root = true, restart_on_dead = false)
return self if self.slave?
unless restart_on_dead
@interp.mainloop(check_root)
@ -1022,6 +1169,10 @@ class MultiTkIp
end
def delete
if safe?
# do 'exit' to call the delete_hook procedure
@interp._eval_without_enc('exit')
end
@interp.delete
end
@ -1041,6 +1192,22 @@ class MultiTkIp
@interp._invoke(*args)
end
def _eval_without_enc(str)
@interp._eval_without_enc(str)
end
def _invoke_without_enc(*args)
@interp._invoke_without_enc(*args)
end
def _eval_with_enc(str)
@interp._eval_with_enc(str)
end
def _invoke_with_enc(*args)
@interp._invoke_with_enc(*args)
end
def _toUTF8(str, encoding)
@interp._toUTF8(str, encoding)
end
@ -1060,6 +1227,54 @@ class MultiTkIp
def _return_value
@interp._return_value
end
def _get_variable(var, flag)
@interp._get_variable(var, flag)
end
def _get_variable2(var, idx, flag)
@interp._get_variable2(var, idx, flag)
end
def _set_variable(var, value, flag)
@interp._set_variable(var, value, flag)
end
def _set_variable2(var, idx, value, flag)
@interp._set_variable2(var, idx, value, flag)
end
def _unset_variable(var, flag)
@interp._unset_variable(var, flag)
end
def _unset_variable2(var, idx, flag)
@interp._unset_variable2(var, idx, flag)
end
def _get_global_var(var)
@interp._get_global_var(var)
end
def _get_global_var2(var, idx)
@interp._get_global_var2(var, idx)
end
def _set_global_var(var, value)
@interp._set_global_var(var, value)
end
def _set_global_var2(var, idx, value)
@interp._set_global_var2(var, idx, value)
end
def _unset_global_var(var)
@interp._unset_global_var(var)
end
def _unset_global_var2(var, idx)
@interp._unset_global_var2(var, idx)
end
def _split_tklist(str)
@interp._split_tklist(str)
end
def _merge_tklist(*args)
@interp._merge_tklist(*args)
end
def _conv_listelement(arg)
@interp._conv_listelement(arg)
end
end
@ -1090,7 +1305,7 @@ class MultiTkIp
else
list.push str[0..i-1]
end
list += tk_split_simplelist(str[i+1..-1])
list += _lst2ary(str[i+1..-1])
list
end
private :_lst2ary
@ -1224,6 +1439,14 @@ class MultiTkIp
self
end
def recursion_limit(slave = '', limit = None)
number(@interp._invoke('interp', 'recursionlimit',
_slavearg(slave), limit))
end
def self.recursion_limit(slave = '', limit = None)
__getip.recursion_limit(slave)
end
def alias_target(aliascmd, slave = '')
@interp._invoke('interp', 'target', _slavearg(slave), aliascmd)
end
@ -1309,35 +1532,94 @@ class MultiTkIp
end
# Safe Base :: manipulating safe interpreter
class MultiTkIp
def safeip_configure(slave, slot, value=None)
# use for '-noStatics' option ==> {statics=>false}
# for '-nestedLoadOk' option ==> {nested=>true}
if slot.kind_of?(Hash)
ip = MultiTkIp.__getip
ip._eval('::safe::interpConfigure ' + @ip_name + ' ' +
hash_kv(slot).join(' '))
else
ip._eval('::safe::interpConfigure ' + @ip_name + ' ' +
"-#{slot} #{_get_eval_string(value)}")
end
self
end
def safeip_configinfo(slot = nil)
ip = MultiTkIp.__getip
ret = {}
if slot
conf = _lst2ary(ip._eval("::safe::interpConfigure " +
@ip_name + " -#{slot}"))
if conf[0] == '-deleteHook'
if conf[1] =~ /^rb_out (c\d+)/
ret[conf[0][1..-1]] = MultiTkIp._tk_cmd_tbl[$1]
else
ret[conf[0][1..-1]] = conf[1]
end
else
ret[conf[0][1..-1]] = conf[1]
end
else
Hash[*_lst2ary(ip._eval("::safe::interpConfigure " +
@ip_name))].each{|k, v|
if k == '-deleteHook'
if v =~ /^rb_out (c\d+)/
ret[k[1..-1]] = MultiTkIp._tk_cmd_tbl[$1]
else
ret[k[1..-1]] = v
end
else
ret[k[1..-1]] = v
end
}
end
ret
end
def safeip_delete(slave)
ip = MultiTkIp.__getip
ip._eval("::safe::interpDelete " + @ip_name)
end
def safeip_add_to_access_path(slave, dir)
ip = MultiTkIp.__getip
ip._eval("::safe::interpAddToAccessPath #{@ip_name} #{dir}")
end
def safeip_find_in_access_path(slave, dir)
ip = MultiTkIp.__getip
ip._eval("::safe::interpFindInAccessPath #{@ip_name} #{dir}")
end
def safeip_set_log_cmd(slave, cmd = Proc.new)
ip = MultiTkIp.__getip
ip._eval("::safe::setLogCmd #{@ip_name} #{_get_eval_string(cmd)}")
end
end
# encoding convert
class MultiTkIp
# from tkencoding.rb by ttate@jaist.ac.jp
alias __eval _eval
alias __invoke _invoke
def encoding
@encoding[0]
@interp.encoding
end
def encoding=(enc)
@encoding[0] = enc
end
def _eval(cmd)
if @encoding[0] != nil
_fromUTF8(__eval(_toUTF8(cmd, @encoding[0])), @encoding[0])
else
__eval(cmd)
end
@interp.encoding = enc
end
def _invoke(*cmds)
if defined?(@encoding[0]) && @encoding[0] != nil
cmds = cmds.collect{|cmd| _toUTF8(cmd, @encoding[0])}
_fromUTF8(__invoke(*cmds), @encoding[0])
else
__invoke(*cmds)
end
def encoding_convertfrom(str, enc=None)
@interp.encoding_convertfrom(str, enc)
end
alias encoding_convert_from encoding_convertfrom
def encoding_convertto(str, enc=None)
@interp.encoding_convertto(str, enc)
end
alias encoding_convert_to encoding_convertto
end

File diff suppressed because it is too large Load Diff

6
ext/tk/lib/tk/after.rb Normal file
View File

@ -0,0 +1,6 @@
#
# tk/after.rb : methods for Tcl/Tk after command
#
# $Id$
#
require 'tk/timer'

181
ext/tk/lib/tk/autoload.rb Normal file
View File

@ -0,0 +1,181 @@
#
# autoload
#
#######################
# geometry manager
autoload :TkGrid, 'tk/grid'
def TkGrid(*args); TkGrid.configure(*args); end
autoload :TkPack, 'tk/pack'
def TkPack(*args); TkPack.configure(*args); end
autoload :TkPlace, 'tk/place'
def TkPlace(*args); TkPlace.configure(*args); end
#######################
# others
autoload :TkBgError, 'tk/bgerror'
autoload :TkBindTag, 'tk/bindtag'
autoload :TkBindTagAll, 'tk/bindtag'
autoload :TkDatabaseClass, 'tk/bindtag'
autoload :TkButton, 'tk/button'
autoload :TkConsole, 'tk/console'
autoload :TkCanvas, 'tk/canvas'
autoload :TkcTagAccess, 'tk/canvastag'
autoload :TkcTag, 'tk/canvastag'
autoload :TkcTagString, 'tk/canvastag'
autoload :TkcNamedTag, 'tk/canvastag'
autoload :TkcTagAll, 'tk/canvastag'
autoload :TkcTagCurrent, 'tk/canvastag'
autoload :TkcTagGroup, 'tk/canvastag'
autoload :TkCheckButton, 'tk/checkbutton'
autoload :TkCheckbutton, 'tk/checkbutton'
autoload :TkClipboard, 'tk/clipboard'
autoload :TkComposite, 'tk/composite'
autoload :TkConsole, 'tk/console'
autoload :TkDialog, 'tk/dialog'
autoload :TkDialog2, 'tk/dialog'
autoload :TkWarning, 'tk/dialog'
autoload :TkWarning2, 'tk/dialog'
autoload :TkEntry, 'tk/entry'
autoload :TkEvent, 'tk/event'
autoload :TkFont, 'tk/font'
autoload :TkTreatTagFont, 'tk/font'
autoload :TkFrame, 'tk/frame'
autoload :TkImage, 'tk/image'
autoload :TkBitmapImage, 'tk/image'
autoload :TkPhotoImage, 'tk/image'
autoload :TkTreatItemFont, 'tk/itemfont'
autoload :TkKinput, 'tk/kinput'
autoload :TkLabel, 'tk/label'
autoload :TkLabelFrame, 'tk/labelframe'
autoload :TkLabelframe, 'tk/labelframe'
autoload :TkListbox, 'tk/listbox'
autoload :TkMacResource, 'tk/macpkg'
autoload :TkMenu, 'tk/menu'
autoload :TkMenuClone, 'tk/menu'
autoload :TkSystemMenu, 'tk/menu'
autoload :TkSysMenu_Help, 'tk/menu'
autoload :TkSysMenu_System, 'tk/menu'
autoload :TkSysMenu_Apple, 'tk/menu'
autoload :TkMenubutton, 'tk/menu'
autoload :TkOptionMenubutton, 'tk/menu'
autoload :TkMenubar, 'tk/menubar'
autoload :TkMessage, 'tk/message'
autoload :TkManageFocus, 'tk/mngfocus'
autoload :TkMsgCatalog, 'tk/msgcat'
autoload :TkMsgCat, 'tk/msgcat'
autoload :TkNamespace, 'tk/namespace'
autoload :TkOptionDB, 'tk/optiondb'
autoload :TkOption, 'tk/optiondb'
autoload :TkResourceDB, 'tk/optiondb'
autoload :TkPackage, 'tk/package'
autoload :TkPalette, 'tk/palette'
autoload :TkPanedWindow, 'tk/panedwindow'
autoload :TkPanedwindow, 'tk/panedwindow'
autoload :TkRadioButton, 'tk/radiobutton'
autoload :TkRadiobutton, 'tk/radiobutton'
autoload :TkRoot, 'tk/root'
autoload :TkScale, 'tk/scale'
autoload :TkScrollbar, 'tk/scrollbar'
autoload :TkXScrollbar, 'tk/scrollbar'
autoload :TkYScrollbar, 'tk/scrollbar'
autoload :TkScrollbox, 'tk/scrollbox'
autoload :TkSelection, 'tk/selection'
autoload :TkSpinbox, 'tk/spinbox'
autoload :TkTreatTagFont, 'tk/tagfont'
autoload :TkText, 'tk/text'
autoload :TkTextImage, 'tk/textimage'
autoload :TkTextMark, 'tk/textmark'
autoload :TkTextNamedMark, 'tk/textmark'
autoload :TkTextMarkInsert, 'tk/textmark'
autoload :TkTextMarkCurrent, 'tk/textmark'
autoload :TkTextMarkAnchor, 'tk/textmark'
autoload :TkTextTag, 'tk/texttag'
autoload :TkTextNamedTag, 'tk/texttag'
autoload :TkTextTagSel, 'tk/texttag'
autoload :TkTextWindow, 'tk/textwindow'
autoload :TkAfter, 'tk/timer'
autoload :TkTimer, 'tk/timer'
autoload :TkToplevel, 'tk/toplevel'
autoload :TkTextWin, 'tk/txtwin_abst'
autoload :TkValidation, 'tk/validation'
autoload :TkVariable, 'tk/variable'
autoload :TkVarAccess, 'tk/variable'
autoload :TkVirtualEvent, 'tk/virtevent'
autoload :TkWinfo, 'tk/winfo'
autoload :TkWinDDE, 'tk/winpkg'
autoload :TkWinRegistry, 'tk/winpkg'
autoload :TkXIM, 'tk/xim'
#######################
# sub-module of Tk
module Tk
autoload :Clock, 'tk/clock'
autoload :Scrollable, 'tk/scrollable'
autoload :Wm, 'tk/wm'
autoload :EncodedString, 'tk/encodedstr'
def Tk.EncodedString(str, enc = nil); Tk::EncodedString.new(str, enc); end
autoload :BinaryString, 'tk/encodedstr'
def Tk.BinaryString(str); Tk::BinaryString.new(str); end
autoload :UTF8_String, 'tk/encodedstr'
def Tk.UTF8_String(str); Tk::UTF8_String.new(str); end
end

29
ext/tk/lib/tk/bgerror.rb Normal file
View File

@ -0,0 +1,29 @@
#
# tkbgerror -- bgerror ( tkerror ) module
# 1998/07/16 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
#
require 'tk'
module TkBgError
extend Tk
TkCommandNames = ['bgerror'.freeze].freeze
def bgerror(message)
tk_call('bgerror', message)
end
alias tkerror bgerror
alias show bgerror
module_function :bgerror, :tkerror, :show
def set_handler(hdlr = Proc.new) #==> handler :: proc{|msg| ...body... }
tk_call('proc', 'bgerror', 'msg', install_cmd(hdlr) + ' $msg')
end
def set_default
begin
tk_call('rename', 'bgerror', '')
rescue RuntimeError
end
end
module_function :set_handler, :set_default
end

78
ext/tk/lib/tk/bindtag.rb Normal file
View File

@ -0,0 +1,78 @@
#
# tk/bind.rb : control event binding
#
require 'tk'
class TkBindTag
include TkBindCore
#BTagID_TBL = {}
BTagID_TBL = TkCore::INTERP.create_table
Tk_BINDTAG_ID = ["btag".freeze, "00000".taint].freeze
TkCore::INTERP.init_ip_env{ BTagID_TBL.clear }
def TkBindTag.id2obj(id)
BTagID_TBL[id]? BTagID_TBL[id]: id
end
def TkBindTag.new_by_name(name, *args, &b)
return BTagID_TBL[name] if BTagID_TBL[name]
self.new(*args, &b).instance_eval{
BTagID_TBL.delete @id
@id = name
BTagID_TBL[@id] = self
}
end
def initialize(*args, &b)
@id = Tk_BINDTAG_ID.join('')
Tk_BINDTAG_ID[1].succ!
BTagID_TBL[@id] = self
bind(*args, &b) if args != []
end
ALL = self.new_by_name('all')
def name
@id
end
def to_eval
@id
end
def inspect
#Kernel.format "#<TkBindTag: %s>", @id
'#<TkBindTag: ' + @id + '>'
end
end
class TkBindTagAll<TkBindTag
def TkBindTagAll.new(*args, &b)
$stderr.puts "Warning: TkBindTagALL is obsolete. Use TkBindTag::ALL\n"
TkBindTag::ALL.bind(*args, &b) if args != []
TkBindTag::ALL
end
end
class TkDatabaseClass<TkBindTag
def self.new(name, *args, &b)
return BTagID_TBL[name] if BTagID_TBL[name]
super(name, *args, &b)
end
def initialize(name, *args, &b)
@id = name
BTagID_TBL[@id] = self
bind(*args, &b) if args != []
end
def inspect
#Kernel.format "#<TkDatabaseClass: %s>", @id
'#<TkDatabaseClass: ' + @id + '>'
end
end

27
ext/tk/lib/tk/button.rb Normal file
View File

@ -0,0 +1,27 @@
#
# tk/button.rb : treat button widget
#
require 'tk'
require 'tk/label'
class TkButton<TkLabel
TkCommandNames = ['button'.freeze].freeze
WidgetClassName = 'Button'.freeze
WidgetClassNames[WidgetClassName] = self
def create_self(keys)
if keys and keys != None
tk_call_without_enc('button', @path, *hash_kv(keys, true))
else
tk_call_without_enc('button', @path)
end
end
private :create_self
def invoke
_fromUTF8(tk_send_without_enc('invoke'))
end
def flash
tk_send_without_enc('flash')
self
end
end

697
ext/tk/lib/tk/canvas.rb Normal file
View File

@ -0,0 +1,697 @@
#
# tk/canvas.rb - Tk canvas classes
# $Date$
# by Yukihiro Matsumoto <matz@caelum.co.jp>
# $Date$
# by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
#
require 'tk'
require 'tk/canvastag'
require 'tk/itemfont'
require 'tk/scrollable'
module TkTreatCItemFont
include TkTreatItemFont
ItemCMD = ['itemconfigure'.freeze, TkComm::None].freeze
def __conf_cmd(idx)
ItemCMD[idx]
end
def __item_pathname(tagOrId)
if tagOrId.kind_of?(TkcItem) || tagOrId.kind_of?(TkcTag)
self.path + ';' + tagOrId.id.to_s
else
self.path + ';' + tagOrId.to_s
end
end
private :__conf_cmd, :__item_pathname
end
class TkCanvas<TkWindow
include TkTreatCItemFont
include Scrollable
TkCommandNames = ['canvas'.freeze].freeze
WidgetClassName = 'Canvas'.freeze
WidgetClassNames[WidgetClassName] = self
def __destroy_hook__
TkcItem::CItemID_TBL.delete(@path)
end
def create_self(keys)
if keys and keys != None
tk_call_without_enc('canvas', @path, *hash_kv(keys, true))
else
tk_call_without_enc('canvas', @path)
end
end
private :create_self
def tagid(tag)
if tag.kind_of?(TkcItem) || tag.kind_of?(TkcTag)
tag.id
else
tag
end
end
private :tagid
def create(type, *args)
# create a canvas item without creating a TkcItem object
if type.kind_of?(TkcItem)
fail ArgumentError, 'TkcItem class expected for 1st argument'
end
type.create(@path, *args)
end
def addtag(tag, mode, *args)
tk_send_without_enc('addtag', tagid(tag), mode, *args)
self
end
def addtag_above(tagOrId, target)
addtag(tagOrId, 'above', tagid(target))
end
def addtag_all(tagOrId)
addtag(tagOrId, 'all')
end
def addtag_below(tagOrId, target)
addtag(tagOrId, 'below', tagid(target))
end
def addtag_closest(tagOrId, x, y, halo=None, start=None)
addtag(tagOrId, 'closest', x, y, halo, start)
end
def addtag_enclosed(tagOrId, x1, y1, x2, y2)
addtag(tagOrId, 'enclosed', x1, y1, x2, y2)
end
def addtag_overlapping(tagOrId, x1, y1, x2, y2)
addtag(tagOrId, 'overlapping', x1, y1, x2, y2)
end
def addtag_withtag(tagOrId, tag)
addtag(tagOrId, 'withtag', tagid(tag))
end
def bbox(tagOrId, *tags)
list(tk_send_without_enc('bbox', tagid(tagOrId),
*tags.collect{|t| tagid(t)}))
end
def itembind(tag, context, cmd=Proc.new, args=nil)
_bind([path, "bind", tagid(tag)], context, cmd, args)
self
end
def itembind_append(tag, context, cmd=Proc.new, args=nil)
_bind_append([path, "bind", tagid(tag)], context, cmd, args)
self
end
def itembind_remove(tag, context)
_bind_remove([path, "bind", tagid(tag)], context)
self
end
def itembindinfo(tag, context=nil)
_bindinfo([path, "bind", tagid(tag)], context)
end
def canvasx(screen_x, *args)
#tk_tcl2ruby(tk_send_without_enc('canvasx', screen_x, *args))
number(tk_send_without_enc('canvasx', screen_x, *args))
end
def canvasy(screen_y, *args)
#tk_tcl2ruby(tk_send_without_enc('canvasy', screen_y, *args))
number(tk_send_without_enc('canvasy', screen_y, *args))
end
def coords(tag, *args)
if args == []
tk_split_list(tk_send_without_enc('coords', tagid(tag)))
else
tk_send_without_enc('coords', tagid(tag), *(args.flatten))
end
end
def dchars(tag, first, last=None)
tk_send_without_enc('dchars', tagid(tag),
_get_eval_enc_str(first), _get_eval_enc_str(last))
self
end
def delete(*args)
if TkcItem::CItemID_TBL[self.path]
find('withtag', *args).each{|item|
TkcItem::CItemID_TBL[self.path].delete(item.id)
}
end
tk_send_without_enc('delete', *args.collect{|t| tagid(t)})
self
end
alias remove delete
def dtag(tag, tag_to_del=None)
tk_send_without_enc('dtag', tagid(tag), tag_to_del)
self
end
def find(mode, *args)
list(tk_send_without_enc('find', mode, *args)).collect!{|id|
TkcItem.id2obj(self, id)
}
end
def find_above(target)
find('above', tagid(target))
end
def find_all
find('all')
end
def find_below(target)
find('below', tagid(target))
end
def find_closest(x, y, halo=None, start=None)
find('closest', x, y, halo, start)
end
def find_enclosed(x1, y1, x2, y2)
find('enclosed', x1, y1, x2, y2)
end
def find_overlapping(x1, y1, x2, y2)
find('overlapping', x1, y1, x2, y2)
end
def find_withtag(tag)
find('withtag', tag)
end
def itemfocus(tagOrId=nil)
if tagOrId
tk_send_without_enc('focus', tagid(tagOrId))
self
else
ret = tk_send_without_enc('focus')
if ret == ""
nil
else
TkcItem.id2obj(self, ret)
end
end
end
def gettags(tagOrId)
list(tk_send_without_enc('gettags', tagid(tagOrId))).collect{|tag|
TkcTag.id2obj(self, tag)
}
end
def icursor(tagOrId, index)
tk_send_without_enc('icursor', tagid(tagOrId), index)
self
end
def index(tagOrId, index)
number(tk_send_without_enc('index', tagid(tagOrId), index))
end
def insert(tagOrId, index, string)
tk_send_without_enc('insert', tagid(tagOrId), index,
_get_eval_enc_str(string))
self
end
def itemcget(tagOrId, option)
case option.to_s
when 'dash', 'activedash', 'disableddash'
conf = tk_send_without_enc('itemcget', tagid(tagOrId), "-#{option}")
if conf =~ /^[0-9]/
list(conf)
else
conf
end
when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile'
_fromUTF8(tk_send_without_enc('itemcget', tagid(tagOrId), "-#{option}"))
when 'font', 'kanjifont'
#fnt = tk_tcl2ruby(tk_send('itemcget', tagid(tagOrId), "-#{option}"))
fnt = tk_tcl2ruby(_fromUTF8(tk_send_with_enc('itemcget', tagid(tagOrId), '-font')))
unless fnt.kind_of?(TkFont)
fnt = tagfontobj(tagid(tagOrId), fnt)
end
if option.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
# obsolete; just for compatibility
fnt.kanji_font
else
fnt
end
else
tk_tcl2ruby(_fromUTF8(tk_send_without_enc('itemcget', tagid(tagOrId),
"-#{option}")))
end
end
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(tagid(tagOrId), key.dup)
else
_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId),
*hash_kv(key, true)))
end
else
if ( key == 'font' || key == :font ||
key == 'kanjifont' || key == :kanjifont ||
key == 'latinfont' || key == :latinfont ||
key == 'asciifont' || key == :asciifont )
if value == None
tagfontobj(tagid(tagOrId))
else
tagfont_configure(tagid(tagOrId), {key=>value})
end
else
_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId),
"-#{key}", _get_eval_enc_str(value)))
end
end
self
end
# def itemconfigure(tagOrId, key, value=None)
# if key.kind_of? Hash
# tk_send 'itemconfigure', tagid(tagOrId), *hash_kv(key)
# else
# tk_send 'itemconfigure', tagid(tagOrId), "-#{key}", value
# end
# end
# def itemconfigure(tagOrId, keys)
# tk_send 'itemconfigure', tagid(tagOrId), *hash_kv(keys)
# end
def itemconfiginfo(tagOrId, key=nil)
if TkComm::GET_CONFIGINFO_AS_ARRAY
if key
case key.to_s
when 'dash', 'activedash', 'disableddash'
conf = tk_split_simplelist(tk_send_without_enc('itemconfigure', tagid(tagOrId), "-#{key}"))
if conf[3] && conf[3] =~ /^[0-9]/
conf[3] = list(conf[3])
end
if conf[4] && conf[4] =~ /^[0-9]/
conf[4] = list(conf[4])
end
when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile'
conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId), "-#{key}")))
when 'font', 'kanjifont'
conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId),"-#{key}")))
conf[4] = tagfont_configinfo(tagid(tagOrId), conf[4])
else
conf = tk_split_list(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId), "-#{key}")))
end
conf[0] = conf[0][1..-1]
conf
else
ret = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId)))).collect{|conflist|
conf = tk_split_simplelist(conflist)
conf[0] = conf[0][1..-1]
case conf[0]
when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile'
when 'dash', 'activedash', 'disableddash'
if conf[3] && conf[3] =~ /^[0-9]/
conf[3] = list(conf[3])
end
if conf[4] && conf[4] =~ /^[0-9]/
conf[4] = list(conf[4])
end
else
if conf[3]
if conf[3].index('{')
conf[3] = tk_split_list(conf[3])
else
conf[3] = tk_tcl2ruby(conf[3])
end
end
if conf[4]
if conf[4].index('{')
conf[4] = tk_split_list(conf[4])
else
conf[4] = tk_tcl2ruby(conf[4])
end
end
end
conf[1] = conf[1][1..-1] if conf.size == 2 # alias info
conf
}
fontconf = ret.assoc('font')
if fontconf
ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'}
fontconf[4] = tagfont_configinfo(tagid(tagOrId), fontconf[4])
ret.push(fontconf)
else
ret
end
end
else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
if key
case key.to_s
when 'dash', 'activedash', 'disableddash'
conf = tk_split_simplelist(tk_send_without_enc('itemconfigure',
tagid(tagOrId),
"-#{key}"))
if conf[3] && conf[3] =~ /^[0-9]/
conf[3] = list(conf[3])
end
if conf[4] && conf[4] =~ /^[0-9]/
conf[4] = list(conf[4])
end
when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile'
conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId), "-#{key}")))
when 'font', 'kanjifont'
conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId),"-#{key}")))
conf[4] = tagfont_configinfo(tagid(tagOrId), conf[4])
else
conf = tk_split_list(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId), "-#{key}")))
end
key = conf.shift[1..-1]
{ key => conf }
else
ret = {}
tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId)))).each{|conflist|
conf = tk_split_simplelist(conflist)
key = conf.shift[1..-1]
case key
when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile'
when 'dash', 'activedash', 'disableddash'
if conf[2] && conf[2] =~ /^[0-9]/
conf[2] = list(conf[2])
end
if conf[3] && conf[3] =~ /^[0-9]/
conf[3] = list(conf[3])
end
else
if conf[2]
if conf[2].index('{')
conf[2] = tk_split_list(conf[2])
else
conf[2] = tk_tcl2ruby(conf[2])
end
end
if conf[3]
if conf[3].index('{')
conf[3] = tk_split_list(conf[3])
else
conf[3] = tk_tcl2ruby(conf[3])
end
end
end
if conf.size == 1
ret[key] = conf[0][1..-1] # alias info
else
ret[key] = conf
end
}
fontconf = ret['font']
if fontconf
ret.delete('font')
ret.delete('kanjifont')
fontconf[3] = tagfont_configinfo(tagid(tagOrId), fontconf[3])
ret['font'] = fontconf
end
ret
end
end
end
def current_itemconfiginfo(tagOrId, key=nil)
if TkComm::GET_CONFIGINFO_AS_ARRAY
if key
conf = itemconfiginfo(tagOrId, key)
{conf[0] => conf[4]}
else
ret = {}
itemconfiginfo(tagOrId).each{|conf|
ret[conf[0]] = conf[4] if conf.size > 2
}
ret
end
else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
ret = {}
itemconfiginfo(tagOrId, key).each{|k, conf|
ret[k] = conf[-1] if conf.kind_of?(Array)
}
ret
end
end
def lower(tag, below=nil)
if below
tk_send_without_enc('lower', tagid(tag), tagid(below))
else
tk_send_without_enc('lower', tagid(tag))
end
self
end
def move(tag, x, y)
tk_send_without_enc('move', tagid(tag), x, y)
self
end
def postscript(keys)
tk_send("postscript", *hash_kv(keys))
end
def raise(tag, above=nil)
if above
tk_send_without_enc('raise', tagid(tag), tagid(above))
else
tk_send_without_enc('raise', tagid(tag))
end
self
end
def scale(tag, x, y, xs, ys)
tk_send_without_enc('scale', tagid(tag), x, y, xs, ys)
self
end
def scan_mark(x, y)
tk_send_without_enc('scan', 'mark', x, y)
self
end
def scan_dragto(x, y)
tk_send_without_enc('scan', 'dragto', x, y)
self
end
def select(mode, *args)
r = tk_send_without_enc('select', mode, *args)
(mode == 'item')? TkcItem.id2obj(self, r): self
end
def select_adjust(tagOrId, index)
select('adjust', tagid(tagOrId), index)
end
def select_clear
select('clear')
end
def select_from(tagOrId, index)
select('from', tagid(tagOrId), index)
end
def select_item
select('item')
end
def select_to(tagOrId, index)
select('to', tagid(tagOrId), index)
end
def itemtype(tag)
TkcItem.type2class(tk_send('type', tagid(tag)))
end
end
class TkcItem<TkObject
extend Tk
include TkcTagAccess
CItemTypeToClass = {}
CItemID_TBL = TkCore::INTERP.create_table
TkCore::INTERP.init_ip_env{ CItemID_TBL.clear }
def TkcItem.type2class(type)
CItemTypeToClass[type]
end
def TkcItem.id2obj(canvas, id)
cpath = canvas.path
return id unless CItemID_TBL[cpath]
CItemID_TBL[cpath][id]? CItemID_TBL[cpath][id]: id
end
########################################
def self.create(canvas, *args)
fail RuntimeError, "TkcItem is an abstract class"
end
########################################
def initialize(parent, *args)
unless parent.kind_of?(TkCanvas)
fail ArguemntError, "expect TkCanvas for 1st argument"
end
@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')
unless 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
keys = _symbolkey2str(args.pop)
['font', 'kanjifont', 'latinfont', 'asciifont'].each{|key|
fontkeys[key] = keys.delete(key) if keys.key?(key)
}
args.concat(hash_kv(keys))
end
@id = create_self(*args).to_i ;# 'canvas item id' is integer number
CItemID_TBL[@path] = {} unless CItemID_TBL[@path]
CItemID_TBL[@path][@id] = self
configure(fontkeys) unless fontkeys.empty?
######## old version
# if args[-1].kind_of? Hash
# keys = args.pop
# end
# @id = create_self(*args).to_i ;# 'canvas item id' is integer number
# CItemID_TBL[@path] = {} unless CItemID_TBL[@path]
# CItemID_TBL[@path][@id] = self
# if keys
# # tk_call @path, 'itemconfigure', @id, *hash_kv(keys)
# configure(keys) if keys
# end
########
end
def create_self(*args)
self.class.create(@path, *args)
end
private :create_self
def id
@id
end
def delete
@c.delete @id
CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path]
self
end
alias remove delete
alias destroy delete
end
class TkcArc<TkcItem
CItemTypeToClass['arc'] = self
def self.create(path, *args)
if args[-1].kind_of?(Hash)
keys = args.pop
args.concat(hash_kv(keys))
end
tk_call_without_enc(path, 'create', 'arc', *args)
end
end
class TkcBitmap<TkcItem
CItemTypeToClass['bitmap'] = self
def self.create(path, *args)
if args[-1].kind_of?(Hash)
keys = args.pop
args.concat(hash_kv(keys))
end
tk_call_without_enc(path, 'create', 'bitmap', *args)
end
end
class TkcImage<TkcItem
CItemTypeToClass['image'] = self
def self.create(path, *args)
if args[-1].kind_of?(Hash)
keys = args.pop
args.concat(hash_kv(keys))
end
tk_call_without_enc(path, 'create', 'image', *args)
end
end
class TkcLine<TkcItem
CItemTypeToClass['line'] = self
def self.create(path, *args)
if args[-1].kind_of?(Hash)
keys = args.pop
args.concat(hash_kv(keys))
end
tk_call_without_enc(path, 'create', 'line', *args)
end
end
class TkcOval<TkcItem
CItemTypeToClass['oval'] = self
def self.create(path, *args)
if args[-1].kind_of?(Hash)
keys = args.pop
args.concat(hash_kv(keys))
end
tk_call_without_enc(path, 'create', 'oval', *args)
end
end
class TkcPolygon<TkcItem
CItemTypeToClass['polygon'] = self
def self.create(path, *args)
if args[-1].kind_of?(Hash)
keys = args.pop
args.concat(hash_kv(keys))
end
tk_call_without_enc(path, 'create', 'polygon', *args)
end
end
class TkcRectangle<TkcItem
CItemTypeToClass['rectangle'] = self
def self.create(path, *args)
if args[-1].kind_of?(Hash)
keys = args.pop
args.concat(hash_kv(keys))
end
tk_call_without_enc(path, 'create', 'rectangle', *args)
end
end
class TkcText<TkcItem
CItemTypeToClass['text'] = self
def self.create(path, *args)
if args[-1].kind_of?(Hash)
keys = args.pop
args.concat(hash_kv(keys))
end
#tk_call_without_enc(path, 'create', 'text',
# *(args.each{|arg| _get_eval_enc_str(arg)}))
tk_call(path, 'create', 'text', *args)
end
end
class TkcWindow<TkcItem
CItemTypeToClass['window'] = self
def self.create(path, *args)
if args[-1].kind_of?(Hash)
keys = _symbolkey2str(args.pop)
win = keys['window']
# keys['window'] = win.epath if win.kind_of?(TkWindow)
keys['window'] = _epath(win) if win
args.concat(hash_kv(keys))
end
tk_call_without_enc(path, 'create', 'window', *args)
end
end

337
ext/tk/lib/tk/canvastag.rb Normal file
View File

@ -0,0 +1,337 @@
#
# tk/canvastag.rb - methods for treating canvas tags
#
require 'tk'
require 'tk/canvas'
require 'tk/tagfont'
module TkcTagAccess
include TkComm
include TkTreatTagFont
def addtag(tag)
@c.addtag(tag, 'with', @id)
self
end
def bbox
@c.bbox(@id)
end
def bind(seq, cmd=Proc.new, args=nil)
@c.itembind @id, seq, cmd, args
self
end
def bind_append(seq, cmd=Proc.new, args=nil)
@c.itembind_append @id, seq, cmd, args
self
end
def bind_remove(seq)
@c.itembind_remove @id, seq
self
end
def bindinfo(seq=nil)
@c.itembindinfo @id, seq
end
def cget(option)
@c.itemcget @id, option
end
def configure(key, value=None)
@c.itemconfigure @id, key, value
self
end
# def configure(keys)
# @c.itemconfigure @id, keys
# end
def configinfo(key=nil)
@c.itemconfiginfo @id, key
end
def current_configinfo(key=nil)
@c.current_itemconfiginfo @id, key
end
def coords(*args)
@c.coords @id, *args
end
def dchars(first, last=None)
@c.dchars @id, first, last
self
end
def dtag(tag_to_del=None)
@c.dtag @id, tag_to_del
self
end
def find
@c.find 'withtag', @id
end
alias list find
def focus
@c.itemfocus @id
end
def gettags
@c.gettags @id
end
def icursor(index)
@c.icursor @id, index
self
end
def index(index)
@c.index @id, index
end
def insert(beforethis, string)
@c.insert @id, beforethis, string
self
end
def lower(belowthis=None)
@c.lower @id, belowthis
self
end
def move(xamount, yamount)
@c.move @id, xamount, yamount
self
end
def raise(abovethis=None)
@c.raise @id, abovethis
self
end
def scale(xorigin, yorigin, xscale, yscale)
@c.scale @id, xorigin, yorigin, xscale, yscale
self
end
def select_adjust(index)
@c.select('adjust', @id, index)
self
end
def select_from(index)
@c.select('from', @id, index)
self
end
def select_to(index)
@c.select('to', @id, index)
self
end
def itemtype
@c.itemtype @id
end
# 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)"
# ltag = tag1 | tag2; ltag.path => "(t1)||(t2)"
# ltag = tag1 ^ tag2; ltag.path => "(t1)^(t2)"
# ltag = - tag1; ltag.path => "!(t1)"
def & (tag)
if tag.kind_of? TkObject
TkcTagString.new(@c, '(' + @id + ')&&(' + tag.path + ')')
else
TkcTagString.new(@c, '(' + @id + ')&&(' + tag.to_s + ')')
end
end
def | (tag)
if tag.kind_of? TkObject
TkcTagString.new(@c, '(' + @id + ')||(' + tag.path + ')')
else
TkcTagString.new(@c, '(' + @id + ')||(' + tag.to_s + ')')
end
end
def ^ (tag)
if tag.kind_of? TkObject
TkcTagString.new(@c, '(' + @id + ')^(' + tag.path + ')')
else
TkcTagString.new(@c, '(' + @id + ')^(' + tag.to_s + ')')
end
end
def -@
TkcTagString.new(@c, '!(' + @id + ')')
end
end
class TkcTag<TkObject
include TkcTagAccess
CTagID_TBL = TkCore::INTERP.create_table
Tk_CanvasTag_ID = ['ctag'.freeze, '00000'.taint].freeze
TkCore::INTERP.init_ip_env{ CTagID_TBL.clear }
def TkcTag.id2obj(canvas, id)
cpath = canvas.path
return id unless CTagID_TBL[cpath]
CTagID_TBL[cpath][id]? CTagID_TBL[cpath][id]: id
end
def initialize(parent, mode=nil, *args)
unless parent.kind_of?(TkCanvas)
fail ArguemntError, "expect TkCanvas for 1st argument"
end
@c = parent
@cpath = parent.path
@path = @id = Tk_CanvasTag_ID.join('')
CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
CTagID_TBL[@cpath][@id] = self
Tk_CanvasTag_ID[1].succ!
if mode
tk_call_without_enc(@c.path, "addtag", @id, mode, *args)
end
end
def id
@id
end
def delete
@c.delete @id
CTagID_TBL[@cpath].delete(@id) if CTagID_TBL[@cpath]
self
end
alias remove delete
alias destroy delete
def set_to_above(target)
@c.addtag_above(@id, target)
self
end
alias above set_to_above
def set_to_all
@c.addtag_all(@id)
self
end
alias all set_to_all
def set_to_below(target)
@c.addtag_below(@id, target)
self
end
alias below set_to_below
def set_to_closest(x, y, halo=None, start=None)
@c.addtag_closest(@id, x, y, halo, start)
self
end
alias closest set_to_closest
def set_to_enclosed(x1, y1, x2, y2)
@c.addtag_enclosed(@id, x1, y1, x2, y2)
self
end
alias enclosed set_to_enclosed
def set_to_overlapping(x1, y1, x2, y2)
@c.addtag_overlapping(@id, x1, y1, x2, y2)
self
end
alias overlapping set_to_overlapping
def set_to_withtag(target)
@c.addtag_withtag(@id, target)
self
end
alias withtag set_to_withtag
end
class TkcTagString<TkcTag
def self.new(parent, name, *args)
if CTagID_TBL[parent.path] && CTagID_TBL[parent.path][name]
return CTagID_TBL[parent.path][name]
else
super(parent, name, *args)
end
end
def initialize(parent, name, mode=nil, *args)
unless parent.kind_of?(TkCanvas)
fail ArguemntError, "expect TkCanvas for 1st argument"
end
@c = parent
@cpath = parent.path
@path = @id = name
CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
CTagID_TBL[@cpath][@id] = self
if mode
tk_call_without_enc(@c.path, "addtag", @id, mode, *args)
end
end
end
TkcNamedTag = TkcTagString
class TkcTagAll<TkcTag
def initialize(parent)
unless parent.kind_of?(TkCanvas)
fail ArguemntError, "expect TkCanvas for 1st argument"
end
@c = parent
@cpath = parent.path
@path = @id = 'all'
CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
CTagID_TBL[@cpath][@id] = self
end
end
class TkcTagCurrent<TkcTag
def initialize(parent)
unless parent.kind_of?(TkCanvas)
fail ArguemntError, "expect TkCanvas for 1st argument"
end
@c = parent
@cpath = parent.path
@path = @id = 'current'
CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
CTagID_TBL[@cpath][@id] = self
end
end
class TkcGroup<TkcTag
Tk_cGroup_ID = ['tkcg'.freeze, '00000'.taint].freeze
def create_self(parent, *args)
unless parent.kind_of?(TkCanvas)
fail ArguemntError, "expect TkCanvas for 1st argument"
end
@c = parent
@cpath = parent.path
@path = @id = Tk_cGroup_ID.join('')
CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
CTagID_TBL[@cpath][@id] = self
Tk_cGroup_ID[1].succ!
add(*args) if args != []
end
private :create_self
def include(*tags)
for i in tags
i.addtag @id
end
self
end
def exclude(*tags)
for i in tags
i.delete @id
end
self
end
end

View File

@ -0,0 +1,25 @@
#
# tk/checkbutton.rb : treat checkbutton widget
#
require 'tk'
require 'tk/radiobutton'
class TkCheckButton<TkRadioButton
TkCommandNames = ['checkbutton'.freeze].freeze
WidgetClassName = 'Checkbutton'.freeze
WidgetClassNames[WidgetClassName] = self
def create_self(keys)
if keys and keys != None
tk_call_without_enc('checkbutton', @path, *hash_kv(keys, true))
else
tk_call_without_enc('checkbutton', @path)
end
end
private :create_self
def toggle
tk_send_without_enc('toggle')
self
end
end
TkCheckbutton = TkCheckButton

View File

@ -0,0 +1,75 @@
#
# tk/clipboard.rb : methods to treat clipboard
#
require 'tk'
module TkClipboard
include Tk
extend Tk
TkCommandNames = ['clipboard'.freeze].freeze
def self.clear(win=nil)
if win
tk_call_without_enc('clipboard', 'clear', '-displayof', win)
else
tk_call_without_enc('clipboard', 'clear')
end
end
def self.clear_on_display(win)
tk_call_without_enc('clipboard', 'clear', '-displayof', win)
end
def self.get(type=nil)
if type
tk_call_without_enc('clipboard', 'get', '-type', type)
else
tk_call_without_enc('clipboard', 'get')
end
end
def self.get_on_display(win, type=nil)
if type
tk_call_without_enc('clipboard', 'get', '-displayof', win, '-type', type)
else
tk_call_without_enc('clipboard', 'get', '-displayof', win)
end
end
def self.set(data, keys=nil)
clear
append(data, keys)
end
def self.set_on_display(win, data, keys=nil)
clear(win)
append_on_display(win, data, keys)
end
def self.append(data, keys=nil)
args = ['clipboard', 'append']
args.concat(hash_kv(keys))
args.concat(['--', data])
tk_call(*args)
end
def self.append_on_display(win, data, keys=nil)
args = ['clipboard', 'append', '-displayof', win]
args.concat(hash_kv(keys))
args.concat(['--', data])
tk_call(*args)
end
def clear
TkClipboard.clear_on_display(self)
self
end
def get(type=nil)
TkClipboard.get_on_display(self, type)
end
def set(data, keys=nil)
TkClipboard.set_on_display(self, data, keys)
self
end
def append(data, keys=nil)
TkClipboard.append_on_display(self, data, keys)
self
end
end

57
ext/tk/lib/tk/clock.rb Normal file
View File

@ -0,0 +1,57 @@
#
# tk/clock.rb : methods for clock command
#
require 'tk'
module Tk
module Clock
def self.clicks(ms=nil)
case ms
when nil
tk_call_without_enc('clock','clicks').to_i
when /^mic/
tk_call_without_enc('clock','clicks','-microseconds').to_i
when /^mil/
tk_call_without_enc('clock','clicks','-milliseconds').to_i
else
tk_call_without_enc('clock','clicks','-milliseconds').to_i
end
end
def self.format(clk, form=nil)
if form
tk_call('clock','format',clk,'-format',form)
else
tk_call('clock','format',clk)
end
end
def self.formatGMT(clk, form=nil)
if form
tk_call('clock','format',clk,'-format',form,'-gmt','1')
else
tk_call('clock','format',clk,'-gmt','1')
end
end
def self.scan(str, base=nil)
if base
tk_call('clock','scan',str,'-base',base).to_i
else
tk_call('clock','scan',str).to_i
end
end
def self.scanGMT(str, base=nil)
if base
tk_call('clock','scan',str,'-base',base,'-gmt','1').to_i
else
tk_call('clock','scan',str,'-gmt','1').to_i
end
end
def self.seconds
tk_call_without_enc('clock','seconds').to_i
end
end
end

View File

@ -0,0 +1,64 @@
#
# tk/composite.rb :
#
require 'tk'
module TkComposite
include Tk
extend Tk
def initialize(parent=nil, *args)
@delegates = {}
if parent.kind_of? Hash
keys = _symbolkey2str(parent)
parent = keys.delete('parent')
@frame = TkFrame.new(parent)
@delegates['DEFAULT'] = @frame
@path = @epath = @frame.path
initialize_composite(keys)
else
@frame = TkFrame.new(parent)
@delegates['DEFAULT'] = @frame
@path = @epath = @frame.path
initialize_composite(*args)
end
end
def epath
@epath
end
def initialize_composite(*args) end
private :initialize_composite
def delegate(option, *wins)
if @delegates[option].kind_of?(Array)
for i in wins
@delegates[option].push(i)
end
else
@delegates[option] = wins
end
end
def configure(slot, value=None)
if slot.kind_of? Hash
slot.each{|slot,value| configure slot, value}
else
if @delegates and @delegates[slot]
for i in @delegates[slot]
if not i
i = @delegates['DEFALUT']
redo
else
last = i.configure(slot, value)
end
end
last
else
super
end
end
end
end

29
ext/tk/lib/tk/console.rb Normal file
View File

@ -0,0 +1,29 @@
#
# tk/console.rb : control the console on system without a real console
#
require 'tk'
module TkConsole
include Tk
extend Tk
TkCommandNames = ['console'.freeze].freeze
def self.title(str=None)
tk_call 'console', str
end
def self.hide
tk_call_without_enc('console', 'hide')
end
def self.show
tk_call_without_enc('console', 'show')
end
def self.eval(tcl_script)
#
# supports a Tcl script only
# I have no idea to support a Ruby script seamlessly.
#
_fromUTF8(tk_call_without_enc('console', 'eval',
_get_eval_enc_str(tcl_script)))
end
end

290
ext/tk/lib/tk/dialog.rb Normal file
View File

@ -0,0 +1,290 @@
#
# tk/dialog.rb : create dialog boxes
#
require 'tk'
class TkDialog2 < TkWindow
extend Tk
TkCommandNames = ['tk_dialog'.freeze].freeze
def self.show(*args)
dlog = self.new(*args)
dlog.show
dlog
end
def _set_button_config(configs)
set_config = proc{|c,i|
if $VERBOSE && (c.has_key?('command') || c.has_key?(:command))
STDERR.print("Warning: cannot give a command option " +
"to the dialog button#{i}. It was removed.\n")
end
c.delete('command'); c.delete(:command)
# @config << Kernel.format("%s.button%s configure %s; ",
# @path, i, hash_kv(c).join(' '))
@config << @path+'.button'+i.to_s+'configure '+hash_kv(c).join(' ')+'; '
}
case configs
when Proc
@buttons.each_index{|i|
if (c = configs.call(i)).kind_of? Hash
set_config.call(c,i)
end
}
when Array
@buttons.each_index{|i|
if (c = configs[i]).kind_of? Hash
set_config.call(c,i)
end
}
when Hash
@buttons.each_with_index{|s,i|
if (c = configs[s]).kind_of? Hash
set_config.call(c,i)
end
}
end
@config = 'after idle {' + @config + '};' if @config != ""
end
private :_set_button_config
# initialize tk_dialog
def create_self(keys)
#@var = TkVariable.new
@val = nil
@title = title
@message = message
@message_config = message_config
@msgframe_config = msgframe_config
@bitmap = bitmap
@bitmap_config = message_config
@default_button = default_button
@buttons = buttons
@button_configs = proc{|num| button_configs(num)}
@btnframe_config = btnframe_config
#@config = "puts [winfo children .w0000];"
@config = ""
@command = nil
if keys.kind_of? Hash
@title = keys['title'] if keys.key? 'title'
@message = keys['message'] if keys.key? 'message'
@bitmap = keys['bitmap'] if keys.key? 'bitmap'
@bitmap = '{}' if @bitmap == nil || @bitmap == ""
@default_button = keys['default'] if keys.key? 'default'
@buttons = keys['buttons'] if keys.key? 'buttons'
@command = keys['prev_command']
@message_config = keys['message_config'] if keys.key? 'message_config'
@msgframe_config = keys['msgframe_config'] if keys.key? 'msgframe_config'
@bitmap_config = keys['bitmap_config'] if keys.key? 'bitmap_config'
@button_configs = keys['button_configs'] if keys.key? 'button_configs'
@btnframe_config = keys['btnframe_config'] if keys.key? 'btnframe_config'
end
if @title.include? ?\s
@title = '{' + @title + '}'
end
if @buttons.kind_of? Array
_set_button_config(@buttons.collect{|cfg|
(cfg.kind_of? Array)? cfg[1]: nil})
@buttons = @buttons.collect{|cfg| (cfg.kind_of? Array)? cfg[0]: cfg}
end
if @buttons.kind_of? Hash
_set_button_config(@buttons)
@buttons = @buttons.keys
end
@buttons = tk_split_simplelist(@buttons) if @buttons.kind_of? String
@buttons = @buttons.collect{|s|
if s.kind_of? Array
s = s.join(' ')
end
if s.include? ?\s
'{' + s + '}'
else
s
end
}
if @message_config.kind_of? Hash
# @config << Kernel.format("%s.msg configure %s;",
# @path, hash_kv(@message_config).join(' '))
@config << @path+'.msg configure '+hash_kv(@message_config).join(' ')+';'
end
if @msgframe_config.kind_of? Hash
# @config << Kernel.format("%s.top configure %s;",
# @path, hash_kv(@msgframe_config).join(' '))
@config << @path+'.top configure '+hash_kv(@msgframe_config).join(' ')+';'
end
if @btnframe_config.kind_of? Hash
# @config << Kernel.format("%s.bot configure %s;",
# @path, hash_kv(@btnframe_config).join(' '))
@config << @path+'.bot configure '+hash_kv(@btnframe_config).join(' ')+';'
end
if @bitmap_config.kind_of? Hash
# @config << Kernel.format("%s.bitmap configure %s;",
# @path, hash_kv(@bitmap_config).join(' '))
@config << @path+'.bitmap configure '+hash_kv(@bitmap_config).join(' ')+';'
end
_set_button_config(@button_configs) if @button_configs
if @command.kind_of? Proc
@command.call(self)
end
end
private :create_self
def show
if @default_button.kind_of? String
default_button = @buttons.index(@default_button)
else
default_button = @default_button
end
default_button = '{}' if default_button == nil
#Tk.ip_eval('eval {global '+@var.id+';'+@config+
# 'set '+@var.id+' [tk_dialog '+
# @path+" "+@title+" {#{@message}} "+@bitmap+" "+
# String(default_button)+" "+@buttons.join(' ')+']}')
Tk.ip_eval(@config)
@val = Tk.ip_eval('tk_dialog ' + @path + ' ' + @title +
' {' + @message + '} ' + @bitmap + ' ' +
String(default_button) + ' ' + @buttons.join(' ')).to_i
end
def value
# @var.value.to_i
@val
end
######################################################
# #
# these methods must be overridden for each dialog #
# #
######################################################
private
def title
# returns a title string of the dialog window
return "DIALOG"
end
def message
# returns a message text to display on the dialog
return "MESSAGE"
end
def message_config
# returns a Hash {option=>value, ...} for the message text
return nil
end
def msgframe_config
# returns a Hash {option=>value, ...} for the message text frame
return nil
end
def bitmap
# returns a bitmap name or a bitmap file path
# (@ + path ; e.g. '@/usr/share/bitmap/sample.xbm')
return "info"
end
def bitmap_config
# returns nil or a Hash {option=>value, ...} for the bitmap
return nil
end
def default_button
# returns a default button's number or name
# if nil or null string, set no-default
return 0
end
def buttons
#return "BUTTON1 BUTTON2"
return ["BUTTON1", "BUTTON2"]
end
def button_configs(num)
# returns nil / Proc / Array or Hash (see _set_button_config)
return nil
end
def btnframe_config
# returns nil or a Hash {option=>value, ...} for the button frame
return nil
end
end
#
# TkDialog : with showing at initialize
#
class TkDialog < TkDialog2
def self.show(*args)
self.new(*args)
end
def initialize(*args)
super(*args)
show
end
end
#
# dialog for warning
#
class TkWarning2 < TkDialog2
def initialize(parent = nil, mes = nil)
if !mes
if parent.kind_of? TkWindow
mes = ""
else
mes = parent.to_s
parent = nil
end
end
super(parent, :message=>mes)
end
def show(mes = nil)
mes_bup = @message
@message = mes if mes
ret = super()
@message = mes_bup
ret
end
#######
private
def title
return "WARNING";
end
def bitmap
return "warning";
end
def default_button
return 0;
end
def buttons
return "OK";
end
end
class TkWarning < TkWarning2
def self.show(*args)
self.new(*args)
end
def initialize(*args)
super(*args)
show
end
end

107
ext/tk/lib/tk/encodedstr.rb Normal file
View File

@ -0,0 +1,107 @@
#
# tk/encodedstr.rb : Tk::EncodedString class
#
require 'tk'
###########################################
# string with Tcl's encoding
###########################################
module Tk
class EncodedString < String
Encoding = nil
def self.subst_utf_backslash(str)
# str.gsub(/\\u([0-9A-Fa-f]{1,4})/){[$1.hex].pack('U')}
TclTkLib._subst_UTF_backslash(str)
end
def self.utf_backslash(str)
self.subst_utf_backslash(str)
end
def self.subst_tk_backslash(str)
TclTkLib._subst_Tcl_backslash(str)
end
def self.utf_to_backslash_sequence(str)
str.unpack('U*').collect{|c|
if c <= 0xFF # ascii character
c.chr
else
format('\u%X', c)
end
}.join('')
end
def self.utf_to_backslash(str)
self.utf_to_backslash_sequence(str)
end
def self.to_backslash_sequence(str)
str.unpack('U*').collect{|c|
if c <= 0x1F # control character
case c
when 0x07; '\a'
when 0x08; '\b'
when 0x09; '\t'
when 0x0a; '\n'
when 0x0b; '\v'
when 0x0c; '\f'
when 0x0d; '\r'
else
format('\x%02X', c)
end
elsif c <= 0xFF # ascii character
c.chr
else
format('\u%X', c)
end
}.join('')
end
def self.new_with_utf_backslash(str, enc = nil)
self.new('', enc).replace(self.subst_utf_backslash(str))
end
def self.new_without_utf_backslash(str, enc = nil)
self.new('', enc).replace(str)
end
def initialize(str, enc = nil)
super(str)
@encoding = ( enc ||
((self.class::Encoding)?
self.class::Encoding : Tk.encoding_system) )
end
attr_reader :encoding
end
# def Tk.EncodedString(str, enc = nil)
# Tk::EncodedString.new(str, enc)
# end
##################################
class BinaryString < EncodedString
Encoding = 'binary'.freeze
end
# def Tk.BinaryString(str)
# Tk::BinaryString.new(str)
# end
##################################
class UTF8_String < EncodedString
Encoding = 'utf-8'.freeze
def self.new(str)
super(self.subst_utf_backslash(str))
end
def to_backslash_sequence
Tk::EncodedString.utf_to_backslash_sequence(self)
end
alias to_backslash to_backslash_sequence
end
# def Tk.UTF8_String(str)
# Tk::UTF8_String.new(str)
# end
end

114
ext/tk/lib/tk/entry.rb Normal file
View File

@ -0,0 +1,114 @@
#
# tk/entry.rb - Tk entry classes
# $Date$
# by Yukihiro Matsumoto <matz@caelum.co.jp>
require 'tk'
require 'tk/label'
require 'tk/scrollable'
require 'tk/validation'
class TkEntry<TkLabel
include Scrollable
include TkValidation
TkCommandNames = ['entry'.freeze].freeze
WidgetClassName = 'Entry'.freeze
WidgetClassNames[WidgetClassName] = self
def create_self(keys)
tk_call_without_enc('entry', @path)
if keys and keys != None
configure(keys)
end
end
private :create_self
def bbox(index)
list(tk_send_without_enc('bbox', index))
end
def cursor
number(tk_send_without_enc('index', 'insert'))
end
def cursor=(index)
tk_send_without_enc('icursor', index)
#self
index
end
def index(index)
number(tk_send_without_enc('index', index))
end
def insert(pos,text)
tk_send_without_enc('insert', pos, _get_eval_enc_str(text))
self
end
def delete(first, last=None)
tk_send_without_enc('delete', first, last)
self
end
def mark(pos)
tk_send_without_enc('scan', 'mark', pos)
self
end
def dragto(pos)
tk_send_without_enc('scan', 'dragto', pos)
self
end
def selection_adjust(index)
tk_send_without_enc('selection', 'adjust', index)
self
end
def selection_clear
tk_send_without_enc('selection', 'clear')
self
end
def selection_from(index)
tk_send_without_enc('selection', 'from', index)
self
end
def selection_present()
bool(tk_send_without_enc('selection', 'present'))
end
def selection_range(s, e)
tk_send_without_enc('selection', 'range', s, e)
self
end
def selection_to(index)
tk_send_without_enc('selection', 'to', index)
self
end
def invoke_validate
bool(tk_send_without_enc('validate'))
end
def validate(mode = nil)
if mode
configure 'validate', mode
else
invoke_validate
end
end
def value
_fromUTF8(tk_send_without_enc('get'))
end
def value= (val)
tk_send_without_enc('delete', 0, 'end')
tk_send_without_enc('insert', 0, _get_eval_enc_str(val))
val
end
alias get value
alias set value=
def [](*args)
self.value[*args]
end
def []=(*args)
val = args.pop
str = self.value
str[*args] = val
self.value = str
val
end
end

142
ext/tk/lib/tk/event.rb Normal file
View File

@ -0,0 +1,142 @@
#
# tk/event.rb - module for event
#
require 'tk'
module TkEvent
class Event < TkUtil::CallbackSubst
module TypeNum
KeyPress = 2
KeyRelease = 3
ButtonPress = 4
ButtonRelease = 5
MotionNotify = 6
EnterNotify = 7
LeaveNotify = 8
FocusIn = 9
FocusOut = 10
KeymapNotify = 11
Expose = 12
GraphicsExpose = 13
NoExpose = 14
VisibilityNotify = 15
CreateNotify = 16
DestroyNotify = 17
UnmapNotify = 18
MapNotify = 19
MapRequest = 20
ReparentNotify = 21
ConfigureNotify = 22
ConfigureRequest = 23
GravityNotify = 24
ResizeRequest = 25
CirculateNotify = 26
CirculateRequest = 27
PropertyNotify = 28
SelectionClear = 29
SelectionRequest = 30
SelectionNotify = 31
ColormapNotify = 32
ClientMessage = 33
MappingNotify = 34
end
# [ <'%' subst-key char>, <proc type char>, <instance var (accessor) name>]
key_tbl = [
[ ?#, ?n, :serial ],
[ ?a, ?s, :above ],
[ ?b, ?n, :num ],
[ ?c, ?n, :count ],
[ ?d, ?s, :detail ],
[ ?f, ?b, :focus ],
[ ?h, ?n, :height ],
[ ?i, ?s, :win_hex ],
[ ?k, ?n, :keycode ],
[ ?m, ?s, :mode ],
[ ?o, ?b, :override ],
[ ?p, ?s, :place ],
[ ?s, ?x, :state ],
[ ?t, ?n, :time ],
[ ?w, ?n, :width ],
[ ?x, ?n, :x ],
[ ?y, ?n, :y ],
[ ?A, ?s, :char ],
[ ?B, ?n, :borderwidth ],
[ ?D, ?n, :wheel_delta ],
[ ?E, ?b, :send_event ],
[ ?K, ?s, :keysym ],
[ ?N, ?n, :keysym_num ],
[ ?R, ?s, :rootwin_id ],
[ ?S, ?s, :subwindow ],
[ ?T, ?n, :type ],
[ ?W, ?w, :widget ],
[ ?X, ?n, :x_root ],
[ ?Y, ?n, :y_root ],
nil
]
# [ <proc type char>, <proc/method to convert tcl-str to ruby-obj>]
proc_tbl = [
[ ?n, TkComm.method(:num_or_str) ],
[ ?s, TkComm.method(:string) ],
[ ?b, TkComm.method(:bool) ],
[ ?w, TkComm.method(:window) ],
[ ?x, proc{|val|
begin
TkComm::number(val)
rescue ArgumentError
val
end
}
],
nil
]
# setup tables to be used by scan_args, _get_subst_key, _get_all_subst_keys
#
# _get_subst_key() and _get_all_subst_keys() generates key-string
# which describe how to convert callback arguments to ruby objects.
# When binding parameters are given, use _get_subst_key().
# But when no parameters are given, use _get_all_subst_keys() to
# create a Event class object as a callback parameter.
#
# scan_args() is used when doing callback. It convert arguments
# ( which are Tcl strings ) to ruby objects based on the key string
# that is generated by _get_subst_key() or _get_all_subst_keys().
#
_setup_subst_table(key_tbl, proc_tbl);
end
def install_bind(cmd, *args)
if args.compact.size > 0
args = args.join(' ')
keys = Event._get_subst_key(args)
if cmd.kind_of?(String)
id = cmd
elsif cmd.kind_of?(TkCallbackEntry)
id = install_cmd(cmd)
else
id = install_cmd(proc{|*arg|
TkUtil.eval_cmd(cmd, *Event.scan_args(keys, arg))
})
end
id + ' ' + args
else
keys, args = Event._get_all_subst_keys
if cmd.kind_of?(String)
id = cmd
elsif cmd.kind_of?(TkCallbackEntry)
id = install_cmd(cmd)
else
id = install_cmd(proc{|*arg|
TkUtil.eval_cmd(cmd, Event.new(*Event.scan_args(keys, arg)))
})
end
id + ' ' + args
end
end
end

1407
ext/tk/lib/tk/font.rb Normal file

File diff suppressed because it is too large Load Diff

123
ext/tk/lib/tk/frame.rb Normal file
View File

@ -0,0 +1,123 @@
#
# tk/frame.rb : treat frame widget
#
require 'tk'
class TkFrame<TkWindow
TkCommandNames = ['frame'.freeze].freeze
WidgetClassName = 'Frame'.freeze
WidgetClassNames[WidgetClassName] = self
################# old version
# def initialize(parent=nil, keys=nil)
# if keys.kind_of? Hash
# keys = keys.dup
# @classname = keys.delete('classname') if keys.key?('classname')
# @colormap = keys.delete('colormap') if keys.key?('colormap')
# @container = keys.delete('container') if keys.key?('container')
# @visual = keys.delete('visual') if keys.key?('visual')
# end
# super(parent, keys)
# end
#
# def create_self
# s = []
# s << "-class" << @classname if @classname
# s << "-colormap" << @colormap if @colormap
# s << "-container" << @container if @container
# s << "-visual" << @visual if @visual
# tk_call 'frame', @path, *s
# end
#################
def initialize(parent=nil, keys=nil)
my_class_name = nil
if self.class < WidgetClassNames[WidgetClassName]
my_class_name = self.class.name
my_class_name = nil if my_class_name == ''
end
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')
keys['class'] = keys.delete('classname')
end
@classname = keys['class']
@colormap = keys['colormap']
@container = keys['container']
@visual = keys['visual']
if !@classname && my_class_name
keys['class'] = @classname = my_class_name
end
if @classname.kind_of? TkBindTag
@db_class = @classname
@classname = @classname.id
elsif @classname
@db_class = TkDatabaseClass.new(@classname)
else
@db_class = self.class
@classname = @db_class::WidgetClassName
end
super(keys)
end
def create_self(keys)
if keys and keys != None
tk_call_without_enc('frame', @path, *hash_kv(keys))
else
tk_call_without_enc( 'frame', @path)
end
end
private :create_self
def database_classname
@classname
end
def self.database_class
if self == WidgetClassNames[WidgetClassName] || self.name == ''
self
else
TkDatabaseClass.new(self.name)
end
end
def self.database_classname
self.database_class.name
end
def self.bind(*args)
if self == WidgetClassNames[WidgetClassName] || self.name == ''
super(*args)
else
TkDatabaseClass.new(self.name).bind(*args)
end
end
def self.bind_append(*args)
if self == WidgetClassNames[WidgetClassName] || self.name == ''
super(*args)
else
TkDatabaseClass.new(self.name).bind_append(*args)
end
end
def self.bind_remove(*args)
if self == WidgetClassNames[WidgetClassName] || self.name == ''
super(*args)
else
TkDatabaseClass.new(self.name).bind_remove(*args)
end
end
def self.bindinfo(*args)
if self == WidgetClassNames[WidgetClassName] || self.name == ''
super(*args)
else
TkDatabaseClass.new(self.name).bindinfo(*args)
end
end
end

182
ext/tk/lib/tk/grid.rb Normal file
View File

@ -0,0 +1,182 @@
#
# tk/grid.rb : control grid geometry manager
#
require 'tk'
module TkGrid
include Tk
extend Tk
TkCommandNames = ['grid'.freeze].freeze
def anchor(master, anchor=None)
# master = master.epath if master.kind_of?(TkObject)
master = _epath(master)
tk_call_without_enc('grid', 'anchor', master, anchor)
end
def bbox(master, *args)
# master = master.epath if master.kind_of?(TkObject)
master = _epath(master)
args.unshift(master)
list(tk_call_without_enc('grid', 'bbox', *args))
end
def configure(win, *args)
if args[-1].kind_of?(Hash)
opts = args.pop
else
opts = {}
end
params = []
params.push(_epath(win))
args.each{|win|
case win
when '-', 'x', '^' # RELATIVE PLACEMENT
params.push(win)
else
params.push(_epath(win))
end
}
opts.each{|k, v|
params.push("-#{k}")
params.push((v.kind_of?(TkObject))? v.epath: v)
}
tk_call_without_enc("grid", 'configure', *params)
end
def columnconfigure(master, index, args)
# master = master.epath if master.kind_of?(TkObject)
master = _epath(master)
tk_call_without_enc("grid", 'columnconfigure',
master, index, *hash_kv(args))
end
def rowconfigure(master, index, args)
# master = master.epath if master.kind_of?(TkObject)
master = _epath(master)
tk_call_without_enc("grid", 'rowconfigure', master, index, *hash_kv(args))
end
def columnconfiginfo(master, index, slot=nil)
# master = master.epath if master.kind_of?(TkObject)
master = _epath(master)
if slot
num_or_str(tk_call_without_enc('grid', 'columnconfigure',
master, index, "-#{slot}"))
else
ilist = list(tk_call_without_enc('grid','columnconfigure',master,index))
info = {}
while key = ilist.shift
info[key[1..-1]] = ilist.shift
end
info
end
end
def rowconfiginfo(master, index, slot=nil)
# master = master.epath if master.kind_of?(TkObject)
master = _epath(master)
if slot
num_or_str(tk_call_without_enc('grid', 'rowconfigure',
master, index, "-#{slot}"))
else
ilist = list(tk_call_without_enc('grid', 'rowconfigure', master, index))
info = {}
while key = ilist.shift
info[key[1..-1]] = ilist.shift
end
info
end
end
def add(widget, *args)
configure(widget, *args)
end
def forget(*args)
return '' if args.size == 0
wins = args.collect{|win|
# (win.kind_of?(TkObject))? win.epath: win
_epath(win)
}
tk_call_without_enc('grid', 'forget', *wins)
end
def info(slave)
# slave = slave.epath if slave.kind_of?(TkObject)
slave = _epath(slave)
ilist = list(tk_call_without_enc('grid', 'info', slave))
info = {}
while key = ilist.shift
info[key[1..-1]] = ilist.shift
end
return info
end
def location(master, x, y)
# master = master.epath if master.kind_of?(TkObject)
master = _epath(master)
list(tk_call_without_enc('grid', 'location', master, x, y))
end
def propagate(master, bool=None)
# master = master.epath if master.kind_of?(TkObject)
master = _epath(master)
if bool == None
bool(tk_call_without_enc('grid', 'propagate', master))
else
tk_call_without_enc('grid', 'propagate', master, bool)
end
end
def remove(*args)
return '' if args.size == 0
wins = args.collect{|win|
# (win.kind_of?(TkObject))? win.epath: win
_epath(win)
}
tk_call_without_enc('grid', 'remove', *wins)
end
def size(master)
# master = master.epath if master.kind_of?(TkObject)
master = _epath(master)
list(tk_call_without_enc('grid', 'size', master))
end
def slaves(master, args)
# master = master.epath if master.kind_of?(TkObject)
master = _epath(master)
list(tk_call_without_enc('grid', 'slaves', master, *hash_kv(args)))
end
module_function :bbox, :forget, :propagate, :info
module_function :remove, :size, :slaves, :location
module_function :configure, :columnconfigure, :rowconfigure
module_function :columnconfiginfo, :rowconfiginfo
end
=begin
def TkGrid(win, *args)
if args[-1].kind_of?(Hash)
opts = args.pop
else
opts = {}
end
params = []
params.push((win.kind_of?(TkObject))? win.epath: win)
args.each{|win|
case win
when '-', 'x', '^' # RELATIVE PLACEMENT
params.push(win)
else
params.push((win.kind_of?(TkObject))? win.epath: win)
end
}
opts.each{|k, v|
params.push("-#{k}")
params.push((v.kind_of?(TkObject))? v.epath: v)
}
tk_call_without_enc("grid", *params)
end
=end

185
ext/tk/lib/tk/image.rb Normal file
View File

@ -0,0 +1,185 @@
#
# tk/image.rb : treat Tk image objects
#
require 'tk'
class TkImage<TkObject
include Tk
TkCommandNames = ['image'.freeze].freeze
Tk_IMGTBL = TkCore::INTERP.create_table
Tk_Image_ID = ['i'.freeze, '00000'.taint].freeze
TkCore::INTERP.init_ip_env{ Tk_IMGTBL.clear }
def initialize(keys=nil)
@path = Tk_Image_ID.join('')
Tk_Image_ID[1].succ!
tk_call_without_enc('image', 'create', @type, @path, *hash_kv(keys, true))
Tk_IMGTBL[@path] = self
end
def delete
Tk_IMGTBL.delete(@id) if @id
tk_call_without_enc('image', 'delete', @path)
self
end
def height
number(tk_call_without_enc('image', 'height', @path))
end
def inuse
bool(tk_call_without_enc('image', 'inuse', @path))
end
def itemtype
tk_call_without_enc('image', 'type', @path)
end
def width
number(tk_call_without_enc('image', 'width', @path))
end
def TkImage.names
Tk.tk_call_without_enc('image', 'names').split.collect!{|id|
(Tk_IMGTBL[id])? Tk_IMGTBL[id] : id
}
end
def TkImage.types
Tk.tk_call_without_enc('image', 'types').split
end
end
class TkBitmapImage<TkImage
def initialize(*args)
@type = 'bitmap'
super
end
end
class TkPhotoImage<TkImage
NullArgOptionKeys = [ "shrink", "grayscale" ]
def _photo_hash_kv(keys)
keys = _symbolkey2str(keys)
NullArgOptionKeys.collect{|opt|
if keys[opt]
keys[opt] = None
else
keys.delete(opt)
end
}
hash_kv(keys).flatten
end
private :_photo_hash_kv
def initialize(*args)
@type = 'photo'
super
end
def blank
tk_send_without_enc('blank')
self
end
def cget(option)
case option.to_s
when 'data', 'file'
tk_send 'cget', option
else
tk_tcl2ruby(tk_send('cget', option))
end
end
def copy(src, *opts)
if opts.size == 0
tk_send('copy', src)
elsif opts.size == 1 && opts[0].kind_of?(Hash)
tk_send('copy', src, *_photo_hash_kv(opts[0]))
else
# for backward compatibility
args = opts.collect{|term|
if term.kind_of?(String) && term.include?(?\s)
term.split
else
term
end
}.flatten
tk_send('copy', source, *args)
end
self
end
def data(keys={})
#tk_send('data', *_photo_hash_kv(keys))
tk_split_list(tk_send('data', *_photo_hash_kv(keys)))
end
def get(x, y)
tk_send('get', x, y).split.collect{|n| n.to_i}
end
def put(data, *opts)
if opts == []
tk_send('put', data)
elsif opts.size == 1 && opts[0].kind_of?(Hash)
tk_send('put', data, *_photo_hash_kv(opts[0]))
else
# for backward compatibility
tk_send('put', data, '-to', *opts)
end
self
end
def read(file, *opts)
if opts.size == 0
tk_send('read', file)
elsif opts.size == 1 && opts[0].kind_of?(Hash)
tk_send('read', file, *_photo_hash_kv(opts[0]))
else
# for backward compatibility
args = opts.collect{|term|
if term.kind_of?(String) && term.include?(?\s)
term.split
else
term
end
}.flatten
tk_send('read', file, *args)
end
self
end
def redither
tk_send 'redither'
self
end
def get_transparency(x, y)
bool(tk_send('transparency', 'get', x, y))
end
def set_transparency(x, y, st)
tk_send('transparency', 'set', x, y, st)
self
end
def write(file, *opts)
if opts.size == 0
tk_send('write', file)
elsif opts.size == 1 && opts[0].kind_of?(Hash)
tk_send('write', file, *_photo_hash_kv(opts[0]))
else
# for backward compatibility
args = opts.collect{|term|
if term.kind_of?(String) && term.include?(?\s)
term.split
else
term
end
}.flatten
tk_send('write', file, *args)
end
self
end
end

185
ext/tk/lib/tk/itemfont.rb Normal file
View File

@ -0,0 +1,185 @@
#
# tk/itemfont.rb : control font of widget items
#
require 'tk'
module TkTreatItemFont
def __conf_cmd(idx)
raise NotImplementedError, "need to define `__conf_cmd'"
end
def __item_pathname(tagOrId)
raise NotImplementedError, "need to define `__item_pathname'"
end
private :__conf_cmd, :__item_pathname
def tagfont_configinfo(tagOrId, name = nil)
pathname = __item_pathname(tagOrId)
ret = TkFont.used_on(pathname)
if ret == nil
=begin
if name
ret = name
else
ret = TkFont.init_widget_font(pathname, self.path,
__conf_cmd(0), __conf_cmd(1), tagOrId)
end
=end
ret = TkFont.init_widget_font(pathname, self.path,
__conf_cmd(0), __conf_cmd(1), tagOrId)
end
ret
end
alias tagfontobj tagfont_configinfo
def tagfont_configure(tagOrId, slot)
pathname = __item_pathname(tagOrId)
slot = _symbolkey2str(slot)
if slot.key?('font')
fnt = slot.delete('font')
if fnt.kind_of? TkFont
return fnt.call_font_configure(pathname, self.path,
__conf_cmd(0), __conf_cmd(1),
tagOrId, slot)
else
if fnt
if (slot.key?('kanjifont') ||
slot.key?('latinfont') ||
slot.key?('asciifont'))
fnt = TkFont.new(fnt)
lfnt = slot.delete('latinfont')
lfnt = slot.delete('asciifont') if slot.key?('asciifont')
kfnt = slot.delete('kanjifont')
fnt.latin_replace(lfnt) if lfnt
fnt.kanji_replace(kfnt) if kfnt
end
slot['font'] = fnt
tk_call(self.path, __conf_cmd(0), __conf_cmd(1),
tagOrId, *hash_kv(slot))
end
return self
end
end
lfnt = slot.delete('latinfont')
lfnt = slot.delete('asciifont') if slot.key?('asciifont')
kfnt = slot.delete('kanjifont')
if lfnt && kfnt
return TkFont.new(lfnt, kfnt).call_font_configure(pathname, self.path,
__conf_cmd(0),
__conf_cmd(1),
tagOrId, slot)
end
latintagfont_configure(tagOrId, lfnt) if lfnt
kanjitagfont_configure(tagOrId, kfnt) if kfnt
tk_call(self.path, __conf_cmd(0), __conf_cmd(1),
tagOrId, *hash_kv(slot)) if slot != {}
self
end
def latintagfont_configure(tagOrId, ltn, keys=nil)
pathname = __item_pathname(tagOrId)
if (fobj = TkFont.used_on(pathname))
fobj = TkFont.new(fobj) # create a new TkFont object
elsif Tk::JAPANIZED_TK
fobj = tagfontobj(tagOrId) # create a new TkFont object
else
tk_call(self.path, __conf_cmd(0), __conf_cmd(1), tagOrId, '-font', ltn)
return self
end
if fobj.kind_of?(TkFont)
if ltn.kind_of? TkFont
conf = {}
ltn.latin_configinfo.each{|key,val| conf[key] = val}
if keys
fobj.latin_configure(conf.update(keys))
else
fobj.latin_configure(conf)
end
else
fobj.latin_replace(ltn)
end
end
return fobj.call_font_configure(pathname, self.path,
__conf_cmd(0), __conf_cmd(1), tagOrId, {})
end
alias asciitagfont_configure latintagfont_configure
def kanjitagfont_configure(tagOrId, knj, keys=nil)
pathname = __item_pathname(tagOrId)
if (fobj = TkFont.used_on(pathname))
fobj = TkFont.new(fobj) # create a new TkFont object
elsif Tk::JAPANIZED_TK
fobj = tagfontobj(tagOrId) # create a new TkFont object
else
tk_call(self.path, __conf_cmd(0), __conf_cmd(1), tagOrId, '-font', knj)
return self
end
if fobj.kind_of?(TkFont)
if knj.kind_of? TkFont
conf = {}
knj.kanji_configinfo.each{|key,val| conf[key] = val}
if keys
fobj.kanji_configure(conf.update(keys))
else
fobj.kanji_configure(conf)
end
else
fobj.kanji_replace(knj)
end
end
return fobj.call_font_configure(pathname, self.path,
__conf_cmd(0), __conf_cmd(1), tagOrId, {})
end
def tagfont_copy(tagOrId, window, wintag=nil)
pathname = __item_pathname(tagOrId)
if wintag
fnt = window.tagfontobj(wintag).dup
else
fnt = window.fontobj.dup
end
fnt.call_font_configure(pathname, self.path,
__conf_cmd(0), __conf_cmd(1), tagOrId, {})
return self
end
def latintagfont_copy(tagOrId, window, wintag=nil)
pathname = __item_pathname(tagOrId)
tagfontobj(tagOrId).dup.call_font_configure(pathname, self.path,
__conf_cmd(0), __conf_cmd(1),
tagOrId, {})
if wintag
tagfontobj(tagOrId).
latin_replace(window.tagfontobj(wintag).latin_font_id)
else
tagfontobj(tagOrId).latin_replace(window.fontobj.latin_font_id)
end
self
end
alias asciitagfont_copy latintagfont_copy
def kanjitagfont_copy(tagOrId, window, wintag=nil)
pathname = __item_pathname(tagOrId)
tagfontobj(tagOrId).dup.call_font_configure(pathname, self.path,
__conf_cmd(0), __conf_cmd(1),
tagOrId, {})
if wintag
tagfontobj(tagOrId).
kanji_replace(window.tagfontobj(wintag).kanji_font_id)
else
tagfontobj(tagOrId).kanji_replace(window.fontobj.kanji_font_id)
end
self
end
end

71
ext/tk/lib/tk/kinput.rb Normal file
View File

@ -0,0 +1,71 @@
#
# tk/kinput.rb : control kinput
#
require 'tk'
module TkKinput
include Tk
extend Tk
TkCommandNames = [
'kinput_start'.freeze,
'kinput_send_spot'.freeze,
'kanjiInput'.freeze
].freeze
def TkKinput.start(window, style=None)
tk_call('kinput_start', window, style)
end
def kinput_start(style=None)
TkKinput.start(self, style)
end
def TkKinput.send_spot(window)
tk_call('kinput_send_spot', window)
end
def kinput_send_spot
TkKinput.send_spot(self)
end
def TkKinput.input_start(window, keys=nil)
tk_call('kanjiInput', 'start', window, *hash_kv(keys))
end
def kanji_input_start(keys=nil)
TkKinput.input_start(self, keys)
end
def TkKinput.attribute_config(window, slot, value=None)
if slot.kind_of? Hash
tk_call('kanjiInput', 'attribute', window, *hash_kv(slot))
else
tk_call('kanjiInput', 'attribute', window, "-#{slot}", value)
end
end
def kinput_attribute_config(slot, value=None)
TkKinput.attribute_config(self, slot, value)
end
def TkKinput.attribute_info(window, slot=nil)
if slot
conf = tk_split_list(tk_call('kanjiInput', 'attribute',
window, "-#{slot}"))
conf[0] = conf[0][1..-1]
conf
else
tk_split_list(tk_call('kanjiInput', 'attribute', window)).collect{|conf|
conf[0] = conf[0][1..-1]
conf
}
end
end
def kinput_attribute_info(slot=nil)
TkKinput.attribute_info(self, slot)
end
def TkKinput.input_end(window)
tk_call('kanjiInput', 'end', window)
end
def kanji_input_end
TkKinput.input_end(self)
end
end

22
ext/tk/lib/tk/label.rb Normal file
View File

@ -0,0 +1,22 @@
#
# tk/label.rb : treat label widget
#
require 'tk'
class TkLabel<TkWindow
TkCommandNames = ['label'.freeze].freeze
WidgetClassName = 'Label'.freeze
WidgetClassNames[WidgetClassName] = self
def create_self(keys)
if keys and keys != None
tk_call_without_enc('label', @path, *hash_kv(keys, true))
else
tk_call_without_enc('label', @path)
end
end
private :create_self
def textvariable(v)
configure 'textvariable', tk_trace_variable(v)
end
end

View File

@ -0,0 +1,20 @@
#
# tk/labelframe.rb : treat labelframe widget
#
require 'tk'
require 'tk/frame'
class TkLabelFrame<TkFrame
TkCommandNames = ['labelframe'.freeze].freeze
WidgetClassName = 'Labelframe'.freeze
WidgetClassNames[WidgetClassName] = self
def create_self(keys)
if keys and keys != None
tk_call_without_enc('labelframe', @path, *hash_kv(keys, true))
else
tk_call_without_enc('labelframe', @path)
end
end
private :create_self
end
TkLabelframe = TkLabelFrame

252
ext/tk/lib/tk/listbox.rb Normal file
View File

@ -0,0 +1,252 @@
#
# tk/listbox.rb : treat listbox widget
#
require 'tk'
require 'tk/scrollable'
require 'tk/txtwin_abst'
module TkTreatListItemFont
include TkTreatItemFont
ItemCMD = ['itemconfigure'.freeze, TkComm::None].freeze
def __conf_cmd(idx)
ItemCMD[idx]
end
def __item_pathname(tagOrId)
self.path + ';' + tagOrId.to_s
end
private :__conf_cmd, :__item_pathname
end
class TkListbox<TkTextWin
include TkTreatListItemFont
include Scrollable
TkCommandNames = ['listbox'.freeze].freeze
WidgetClassName = 'Listbox'.freeze
WidgetClassNames[WidgetClassName] = self
def create_self(keys)
if keys and keys != None
tk_call_without_enc('listbox', @path, *hash_kv(keys, true))
else
tk_call_without_enc('listbox', @path)
end
end
private :create_self
def activate(y)
tk_send_without_enc('activate', y)
self
end
def curselection
list(tk_send_without_enc('curselection'))
end
def get(first, last=nil)
if last
tk_split_simplelist(_fromUTF8(tk_send_without_enc('get', first, last)))
else
_fromUTF8(tk_send_without_enc('get', first))
end
end
def nearest(y)
tk_send_without_enc('nearest', y).to_i
end
def size
tk_send_without_enc('size').to_i
end
def selection_anchor(index)
tk_send_without_enc('selection', 'anchor', index)
self
end
def selection_clear(first, last=None)
tk_send_without_enc('selection', 'clear', first, last)
self
end
def selection_includes(index)
bool(tk_send_without_enc('selection', 'includes', index))
end
def selection_set(first, last=None)
tk_send_without_enc('selection', 'set', first, last)
self
end
def index(index)
tk_send_without_enc('index', index).to_i
end
def itemcget(index, key)
case key.to_s
when 'text', 'label', 'show'
_fromUTF8(tk_send_without_enc('itemcget', index, "-#{key}"))
when 'font', 'kanjifont'
#fnt = tk_tcl2ruby(tk_send('itemcget', index, "-#{key}"))
fnt = tk_tcl2ruby(_fromUTF8(tk_send_without_enc('itemcget', index,
'-font')))
unless fnt.kind_of?(TkFont)
fnt = tagfontobj(index, fnt)
end
if key.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
# obsolete; just for compatibility
fnt.kanji_font
else
fnt
end
else
tk_tcl2ruby(_fromUTF8(tk_send_without_enc('itemcget', index, "-#{key}")))
end
end
def itemconfigure(index, key, val=None)
if key.kind_of? Hash
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_without_enc('itemconfigure', index, *hash_kv(key, true))
end
else
if (key == 'font' || key == :font ||
key == 'kanjifont' || key == :kanjifont ||
key == 'latinfont' || key == :latinfont ||
key == 'asciifont' || key == :asciifont )
if val == None
tagfontobj(index)
else
tagfont_configure(index, {key=>val})
end
else
tk_call('itemconfigure', index, "-#{key}", val)
end
end
self
end
def itemconfiginfo(index, key=nil)
if TkComm::GET_CONFIGINFO_AS_ARRAY
if key
case key.to_s
when 'text', 'label', 'show'
conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure',index,"-#{key}")))
when 'font', 'kanjifont'
conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure',index,"-#{key}")))
conf[4] = tagfont_configinfo(index, conf[4])
else
conf = tk_split_list(_fromUTF8(tk_send_without_enc('itemconfigure',index,"-#{key}")))
end
conf[0] = conf[0][1..-1]
conf
else
ret = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', index))).collect{|conflist|
conf = tk_split_simplelist(conflist)
conf[0] = conf[0][1..-1]
case conf[0]
when 'text', 'label', 'show'
else
if conf[3]
if conf[3].index('{')
conf[3] = tk_split_list(conf[3])
else
conf[3] = tk_tcl2ruby(conf[3])
end
end
if conf[4]
if conf[4].index('{')
conf[4] = tk_split_list(conf[4])
else
conf[4] = tk_tcl2ruby(conf[4])
end
end
end
conf[1] = conf[1][1..-1] if conf.size == 2 # alias info
conf
}
fontconf = ret.assoc('font')
if fontconf
ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'}
fontconf[4] = tagfont_configinfo(index, fontconf[4])
ret.push(fontconf)
else
ret
end
end
else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
if key
case key.to_s
when 'text', 'label', 'show'
conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure',index,"-#{key}")))
when 'font', 'kanjifont'
conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure',index,"-#{key}")))
conf[4] = tagfont_configinfo(index, conf[4])
else
conf = tk_split_list(_fromUTF8(tk_send_without_enc('itemconfigure',index,"-#{key}")))
end
key = conf.shift[1..-1]
{ key => conf }
else
ret = {}
tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', index))).each{|conflist|
conf = tk_split_simplelist(conflist)
key = conf.shift[1..-1]
case key
when 'text', 'label', 'show'
else
if conf[2]
if conf[2].index('{')
conf[2] = tk_split_list(conf[2])
else
conf[2] = tk_tcl2ruby(conf[2])
end
end
if conf[3]
if conf[3].index('{')
conf[3] = tk_split_list(conf[3])
else
conf[3] = tk_tcl2ruby(conf[3])
end
end
end
if conf.size == 1
ret[key] = conf[0][1..-1] # alias info
else
ret[key] = conf
end
}
fontconf = ret['font']
if fontconf
ret.delete('font')
ret.delete('kanjifont')
fontconf[3] = tagfont_configinfo(index, fontconf[3])
ret['font'] = fontconf
end
ret
end
end
end
def current_itemconfiginfo(index, key=nil)
if TkComm::GET_CONFIGINFO_AS_ARRAY
if key
conf = itemconfiginfo(index, key)
{conf[0] => conf[4]}
else
ret = {}
itemconfiginfo(index).each{|conf|
ret[conf[0]] = conf[4] if conf.size > 2
}
ret
end
else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
ret = {}
itemconfiginfo(index, key).each{|k, conf|
ret[k] = conf[-1] if conf.kind_of?(Array)
}
ret
end
end
end

68
ext/tk/lib/tk/macpkg.rb Normal file
View File

@ -0,0 +1,68 @@
#
# tk/macpkg.rb : methods for Tcl/Tk packages for Macintosh
# 2000/11/22 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
#
# ATTENTION !!
# This is NOT TESTED. Because I have no test-environment.
#
#
require 'tk'
module Tk
def Tk.load_tclscript_rsrc(resource_name, file=None)
# Mac only
tk_call('source', '-rsrc', resource_name, file)
end
def Tk.load_tclscript_rsrcid(resource_id, file=None)
# Mac only
tk_call('source', '-rsrcid', resource_id, file)
end
end
module TkMacResource
extend Tk
extend TkMacResource
TkCommandNames = ['resource'.freeze].freeze
tk_call_without_enc('package', 'require', 'resource')
def close(rsrcRef)
tk_call('resource', 'close', rsrcRef)
end
def delete(rsrcType, opts=nil)
tk_call('resource', 'delete', *(hash_kv(opts) << rsrcType))
end
def files(rsrcRef=nil)
if rsrcRef
tk_call('resource', 'files', rsrcRef)
else
tk_split_simplelist(tk_call('resource', 'files'))
end
end
def list(rsrcType, rsrcRef=nil)
tk_split_simplelist(tk_call('resource', 'list', rsrcType, rsrcRef))
end
def open(fname, access=nil)
tk_call('resource', 'open', fname, access)
end
def read(rsrcType, rsrcID, rsrcRef=nil)
tk_call('resource', 'read', rsrcType, rsrcID, rsrcRef)
end
def types(rsrcRef=nil)
tk_split_simplelist(tk_call('resource', 'types', rsrcRef))
end
def write(rsrcType, data, opts=nil)
tk_call('resource', 'write', *(hash_kv(opts) << rsrcType << data))
end
module_function :close, :delete, :files, :list, :open, :read, :types, :write
end

460
ext/tk/lib/tk/menu.rb Normal file
View File

@ -0,0 +1,460 @@
#
# tk/menu.rb : treat menu and menubutton
#
require 'tk'
module TkTreatMenuEntryFont
include TkTreatItemFont
ItemCMD = ['entryconfigure'.freeze, TkComm::None].freeze
def __conf_cmd(idx)
ItemCMD[idx]
end
def __item_pathname(tagOrId)
self.path + ';' + tagOrId.to_s
end
private :__conf_cmd, :__item_pathname
end
class TkMenu<TkWindow
include TkTreatMenuEntryFont
TkCommandNames = ['menu'.freeze].freeze
WidgetClassName = 'Menu'.freeze
WidgetClassNames[WidgetClassName] = self
def create_self(keys)
if keys and keys != None
tk_call_without_enc('menu', @path, *hash_kv(keys, true))
else
tk_call_without_enc('menu', @path)
end
end
private :create_self
def activate(index)
tk_send_without_enc('activate', _get_eval_enc_str(index))
self
end
def add(type, keys=nil)
tk_send_without_enc('add', type, *hash_kv(keys, true))
self
end
def add_cascade(keys=nil)
add('cascade', keys)
end
def add_checkbutton(keys=nil)
add('checkbutton', keys)
end
def add_command(keys=nil)
add('command', keys)
end
def add_radiobutton(keys=nil)
add('radiobutton', keys)
end
def add_separator(keys=nil)
add('separator', keys)
end
def index(index)
ret = tk_send_without_enc('index', _get_eval_enc_str(index))
(ret == 'none')? nil: number(ret)
end
def invoke(index)
_fromUTF8(tk_send_without_enc('invoke', _get_eval_enc_str(index)))
end
def insert(index, type, keys=nil)
tk_send_without_enc('insert', _get_eval_enc_str(index),
type, *hash_kv(keys, true))
self
end
def delete(first, last=nil)
if last
tk_send_without_enc('delete', _get_eval_enc_str(first),
_get_eval_enc_str(last))
else
tk_send_without_enc('delete', _get_eval_enc_str(first))
end
self
end
def popup(x, y, index=nil)
if index
tk_call_without_enc('tk_popup', path, x, y,
_get_eval_enc_str(index))
else
tk_call_without_enc('tk_popup', path, x, y)
end
self
end
def post(x, y)
_fromUTF8(tk_send_without_enc('post', x, y))
end
def postcascade(index)
tk_send_without_enc('postcascade', _get_eval_enc_str(index))
self
end
def postcommand(cmd=Proc.new)
configure_cmd 'postcommand', cmd
self
end
def set_focus
tk_call_without_enc('tk_menuSetFocus', path)
self
end
def tearoffcommand(cmd=Proc.new)
configure_cmd 'tearoffcommand', cmd
self
end
def menutype(index)
tk_send_without_enc('type', _get_eval_enc_str(index))
end
def unpost
tk_send_without_enc('unpost')
self
end
def yposition(index)
number(tk_send_without_enc('yposition', _get_eval_enc_str(index)))
end
def entrycget(index, key)
case key.to_s
when 'text', 'label', 'show'
_fromUTF8(tk_send_without_enc('entrycget',
_get_eval_enc_str(index), "-#{key}"))
when 'font', 'kanjifont'
#fnt = tk_tcl2ruby(tk_send('entrycget', index, "-#{key}"))
fnt = tk_tcl2ruby(_fromUTF8(tk_send_without_enc('entrycget', _get_eval_enc_str(index), '-font')))
unless fnt.kind_of?(TkFont)
fnt = tagfontobj(index, fnt)
end
if key.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
# obsolete; just for compatibility
fnt.kanji_font
else
fnt
end
else
tk_tcl2ruby(_fromUTF8(tk_send_without_enc('entrycget', _get_eval_enc_str(index), "-#{key}")))
end
end
def entryconfigure(index, key, val=None)
if key.kind_of? Hash
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_without_enc('entryconfigure', _get_eval_enc_str(index),
*hash_kv(key, true))
end
else
if (key == 'font' || key == :font ||
key == 'kanjifont' || key == :kanjifont ||
key == 'latinfont' || key == :latinfont ||
key == 'asciifont' || key == :asciifont )
if val == None
tagfontobj(index)
else
tagfont_configure(index, {key=>val})
end
else
tk_call('entryconfigure', index, "-#{key}", val)
end
end
self
end
def entryconfiginfo(index, key=nil)
if TkComm::GET_CONFIGINFO_AS_ARRAY
if key
case key.to_s
when 'text', 'label', 'show'
conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('entryconfigure',_get_eval_enc_str(index),"-#{key}")))
when 'font', 'kanjifont'
conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('entryconfigure',_get_eval_enc_str(index),"-#{key}")))
conf[4] = tagfont_configinfo(index, conf[4])
else
conf = tk_split_list(_fromUTF8(tk_send_without_enc('entryconfigure',_get_eval_enc_str(index),"-#{key}")))
end
conf[0] = conf[0][1..-1]
conf
else
ret = tk_split_simplelist(_fromUTF8(tk_send_without_enc('entryconfigure', _get_eval_enc_str(index)))).collect{|conflist|
conf = tk_split_simplelist(conflist)
conf[0] = conf[0][1..-1]
case conf[0]
when 'text', 'label', 'show'
else
if conf[3]
if conf[3].index('{')
conf[3] = tk_split_list(conf[3])
else
conf[3] = tk_tcl2ruby(conf[3])
end
end
if conf[4]
if conf[4].index('{')
conf[4] = tk_split_list(conf[4])
else
conf[4] = tk_tcl2ruby(conf[4])
end
end
end
conf[1] = conf[1][1..-1] if conf.size == 2 # alias info
conf
}
if fontconf
ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'}
fontconf[4] = tagfont_configinfo(index, fontconf[4])
ret.push(fontconf)
else
ret
end
end
else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
if key
case key.to_s
when 'text', 'label', 'show'
conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('entryconfigure',_get_eval_enc_str(index),"-#{key}")))
when 'font', 'kanjifont'
conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('entryconfigure',_get_eval_enc_str(index),"-#{key}")))
conf[4] = tagfont_configinfo(index, conf[4])
else
conf = tk_split_list(_fromUTF8(tk_send_without_enc('entryconfigure',_get_eval_enc_str(index),"-#{key}")))
end
key = conf.shift[1..-1]
{ key => conf }
else
ret = {}
tk_split_simplelist(_fromUTF8(tk_send_without_enc('entryconfigure', _get_eval_enc_str(index)))).each{|conflist|
conf = tk_split_simplelist(conflist)
key = conf.shift[1..-1]
case key
when 'text', 'label', 'show'
else
if conf[2]
if conf[2].index('{')
conf[2] = tk_split_list(conf[2])
else
conf[2] = tk_tcl2ruby(conf[2])
end
end
if conf[3]
if conf[3].index('{')
conf[3] = tk_split_list(conf[3])
else
conf[3] = tk_tcl2ruby(conf[3])
end
end
end
if conf.size == 1
ret[key] = conf[0][1..-1] # alias info
else
ret[key] = conf
end
}
fontconf = ret['font']
if fontconf
ret.delete('font')
ret.delete('kanjifont')
fontconf[3] = tagfont_configinfo(index, fontconf[3])
ret['font'] = fontconf
end
ret
end
end
end
def current_entryconfiginfo(index, key=nil)
if TkComm::GET_CONFIGINFO_AS_ARRAY
if key
conf = entryconfiginfo(index, key)
{conf[0] => conf[4]}
else
ret = {}
entryconfiginfo(index).each{|conf|
ret[conf[0]] = conf[4] if conf.size > 2
}
ret
end
else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
ret = {}
entryconfiginfo(index, key).each{|k, conf|
ret[k] = conf[-1] if conf.kind_of?(Array)
}
ret
end
end
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, widgetname)
tk_call_without_enc(@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
unless parent.kind_of? TkMenu
fail ArgumentError, "parent must be a TkMenu object"
end
# @path = Kernel.format("%s.%s", parent.path, self.class::SYSMENU_NAME)
@path = parent_path + '.' + self.class::SYSMENU_NAME
#TkComm::Tk_WINDOWS[@path] = self
TkCore::INTERP.tk_windows[@path] = self
if self.method(:create_self).arity == 0
p 'create_self has no arg' if $DEBUG
create_self
configure(keys) if keys
else
p 'create_self has an arg' if $DEBUG
create_self(keys)
end
end
end
class TkSysMenu_Help<TkMenu
# for all platform
include TkSystemMenu
SYSMENU_NAME = 'help'
end
class TkSysMenu_System<TkMenu
# for Windows
include TkSystemMenu
SYSMENU_NAME = 'system'
end
class TkSysMenu_Apple<TkMenu
# for Machintosh
include TkSystemMenu
SYSMENU_NAME = 'apple'
end
class TkMenubutton<TkLabel
TkCommandNames = ['menubutton'.freeze].freeze
WidgetClassName = 'Menubutton'.freeze
WidgetClassNames[WidgetClassName] = self
def create_self(keys)
if keys and keys != None
tk_call_without_enc('menubutton', @path, *hash_kv(keys, true))
else
tk_call_without_enc('menubutton', @path)
end
end
private :create_self
end
class TkOptionMenubutton<TkMenubutton
TkCommandNames = ['tk_optionMenu'.freeze].freeze
class OptionMenu<TkMenu
def initialize(path) #==> return value of tk_optionMenu
@path = path
#TkComm::Tk_WINDOWS[@path] = self
TkCore::INTERP.tk_windows[@path] = self
end
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 'variable option must be TkVariable' unless var.kind_of? TkVariable
@variable = var
firstval = @variable.value unless firstval
@variable.value = firstval
install_win(if parent then parent.path end)
@menu = OptionMenu.new(tk_call('tk_optionMenu', @path, @variable.id,
firstval, *vals))
end
def value
@variable.value
end
def activate(index)
@menu.activate(index)
self
end
def add(value)
@menu.add('radiobutton', 'variable'=>@variable,
'label'=>value, 'value'=>value)
self
end
def index(index)
@menu.index(index)
end
def invoke(index)
@menu.invoke(index)
end
def insert(index, value)
@menu.add(index, 'radiobutton', 'variable'=>@variable,
'label'=>value, 'value'=>value)
self
end
def delete(index, last=None)
@menu.delete(index, last)
self
end
def yposition(index)
@menu.yposition(index)
end
def menu
@menu
end
def menucget(key)
@menu.cget(key)
end
def menuconfigure(key, val=None)
@menu.configure(key, val)
self
end
def menuconfiginfo(key=nil)
@menu.configinfo(key)
end
def current_menuconfiginfo(key=nil)
@menu.current_configinfo(key)
end
def entrycget(index, key)
@menu.entrycget(index, key)
end
def entryconfigure(index, key, val=None)
@menu.entryconfigure(index, key, val)
self
end
def entryconfiginfo(index, key=nil)
@menu.entryconfiginfo(index, key)
end
def current_entryconfiginfo(index, key=nil)
@menu.current_entryconfiginfo(index, key)
end
end

144
ext/tk/lib/tk/menubar.rb Normal file
View File

@ -0,0 +1,144 @@
#
# tk/menubar.rb
#
# Copyright (C) 1998 maeda shugo. All rights reserved.
# This file can be distributed under the terms of the Ruby.
# Usage:
#
# menu_spec = [
# [['File', 0],
# ['Open', proc{puts('Open clicked')}, 0],
# '---',
# ['Quit', proc{exit}, 0]],
# [['Edit', 0],
# ['Cut', proc{puts('Cut clicked')}, 2],
# ['Copy', proc{puts('Copy clicked')}, 0],
# ['Paste', proc{puts('Paste clicked')}, 0]]
# ]
# menubar = TkMenubar.new(nil, menu_spec,
# 'tearoff'=>false,
# 'foreground'=>'grey40',
# 'activeforeground'=>'red',
# 'font'=>'-adobe-helvetica-bold-r-*--12-*-iso8859-1')
# menubar.pack('side'=>'top', 'fill'=>'x')
#
#
# OR
#
#
# menubar = TkMenubar.new
# menubar.add_menu([['File', 0],
# ['Open', proc{puts('Open clicked')}, 0],
# '---',
# ['Quit', proc{exit}, 0]])
# menubar.add_menu([['Edit', 0],
# ['Cut', proc{puts('Cut clicked')}, 2],
# ['Copy', proc{puts('Copy clicked')}, 0],
# ['Paste', proc{puts('Paste clicked')}, 0]])
# menubar.configure('tearoff', false)
# menubar.configure('foreground', 'grey40')
# menubar.configure('activeforeground', 'red')
# menubar.configure('font', '-adobe-helvetica-bold-r-*--12-*-iso8859-1')
# menubar.pack('side'=>'top', 'fill'=>'x')
# The format of the menu_spec is:
# [
# [
# [button text, underline, accelerator],
# [menu label, command, underline, accelerator],
# '---', # separator
# ...
# ],
# ...
# ]
# underline and accelerator are optional parameters.
# Hashes are OK instead of Arrays.
# To use add_menu, configuration must be done by calling configure after
# adding all menus by add_menu, not by the constructor arguments.
require 'tk'
require 'tk/frame'
class TkMenubar<TkFrame
include TkComposite
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)
end
@menus = []
if spec
for menu_info in spec
add_menu(menu_info)
end
end
if options
for key, value in options
configure(key, value)
end
end
end
def add_menu(menu_info)
btn_info = menu_info.shift
mbtn = TkMenubutton.new(@frame)
if btn_info.kind_of?(Hash)
for key, value in btn_info
mbtn.configure(key, value)
end
elsif btn_info.kind_of?(Array)
mbtn.configure('text', btn_info[0]) if btn_info[0]
mbtn.configure('underline', btn_info[1]) if btn_info[1]
mbtn.configure('accelerator', btn_info[2]) if btn_info[2]
else
mbtn.configure('text', btn_info)
end
menu = TkMenu.new(mbtn)
for item_info in menu_info
if item_info.kind_of?(Hash)
menu.add('command', item_info)
elsif item_info.kind_of?(Array)
options = {}
options['label'] = item_info[0] if item_info[0]
options['command'] = item_info[1] if item_info[1]
options['underline'] = item_info[2] if item_info[2]
options['accelerator'] = item_info[3] if item_info[3]
menu.add('command', options)
elsif /^-+$/ =~ item_info
menu.add('sep')
else
menu.add('command', 'label' => item_info)
end
end
mbtn.menu(menu)
@menus.push([mbtn, menu])
delegate('tearoff', menu)
delegate('foreground', mbtn, menu)
delegate('background', mbtn, menu)
delegate('disabledforeground', mbtn, menu)
delegate('activeforeground', mbtn, menu)
delegate('activebackground', mbtn, menu)
delegate('font', mbtn, menu)
delegate('kanjifont', mbtn, menu)
mbtn.pack('side' => 'left')
end
def [](index)
return @menus[index]
end
end

19
ext/tk/lib/tk/message.rb Normal file
View File

@ -0,0 +1,19 @@
#
# tk/message.rb : treat message widget
#
require 'tk'
require 'tk/label'
class TkMessage<TkLabel
TkCommandNames = ['message'.freeze].freeze
WidgetClassName = 'Message'.freeze
WidgetClassNames[WidgetClassName] = self
def create_self(keys)
if keys and keys != None
tk_call_without_enc('message', @path, *hash_kv(keys, true))
else
tk_call_without_enc('message', @path)
end
end
private :create_self
end

33
ext/tk/lib/tk/mngfocus.rb Normal file
View File

@ -0,0 +1,33 @@
#
# tk/mngfocus.rb : methods for Tcl/Tk standard library 'focus.tcl'
# by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
#
require 'tk'
module TkManageFocus
extend Tk
TkCommandNames = [
'tk_focusFollowMouse'.freeze,
'tk_focusNext'.freeze,
'tk_focusPrev'.freeze
].freeze
def TkManageFocus.followsMouse
tk_call_without_enc('tk_focusFollowsMouse')
end
def TkManageFocus.next(window)
tk_tcl2ruby(tk_call('tk_focusNext', window))
end
def focusNext
TkManageFocus.next(self)
end
def TkManageFocus.prev(window)
tk_tcl2ruby(tk_call('tk_focusPrev', window))
end
def focusPrev
TkManageFocus.prev(self)
end
end

268
ext/tk/lib/tk/msgcat.rb Normal file
View File

@ -0,0 +1,268 @@
#
# tk/msgcat.rb : methods for Tcl message catalog
# by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
#
require 'tk'
#class TkMsgCatalog
class TkMsgCatalog < TkObject
include TkCore
extend Tk
#extend TkMsgCatalog
TkCommandNames = [
'::msgcat::mc'.freeze,
'::msgcat::mcmax'.freeze,
'::msgcat::mclocale'.freeze,
'::msgcat::mcpreferences'.freeze,
'::msgcat::mcload'.freeze,
'::msgcat::mcset'.freeze,
'::msgcat::mcmset'.freeze,
'::msgcat::mcunknown'.freeze
].freeze
tk_call_without_enc('package', 'require', 'Tcl', '8.2')
if self.const_defined? :FORCE_VERSION
tk_call_without_enc('package', 'require', 'msgcat', FORCE_VERSION)
else
tk_call_without_enc('package', 'require', 'msgcat')
end
MSGCAT_EXT = '.msg'
UNKNOWN_CBTBL = Hash.new{|hash,key| hash[key] = {}}.taint
TkCore::INTERP.add_tk_procs('::msgcat::mcunknown', 'args', <<-'EOL')
if {[set st [catch {eval {ruby_cmd TkMsgCatalog callback} [namespace current] $args} ret]] != 0} {
#return -code $st $ret
set idx [string first "\n\n" $ret]
if {$idx > 0} {
return -code $st \
-errorinfo [string range $ret [expr $idx + 2] \
[string length $ret]] \
[string range $ret 0 [expr $idx - 1]]
} else {
return -code $st $ret
}
} else {
return $ret
}
EOL
def self.callback(namespace, locale, src_str)
cmd_tbl = TkMsgCatalog::UNKNOWN_CBTBL[TkCore::INTERP.__getip]
cmd = cmd_tbl[namespace]
cmd = cmd_tbl['::'] unless cmd # use global scope as interp default
return src_str unless cmd # no cmd -> return src-str (default action)
begin
cmd.call(locale, src_str)
rescue Exception => e
begin
msg = _toUTF8(e.class.inspect) + ': ' +
_toUTF8(e.message) + "\n" +
"\n---< backtrace of Ruby side >-----\n" +
_toUTF8(e.backtrace.join("\n")) +
"\n---< backtrace of Tk side >-------"
msg.instance_variable_set(:@encoding, 'utf-8')
rescue Exception
msg = e.class.inspect + ': ' + e.message + "\n" +
"\n---< backtrace of Ruby side >-----\n" +
e.backtrace.join("\n") +
"\n---< backtrace of Tk side >-------"
end
fail(e, msg)
end
end
def initialize(namespace = nil)
if namespace.kind_of?(TkNamespace)
@namespace = namespace
elsif namespace == nil
@namespace = TkNamespace.new('::') # global namespace
else
@namespace = TkNamespace.new(namespace)
end
@path = @namespace.path
@msgcat_ext = '.msg'
end
attr_accessor :msgcat_ext
def method_missing(id, *args)
# locale(src, trans) ==> set_translation(locale, src, trans)
loc = id.id2name
case args.length
when 0 # set locale
self.locale=(loc)
when 1 # src only, or trans_list
if args[0].kind_of?(Array)
# trans_list
#list = args[0].collect{|src, trans|
# [ Tk::UTF8_String.new(src), Tk::UTF8_String.new(trans) ]
#}
self.set_translation_list(loc, args[0])
else
# src
#self.set_translation(loc, Tk::UTF8_String.new(args[0]))
self.set_translation(loc, args[0])
end
when 2 # src and trans, or, trans_list and enc
if args[0].kind_of?(Array)
else
#self.set_translation(loc, args[0], Tk::UTF8_String.new(args[1]))
self.set_translation(loc, *args)
end
when 3 # src and trans and enc
self.set_translation(loc, *args)
else
fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at
end
end
# *args ::= form, arg, arg, ...
def self.translate(*args)
dst = args.collect{|src|
tk_call_without_enc('::msgcat::mc', _get_eval_string(src, true))
}
Tk.UTF8_String(sprintf(*dst))
end
class << self
alias mc translate
alias [] translate
end
def translate(*args)
dst = args.collect{|src|
@namespace.eval{tk_call_without_enc('::msgcat::mc',
_get_eval_string(src, true))}
}
Tk.UTF8_String(sprintf(*dst))
end
alias mc translate
alias [] translate
def self.maxlen(*src_strings)
tk_call('::msgcat::mcmax', *src_strings).to_i
end
def maxlen(*src_strings)
@namespace.eval{tk_call('::msgcat::mcmax', *src_strings).to_i}
end
def self.locale
tk_call('::msgcat::mclocale')
end
def locale
@namespace.eval{tk_call('::msgcat::mclocale')}
end
def self.locale=(locale)
tk_call('::msgcat::mclocale', locale)
end
def locale=(locale)
@namespace.eval{tk_call('::msgcat::mclocale', locale)}
end
def self.preferences
tk_split_simplelist(tk_call('::msgcat::mcpreferences'))
end
def preferences
tk_split_simplelist(@namespace.eval{tk_call('::msgcat::mcpreferences')})
end
def self.load_tk(dir)
number(tk_call('::msgcat::mcload', dir))
end
def self.load_rb(dir)
count = 0
preferences().each{|loc|
file = File.join(dir, loc + self::MSGCAT_EXT)
if File.readable?(file)
count += 1
eval(open(file){|f| f.read})
end
}
count
end
def load_tk(dir)
number(@namespace.eval{tk_call('::msgcat::mcload', dir)})
end
def load_rb(dir)
count = 0
preferences().each{|loc|
file = File.join(dir, loc + @msgcat_ext)
if File.readable?(file)
count += 1
@namespace.eval(open(file){|f| f.read})
end
}
count
end
def self.load(dir)
self.load_rb(dir)
end
alias load load_rb
def self.set_translation(locale, src_str, trans_str=None, enc='utf-8')
trans_str = Tk.UTF8_String(_toUTF8(trans_str, enc)) if trans_str != None
Tk.UTF8_String(tk_call_without_enc('::msgcat::mcset',
locale,
_get_eval_string(src_str, true),
trans_str))
end
def set_translation(locale, src_str, trans_str=None, enc='utf-8')
trans_str = Tk.UTF8_String(_toUTF8(trans_str, enc)) if trans_str != None
Tk.UTF8_String(@namespace.eval{
tk_call_without_enc('::msgcat::mcset',
locale,
_get_eval_string(src_str, true),
trans_str)
})
end
def self.set_translation_list(locale, trans_list, enc='utf-8')
# trans_list ::= [ [src, trans], [src, trans], ... ]
list = []
trans_list.each{|src, trans|
if trans && trans != None
list << _get_eval_string(src, true)
list << Tk.UTF8_Stirng(_toUTF8(trans, enc))
else
list << _get_eval_string(src, true) << ''
end
}
number(tk_call_without_enc('::msgcat::mcmset', locale, list))
end
def set_translation_list(locale, trans_list, enc='utf-8')
# trans_list ::= [ [src, trans], [src, trans], ... ]
list = []
trans_list.each{|src, trans|
if trans && trans != None
list << _get_eval_string(src, true)
list << Tk.UTF8_String(_toUTF8(trans, enc))
else
list << _get_eval_string(src, true) << ''
end
}
number(@namespace.eval{
tk_call_without_enc('::msgcat::mcmset', locale, list)
})
end
def self.def_unknown_proc(cmd=Proc.new)
TkMsgCatalog::UNKNOWN_CBTBL[TkCore::INTERP.__getip]['::'] = cmd
end
def def_unknown_proc(cmd=Proc.new)
TkMsgCatalog::UNKNOWN_CBTBL[TkCore::INTERP.__getip][@namespace.path] = cmd
end
end
TkMsgCat = TkMsgCatalog

293
ext/tk/lib/tk/namespace.rb Normal file
View File

@ -0,0 +1,293 @@
#
# tk/namespace.rb : methods to manipulate Tcl/Tk namespace
# by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
#
require 'tk'
class TkNamespace < TkObject
extend Tk
TkCommandNames = [
'namespace'.freeze,
].freeze
Tk_Namespace_ID_TBL = TkCore::INTERP.create_table
Tk_Namespace_ID = ["ns".freeze, "00000".taint].freeze
class ScopeArgs < Array
include Tk
# alias __tk_call tk_call
# alias __tk_call_without_enc tk_call_without_enc
# alias __tk_call_with_enc tk_call_with_enc
def tk_call(*args)
#super('namespace', 'eval', @namespace, *args)
args = args.collect{|arg| (s = _get_eval_string(arg))? s: ''}
super('namespace', 'eval', @namespace,
TkCore::INTERP._merge_tklist(*args))
end
def tk_call_without_enc(*args)
#super('namespace', 'eval', @namespace, *args)
args = args.collect{|arg| (s = _get_eval_string(arg))? s: ''}
super('namespace', 'eval', @namespace,
TkCore::INTERP._merge_tklist(*args))
end
def tk_call_with_enc(*args)
#super('namespace', 'eval', @namespace, *args)
args = args.collect{|arg| (s = _get_eval_string(arg))? s: ''}
super('namespace', 'eval', @namespace,
TkCore::INTERP._merge_tklist(*args))
end
def initialize(namespace, *args)
@namespace = namespace
super(args.size)
self.replace(args)
end
end
class NsCode < TkObject
def initialize(scope)
@scope = scope + ' '
end
def path
@scope
end
def to_eval
@scope
end
def call(*args)
TkCore::INTERP._eval_without_enc(@scope + array2tk_list(args))
end
end
alias __tk_call tk_call
alias __tk_call_without_enc tk_call_without_enc
alias __tk_call_with_enc tk_call_with_enc
def tk_call(*args)
#super('namespace', 'eval', @fullname, *args)
args = args.collect{|arg| (s = _get_eval_string(arg))? s: ''}
super('namespace', 'eval', @fullname,
TkCore::INTERP._merge_tklist(*args))
end
def tk_call_without_enc(*args)
#super('namespace', 'eval', @fullname, *args)
args = args.collect{|arg| (s = _get_eval_string(arg))? s: ''}
super('namespace', 'eval', @fullname,
TkCore::INTERP._merge_tklist(*args))
end
def tk_call_with_enc(*args)
#super('namespace', 'eval', @fullname, *args)
args = args.collect{|arg| (s = _get_eval_string(arg))? s: ''}
super('namespace', 'eval', @fullname,
TkCore::INTERP._merge_tklist(*args))
end
alias ns_tk_call tk_call
alias ns_tk_call_without_enc tk_call_without_enc
alias ns_tk_call_with_enc tk_call_with_enc
def initialize(name = nil, parent = nil)
unless name
name = Tk_Namespace_ID.join('')
Tk_Namespace_ID[1].succ!
end
name = __tk_call('namespace', 'current') if name == ''
if parent
if parent =~ /^::/
if name =~ /^::/
@fullname = parent + name
else
@fullname = parent +'::'+ name
end
else
ancestor = __tk_call('namespace', 'current')
ancestor = '' if ancestor == '::'
if name =~ /^::/
@fullname = ancestor + '::' + parent + name
else
@fullname = ancestor + '::'+ parent +'::'+ name
end
end
else # parent == nil
ancestor = __tk_call('namespace', 'current')
ancestor = '' if ancestor == '::'
if name =~ /^::/
@fullname = name
else
@fullname = ancestor + '::' + name
end
end
@path = @fullname
@parent = __tk_call('namespace', 'qualifiers', @fullname)
@name = __tk_call('namespace', 'tail', @fullname)
# create namespace
__tk_call('namespace', 'eval', @fullname, '')
Tk_Namespace_ID_TBL[@fullname] = self
end
def self.children(*args)
# args ::= [<namespace>] [<pattern>]
# <pattern> must be glob-style pattern
tk_split_simplelist(tk_call('namespace', 'children', *args)).collect{|ns|
# ns is fullname
if Tk_Namesapce_ID.key?(ns)
Tk_Namesapce_ID[ns]
else
ns
end
}
end
def children(pattern=None)
TkNamespace.children(@fullname, pattern)
end
def self.code(script = Proc.new)
TkNamespace.new('').code(script)
end
def code(script = Proc.new)
if script.kind_of?(String)
cmd = proc{|*args| ScopeArgs.new(@fullname,*args).instance_eval(script)}
elsif script.kind_of?(Proc)
cmd = proc{|*args| ScopeArgs.new(@fullname,*args).instance_eval(&script)}
else
fail ArgumentError, "String or Proc is expected"
end
TkNamespace::NsCode.new(tk_call_without_enc('namespace', 'code',
_get_eval_string(cmd, false)))
end
def self.current
tk_call('namespace', 'current')
end
def current_namespace
# ns_tk_call('namespace', 'current')
@fullname
end
alias current current_namespace
def self.delete(*ns_list)
tk_call('namespace', 'delete', *ns_list)
end
def delete
TkNamespece.delete(@fullname)
end
def self.ensemble_create(*keys)
tk_call('namespace', 'ensemble', 'create', *hash_kv(keys))
end
def self.ensemble_configure(cmd, slot, value=None)
if slot.kind_of?(Hash)
tk_call('namespace', 'ensemble', 'configure', cmd, *hash_kv(slot))
else
tk_call('namespace', 'ensemble', 'configure', cmd, '-'+slot.to_s, value)
end
end
def self.ensemble_configinfo(cmd, slot = nil)
if slot
tk_call('namespace', 'ensemble', 'configure', cmd, '-' + slot.to_s)
else
inf = {}
Hash(*tk_split_simplelist(tk_call('namespace', 'ensemble', 'configure', cmd))).each{|k, v| inf[k[1..-1]] = v}
inf
end
end
def self.ensemble_exist?(cmd)
bool(tk_call('namespace', 'ensemble', 'exists', cmd))
end
def self.eval(namespace, cmd = Proc.new, *args)
#tk_call('namespace', 'eval', namespace, cmd, *args)
TkNamespace.new(namespece).eval(cmd, *args)
end
def eval(cmd = Proc.new, *args)
#TkNamespace.eval(@fullname, cmd, *args)
#ns_tk_call(cmd, *args)
code_obj = code(cmd)
ret = code_obj.call(*args)
uninstall_cmd(TkCore::INTERP._split_tklist(code_obj.path)[-1])
ret
end
def self.exist?(ns)
bool(tk_call('namespace', 'exists', ns))
end
def exist?
TkNamespece.delete(@fullname)
end
def self.export(*patterns)
tk_call('namespace', 'export', *patterns)
end
def self.export_with_clear(*patterns)
tk_call('namespace', 'export', '-clear', *patterns)
end
def export
TkNamespace.export(@fullname)
end
def export_with_clear
TkNamespace.export_with_clear(@fullname)
end
def self.forget(*patterns)
tk_call('namespace', 'forget', *patterns)
end
def forget
TkNamespace.forget(@fullname)
end
def self.import(*patterns)
tk_call('namespace', 'import', *patterns)
end
def self.force_import(*patterns)
tk_call('namespace', 'import', '-force', *patterns)
end
def import
TkNamespace.import(@fullname)
end
def force_import
TkNamespace.force_import(@fullname)
end
def self.inscope(namespace, script, *args)
tk_call('namespace', 'inscope', namespace, script, *args)
end
def inscope(script, *args)
TkNamespace(@fullname, script, *args)
end
def self.origin(cmd)
tk_call('namespace', 'origin', cmd)
end
def self.parent(namespace=None)
ns = tk_call('namespace', 'parent', namespace)
if Tk_Namesapce_ID.key?(ns)
Tk_Namesapce_ID[ns]
else
ns
end
end
def parent
tk_call('namespace', 'parent', @fullname)
end
def self.qualifiers(str)
tk_call('namespace', 'qualifiers', str)
end
def self.tail(str)
tk_call('namespace', 'tail', str)
end
def self.which(name)
tk_call('namespace', 'which', name)
end
def self.which_command(name)
tk_call('namespace', 'which', '-command', name)
end
def self.which_variable(name)
tk_call('namespace', 'which', '-variable', name)
end
end

297
ext/tk/lib/tk/optiondb.rb Normal file
View File

@ -0,0 +1,297 @@
#
# tk/optiondb.rb : treat option database
#
require 'tk'
module TkOptionDB
include Tk
extend Tk
TkCommandNames = ['option'.freeze].freeze
module Priority
WidgetDefault = 20
StartupFile = 40
UserDefault = 60
Interactive = 80
end
def add(pat, value, pri=None)
if $SAFE >= 4
fail SecurityError, "can't call 'TkOptionDB.add' at $SAFE >= 4"
end
tk_call('option', 'add', pat, value, pri)
end
def clear
if $SAFE >= 4
fail SecurityError, "can't call 'TkOptionDB.crear' at $SAFE >= 4"
end
tk_call_without_enc('option', 'clear')
end
def get(win, name, klass)
tk_call('option', 'get', win ,name, klass)
end
def readfile(file, pri=None)
tk_call('option', 'readfile', file, pri)
end
module_function :add, :clear, :get, :readfile
def read_entries(file, f_enc=nil)
if TkCore::INTERP.safe?
fail SecurityError,
"can't call 'TkOptionDB.read_entries' on a safe interpreter"
end
i_enc = Tk.encoding()
unless f_enc
f_enc = i_enc
end
ent = []
cline = ''
open(file, 'r') {|f|
while line = f.gets
cline += line.chomp!
case cline
when /\\$/ # continue
cline.chop!
next
when /^\s*(!|#)/ # coment
cline = ''
next
when /^([^:]+):(.*)$/
pat = $1.strip
val = $2.lstrip
p "ResourceDB: #{[pat, val].inspect}" if $DEBUG
pat = TkCore::INTERP._toUTF8(pat, f_enc)
pat = TkCore::INTERP._fromUTF8(pat, i_enc)
val = TkCore::INTERP._toUTF8(val, f_enc)
val = TkCore::INTERP._fromUTF8(val, i_enc)
ent << [pat, val]
cline = ''
else # unknown --> ignore
cline = ''
next
end
end
}
ent
end
module_function :read_entries
def read_with_encoding(file, f_enc=nil, pri=None)
# try to read the file as an OptionDB file
read_entries(file, f_enc).each{|pat, val|
add(pat, val, pri)
}
=begin
i_enc = Tk.encoding()
unless f_enc
f_enc = i_enc
end
cline = ''
open(file, 'r') {|f|
while line = f.gets
cline += line.chomp!
case cline
when /\\$/ # continue
cline.chop!
next
when /^\s*!/ # coment
cline = ''
next
when /^([^:]+):\s(.*)$/
pat = $1
val = $2
p "ResourceDB: #{[pat, val].inspect}" if $DEBUG
pat = TkCore::INTERP._toUTF8(pat, f_enc)
pat = TkCore::INTERP._fromUTF8(pat, i_enc)
val = TkCore::INTERP._toUTF8(val, f_enc)
val = TkCore::INTERP._fromUTF8(val, i_enc)
add(pat, val, pri)
cline = ''
else # unknown --> ignore
cline = ''
next
end
end
}
=end
end
module_function :read_with_encoding
# support procs on the resource database
@@resource_proc_class = Class.new
class << @@resource_proc_class
private :new
CARRIER = '.'.freeze
METHOD_TBL = TkCore::INTERP.create_table
ADD_METHOD = false
SAFE_MODE = 4
=begin
def __closed_block_check__(str)
depth = 0
str.scan(/[{}]/){|x|
if x == "{"
depth += 1
elsif x == "}"
depth -= 1
end
if depth <= 0 && !($' =~ /\A\s*\Z/)
fail RuntimeError, "bad string for procedure : #{str.inspect}"
end
}
str
end
private :__closed_block_check__
=end
def __check_proc_string__(str)
# If you want to check the proc_string, do it in this method.
# Please define this in the block given to 'new_proc_class' method.
str
end
def method_missing(id, *args)
res_proc, proc_str = self::METHOD_TBL[id]
proc_source = TkOptionDB.get(self::CARRIER, id.id2name, '').strip
res_proc = nil if proc_str != proc_source # resource is changed
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 = proc_source
proc_str = '{' + proc_str + '}' unless /\A\{.*\}\Z/ =~ proc_str
#proc_str = __closed_block_check__(proc_str)
proc_str = __check_proc_string__(proc_str)
res_proc = proc{
begin
eval("$SAFE = #{self::SAFE_MODE};\nProc.new" + proc_str)
rescue SyntaxError=>err
raise SyntaxError,
TkCore::INTERP._toUTF8(err.message.gsub(/\(eval\):\d:/,
"(#{id.id2name}):"))
end
}.call
self::METHOD_TBL[id] = [res_proc, proc_source]
end
res_proc.call(*args)
end
private :__check_proc_string__, :method_missing
end
@@resource_proc_class.freeze
def __create_new_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_without_enc('frame', @path, '-class', klass)
body = <<-"EOD"
class #{klass} < TkOptionDB.module_eval('@@resource_proc_class')
CARRIER = '#{carrier}'.freeze
METHOD_TBL = TkCore::INTERP.create_table
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('TkOptionDB::' + klass)
end
end
module_function :__create_new_class
private_class_method :__create_new_class
def __remove_methods_of_proc_class(klass)
# for security, make these methods invalid
class << klass
attr_reader :class_eval, :name, :superclass,
:ancestors, :const_defined?, :const_get, :const_set,
:constants, :included_modules, :instance_methods,
:method_defined?, :module_eval, :private_instance_methods,
:protected_instance_methods, :public_instance_methods,
:remove_const, :remove_method, :undef_method,
:to_s, :inspect, :display, :method, :methods,
:instance_eval, :instance_variables, :kind_of?, :is_a?,
:private_methods, :protected_methods, :public_methods
end
end
module_function :__remove_methods_of_proc_class
private_class_method :__remove_methods_of_proc_class
RAND_BASE_CNT = [0]
RAND_BASE_HEAD = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
RAND_BASE_CHAR = RAND_BASE_HEAD + 'abcdefghijklmnopqrstuvwxyz0123456789_'
def __get_random_basename
name = '%s%03d' % [RAND_BASE_HEAD[rand(RAND_BASE_HEAD.size),1],
RAND_BASE_CNT[0]]
len = RAND_BASE_CHAR.size
(6+rand(10)).times{
name << RAND_BASE_CHAR[rand(len),1]
}
RAND_BASE_CNT[0] = RAND_BASE_CNT[0] + 1
name
end
module_function :__get_random_basename
private_class_method :__get_random_basename
# define new proc class :
# If you want to modify the new class or create a new subclass,
# you must do such operation in the block parameter.
# Because the created class is flozen after evaluating the block.
def new_proc_class(klass, func, safe = 4, add = false, parent = nil, &b)
new_klass = __create_new_class(klass, func, safe, add, parent)
new_klass.class_eval(&b) if block_given?
__remove_methods_of_proc_class(new_klass)
new_klass.freeze
new_klass
end
module_function :new_proc_class
def eval_under_random_base(parent = nil, &b)
new_klass = __create_new_class(__get_random_basename(),
[], 4, false, parent)
ret = new_klass.class_eval(&b) if block_given?
__remove_methods_of_proc_class(new_klass)
new_klass.freeze
ret
end
module_function :eval_under_random_base
def new_proc_class_random(klass, func, safe = 4, add = false, &b)
eval_under_random_base(){
TkOption.new_proc_class(klass, func, safe, add, self, &b)
}
end
module_function :new_proc_class_random
end
TkOption = TkOptionDB
TkResourceDB = TkOptionDB

89
ext/tk/lib/tk/pack.rb Normal file
View File

@ -0,0 +1,89 @@
#
# tk/pack.rb : control pack geometry manager
#
require 'tk'
module TkPack
include Tk
extend Tk
TkCommandNames = ['pack'.freeze].freeze
def configure(win, *args)
if args[-1].kind_of?(Hash)
opts = args.pop
else
opts = {}
end
params = []
# params.push((win.kind_of?(TkObject))? win.epath: win)
params.push(_epath(win))
args.each{|win|
# params.push((win.kind_of?(TkObject))? win.epath: win)
params.push(_epath(win))
}
opts.each{|k, v|
params.push("-#{k}")
# params.push((v.kind_of?(TkObject))? v.epath: v)
params.push(_epath(v))
}
tk_call_without_enc("pack", 'configure', *params)
end
def forget(*args)
return '' if args.size == 0
wins = args.collect{|win|
# (win.kind_of?(TkObject))? win.epath: win
_epath(win)
}
tk_call_without_enc('pack', 'forget', *wins)
end
def info(slave)
# slave = slave.epath if slave.kind_of?(TkObject)
slave = _epath(slave)
ilist = list(tk_call_without_enc('pack', 'info', slave))
info = {}
while key = ilist.shift
info[key[1..-1]] = ilist.shift
end
return info
end
def propagate(master, bool=None)
# master = master.epath if master.kind_of?(TkObject)
master = _epath(master)
if bool == None
bool(tk_call_without_enc('pack', 'propagate', master))
else
tk_call_without_enc('pack', 'propagate', master, bool)
end
end
def slaves(master)
# master = master.epath if master.kind_of?(TkObject)
master = _epath(master)
list(tk_call_without_enc('pack', 'slaves', master))
end
module_function :configure, :forget, :info, :propagate, :slaves
end
=begin
def TkPack(win, *args)
if args[-1].kind_of?(Hash)
opts = args.pop
else
opts = {}
end
params = []
params.push((win.kind_of?(TkObject))? win.epath: win)
args.each{|win|
params.push((win.kind_of?(TkObject))? win.epath: win)
}
opts.each{|k, v|
params.push("-#{k}")
params.push((v.kind_of?(TkObject))? v.epath: v)
}
tk_call_without_enc("pack", *params)
end
=end

61
ext/tk/lib/tk/package.rb Normal file
View File

@ -0,0 +1,61 @@
#
# tk/package.rb : package command
#
require 'tk'
module TkPackage
include TkCore
extend TkPackage
TkCommandNames = ['package'.freeze].freeze
def add_path(path)
Tk::AUTO_PATH.value = Tk::AUTO_PATH.to_a << path
end
def forget(package)
tk_call('package', 'forget', package)
nil
end
def names
tk_split_simplelist(tk_call('package', 'names'))
end
def provide(package, version=nil)
if version
tk_call('package', 'provide', package, version)
nil
else
tk_call('package', 'provide', package)
end
end
def present(package, version=None)
tk_call('package', 'present', package, version)
end
def present_exact(package, version)
tk_call('package', 'present', '-exact', package, version)
end
def require(package, version=None)
tk_call('package', 'require', package, version)
end
def require_exact(package, version)
tk_call('package', 'require', '-exact', package, version)
end
def versions(package)
tk_split_simplelist(tk_call('package', 'versions', package))
end
def vcompare(version1, version2)
number(tk_call('package', 'vcompare', version1, version2))
end
def vsatisfies(version1, version2)
bool(tk_call('package', 'vsatisfies', version1, version2))
end
end

54
ext/tk/lib/tk/palette.rb Normal file
View File

@ -0,0 +1,54 @@
#
# tk/palette.rb : methods for Tcl/Tk standard library 'palette.tcl'
# 1998/06/21 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
#
require 'tk'
module TkPalette
include Tk
extend Tk
TkCommandNames = [
'tk_setPalette'.freeze,
'tk_bisque'.freeze,
'tkDarken'.freeze
].freeze
def TkPalette.set(*args)
args = args.to_a.flatten if args.kind_of? Hash
tk_call('tk_setPalette', *args)
end
def TkPalette.setPalette(*args)
TkPalette.set(*args)
end
def TkPalette.bisque
tk_call('tk_bisque')
end
def TkPalette.darken(color, percent)
tk_call('tkDarken', color, percent)
end
def TkPalette.recolorTree(window, colors)
if not colors.kind_of?(Hash)
fail "2nd arg need to be Hash"
end
colors.each{|key, value|
begin
if window.cget(key) == tk_call('set', "tkPalette(#{key})")
window[key] = colors[key]
end
rescue
# ignore
end
}
TkWinfo.children(window).each{|w| TkPalette.recolorTree(w, colors)}
end
def recolorTree(colors)
TkPalette.recolorTree(self, colors)
end
end

View File

@ -0,0 +1,204 @@
#
# tk/panedwindow.rb : treat panedwindow
#
require 'tk'
class TkPanedWindow<TkWindow
TkCommandNames = ['panedwindow'.freeze].freeze
WidgetClassName = 'Panedwindow'.freeze
WidgetClassNames[WidgetClassName] = self
def create_self(keys)
if keys and keys != None
tk_call_without_enc('panedwindow', @path, *hash_kv(keys, true))
else
tk_call_without_enc('panedwindow', @path)
end
end
private :create_self
def add(*args)
keys = args.pop
fail ArgumentError, "no window in arguments" unless keys
if keys && keys.kind_of?(Hash)
fail ArgumentError, "no window in arguments" if args == []
# args = args.collect{|w| (w.kind_of?(TkObject))? w.epath: w }
args = args.collect{|w| _epath(w) }
#args.push(hash_kv(keys))
args.concat(hash_kv(keys))
else
args.push(keys) if keys
# args = args.collect{|w| (w.kind_of?(TkObject))? w.epath: w }
args = args.collect{|w| _epath(w) }
end
tk_send_without_enc('add', *args)
self
end
def forget(win, *wins)
wins.unshift(win)
# tk_send_without_enc('forget', *((w.kind_of?(TkObject))? w.epath: w))
tk_send_without_enc('forget', *(wins.collect{|w| _epath(w)}))
self
end
alias del forget
alias delete forget
alias remove forget
def identify(x, y)
list(tk_send_without_enc('identify', x, y))
end
def proxy_coord
list(tk_send_without_enc('proxy', 'coord'))
end
def proxy_forget
tk_send_without_enc('proxy', 'forget')
self
end
def proxy_place(x, y)
tk_send_without_enc('proxy', 'place', x, y)
self
end
def sash_coord(index)
list(tk_send('sash', 'coord', index))
end
def sash_dragto(index)
tk_send('sash', 'dragto', index, x, y)
self
end
def sash_mark(index, x, y)
tk_send('sash', 'mark', index, x, y)
self
end
def sash_place(index, x, y)
tk_send('sash', 'place', index, x, y)
self
end
def panecget(win, key)
# win = win.epath if win.kind_of?(TkObject)
win = _epath(win)
tk_tcl2ruby(tk_send_without_enc('panecget', win, "-#{key}"))
end
def paneconfigure(win, key, value=nil)
# win = win.epath if win.kind_of?(TkObject)
win = _epath(win)
if key.kind_of? Hash
params = []
key.each{|k, v|
params.push("-#{k}")
# params.push((v.kind_of?(TkObject))? v.epath: v)
params.push(_epath(v))
}
tk_send_without_enc('paneconfigure', win, *params)
else
# value = value.epath if value.kind_of?(TkObject)
value = _epath(value)
tk_send_without_enc('paneconfigure', win, "-#{key}", value)
end
self
end
alias pane_config paneconfigure
def paneconfiginfo(win, key=nil)
if TkComm::GET_CONFIGINFO_AS_ARRAY
# win = win.epath if win.kind_of?(TkObject)
win = _epath(win)
if key
conf = tk_split_list(tk_send_without_enc('paneconfigure',
win, "-#{key}"))
conf[0] = conf[0][1..-1]
conf
else
tk_split_simplelist(tk_send_without_enc('paneconfigure',
win)).collect{|conflist|
conf = tk_split_simplelist(conflist)
conf[0] = conf[0][1..-1]
if conf[3]
if conf[3].index('{')
conf[3] = tk_split_list(conf[3])
else
conf[3] = tk_tcl2ruby(conf[3])
end
end
if conf[4]
if conf[4].index('{')
conf[4] = tk_split_list(conf[4])
else
conf[4] = tk_tcl2ruby(conf[4])
end
end
conf[1] = conf[1][1..-1] if conf.size == 2 # alias info
conf
}
end
else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
# win = win.epath if win.kind_of?(TkObject)
win = _epath(win)
if key
conf = tk_split_list(tk_send_without_enc('paneconfigure',
win, "-#{key}"))
key = conf.shift[1..-1]
{ key => conf }
else
ret = {}
tk_split_simplelist(tk_send_without_enc('paneconfigure',
win)).each{|conflist|
conf = tk_split_simplelist(conflist)
key = conf.shift[1..-1]
if key
if conf[2].index('{')
conf[2] = tk_split_list(conf[2])
else
conf[2] = tk_tcl2ruby(conf[2])
end
end
if conf[3]
if conf[3].index('{')
conf[3] = tk_split_list(conf[3])
else
conf[3] = tk_tcl2ruby(conf[3])
end
end
if conf.size == 1
ret[key] = conf[0][1..-1] # alias info
else
ret[key] = conf
end
}
ret
end
end
end
alias pane_configinfo paneconfiginfo
def current_paneconfiginfo(win, key=nil)
if TkComm::GET_CONFIGINFO_AS_ARRAY
if key
conf = paneconfiginfo(win, key)
{conf[0] => conf[4]}
else
ret = {}
paneconfiginfo(win).each{|conf|
ret[conf[0]] = conf[4] if conf.size > 2
}
ret
end
else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
ret = {}
paneconfiginfo(win, key).each{|k, conf|
ret[k] = conf[-1] if conf.kind_of?(Array)
}
ret
end
end
alias current_pane_configinfo current_paneconfiginfo
def panes
list(tk_send_without_enc('panes'))
end
end
TkPanedwindow = TkPanedWindow

110
ext/tk/lib/tk/place.rb Normal file
View File

@ -0,0 +1,110 @@
#
# tk/place.rb : control place geometry manager
#
require 'tk'
module TkPlace
include Tk
extend Tk
TkCommandNames = ['place'.freeze].freeze
def configure(win, slot, value=None)
# for >= Tk8.4a2 ?
# win = win.epath if win.kind_of?(TkObject)
win = _epath(win)
if slot.kind_of? Hash
params = []
slot.each{|k, v|
params.push("-#{k}")
# params.push((v.kind_of?(TkObject))? v.epath: v)
params.push(_epath(v))
}
tk_call_without_enc('place', 'configure', win, *params)
else
# value = value.epath if value.kind_of?(TkObject)
value = _epath(value)
tk_call_without_enc('place', 'configure', win, "-#{slot}", value)
end
end
def configinfo(win, slot = nil)
# for >= Tk8.4a2 ?
if TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
# win = win.epath if win.kind_of?(TkObject)
win = _epath(win)
if slot
conf = tk_split_list(tk_call_without_enc('place', 'configure',
win, "-#{slot}") )
conf[0] = conf[0][1..-1]
conf
else
tk_split_simplelist(tk_call_without_enc('place', 'configure',
win)).collect{|conflist|
conf = list(conflist)
conf[0] = conf[0][1..-1]
conf
}
end
else # ! TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
current_configinfo(win, slot)
end
end
def current_configinfo(win, slot = nil)
# win = win.epath if win.kind_of?(TkObject)
win = _epath(win)
if slot
conf = tk_split_list(tk_call_without_enc('place', 'configure',
win, "-#{slot}") )
{ conf[0][1..-1] => conf[1] }
else
ret = {}
tk_split_list(tk_call_without_enc('place','configure',win)).each{|conf|
ret[conf[0][1..-1]] = conf[1]
}
ret
end
end
def forget(win)
# win = win.epath if win.kind_of?(TkObject)
win = _epath(win)
tk_call_without_enc('place', 'forget', win)
end
def info(win)
# win = win.epath if win.kind_of?(TkObject)
win = _epath(win)
ilist = list(tk_call_without_enc('place', 'info', win))
info = {}
while key = ilist.shift
info[key[1..-1]] = ilist.shift
end
return info
end
def slaves(master)
# master = master.epath if master.kind_of?(TkObject)
master = _epath(master)
list(tk_call('place', 'slaves', master))
end
module_function :configure, :configinfo, :forget, :info, :slaves
end
=begin
def TkPlace(win, slot, value=None)
win = win.epath if win.kind_of?(TkObject)
if slot.kind_of? Hash
params = []
slot.each{|k, v|
params.push("-#{k}")
params.push((v.kind_of?(TkObject))? v.epath: v)
}
tk_call_without_enc('place', win, *params)
else
value = value.epath if value.kind_of?(TkObject)
tk_call_without_enc('place', win, "-#{slot}", value)
end
end
=end

View File

@ -0,0 +1,32 @@
#
# tk/radiobutton.rb : treat radiobutton widget
#
require 'tk'
require 'tk/button'
class TkRadioButton<TkButton
TkCommandNames = ['radiobutton'.freeze].freeze
WidgetClassName = 'Radiobutton'.freeze
WidgetClassNames[WidgetClassName] = self
def create_self(keys)
if keys and keys != None
tk_call_without_enc('radiobutton', @path, *hash_kv(keys, true))
else
tk_call_without_enc('radiobutton', @path)
end
end
private :create_self
def deselect
tk_send_without_enc('deselect')
self
end
def select
tk_send_without_enc('select')
self
end
def variable(v)
configure 'variable', tk_trace_variable(v)
end
end
TkRadiobutton = TkRadioButton

65
ext/tk/lib/tk/root.rb Normal file
View File

@ -0,0 +1,65 @@
#
# tk/root.rb : treat root widget
#
require 'tk'
require 'tk/wm'
class TkRoot<TkWindow
include Wm
=begin
ROOT = []
def TkRoot.new(keys=nil)
if ROOT[0]
Tk_WINDOWS["."] = ROOT[0]
return ROOT[0]
end
new = super(:without_creating=>true, :widgetname=>'.')
if keys # wm commands
keys.each{|k,v|
if v.kind_of? Array
new.send(k,*v)
else
new.send(k,v)
end
}
end
ROOT[0] = new
Tk_WINDOWS["."] = new
end
=end
def TkRoot.new(keys=nil, &b)
unless TkCore::INTERP.tk_windows['.']
TkCore::INTERP.tk_windows['.'] =
super(:without_creating=>true, :widgetname=>'.'){}
end
root = TkCore::INTERP.tk_windows['.']
if keys # wm commands
keys.each{|k,v|
if v.kind_of? Array
root.send(k,*v)
else
root.send(k,v)
end
}
end
root.instance_eval(&b) if block_given?
root
end
WidgetClassName = 'Tk'.freeze
WidgetClassNames[WidgetClassName] = self
def create_self
@path = '.'
end
private :create_self
def path
"."
end
def TkRoot.destroy
TkCore::INTERP._invoke('destroy', '.')
end
end

78
ext/tk/lib/tk/scale.rb Normal file
View File

@ -0,0 +1,78 @@
#
# tk/scale.rb : treat scale widget
#
require 'tk'
class TkScale<TkWindow
TkCommandNames = ['scale'.freeze].freeze
WidgetClassName = 'Scale'.freeze
WidgetClassNames[WidgetClassName] = self
def create_self(keys)
if keys and keys != None
if keys.key?('command')
cmd = keys.delete('command')
keys['command'] = proc{|val| cmd.call(val.to_f)}
end
tk_call_without_enc('scale', @path, *hash_kv(keys, true))
else
tk_call_without_enc('scale', @path)
end
end
private :create_self
def _wrap_command_arg(cmd)
proc{|val|
if val.kind_of?(String)
cmd.call(number(val))
else
cmd.call(val)
end
}
end
private :_wrap_command_arg
def configure_cmd(slot, value)
configure(slot=>value)
end
def configure(slot, value=None)
if (slot == 'command' || slot == :command)
configure('command'=>value)
elsif slot.kind_of?(Hash) &&
(slot.key?('command') || slot.key?(:command))
slot = _symbolkey2str(slot)
slot['command'] = _wrap_command_arg(slot.delete('command'))
end
super(slot, value)
end
def command(cmd=Proc.new)
configure('command'=>cmd)
end
def get(x=None, y=None)
number(tk_send_without_enc('get', x, y))
end
def coords(val=None)
tk_split_list(tk_send_without_enc('coords', val))
end
def identify(x, y)
tk_send_without_enc('identify', x, y)
end
def set(val)
tk_send_without_enc('set', val)
end
def value
get
end
def value= (val)
set(val)
val
end
end

View File

@ -0,0 +1,49 @@
#
# tk/scrollable.rb : module for scrollable widget
#
require 'tk'
module Tk
module Scrollable
def xscrollcommand(cmd=Proc.new)
configure_cmd 'xscrollcommand', cmd
end
def yscrollcommand(cmd=Proc.new)
configure_cmd 'yscrollcommand', cmd
end
def xview(*index)
if index.size == 0
list(tk_send_without_enc('xview'))
else
tk_send_without_enc('xview', *index)
self
end
end
def yview(*index)
if index.size == 0
list(tk_send_without_enc('yview'))
else
tk_send_without_enc('yview', *index)
self
end
end
def xscrollbar(bar=nil)
if bar
@xscrollbar = bar
@xscrollbar.orient 'horizontal'
self.xscrollcommand {|*arg| @xscrollbar.set(*arg)}
@xscrollbar.command {|*arg| self.xview(*arg)}
end
@xscrollbar
end
def yscrollbar(bar=nil)
if bar
@yscrollbar = bar
@yscrollbar.orient 'vertical'
self.yscrollcommand {|*arg| @yscrollbar.set(*arg)}
@yscrollbar.command {|*arg| self.yview(*arg)}
end
@yscrollbar
end
end
end

105
ext/tk/lib/tk/scrollbar.rb Normal file
View File

@ -0,0 +1,105 @@
#
# tk/scrollbar.rb : treat scrollbar widget
#
require 'tk'
class TkScrollbar<TkWindow
TkCommandNames = ['scrollbar'.freeze].freeze
WidgetClassName = 'Scrollbar'.freeze
WidgetClassNames[WidgetClassName] = self
def create_self(keys)
@assigned = []
@scroll_proc = proc{|*args|
if self.orient == 'horizontal'
@assigned.each{|w| w.xview(*args)}
else # 'vertical'
@assigned.each{|w| w.yview(*args)}
end
}
if keys and keys != None
tk_call_without_enc('scrollbar', @path, *hash_kv(keys, true))
else
tk_call_without_enc('scrollbar', @path)
end
end
private :create_self
def assign(*wins)
begin
self.command(@scroll_proc) if self.cget('command').cmd != @scroll_proc
rescue Exception
self.command(@scroll_proc)
end
orient = self.orient
wins.each{|w|
@assigned << w unless @assigned.index(w)
if orient == 'horizontal'
w.xscrollcommand proc{|first, last| self.set(first, last)}
else # 'vertical'
w.yscrollcommand proc{|first, last| self.set(first, last)}
end
}
self
end
def assigned_list
begin
return @assigned.dup if self.cget('command').cmd == @scroll_proc
rescue Exception
end
fail RuntimeError, "not depend on the assigned_list"
end
#def delta(deltax=None, deltay=None)
def delta(deltax, deltay)
number(tk_send_without_enc('delta', deltax, deltay))
end
#def fraction(x=None, y=None)
def fraction(x, y)
number(tk_send_without_enc('fraction', x, y))
end
def identify(x, y)
tk_send_without_enc('identify', x, y)
end
def get
#ary1 = tk_send('get').split
#ary2 = []
#for i in ary1
# ary2.push number(i)
#end
#ary2
list(tk_send_without_enc('get'))
end
def set(first, last)
tk_send_without_enc('set', first, last)
self
end
def activate(element=None)
tk_send_without_enc('activate', element)
end
end
class TkXScrollbar<TkScrollbar
def create_self(keys)
keys = {} unless keys
keys['orient'] = 'horizontal'
super(keys)
end
private :create_self
end
class TkYScrollbar<TkScrollbar
def create_self(keys)
keys = {} unless keys
keys['orient'] = 'vertical'
super(keys)
end
private :create_self
end

View File

@ -0,0 +1,31 @@
#
# tk/scrollbox.rb - Tk Listbox with Scrollbar
# as an example of Composite Widget
# $Date$
# by Yukihiro Matsumoto <matz@netlab.co.jp>
#
require 'tk'
require 'tk/listbox'
class TkScrollbox<TkListbox
include TkComposite
def initialize_composite(keys=nil)
list = TkListbox.new(@frame)
scroll = TkScrollbar.new(@frame)
@path = list.path
list.configure 'yscroll', scroll.path+" set"
list.pack 'side'=>'left','fill'=>'both','expand'=>'yes'
scroll.configure 'command', list.path+" yview"
scroll.pack 'side'=>'right','fill'=>'y'
delegate('DEFAULT', list)
delegate('foreground', list)
delegate('background', list, scroll)
delegate('borderwidth', @frame)
delegate('relief', @frame)
configure keys if keys
end
private :initialize_composite
end

View File

@ -0,0 +1,86 @@
#
# tk/selection.rb : control selection
#
require 'tk'
module TkSelection
include Tk
extend Tk
TkCommandNames = ['selection'.freeze].freeze
def self.clear(sel=nil)
if sel
tk_call_without_enc('selection', 'clear', '-selection', sel)
else
tk_call_without_enc('selection', 'clear')
end
end
def self.clear_on_display(win, sel=nil)
if sel
tk_call_without_enc('selection', 'clear',
'-displayof', win, '-selection', sel)
else
tk_call_without_enc('selection', 'clear', '-displayof', win)
end
end
def clear(sel=nil)
TkSelection.clear_on_display(self, sel)
self
end
def self.get(keys=nil)
#tk_call('selection', 'get', *hash_kv(keys))
_fromUTF8(tk_call_without_enc('selection', 'get', *hash_kv(keys)))
end
def self.get_on_display(win, keys=nil)
#tk_call('selection', 'get', '-displayof', win, *hash_kv(keys))
_fromUTF8(tk_call_without_enc('selection', 'get', '-displayof',
win, *hash_kv(keys)))
end
def get(keys=nil)
TkSelection.get_on_display(self, sel)
end
def self.handle(win, func=Proc.new, keys=nil, &b)
if func.kind_of?(Hash) && keys == nil
keys = func
func = Proc.new(&b)
end
args = ['selection', 'handle']
args.concat(hash_kv(keys))
args.concat([win, func])
tk_call_without_enc(*args)
end
def handle(func=Proc.new, keys=nil, &b)
TkSelection.handle(self, func, keys, &b)
end
def self.get_owner(sel=nil)
if sel
window(tk_call_without_enc('selection', 'own', '-selection', sel))
else
window(tk_call_without_enc('selection', 'own'))
end
end
def self.get_owner_on_display(win, sel=nil)
if sel
window(tk_call_without_enc('selection', 'own',
'-displayof', win, '-selection', sel))
else
window(tk_call_without_enc('selection', 'own', '-displayof', win))
end
end
def get_owner(sel=nil)
TkSelection.get_owner_on_display(self, sel)
self
end
def self.set_owner(win, keys=nil)
tk_call_without_enc('selection', 'own', *(hash_kv(keys) << win))
end
def set_owner(keys=nil)
TkSelection.set_owner(self, keys)
self
end
end

39
ext/tk/lib/tk/spinbox.rb Normal file
View File

@ -0,0 +1,39 @@
#
# tk/spinbox.rb - Tk spinbox classes
# $Date$
# by Yukihiro Matsumoto <matz@caelum.co.jp>
#
require 'tk'
require 'tk/entry'
class TkSpinbox<TkEntry
TkCommandNames = ['spinbox'.freeze].freeze
WidgetClassName = 'Spinbox'.freeze
WidgetClassNames[WidgetClassName] = self
def create_self(keys)
tk_call_without_enc('spinbox', @path)
if keys and keys != None
configure(keys)
end
end
private :create_self
def identify(x, y)
tk_send_without_enc('identify', x, y)
end
def spinup
tk_send_without_enc('invoke', 'spinup')
self
end
def spindown
tk_send_without_enc('invoke', 'spindown')
self
end
def set(str)
_freomUTF8(tk_send_without_enc('set', _get_eval_enc_str(str)))
end
end

43
ext/tk/lib/tk/tagfont.rb Normal file
View File

@ -0,0 +1,43 @@
#
# tk/tagfont.rb : control font of tags
#
require 'tk'
module TkTreatTagFont
def font_configinfo
@parent.tagfont_configinfo(@id)
end
# alias font font_configinfo
def font_configure(slot)
@parent.tagfont_configure(@id, slot)
self
end
def latinfont_configure(ltn, keys=nil)
@parent.latintagfont_configure(@id, ltn, keys)
self
end
alias asciifont_configure latinfont_configure
def kanjifont_configure(knj, keys=nil)
@parent.kanjitagfont_configure(@id, ltn, keys)
self
end
def font_copy(window, wintag=nil)
@parent.tagfont_copy(@id, window, wintag)
self
end
def latinfont_copy(window, wintag=nil)
@parent.latintagfont_copy(@id, window, wintag)
self
end
alias asciifont_copy latinfont_copy
def kanjifont_copy(window, wintag=nil)
@parent.kanjitagfont_copy(@id, window, wintag)
self
end
end

1179
ext/tk/lib/tk/text.rb Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,72 @@
#
# tk/textimage.rb - treat Tk text image object
#
require 'tk'
require 'tk/text'
class TkTextImage<TkObject
def initialize(parent, index, keys)
unless parent.kind_of?(TkText)
fail ArguemntError, "expect TkText for 1st argument"
end
@t = parent
if index == 'end'
@path = TkTextMark.new(@t, tk_call(@t.path, 'index', 'end - 1 chars'))
elsif index.kind_of? TkTextMark
if tk_call_without_enc(@t.path,'index',index.path) == tk_call_without_enc(@t.path,'index','end')
@path = TkTextMark.new(@t, tk_call_without_enc(@t.path, 'index',
'end - 1 chars'))
else
@path = TkTextMark.new(@t, tk_call_without_enc(@t.path, 'index',
index.path))
end
else
@path = TkTextMark.new(@t, tk_call_without_enc(@t.path, 'index',
_get_eval_enc_str(index)))
end
@path.gravity = 'left'
@index = @path.path
@id = tk_call_without_enc(@t.path, 'image', 'create', @index,
*hash_kv(keys, true))
end
def [](slot)
cget(slot)
end
def []=(slot, value)
configure(slot, value)
value
end
def cget(slot)
@t.image_cget(@index, slot)
end
def configure(slot, value=None)
@t.image_configure(@index, slot, value)
self
end
# def configure(slot, value)
# tk_call @t.path, 'image', 'configure', @index, "-#{slot}", value
# end
def configinfo(slot = nil)
@t.image_configinfo(@index, slot)
end
def current_configinfo(slot = nil)
@t.current_image_configinfo(@index, slot)
end
def image
img = tk_call_without_enc(@t.path, 'image', 'configure', @index, '-image')
TkImage::Tk_IMGTBL[img]? TkImage::Tk_IMGTBL[img] : img
end
def image=(value)
tk_call_without_enc(@t.path, 'image', 'configure', @index, '-image',
_get_eval_enc_str(value))
#self
value
end
end

126
ext/tk/lib/tk/textmark.rb Normal file
View File

@ -0,0 +1,126 @@
#
# tk/textmark.rb - methods for treating text marks
#
require 'tk'
require 'tk/text'
class TkTextMark<TkObject
TMarkID_TBL = TkCore::INTERP.create_table
Tk_TextMark_ID = ['mark'.freeze, '00000'.taint].freeze
TkCore::INTERP.init_ip_env{ TMarkID_TBL.clear }
def TkTextMark.id2obj(text, id)
tpath = text.path
return id unless TMarkID_TBL[tpath]
TMarkID_TBL[tpath][id]? TMarkID_TBL[tpath][id]: id
end
def initialize(parent, index)
unless parent.kind_of?(TkText)
fail ArguemntError, "expect TkText for 1st argument"
end
@parent = @t = parent
@tpath = parent.path
@path = @id = Tk_TextMark_ID.join('')
TMarkID_TBL[@id] = self
TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath]
TMarkID_TBL[@tpath][@id] = self
Tk_TextMark_ID[1].succ!
tk_call_without_enc(@t.path, 'mark', 'set', @id,
_get_eval_enc_str(index))
@t._addtag id, self
end
def id
@id
end
def +(mod)
@id + ' + ' + mod
end
def -(mod)
@id + ' - ' + mod
end
def set(where)
tk_call_without_enc(@t.path, 'mark', 'set', @id,
_get_eval_enc_str(where))
self
end
def unset
tk_call_without_enc(@t.path, 'mark', 'unset', @id)
self
end
alias destroy unset
def gravity
tk_call_without_enc(@t.path, 'mark', 'gravity', @id)
end
def gravity=(direction)
tk_call_without_enc(@t.path, 'mark', 'gravity', @id, direction)
#self
direction
end
def next(index = nil)
if index
@t.tagid2obj(_fromUTF8(tk_call_without_enc(@t.path, 'mark', 'next', _get_eval_enc_str(index))))
else
@t.tagid2obj(_fromUTF8(tk_call_without_enc(@t.path, 'mark', 'next', @id)))
end
end
def previous(index = nil)
if index
@t.tagid2obj(_fromUTF8(tk_call_without_enc(@t.path, 'mark', 'previous', _get_eval_enc_str(index))))
else
@t.tagid2obj(_fromUTF8(tk_call_without_enc(@t.path, 'mark', 'previous', @id)))
end
end
end
class TkTextNamedMark<TkTextMark
def self.new(parent, name, *args)
if TMarkID_TBL[parent.path] && TMarkID_TBL[parent.path][name]
return TMarkID_TBL[parent.path][name]
else
super(parent, name, *args)
end
end
def initialize(parent, name, index=nil)
unless parent.kind_of?(TkText)
fail ArguemntError, "expect TkText for 1st argument"
end
@parent = @t = parent
@tpath = parent.path
@path = @id = name
TMarkID_TBL[@id] = self
TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath]
TMarkID_TBL[@tpath][@id] = self unless TMarkID_TBL[@tpath][@id]
tk_call_without_enc(@t.path, 'mark', 'set', @id,
_get_eval_enc_str(index)) if index
@t._addtag id, self
end
end
class TkTextMarkInsert<TkTextNamedMark
def self.new(parent,*args)
super(parent, 'insert', *args)
end
end
class TkTextMarkCurrent<TkTextMark
def self.new(parent,*args)
super(parent, 'current', *args)
end
end
class TkTextMarkAnchor<TkTextMark
def self.new(parent,*args)
super(parent, 'anchor', *args)
end
end

239
ext/tk/lib/tk/texttag.rb Normal file
View File

@ -0,0 +1,239 @@
#
# tk/texttag.rb - methods for treating text tags
#
require 'tk'
require 'tk/text'
require 'tk/tagfont'
class TkTextTag<TkObject
include TkTreatTagFont
TTagID_TBL = TkCore::INTERP.create_table
Tk_TextTag_ID = ['tag'.freeze, '00000'.taint].freeze
TkCore::INTERP.init_ip_env{ TTagID_TBL.clear }
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)
unless parent.kind_of?(TkText)
fail ArguemntError, "expect TkText for 1st argument"
end
@parent = @t = parent
@tpath = parent.path
@path = @id = Tk_TextTag_ID.join('')
TTagID_TBL[@id] = self
TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath]
TTagID_TBL[@tpath][@id] = self
Tk_TextTag_ID[1].succ!
#tk_call @t.path, "tag", "configure", @id, *hash_kv(keys)
if args != [] then
keys = args.pop
if keys.kind_of? Hash then
add(*args) if args != []
configure(keys)
else
args.push keys
add(*args)
end
end
@t._addtag id, self
end
def id
@id
end
def first
@id + '.first'
end
def last
@id + '.last'
end
def add(*indices)
tk_call_without_enc(@t.path, 'tag', 'add', @id,
*(indices.collect{|idx| _get_eval_enc_str(idx)}))
self
end
def remove(*indices)
tk_call_without_enc(@t.path, 'tag', 'remove', @id,
*(indices.collect{|idx| _get_eval_enc_str(idx)}))
self
end
def ranges
l = tk_split_simplelist(tk_call_without_enc(@t.path, 'tag', 'ranges', @id))
r = []
while key=l.shift
r.push [key, l.shift]
end
r
end
def nextrange(first, last=None)
tk_split_list(tk_call_without_enc(@t.path, 'tag', 'nextrange', @id,
_get_eval_enc_str(first),
_get_eval_enc_str(last)))
end
def prevrange(first, last=None)
tk_split_list(tk_call_without_enc(@t.path, 'tag', 'prevrange', @id,
_get_eval_enc_str(first),
_get_eval_enc_str(last)))
end
def [](key)
cget key
end
def []=(key,val)
configure key, val
val
end
def cget(key)
case key.to_s
when 'text', 'label', 'show', 'data', 'file'
_fromUTF8(tk_call_without_enc(@t.path, 'tag', 'cget', @id, "-#{key}"))
when 'font', 'kanjifont'
#fnt = tk_tcl2ruby(tk_call(@t.path, 'tag', 'cget', @id, "-#{key}"))
fnt = tk_tcl2ruby(_fromUTF8(tk_call_without_enc(@t.path, 'tag', 'cget',
@id, '-font')))
unless fnt.kind_of?(TkFont)
fnt = tagfontobj(@id, fnt)
end
if key.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
# obsolete; just for compatibility
fnt.kanji_font
else
fnt
end
else
tk_tcl2ruby(_fromUTF8(tk_call_without_enc(@t.path, 'tag', 'cget',
@id, "-#{key}")))
end
end
def configure(key, val=None)
@t.tag_configure @id, key, val
end
# def configure(key, val=None)
# if key.kind_of? Hash
# tk_call @t.path, 'tag', 'configure', @id, *hash_kv(key)
# else
# tk_call @t.path, 'tag', 'configure', @id, "-#{key}", val
# end
# end
# def configure(key, value)
# if value == FALSE
# value = "0"
# elsif value.kind_of? Proc
# value = install_cmd(value)
# end
# tk_call @t.path, 'tag', 'configure', @id, "-#{key}", value
# end
def configinfo(key=nil)
@t.tag_configinfo @id, key
end
def current_configinfo(key=nil)
@t.current_tag_configinfo @id, key
end
def bind(seq, cmd=Proc.new, args=nil)
_bind([@t.path, 'tag', 'bind', @id], seq, cmd, args)
self
end
def bind_append(seq, cmd=Proc.new, args=nil)
_bind_append([@t.path, 'tag', 'bind', @id], seq, cmd, args)
self
end
def bind_remove(seq)
_bind_remove([@t.path, 'tag', 'bind', @id], seq)
self
end
def bindinfo(context=nil)
_bindinfo([@t.path, 'tag', 'bind', @id], context)
end
def raise(above=None)
tk_call_without_enc(@t.path, 'tag', 'raise', @id,
_get_eval_enc_str(above))
self
end
def lower(below=None)
tk_call_without_enc(@t.path, 'tag', 'lower', @id,
_get_eval_enc_str(below))
self
end
def destroy
tk_call_without_enc(@t.path, 'tag', 'delete', @id)
TTagID_TBL[@tpath].delete(@id) if TTagID_TBL[@tpath]
self
end
end
class TkTextNamedTag<TkTextTag
def self.new(parent, name, *args)
if TTagID_TBL[parent.path] && TTagID_TBL[parent.path][name]
tagobj = TTagID_TBL[parent.path][name]
if args != [] then
keys = args.pop
if keys.kind_of? Hash then
tagobj.add(*args) if args != []
tagobj.configure(keys)
else
args.push keys
tagobj.add(*args)
end
end
return tagobj
else
super(parent, name, *args)
end
end
def initialize(parent, name, *args)
unless parent.kind_of?(TkText)
fail ArguemntError, "expect TkText for 1st argument"
end
@parent = @t = parent
@tpath = parent.path
@path = @id = name
TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath]
TTagID_TBL[@tpath][@id] = self unless TTagID_TBL[@tpath][@id]
#if mode
# tk_call @t.path, "addtag", @id, *args
#end
if args != [] then
keys = args.pop
if keys.kind_of? Hash then
add(*args) if args != []
configure(keys)
else
args.push keys
add(*args)
end
end
@t._addtag id, self
end
end
class TkTextTagSel<TkTextNamedTag
def self.new(parent, *args)
super(parent, 'sel', *args)
end
end

137
ext/tk/lib/tk/textwindow.rb Normal file
View File

@ -0,0 +1,137 @@
#
# tk/textwindow.rb - treat Tk text window object
#
require 'tk'
require 'tk/text'
class TkTextWindow<TkObject
def initialize(parent, index, keys)
unless parent.kind_of?(TkText)
fail ArguemntError, "expect TkText for 1st argument"
end
@t = parent
if index == 'end'
@path = TkTextMark.new(@t, tk_call_without_enc(@t.path, 'index',
'end - 1 chars'))
elsif index.kind_of? TkTextMark
if tk_call_without_enc(@t.path,'index',index.path) == tk_call_without_enc(@t.path,'index','end')
@path = TkTextMark.new(@t, tk_call_without_enc(@t.path, 'index',
'end - 1 chars'))
else
@path = TkTextMark.new(@t, tk_call_without_enc(@t.path, 'index',
index.path))
end
else
@path = TkTextMark.new(@t, tk_call_without_enc(@t.path, 'index', _get_eval_enc_str(index)))
end
@path.gravity = 'left'
@index = @path.path
keys = _symbolkey2str(keys)
@id = keys['window']
# keys['window'] = @id.epath if @id.kind_of?(TkWindow)
keys['window'] = _epath(@id) if @id
if keys['create']
@p_create = keys['create']
if @p_create.kind_of? Proc
=begin
keys['create'] = install_cmd(proc{
@id = @p_create.call
if @id.kind_of?(TkWindow)
@id.epath
else
@id
end
})
=end
keys['create'] = install_cmd(proc{@id = @p_create.call; _epath(@id)})
end
end
tk_call_without_enc(@t.path, 'window', 'create', @index,
*hash_kv(keys, true))
end
def [](slot)
cget(slot)
end
def []=(slot, value)
configure(slot, value)
value
end
def cget(slot)
@t.window_cget(@index, slot)
end
def configure(slot, value=None)
if slot.kind_of? Hash
slot = _symbolkey2str(slot)
if slot['window']
@id = slot['window']
# slot['window'] = @id.epath if @id.kind_of?(TkWindow)
slot['window'] = _epath(@id) if @id
end
if slot['create']
self.create=slot.delete('create')
end
if slot.size > 0
tk_call_without_enc(@t.path, 'window', 'configure', @index,
*hash_kv(slot, true))
end
else
if slot == 'window' || slot == :window
@id = value
# value = @id.epath if @id.kind_of?(TkWindow)
value = _epath(@id) if @id
end
if slot == 'create' || slot == :create
self.create=value
else
tk_call_without_enc(@t.path, 'window', 'configure', @index,
"-#{slot}", _get_eval_enc_str(value))
end
end
self
end
def configinfo(slot = nil)
@t.window_configinfo(@index, slot)
end
def current_configinfo(slot = nil)
@t.current_window_configinfo(@index, slot)
end
def window
@id
end
def window=(value)
@id = value
# value = @id.epath if @id.kind_of?(TkWindow)
value = _epath(@id) if @id
tk_call_without_enc(@t.path, 'window', 'configure', @index,
'-window', _get_eval_enc_str(value))
value
end
def create
@p_create
end
def create=(value)
@p_create = value
if @p_create.kind_of? Proc
value = install_cmd(proc{
@id = @p_create.call
if @id.kind_of?(TkWindow)
@id.epath
else
@id
end
})
end
tk_call_without_enc(@t.path, 'window', 'configure', @index,
'-create', _get_eval_enc_str(value))
value
end
end

441
ext/tk/lib/tk/timer.rb Normal file
View File

@ -0,0 +1,441 @@
#
# tk/timer.rb : methods for Tcl/Tk after command
#
# $Id$
#
require 'tk'
class TkTimer
include TkCore
extend TkCore
TkCommandNames = ['after'.freeze].freeze
Tk_CBID = ['a'.freeze, '00000'.taint].freeze
Tk_CBTBL = {}.taint
TkCore::INTERP.add_tk_procs('rb_after', 'id', <<-'EOL')
if {[set st [catch {eval {ruby_cmd TkTimer callback} $id} ret]] != 0} {
return -code $st $ret
} {
return $ret
}
EOL
DEFAULT_IGNORE_EXCEPTIONS = [ NameError, RuntimeError ].freeze
###############################
# class methods
###############################
def self.callback(obj_id)
@after_id = nil
ex_obj = Tk_CBTBL[obj_id]
return "" if ex_obj == nil; # canceled
ex_obj.cb_call
end
def self.info(obj = nil)
if obj
if obj.kind_of?(TkTimer)
if obj.after_id
inf = tk_split_list(tk_call_without_enc('after','info',obj.after_id))
[Tk_CBTBL[inf[0][1]], inf[1]]
else
nil
end
else
fail ArgumentError, "TkTimer object is expected"
end
else
tk_call_without_enc('after', 'info').split(' ').collect!{|id|
ret = Tk_CBTBL.find{|key,val| val.after_id == id}
(ret == nil)? id: ret[1]
}
end
end
###############################
# instance methods
###############################
def do_callback
@in_callback = true
begin
@return_value = @current_proc.call(self)
rescue Exception => e
if @cancel_on_exception &&
@cancel_on_exception.find{|exc| e.kind_of?(exc)}
cancel
@return_value = e
return e
else
fail e
end
end
if @set_next
set_next_callback(@current_args)
else
@set_next = true
end
@in_callback = false
@return_value
end
def set_callback(sleep, args=nil)
@after_script = "rb_after #{@id}"
@after_id = tk_call_without_enc('after', sleep, @after_script)
@current_args = args
@current_script = [sleep, @after_script]
self
end
def set_next_callback(args)
if @running == false || @proc_max == 0 || @do_loop == 0
Tk_CBTBL.delete(@id) ;# for GC
@running = false
@wait_var.value = 0
return
end
if @current_pos >= @proc_max
if @do_loop < 0 || (@do_loop -= 1) > 0
@current_pos = 0
else
Tk_CBTBL.delete(@id) ;# for GC
@running = false
@wait_var.value = 0
return
end
end
@current_args = args
if @sleep_time.kind_of? Proc
sleep = @sleep_time.call(self)
else
sleep = @sleep_time
end
@current_sleep = sleep
cmd, *cmd_args = @loop_proc[@current_pos]
@current_pos += 1
@current_proc = cmd
set_callback(sleep, cmd_args)
end
def initialize(*args)
@id = Tk_CBID.join('')
Tk_CBID[1].succ!
@wait_var = TkVariable.new(0)
@cb_cmd = TkCore::INTERP.get_cb_entry(self.method(:do_callback))
@set_next = true
@init_sleep = 0
@init_proc = nil
@init_args = []
@current_script = []
@current_proc = nil
@current_args = nil
@return_value = nil
@sleep_time = 0
@current_sleep = 0
@loop_exec = 0
@do_loop = 0
@loop_proc = []
@proc_max = 0
@current_pos = 0
@after_id = nil
@after_script = nil
@cancel_on_exception = DEFAULT_IGNORE_EXCEPTIONS
# Unless @cancel_on_exception, Ruby/Tk shows an error dialog box when
# an excepsion is raised on TkTimer callback procedure.
# If @cancel_on_exception is an array of exception classes and the raised
# exception is included in the array, Ruby/Tk cancels executing TkTimer
# callback procedures silently (TkTimer#cancel is called and no dialog is
# shown).
set_procs(*args) if args != []
@running = false
@in_callback = false
end
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
def cb_call
@cb_cmd.call
end
def get_procs
[@init_sleep, @init_proc, @init_args, @sleep_time, @loop_exec, @loop_proc]
end
def current_status
[@running, @current_sleep, @current_proc, @current_args,
@do_loop, @cancel_on_exception]
end
def cancel_on_exception?
@cancel_on_exception
end
def cancel_on_exception=(mode)
if mode.kind_of?(Array)
@cancel_on_exception = mode
elsif mode
@cancel_on_exception = DEFAULT_IGNORE_EXCEPTIONS
else
@cancel_on_exception = false
end
#self
end
def running?
@running
end
def loop_rest
@do_loop
end
def loop_rest=(rest)
@do_loop = rest
#self
end
def set_procs(interval, loop_exec, *procs)
if !interval == 'idle' \
&& !interval.kind_of?(Integer) && !interval.kind_of?(Proc)
fail ArguemntError, "expect Integer or Proc for 1st argument"
end
@sleep_time = interval
@loop_proc = []
procs.each{|e|
if e.kind_of? Proc
@loop_proc.push([e])
else
@loop_proc.push(e)
end
}
@proc_max = @loop_proc.size
@current_pos = 0
@do_loop = 0
if loop_exec
if loop_exec.kind_of?(Integer) && loop_exec < 0
@loop_exec = -1
elsif loop_exec == nil || loop_exec == false || loop_exec == 0
@loop_exec = 1
else
if not loop_exec.kind_of?(Integer)
fail ArguemntError, "expect Integer for 2nd argument"
end
@loop_exec = loop_exec
end
@do_loop = @loop_exec
end
self
end
def add_procs(*procs)
procs.each{|e|
if e.kind_of? Proc
@loop_proc.push([e])
else
@loop_proc.push(e)
end
}
@proc_max = @loop_proc.size
self
end
def delete_procs(*procs)
procs.each{|e|
if e.kind_of? Proc
@loop_proc.delete([e])
else
@loop_proc.delete(e)
end
}
@proc_max = @loop_proc.size
cancel if @proc_max == 0
self
end
def delete_at(n)
@loop_proc.delete_at(n)
@proc_max = @loop_proc.size
cancel if @proc_max == 0
self
end
def set_start_proc(sleep, init_proc, *init_args)
if !sleep == 'idle' && !sleep.kind_of?(Integer)
fail ArguemntError, "expect Integer or 'idle' for 1st argument"
end
@init_sleep = sleep
@init_proc = init_proc
@init_args = init_args
self
end
def start(*init_args)
return nil if @running
Tk_CBTBL[@id] = self
@do_loop = @loop_exec
@current_pos = 0
argc = init_args.size
if argc > 0
sleep = init_args.shift
if !sleep == 'idle' && !sleep.kind_of?(Integer)
fail ArguemntError, "expect Integer or 'idle' for 1st argument"
end
@init_sleep = sleep
end
@init_proc = init_args.shift if argc > 1
@init_args = init_args if argc > 0
@current_sleep = @init_sleep
@running = true
if @init_proc
if not @init_proc.kind_of? Proc
fail ArgumentError, "Argument '#{@init_proc}' need to be Proc"
end
@current_proc = @init_proc
set_callback(@init_sleep, @init_args)
@set_next = false if @in_callback
else
set_next_callback(@init_args)
end
self
end
def reset(*reset_args)
restart() if @running
if @init_proc
@return_value = @init_proc.call(self)
else
@return_value = nil
end
@current_pos = 0
@current_args = @init_args
@set_next = false if @in_callback
self
end
def restart(*restart_args)
cancel if @running
if restart_args == []
start(@init_sleep, @init_proc, *@init_args)
else
start(*restart_args)
end
end
def cancel
@running = false
@wait_var.value = 0
tk_call 'after', 'cancel', @after_id if @after_id
@after_id = nil
Tk_CBTBL.delete(@id) ;# for GC
self
end
alias stop cancel
def continue(wait=nil)
fail RuntimeError, "is already running" if @running
sleep, cmd = @current_script
fail RuntimeError, "no procedure to continue" unless cmd
if wait
unless wait.kind_of? Integer
fail ArguemntError, "expect Integer for 1st argument"
end
sleep = wait
end
Tk_CBTBL[@id] = self
@running = true
@after_id = tk_call_without_enc('after', sleep, cmd)
self
end
def skip
fail RuntimeError, "is not running now" unless @running
cancel
Tk_CBTBL[@id] = self
@running = true
set_next_callback(@current_args)
self
end
def info
if @after_id
inf = tk_split_list(tk_call_without_enc('after', 'info', @after_id))
[Tk_CBTBL[inf[0][1]], inf[1]]
else
nil
end
end
def wait(on_thread = true, check_root = false)
if $SAFE >= 4
fail SecurityError, "can't wait timer at $SAFE >= 4"
end
unless @running
if @return_value.kind_of?(Exception)
fail @return_value
else
return @return_value
end
end
@wait_var.wait(on_thread, check_root)
if @return_value.kind_of?(Exception)
fail @return_value
else
@return_value
end
end
def eventloop_wait(check_root = false)
wait(false, check_root)
end
def thread_wait(check_root = false)
wait(true, check_root)
end
def tkwait(on_thread = true)
wait(on_thread, true)
end
def eventloop_tkwait
wait(false, true)
end
def thread_tkwait
wait(true, true)
end
end
TkAfter = TkTimer

211
ext/tk/lib/tk/toplevel.rb Normal file
View File

@ -0,0 +1,211 @@
#
# tk/toplevel.rb : treat toplevel widget
#
require 'tk'
require 'tk/wm'
class TkToplevel<TkWindow
include Wm
TkCommandNames = ['toplevel'.freeze].freeze
WidgetClassName = 'Toplevel'.freeze
WidgetClassNames[WidgetClassName] = self
################# old version
# def initialize(parent=nil, screen=nil, classname=nil, keys=nil)
# if screen.kind_of? Hash
# keys = screen.dup
# else
# @screen = screen
# end
# @classname = classname
# if keys.kind_of? Hash
# keys = keys.dup
# @classname = keys.delete('classname') if keys.key?('classname')
# @colormap = keys.delete('colormap') if keys.key?('colormap')
# @container = keys.delete('container') if keys.key?('container')
# @screen = keys.delete('screen') if keys.key?('screen')
# @use = keys.delete('use') if keys.key?('use')
# @visual = keys.delete('visual') if keys.key?('visual')
# end
# super(parent, keys)
# end
#
# def create_self
# s = []
# s << "-class" << @classname if @classname
# s << "-colormap" << @colormap if @colormap
# s << "-container" << @container if @container
# s << "-screen" << @screen if @screen
# s << "-use" << @use if @use
# s << "-visual" << @visual if @visual
# tk_call 'toplevel', @path, *s
# end
#################
def _wm_command_option_chk(keys)
keys = {} unless keys
new_keys = {}
wm_cmds = {}
keys.each{|k,v|
if Wm.method_defined?(k)
case k
when 'screen','class','colormap','container','use','visual'
new_keys[k] = v
else
case self.method(k).arity
when -1,1
wm_cmds[k] = v
else
new_keys[k] = v
end
end
else
new_keys[k] = v
end
}
[new_keys, wm_cmds]
end
private :_wm_command_option_chk
def initialize(parent=nil, screen=nil, classname=nil, keys=nil)
my_class_name = nil
if self.class < WidgetClassNames[WidgetClassName]
my_class_name = self.class.name
my_class_name = nil if my_class_name == ''
end
if parent.kind_of? Hash
keys = _symbolkey2str(parent)
if keys.key?('classname')
keys['class'] = keys.delete('classname')
end
@classname = keys['class']
@colormap = keys['colormap']
@container = keys['container']
@screen = keys['screen']
@use = keys['use']
@visual = keys['visual']
if !@classname && my_class_name
keys['class'] = @classname = my_class_name
end
if @classname.kind_of? TkBindTag
@db_class = @classname
@classname = @classname.id
elsif @classname
@db_class = TkDatabaseClass.new(@classname)
else
@db_class = self.class
@classname = @db_class::WidgetClassName
end
keys, cmds = _wm_command_option_chk(keys)
super(keys)
cmds.each{|k,v|
if v.kind_of? Array
self.send(k,*v)
else
self.send(k,v)
end
}
return
end
if screen.kind_of? Hash
keys = screen
else
@screen = screen
if classname.kind_of? Hash
keys = classname
else
@classname = classname
end
end
if keys.kind_of? Hash
keys = _symbolkey2str(keys)
if keys.key?('classname')
keys['class'] = keys.delete('classname')
end
@classname = keys['class'] unless @classname
@colormap = keys['colormap']
@container = keys['container']
@screen = keys['screen'] unless @screen
@use = keys['use']
@visual = keys['visual']
else
keys = {}
end
if !@classname && my_class_name
keys['class'] = @classname = my_class_name
end
if @classname.kind_of? TkBindTag
@db_class = @classname
@classname = @classname.id
elsif @classname
@db_class = TkDatabaseClass.new(@classname)
else
@db_class = self.class
@classname = @db_class::WidgetClassName
end
keys, cmds = _wm_command_option_chk(keys)
super(parent, keys)
cmds.each{|k,v|
if v.kind_of? Array
self.send(k,*v)
else
self.send(k,v)
end
}
end
def create_self(keys)
if keys and keys != None
tk_call_without_enc('toplevel', @path, *hash_kv(keys, true))
else
tk_call_without_enc('toplevel', @path)
end
end
private :create_self
def specific_class
@classname
end
def self.database_class
if self == WidgetClassNames[WidgetClassName] || self.name == ''
self
else
TkDatabaseClass.new(self.name)
end
end
def self.database_classname
self.database_class.name
end
def self.bind(*args)
if self == WidgetClassNames[WidgetClassName] || self.name == ''
super(*args)
else
TkDatabaseClass.new(self.name).bind(*args)
end
end
def self.bind_append(*args)
if self == WidgetClassNames[WidgetClassName] || self.name == ''
super(*args)
else
TkDatabaseClass.new(self.name).bind_append(*args)
end
end
def self.bind_remove(*args)
if self == WidgetClassNames[WidgetClassName] || self.name == ''
super(*args)
else
TkDatabaseClass.new(self.name).bind_remove(*args)
end
end
def self.bindinfo(*args)
if self == WidgetClassNames[WidgetClassName] || self.name == ''
super(*args)
else
TkDatabaseClass.new(self.name).bindinfo(*args)
end
end
end

View File

@ -0,0 +1,38 @@
#
# tk/txtwin_abst.rb : TkTextWin abstruct class
#
require 'tk'
class TkTextWin<TkWindow
def create_self
fail RuntimeError, "TkTextWin is an abstract class"
end
private :create_self
def bbox(index)
list(tk_send_without_enc('bbox', index))
end
def delete(first, last=None)
tk_send_without_enc('delete', first, last)
self
end
def get(*index)
_fromUTF8(tk_send_without_enc('get', *index))
end
def insert(index, *args)
tk_send('insert', index, *args)
self
end
def scan_mark(x, y)
tk_send_without_enc('scan', 'mark', x, y)
self
end
def scan_dragto(x, y)
tk_send_without_enc('scan', 'dragto', x, y)
self
end
def see(index)
tk_send_without_enc('see', index)
self
end
end

166
ext/tk/lib/tk/validation.rb Normal file
View File

@ -0,0 +1,166 @@
#
# tk/validation.rb - validation support module for entry, spinbox, and so on
#
require 'tk'
module TkValidation
class ValidateCmd
include TkComm
module Action
Insert = 1
Delete = 0
Others = -1
Focus = -1
Forced = -1
Textvariable = -1
TextVariable = -1
end
class ValidateArgs < TkUtil::CallbackSubst
key_tbl = [
[ ?d, ?n, :action ],
[ ?i, ?x, :index ],
[ ?s, ?e, :current ],
[ ?v, ?s, :type ],
[ ?P, ?e, :value ],
[ ?S, ?e, :string ],
[ ?V, ?s, :triggered ],
[ ?W, ?w, :widget ],
nil
]
proc_tbl = [
[ ?n, TkComm.method(:number) ],
[ ?s, TkComm.method(:string) ],
[ ?w, TkComm.method(:window) ],
[ ?e, proc{|val|
enc = Tk.encoding
if enc
Tk.fromUTF8(TkComm::string(val), enc)
else
TkComm::string(val)
end
}
],
[ ?x, proc{|val|
idx = TkComm::number(val)
if idx < 0
nil
else
idx
end
}
],
nil
]
_setup_subst_table(key_tbl, proc_tbl);
end
def initialize(cmd = Proc.new, *args)
if args.compact.size > 0
args = args.join(' ')
keys = ValidateArgs._get_subst_key(args)
if cmd.kind_of?(String)
id = cmd
elsif cmd.kind_of?(TkCallbackEntry)
@id = install_cmd(cmd)
else
@id = install_cmd(proc{|*arg|
(cmd.call(*ValidateArgs.scan_args(keys, arg)))? '1':'0'
}) + ' ' + args
end
else
keys, args = ValidateArgs._get_all_subst_keys
if cmd.kind_of?(String)
id = cmd
elsif cmd.kind_of?(TkCallbackEntry)
@id = install_cmd(cmd)
else
@id = install_cmd(proc{|*arg|
(cmd.call(
ValidateArgs.new(*ValidateArgs.scan_args(keys,arg)))
)? '1': '0'
}) + ' ' + args
end
end
end
def to_eval
@id
end
end
#####################################
def configure(slot, value=TkComm::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(' '))
elsif slot['vcmd'].kind_of? Proc
slot['vcmd'] = ValidateCmd.new(slot['vcmd'])
end
if slot['validatecommand'].kind_of? Array
cmd, *args = slot['validatecommand']
slot['validatecommand'] = ValidateCmd.new(cmd, args.join(' '))
elsif slot['validatecommand'].kind_of? Proc
slot['validatecommand'] = ValidateCmd.new(slot['validatecommand'])
end
if slot['invcmd'].kind_of? Array
cmd, *args = slot['invcmd']
slot['invcmd'] = ValidateCmd.new(cmd, args.join(' '))
elsif slot['invcmd'].kind_of? Proc
slot['invcmd'] = ValidateCmd.new(slot['invcmd'])
end
if slot['invalidcommand'].kind_of? Array
cmd, *args = slot['invalidcommand']
slot['invalidcommand'] = ValidateCmd.new(cmd, args.join(' '))
elsif slot['invalidcommand'].kind_of? Proc
slot['invalidcommand'] = ValidateCmd.new(slot['invalidcommand'])
end
super(slot)
else
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(' '))
elsif value.kind_of? Proc
value = ValidateCmd.new(value)
end
end
super(slot, value)
end
self
end
def validatecommand(cmd = Proc.new, args = nil)
if cmd.kind_of?(ValidateCmd)
configure('validatecommand', cmd)
elsif args
configure('validatecommand', [cmd, args])
else
configure('validatecommand', cmd)
end
end
alias vcmd validatecommand
def invalidcommand(cmd = Proc.new, args = nil)
if cmd.kind_of?(ValidateCmd)
configure('invalidcommand', cmd)
elsif args
configure('invalidcommand', [cmd, args])
else
configure('invalidcommand', cmd)
end
end
alias invcmd invalidcommand
end

847
ext/tk/lib/tk/variable.rb Normal file
View File

@ -0,0 +1,847 @@
#
# tk/variable.rb : treat Tk variable object
#
require 'tk'
class TkVariable
include Tk
extend TkCore
include Comparable
#TkCommandNames = ['tkwait'.freeze].freeze
TkCommandNames = ['vwait'.freeze].freeze
#TkVar_CB_TBL = {}
#TkVar_ID_TBL = {}
TkVar_CB_TBL = TkCore::INTERP.create_table
TkVar_ID_TBL = TkCore::INTERP.create_table
Tk_VARIABLE_ID = ["v".freeze, "00000".taint].freeze
#TkCore::INTERP.add_tk_procs('rb_var', 'args',
# "ruby [format \"TkVariable.callback %%Q!%s!\" $args]")
TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL')
if {[set st [catch {eval {ruby_cmd TkVariable callback} $args} ret]] != 0} {
set idx [string first "\n\n" $ret]
if {$idx > 0} {
global errorInfo
set tcl_backtrace $errorInfo
set errorInfo [string range $ret [expr $idx + 2] \
[string length $ret]]
append errorInfo "\n" $tcl_backtrace
bgerror [string range $ret 0 [expr $idx - 1]]
} else {
bgerror $ret
}
return ""
#return -code $st $ret
} else {
return $ret
}
EOL
#def TkVariable.callback(args)
def TkVariable.callback(name1, name2, op)
#name1,name2,op = tk_split_list(args)
#name1,name2,op = tk_split_simplelist(args)
if TkVar_CB_TBL[name1]
#_get_eval_string(TkVar_CB_TBL[name1].trace_callback(name2,op))
begin
_get_eval_string(TkVar_CB_TBL[name1].trace_callback(name2, op))
rescue Exception => e
begin
msg = _toUTF8(e.class.inspect) + ': ' +
_toUTF8(e.message) + "\n" +
"\n---< backtrace of Ruby side >-----\n" +
_toUTF8(e.backtrace.join("\n")) +
"\n---< backtrace of Tk side >-------"
msg.instance_variable_set(:@encoding, 'utf-8')
rescue Exception
msg = e.class.inspect + ': ' + e.message + "\n" +
"\n---< backtrace of Ruby side >-----\n" +
e.backtrace.join("\n") +
"\n---< backtrace of Tk side >-------"
end
fail(e, msg)
end
=begin
begin
raise 'check backtrace'
rescue
# ignore backtrace before 'callback'
pos = -($!.backtrace.size)
end
begin
_get_eval_string(TkVar_CB_TBL[name1].trace_callback(name2,op))
rescue
trace = $!.backtrace
raise $!, "\n#{trace[0]}: #{$!.message} (#{$!.class})\n" +
"\tfrom #{trace[1..pos].join("\n\tfrom ")}"
end
=end
else
''
end
end
def initialize(val="")
@id = Tk_VARIABLE_ID.join('')
Tk_VARIABLE_ID[1].succ!
TkVar_ID_TBL[@id] = self
@trace_var = nil
@trace_elem = nil
@trace_opts = nil
begin
INTERP._unset_global_var(@id)
rescue
end
# teach Tk-ip that @id is global var
INTERP._invoke_without_enc('global', @id)
#INTERP._invoke('global', @id)
self.value = val
=begin
if val == []
# INTERP._eval(format('global %s; set %s(0) 0; unset %s(0)',
# @id, @id, @id))
elsif val.kind_of?(Array)
a = []
# val.each_with_index{|e,i| a.push(i); a.push(array2tk_list(e))}
# s = '"' + a.join(" ").gsub(/[\[\]$"]/, '\\\\\&') + '"'
val.each_with_index{|e,i| a.push(i); a.push(e)}
#s = '"' + array2tk_list(a).gsub(/[\[\]$"]/, '\\\\\&') + '"'
s = '"' + array2tk_list(a).gsub(/[\[\]$"\\]/, '\\\\\&') + '"'
INTERP._eval(format('global %s; array set %s %s', @id, @id, s))
elsif val.kind_of?(Hash)
#s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\
# .gsub(/[\[\]$"]/, '\\\\\&') + '"'
s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\
.gsub(/[\[\]$"\\]/, '\\\\\&') + '"'
INTERP._eval(format('global %s; array set %s %s', @id, @id, s))
else
#s = '"' + _get_eval_string(val).gsub(/[\[\]$"]/, '\\\\\&') + '"'
s = '"' + _get_eval_string(val).gsub(/[\[\]$"\\]/, '\\\\\&') + '"'
INTERP._eval(format('global %s; set %s %s', @id, @id, s))
end
=end
=begin
if val.kind_of?(Hash)
#s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\
# .gsub(/[\[\]$"]/, '\\\\\&') + '"'
s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\
.gsub(/[\[\]$"\\]/, '\\\\\&') + '"'
INTERP._eval(Kernel.format('global %s; array set %s %s', @id, @id, s))
else
#s = '"' + _get_eval_string(val).gsub(/[\[\]$"]/, '\\\\\&') + '"'
s = '"' + _get_eval_string(val).gsub(/[\[\]$"\\]/, '\\\\\&') + '"'
INTERP._eval(Kernel.format('global %s; set %s %s', @id, @id, s))
end
=end
end
def wait(on_thread = false, check_root = false)
if $SAFE >= 4
fail SecurityError, "can't wait variable at $SAFE >= 4"
end
on_thread &= (Thread.list.size != 1)
if on_thread
if check_root
INTERP._thread_tkwait('variable', @id)
else
INTERP._thread_vwait(@id)
end
else
if check_root
INTERP._invoke_without_enc('tkwait', 'variable', @id)
else
INTERP._invoke_without_enc('vwait', @id)
end
end
end
def eventloop_wait(check_root = false)
wait(false, check_root)
end
def thread_wait(check_root = false)
wait(true, check_root)
end
def tkwait(on_thread = true)
wait(on_thread, true)
end
def eventloop_tkwait
wait(false, true)
end
def thread_tkwait
wait(true, true)
end
def id
@id
end
def is_hash?
#ITNERP._eval("global #{@id}; array exist #{@id}") == '1'
ITNERP._invoke_without_enc('array', 'exist', @id) == '1'
end
def is_scalar?
! is_hash?
end
def keys
if (is_scalar?)
fail RuntimeError, 'cannot get keys from a scalar variable'
end
#tk_split_simplelist(INTERP._eval("global #{@id}; array get #{@id}"))
tk_split_simplelist(INTERP._fromUTF8(INTERP._invoke_without_enc('array', 'get', @id)))
end
unless const_defined?(:USE_TCLs_SET_VARIABLE_FUNCTIONS)
USE_TCLs_SET_VARIABLE_FUNCTIONS = true
end
if USE_TCLs_SET_VARIABLE_FUNCTIONS
###########################################################################
# use Tcl function version of set tkvariable
###########################################################################
def value
#if INTERP._eval("global #{@id}; array exist #{@id}") == '1'
if INTERP._invoke('array', 'exist', @id) == '1'
#Hash[*tk_split_simplelist(INTERP._eval("global #{@id}; array get #{@id}"))]
Hash[*tk_split_simplelist(INTERP._invoke('array', 'get', @id))]
else
_fromUTF8(INTERP._get_global_var(@id))
end
end
def value=(val)
if val.kind_of?(Hash)
val.each{|k, v|
#INTERP._set_global_var2(@id, _toUTF8(_get_eval_string(k)),
# _toUTF8(_get_eval_string(v)))
INTERP._set_global_var2(@id, __get_eval_string(k, true),
_get_eval_string(v, true))
}
self.value
elsif val.kind_of?(Array)
INTERP._set_global_var(@id, '')
val.each{|v|
#INTERP._set_variable(@id, _toUTF8(_get_eval_string(v)),
INTERP._set_variable(@id, _get_eval_string(v, true),
TclTkLib::VarAccessFlag::GLOBAL_ONLY |
TclTkLib::VarAccessFlag::LEAVE_ERR_MSG |
TclTkLib::VarAccessFlag::APPEND_VALUE |
TclTkLib::VarAccessFlag::LIST_ELEMENT)
}
self.value
else
#_fromUTF8(INTERP._set_global_var(@id, _toUTF8(_get_eval_string(val))))
_fromUTF8(INTERP._set_global_var(@id, _get_eval_string(val, true)))
end
end
def [](index)
#_fromUTF8(INTERP._get_global_var2(@id, _toUTF8(_get_eval_string(index))))
_fromUTF8(INTERP._get_global_var2(@id, _get_eval_string(index, true)))
end
def []=(index,val)
#_fromUTF8(INTERP._set_global_var2(@id, _toUTF8(_get_eval_string(index)),
# _toUTF8(_get_eval_string(val))))
_fromUTF8(INTERP._set_global_var2(@id, _get_eval_string(index, true),
_get_eval_string(val, true)))
end
def unset(elem=nil)
if elem
INTERP._unset_global_var2(@id, tk_tcl2ruby(elem))
else
INTERP._unset_global_var(@id)
end
end
alias remove unset
else
###########################################################################
# use Ruby script version of set tkvariable (traditional methods)
###########################################################################
def value
begin
INTERP._eval(Kernel.format('global %s; set %s', @id, @id))
#INTERP._eval(Kernel.format('set %s', @id))
#INTERP._invoke_without_enc('set', @id)
rescue
if INTERP._eval(Kernel.format('global %s; array exists %s',
@id, @id)) != "1"
#if INTERP._eval(Kernel.format('array exists %s', @id)) != "1"
#if INTERP._invoke_without_enc('array', 'exists', @id) != "1"
fail
else
Hash[*tk_split_simplelist(INTERP._eval(Kernel.format('global %s; array get %s', @id, @id)))]
#Hash[*tk_split_simplelist(_fromUTF8(INTERP._invoke_without_enc('array', 'get', @id)))]
end
end
end
def value=(val)
begin
#s = '"' + _get_eval_string(val).gsub(/[\[\]$"]/, '\\\\\&') + '"'
s = '"' + _get_eval_string(val).gsub(/[\[\]$"\\]/, '\\\\\&') + '"'
INTERP._eval(Kernel.format('global %s; set %s %s', @id, @id, s))
#INTERP._eval(Kernel.format('set %s %s', @id, s))
#_fromUTF8(INTERP._invoke_without_enc('set', @id, _toUTF8(s)))
rescue
if INTERP._eval(Kernel.format('global %s; array exists %s',
@id, @id)) != "1"
#if INTERP._eval(Kernel.format('array exists %s', @id)) != "1"
#if INTERP._invoke_without_enc('array', 'exists', @id) != "1"
fail
else
if val == []
INTERP._eval(Kernel.format('global %s; unset %s; set %s(0) 0; unset %s(0)', @id, @id, @id, @id))
#INTERP._eval(Kernel.format('unset %s; set %s(0) 0; unset %s(0)',
# @id, @id, @id))
#INTERP._invoke_without_enc('unset', @id)
#INTERP._invoke_without_enc('set', @id+'(0)', 0)
#INTERP._invoke_without_enc('unset', @id+'(0)')
elsif val.kind_of?(Array)
a = []
val.each_with_index{|e,i| a.push(i); a.push(array2tk_list(e))}
#s = '"' + a.join(" ").gsub(/[\[\]$"]/, '\\\\\&') + '"'
s = '"' + a.join(" ").gsub(/[\[\]$"\\]/, '\\\\\&') + '"'
INTERP._eval(Kernel.format('global %s; unset %s; array set %s %s',
@id, @id, @id, s))
#INTERP._eval(Kernel.format('unset %s; array set %s %s',
# @id, @id, s))
#INTERP._invoke_without_enc('unset', @id)
#_fromUTF8(INTERP._invoke_without_enc('array','set', @id, _toUTF8(s)))
elsif val.kind_of?(Hash)
#s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\
# .gsub(/[\[\]$"]/, '\\\\\&') + '"'
s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\
.gsub(/[\[\]$\\"]/, '\\\\\&') + '"'
INTERP._eval(Kernel.format('global %s; unset %s; array set %s %s',
@id, @id, @id, s))
#INTERP._eval(Kernel.format('unset %s; array set %s %s',
# @id, @id, s))
#INTERP._invoke_without_enc('unset', @id)
#_fromUTF8(INTERP._invoke_without_enc('array','set', @id, _toUTF8(s)))
else
fail
end
end
end
end
def [](index)
INTERP._eval(Kernel.format('global %s; set %s(%s)',
@id, @id, _get_eval_string(index)))
#INTERP._eval(Kernel.format('set %s(%s)', @id, _get_eval_string(index)))
#INTERP._eval('set ' + @id + '(' + _get_eval_string(index) + ')')
end
def []=(index,val)
INTERP._eval(Kernel.format('global %s; set %s(%s) %s', @id, @id,
_get_eval_string(index), _get_eval_string(val)))
#INTERP._eval(Kernel.format('set %s(%s) %s', @id,
# _get_eval_string(index), _get_eval_string(val)))
#INTERP._eval('set ' + @id + '(' + _get_eval_string(index) + ') ' +
# _get_eval_string(val))
end
def unset(elem=nil)
if elem
INTERP._eval(Kernel.format('global %s; unset %s(%s)',
@id, @id, tk_tcl2ruby(elem)))
#INTERP._eval(Kernel.format('unset %s(%s)', @id, tk_tcl2ruby(elem)))
#INTERP._eval('unset ' + @id + '(' + _get_eval_string(elem) + ')')
else
INTERP._eval(Kernel.format('global %s; unset %s', @id, @id))
#INTERP._eval(Kernel.format('unset %s', @id))
#INTERP._eval('unset ' + @id)
end
end
alias remove unset
end
def numeric
number(value)
end
def numeric=(val)
case val
when Numeric
self.value=(val)
when TkVariable
self.value=(val.numeric)
else
raise ArgumentError, "Numeric is expected"
end
val
end
def to_i
number(value).to_i
end
def to_f
number(value).to_f
end
def to_s
#string(value).to_s
value
end
def to_sym
value.intern
end
def list
#tk_split_list(value)
tk_split_simplelist(value)
end
alias to_a list
def list=(val)
case val
when Array
self.value=(val)
when TkVariable
self.value=(val.list)
else
raise ArgumentError, "Array is expected"
end
val
end
def inspect
#Kernel.format "#<TkVariable: %s>", @id
'#<TkVariable: ' + @id + '>'
end
def coerce(other)
case other
when TkVariable
[other.value, self.value]
when String
[other, self.to_s]
when Symbol
[other, self.to_sym]
when Integer
[other, self.to_i]
when Float
[other, self.to_f]
when Array
[other, self.to_a]
else
[other, self.value]
end
end
def &(other)
if other.kind_of?(Array)
self.to_a & other.to_a
else
self.to_i & other.to_i
end
end
def |(other)
if other.kind_of?(Array)
self.to_a | other.to_a
else
self.to_i | other.to_i
end
end
def +(other)
case other
when Array
self.to_a + other
when String
self.value + other
else
begin
number(self.value) + other
rescue
self.value + other.to_s
end
end
end
def -(other)
if other.kind_of?(Array)
self.to_a - other
else
number(self.value) - other
end
end
def *(other)
begin
number(self.value) * other
rescue
self.value * other
end
end
def /(other)
number(self.value) / other
end
def %(other)
begin
number(self.value) % other
rescue
self.value % other
end
end
def **(other)
number(self.value) ** other
end
def =~(other)
self.value =~ other
end
def ==(other)
case other
when TkVariable
self.equal?(other)
when String
self.to_s == other
when Symbol
self.to_sym == other
when Integer
self.to_i == other
when Float
self.to_f == other
when Array
self.to_a == other
when Hash
self.value == other
else
false
end
end
def zero?
numeric.zero?
end
def nonzero?
!(numeric.zero?)
end
def <=>(other)
if other.kind_of?(TkVariable)
begin
val = other.numeric
other = val
rescue
other = other.value
end
end
if other.kind_of?(Numeric)
begin
return self.numeric <=> other
rescue
return self.value <=> other.to_s
end
else
return self.value <=> other
end
end
def to_eval
@id
end
def trace_callback(elem, op)
if @trace_var.kind_of? Array
@trace_var.each{|m,e| e.call(self,elem,op) if m.index(op)}
end
if elem.kind_of?(String) && elem != ''
if @trace_elem.kind_of?(Hash) && @trace_elem[elem].kind_of?(Array)
@trace_elem[elem].each{|m,e| e.call(self,elem,op) if m.index(op)}
end
end
end
def trace(opts, cmd = Proc.new)
@trace_var = [] if @trace_var == nil
opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
@trace_var.unshift([opts,cmd])
if @trace_opts == nil
TkVar_CB_TBL[@id] = self
@trace_opts = opts.dup
Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts, 'rb_var')
=begin
if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
# TCL_VERSION >= 8.4
Tk.tk_call_without_enc('trace', 'add', 'variable',
@id, @trace_opts, 'rb_var')
else
# TCL_VERSION <= 8.3
Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts, 'rb_var')
end
=end
else
newopts = @trace_opts.dup
opts.each_byte{|c| newopts += c.chr unless newopts.index(c)}
if newopts != @trace_opts
Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts, 'rb_var')
@trace_opts.replace(newopts)
Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts, 'rb_var')
=begin
if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
# TCL_VERSION >= 8.4
Tk.tk_call_without_enc('trace', 'remove', 'variable',
@id, @trace_opts, 'rb_var')
@trace_opts.replace(newopts)
Tk.tk_call_without_enc('trace', 'add', 'variable',
@id, @trace_opts, 'rb_var')
else
# TCL_VERSION <= 8.3
Tk.tk_call_without_enc('trace', 'vdelete',
@id, @trace_opts, 'rb_var')
@trace_opts.replace(newopts)
Tk.tk_call_without_enc('trace', 'variable',
@id, @trace_opts, 'rb_var')
end
=end
end
end
self
end
def trace_element(elem, opts, cmd = Proc.new)
@trace_elem = {} if @trace_elem == nil
@trace_elem[elem] = [] if @trace_elem[elem] == nil
opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
@trace_elem[elem].unshift([opts,cmd])
if @trace_opts == nil
TkVar_CB_TBL[@id] = self
@trace_opts = opts.dup
Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts, 'rb_var')
=begin
if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
# TCL_VERSION >= 8.4
Tk.tk_call_without_enc('trace', 'add', 'variable',
@id, @trace_opts, 'rb_var')
else
# TCL_VERSION <= 8.3
Tk.tk_call_without_enc('trace', 'variable',
@id, @trace_opts, 'rb_var')
end
=end
else
newopts = @trace_opts.dup
opts.each_byte{|c| newopts += c.chr unless newopts.index(c)}
if newopts != @trace_opts
Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts, 'rb_var')
@trace_opts.replace(newopts)
Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts, 'rb_var')
=begin
if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
# TCL_VERSION >= 8.4
Tk.tk_call_without_enc('trace', 'remove', 'variable',
@id, @trace_opts, 'rb_var')
@trace_opts.replace(newopts)
Tk.tk_call_without_enc('trace', 'add', 'variable',
@id, @trace_opts, 'rb_var')
else
# TCL_VERSION <= 8.3
Tk.tk_call_without_enc('trace', 'vdelete',
@id, @trace_opts, 'rb_var')
@trace_opts.replace(newopts)
Tk.tk_call_without_enc('trace', 'variable',
@id, @trace_opts, 'rb_var')
end
=end
end
end
self
end
def trace_vinfo
return [] unless @trace_var
@trace_var.dup
end
def trace_vinfo_for_element(elem)
return [] unless @trace_elem
return [] unless @trace_elem[elem]
@trace_elem[elem].dup
end
def trace_vdelete(opts,cmd)
return self unless @trace_var.kind_of? Array
opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
idx = -1
newopts = ''
@trace_var.each_with_index{|e,i|
if idx < 0 && e[0] == opts && e[1] == cmd
idx = i
next
end
e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
}
if idx >= 0
@trace_var.delete_at(idx)
else
return self
end
@trace_elem.each{|elem|
@trace_elem[elem].each{|e|
e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
}
}
newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('')
if newopts != @trace_opts
Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts, 'rb_var')
=begin
if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
# TCL_VERSION >= 8.4
Tk.tk_call_without_enc('trace', 'remove', 'variable',
@id, @trace_opts, 'rb_var')
else
# TCL_VERSION <= 8.3
Tk.tk_call_without_enc('trace', 'vdelete',
@id, @trace_opts, 'rb_var')
end
=end
@trace_opts.replace(newopts)
if @trace_opts != ''
Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts, 'rb_var')
=begin
if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
# TCL_VERSION >= 8.4
Tk.tk_call_without_enc('trace', 'add', 'variable',
@id, @trace_opts, 'rb_var')
else
# TCL_VERSION <= 8.3
Tk.tk_call_without_enc('trace', 'variable',
@id, @trace_opts, 'rb_var')
end
=end
end
end
self
end
def trace_vdelete_for_element(elem,opts,cmd)
return self unless @trace_elem.kind_of? Hash
return self unless @trace_elem[elem].kind_of? Array
opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
idx = -1
@trace_elem[elem].each_with_index{|e,i|
if idx < 0 && e[0] == opts && e[1] == cmd
idx = i
next
end
}
if idx >= 0
@trace_elem[elem].delete_at(idx)
else
return self
end
newopts = ''
@trace_var.each{|e|
e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
}
@trace_elem.each{|elem|
@trace_elem[elem].each{|e|
e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
}
}
newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('')
if newopts != @trace_opts
Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts, 'rb_var')
=begin
if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
# TCL_VERSION >= 8.4
Tk.tk_call_without_enc('trace', 'remove', 'variable',
@id, @trace_opts, 'rb_var')
else
# TCL_VERSION <= 8.3
Tk.tk_call_without_enc('trace', 'vdelete',
@id, @trace_opts, 'rb_var')
end
=end
@trace_opts.replace(newopts)
if @trace_opts != ''
Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts, 'rb_var')
=begin
if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
# TCL_VERSION >= 8.4
Tk.tk_call_without_enc('trace', 'add', 'variable',
@id, @trace_opts, 'rb_var')
else
# TCL_VERSION <= 8.3
Tk.tk_call_without_enc('trace', 'variable', @id,
@trace_opts, 'rb_var')
end
=end
end
end
self
end
end
class TkVarAccess<TkVariable
def self.new(name, *args)
return TkVar_ID_TBL[name] if TkVar_ID_TBL[name]
super(name, *args)
end
def initialize(varname, val=nil)
@id = varname
TkVar_ID_TBL[@id] = self
# teach Tk-ip that @id is global var
INTERP._invoke_without_enc('global', @id)
if val
#s = '"' + _get_eval_string(val).gsub(/[\[\]$"]/, '\\\\\&') + '"' #"
#s = '"' + _get_eval_string(val).gsub(/[\[\]$"\\]/, '\\\\\&') + '"' #"
#INTERP._eval(Kernel.format('global %s; set %s %s', @id, @id, s))
#INTERP._set_global_var(@id, _toUTF8(_get_eval_string(val)))
self.value = val
end
end
end
module Tk
begin
auto_path = INTERP._invoke('set', 'auto_path')
rescue
begin
auto_path = INTERP._invoke('set', 'env(TCLLIBPATH)')
rescue
auto_path = Tk::LIBRARY
end
end
AUTO_PATH = TkVarAccess.new('auto_path', auto_path)
=begin
AUTO_OLDPATH = tk_split_simplelist(INTERP._invoke('set', 'auto_oldpath'))
AUTO_OLDPATH.each{|s| s.freeze}
AUTO_OLDPATH.freeze
=end
TCL_PACKAGE_PATH = TkVarAccess.new('tcl_pkgPath')
PACKAGE_PATH = TCL_PACKAGE_PATH
TCL_LIBRARY_PATH = TkVarAccess.new('tcl_libPath')
LIBRARY_PATH = TCL_LIBRARY_PATH
TCL_PRECISION = TkVarAccess.new('tcl_precision')
end

View File

@ -0,0 +1,89 @@
#
# tk/virtevent.rb : treats virtual events
# 1998/07/16 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
#
require 'tk'
class TkVirtualEvent<TkObject
extend Tk
TkCommandNames = ['event'.freeze].freeze
TkVirtualEventID = ["<VirtEvent".freeze, "00000".taint, ">".freeze].freeze
TkVirtualEventTBL = TkCore::INTERP.create_table
TkCore::INTERP.init_ip_env{ TkVirtualEventTBL.clear }
class PreDefVirtEvent<self
def initialize(event)
@path = @id = event
TkVirtualEvent::TkVirtualEventTBL[@id] = self
end
end
def TkVirtualEvent.getobj(event)
obj = TkVirtualEventTBL[event]
if obj
obj
else
if tk_call_without_enc('event', 'info').index("<#{event}>")
PreDefVirtEvent.new(event)
else
fail ArgumentError, "undefined virtual event '<#{event}>'"
end
end
end
def TkVirtualEvent.info
tk_call_without_enc('event', 'info').split(/\s+/).collect!{|seq|
TkVirtualEvent.getobj(seq[1..-2])
}
end
def initialize(*sequences)
@path = @id = TkVirtualEventID.join('')
TkVirtualEventID[1].succ!
add(*sequences)
end
def add(*sequences)
if sequences != []
tk_call_without_enc('event', 'add', "<#{@id}>",
*(sequences.collect{|seq|
"<#{tk_event_sequence(seq)}>"
}) )
TkVirtualEventTBL[@id] = self
end
self
end
def delete(*sequences)
if sequences == []
tk_call_without_enc('event', 'delete', "<#{@id}>")
TkVirtualEventTBL.delete(@id)
else
tk_call_without_enc('event', 'delete', "<#{@id}>",
*(sequences.collect{|seq|
"<#{tk_event_sequence(seq)}>"
}) )
TkVirtualEventTBL.delete(@id) if info == []
end
self
end
def info
tk_call_without_enc('event','info',"<#{@id}>").split(/\s+/).collect!{|seq|
l = seq.scan(/<*[^<>]+>*/).collect!{|subseq|
case (subseq)
when /^<<[^<>]+>>$/
TkVirtualEvent.getobj(subseq[1..-2])
when /^<[^<>]+>$/
subseq[1..-2]
else
subseq.split('')
end
}.flatten
(l.size == 1) ? l[0] : l
}
end
end

384
ext/tk/lib/tk/winfo.rb Normal file
View File

@ -0,0 +1,384 @@
#
# tk/winfo.rb : methods for winfo command
#
require 'tk'
module TkWinfo
include Tk
extend Tk
TkCommandNames = ['winfo'.freeze].freeze
def TkWinfo.atom(name, win=nil)
if win
number(tk_call_without_enc('winfo', 'atom', '-displayof', win,
_get_eval_enc_str(name)))
else
number(tk_call_without_enc('winfo', 'atom', _get_eval_enc_str(name)))
end
end
def winfo_atom(name)
TkWinfo.atom(name, self)
end
def TkWinfo.atomname(id, win=nil)
if win
_fromUTF8(tk_call_without_enc('winfo', 'atomname',
'-displayof', win, id))
else
_fromUTF8(tk_call_without_enc('winfo', 'atomname', id))
end
end
def winfo_atomname(id)
TkWinfo.atomname(id, self)
end
def TkWinfo.cells(window)
number(tk_call_without_enc('winfo', 'cells', window))
end
def winfo_cells
TkWinfo.cells self
end
def TkWinfo.children(window)
list(tk_call_without_enc('winfo', 'children', window))
end
def winfo_children
TkWinfo.children self
end
def TkWinfo.classname(window)
tk_call_without_enc('winfo', 'class', window)
end
def winfo_classname
TkWinfo.classname self
end
alias winfo_class winfo_classname
def TkWinfo.colormapfull(window)
bool(tk_call_without_enc('winfo', 'colormapfull', window))
end
def winfo_colormapfull
TkWinfo.colormapfull self
end
def TkWinfo.containing(rootX, rootY, win=nil)
if win
window(tk_call_without_enc('winfo', 'containing',
'-displayof', win, rootX, rootY))
else
window(tk_call_without_enc('winfo', 'containing', rootX, rootY))
end
end
def winfo_containing(x, y)
TkWinfo.containing(x, y, self)
end
def TkWinfo.depth(window)
number(tk_call_without_enc('winfo', 'depth', window))
end
def winfo_depth
TkWinfo.depth self
end
def TkWinfo.exist?(window)
bool(tk_call_without_enc('winfo', 'exists', window))
end
def winfo_exist?
TkWinfo.exist? self
end
def TkWinfo.fpixels(window, dist)
number(tk_call_without_enc('winfo', 'fpixels', window, dist))
end
def winfo_fpixels(dist)
TkWinfo.fpixels self, dist
end
def TkWinfo.geometry(window)
tk_call_without_enc('winfo', 'geometry', window)
end
def winfo_geometry
TkWinfo.geometry self
end
def TkWinfo.height(window)
number(tk_call_without_enc('winfo', 'height', window))
end
def winfo_height
TkWinfo.height self
end
def TkWinfo.id(window)
tk_call_without_enc('winfo', 'id', window)
end
def winfo_id
TkWinfo.id self
end
def TkWinfo.interps(window=nil)
if window
tk_split_simplelist(tk_call_without_enc('winfo', 'interps',
'-displayof', window))
else
tk_split_simplelist(tk_call_without_enc('winfo', 'interps'))
end
end
def winfo_interps
TkWinfo.interps self
end
def TkWinfo.mapped?(window)
bool(tk_call_without_enc('winfo', 'ismapped', window))
end
def winfo_mapped?
TkWinfo.mapped? self
end
def TkWinfo.manager(window)
tk_call_without_enc('winfo', 'manager', window)
end
def winfo_manager
TkWinfo.manager self
end
def TkWinfo.appname(window)
tk_call('winfo', 'name', window)
end
def winfo_appname
TkWinfo.appname self
end
def TkWinfo.parent(window)
window(tk_call_without_enc('winfo', 'parent', window))
end
def winfo_parent
TkWinfo.parent self
end
def TkWinfo.widget(id, win=nil)
if win
window(tk_call_without_enc('winfo', 'pathname', '-displayof', win, id))
else
window(tk_call_without_enc('winfo', 'pathname', id))
end
end
def winfo_widget(id)
TkWinfo.widget id, self
end
def TkWinfo.pixels(window, dist)
number(tk_call_without_enc('winfo', 'pixels', window, dist))
end
def winfo_pixels(dist)
TkWinfo.pixels self, dist
end
def TkWinfo.reqheight(window)
number(tk_call_without_enc('winfo', 'reqheight', window))
end
def winfo_reqheight
TkWinfo.reqheight self
end
def TkWinfo.reqwidth(window)
number(tk_call_without_enc('winfo', 'reqwidth', window))
end
def winfo_reqwidth
TkWinfo.reqwidth self
end
def TkWinfo.rgb(window, color)
list(tk_call_without_enc('winfo', 'rgb', window, color))
end
def winfo_rgb(color)
TkWinfo.rgb self, color
end
def TkWinfo.rootx(window)
number(tk_call_without_enc('winfo', 'rootx', window))
end
def winfo_rootx
TkWinfo.rootx self
end
def TkWinfo.rooty(window)
number(tk_call_without_enc('winfo', 'rooty', window))
end
def winfo_rooty
TkWinfo.rooty self
end
def TkWinfo.screen(window)
tk_call('winfo', 'screen', window)
end
def winfo_screen
TkWinfo.screen self
end
def TkWinfo.screencells(window)
number(tk_call_without_enc('winfo', 'screencells', window))
end
def winfo_screencells
TkWinfo.screencells self
end
def TkWinfo.screendepth(window)
number(tk_call_without_enc('winfo', 'screendepth', window))
end
def winfo_screendepth
TkWinfo.screendepth self
end
def TkWinfo.screenheight (window)
number(tk_call_without_enc('winfo', 'screenheight', window))
end
def winfo_screenheight
TkWinfo.screenheight self
end
def TkWinfo.screenmmheight(window)
number(tk_call_without_enc('winfo', 'screenmmheight', window))
end
def winfo_screenmmheight
TkWinfo.screenmmheight self
end
def TkWinfo.screenmmwidth(window)
number(tk_call_without_enc('winfo', 'screenmmwidth', window))
end
def winfo_screenmmwidth
TkWinfo.screenmmwidth self
end
def TkWinfo.screenvisual(window)
tk_call_without_enc('winfo', 'screenvisual', window)
end
def winfo_screenvisual
TkWinfo.screenvisual self
end
def TkWinfo.screenwidth(window)
number(tk_call_without_enc('winfo', 'screenwidth', window))
end
def winfo_screenwidth
TkWinfo.screenwidth self
end
def TkWinfo.server(window)
tk_call('winfo', 'server', window)
end
def winfo_server
TkWinfo.server self
end
def TkWinfo.toplevel(window)
window(tk_call_without_enc('winfo', 'toplevel', window))
end
def winfo_toplevel
TkWinfo.toplevel self
end
def TkWinfo.visual(window)
tk_call_without_enc('winfo', 'visual', window)
end
def winfo_visual
TkWinfo.visual self
end
def TkWinfo.visualid(window)
tk_call_without_enc('winfo', 'visualid', window)
end
def winfo_visualid
TkWinfo.visualid self
end
def TkWinfo.visualsavailable(window, includeids=false)
if includeids
list(tk_call_without_enc('winfo', 'visualsavailable',
window, "includeids"))
else
list(tk_call_without_enc('winfo', 'visualsavailable', window))
end
end
def winfo_visualsavailable(includeids=false)
TkWinfo.visualsavailable self, includeids
end
def TkWinfo.vrootheight(window)
number(tk_call_without_enc('winfo', 'vrootheight', window))
end
def winfo_vrootheight
TkWinfo.vrootheight self
end
def TkWinfo.vrootwidth(window)
number(tk_call_without_enc('winfo', 'vrootwidth', window))
end
def winfo_vrootwidth
TkWinfo.vrootwidth self
end
def TkWinfo.vrootx(window)
number(tk_call_without_enc('winfo', 'vrootx', window))
end
def winfo_vrootx
TkWinfo.vrootx self
end
def TkWinfo.vrooty(window)
number(tk_call_without_enc('winfo', 'vrooty', window))
end
def winfo_vrooty
TkWinfo.vrooty self
end
def TkWinfo.width(window)
number(tk_call_without_enc('winfo', 'width', window))
end
def winfo_width
TkWinfo.width self
end
def TkWinfo.x(window)
number(tk_call_without_enc('winfo', 'x', window))
end
def winfo_x
TkWinfo.x self
end
def TkWinfo.y(window)
number(tk_call_without_enc('winfo', 'y', window))
end
def winfo_y
TkWinfo.y self
end
def TkWinfo.viewable(window)
bool(tk_call_without_enc('winfo', 'viewable', window))
end
def winfo_viewable
TkWinfo.viewable self
end
def TkWinfo.pointerx(window)
number(tk_call_without_enc('winfo', 'pointerx', window))
end
def winfo_pointerx
TkWinfo.pointerx self
end
def TkWinfo.pointery(window)
number(tk_call_without_enc('winfo', 'pointery', window))
end
def winfo_pointery
TkWinfo.pointery self
end
def TkWinfo.pointerxy(window)
list(tk_call_without_enc('winfo', 'pointerxy', window))
end
def winfo_pointerxy
TkWinfo.pointerxy self
end
end

136
ext/tk/lib/tk/winpkg.rb Normal file
View File

@ -0,0 +1,136 @@
#
# tk/winpkg.rb : methods for Tcl/Tk packages for Microsoft Windows
# 2000/11/22 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
#
# ATTENTION !!
# This is NOT TESTED. Because I have no test-environment.
#
require 'tk'
module TkWinDDE
extend Tk
extend TkWinDDE
TkCommandNames = ['dde'.freeze].freeze
if self.const_defined? :FORCE_VERSION
tk_call_without_enc('package', 'require', 'dde', FORCE_VERSION)
else
tk_call_without_enc('package', 'require', 'dde')
end
def servername(topic=None)
tk_call('dde', 'servername', topic)
end
def servername(*args)
if args.size == 0
tk_call('dde', 'servername')
else
if args[-1].kind_of?(Hash)
keys = _symbolkey2str(args.pop)
force = (keys.delete('force'))? '-force': None
exact = (keys.delete('exact'))? '-exact': None
if keys.size == 0
tk_call('dde', 'servername', force, exact)
elsif args.size == 0
tk_call('dde', 'servername', force, exact, *hash_kv(keys))
else
tk_call('dde', 'servername', force, exact,
*((hash_kv(keys) << '--') + args))
end
end
end
end
def execute(service, topic, data)
tk_call('dde', 'execute', service, topic, data)
end
def async_execute(service, topic, data)
tk_call('dde', '-async', 'execute', service, topic, data)
end
def poke(service, topic, item, data)
tk_call('dde', 'poke', service, topic, item, data)
end
def request(service, topic, item)
tk_call('dde', 'request', service, topic, item)
end
def binary_request(service, topic, item)
tk_call('dde', 'request', '-binary', service, topic, item)
end
def services(service, topic)
tk_call('dde', 'services', service, topic)
end
def eval(topic, cmd, *args)
tk_call('dde', 'eval', topic, cmd, *args)
end
def async_eval(topic, cmd, *args)
tk_call('dde', 'eval', -async, topic, cmd, *args)
end
module_function :servername, :execute, :async_execute,
:poke, :request, :services, :eval
end
module TkWinRegistry
extend Tk
extend TkWinRegistry
TkCommandNames = ['registry'.freeze].freeze
if self.const_defined? :FORCE_VERSION
tk_call('package', 'require', 'registry', FORCE_VERSION)
else
tk_call('package', 'require', 'registry')
end
def broadcast(keynam, timeout=nil)
if timeout
tk_call('registry', 'broadcast', keynam, '-timeout', timeout)
else
tk_call('registry', 'broadcast', keynam)
end
end
def delete(keynam, valnam=None)
tk_call('registry', 'delete', keynam, valnam)
end
def get(keynam, valnam)
tk_call('registry', 'get', keynam, valnam)
end
def keys(keynam, pattern=nil)
lst = tk_split_simplelist(tk_call('registry', 'keys', keynam))
if pattern
lst.find_all{|key| key =~ pattern}
else
lst
end
end
def set(keynam, valnam=None, data=None, dattype=None)
tk_call('registry', 'set', keynam, valnam, data, dattype)
end
def type(keynam, valnam)
tk_call('registry', 'type', keynam, valnam)
end
def values(keynam, pattern=nil)
lst = tk_split_simplelist(tk_call('registry', 'values', keynam))
if pattern
lst.find_all{|val| val =~ pattern}
else
lst
end
end
module_function :delete, :get, :keys, :set, :type, :values
end

247
ext/tk/lib/tk/wm.rb Normal file
View File

@ -0,0 +1,247 @@
#
# tk/wm.rb : methods for wm command
#
require 'tk'
module Tk
module Wm
include TkComm
TkCommandNames = ['wm'.freeze].freeze
def aspect(*args)
if args.length == 0
list(tk_call_without_enc('wm', 'aspect', path))
else
tk_call('wm', 'aspect', path, *args)
self
end
end
def attributes(slot=nil,value=None)
if slot == nil
lst = tk_split_list(tk_call('wm', 'attributes', path))
info = {}
while key = lst.shift
info[key[1..-1]] = lst.shift
end
info
elsif slot.kind_of? Hash
tk_call('wm', 'attributes', path, *hash_kv(slot))
self
elsif value == None
tk_call('wm', 'attributes', path, "-#{slot}")
else
tk_call('wm', 'attributes', path, "-#{slot}", value)
self
end
end
def client(name=None)
if name == None
tk_call('wm', 'client', path)
else
name = '' if name == nil
tk_call('wm', 'client', path, name)
self
end
end
def colormapwindows(*args)
if args.size == 0
list(tk_call_without_enc('wm', 'colormapwindows', path))
else
tk_call_without_enc('wm', 'colormapwindows', path, *args)
self
end
end
def wm_command(value=nil)
if value
tk_call('wm', 'command', path, value)
self
else
#procedure(tk_call('wm', 'command', path))
tk_call('wm', 'command', path)
end
end
def deiconify(ex = true)
tk_call_without_enc('wm', 'deiconify', path) if ex
self
end
def focusmodel(mode = nil)
if mode
tk_call_without_enc('wm', 'focusmodel', path, mode)
self
else
tk_call_without_enc('wm', 'focusmodel', path)
end
end
def frame
tk_call_without_enc('wm', 'frame', path)
end
def geometry(geom=nil)
if geom
tk_call_without_enc('wm', 'geometry', path, geom)
self
else
tk_call_without_enc('wm', 'geometry', path)
end
end
def wm_grid(*args)
if args.size == 0
list(tk_call_without_enc('wm', 'grid', path))
else
tk_call_without_enc('wm', 'grid', path, *args)
self
end
end
def group(leader = nil)
if leader
tk_call('wm', 'group', path, leader)
self
else
window(tk_call('wm', 'group', path))
end
end
def iconbitmap(bmp=nil)
if bmp
tk_call_without_enc('wm', 'iconbitmap', path, bmp)
self
else
image_obj(tk_call_without_enc('wm', 'iconbitmap', path))
end
end
def iconify(ex = true)
tk_call_without_enc('wm', 'iconify', path) if ex
self
end
def iconmask(bmp=nil)
if bmp
tk_call_without_enc('wm', 'iconmask', path, bmp)
self
else
image_obj(tk_call_without_enc('wm', 'iconmask', path))
end
end
def iconname(name=nil)
if name
tk_call('wm', 'iconname', path, name)
self
else
tk_call('wm', 'iconname', path)
end
end
def iconposition(*args)
if args.size == 0
list(tk_call_without_enc('wm', 'iconposition', path))
else
tk_call_without_enc('wm', 'iconposition', path, *args)
self
end
end
def iconwindow(win = nil)
if win
tk_call_without_enc('wm', 'iconwindow', path, win)
self
else
w = tk_call_without_enc('wm', 'iconwindow', path)
(w == '')? nil: window(w)
end
end
def maxsize(*args)
if args.size == 0
list(tk_call_without_enc('wm', 'maxsize', path))
else
tk_call_without_enc('wm', 'maxsize', path, *args)
self
end
end
def minsize(*args)
if args.size == 0
list(tk_call_without_enc('wm', 'minsize', path))
else
tk_call_without_enc('wm', 'minsize', path, *args)
self
end
end
def overrideredirect(bool=None)
if bool == None
bool(tk_call_without_enc('wm', 'overrideredirect', path))
else
tk_call_without_enc('wm', 'overrideredirect', path, bool)
self
end
end
def positionfrom(who=None)
if who == None
r = tk_call_without_enc('wm', 'positionfrom', path)
(r == "")? nil: r
else
tk_call_without_enc('wm', 'positionfrom', path, who)
self
end
end
def protocol(name=nil, cmd=nil)
if cmd
tk_call_without_enc('wm', 'protocol', path, name, cmd)
self
elsif name
result = tk_call_without_enc('wm', 'protocol', path, name)
(result == "")? nil : tk_tcl2ruby(result)
else
tk_split_simplelist(tk_call_without_enc('wm', 'protocol', path))
end
end
def resizable(*args)
if args.length == 0
list(tk_call_without_enc('wm', 'resizable', path)).collect{|e| bool(e)}
else
tk_call_without_enc('wm', 'resizable', path, *args)
self
end
end
def sizefrom(who=None)
if who == None
r = tk_call_without_enc('wm', 'sizefrom', path)
(r == "")? nil: r
else
tk_call_without_enc('wm', 'sizefrom', path, who)
self
end
end
def stackorder
list(tk_call('wm', 'stackorder', path))
end
def stackorder_isabove(win)
bool(tk_call('wm', 'stackorder', path, 'isabove', win))
end
def stackorder_isbelow(win)
bool(tk_call('wm', 'stackorder', path, 'isbelow', win))
end
def state(state=nil)
if state
tk_call_without_enc('wm', 'state', path, state)
self
else
tk_call_without_enc('wm', 'state', path)
end
end
def title(str=nil)
if str
tk_call('wm', 'title', path, str)
self
else
tk_call('wm', 'title', path)
end
end
def transient(master=nil)
if master
tk_call_without_enc('wm', 'transient', path, master)
self
else
window(tk_call_without_enc('wm', 'transient', path))
end
end
def withdraw(ex = true)
tk_call_without_enc('wm', 'withdraw', path) if ex
self
end
end
end

122
ext/tk/lib/tk/xim.rb Normal file
View File

@ -0,0 +1,122 @@
#
# tk/xim.rb : control imput_method
#
require 'tk'
module TkXIM
include Tk
extend Tk
TkCommandNames = ['imconfigure'.freeze].freeze
def TkXIM.useinputmethods(value = None, window = nil)
if value == None
if window
bool(tk_call_without_enc('tk', 'useinputmethods',
'-displayof', window))
else
bool(tk_call_without_enc('tk', 'useinputmethods'))
end
else
if window
bool(tk_call_without_enc('tk', 'useinputmethods',
'-displayof', window, value))
else
bool(tk_call_without_enc('tk', 'useinputmethods', value))
end
end
end
def TkXIM.useinputmethods_displayof(window, value = None)
TkXIM.useinputmethods(value, window)
end
def TkXIM.caret(window, keys=nil)
if keys
tk_call_without_enc('tk', 'caret', window, *hash_kv(keys))
self
else
lst = tk_split_list(tk_call_without_enc('tk', 'caret', window))
info = {}
while key = lst.shift
info[key[1..-1]] = lst.shift
end
info
end
end
def TkXIM.configure(window, slot, value=None)
begin
if /^8\.*/ === Tk::TK_VERSION && JAPANIZED_TK
if slot.kind_of? Hash
tk_call('imconfigure', window, *hash_kv(slot))
else
tk_call('imconfigure', window, "-#{slot}", value)
end
end
rescue
end
end
def TkXIM.configinfo(window, slot=nil)
if TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
begin
if /^8\.*/ === Tk::TK_VERSION && JAPANIZED_TK
if slot
conf = tk_split_list(tk_call('imconfigure', window, "-#{slot}"))
conf[0] = conf[0][1..-1]
conf
else
tk_split_list(tk_call('imconfigure', window)).collect{|conf|
conf[0] = conf[0][1..-1]
conf
}
end
else
[]
end
rescue
[]
end
else # ! TkComm::GET_CONFIGINFOwoRES_AS_ARRAY
TkXIM.current_configinfo(window, slot)
end
end
def TkXIM.current_configinfo(window, slot=nil)
begin
if /^8\.*/ === Tk::TK_VERSION && JAPANIZED_TK
if slot
conf = tk_split_list(tk_call('imconfigure', window, "-#{slot}"))
{ conf[0][1..-1] => conf[1] }
else
ret = {}
tk_split_list(tk_call('imconfigure', window)).each{|conf|
ret[conf[0][1..-1]] = conf[1]
}
ret
end
else
{}
end
rescue
{}
end
end
def useinputmethods(value=None)
TkXIM.useinputmethods(value, self)
end
def caret(keys=nil)
TkXIM.caret(self, keys=nil)
end
def imconfigure(slot, value=None)
TkXIM.configure(self, slot, value)
end
def imconfiginfo(slot=nil)
TkXIM.configinfo(self, slot)
end
end

View File

@ -1,414 +1,4 @@
#
# tkafter.rb : methods for Tcl/Tk after command
# tkafter.rb - load tk/after.rb
#
# $Id$
#
require 'tk'
class TkTimer
include TkCore
extend TkCore
TkCommandNames = ['after'.freeze].freeze
Tk_CBID = ['a'.freeze, '00000'.taint].freeze
Tk_CBTBL = {}.taint
TkCore::INTERP.add_tk_procs('rb_after', 'id', <<-'EOL')
if {[set st [catch {ruby [format "TkTimer.callback %%Q!%s!" $id]} ret]] != 0} {
return -code $st $ret
} {
return $ret
}
EOL
###############################
# class methods
###############################
def self.callback(obj_id)
@after_id = nil
ex_obj = Tk_CBTBL[obj_id]
return "" if ex_obj == nil; # canceled
ex_obj.cb_call
end
def self.info
tk_call('after', 'info').split(' ').collect!{|id|
ret = Tk_CBTBL.find{|key,val| val.after_id == id}
(ret == nil)? id: ret[1]
}
end
###############################
# instance methods
###############################
def do_callback
@in_callback = true
begin
@return_value = @current_proc.call(self)
rescue Exception => e
if @cancel_on_exception
cancel
@return_value = e
return e
else
fail e
end
end
if @set_next
set_next_callback(@current_args)
else
@set_next = true
end
@in_callback = false
@return_value
end
def set_callback(sleep, args=nil)
@after_script = "rb_after #{@id}"
@after_id = tk_call('after', sleep, @after_script)
@current_args = args
@current_script = [sleep, @after_script]
self
end
def set_next_callback(args)
if @running == false || @proc_max == 0 || @do_loop == 0
Tk_CBTBL.delete(@id) ;# for GC
@running = false
@wait_var.value = 0
return
end
if @current_pos >= @proc_max
if @do_loop < 0 || (@do_loop -= 1) > 0
@current_pos = 0
else
Tk_CBTBL.delete(@id) ;# for GC
@running = false
@wait_var.value = 0
return
end
end
@current_args = args
if @sleep_time.kind_of? Proc
sleep = @sleep_time.call(self)
else
sleep = @sleep_time
end
@current_sleep = sleep
cmd, *cmd_args = @loop_proc[@current_pos]
@current_pos += 1
@current_proc = cmd
set_callback(sleep, cmd_args)
end
def initialize(*args)
@id = Tk_CBID.join
Tk_CBID[1].succ!
@wait_var = TkVariable.new(0)
@cb_cmd = TkCore::INTERP.get_cb_entry(self.method(:do_callback))
@set_next = true
@init_sleep = 0
@init_proc = nil
@init_args = []
@current_script = []
@current_proc = nil
@current_args = nil
@return_value = nil
@sleep_time = 0
@current_sleep = 0
@loop_exec = 0
@do_loop = 0
@loop_proc = []
@proc_max = 0
@current_pos = 0
@after_id = nil
@after_script = nil
@cancel_on_exception = true
set_procs(*args) if args != []
@running = false
@in_callback = false
end
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
def cb_call
@cb_cmd.call
end
def get_procs
[@init_sleep, @init_proc, @init_args, @sleep_time, @loop_exec, @loop_proc]
end
def current_status
[@running, @current_sleep, @current_proc, @current_args,
@do_loop, @cancel_on_exception]
end
def cancel_on_exception?
@cancel_on_exception
end
def cancel_on_exception=(mode)
@cancel_on_exception = mode
self
end
def running?
@running
end
def loop_rest
@do_loop
end
def loop_rest=(rest)
@do_loop = rest
self
end
def set_procs(interval, loop_exec, *procs)
if !interval == 'idle' \
&& !interval.kind_of?(Integer) && !interval.kind_of?(Proc)
fail Kernel.format("%s need to be Integer or Proc", interval.inspect)
end
@sleep_time = interval
@loop_proc = []
procs.each{|e|
if e.kind_of? Proc
@loop_proc.push([e])
else
@loop_proc.push(e)
end
}
@proc_max = @loop_proc.size
@current_pos = 0
@do_loop = 0
if loop_exec
if loop_exec.kind_of?(Integer) && loop_exec < 0
@loop_exec = -1
elsif loop_exec == nil || loop_exec == false || loop_exec == 0
@loop_exec = 1
else
if not loop_exec.kind_of?(Integer)
fail Kernel.format("%s need to be Integer", loop_exec.inspect)
end
@loop_exec = loop_exec
end
@do_loop = @loop_exec
end
self
end
def add_procs(*procs)
procs.each{|e|
if e.kind_of? Proc
@loop_proc.push([e])
else
@loop_proc.push(e)
end
}
@proc_max = @loop_proc.size
self
end
def delete_procs(*procs)
procs.each{|e|
if e.kind_of? Proc
@loop_proc.delete([e])
else
@loop_proc.delete(e)
end
}
@proc_max = @loop_proc.size
cancel if @proc_max == 0
self
end
def delete_at(n)
@loop_proc.delete_at(n)
@proc_max = @loop_proc.size
cancel if @proc_max == 0
self
end
def set_start_proc(sleep, init_proc, *init_args)
if !sleep == 'idle' && !sleep.kind_of?(Integer)
fail Kernel.format("%s need to be Integer", sleep.inspect)
end
@init_sleep = sleep
@init_proc = init_proc
@init_args = init_args
self
end
def start(*init_args)
return nil if @running
Tk_CBTBL[@id] = self
@do_loop = @loop_exec
@current_pos = 0
argc = init_args.size
if argc > 0
sleep = init_args.shift
if !sleep == 'idle' && !sleep.kind_of?(Integer)
fail Kernel.format("%s need to be Integer", sleep.inspect)
end
@init_sleep = sleep
end
@init_proc = init_args.shift if argc > 1
@init_args = init_args if argc > 0
@current_sleep = @init_sleep
@running = true
if @init_proc
if not @init_proc.kind_of? Proc
fail Kernel.format("%s need to be Proc", @init_proc.inspect)
end
@current_proc = @init_proc
set_callback(@init_sleep, @init_args)
@set_next = false if @in_callback
else
set_next_callback(@init_args)
end
self
end
def reset(*reset_args)
restart() if @running
if @init_proc
@return_value = @init_proc.call(self)
else
@return_value = nil
end
@current_pos = 0
@current_args = @init_args
@set_next = false if @in_callback
self
end
def restart(*restart_args)
cancel if @running
if restart_args == []
start(@init_sleep, @init_proc, *@init_args)
else
start(*restart_args)
end
end
def cancel
@running = false
@wait_var.value = 0
tk_call 'after', 'cancel', @after_id if @after_id
@after_id = nil
Tk_CBTBL.delete(@id) ;# for GC
self
end
alias stop cancel
def continue(wait=nil)
fail RuntimeError, "is already running" if @running
sleep, cmd = @current_script
fail RuntimeError, "no procedure to continue" unless cmd
if wait
if not wait.kind_of? Integer
fail RuntimeError, Kernel.format("%s need to be Integer", wait.inspect)
end
sleep = wait
end
Tk_CBTBL[@id] = self
@running = true
@after_id = tk_call('after', sleep, cmd)
self
end
def skip
fail RuntimeError, "is not running now" unless @running
cancel
Tk_CBTBL[@id] = self
@running = true
set_next_callback(@current_args)
self
end
def info
if @after_id
inf = tk_split_list(tk_call('after', 'info', @after_id))
[Tk_CBTBL[inf[0][1]], inf[1]]
else
nil
end
end
def wait(on_thread = true, check_root = false)
if $SAFE >= 4
fail SecurityError, "can't wait timer at $SAFE >= 4"
end
unless @running
if @return_value.kind_of?(Exception)
fail @return_value
else
return @return_value
end
end
@wait_var.wait(on_thread, check_root)
if @return_value.kind_of?(Exception)
fail @return_value
else
@return_value
end
end
def eventloop_wait(check_root = false)
wait(false, check_root)
end
def thread_wait(check_root = false)
wait(true, check_root)
end
def tkwait(on_thread = true)
wait(on_thread, true)
end
def eventloop_tkwait
wait(false, true)
end
def thread_tkwait
wait(true, true)
end
end
TkAfter = TkTimer
require 'tk/timer'

View File

@ -1,29 +1,4 @@
#
# tkbgerror -- bgerror ( tkerror ) module
# 1998/07/16 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
# tkbgerror.rb - load tk/bgerror.rb
#
require 'tk'
module TkBgError
extend Tk
TkCommandNames = ['bgerror'.freeze].freeze
def bgerror(message)
tk_call 'bgerror', message
end
alias tkerror bgerror
alias show bgerror
module_function :bgerror, :tkerror, :show
def set_handler(hdlr = Proc.new) #==> handler :: proc{|msg| ...body... }
tk_call('proc', 'bgerror', 'msg', install_cmd(hdlr) + ' $msg')
end
def set_default
begin
tk_call('rename', 'bgerror', '')
rescue RuntimeError
end
end
module_function :set_handler, :set_default
end
require 'tk/bgerror'

File diff suppressed because it is too large Load Diff

View File

@ -1,28 +1,4 @@
#
# tkconsole.rb : control the console on system without a real console
# tkconsole.rb - load tk/console.rb
#
require 'tk'
module TkConsole
include Tk
extend Tk
TkCommandNames = ['console'.freeze].freeze
def self.title(str=None)
tk_call 'console', str
end
def self.hide
tk_call 'console', 'hide'
end
def self.show
tk_call 'console', 'show'
end
def self.eval(tcl_script)
#
# supports a Tcl script only
# I have no idea to support a Ruby script seamlessly.
#
tk_call 'console', 'eval', tcl_script
end
end
require 'tk/console'

View File

@ -1,276 +1,4 @@
require "tk"
class TkDialog2 < TkWindow
extend Tk
TkCommandNames = ['tk_dialog'.freeze].freeze
def self.show(*args)
dlog = self.new(*args)
dlog.show
dlog
end
def _set_button_config(configs)
set_config = proc{|c,i|
if $VERBOSE && (c.has_key?('command') || c.has_key?(:command))
STDERR.print("Warning: cannot give a command option " +
"to the dialog button#{i}. It was removed.\n")
end
c.delete('command'); c.delete(:command)
@config << Kernel.format("%s.button%s configure %s; ",
@path, i, hash_kv(c).join(' '))
}
case configs
when Proc
@buttons.each_index{|i|
if (c = configs.call(i)).kind_of? Hash
set_config.call(c,i)
end
}
when Array
@buttons.each_index{|i|
if (c = configs[i]).kind_of? Hash
set_config.call(c,i)
end
}
when Hash
@buttons.each_with_index{|s,i|
if (c = configs[s]).kind_of? Hash
set_config.call(c,i)
end
}
end
@config = 'after idle {' + @config + '};' if @config != ""
end
private :_set_button_config
# initialize tk_dialog
def create_self(keys)
@var = TkVariable.new
@title = title
@message = message
@message_config = message_config
@msgframe_config = msgframe_config
@bitmap = bitmap
@bitmap_config = message_config
@default_button = default_button
@buttons = buttons
@button_configs = proc{|num| button_configs(num)}
@btnframe_config = btnframe_config
#@config = "puts [winfo children .w0000];"
@config = ""
@command = nil
if keys.kind_of? Hash
@title = keys['title'] if keys.key? 'title'
@message = keys['message'] if keys.key? 'message'
@bitmap = keys['bitmap'] if keys.key? 'bitmap'
@bitmap = '{}' if @bitmap == nil || @bitmap == ""
@default_button = keys['default'] if keys.key? 'default'
@buttons = keys['buttons'] if keys.key? 'buttons'
@command = keys['prev_command']
@message_config = keys['message_config'] if keys.key? 'message_config'
@msgframe_config = keys['msgframe_config'] if keys.key? 'msgframe_config'
@bitmap_config = keys['bitmap_config'] if keys.key? 'bitmap_config'
@button_configs = keys['button_configs'] if keys.key? 'button_configs'
@btnframe_config = keys['btnframe_config'] if keys.key? 'btnframe_config'
end
if @title.include? ?\s
@title = '{' + @title + '}'
end
if @buttons.kind_of? Array
_set_button_config(@buttons.collect{|cfg|
(cfg.kind_of? Array)? cfg[1]: nil})
@buttons = @buttons.collect{|cfg| (cfg.kind_of? Array)? cfg[0]: cfg}
end
if @buttons.kind_of? Hash
_set_button_config(@buttons)
@buttons = @buttons.keys
end
@buttons = tk_split_simplelist(@buttons) if @buttons.kind_of? String
@buttons = @buttons.collect{|s|
if s.kind_of? Array
s = s.join(' ')
end
if s.include? ?\s
'{' + s + '}'
else
s
end
}
if @message_config.kind_of? Hash
@config << Kernel.format("%s.msg configure %s;",
@path, hash_kv(@message_config).join(' '))
end
if @msgframe_config.kind_of? Hash
@config << Kernel.format("%s.top configure %s;",
@path, hash_kv(@msgframe_config).join(' '))
end
if @btnframe_config.kind_of? Hash
@config << Kernel.format("%s.bot configure %s;",
@path, hash_kv(@btnframe_config).join(' '))
end
if @bitmap_config.kind_of? Hash
@config << Kernel.format("%s.bitmap configure %s;",
@path, hash_kv(@bitmap_config).join(' '))
end
_set_button_config(@button_configs) if @button_configs
if @command.kind_of? Proc
@command.call(self)
end
end
private :create_self
def show
if @default_button.kind_of? String
default_button = @buttons.index(@default_button)
else
default_button = @default_button
end
default_button = '{}' if default_button == nil
Tk.ip_eval('eval {global '+@var.id+';'+@config+
'set '+@var.id+' [tk_dialog '+
@path+" "+@title+" {#{@message}} "+@bitmap+" "+
String(default_button)+" "+@buttons.join(' ')+']}')
end
def value
return @var.value.to_i
end
######################################################
# #
# these methods must be overridden for each dialog #
# #
######################################################
private
def title
# returns a title string of the dialog window
return "DIALOG"
end
def message
# returns a message text to display on the dialog
return "MESSAGE"
end
def message_config
# returns a Hash {option=>value, ...} for the message text
return nil
end
def msgframe_config
# returns a Hash {option=>value, ...} for the message text frame
return nil
end
def bitmap
# returns a bitmap name or a bitmap file path
# (@ + path ; e.g. '@/usr/share/bitmap/sample.xbm')
return "info"
end
def bitmap_config
# returns nil or a Hash {option=>value, ...} for the bitmap
return nil
end
def default_button
# returns a default button's number or name
# if nil or null string, set no-default
return 0
end
def buttons
#return "BUTTON1 BUTTON2"
return ["BUTTON1", "BUTTON2"]
end
def button_configs(num)
# returns nil / Proc / Array or Hash (see _set_button_config)
return nil
end
def btnframe_config
# returns nil or a Hash {option=>value, ...} for the button frame
return nil
end
end
#
# TkDialog : with showing at initialize
# tkdialog.rb - load tk/dialog.rb
#
class TkDialog < TkDialog2
def self.show(*args)
self.new(*args)
end
def initialize(*args)
super(*args)
show
end
end
#
# dialog for warning
#
class TkWarning2 < TkDialog2
def initialize(parent = nil, mes = nil)
if !mes
if parent.kind_of? TkWindow
mes = ""
else
mes = parent.to_s
parent = nil
end
end
super(parent, :message=>mes)
end
def show(mes = nil)
mes_bup = @message
@message = mes if mes
ret = super()
@message = mes_bup
ret
end
#######
private
def title
return "WARNING";
end
def bitmap
return "warning";
end
def default_button
return 0;
end
def buttons
return "OK";
end
end
class TkWarning < TkWarning2
def self.show(*args)
self.new(*args)
end
def initialize(*args)
super(*args)
show
end
end
require 'tk/dialog'

View File

@ -1,292 +1,4 @@
#
# tkentry.rb - Tk entry classes
# $Date$
# by Yukihiro Matsumoto <matz@caelum.co.jp>
require 'tk.rb'
class TkEntry<TkLabel
include Scrollable
TkCommandNames = ['entry'.freeze].freeze
WidgetClassName = 'Entry'.freeze
WidgetClassNames[WidgetClassName] = self
class ValidateCmd
include TkComm
module Action
Insert = 1
Delete = 0
Others = -1
Focus = -1
Forced = -1
Textvariable = -1
TextVariable = -1
end
class ValidateArgs
VARG_KEY = 'disvPSVW'
VARG_TYPE = 'nxeseesw'
def self.scan_args(arg_str, arg_val)
enc = Tk.encoding
arg_cnv = []
arg_str.strip.split(/\s+/).each_with_index{|kwd,idx|
if kwd =~ /^%(.)$/
if num = VARG_KEY.index($1)
case VARG_TYPE[num]
when ?n
arg_cnv << TkComm::number(arg_val[idx])
when ?s
arg_cnv << TkComm::string(arg_val[idx])
when ?e
if enc
arg_cnv << Tk.fromUTF8(TkComm::string(arg_val[idx]), enc)
else
arg_cnv << TkComm::string(arg_val[idx])
end
when ?w
arg_cnv << TkComm::window(arg_val[idx])
when ?x
idx = TkComm::number(arg_val[idx])
if idx < 0
arg_cnv << nil
else
arg_cnv << idx
end
else
arg_cnv << arg_val[idx]
end
else
arg_cnv << arg_val[idx]
end
else
arg_cnv << arg_val[idx]
end
}
arg_cnv
end
def initialize(d,i,s,v,pp,ss,vv,ww)
@action = d
@index = i
@current = s
@type = v
@value = pp
@string = ss
@triggered = vv
@widget = ww
end
attr :action
attr :index
attr :current
attr :type
attr :value
attr :string
attr :triggered
attr :widget
end
def initialize(cmd = Proc.new, args=nil)
if args
@id =
install_cmd(proc{|*arg|
TkUtil.eval_cmd(proc{|*v| (cmd.call(*v))? '1': '0'},
*ValidateArgs.scan_args(args, arg))
}) + " " + args
else
args = ' %d %i %s %v %P %S %V %W'
@id =
install_cmd(proc{|*arg|
TkUtil.eval_cmd(proc{|*v| (cmd.call(*v))? '1': '0'},
ValidateArgs.new(*ValidateArgs \
.scan_args(args,arg)))
}) + args
end
end
def to_eval
@id
end
end
def create_self(keys)
tk_call 'entry', @path
if keys and keys != None
configure(keys)
end
end
private :create_self
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(' '))
elsif slot['vcmd'].kind_of? Proc
slot['vcmd'] = ValidateCmd.new(slot['vcmd'])
end
if slot['validatecommand'].kind_of? Array
cmd, *args = slot['validatecommand']
slot['validatecommand'] = ValidateCmd.new(cmd, args.join(' '))
elsif slot['validatecommand'].kind_of? Proc
slot['validatecommand'] = ValidateCmd.new(slot['validatecommand'])
end
if slot['invcmd'].kind_of? Array
cmd, *args = slot['invcmd']
slot['invcmd'] = ValidateCmd.new(cmd, args.join(' '))
elsif slot['invcmd'].kind_of? Proc
slot['invcmd'] = ValidateCmd.new(slot['invcmd'])
end
if slot['invalidcommand'].kind_of? Array
cmd, *args = slot['invalidcommand']
slot['invalidcommand'] = ValidateCmd.new(cmd, args.join(' '))
elsif slot['invalidcommand'].kind_of? Proc
slot['invalidcommand'] = ValidateCmd.new(slot['invalidcommand'])
end
super(slot)
else
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(' '))
elsif value.kind_of? Proc
value = ValidateCmd.new(value)
end
end
super(slot, value)
end
self
end
def bbox(index)
list(tk_send('bbox', index))
end
def cursor
number(tk_send('index', 'insert'))
end
def cursor=(index)
tk_send 'icursor', index
self
end
def index(index)
number(tk_send('index', index))
end
def insert(pos,text)
tk_send 'insert', pos, text
self
end
def delete(first, last=None)
tk_send 'delete', first, last
self
end
def mark(pos)
tk_send 'scan', 'mark', pos
self
end
def dragto(pos)
tk_send 'scan', 'dragto', pos
self
end
def selection_adjust(index)
tk_send 'selection', 'adjust', index
self
end
def selection_clear
tk_send 'selection', 'clear'
self
end
def selection_from(index)
tk_send 'selection', 'from', index
self
end
def selection_present()
bool(tk_send('selection', 'present'))
end
def selection_range(s, e)
tk_send 'selection', 'range', s, e
self
end
def selection_to(index)
tk_send 'selection', 'to', index
self
end
def invoke_validate
bool(tk_send('validate'))
end
def validate(mode = nil)
if mode
configure 'validate', mode
else
invoke_validate
end
end
def validatecommand(cmd = Proc.new, args = nil)
if cmd.kind_of?(ValidateCmd)
configure('validatecommand', cmd)
elsif args
configure('validatecommand', [cmd, args])
else
configure('validatecommand', cmd)
end
end
alias vcmd validatecommand
def invalidcommand(cmd = Proc.new, args = nil)
if cmd.kind_of?(ValidateCmd)
configure('invalidcommand', cmd)
elsif args
configure('invalidcommand', [cmd, args])
else
configure('invalidcommand', cmd)
end
end
alias invcmd invalidcommand
def value
tk_send 'get'
end
def value= (val)
tk_send 'delete', 0, 'end'
tk_send 'insert', 0, val
end
end
class TkSpinbox<TkEntry
TkCommandNames = ['spinbox'.freeze].freeze
WidgetClassName = 'Spinbox'.freeze
WidgetClassNames[WidgetClassName] = self
def create_self(keys)
tk_call 'spinbox', @path
if keys and keys != None
configure(keys)
end
end
private :create_self
def identify(x, y)
tk_send 'identify', x, y
end
def spinup
tk_send 'invoke', 'spinup'
self
end
def spindown
tk_send 'invoke', 'spindown'
self
end
def set(str)
tk_send 'set', str
end
end
# tkentry.rb - load tk/entry.rb
#
require 'tk/entry'

File diff suppressed because it is too large Load Diff

View File

@ -1,56 +1,4 @@
#
# tkmacpkg.rb : methods for Tcl/Tk packages for Macintosh
# 2000/11/22 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
# tkmacpkg.rb - load tk/macpkg.rb
#
# ATTENTION !!
# This is NOT TESTED. Because I have no test-environment.
#
#
require 'tk'
module TkMacResource
extend Tk
extend TkMacResource
TkCommandNames = ['resource'.freeze].freeze
tk_call('package', 'require', 'resource')
def close(rsrcRef)
tk_call('resource', 'close', rsrcRef)
end
def delete(rsrcType, opts=nil)
tk_call('resource', 'delete', *(hash_kv(opts) + rsrcType))
end
def files(rsrcRef=nil)
if rsrcRef
tk_call('resource', 'files', rsrcRef)
else
tk_split_simplelist(tk_call('resource', 'files'))
end
end
def list(rsrcType, rsrcRef=nil)
tk_split_simplelist(tk_call('resource', 'list', rsrcType, rsrcRef))
end
def open(fname, access=nil)
tk_call('resource', 'open', fname, access)
end
def read(rsrcType, rsrcID, rsrcRef=nil)
tk_call('resource', 'read', rsrcType, rsrcID, rsrcRef)
end
def types(rsrcRef=nil)
tk_split_simplelist(tk_call('resource', 'types', rsrcRef))
end
def write(rsrcType, data, opts=nil)
tk_call('resource', 'write', *(hash_kv(opts) + rsrcType + data))
end
module_function :close, :delete, :files, :list, :open, :read, :types, :write
end
require 'tk/macpkg'

View File

@ -1,143 +1,4 @@
#
# tkmenubar.rb
# tkmenubar.rb - load tk/menubar.rb
#
# Copyright (C) 1998 maeda shugo. All rights reserved.
# This file can be distributed under the terms of the Ruby.
# Usage:
#
# menu_spec = [
# [['File', 0],
# ['Open', proc{puts('Open clicked')}, 0],
# '---',
# ['Quit', proc{exit}, 0]],
# [['Edit', 0],
# ['Cut', proc{puts('Cut clicked')}, 2],
# ['Copy', proc{puts('Copy clicked')}, 0],
# ['Paste', proc{puts('Paste clicked')}, 0]]
# ]
# menubar = TkMenubar.new(nil, menu_spec,
# 'tearoff'=>false,
# 'foreground'=>'grey40',
# 'activeforeground'=>'red',
# 'font'=>'-adobe-helvetica-bold-r-*--12-*-iso8859-1')
# menubar.pack('side'=>'top', 'fill'=>'x')
#
#
# OR
#
#
# menubar = TkMenubar.new
# menubar.add_menu([['File', 0],
# ['Open', proc{puts('Open clicked')}, 0],
# '---',
# ['Quit', proc{exit}, 0]])
# menubar.add_menu([['Edit', 0],
# ['Cut', proc{puts('Cut clicked')}, 2],
# ['Copy', proc{puts('Copy clicked')}, 0],
# ['Paste', proc{puts('Paste clicked')}, 0]])
# menubar.configure('tearoff', false)
# menubar.configure('foreground', 'grey40')
# menubar.configure('activeforeground', 'red')
# menubar.configure('font', '-adobe-helvetica-bold-r-*--12-*-iso8859-1')
# menubar.pack('side'=>'top', 'fill'=>'x')
# The format of the menu_spec is:
# [
# [
# [button text, underline, accelerator],
# [menu label, command, underline, accelerator],
# '---', # separator
# ...
# ],
# ...
# ]
# underline and accelerator are optional parameters.
# Hashes are OK instead of Arrays.
# To use add_menu, configuration must be done by calling configure after
# adding all menus by add_menu, not by the constructor arguments.
require "tk"
class TkMenubar<TkFrame
include TkComposite
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)
end
@menus = []
if spec
for menu_info in spec
add_menu(menu_info)
end
end
if options
for key, value in options
configure(key, value)
end
end
end
def add_menu(menu_info)
btn_info = menu_info.shift
mbtn = TkMenubutton.new(@frame)
if btn_info.kind_of?(Hash)
for key, value in btn_info
mbtn.configure(key, value)
end
elsif btn_info.kind_of?(Array)
mbtn.configure('text', btn_info[0]) if btn_info[0]
mbtn.configure('underline', btn_info[1]) if btn_info[1]
mbtn.configure('accelerator', btn_info[2]) if btn_info[2]
else
mbtn.configure('text', btn_info)
end
menu = TkMenu.new(mbtn)
for item_info in menu_info
if item_info.kind_of?(Hash)
menu.add('command', item_info)
elsif item_info.kind_of?(Array)
options = {}
options['label'] = item_info[0] if item_info[0]
options['command'] = item_info[1] if item_info[1]
options['underline'] = item_info[2] if item_info[2]
options['accelerator'] = item_info[3] if item_info[3]
menu.add('command', options)
elsif /^-+$/ =~ item_info
menu.add('sep')
else
menu.add('command', 'label' => item_info)
end
end
mbtn.menu(menu)
@menus.push([mbtn, menu])
delegate('tearoff', menu)
delegate('foreground', mbtn, menu)
delegate('background', mbtn, menu)
delegate('disabledforeground', mbtn, menu)
delegate('activeforeground', mbtn, menu)
delegate('activebackground', mbtn, menu)
delegate('font', mbtn, menu)
delegate('kanjifont', mbtn, menu)
mbtn.pack('side' => 'left')
end
def [](index)
return @menus[index]
end
end
require 'tk/menubar'

View File

@ -1,33 +1,4 @@
#
# tkmngfocus.rb : methods for Tcl/Tk standard library 'focus.tcl'
# by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
# tkmngfocus.rb - load tk/mngfocus.rb
#
require 'tk'
module TkManageFocus
extend Tk
TkCommandNames = [
'tk_focusFollowMouse'.freeze,
'tk_focusNext'.freeze,
'tk_focusPrev'.freeze
].freeze
def TkManageFocus.followsMouse
tk_call 'tk_focusFollowsMouse'
end
def TkManageFocus.next(window)
tk_tcl2ruby(tk_call('tk_focusNext', window))
end
def focusNext
TkManageFocus.next(self)
end
def TkManageFocus.prev(window)
tk_tcl2ruby(tk_call('tk_focusPrev', window))
end
def focusPrev
TkManageFocus.prev(self)
end
end
require 'tk/mngfocus'

View File

@ -1,54 +1,4 @@
#
# tkpalette.rb : methods for Tcl/Tk standard library 'palette.tcl'
# 1998/06/21 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
# tkpalette.rb - load tk/palette.rb
#
require 'tk'
module TkPalette
include Tk
extend Tk
TkCommandNames = [
'tk_setPalette'.freeze,
'tk_bisque'.freeze,
'tkDarken'.freeze
].freeze
def TkPalette.set(*args)
args = args.to_a.flatten if args.kind_of? Hash
tk_call 'tk_setPalette', *args
end
def TkPalette.setPalette(*args)
TkPalette.set(*args)
end
def TkPalette.bisque
tk_call 'tk_bisque'
end
def TkPalette.darken(color, percent)
tk_call 'tkDarken', color, percent
end
def TkPalette.recolorTree(window, colors)
if not colors.kind_of?(Hash)
fail "2nd arg need to be Hash"
end
colors.each{|key, value|
begin
if window.cget(key) == tk_call('set', "tkPalette(#{key})")
window[key] = colors[key]
end
rescue
# ignore
end
}
TkWinfo.children(window).each{|w| TkPalette.recolorTree(w, colors)}
end
def recolorTree(colors)
TkPalette.recolorTree(self, colors)
end
end
require 'tk/palette'

View File

@ -1,30 +1,4 @@
#
# tkscrollbox.rb - Tk Listbox with Scrollbar
# as an example of Composite Widget
# $Date$
# by Yukihiro Matsumoto <matz@netlab.co.jp>
require 'tk.rb'
class TkScrollbox<TkListbox
include TkComposite
def initialize_composite(keys=nil)
list = TkListbox.new(@frame)
scroll = TkScrollbar.new(@frame)
@path = list.path
list.configure 'yscroll', scroll.path+" set"
list.pack 'side'=>'left','fill'=>'both','expand'=>'yes'
scroll.configure 'command', list.path+" yview"
scroll.pack 'side'=>'right','fill'=>'y'
delegate('DEFAULT', list)
delegate('foreground', list)
delegate('background', list, scroll)
delegate('borderwidth', @frame)
delegate('relief', @frame)
configure keys if keys
end
private :initialize_composite
end
# tkscrollbox.rb - load tk/scrollbox.rb
#
require 'tk/scrollbox'

File diff suppressed because it is too large Load Diff

View File

@ -1,85 +1,4 @@
#
# tkvirtevent.rb : treats virtual events
# 1998/07/16 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
# tkvirtevent.rb - load tk/virtevent.rb
#
require 'tk'
class TkVirtualEvent<TkObject
extend Tk
TkCommandNames = ['event'.freeze].freeze
TkVirtualEventID = ["<VirtEvent".freeze, "00000".taint, ">".freeze].freeze
TkVirtualEventTBL = TkCore::INTERP.create_table
TkCore::INTERP.init_ip_env{ TkVirtualEventTBL.clear }
class PreDefVirtEvent<self
def initialize(event)
@path = @id = event
TkVirtualEvent::TkVirtualEventTBL[@id] = self
end
end
def TkVirtualEvent.getobj(event)
obj = TkVirtualEventTBL[event]
if obj
obj
else
if tk_call('event', 'info').index("<#{event}>")
PreDefVirtEvent.new(event)
else
fail ArgumentError, "undefined virtual event '<#{event}>'"
end
end
end
def TkVirtualEvent.info
tk_call('event', 'info').split(/\s+/).collect!{|seq|
TkVirtualEvent.getobj(seq[1..-2])
}
end
def initialize(*sequences)
@path = @id = TkVirtualEventID.join
TkVirtualEventID[1].succ!
add(*sequences)
end
def add(*sequences)
if sequences != []
tk_call('event', 'add', "<#{@id}>",
*(sequences.collect{|seq| "<#{tk_event_sequence(seq)}>"}) )
TkVirtualEventTBL[@id] = self
end
self
end
def delete(*sequences)
if sequences == []
tk_call('event', 'delete', "<#{@id}>")
TkVirtualEventTBL.delete(@id)
else
tk_call('event', 'delete', "<#{@id}>",
*(sequences.collect{|seq| "<#{tk_event_sequence(seq)}>"}) )
TkVirtualEventTBL.delete(@id) if info == []
end
self
end
def info
tk_call('event', 'info', "<#{@id}>").split(/\s+/).collect!{|seq|
l = seq.scan(/<*[^<>]+>*/).collect!{|subseq|
case (subseq)
when /^<<[^<>]+>>$/
TkVirtualEvent.getobj(subseq[1..-2])
when /^<[^<>]+>$/
subseq[1..-2]
else
subseq.split('')
end
}.flatten
(l.size == 1) ? l[0] : l
}
end
end
require 'tk/virtevent'

View File

@ -1,84 +1,4 @@
#
# tkwinpkg.rb : methods for Tcl/Tk packages for Microsoft Windows
# 2000/11/22 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
# tkwinpkg.rb - load tk/winpkg.rb
#
# ATTENTION !!
# This is NOT TESTED. Because I have no test-environment.
#
#
require 'tk'
module TkWinDDE
extend Tk
extend TkWinDDE
TkCommandNames = ['dde'.freeze].freeze
tk_call('package', 'require', 'dde')
def servername(topic=nil)
tk_call('dde', 'servername', topic)
end
def execute(service, topic, data)
tk_call('dde', 'execute', service, topic, data)
end
def async_execute(service, topic, data)
tk_call('dde', '-async', 'execute', service, topic, data)
end
def poke(service, topic, item, data)
tk_call('dde', 'poke', service, topic, item, data)
end
def request(service, topic, item)
tk_call('dde', 'request', service, topic, item)
end
def services(service, topic)
tk_call('dde', 'services', service, topic)
end
def eval(topic, cmd, *args)
tk_call('dde', 'eval', topic, cmd, *args)
end
module_function :servername, :execute, :async_execute,
:poke, :request, :services, :eval
end
module TkWinRegistry
extend Tk
extend TkWinRegistry
TkCommandNames = ['registry'.freeze].freeze
tk_call('package', 'require', 'registry')
def delete(keynam, valnam=nil)
tk_call('registry', 'delete', keynam, valnam)
end
def get(keynam, valnam)
tk_call('registry', 'get', keynam, valnam)
end
def keys(keynam)
tk_split_simplelist(tk_call('registry', 'keys', keynam))
end
def set(keynam, valnam=nil, data=nil, dattype=nil)
tk_call('registry', 'set', keynam, valnam, data, dattype)
end
def type(keynam, valnam)
tk_call('registry', 'type', keynam, valnam)
end
def values(keynam)
tk_split_simplelist(tk_call('registry', 'values', keynam))
end
module_function :delete, :get, :keys, :set, :type, :values
end
require 'tk/winpkg'

View File

@ -0,0 +1,87 @@
#!/usr/bin/env ruby
require 'tk'
class Button_clone < TkLabel
def initialize(*args)
@command = nil
if args[-1].kind_of?(Hash)
keys = _symbolkey2str(args.pop)
@command = keys.delete('command')
keys['highlightthickness'] = 1 unless keys.key?('highlightthickness')
keys['padx'] = '3m' unless keys.key?('padx')
keys['pady'] = '1m' unless keys.key?('pady')
keys['relief'] = 'raised' unless keys.key?('relief')
args.push(keys)
end
super(*args)
@press = false
self.bind('Enter', proc{self.background(self.activebackground)})
self.bind('Leave', proc{
@press = false
self.background(self.highlightbackground)
self.relief('raised')
})
self.bind('ButtonPress-1', proc{@press = true; self.relief('sunken')})
self.bind('ButtonRelease-1', proc{
self.relief('raised')
@command.call if @press && @command
@press = false
})
end
def command(cmd = Proc.new)
@command = cmd
end
def invoke
if @command
@command.call
else
''
end
end
end
TkLabel.new(:text=><<EOT).pack
This is a sample of 'event binding'.
The first button is a normal button widget.
And the second one is a normal label widget
but with some bindings like a button widget.
EOT
lbl = TkLabel.new(:foreground=>'red').pack(:pady=>3)
v = TkVariable.new(0)
TkFrame.new{|f|
TkLabel.new(f, :text=>'click count : ').pack(:side=>:left)
TkLabel.new(f, :textvariable=>v).pack(:side=>:left)
}.pack
TkButton.new(:text=>'normal Button widget',
:command=>proc{
puts 'button is clicked!!'
lbl.text 'button is clicked!!'
v.numeric += 1
}){
pack(:fill=>:x, :expand=>true)
}
Button_clone.new(:text=>'Label with Button binding',
:command=>proc{
puts 'label is clicked!!'
lbl.text 'label is clicked!!'
v.numeric += 1
}){
pack(:fill=>:x, :expand=>true)
}
Tk.mainloop

View File

@ -0,0 +1,127 @@
#!/usr/bin/env ruby
require 'tk'
TkLabel.new(:text=><<EOT, :justify=>:left).pack
This is a sample of bindtags and usage of
Tk.callback_break/Tk.callback_continue.
Please check the work of following buttons
(attend the difference between before/after
pressing the bottom button), and see the
source code.
EOT
def set_class_bind
TkButton.bind('ButtonPress-1',
proc{puts 'bind "ButtonPress-1" of TkButton class'})
TkButton.bind('ButtonRelease-1',
proc{puts 'bind "ButtonRelease-1" of TkButton class'})
end
# set root binding
r = TkRoot.new
r.bind('ButtonPress-1', proc{puts 'bind "ButtonPress-1" of root widget'})
r.bind('ButtonRelease-1', proc{puts 'bind "ButtonRelease-1" of root widget'})
# set 'all' binding
TkBindTag::ALL.bind('ButtonPress-1',
proc{puts 'bind "ButtonPress-1" of the tag "all"'})
TkBindTag::ALL.bind('ButtonRelease-1',
proc{puts 'bind "ButtonRelease-1" of the tag "all"'})
# create buttons
b1 = TkButton.new(:text=>'button-1',
:command=>proc{puts "command of button-1"}).pack
b2 = TkButton.new(:text=>'button-2',
:command=>proc{puts "command of button-2"}).pack
b3 = TkButton.new(:text=>'button-3',
:command=>proc{puts "command of button-3"}).pack
b4 = TkButton.new(:text=>'button-4',
:command=>proc{puts "command of button-4"}).pack
b5 = TkButton.new(:text=>'button-5',
:command=>proc{puts "command of button-5"}).pack
# set button binding
b1.bind('ButtonPress-1', proc{puts 'bind "ButtonPress-1" of button-1'})
b1.bind('ButtonRelease-1', proc{puts 'bind "ButtonRelease-1" of button-1'})
b2.bind('ButtonPress-1', proc{puts 'bind "ButtonPress-1" of button-2'})
b2.bind('ButtonRelease-1', proc{puts 'bind "ButtonRelease-1" of button-2'})
b3.bind('ButtonPress-1', proc{puts 'bind "ButtonPress-1" of button-3'})
b3.bind('ButtonRelease-1', proc{puts 'bind "ButtonRelease-1" of button-3'})
b4.bind('ButtonPress-1', proc{puts 'bind "ButtonPress-1" of button-4'})
b4.bind('ButtonRelease-1', proc{puts 'bind "ButtonRelease-1" of button-4'})
b5.bind('ButtonPress-1', proc{puts 'bind "ButtonPress-1" of button-5'})
b5.bind('ButtonRelease-1', proc{puts 'bind "ButtonRelease-1" of button-5'})
# create bindtag and set binding
tag1 = TkBindTag.new
tag1.bind('ButtonPress-1', proc{puts 'bind "ButtonPress-1" of tag1'})
tag1.bind('ButtonRelease-1', proc{puts 'bind "ButtonRelease-1" of tag1'})
tag2 = TkBindTag.new
tag2.bind('ButtonPress-1',
proc{
puts 'bind "ButtonPress-1" of tag2'
puts 'call Tk.callback_continue'
Tk.callback_continue
puts 'never see this message'
})
tag2.bind('ButtonRelease-1',
proc{
puts 'bind "ButtonRelease-1" of tag2'
puts 'call Tk.callback_continue'
Tk.callback_continue
puts 'never see this message'
})
tag3 = TkBindTag.new
tag3.bind('ButtonPress-1',
proc{
puts 'bind "ButtonPress-1" of tag3'
puts 'call Tk.callback_break'
Tk.callback_break
puts 'never see this message'
})
tag3.bind('ButtonRelease-1',
proc{
puts 'bind "ButtonRelease-1" of tag3'
puts 'call Tk.callback_break'
Tk.callback_break
puts 'never see this message'
})
# set bindtags
p b1.bindtags
tags = b2.bindtags
tags[2,0] = tag1
tags[0,0] = tag1
b2.bindtags(tags)
p b2.bindtags
tags = b3.bindtags
tags[2,0] = tag2
tags[0,0] = tag2
b3.bindtags(tags)
p b3.bindtags
tags = b4.bindtags
tags[2,0] = tag3
tags[0,0] = tag3
b4.bindtags(tags)
p b4.bindtags
b5.bindtags([tag1, TkButton, tag2, b5])
# create button to set button class binding
TkButton.new(:text=>'set binding to TkButton class',
:command=>proc{
puts 'call "set_class_bind"'
set_class_bind
}).pack(:pady=>7)
# start event-loop
Tk.mainloop

View File

@ -0,0 +1,39 @@
#!/usr/bin/env ruby
require "tk"
TkMessage.new(:width=>360, :text=><<EOM).pack
This sample shows how to use a binary sequence between Ruby and Tk. \
This reads the image data from the file as the binary sequence.
To treat the difference of encodings between on Ruby and on Tk seamlessly, \
Ruby/Tk converts the encoding of string arguments automatically. \
I think it is comfortable for users on almost all situations. \
However, when treats a binary sequence, the convert process makes troubles.
Tk::BinaryString class (subclass of Tk::EncodedString class) is the class \
to avoid such troubles. Please see the source code of this sample. \
A Tk::BinaryString instance is used to create the image for the center button.
EOM
ImgFile=['images','tcllogo.gif'].join(File::Separator)
ph1 = TkPhotoImage.new(:file=>ImgFile)
p ph1.configinfo
b_str = Tk::BinaryString(IO.read(ImgFile))
p [b_str, b_str.encoding]
ph2 = TkPhotoImage.new(:data=>b_str)
p ph2.configinfo
p ph2.data(:grayscale=>true)
ph3 = TkPhotoImage.new()
ph3.put(ph2.data(:grayscale=>true))
f = TkFrame.new.pack
TkButton.new(:parent=>f, :image=>ph1, :command=>proc{exit}).pack(:side=>:left)
TkButton.new(:parent=>f, :image=>ph2, :command=>proc{exit}).pack(:side=>:left)
TkButton.new(:parent=>f, :image=>ph3, :command=>proc{exit}).pack(:side=>:left)
Tk.mainloop

View File

@ -0,0 +1,20 @@
require 'tk'
class Button_with_Frame < TkButton
def create_self(keys)
@frame = TkFrame.new('widgetname'=>@path, 'background'=>'yellow')
install_win(@path) # create new @path which is a daughter of old @path
super(keys)
TkPack(@path, :padx=>7, :pady=>7)
@epath = @frame.path
end
def epath
@epath
end
end
Button_with_Frame.new(:text=>'QUIT', :command=>proc{exit}) {
pack(:padx=>15, :pady=>5)
}
Tk.mainloop

View File

@ -0,0 +1,18 @@
There are Ruby/Tk demo scripts.
Files with '.rb' extension are sub-scripts which are launched 'widget'
script. Those files don't work independently. Please call them from
'widget' script.
If you want start some sub-scripts at same time when the launcher
script tarts, please give the sub-script names as arguments.
(e.g. /usr/local/bin/ruby widget button.rb entry1.rb text.rb )
You can ommit '.rb' of the sub-scripts
(e.g. /usr/local/bin/ruby widget button entry1 text )
If you don't need launcher's main window, give -n option.
(e.g. /usr/local/bin/ruby widget -n button.rb entry1.rb text.rb )
Others (browse1, hello, and so on) are standalone scripts.
2004/04/14 Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)

View File

@ -1,3 +1,8 @@
This is a original document of 'tkencoding.rb'.
The library 'tkencoding.rb' is obsolete.
Functions of tkencoding.rb is already included into Ruby/Tk.
-------------------------------------------------
tkencoding.rbを用いた日本語の表示について
Copyright (C) 1999/07, Takaaki Tateishi <ttate@jaist.ac.jp>

View File

@ -150,7 +150,7 @@ if TkWinfo.depth($arrow_canvas) > 1
$demo_arrowInfo.activeStyle = {'fill'=>'red', 'outline'=>'black', 'width'=>1}
else
$demo_arrowInfo.bigLineStyle = {'fill'=>'black',
'stipple'=>'@'+[$demo_dir, 'images', 'grey.25'].join(File::Separator)}
'stipple'=>'@'+[$demo_dir,'..','images','grey.25'].join(File::Separator)}
$demo_arrowInfo.boxStyle = {'fill'=>'', 'outline'=>'black', 'width'=>1}
$demo_arrowInfo.activeStyle = {'fill'=>'black','outline'=>'black','width'=>1}
end

View File

@ -67,7 +67,7 @@ TkText.new($bind_demo){|t|
tagstyle_normal = {'foreground'=>'', 'background'=>''}
end
# テキスト挿入
# insert text
insert 'insert', "The same tag mechanism that controls display styles in text widgets can also be used to associate Tcl commands with regions of text, so that mouse or keyboard actions on the text cause particular Tcl commands to be invoked. For example, in the text below the descriptions of the canvas demonstrations have been tagged. When you move the mouse over a demo description the description lights up, and when you press button 1 over a description then that particular demonstration is invoked.
"

View File

@ -39,11 +39,11 @@ class Browse
}
# Set up bindings for the browser.
base.bind('Control-c',
proc{
base.destroy
base.bind('Destroy', proc{
Browse::BROWSE_WIN_COUNTER.value = \
Browse::BROWSE_WIN_COUNTER.to_i - 1})
Browse::BROWSE_WIN_COUNTER.to_i - 1
})
base.bind('Control-c', proc{base.destroy})
list.bind('Double-Button-1',
proc{TkSelection.get.each{|f| self.browse dir, f}})
end

Some files were not shown because too many files have changed in this diff Show More