diff options
Diffstat (limited to 'jni/ruby/ext/tk/lib')
343 files changed, 64740 insertions, 0 deletions
diff --git a/jni/ruby/ext/tk/lib/README b/jni/ruby/ext/tk/lib/README new file mode 100644 index 0000000..c076755 --- /dev/null +++ b/jni/ruby/ext/tk/lib/README @@ -0,0 +1,30 @@ +README this file +multi-tk.rb multiple Tk interpreter (included safe-Tk) support +remotei-tk.rb control remote Tk interpreter on the other process support +tk.rb Tk interface + +tk/ library files construct Ruby/Tk + +tkextlib/ non-standard Tcl/Tk extension support libraries + +********************************************************************* +*** The followings exists for backward compatibility only. +*** The only thing which they work is that requires current +*** library files ( tk/*.rb ). +********************************************************************* +tkafter.rb handles Tcl after +tkbgerror.rb Tk error module +tkcanvas.rb Tk canvas interface +tkclass.rb provides generic names for Tk classes +tkconsole.rb console command support +tkdialog.rb Tk dialog class +tkentry.rb Tk entry class +tkfont.rb Tk font support +tkmacpkg.rb Mac resource support +tkmenubar.rb TK menubar utility +tkmngfocus.rb focus manager +tkpalette.rb pallete support +tkscrollbox.rb scroll box, also example of compound widget +tktext.rb text classes +tkvirtevent.rb virtual event support +tkwinpkg.rb Win DDE and registry support diff --git a/jni/ruby/ext/tk/lib/multi-tk.rb b/jni/ruby/ext/tk/lib/multi-tk.rb new file mode 100644 index 0000000..bb6e69a --- /dev/null +++ b/jni/ruby/ext/tk/lib/multi-tk.rb @@ -0,0 +1,3754 @@ +# +# multi-tk.rb - supports multi Tk interpreters +# by Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + +require 'tcltklib' +require 'tkutil' +require 'thread' + +if defined? Tk + fail RuntimeError,"'multi-tk' library must be required before requiring 'tk'" +end + +################################################ +# ignore exception on the mainloop? + +TclTkLib.mainloop_abort_on_exception = true +# TclTkLib.mainloop_abort_on_exception = false +# TclTkLib.mainloop_abort_on_exception = nil + + +################################################ +# add ThreadGroup check to TclTkIp.new +class << TclTkIp + alias __new__ new + private :__new__ + + def new(*args) + if Thread.current.group != ThreadGroup::Default + raise SecurityError, 'only ThreadGroup::Default can call TclTkIp.new' + end + obj = __new__(*args) + obj.instance_eval{ + @force_default_encoding ||= TkUtil.untrust([false]) + @encoding ||= TkUtil.untrust([nil]) + def @encoding.to_s; self.join(nil); end + } + obj + end +end + + +################################################ +# exceptiopn to treat the return value from IP +class MultiTkIp_OK < Exception + def self.send(thread, ret=nil) + thread.raise self.new(ret) + end + + def initialize(ret=nil) + super('succeed') + @return_value = ret + end + + attr_reader :return_value + alias value return_value +end +MultiTkIp_OK.freeze + + +################################################ +# methods for construction +class MultiTkIp + class Command_Queue < Queue + def initialize(interp) + @interp = interp + super() + end + + def push(value) + if !@interp || @interp.deleted? + fail RuntimeError, "Tk interpreter is already deleted" + end + super(value) + end + alias << push + alias enq push + + def close + @interp = nil + end + end + Command_Queue.freeze + + BASE_DIR = File.dirname(__FILE__) + + WITH_RUBY_VM = Object.const_defined?(:RubyVM) && ::RubyVM.class == Class + WITH_ENCODING = defined?(::Encoding.default_external) + #WITH_ENCODING = Object.const_defined?(:Encoding) && ::Encoding.class == Class + + (@@SLAVE_IP_ID = ['slave'.freeze, TkUtil.untrust('0')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + @@IP_TABLE = TkUtil.untrust({}) unless defined?(@@IP_TABLE) + + @@INIT_IP_ENV = TkUtil.untrust([]) unless defined?(@@INIT_IP_ENV) # table of Procs + @@ADD_TK_PROCS = TkUtil.untrust([]) unless defined?(@@ADD_TK_PROCS) # table of [name, args, body] + + @@TK_TABLE_LIST = TkUtil.untrust([]) unless defined?(@@TK_TABLE_LIST) + + unless defined?(@@TK_CMD_TBL) + @@TK_CMD_TBL = TkUtil.untrust(Object.new) + + # @@TK_CMD_TBL.instance_variable_set('@tbl', {}.taint) + tbl_obj = TkUtil.untrust(Hash.new{|hash,key| + fail IndexError, "unknown command ID '#{key}'" + }) + @@TK_CMD_TBL.instance_variable_set('@tbl', tbl_obj) + + class << @@TK_CMD_TBL + allow = [ + '__send__', '__id__', 'freeze', 'inspect', 'kind_of?', 'object_id', + '[]', '[]=', 'delete', 'each', 'has_key?' + ] + instance_methods.each{|m| undef_method(m) unless allow.index(m.to_s)} + + def kind_of?(klass) + @tbl.kind_of?(klass) + end + + def inspect + if Thread.current.group == ThreadGroup::Default + @tbl.inspect + else + ip = MultiTkIp.__getip + @tbl.reject{|idx, ent| ent.respond_to?(:ip) && ent.ip != ip}.inspect + end + end + + def [](idx) + return unless (ent = @tbl[idx]) + if Thread.current.group == ThreadGroup::Default + ent + elsif ent.respond_to?(:ip) + (ent.ip == MultiTkIp.__getip)? ent: nil + else + ent + end + end + + def []=(idx,val) + if self.has_key?(idx) && Thread.current.group != ThreadGroup::Default + fail SecurityError,"cannot change the entried command" + end + @tbl[idx] = val + end + + def delete(idx, &blk) + # if gets an entry, is permitted to delete + if self[idx] + @tbl.delete(idx) + elsif blk + blk.call(idx) + else + nil + end + end + + def each(&blk) + if Thread.current.group == ThreadGroup::Default + @tbl.each(&blk) + else + ip = MultiTkIp.__getip + @tbl.each{|idx, ent| + blk.call(idx, ent) unless ent.respond_to?(:ip) && ent.ip != ip + } + end + self + end + + def has_key?(k) + @tbl.has_key?(k) + end + alias include? has_key? + alias key? has_key? + alias member? has_key? + end + + @@TK_CMD_TBL.freeze + end + + ###################################### + + @@CB_ENTRY_CLASS = Class.new(TkCallbackEntry){ + def initialize(ip, cmd) + @ip = ip + @safe = safe = $SAFE + # @cmd = cmd + cmd = MultiTkIp._proc_on_safelevel(&cmd) + @cmd = proc{|*args| cmd.call(safe, *args)} + self.freeze + end + attr_reader :ip, :cmd + def inspect + cmd.inspect + end + def call(*args) + unless @ip.deleted? + current = Thread.current + backup_ip = current[:callback_ip] + current[:callback_ip] = @ip + begin + ret = @ip.cb_eval(@cmd, *args) + fail ret if ret.kind_of?(Exception) + ret + rescue TkCallbackBreak, TkCallbackContinue => e + fail e + rescue SecurityError => e + # in 'exit', 'exit!', and 'abort' : security error --> delete IP + if e.backtrace[0] =~ /^(.+?):(\d+):in `(exit|exit!|abort)'/ + @ip.delete + elsif @ip.safe? + if @ip.respond_to?(:cb_error) + @ip.cb_error(e) + else + nil # ignore + end + else + fail e + end + rescue Exception => e + fail e if e.message =~ /^TkCallback/ + + if @ip.safe? + if @ip.respond_to?(:cb_error) + @ip.cb_error(e) + else + nil # ignore + end + else + fail e + end + ensure + current[:callback_ip] = backup_ip + end + end + end + }.freeze + + ###################################### + + 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 + + def _check_and_return(thread, exception, wait=0) + unless thread + unless exception.kind_of?(MultiTkIp_OK) + msg = "#{exception.class}: #{exception.message}" + + if @interp.deleted? + warn("Warning (#{self}): " + msg) + return nil + end + + if safe? + warn("Warning (#{self}): " + msg) if $DEBUG + return nil + end + + begin + @interp._eval_without_enc(@interp._merge_tklist('bgerror', msg)) + rescue Exception => e + warn("Warning (#{self}): " + msg) + end + end + return nil + end + + if wait == 0 + # no wait + Thread.pass + if thread.stop? + thread.raise exception + end + return thread + end + + # wait to stop the caller thread + wait.times{ + if thread.stop? + # ready to send exception + thread.raise exception + return thread + end + + # wait + Thread.pass + } + + # unexpected error + thread.raise RuntimeError, "the thread may not wait for the return value" + return thread + end + + ###################################### + + def set_cb_error(cmd = Proc.new) + @cb_error_proc[0] = cmd + end + + def cb_error(e) + if @cb_error_proc[0].respond_to?(:call) + @cb_error_proc[0].call(e) + end + end + + ###################################### + + def set_safe_level(safe) + if safe > @safe_level[0] + @safe_level[0] = safe + @cmd_queue.enq([@system, 'set_safe_level', safe]) + end + @safe_level[0] + end + def safe_level=(safe) + set_safe_level(safe) + end + def self.set_safe_level(safe) + __getip.set_safe_level(safe) + end + def self.safe_level=(safe) + self.set_safe_level(safe) + end + def safe_level + @safe_level[0] + end + def self.safe_level + __getip.safe_level + end + + def wait_on_mainloop? + @wait_on_mainloop[0] + end + def wait_on_mainloop=(bool) + @wait_on_mainloop[0] = bool + end + + def running_mainloop? + @wait_on_mainloop[1] > 0 + end + + def _destroy_slaves_of_slaveIP(ip) + unless ip.deleted? + # ip._split_tklist(ip._invoke('interp', 'slaves')).each{|name| + ip._split_tklist(ip._invoke_without_enc('interp', 'slaves')).each{|name| + name = _fromUTF8(name) + begin + # ip._eval_without_enc("#{name} eval {foreach i [after info] {after cancel $i}}") + after_ids = ip._eval_without_enc("#{name} eval {after info}") + ip._eval_without_enc("#{name} eval {foreach i {#{after_ids}} {after cancel $i}}") + rescue Exception + end + begin + # ip._invoke('interp', 'eval', name, 'destroy', '.') + ip._invoke(name, 'eval', 'destroy', '.') + rescue Exception + end + + # safe_base? + if ip._eval_without_enc("catch {::safe::interpConfigure #{name}}") == '0' + begin + ip._eval_without_enc("::safe::interpDelete #{name}") + rescue Exception + end + end +=begin + if ip._invoke('interp', 'exists', name) == '1' + begin + ip._invoke(name, 'eval', 'exit') + rescue Exception + end + end +=end + unless ip.deleted? + if ip._invoke('interp', 'exists', name) == '1' + begin + ip._invoke('interp', 'delete', name) + rescue Exception + end + end + end + } + end + end + + def _receiver_eval_proc_core(safe_level, thread, cmd, *args) + begin + #ret = proc{$SAFE = safe_level; cmd.call(*args)}.call + #ret = cmd.call(safe_level, *args) + normal_ret = false + ret = catch(:IRB_EXIT) do # IRB hack + retval = cmd.call(safe_level, *args) + normal_ret = true + retval + end + unless normal_ret + # catch IRB_EXIT + exit(ret) + end + ret + rescue SystemExit => e + # delete IP + unless @interp.deleted? + @slave_ip_tbl.each{|name, subip| + _destroy_slaves_of_slaveIP(subip) + begin + # subip._eval_without_enc("foreach i [after info] {after cancel $i}") + after_ids = subip._eval_without_enc("after info") + subip._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}") + rescue Exception + end +=begin + begin + subip._invoke('destroy', '.') unless subip.deleted? + rescue Exception + end +=end + # safe_base? + if @interp._eval_without_enc("catch {::safe::interpConfigure #{name}}") == '0' + begin + @interp._eval_without_enc("::safe::interpDelete #{name}") + rescue Exception + else + next if subip.deleted? + end + end + if subip.respond_to?(:safe_base?) && subip.safe_base? && + !subip.deleted? + # do 'exit' to call the delete_hook procedure + begin + subip._eval_without_enc('exit') + rescue Exception + end + else + begin + subip.delete unless subip.deleted? + rescue Exception + end + end + } + + begin + # @interp._eval_without_enc("foreach i [after info] {after cancel $i}") + after_ids = @interp._eval_without_enc("after info") + @interp._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}") + rescue Exception + end + begin + @interp._invoke('destroy', '.') unless @interp.deleted? + rescue Exception + end + if @safe_base && !@interp.deleted? + # do 'exit' to call the delete_hook procedure + @interp._eval_without_enc('exit') + else + @interp.delete unless @interp.deleted? + end + end + + if e.backtrace[0] =~ /^(.+?):(\d+):in `(exit|exit!|abort)'/ + _check_and_return(thread, MultiTkIp_OK.new($3 == 'exit')) + else + _check_and_return(thread, MultiTkIp_OK.new(nil)) + end + + # if master? && !safe? && allow_ruby_exit? + if !@interp.deleted? && master? && !safe? && allow_ruby_exit? +=begin + ObjectSpace.each_object(TclTkIp){|obj| + obj.delete unless obj.deleted? + } +=end + #exit(e.status) + fail e + end + # break + + rescue SecurityError => e + # in 'exit', 'exit!', and 'abort' : security error --> delete IP + if e.backtrace[0] =~ /^(.+?):(\d+):in `(exit|exit!|abort)'/ + ret = ($3 == 'exit') + unless @interp.deleted? + @slave_ip_tbl.each{|name, subip| + _destroy_slaves_of_slaveIP(subip) + begin + # subip._eval_without_enc("foreach i [after info] {after cancel $i}") + after_ids = subip._eval_without_enc("after info") + subip._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}") + rescue Exception + end +=begin + begin + subip._invoke('destroy', '.') unless subip.deleted? + rescue Exception + end +=end + # safe_base? + if @interp._eval_without_enc("catch {::safe::interpConfigure #{name}}") == '0' + begin + @interp._eval_without_enc("::safe::interpDelete #{name}") + rescue Exception + else + next if subip.deleted? + end + end + if subip.respond_to?(:safe_base?) && subip.safe_base? && + !subip.deleted? + # do 'exit' to call the delete_hook procedure + begin + subip._eval_without_enc('exit') + rescue Exception + end + else + begin + subip.delete unless subip.deleted? + rescue Exception + end + end + } + + begin + # @interp._eval_without_enc("foreach i [after info] {after cancel $i}") + after_ids = @interp._eval_without_enc("after info") + @interp._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}") + rescue Exception + end +=begin + begin + @interp._invoke('destroy', '.') unless @interp.deleted? + rescue Exception + end +=end + if @safe_base && !@interp.deleted? + # do 'exit' to call the delete_hook procedure + @interp._eval_without_enc('exit') + else + @interp.delete unless @interp.deleted? + end + end + _check_and_return(thread, MultiTkIp_OK.new(ret)) + # break + + else + # raise security error + _check_and_return(thread, e) + end + + rescue Exception => e + # raise exception + begin + bt = _toUTF8(e.backtrace.join("\n")) + if MultiTkIp::WITH_ENCODING + bt.force_encoding('utf-8') + else + bt.instance_variable_set(:@encoding, 'utf-8') + end + rescue Exception + bt = e.backtrace.join("\n") + end + begin + @interp._set_global_var('errorInfo', bt) + rescue Exception + end + _check_and_return(thread, e) + + else + # no exception + _check_and_return(thread, MultiTkIp_OK.new(ret)) + end + end + + def _receiver_eval_proc(last_thread, safe_level, thread, cmd, *args) + if thread + Thread.new{ + last_thread.join if last_thread + unless @interp.deleted? + _receiver_eval_proc_core(safe_level, thread, cmd, *args) + end + } + else + Thread.new{ + unless @interp.deleted? + _receiver_eval_proc_core(safe_level, thread, cmd, *args) + end + } + last_thread + end + end + + private :_receiver_eval_proc, :_receiver_eval_proc_core + + def _receiver_mainloop(check_root) + if @evloop_thread[0] && @evloop_thread[0].alive? + @evloop_thread[0] + else + @evloop_thread[0] = Thread.new{ + while !@interp.deleted? + #if check_root + # inf = @interp._invoke_without_enc('info', 'command', '.') + # break if !inf.kind_of?(String) || inf != '.' + #end + break if check_root && !@interp.has_mainwindow? + sleep 0.5 + end + } + @evloop_thread[0] + end + end + + def _create_receiver_and_watchdog(lvl = $SAFE) + lvl = $SAFE if lvl < $SAFE + + # command-procedures receiver + receiver = Thread.new(lvl){|safe_level| + last_thread = {} + + loop do + break if @interp.deleted? + thread, cmd, *args = @cmd_queue.deq + if thread == @system + # control command + case cmd + when 'set_safe_level' + begin + safe_level = args[0] if safe_level < args[0] + rescue Exception + end + when 'call_mainloop' + thread = args.shift + _check_and_return(thread, + MultiTkIp_OK.new(_receiver_mainloop(*args))) + else + # ignore + end + + else + # procedure + last_thread[thread] = _receiver_eval_proc(last_thread[thread], + safe_level, thread, + cmd, *args) + end + end + } + + # watchdog of receiver + watchdog = Thread.new{ + begin + loop do + sleep 1 + if @interp.deleted? + receiver.kill + @cmd_queue.close + end + break unless receiver.alive? + end + rescue Exception + # ignore all kind of Exception + end + + # receiver is dead + retry_count = 3 + loop do + Thread.pass + begin + thread, cmd, *args = @cmd_queue.deq(true) # non-block + rescue ThreadError + # queue is empty + retry_count -= 1 + break if retry_count <= 0 + sleep 0.5 + retry + end + next unless thread + if thread.alive? + if @interp.deleted? + thread.raise RuntimeError, 'the interpreter is already deleted' + else + thread.raise RuntimeError, + 'the interpreter no longer receives command procedures' + end + end + end + } + + # return threads + [receiver, watchdog] + end + private :_check_and_return, :_create_receiver_and_watchdog + + ###################################### + + unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD + ### Ruby 1.9 !!!!!!!!!!!!!!!!!!!!!!!!!! + RUN_EVENTLOOP_ON_MAIN_THREAD = false + end + + if self.const_defined? :DEFAULT_MASTER_NAME + name = DEFAULT_MASTER_NAME.to_s + else + name = nil + end + if self.const_defined?(:DEFAULT_MASTER_OPTS) && + DEFAULT_MASTER_OPTS.kind_of?(Hash) + keys = DEFAULT_MASTER_OPTS + else + keys = {} + end + + @@DEFAULT_MASTER = self.allocate + @@DEFAULT_MASTER.instance_eval{ + @tk_windows = TkUtil.untrust({}) + + @tk_table_list = TkUtil.untrust([]) + + @slave_ip_tbl = TkUtil.untrust({}) + + @slave_ip_top = TkUtil.untrust({}) + + @evloop_thread = TkUtil.untrust([]) + + unless keys.kind_of? Hash + fail ArgumentError, "expecting a Hash object for the 2nd argument" + end + + if !WITH_RUBY_VM || RUN_EVENTLOOP_ON_MAIN_THREAD ### check Ruby 1.9 !!!!!!! + @interp = TclTkIp.new(name, _keys2opts(keys)) + else ### Ruby 1.9 !!!!!!!!!!! + @interp_thread = Thread.new{ + current = Thread.current + begin + current[:interp] = interp = TclTkIp.new(name, _keys2opts(keys)) + rescue e + current[:interp] = e + raise e + end + #sleep + current[:mutex] = mutex = Mutex.new + current[:root_check] = cond_var = ConditionVariable.new + + status = [nil] + def status.value + self[0] + end + def status.value=(val) + self[0] = val + end + current[:status] = status + + begin + begin + #TclTkLib.mainloop_abort_on_exception = false + #Thread.current[:status].value = TclTkLib.mainloop(true) + interp.mainloop_abort_on_exception = true + current[:status].value = interp.mainloop(true) + rescue SystemExit=>e + current[:status].value = e + rescue Exception=>e + current[:status].value = e + retry if interp.has_mainwindow? + ensure + mutex.synchronize{ cond_var.broadcast } + end + + #Thread.current[:status].value = TclTkLib.mainloop(false) + current[:status].value = interp.mainloop(false) + + ensure + # interp must be deleted before the thread for interp is dead. + # If not, raise Tcl_Panic on Tcl_AsyncDelete because async handler + # deleted by the wrong thread. + interp.delete + end + } + until @interp_thread[:interp] + Thread.pass + end + # INTERP_THREAD.run + raise @interp_thread[:interp] if @interp_thread[:interp].kind_of? Exception + @interp = @interp_thread[:interp] + + # delete the interpreter and kill the eventloop thread at exit + interp = @interp + interp_thread = @interp_thread + END{ + if interp_thread.alive? + interp.delete + interp_thread.kill + end + } + + def self.mainloop(check_root = true) + begin + TclTkLib.set_eventloop_window_mode(true) + @interp_thread.value + ensure + TclTkLib.set_eventloop_window_mode(false) + end + end + end + + @interp.instance_eval{ + @force_default_encoding ||= TkUtil.untrust([false]) + @encoding ||= TkUtil.untrust([nil]) + def @encoding.to_s; self.join(nil); end + } + + @ip_name = nil + + @callback_status = TkUtil.untrust([]) + + @system = Object.new + + @wait_on_mainloop = TkUtil.untrust([true, 0]) + + @threadgroup = Thread.current.group + + @safe_base = false + + @safe_level = [$SAFE] + + @cmd_queue = MultiTkIp::Command_Queue.new(@interp) + + @cmd_receiver, @receiver_watchdog = _create_receiver_and_watchdog(@safe_level[0]) + + @threadgroup.add @cmd_receiver + @threadgroup.add @receiver_watchdog + + # NOT enclose @threadgroup for @@DEFAULT_MASTER + + @@IP_TABLE[ThreadGroup::Default] = self + @@IP_TABLE[@threadgroup] = self + + ################################# + + @pseudo_toplevel = [false, nil] + + def self.__pseudo_toplevel + Thread.current.group == ThreadGroup::Default && + MultiTkIp.__getip == @@DEFAULT_MASTER && + self.__pseudo_toplevel_evaluable? && @pseudo_toplevel[1] + end + + def self.__pseudo_toplevel=(m) + unless (Thread.current.group == ThreadGroup::Default && + MultiTkIp.__getip == @@DEFAULT_MASTER) + fail SecurityError, "no permission to manipulate" + end + + # if m.kind_of?(Module) && m.respond_to?(:pseudo_toplevel_evaluable?) + if m.respond_to?(:pseudo_toplevel_evaluable?) + @pseudo_toplevel[0] = true + @pseudo_toplevel[1] = m + else + fail ArgumentError, 'fail to set pseudo-toplevel' + end + self + end + + def self.__pseudo_toplevel_evaluable? + begin + @pseudo_toplevel[0] && @pseudo_toplevel[1].pseudo_toplevel_evaluable? + rescue Exception + false + end + end + + def self.__pseudo_toplevel_evaluable=(mode) + unless (Thread.current.group == ThreadGroup::Default && + MultiTkIp.__getip == @@DEFAULT_MASTER) + fail SecurityError, "no permission to manipulate" + end + + @pseudo_toplevel[0] = (mode)? true: false + end + + ################################# + + @assign_request = Class.new(Exception){ + def self.new(target, ret) + obj = super() + obj.target = target + obj.ret = ret + obj + end + attr_accessor :target, :ret + } + + @assign_thread = Thread.new{ + loop do + begin + Thread.stop + rescue @assign_request=>req + begin + req.ret[0] = req.target.instance_eval{ + @cmd_receiver, @receiver_watchdog = + _create_receiver_and_watchdog(@safe_level[0]) + @threadgroup.add @cmd_receiver + @threadgroup.add @receiver_watchdog + @threadgroup.enclose + true + } + rescue Exception=>e + begin + req.ret[0] = e + rescue Exception + # ignore + end + end + rescue Exception + # ignore + end + end + } + + def self.assign_receiver_and_watchdog(target) + ret = [nil] + @assign_thread.raise(@assign_request.new(target, ret)) + while ret[0] == nil + unless @assign_thread.alive? + raise RuntimeError, 'lost the thread to assign a receiver and a watchdog thread' + end + end + if ret[0].kind_of?(Exception) + raise ret[0] + else + ret[0] + end + end + + ################################# + + @init_ip_env_queue = Queue.new + Thread.new{ + current = Thread.current + loop { + mtx, cond, ret, table, script = @init_ip_env_queue.deq + begin + ret[0] = table.each{|tg, ip| ip._init_ip_env(script) } + rescue Exception => e + ret[0] = e + ensure + mtx.synchronize{ cond.signal } + end + mtx = cond = ret = table = script = nil # clear variables for GC + } + } + + def self.__init_ip_env__(table, script) + ret = [] + mtx = (Thread.current[:MultiTk_ip_Mutex] ||= Mutex.new) + cond = (Thread.current[:MultiTk_ip_CondVar] ||= ConditionVariable.new) + mtx.synchronize{ + @init_ip_env_queue.enq([mtx, cond, ret, table, script]) + cond.wait(mtx) + } + if ret[0].kind_of?(Exception) + raise ret[0] + else + ret[0] + end + end + + ################################# + + class << self + undef :instance_eval + end + } + + @@DEFAULT_MASTER.freeze # defend against modification + + ###################################### + + def self.inherited(subclass) + # trust if on ThreadGroup::Default or @@DEFAULT_MASTER's ThreadGroup + if @@IP_TABLE[Thread.current.group] == @@DEFAULT_MASTER + begin + class << subclass + self.methods.each{|m| + name = m.to_s + begin + unless name == '__id__' || name == '__send__' || name == 'freeze' + undef_method(m) + end + rescue Exception + # ignore all exceptions + end + } + end + ensure + subclass.freeze + fail SecurityError, + "cannot create subclass of MultiTkIp on a untrusted ThreadGroup" + end + end + end + + ###################################### + + @@SAFE_OPT_LIST = [ + 'accessPath'.freeze, + 'statics'.freeze, + 'nested'.freeze, + 'deleteHook'.freeze + ].freeze + + def _parse_slaveopts(keys) + name = nil + safe = false + safe_opts = {} + tk_opts = {} + + keys.each{|k,v| + k_str = k.to_s + if k_str == 'name' + name = v + elsif k_str == 'safe' + safe = v + elsif @@SAFE_OPT_LIST.member?(k_str) + safe_opts[k_str] = v + else + tk_opts[k_str] = v + end + } + + 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 + @@SLAVE_IP_ID.mutex.synchronize{ + name = @@SLAVE_IP_ID.join('') + @@SLAVE_IP_ID[1].succ! + name.freeze + } + end + private :_create_slave_ip_name + + ###################################### + + def __check_safetk_optkeys(optkeys) + # based on 'safetk.tcl' + new_keys = {} + optkeys.each{|k,v| new_keys[k.to_s] = v} + + # check 'display' + if !new_keys.key?('display') + begin + #new_keys['display'] = @interp._invoke('winfo screen .') + new_keys['display'] = @interp._invoke('winfo', 'screen', '.') + rescue + if ENV[DISPLAY] + new_keys['display'] = ENV[DISPLAY] + elsif !new_keys.key?('use') + warn "Warning: no screen info or ENV[DISPLAY], so use ':0.0'" + new_keys['display'] = ':0.0' + end + end + end + + # check 'use' + if new_keys.key?('use') + # given 'use' + case new_keys['use'] + when TkWindow + new_keys['use'] = TkWinfo.id(new_keys['use']) + #assoc_display = @interp._eval('winfo screen .') + assoc_display = @interp._invoke('winfo', 'screen', '.') + when /^\..*/ + new_keys['use'] = @interp._invoke('winfo', 'id', new_keys['use']) + assoc_display = @interp._invoke('winfo', 'screen', new_keys['use']) + else + begin + pathname = @interp._invoke('winfo', 'pathname', new_keys['use']) + assoc_display = @interp._invoke('winfo', 'screen', pathname) + rescue + assoc_display = new_keys['display'] + end + end + + # match display? + if assoc_display != new_keys['display'] + if optkeys.key?(:display) || optkeys.key?('display') + fail RuntimeError, + "conflicting 'display'=>#{new_keys['display']} " + + "and display '#{assoc_display}' on 'use'=>#{new_keys['use']}" + else + new_keys['display'] = assoc_display + end + end + end + + # return + new_keys + end + private :__check_safetk_optkeys + + def __create_safetk_frame(slave_ip, slave_name, app_name, keys) + # display option is used by ::safe::loadTk + loadTk_keys = {} + loadTk_keys['display'] = keys['display'] + dup_keys = keys.dup + + # keys for toplevel : allow followings + toplevel_keys = {} + ['height', 'width', 'background', 'menu'].each{|k| + toplevel_keys[k] = dup_keys.delete(k) if dup_keys.key?(k) + } + toplevel_keys['classname'] = 'SafeTk' + toplevel_keys['screen'] = dup_keys.delete('display') + + # other keys used by pack option of container frame + + # create toplevel widget + begin + top = TkToplevel.new(toplevel_keys) + rescue NameError => e + fail e unless @interp.safe? + fail SecurityError, "unable create toplevel on the safe interpreter" + end + msg = "Untrusted Ruby/Tk applet (#{slave_name})" + if app_name.kind_of?(String) + top.title "#{app_name} (#{slave_name})" + else + top.title msg + end + + # 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 + slave_ip._eval_without_enc('exit') + end + begin + top.destroy if top.winfo_exist? + rescue + # ignore + end + } + 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) + + TkFrame.new(fc, :bd=>0){|f| + TkButton.new(f, + :text=>'Delete', :bd=>1, :padx=>2, :pady=>0, + :highlightthickness=>0, :command=>slave_delete_proc + ).pack(:side=>:right, :fill=>:both) + f.pack(:side=>:right, :fill=>:both, :expand=>true) + } + + TkLabel.new(fc, :text=>msg, :padx=>2, :pady=>0, + :anchor=>:w).pack(:side=>:left, :fill=>:both, :expand=>true) + + fc.pack(:side=>:bottom, :fill=>:x) + } + + # container frame for slave interpreter + dup_keys['fill'] = :both unless dup_keys.key?('fill') + dup_keys['expand'] = true unless dup_keys.key?('expand') + c = TkFrame.new(top, :container=>true).pack(dup_keys) + c.bind('Destroy', proc{top.destroy}) + + # return keys + loadTk_keys['use'] = TkWinfo.id(c) + [loadTk_keys, top.path] + end + private :__create_safetk_frame + + def __create_safe_slave_obj(safe_opts, app_name, tk_opts) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + + # safe interpreter + ip_name = _create_slave_ip_name + slave_ip = @interp.create_slave(ip_name, true) + slave_ip.instance_eval{ + @force_default_encoding ||= TkUtil.untrust([false]) + @encoding ||= TkUtil.untrust([nil]) + def @encoding.to_s; self.join(nil); end + } + @slave_ip_tbl[ip_name] = slave_ip + def slave_ip.safe_base? + true + end + + @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)}") + @interp._invoke('__replace_slave_tk_commands__', ip_name) + 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 + + def __create_trusted_slave_obj(name, keys) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + + ip_name = _create_slave_ip_name + slave_ip = @interp.create_slave(ip_name, false) + slave_ip.instance_eval{ + @force_default_encoding ||= TkUtil.untrust([false]) + @encoding ||= TkUtil.untrust([nil]) + def @encoding.to_s; self.join(nil); end + } + slave_ip._invoke('set', 'argv0', name) if name.kind_of?(String) + slave_ip._invoke('set', 'argv', _keys2opts(keys)) + @interp._invoke('load', '', 'Tk', ip_name) + @interp._invoke('__replace_slave_tk_commands__', ip_name) + @slave_ip_tbl[ip_name] = slave_ip + [slave_ip, ip_name] + end + + ###################################### + + def _create_slave_object(keys={}) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + + ip = MultiTkIp.new_slave(self, keys={}) + @slave_ip_tbl[ip.name] = ip + end + + ###################################### + + def initialize(master, safeip=true, keys={}) + if $SAFE >= 4 + fail SecurityError, "cannot create a new interpreter at level #{$SAFE}" + end + + if safeip == nil && $SAFE >= 2 + fail SecurityError, "cannot create a master-ip at level #{$SAFE}" + end + + if master.deleted? && safeip == nil + fail RuntimeError, "cannot create a slave of a deleted interpreter" + end + + if !master.deleted? && !master.master? && master.safe? + fail SecurityError, "safe-slave-ip cannot create a new interpreter" + end + + if safeip == nil && !master.master? + fail SecurityError, "slave-ip cannot create a master-ip" + end + + unless keys.kind_of? Hash + fail ArgumentError, "expecting a Hash object for the 2nd argument" + end + + @tk_windows = {} + @tk_table_list = [] + @slave_ip_tbl = {} + @slave_ip_top = {} + @cb_error_proc = [] + @evloop_thread = [] + + TkUtil.untrust(@tk_windows) unless @tk_windows.tainted? + TkUtil.untrust(@tk_table_list) unless @tk_table_list.tainted? + TkUtil.untrust(@slave_ip_tbl) unless @slave_ip_tbl.tainted? + TkUtil.untrust(@slave_ip_top) unless @slave_ip_top.tainted? + TkUtil.untrust(@cb_error_proc) unless @cb_error_proc.tainted? + TkUtil.untrust(@evloop_thread) unless @evloop_thread.tainted? + + @callback_status = [] + + name, safe, safe_opts, tk_opts = _parse_slaveopts(keys) + + safe = 4 if safe && !safe.kind_of?(Fixnum) + + @safe_base = false + + if safeip == nil + # create master-ip + unless WITH_RUBY_VM + @interp = TclTkIp.new(name, _keys2opts(tk_opts)) + @interp.instance_eval{ + @force_default_encoding ||= TkUtil.untrust([false]) + @encoding ||= TkUtil.untrust([nil]) + def @encoding.to_s; self.join(nil); end + } + + else ### Ruby 1.9 !!!!!!!!!!! +=begin + @interp_thread = Thread.new{ + Thread.current[:interp] = interp = TclTkIp.new(name, _keys2opts(tk_opts)) + interp.instance_eval{ + @force_default_encoding ||= TkUtil.untrust([false]) + @encoding ||= TkUtil.untrust([nil]) + def @encoding.to_s; self.join(nil); end + } + + #sleep + TclTkLib.mainloop(true) + } + until @interp_thread[:interp] + Thread.pass + end + # INTERP_THREAD.run + @interp = @interp_thread[:interp] +=end + @interp_thread = Thread.new{ + current = Thread.current + begin + current[:interp] = interp = TclTkIp.new(name, _keys2opts(tk_opts)) + rescue e + current[:interp] = e + raise e + end + #sleep + #TclTkLib.mainloop(true) + current[:mutex] = mutex = Mutex.new + current[:root_check] = cond_ver = ConditionVariable.new + + status = [nil] + def status.value + self[0] + end + def status.value=(val) + self[0] = val + end + current[:status] = status + + begin + begin + current[:status].value = interp.mainloop(true) + rescue SystemExit=>e + current[:status].value = e + rescue Exception=>e + current[:status].value = e + retry if interp.has_mainwindow? + ensure + mutex.synchronize{ cond_var.broadcast } + end + current[:status].value = interp.mainloop(false) + ensure + interp.delete + end + } + until @interp_thread[:interp] + Thread.pass + end + # INTERP_THREAD.run + @interp = @interp_thread[:interp] + + @evloop_thread[0] = @interp_thread + + def self.mainloop(check_root = true) + begin + TclTkLib.set_eventloop_window_mode(true) + @interp_thread.value + ensure + TclTkLib.set_eventloop_window_mode(false) + end + end + end + + @interp.instance_eval{ + @force_default_encoding ||= TkUtil.untrust([false]) + @encoding ||= TkUtil.untrust([nil]) + def @encoding.to_s; self.join(nil); end + } + + @ip_name = nil + + if safe + safe = $SAFE if safe < $SAFE + @safe_level = [safe] + else + @safe_level = [$SAFE] + end + + else + # create slave-ip + if safeip || master.safe? + @safe_base = true + @interp, @ip_name = master.__create_safe_slave_obj(safe_opts, + name, tk_opts) + # @interp_thread = nil if RUBY_VERSION < '1.9.0' ### !!!!!!!!!!! + @interp_thread = nil unless WITH_RUBY_VM ### Ruby 1.9 !!!!!!!!!!! + if safe + safe = master.safe_level if safe < master.safe_level + @safe_level = [safe] + else + @safe_level = [4] + end + else + @interp, @ip_name = master.__create_trusted_slave_obj(name, tk_opts) + # @interp_thread = nil if RUBY_VERSION < '1.9.0' ### !!!!!!!!!!! + @interp_thread = nil unless WITH_RUBY_VM ### Ruby 1.9 !!!!!!!!!!! + if safe + safe = master.safe_level if safe < master.safe_level + @safe_level = [safe] + else + @safe_level = [master.safe_level] + end + end + @set_alias_proc = proc{|name| + master._invoke('interp', 'alias', @ip_name, name, '', name) + }.freeze + end + + @system = Object.new + + @wait_on_mainloop = TkUtil.untrust([true, 0]) + # @wait_on_mainloop = TkUtil.untrust([false, 0]) + + @threadgroup = ThreadGroup.new + + @pseudo_toplevel = [false, nil] + + @cmd_queue = MultiTkIp::Command_Queue.new(@interp) + +=begin + @cmd_receiver, @receiver_watchdog = _create_receiver_and_watchdog(@safe_level[0]) + + @threadgroup.add @cmd_receiver + @threadgroup.add @receiver_watchdog + + @threadgroup.enclose +=end + @@DEFAULT_MASTER.assign_receiver_and_watchdog(self) + + @@IP_TABLE[@threadgroup] = self + @@TK_TABLE_LIST.size.times{ + @tk_table_list << TkUtil.untrust({}) + } + _init_ip_internal(@@INIT_IP_ENV, @@ADD_TK_PROCS) + + class << self + undef :instance_eval + end + + # dummy call for initialization + self.eval_proc{ Tk.tk_call('set', 'tcl_patchLevel') } + + self.freeze # defend against modification + end + + ###################################### + + def _default_delete_hook(slave) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @slave_ip_tbl.delete(slave) + top = @slave_ip_top.delete(slave) + if top.kind_of?(String) + # call default hook of safetk.tcl (ignore exceptions) + if top == '' + 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 {} #{top} #{slave}") + rescue + warn("Waring: fail to call '::safe::tkDelete'") if $DEBUG + begin + @interp._eval("destroy #{top}") + rescue + warn("Waring: fail to destroy toplevel") if $DEBUG + end + end + end + end + end + +end + + +# get target IP +class MultiTkIp + @@CALLBACK_SUBTHREAD = Class.new(Thread){ + def self.new(interp, &blk) + super(interp){|ip| Thread.current[:callback_ip] = ip; blk.call} + end + + @table = TkUtil.untrust(Hash.new{|h,k| h[k] = TkUtil.untrust([])}) + def self.table + @table + end + } + + def self._ip_id_ + __getip._ip_id_ + end + def _ip_id_ + # for RemoteTkIp + '' + end + + def self.__getip + current = Thread.current + if current.kind_of?(@@CALLBACK_SUBTHREAD) + return current[:callback_ip] + end + if TclTkLib.mainloop_thread? != false && current[:callback_ip] + return current[:callback_ip] + end + if current.group == ThreadGroup::Default + @@DEFAULT_MASTER + else + ip = @@IP_TABLE[current.group] + unless ip + fail SecurityError, + "cannot call Tk methods on #{Thread.current.inspect}" + end + ip + end + end +end + + +# aliases of constructor +class << MultiTkIp + alias __new new + private :__new + + def new_master(safe=nil, keys={}, &blk) + if MultiTkIp::WITH_RUBY_VM + #### TODO !!!!!! + fail RuntimeError, + 'sorry, still not support multiple master-interpreters on RubyVM' + end + + if safe.kind_of?(Hash) + keys = safe + elsif safe.kind_of?(Integer) + raise ArgumentError, "unexpected argument(s)" unless keys.kind_of?(Hash) + if !keys.key?(:safe) && !keys.key?('safe') + keys[:safe] = safe + end + elsif safe == nil + # do nothing + else + raise ArgumentError, "unexpected argument(s)" + end + + ip = __new(__getip, nil, keys) + #ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call) if block_given? + if block_given? + #Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call)} + #Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; yield}.call)} + ip._proc_on_safelevel(&blk).call(ip.safe_level) + end + ip + end + + alias new new_master + + def new_slave(safe=nil, keys={}, &blk) + if safe.kind_of?(Hash) + keys = safe + elsif safe.kind_of?(Integer) + raise ArgumentError, "unexpected argument(s)" unless keys.kind_of?(Hash) + if !keys.key?(:safe) && !keys.key?('safe') + keys[:safe] = safe + end + elsif safe == nil + # do nothing + else + raise ArgumentError, "unexpected argument(s)" + end + + ip = __new(__getip, false, keys) + # ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call) if block_given? + if block_given? + #Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call)} + #Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; yield}.call)} + ip._proc_on_safelevel(&blk).call(ip.safe_level) + end + ip + end + alias new_trusted_slave new_slave + + def new_safe_slave(safe=4, keys={}, &blk) + if safe.kind_of?(Hash) + keys = safe + elsif safe.kind_of?(Integer) + raise ArgumentError, "unexpected argument(s)" unless keys.kind_of?(Hash) + if !keys.key?(:safe) && !keys.key?('safe') + keys[:safe] = safe + end + else + raise ArgumentError, "unexpected argument(s)" + end + + ip = __new(__getip, true, keys) + # ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call) if block_given? + if block_given? + #Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call)} + #Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; yield}.call)} + ip._proc_on_safelevel(&blk).call(ip.safe_level) + end + ip + end + alias new_safeTk new_safe_slave +end + + +# get info +class MultiTkIp + def inspect + s = self.to_s.chop! + if self.manipulable? + if master? + if @interp.deleted? + s << ':deleted-master' + else + s << ':master' + end + else + if @interp.deleted? + s << ':deleted-slave' + elsif @interp.safe? + s << ':safe-slave' + else + s << ':trusted-slave' + end + end + end + s << '>' + end + + def master? + if @ip_name + false + else + true + end + end + def self.master? + __getip.master? + end + + def slave? + not master? + end + def self.slave? + not self.master? + end + + def alive? + raise SecurityError, "no permission to manipulate" unless self.manipulable? + begin + return false unless @cmd_receiver.alive? + return false if @interp.deleted? + return false if @interp._invoke('interp', 'exists', '') == '0' + rescue Exception + return false + end + true + end + def self.alive? + __getip.alive? + end + + def path + @ip_name || '' + end + def self.path + __getip.path + end + def ip_name + @ip_name || '' + end + def self.ip_name + __getip.ip_name + end + def to_eval + @ip_name || '' + end + def self.to_eval + __getip.to_eval + end + + def slaves(all = false) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._invoke('interp','slaves').split.map!{|name| + if @slave_ip_tbl.key?(name) + @slave_ip_tbl[name] + elsif all + name + else + nil + end + }.compact! + end + def self.slaves(all = false) + __getip.slaves(all) + end + + def manipulable? + return true if (Thread.current.group == ThreadGroup::Default) + ip = MultiTkIp.__getip + (ip == self) || ip._is_master_of?(@interp) + end + def self.manipulable? + true + end + + def _is_master_of?(tcltkip_obj) + tcltkip_obj.slave_of?(@interp) + end + protected :_is_master_of? +end + + +# instance methods to treat tables +class MultiTkIp + def _tk_cmd_tbl + tbl = {} + MultiTkIp.tk_cmd_tbl.each{|id, ent| tbl[id] = ent if ent.ip == self } + tbl + end + + def _tk_windows + @tk_windows + end + + def _tk_table_list + @tk_table_list + end + + def _add_new_tables + (@@TK_TABLE_LIST.size - @tk_table_list.size).times{ + @tk_table_list << TkUtil.untrust({}) + } + end + + def _init_ip_env(script) + self.eval_proc{script.call(self)} + end + + def _add_tk_procs(name, args, body) + return if slave? + @interp._invoke('proc', name, args, body) if args && body + @interp._invoke('interp', 'slaves').split.each{|slave| + @interp._invoke('interp', 'alias', slave, name, '', name) + } + end + + def _remove_tk_procs(*names) + return if slave? + names.each{|name| + name = name.to_s + + return if @interp.deleted? + @interp._invoke('rename', name, '') + + return if @interp.deleted? + @interp._invoke('interp', 'slaves').split.each{|slave| + return if @interp.deleted? + @interp._invoke('interp', 'alias', slave, name, '') rescue nil + } + } + end + + def _init_ip_internal(init_ip_env, add_tk_procs) + #init_ip_env.each{|script| self.eval_proc{script.call(self)}} + init_ip_env.each{|script| self._init_ip_env(script)} + add_tk_procs.each{|name, args, body| + if master? + @interp._invoke('proc', name, args, body) if args && body + else + @set_alias_proc.call(name) + end + } + end +end + + +# class methods to treat tables +class MultiTkIp + def self.tk_cmd_tbl + @@TK_CMD_TBL + end + def self.tk_windows + __getip._tk_windows + end + def self.tk_object_table(id) + __getip._tk_table_list[id] + end + def self.create_table + if __getip.slave? + begin + raise SecurityError, "slave-IP has no permission creating a new table" + rescue SecurityError => e + #p e.backtrace + # Is called on a Ruby/Tk library? + caller_info = e.backtrace[1] + if caller_info =~ %r{^#{MultiTkIp::BASE_DIR}/(tk|tkextlib)/[^:]+\.rb:} + # Probably, caller is a Ruby/Tk library --> allow creating + else + raise e + end + end + end + + id = @@TK_TABLE_LIST.size + obj = Object.new + @@TK_TABLE_LIST << obj + obj.instance_variable_set(:@id, id) + obj.instance_variable_set(:@mutex, Mutex.new) + obj.instance_eval{ + def self.mutex + @mutex + end + def self.method_missing(m, *args) + MultiTkIp.tk_object_table(@id).__send__(m, *args) + end + } + obj.freeze + @@IP_TABLE.each{|tg, ip| ip._add_new_tables } + return obj + end + + def self.init_ip_env(script = Proc.new) + @@INIT_IP_ENV << script + if __getip.slave? + begin + raise SecurityError, "slave-IP has no permission initializing IP env" + rescue SecurityError => e + #p e.backtrace + # Is called on a Ruby/Tk library? + caller_info = e.backtrace[1] + if caller_info =~ %r{^#{MultiTkIp::BASE_DIR}/(tk|tkextlib)/[^:]+\.rb:} + # Probably, caller is a Ruby/Tk library --> allow creating + else + raise e + end + end + end + + # @@IP_TABLE.each{|tg, ip| + # ip._init_ip_env(script) + # } + @@DEFAULT_MASTER.__init_ip_env__(@@IP_TABLE, script) + end + + def self.add_tk_procs(name, args=nil, body=nil) + if name.kind_of?(Array) # => an array of [name, args, body] + name.each{|param| self.add_tk_procs(*param)} + else + name = name.to_s + @@ADD_TK_PROCS << [name, args, body] + @@IP_TABLE.each{|tg, ip| + ip._add_tk_procs(name, args, body) + } + end + end + + def self.remove_tk_procs(*names) + names.each{|name| + name = name.to_s + @@ADD_TK_PROCS.delete_if{|elem| + elem.kind_of?(Array) && elem[0].to_s == name + } + } + @@IP_TABLE.each{|tg, ip| + ip._remove_tk_procs(*names) + } + end + + def self.init_ip_internal + __getip._init_ip_internal(@@INIT_IP_ENV, @@ADD_TK_PROCS) + end +end + +# for callback operation +class MultiTkIp + def self.cb_entry_class + @@CB_ENTRY_CLASS + end + def self.get_cb_entry(cmd) + @@CB_ENTRY_CLASS.new(__getip, cmd).freeze + end + +=begin + def cb_eval(cmd, *args) + #self.eval_callback{ TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *args)) } + #ret = self.eval_callback{ TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *args)) } + ret = self.eval_callback(*args){|safe, *params| + $SAFE=safe if $SAFE < safe + TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *params)) + } + if ret.kind_of?(Exception) + raise ret + end + ret + end +=end + def cb_eval(cmd, *args) + self.eval_callback(*args, + &_proc_on_safelevel{|*params| + TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *params)) + }) + end +=begin + def cb_eval(cmd, *args) + self.eval_callback(*args){|safe, *params| + $SAFE=safe if $SAFE < safe + # TkUtil.eval_cmd(cmd, *params) + TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *params)) + } + end +=end +=begin + def cb_eval(cmd, *args) + @callback_status[0] ||= TkVariable.new + @callback_status[1] ||= TkVariable.new + st, val = @callback_status + th = Thread.new{ + self.eval_callback(*args){|safe, *params| + #p [status, val, safe, *params] + $SAFE=safe if $SAFE < safe + begin + TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *params)) + rescue TkCallbackContinue + st.value = 4 + rescue TkCallbackBreak + st.value = 3 + rescue TkCallbackReturn + st.value = 2 + rescue Exception => e + val.value = e.message + st.value = 1 + else + st.value = 0 + end + } + } + begin + st.wait + status = st.numeric + retval = val.value + rescue => e + fail e + end + + if status == 1 + fail RuntimeError, retval + elsif status == 2 + fail TkCallbackReturn, "Tk callback returns 'return' status" + elsif status == 3 + fail TkCallbackBreak, "Tk callback returns 'break' status" + elsif status == 4 + fail TkCallbackContinue, "Tk callback returns 'continue' status" + else + '' + end + end +=end + +end + +# pseudo-toplevel operation support +class MultiTkIp + # instance method + def __pseudo_toplevel + ip = MultiTkIp.__getip + (ip == @@DEFAULT_MASTER || ip == self) && + self.__pseudo_toplevel_evaluable? && @pseudo_toplevel[1] + end + + def __pseudo_toplevel=(m) + unless (Thread.current.group == ThreadGroup::Default && + MultiTkIp.__getip == @@DEFAULT_MASTER) + fail SecurityError, "no permission to manipulate" + end + + # if m.kind_of?(Module) && m.respond_to?(:pseudo_toplevel_evaluable?) + if m.respond_to?(:pseudo_toplevel_evaluable?) + @pseudo_toplevel[0] = true + @pseudo_toplevel[1] = m + else + fail ArgumentError, 'fail to set pseudo-toplevel' + end + self + end + + def __pseudo_toplevel_evaluable? + begin + @pseudo_toplevel[0] && @pseudo_toplevel[1].pseudo_toplevel_evaluable? + rescue Exception + false + end + end + + def __pseudo_toplevel_evaluable=(mode) + unless (Thread.current.group == ThreadGroup::Default && + MultiTkIp.__getip == @@DEFAULT_MASTER) + fail SecurityError, "no permission to manipulate" + end + + @pseudo_toplevel[0] = (mode)? true: false + end +end + + +################################################ +# use pseudo-toplevel feature of MultiTkIp ? +if (!defined?(Use_PseudoToplevel_Feature_of_MultiTkIp) || + Use_PseudoToplevel_Feature_of_MultiTkIp) + module MultiTkIp_PseudoToplevel_Evaluable + #def pseudo_toplevel_eval(body = Proc.new) + # Thread.current[:TOPLEVEL] = self + # begin + # body.call + # ensure + # Thread.current[:TOPLEVEL] = nil + # end + #end + + def pseudo_toplevel_evaluable? + @pseudo_toplevel_evaluable + end + + def pseudo_toplevel_evaluable=(mode) + @pseudo_toplevel_evaluable = (mode)? true: false + end + + def self.extended(mod) + mod.__send__(:extend_object, mod) + mod.instance_variable_set('@pseudo_toplevel_evaluable', true) + end + end + + class Object + alias __method_missing_alias_for_MultiTkIp__ method_missing + private :__method_missing_alias_for_MultiTkIp__ + + def method_missing(id, *args) + begin + has_top = (top = MultiTkIp.__getip.__pseudo_toplevel) && + top.respond_to?(:pseudo_toplevel_evaluable?) && + top.pseudo_toplevel_evaluable? && + top.respond_to?(id) + rescue Exception => e + has_top = false + end + + if has_top + top.__send__(id, *args) + else + __method_missing_alias_for_MultiTkIp__(id, *args) + end + end + end +else + # dummy + module MultiTkIp_PseudoToplevel_Evaluable + def pseudo_toplevel_evaluable? + false + end + end +end + + +################################################ +# evaluate a procedure on the proper interpreter +class MultiTkIp + # instance & class method + def _proc_on_safelevel(cmd=nil) # require a block for eval + if cmd + if cmd.kind_of?(Method) + _proc_on_safelevel{|*args| cmd.call(*args)} + else + _proc_on_safelevel(&cmd) + end + else + #Proc.new{|safe, *args| $SAFE=safe if $SAFE < safe; yield(*args)} + Proc.new{|safe, *args| + # avoid security error on Exception objects + untrust_proc = proc{|err| + begin + err.untrust if err.respond_to?(:untrust) + rescue SecurityError + end + err + } + $SAFE=safe if $SAFE < safe; + begin + yield(*args) + rescue Exception => e + fail untrust_proc.call(e) + end + } + end + end + def MultiTkIp._proc_on_safelevel(cmd=nil, &blk) + MultiTkIp.__getip._proc_on_safelevel(cmd, &blk) + end + + def _proc_on_current_safelevel(cmd=nil, &blk) # require a block for eval + safe = $SAFE + cmd = _proc_on_safelevel(cmd, &blk) + Proc.new{|*args| cmd.call(safe, *args)} + end + def MultiTkIp._proc_on_current_safelevel(cmd=nil, &blk) + MultiTkIp.__getip._proc_on_current_safelevel(cmd, &blk) + end + + ###################################### + # instance method + def eval_proc_core(req_val, cmd, *args) + # check + raise SecurityError, "no permission to manipulate" unless self.manipulable? + unless cmd.kind_of?(Proc) || cmd.kind_of?(Method) + raise RuntimeError, "A Proc/Method object is expected for the 'cmd' argument" + end + + # on IP thread + if @cmd_receiver == Thread.current || + (!req_val && TclTkLib.mainloop_thread? != false) # callback + begin + ret = cmd.call(safe_level, *args) + rescue SystemExit => e + # exit IP + warn("Warning: "+ e.inspect + " on " + self.inspect) if $DEBUG + begin + self._eval_without_enc('exit') + rescue Exception => e + end + self.delete + ret = nil + rescue Exception => e + if $DEBUG + warn("Warning: " + e.class.inspect + + ((e.message.length > 0)? ' "' + e.message + '"': '') + + " on " + self.inspect) + end +=begin + begin + bt = _toUTF8(e.backtrace.join("\n")) + bt.instance_variable_set(:@encoding, 'utf-8') + rescue Exception + bt = e.backtrace.join("\n") + end + begin + @interp._set_global_var('errorInfo', bt) + rescue Exception + end +=end + ret = e + end + return ret + end + + # send cmd to the proc-queue + unless req_val + begin + @cmd_queue.enq([nil, cmd, *args]) + rescue Exception => e + # ignore + if $DEBUG + warn("Warning: " + e.class.inspect + + ((e.message.length > 0)? ' "' + e.message + '"': '') + + " on " + self.inspect) + end + return e + end + return nil + end + + # send and get return value by exception + begin + @cmd_queue.enq([Thread.current, cmd, *args]) + Thread.stop + rescue MultiTkIp_OK => ret + # return value + return ret.value + rescue SystemExit => e + # exit IP + warn("Warning: " + e.inspect + " on " + self.inspect) if $DEBUG + begin + self._eval_without_enc('exit') + rescue Exception + end + if !self.deleted? && !safe? && allow_ruby_exit? + self.delete + fail e + else + self.delete + end + rescue Exception => e + if $DEBUG + warn("Warning: " + e.class.inspect + + ((e.message.length > 0)? ' "' + e.message + '"': '') + + " on " + self.inspect) + end + return e + end + return nil + end + private :eval_proc_core + +if false && WITH_RUBY_VM ### Ruby 1.9 + # Not stable, so disable this feature + def eval_callback(*args) + if block_given? + cmd = Proc.new + else + cmd = args.shift + end + begin + if @@CALLBACK_SUBTHREAD.table[self].index(Thread.current) + last_th = nil + else + last_th = @@CALLBACK_SUBTHREAD.table[self][-1] + end + @@CALLBACK_SUBTHREAD.new(self){ + @@CALLBACK_SUBTHREAD.table[self] << Thread.current + begin + last_th.join if last_th + eval_proc_core(false, cmd, *args) + rescue Exception=>e + e + ensure + @@CALLBACK_SUBTHREAD.table[self].delete(Thread.current) + end + } + end + end +else ### Ruby 1.8 + def eval_callback(*args) + if block_given? + cmd = Proc.new + else + cmd = args.shift + end + begin + eval_proc_core(false, cmd, *args) + rescue Exception=>e + e + ensure + end + end +end + + def eval_proc(*args, &blk) + if block_given? + cmd = _proc_on_safelevel(&blk) + else + unless (cmd = args.shift) + fail ArgumentError, "A Proc or Method object is expected for 1st argument" + end + cmd = _proc_on_safelevel(&cmd) + end + if TclTkLib.mainloop_thread? == true + # call from eventloop + current = Thread.current + backup_ip = current[:callback_ip] + current[:callback_ip] = self + begin + eval_proc_core(false, cmd, *args) + ensure + current[:callback_ip] = backup_ip + end + else + eval_proc_core(true, + proc{|safe, *params| + Thread.new{cmd.call(safe, *params)}.value + }, + *args) + end + end +=begin + def eval_proc(*args) + # The scope of the eval-block of 'eval_proc' method is different from + # the external. If you want to pass local values to the eval-block, + # use arguments of eval_proc method. They are passed to block-arguments. + if block_given? + cmd = Proc.new + else + unless (cmd = args.shift) + fail ArgumentError, "A Proc or Method object is expected for 1st argument" + end + end + if TclTkLib.mainloop_thread? == true + # call from eventloop + current = Thread.current + backup_ip = current[:callback_ip] + current[:callback_ip] = self + begin + eval_proc_core(false, + proc{|safe, *params| + $SAFE=safe if $SAFE < safe + cmd.call(*params) + }, *args) + ensure + current[:callback_ip] = backup_ip + end + else + eval_proc_core(true, + proc{|safe, *params| + $SAFE=safe if $SAFE < safe + Thread.new(*params, &cmd).value + }, + *args) + end + end +=end + alias call eval_proc + + def bg_eval_proc(*args) + if block_given? + cmd = Proc.new + else + unless (cmd = args.shift) + fail ArgumentError, "A Proc or Method object is expected for 1st argument" + end + end + Thread.new{ + eval_proc(cmd, *args) +=begin + eval_proc_core(false, + proc{|safe, *params| + $SAFE=safe if $SAFE < safe + Thread.new(*params, &cmd).value + }, + safe_level, *args) +=end + } + end + alias background_eval_proc bg_eval_proc + alias thread_eval_proc bg_eval_proc + alias bg_call bg_eval_proc + alias background_call bg_eval_proc + + def eval_string(cmd, *eval_args) + # cmd string ==> proc + unless cmd.kind_of?(String) + raise RuntimeError, "A String object is expected for the 'cmd' argument" + end + + eval_proc_core(true, + proc{|safe| + Kernel.eval("$SAFE=#{safe} if $SAFE < #{safe};" << cmd, + *eval_args) + }) + end + alias eval_str eval_string + + def bg_eval_string(cmd, *eval_args) + # cmd string ==> proc + unless cmd.kind_of?(String) + raise RuntimeError, "A String object is expected for the 'cmd' argument" + end + Thread.new{ + eval_proc_core(true, + proc{|safe| + Kernel.eval("$SAFE=#{safe} if $SAFE < #{safe};" << cmd, + *eval_args) + }) + } + end + alias background_eval_string bg_eval_string + alias bg_eval_str bg_eval_string + alias background_eval_str bg_eval_string + + def eval(*args, &blk) + if block_given? + eval_proc(*args, &blk) + elsif args[0] + if args[0].respond_to?(:call) + eval_proc(*args) + else + eval_string(*args) + end + else + fail ArgumentError, "no argument to eval" + end + end + + def bg_eval(*args, &blk) + if block_given? + bg_eval_proc(*args, &blk) + elsif args[0] + if args[0].respond_to?(:call) + bg_eval_proc(*args) + else + bg_eval_string(*args) + end + else + fail ArgumentError, "no argument to eval" + end + end + alias background_eval bg_eval +end + +class << MultiTkIp + # class method + def eval_proc(*args, &blk) + # class ==> interp object + __getip.eval_proc(*args, &blk) + end + alias call eval_proc + + def bg_eval_proc(*args, &blk) + # class ==> interp object + __getip.bg_eval_proc(*args, &blk) + end + alias background_eval_proc bg_eval_proc + alias thread_eval_proc bg_eval_proc + alias bg_call bg_eval_proc + alias background_call bg_eval_proc + + def eval_string(cmd, *eval_args) + # class ==> interp object + __getip.eval_string(cmd, *eval_args) + end + alias eval_str eval_string + + def bg_eval_string(cmd, *eval_args) + # class ==> interp object + __getip.bg_eval_string(cmd, *eval_args) + end + alias background_eval_string bg_eval_string + alias bg_eval_str bg_eval_string + alias background_eval_str bg_eval_string + + def eval(*args, &blk) + # class ==> interp object + __getip.eval(*args, &blk) + end + def bg_eval(*args, &blk) + # class ==> interp object + __getip.bg_eval(*args, &blk) + end + alias background_eval bg_eval +end + + +# event loop +# all master/slave IPs are controled by only one event-loop +class MultiTkIp + def self.default_master? + __getip == @@DEFAULT_MASTER + end +end +class << MultiTkIp + def mainloop(check_root = true) + __getip.mainloop(check_root) + end + def mainloop_watchdog(check_root = true) + __getip.mainloop_watchdog(check_root) + end + def do_one_event(flag = TclTkLib::EventFlag::ALL) + __getip.do_one_event(flag) + end + def 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) + TclTkLib.mainloop_abort_on_exception=(mode) + end + def set_eventloop_tick(tick) + __getip.set_eventloop_tick(tick) + end + def get_eventloop_tick + __getip.get_eventloop_tick + end + def set_no_event_wait(tick) + __getip.set_no_event_wait(tick) + end + def get_no_event_wait + __getip.get_no_event_wait + end + def set_eventloop_weight(loop_max, no_event_tick) + __getip.set_eventloop_weight(loop_max, no_event_tick) + end + def get_eventloop_weight + __getip.get_eventloop_weight + end +end + +# class methods to delegate to TclTkIp +class << MultiTkIp + def method_missing(id, *args) + __getip.__send__(id, *args) + end + + def make_safe + __getip.make_safe + end + + def safe? + __getip.safe? + end + + def safe_base? + begin + __getip.safe_base? + rescue + false + end + end + + def allow_ruby_exit? + __getip.allow_ruby_exit? + end + + def allow_ruby_exit= (mode) + __getip.allow_ruby_exit = mode + end + + def delete + __getip.delete + end + + def deleted? + __getip.deleted? + end + + def has_mainwindow? + __getip.has_mainwindow? + end + + def invalid_namespace? + __getip.invalid_namespace? + end + + def abort(msg = nil) + __getip.abort(msg) + end + + def exit(st = true) + __getip.exit(st) + end + + def exit!(st = false) + __getip.exit!(st) + end + + def restart(app_name = nil, keys = {}) + init_ip_internal + + __getip._invoke('set', 'argv0', app_name) if app_name + if keys.kind_of?(Hash) + __getip._invoke('set', 'argv', _keys2opts(keys)) + end + + __getip.restart + end + + def _eval(str) + __getip._eval(str) + end + + def _invoke(*args) + __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=nil) + __getip._toUTF8(str, encoding) + end + + def _fromUTF8(str, encoding=nil) + __getip._fromUTF8(str, encoding) + end + + def _thread_vwait(var) + __getip._thread_vwait(var) + end + + def _thread_tkwait(mode, target) + __getip._thread_tkwait(mode, target) + end + + 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 _make_menu_embeddable(menu_path) + __getip._make_menu_embeddable(menu_path) + 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 + + def _create_console + __getip._create_console + end +end + + +# wrap methods on TclTkLib : not permit calling TclTkLib module methods +class << TclTkLib + def mainloop(check_root = true) + MultiTkIp.mainloop(check_root) + end + def mainloop_watchdog(check_root = true) + MultiTkIp.mainloop_watchdog(check_root) + end + 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 set_eventloop_tick(tick) + MultiTkIp.set_eventloop_tick(tick) + end + def get_eventloop_tick + MultiTkIp.get_eventloop_tick + end + def set_no_event_wait(tick) + MultiTkIp.set_no_event_wait(tick) + end + def get_no_event_wait + MultiTkIp.get_no_event_wait + end + def set_eventloop_weight(loop_max, no_event_tick) + MultiTkIp.set_eventloop_weight(loop_max, no_event_tick) + end + def get_eventloop_weight + MultiTkIp.get_eventloop_weight + end + def restart(*args) + MultiTkIp.restart(*args) + 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) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + + if WITH_RUBY_VM ### Ruby 1.9 !!!!!!!!!!! + return @interp_thread.value if @interp_thread + end + + #return self if self.slave? + #return self if self != @@DEFAULT_MASTER + if self != @@DEFAULT_MASTER + if @wait_on_mainloop[0] + begin + @wait_on_mainloop[1] += 1 + if $SAFE >= 4 + _receiver_mainloop(check_root).join + else + @cmd_queue.enq([@system, 'call_mainloop', + Thread.current, check_root]) + Thread.stop + end + rescue MultiTkIp_OK => ret + # return value + if ret.value.kind_of?(Thread) + return ret.value.value + else + return ret.value + end + rescue SystemExit => e + # exit IP + warn("Warning: " + e.inspect + " on " + self.inspect) if $DEBUG + begin + self._eval_without_enc('exit') + rescue Exception + end + self.delete + rescue StandardError => e + if $DEBUG + warn("Warning: " + e.class.inspect + + ((e.message.length > 0)? ' "' + e.message + '"': '') + + " on " + self.inspect) + end + return e + rescue Exception => e + return e + ensure + @wait_on_mainloop[1] -= 1 + end + end + return + end + + unless restart_on_dead + @wait_on_mainloop[1] += 1 +=begin + begin + @interp.mainloop(check_root) + rescue StandardError => e + if $DEBUG + warn("Warning: " + e.class.inspect + + ((e.message.length > 0)? ' "' + e.message + '"': '') + + " on " + self.inspect) + end + end +=end + begin + @interp.mainloop(check_root) + ensure + @wait_on_mainloop[1] -= 1 + end + else + loop do + break unless self.alive? + if check_root + begin + break if TclTkLib.num_of_mainwindows == 0 + rescue StandardError + break + end + end + break if @interp.deleted? + begin + @wait_on_mainloop[1] += 1 + @interp.mainloop(check_root) + rescue StandardError => e + if TclTkLib.mainloop_abort_on_exception != nil + #STDERR.print("Warning: Tk mainloop receives ", $!.class.inspect, + # " exception (ignore) : ", $!.message, "\n"); + if $DEBUG + warn("Warning: Tk mainloop receives " << e.class.inspect << + " exception (ignore) : " << e.message); + end + end + #raise e + rescue Exception => e +=begin + if TclTkLib.mainloop_abort_on_exception != nil + #STDERR.print("Warning: Tk mainloop receives ", $!.class.inspect, + # " exception (ignore) : ", $!.message, "\n"); + if $DEBUG + warn("Warning: Tk mainloop receives " << e.class.inspect << + " exception (ignore) : " << e.message); + end + end +=end + raise e + ensure + @wait_on_mainloop[1] -= 1 + Thread.pass # avoid eventloop conflict + end + end + end + self + end + + def make_safe + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp.make_safe + end + + def safe? + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp.safe? + end + + def safe_base? + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @safe_base + end + + def allow_ruby_exit? + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp.allow_ruby_exit? + end + + def allow_ruby_exit= (mode) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp.allow_ruby_exit = mode + end + + def delete + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @slave_ip_tbl.each{|name, subip| + _destroy_slaves_of_slaveIP(subip) +=begin + begin + subip._invoke('destroy', '.') unless subip.deleted? + rescue Exception + end +=end + begin + # subip._eval_without_enc("foreach i [after info] {after cancel $i}") + unless subip.deleted? + after_ids = subip._eval_without_enc("after info") + subip._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}") + end + rescue Exception + end + + # safe_base? + if @interp._eval_without_enc("catch {::safe::interpConfigure #{name}}") == '0' + begin + @interp._eval_without_enc("::safe::interpDelete #{name}") + rescue Exception + else + next if subip.deleted? + end + end + if subip.respond_to?(:safe_base?) && subip.safe_base? && + !subip.deleted? + # do 'exit' to call the delete_hook procedure + begin + subip._eval_without_enc('exit') + rescue Exception + end + else + begin + subip.delete unless subip.deleted? + rescue Exception + end + end + } + + begin + # @interp._eval_without_enc("foreach i [after info] {after cancel $i}") + after_ids = @interp._eval_without_enc("after info") + @interp._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}") + rescue Exception + end + + begin + @interp._invoke('destroy', '.') unless @interp.deleted? + rescue Exception + end + + if @safe_base && !@interp.deleted? + # do 'exit' to call the delete_hook procedure + @interp._eval_without_enc('exit') + end + @interp.delete + self + end + + def deleted? + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp.deleted? + end + + def has_mainwindow? + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp.has_mainwindow? + end + + def invalid_namespace? + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp.invalid_namespace? + end + + def abort(msg = nil) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + if master? && !safe? && allow_ruby_exit? + if msg + Kernel.abort(msg) + else + Kernel.abort + end + else + # ignore msg + delete + 1 + end + end + + def exit(st = true) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + if master? && !safe? && allow_ruby_exit? + Kernel.exit(st) + else + delete + st + end + end + + def exit!(st = false) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + if master? && !safe? && allow_ruby_exit? + Kernel.exit!(st) + else + delete + st + end + end + + def restart(app_name = nil, keys = {}) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + + _init_ip_internal(@@INIT_IP_ENV, @@ADD_TK_PROCS) + + @interp._invoke('set', 'argv0', app_name) if app_name + if keys.kind_of?(Hash) + @interp._invoke('set', 'argv', _keys2opts(keys)) + end + + @interp.restart + end + + def __eval(str) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp.__eval(str) + end + + def __invoke(*args) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp.__invoke(*args) + end + + def _eval(str) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._eval(str) + end + + def _invoke(*args) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._invoke(*args) + end + + def _eval_without_enc(str) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._eval_without_enc(str) + end + + def _invoke_without_enc(*args) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._invoke_without_enc(*args) + end + + def _eval_with_enc(str) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._eval_with_enc(str) + end + + def _invoke_with_enc(*args) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._invoke_with_enc(*args) + end + + def _toUTF8(str, encoding=nil) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._toUTF8(str, encoding) + end + + def _fromUTF8(str, encoding=nil) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._fromUTF8(str, encoding) + end + + def _thread_vwait(var) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._thread_vwait(var) + end + + def _thread_tkwait(mode, target) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._thread_tkwait(mode, target) + end + + def _return_value + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._return_value + end + + def _get_variable(var, flag) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._get_variable(var, flag) + end + def _get_variable2(var, idx, flag) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._get_variable2(var, idx, flag) + end + def _set_variable(var, value, flag) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._set_variable(var, value, flag) + end + def _set_variable2(var, idx, value, flag) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._set_variable2(var, idx, value, flag) + end + def _unset_variable(var, flag) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._unset_variable(var, flag) + end + def _unset_variable2(var, idx, flag) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._unset_variable2(var, idx, flag) + end + + def _get_global_var(var) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._get_global_var(var) + end + def _get_global_var2(var, idx) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._get_global_var2(var, idx) + end + def _set_global_var(var, value) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._set_global_var(var, value) + end + def _set_global_var2(var, idx, value) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._set_global_var2(var, idx, value) + end + def _unset_global_var(var) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._unset_global_var(var) + end + def _unset_global_var2(var, idx) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._unset_global_var2(var, idx) + end + + def _make_menu_embeddable(menu_path) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._make_menu_embeddable(menu_path) + end + + def _split_tklist(str) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._split_tklist(str) + end + def _merge_tklist(*args) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._merge_tklist(*args) + end + def _conv_listelement(arg) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._conv_listelement(arg) + end +end + + +# interp command support +class MultiTkIp + def _lst2ary(str) + return [] if str == "" + idx = str.index('{') + while idx and idx > 0 and str[idx-1] == ?\\ + idx = str.index('{', idx+1) + end + return str.split unless idx + + list = str[0,idx].split + str = str[idx+1..-1] + i = -1 + brace = 1 + str.each_byte {|c| + c = c.chr + i += 1 + brace += 1 if c == '{' + brace -= 1 if c == '}' + break if brace == 0 + } + if i == 0 + list.push '' + elsif str[0, i] == ' ' + list.push ' ' + else + list.push str[0..i-1] + end + #list += _lst2ary(str[i+1..-1]) + list.concat(_lst2ary(str[i+1..-1])) + list + end + private :_lst2ary + + def _slavearg(slave) + if slave.kind_of?(MultiTkIp) + slave.path + elsif slave.kind_of?(String) + slave + else + slave.to_s + end + end + private :_slavearg + + def alias_info(slave, cmd_name) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + _lst2ary(@interp._invoke('interp', 'alias', _slavearg(slave), cmd_name)) + end + def self.alias_info(slave, cmd_name) + __getip.alias_info(slave, cmd_name) + end + + def alias_delete(slave, cmd_name) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._invoke('interp', 'alias', _slavearg(slave), cmd_name, '') + self + end + def self.alias_delete(slave, cmd_name) + __getip.alias_delete(slave, cmd_name) + self + end + + def def_alias(slave, new_cmd, org_cmd, *args) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + ret = @interp._invoke('interp', 'alias', _slavearg(slave), new_cmd, + '', org_cmd, *args) + (ret == new_cmd)? self: nil + end + def self.def_alias(slave, new_cmd, org_cmd, *args) + ret = __getip.def_alias(slave, new_cmd, org_cmd, *args) + (ret == new_cmd)? self: nil + end + + def aliases(slave = '') + raise SecurityError, "no permission to manipulate" unless self.manipulable? + _lst2ary(@interp._invoke('interp', 'aliases', _slavearg(slave))) + end + def self.aliases(slave = '') + __getip.aliases(slave) + end + + def delete_slaves(*args) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + slaves = args.collect{|s| _slavearg(s)} + @interp._invoke('interp', 'delete', *slaves) if slaves.size > 0 + self + end + def self.delete_slaves(*args) + __getip.delete_slaves(*args) + self + end + + def exist?(slave = '') + raise SecurityError, "no permission to manipulate" unless self.manipulable? + ret = @interp._invoke('interp', 'exists', _slavearg(slave)) + (ret == '1')? true: false + end + def self.exist?(slave = '') + __getip.exist?(slave) + end + + def delete_cmd(slave, cmd) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + slave_invoke = @interp._invoke('list', 'rename', cmd, '') + @interp._invoke('interp', 'eval', _slavearg(slave), slave_invoke) + self + end + def self.delete_cmd(slave, cmd) + __getip.delete_cmd(slave, cmd) + self + end + + def expose_cmd(slave, cmd, aliasname = nil) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + if aliasname + @interp._invoke('interp', 'expose', _slavearg(slave), cmd, aliasname) + else + @interp._invoke('interp', 'expose', _slavearg(slave), cmd) + end + self + end + def self.expose_cmd(slave, cmd, aliasname = nil) + __getip.expose_cmd(slave, cmd, aliasname) + self + end + + def hide_cmd(slave, cmd, aliasname = nil) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + if aliasname + @interp._invoke('interp', 'hide', _slavearg(slave), cmd, aliasname) + else + @interp._invoke('interp', 'hide', _slavearg(slave), cmd) + end + self + end + def self.hide_cmd(slave, cmd, aliasname = nil) + __getip.hide_cmd(slave, cmd, aliasname) + self + end + + def hidden_cmds(slave = '') + raise SecurityError, "no permission to manipulate" unless self.manipulable? + _lst2ary(@interp._invoke('interp', 'hidden', _slavearg(slave))) + end + def self.hidden_cmds(slave = '') + __getip.hidden_cmds(slave) + end + + def invoke_hidden(slave, cmd, *args) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + if args[-1].kind_of?(Hash) + keys = _symbolkey2str(args.pop) + else + keys = [] + end + keys << _slavearg(slave) + if Tk::TCL_MAJOR_VERSION > 8 || + (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION >= 5) + keys << '--' + end + keys << cmd + keys.concat(args) + @interp._invoke('interp', 'invokehidden', *keys) + end + def self.invoke_hidden(slave, cmd, *args) + __getip.invoke_hidden(slave, cmd, *args) + end + + def invoke_hidden_on_global(slave, cmd, *args) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + if args[-1].kind_of?(Hash) + keys = _symbolkey2str(args.pop) + else + keys = [] + end + keys << _slavearg(slave) + keys << '-global' + if Tk::TCL_MAJOR_VERSION > 8 || + (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION >= 5) + keys << '--' + end + keys << cmd + keys.concat(args) + @interp._invoke('interp', 'invokehidden', *keys) + end + def self.invoke_hidden_on_global(slave, cmd, *args) + __getip.invoke_hidden_on_global(slave, cmd, *args) + end + + def invoke_hidden_on_namespace(slave, ns, cmd, *args) + # for Tcl8.5 or later + raise SecurityError, "no permission to manipulate" unless self.manipulable? + if args[-1].kind_of?(Hash) + keys = _symbolkey2str(args.pop) + else + keys = [] + end + keys << _slavearg(slave) + keys << '-namespace' << TkComm._get_eval_string(ns) + keys << '--' << cmd + keys.concat(args) + @interp._invoke('interp', 'invokehidden', *keys) + end + def self.invoke_hidden_on_namespace(slave, ns, cmd, *args) + __getip.invoke_hidden_on_namespace(slave, ns, cmd, *args) + end + + def mark_trusted(slave = '') + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._invoke('interp', 'marktrusted', _slavearg(slave)) + self + end + def self.mark_trusted(slave = '') + __getip.mark_trusted(slave) + self + end + + def set_bgerror_handler(cmd = Proc.new, slave = nil, &b) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + + unless TkComm._callback_entry?(cmd) + if !slave && b + slave = cmd + cmd = Proc.new(&b) + end + end + slave = '' unless slave + + @interp._invoke('interp', 'bgerror', _slavearg(slave), cmd) + end + def self.bgerror(cmd = Proc.new, slave = nil, &b) + __getip.bgerror(cmd, slave, &b) + end + + def get_bgerror_handler(slave = '') + raise SecurityError, "no permission to manipulate" unless self.manipulable? + procedure(@interp._invoke('interp', 'bgerror', _slavearg(slave))) + end + def self.bgerror(slave = '') + __getip.bgerror(slave) + end + + def set_limit(limit_type, slave = '', opts = {}) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._invoke('interp', 'limit', _slavearg(slave), limit_type, opts) + end + def self.set_limit(limit_type, slave = '', opts = {}) + __getip.set_limit(limit_type, slave, opts) + end + + def get_limit(limit_type, slave = '', slot = nil) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + + if slot + num_or_str(@interp._invoke('interp', 'limit', _slavearg(slave), + limit_type, slot)) + else + l = @interp._split_tklist(@interp._invoke_without_enc('interp', 'limit', + _slavearg(slave), + limit_type)) + l.map!{|s| _fromUTF8(s)} + r = {} + until l.empty? + key = l.shift[1..-1] + val = l.shift + val = num_or_str(val) if val + r[key] = val + end + r + end + end + def self.get_limit(limit_type, slave = '', slot = nil) + __getip.get_limit(limit_type, slave, slot) + end + + def recursion_limit(slave = '', limit = None) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + 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 = '') + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._invoke('interp', 'target', _slavearg(slave), aliascmd) + end + def self.alias_target(aliascmd, slave = '') + __getip.alias_target(aliascmd, slave) + end + + def share_stdin(dist, src = '') + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._invoke('interp', 'share', src, 'stdin', dist) + self + end + def self.share_stdin(dist, src = '') + __getip.share_stdin(dist, src) + self + end + + def share_stdout(dist, src = '') + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._invoke('interp', 'share', src, 'stdout', dist) + self + end + def self.share_stdout(dist, src = '') + __getip.share_stdout(dist, src) + self + end + + def share_stderr(dist, src = '') + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._invoke('interp', 'share', src, 'stderr', dist) + self + end + def self.share_stderr(dist, src = '') + __getip.share_stderr(dist, src) + self + end + + def transfer_stdin(dist, src = '') + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._invoke('interp', 'transfer', src, 'stdin', dist) + self + end + def self.transfer_stdin(dist, src = '') + __getip.transfer_stdin(dist, src) + self + end + + def transfer_stdout(dist, src = '') + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._invoke('interp', 'transfer', src, 'stdout', dist) + self + end + def self.transfer_stdout(dist, src = '') + __getip.transfer_stdout(dist, src) + self + end + + def transfer_stderr(dist, src = '') + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._invoke('interp', 'transfer', src, 'stderr', dist) + self + end + def self.transfer_stderr(dist, src = '') + __getip.transfer_stderr(dist, src) + self + end + + def share_stdio(dist, src = '') + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._invoke('interp', 'share', src, 'stdin', dist) + @interp._invoke('interp', 'share', src, 'stdout', dist) + @interp._invoke('interp', 'share', src, 'stderr', dist) + self + end + def self.share_stdio(dist, src = '') + __getip.share_stdio(dist, src) + self + end + + def transfer_stdio(dist, src = '') + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._invoke('interp', 'transfer', src, 'stdin', dist) + @interp._invoke('interp', 'transfer', src, 'stdout', dist) + @interp._invoke('interp', 'transfer', src, 'stderr', dist) + self + end + def self.transfer_stdio(dist, src = '') + __getip.transfer_stdio(dist, src) + self + end +end + + +# Safe Base :: manipulating safe interpreter +class MultiTkIp + def safeip_configure(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 + ' ' + _keys2opts(slot)) + 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' +=begin + if conf[1] =~ /^rb_out\S* (c(_\d+_)?\d+)/ + ret[conf[0][1..-1]] = MultiTkIp._tk_cmd_tbl[$1] +=end + if conf[1] =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/ + ret[conf[0][1..-1]] = MultiTkIp._tk_cmd_tbl[$4] + 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' +=begin + if v =~ /^rb_out\S* (c(_\d+_)?\d+)/ + ret[k[1..-1]] = MultiTkIp._tk_cmd_tbl[$1] +=end + if v =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/ + ret[k[1..-1]] = MultiTkIp._tk_cmd_tbl[$4] + else + ret[k[1..-1]] = v + end + else + ret[k[1..-1]] = v + end + } + end + ret + end + + def safeip_delete + ip = MultiTkIp.__getip + ip._eval("::safe::interpDelete " + @ip_name) + end + + def safeip_add_to_access_path(dir) + ip = MultiTkIp.__getip + ip._eval("::safe::interpAddToAccessPath #{@ip_name} #{dir}") + end + + def safeip_find_in_access_path(dir) + ip = MultiTkIp.__getip + ip._eval("::safe::interpFindInAccessPath #{@ip_name} #{dir}") + end + + def safeip_set_log_cmd(cmd = Proc.new) + ip = MultiTkIp.__getip + ip._eval("::safe::setLogCmd #{@ip_name} #{_get_eval_string(cmd)}") + end +end + + +# encoding convert +class << MultiTkIp + def encoding_table + __getip.encoding_table + end + + def force_default_encoding=(mode) + __getip.force_default_encoding=(mode) + end + + def force_default_encoding? + __getip.force_default_encoding? + end + + def default_encoding=(enc) + __getip.default_encoding=(enc) + end + + def encoding=(enc) + __getip.encoding=(enc) + end + + def encoding_name + __getip.encoding_name + end + + def encoding_obj + __getip.encoding_obj + end + alias encoding encoding_name + alias default_encoding encoding_name + + def encoding_convertfrom(str, enc=None) + __getip.encoding_convertfrom(str, enc) + end + alias encoding_convert_from encoding_convertfrom + + def encoding_convertto(str, enc=None) + __getip.encoding_convertto(str, enc) + end + alias encoding_convert_to encoding_convertto +end +class MultiTkIp + def encoding_table + @interp.encoding_table + end + + def force_default_encoding=(mode) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp.force_default_encoding = mode + end + def force_default_encoding? + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp.force_default_encoding? + end + + def default_encoding=(enc) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp.default_encoding = enc + end + + def encoding=(enc) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp.encoding = enc + end + def encoding_name + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp.encoding_name + end + def encoding_obj + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp.encoding_obj + end + alias encoding encoding_name + alias default_encoding encoding_name + + def encoding_convertfrom(str, enc=None) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp.encoding_convertfrom(str, enc) + end + alias encoding_convert_from encoding_convertfrom + + def encoding_convertto(str, enc=None) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp.encoding_convertto(str, enc) + end + alias encoding_convert_to encoding_convertto +end + + +# remove methods for security +=begin +class MultiTkIp + INTERP_THREAD = @@DEFAULT_MASTER.instance_variable_get('@interp_thread') + INTERP_MUTEX = INTERP_THREAD[:mutex] + INTERP_ROOT_CHECK = INTERP_THREAD[:root_check] + + # undef_method :instance_eval + undef_method :instance_variable_get + undef_method :instance_variable_set +end + +module TkCore + if MultiTkIp::WITH_RUBY_VM && + ! MultiTkIp::RUN_EVENTLOOP_ON_MAIN_THREAD ### check Ruby 1.9 !!!!!!! + INTERP_THREAD = MultiTkIp::INTERP_THREAD + INTERP_MUTEX = MultiTkIp::INTERP_MUTEX + INTERP_ROOT_CHECK = MultiTkIp::INTERP_ROOT_CHECK + end +end +class MultiTkIp + remove_const(:INTERP_THREAD) + remove_const(:INTERP_MUTEX) + remove_const(:INTERP_ROOT_CHECK) +end +=end +if MultiTkIp::WITH_RUBY_VM && + ! MultiTkIp::RUN_EVENTLOOP_ON_MAIN_THREAD ### check Ruby 1.9 !!!!!!! + class MultiTkIp + INTERP_THREAD = @@DEFAULT_MASTER.instance_variable_get('@interp_thread') + INTERP_THREAD_STATUS = INTERP_THREAD[:status] + INTERP_MUTEX = INTERP_THREAD[:mutex] + INTERP_ROOT_CHECK = INTERP_THREAD[:root_check] + end + module TkCore + INTERP_THREAD = MultiTkIp::INTERP_THREAD + INTERP_THREAD_STATUS = MultiTkIp::INTERP_THREAD_STATUS + INTERP_MUTEX = MultiTkIp::INTERP_MUTEX + INTERP_ROOT_CHECK = MultiTkIp::INTERP_ROOT_CHECK + end + class MultiTkIp + remove_const(:INTERP_THREAD) + remove_const(:INTERP_THREAD_STATUS) + remove_const(:INTERP_MUTEX) + remove_const(:INTERP_ROOT_CHECK) + end +end + +class MultiTkIp + # undef_method :instance_eval + undef_method :instance_variable_get + undef_method :instance_variable_set +end +# end of MultiTkIp definition + +# defend against modification +#MultiTkIp.freeze +#TclTkLib.freeze + +######################################## +# start Tk which depends on MultiTkIp +module TkCore + INTERP = MultiTkIp +end +require 'tk' diff --git a/jni/ruby/ext/tk/lib/remote-tk.rb b/jni/ruby/ext/tk/lib/remote-tk.rb new file mode 100644 index 0000000..443d660 --- /dev/null +++ b/jni/ruby/ext/tk/lib/remote-tk.rb @@ -0,0 +1,530 @@ +# +# remote-tk.rb - supports to control remote Tk interpreters +# by Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + +if defined? MultiTkIp + fail RuntimeError, "'remote-tk' library must be required before requiring 'multi-tk'" +end + +class MultiTkIp; end +class RemoteTkIp < MultiTkIp; end + +class MultiTkIp + @@IP_TABLE = TkUtil.untrust({}) unless defined?(@@IP_TABLE) + @@TK_TABLE_LIST = TkUtil.untrust([]) unless defined?(@@TK_TABLE_LIST) + def self._IP_TABLE; @@IP_TABLE; end + def self._TK_TABLE_LIST; @@TK_TABLE_LIST; end + + @flag = true + def self._DEFAULT_MASTER + # work only once + if @flag + @flag = nil + @@DEFAULT_MASTER + else + nil + end + end +end +class RemoteTkIp + @@IP_TABLE = MultiTkIp._IP_TABLE unless defined?(@@IP_TABLE) + @@TK_TABLE_LIST = MultiTkIp._TK_TABLE_LIST unless defined?(@@TK_TABLE_LIST) +end +class << MultiTkIp + undef _IP_TABLE + undef _TK_TABLE_LIST +end + +require 'multi-tk' + +class RemoteTkIp + if defined?(@@DEFAULT_MASTER) + MultiTkIp._DEFAULT_MASTER + else + @@DEFAULT_MASTER = MultiTkIp._DEFAULT_MASTER + end +end + + +############################### + +class << RemoteTkIp + undef new_master, new_slave, new_safe_slave + undef new_trusted_slave, new_safeTk + + def new(*args, &b) + ip = __new(*args) + ip.eval_proc(&b) if b + ip + end +end + +class RemoteTkIp + def initialize(remote_ip, displayof=nil, timeout=5) + if $SAFE >= 4 + fail SecurityError, "cannot access another interpreter at level #{$SAFE}" + end + + @interp = MultiTkIp.__getip + if @interp.safe? + fail SecurityError, "safe-IP cannot create RemoteTkIp" + end + + + @interp.allow_ruby_exit = false + @appname = @interp._invoke('tk', 'appname') + @remote = remote_ip.to_s.dup.freeze + if displayof.kind_of?(TkWindow) + @displayof = displayof.path.dup.freeze + else + @displayof = nil + end + if self.deleted? + fail RuntimeError, "no Tk application named \"#{@remote}\"" + end + + @tk_windows = {} + @tk_table_list = [] + @slave_ip_tbl = {} + @slave_ip_top = {} + + @force_default_encoding ||= TkUtil.untrust([false]) + @encoding ||= TkUtil.untrust([nil]) + def @encoding.to_s; self.join(nil); end + + TkUtil.untrust(@tk_windows) unless @tk_windows.tainted? + TkUtil.untrust(@tk_table_list) unless @tk_table_list.tainted? + TkUtil.untrust(@slave_ip_tbl) unless @slave_ip_tbl.tainted? + TkUtil.untrust(@slave_ip_top) unless @slave_ip_top.tainted? + + @system = Object.new + + @threadgroup = ThreadGroup.new + + @safe_level = [$SAFE] + + @wait_on_mainloop = [true, 0] + + @cmd_queue = Queue.new + +=begin + @cmd_receiver, @receiver_watchdog = _create_receiver_and_watchdog() + + @threadgroup.add @cmd_receiver + @threadgroup.add @receiver_watchdog + + @threadgroup.enclose +=end + @@DEFAULT_MASTER.assign_receiver_and_watchdog(self) + + @@IP_TABLE[@threadgroup] = self + @@TK_TABLE_LIST.size.times{ + (tbl = {}).tainted? || TkUtil.untrust(tbl) + @tk_table_list << tbl + } + + @ret_val = TkVariable.new + if timeout > 0 && ! _available_check(timeout) + fail RuntimeError, "cannot create connection" + end + @ip_id = _create_connection + + class << self + undef :instance_eval + end + + self.freeze # defend against modification + end + + def manipulable? + return true if (Thread.current.group == ThreadGroup::Default) + MultiTkIp.__getip == @interp && ! @interp.safe? + end + def self.manipulable? + true + end + + def _is_master_of?(tcltkip_obj) + tcltkip_obj == @interp + end + protected :_is_master_of? + + def _ip_id_ + @ip_id + end + + def _available_check(timeout = 5) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + + return nil if timeout < 1 + @ret_val.value = '' + @interp._invoke('send', '-async', @remote, + 'send', '-async', Tk.appname, + "set #{@ret_val.id} ready") + Tk.update + if @ret_val != 'ready' + (1..(timeout*5)).each{ + sleep 0.2 + Tk.update + break if @ret_val == 'ready' + } + end + @ret_val.value == 'ready' + end + private :_available_check + + def _create_connection + raise SecurityError, "no permission to manipulate" unless self.manipulable? + + ip_id = '_' + @interp._invoke('send', @remote, <<-'EOS') + '_' + if {[catch {set _rubytk_control_ip_id_} ret] != 0} { + set _rubytk_control_ip_id_ 0 + } else { + set _rubytk_control_ip_id_ [expr $ret + 1] + } + return $_rubytk_control_ip_id_ + EOS + + @interp._invoke('send', @remote, <<-EOS) + proc rb_out#{ip_id} args { + send #{@appname} rb_out \$args + } + EOS + + ip_id + end + private :_create_connection + + def _appsend(enc_mode, async, *cmds) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + + p ['_appsend', [@remote, @displayof], enc_mode, async, cmds] if $DEBUG + if $SAFE >= 4 + fail SecurityError, "cannot send commands at level 4" + elsif $SAFE >= 1 && cmds.find{|obj| obj.tainted?} + fail SecurityError, "cannot send tainted commands at level #{$SAFE}" + end + + cmds = @interp._merge_tklist(*TkUtil::_conv_args([], enc_mode, *cmds)) + if @displayof + if async + @interp.__invoke('send', '-async', '-displayof', @displayof, + '--', @remote, *cmds) + else + @interp.__invoke('send', '-displayof', @displayof, + '--', @remote, *cmds) + end + else + if async + @interp.__invoke('send', '-async', '--', @remote, *cmds) + else + @interp.__invoke('send', '--', @remote, *cmds) + end + end + end + private :_appsend + + def ready?(timeout=5) + if timeout < 0 + fail ArgumentError, "timeout must be positive number" + end + _available_check(timeout) + end + + def is_rubytk? + return false if _appsend(false, false, 'info', 'command', 'ruby') == "" + [ _appsend(false, false, 'ruby', 'RUBY_VERSION'), + _appsend(false, false, 'set', 'tk_patchLevel') ] + end + + def appsend(async, *args) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + + if async != true && async != false && async != nil + args.unshift(async) + async = false + end + if @displayof + Tk.appsend_displayof(@remote, @displayof, async, *args) + else + Tk.appsend(@remote, async, *args) + end + end + + def rb_appsend(async, *args) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + + if async != true && async != false && async != nil + args.unshift(async) + async = false + end + if @displayof + Tk.rb_appsend_displayof(@remote, @displayof, async, *args) + else + Tk.rb_appsend(@remote, async, *args) + end + end + + def create_slave(name, safe=false) + if safe + safe_opt = '' + else + safe_opt = '-safe' + end + _appsend(false, false, "interp create #{safe_opt} -- #{name}") + end + + def make_safe + fail RuntimeError, 'cannot change safe mode of the remote interpreter' + end + + def safe? + _appsend(false, false, 'interp issafe') + end + + def safe_base? + false + end + + def allow_ruby_exit? + false + end + + def allow_ruby_exit= (mode) + fail RuntimeError, 'cannot change mode of the remote interpreter' + end + + def delete + _appsend(false, true, 'exit') + end + + def deleted? + raise SecurityError, "no permission to manipulate" unless self.manipulable? + + if @displayof + lst = @interp._invoke_without_enc('winfo', 'interps', + '-displayof', @displayof) + else + lst = @interp._invoke_without_enc('winfo', 'interps') + end + # unless @interp._split_tklist(lst).index(@remote) + unless @interp._split_tklist(lst).index(_toUTF8(@remote)) + true + else + false + end + end + + def has_mainwindow? + raise SecurityError, "no permission to manipulate" unless self.manipulable? + + begin + inf = @interp._invoke_without_enc('info', 'command', '.') + rescue Exception + return nil + end + if !inf.kind_of?(String) || inf != '.' + false + else + true + end + end + + def invalid_namespace? + false + end + + def restart + fail RuntimeError, 'cannot restart the remote interpreter' + end + + def __eval(str) + _appsend(false, false, str) + end + def _eval(str) + _appsend(nil, false, str) + end + def _eval_without_enc(str) + _appsend(false, false, str) + end + def _eval_with_enc(str) + _appsend(true, false, str) + end + + def _invoke(*args) + _appsend(nil, false, *args) + end + + def __invoke(*args) + _appsend(false, false, *args) + end + def _invoke(*args) + _appsend(nil, false, *args) + end + def _invoke_without_enc(*args) + _appsend(false, false, *args) + end + def _invoke_with_enc(*args) + _appsend(true, false, *args) + end + + def _toUTF8(str, encoding=nil) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._toUTF8(str, encoding) + end + + def _fromUTF8(str, encoding=nil) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._fromUTF8(str, encoding) + end + + def _thread_vwait(var_name) + _appsend(false, 'thread_vwait', varname) + end + + def _thread_tkwait(mode, target) + _appsend(false, 'thread_tkwait', mode, target) + end + + def _return_value + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._return_value + end + + def _get_variable(var_name, flag) + # ignore flag + _appsend(false, 'set', TkComm::_get_eval_string(var_name)) + end + def _get_variable2(var_name, index_name, flag) + # ignore flag + _appsend(false, 'set', "#{TkComm::_get_eval_string(var_name)}(#{TkComm::_get_eval_string(index_name)})") + end + + def _set_variable(var_name, value, flag) + # ignore flag + _appsend(false, 'set', TkComm::_get_eval_string(var_name), TkComm::_get_eval_string(value)) + end + def _set_variable2(var_name, index_name, value, flag) + # ignore flag + _appsend(false, 'set', "#{TkComm::_get_eval_string(var_name)}(#{TkComm::_get_eval_string(index_name)})", TkComm::_get_eval_string(value)) + end + + def _unset_variable(var_name, flag) + # ignore flag + _appsend(false, 'unset', TkComm::_get_eval_string(var_name)) + end + def _unset_variable2(var_name, index_name, flag) + # ignore flag + _appsend(false, 'unset', "#{var_name}(#{index_name})") + end + + def _get_global_var(var_name) + _appsend(false, 'set', TkComm::_get_eval_string(var_name)) + end + def _get_global_var2(var_name, index_name) + _appsend(false, 'set', "#{TkComm::_get_eval_string(var_name)}(#{TkComm::_get_eval_string(index_name)})") + end + + def _set_global_var(var_name, value) + _appsend(false, 'set', TkComm::_get_eval_string(var_name), TkComm::_get_eval_string(value)) + end + def _set_global_var2(var_name, index_name, value) + _appsend(false, 'set', "#{TkComm::_get_eval_string(var_name)}(#{TkComm::_get_eval_string(index_name)})", TkComm::_get_eval_string(value)) + end + + def _unset_global_var(var_name) + _appsend(false, 'unset', TkComm::_get_eval_string(var_name)) + end + def _unset_global_var2(var_name, index_name) + _appsend(false, 'unset', "#{var_name}(#{index_name})") + end + + def _split_tklist(str) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._split_tklist(str) + end + + def _merge_tklist(*args) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._merge_tklist(*args) + end + + def _conv_listelement(str) + raise SecurityError, "no permission to manipulate" unless self.manipulable? + @interp._conv_listelement(str) + end + + def _create_console + fail RuntimeError, 'not support "_create_console" on the remote interpreter' + end + + def mainloop + fail RuntimeError, 'not support "mainloop" on the remote interpreter' + end + def mainloop_watchdog + fail RuntimeError, 'not support "mainloop_watchdog" on the remote interpreter' + end + def do_one_event(flag = nil) + fail RuntimeError, 'not support "do_one_event" on the remote interpreter' + end + def mainloop_abort_on_exception + fail RuntimeError, 'not support "mainloop_abort_on_exception" on the remote interpreter' + end + def mainloop_abort_on_exception=(mode) + fail RuntimeError, 'not support "mainloop_abort_on_exception=" on the remote interpreter' + end + def set_eventloop_tick(*args) + fail RuntimeError, 'not support "set_eventloop_tick" on the remote interpreter' + end + def get_eventloop_tick + fail RuntimeError, 'not support "get_eventloop_tick" on the remote interpreter' + end + def set_no_event_wait(*args) + fail RuntimeError, 'not support "set_no_event_wait" on the remote interpreter' + end + def get_no_event_wait + fail RuntimeError, 'not support "get_no_event_wait" on the remote interpreter' + end + def set_eventloop_weight(*args) + fail RuntimeError, 'not support "set_eventloop_weight" on the remote interpreter' + end + def get_eventloop_weight + fail RuntimeError, 'not support "get_eventloop_weight" on the remote interpreter' + end +end + +class << RemoteTkIp + def mainloop(*args) + fail RuntimeError, 'not support "mainloop" on the remote interpreter' + end + def mainloop_watchdog(*args) + fail RuntimeError, 'not support "mainloop_watchdog" on the remote interpreter' + end + def do_one_event(flag = nil) + fail RuntimeError, 'not support "do_one_event" on the remote interpreter' + end + def mainloop_abort_on_exception + fail RuntimeError, 'not support "mainloop_abort_on_exception" on the remote interpreter' + end + def mainloop_abort_on_exception=(mode) + fail RuntimeError, 'not support "mainloop_abort_on_exception=" on the remote interpreter' + end + def set_eventloop_tick(*args) + fail RuntimeError, 'not support "set_eventloop_tick" on the remote interpreter' + end + def get_eventloop_tick + fail RuntimeError, 'not support "get_eventloop_tick" on the remote interpreter' + end + def set_no_event_wait(*args) + fail RuntimeError, 'not support "set_no_event_wait" on the remote interpreter' + end + def get_no_event_wait + fail RuntimeError, 'not support "get_no_event_wait" on the remote interpreter' + end + def set_eventloop_weight(*args) + fail RuntimeError, 'not support "set_eventloop_weight" on the remote interpreter' + end + def get_eventloop_weight + fail RuntimeError, 'not support "get_eventloop_weight" on the remote interpreter' + end +end diff --git a/jni/ruby/ext/tk/lib/tcltk.rb b/jni/ruby/ext/tk/lib/tcltk.rb new file mode 100644 index 0000000..f8fbdfb --- /dev/null +++ b/jni/ruby/ext/tk/lib/tcltk.rb @@ -0,0 +1,367 @@ +# tof + +#### tcltk library, more direct manipulation of tcl/tk +#### Sep. 5, 1997 Y. Shigehiro + +require "tcltklib" + +################ + +# module TclTk: collection of tcl/tk utilities (supplies namespace.) +module TclTk + + # initialize Hash to hold unique symbols and such + @namecnt = {} + + # initialize Hash to hold callbacks + @callback = {} +end + +# TclTk.mainloop(): call TclTkLib.mainloop() +def TclTk.mainloop() + print("mainloop: start\n") if $DEBUG + TclTkLib.mainloop() + print("mainloop: end\n") if $DEBUG +end + +# TclTk.deletecallbackkey(ca): remove callback from TclTk module +# this does not remove callbacks from tcl/tk interpreter +# without calling this method, TclTkInterpreter will not be GCed +# ca: callback(TclTkCallback) +def TclTk.deletecallbackkey(ca) + print("deletecallbackkey: ", ca.to_s(), "\n") if $DEBUG + @callback.delete(ca.to_s) +end + +# TclTk.dcb(ca, wid, W): call TclTk.deletecallbackkey() for each callbacks +# in an array. +# this is for callback for top-level <Destroy> +# ca: array of callbacks(TclTkCallback) +# wid: top-level widget(TclTkWidget) +# w: information about window given by %W(String) +def TclTk.dcb(ca, wid, w) + if wid.to_s() == w + ca.each{|i| + TclTk.deletecallbackkey(i) + } + end +end + +# TclTk._addcallback(ca): register callback +# ca: callback(TclTkCallback) +def TclTk._addcallback(ca) + print("_addcallback: ", ca.to_s(), "\n") if $DEBUG + @callback[ca.to_s()] = ca +end + +# TclTk._callcallback(key, arg): invoke registered callback +# key: key to select callback (to_s value of the TclTkCallback) +# arg: parameter from tcl/tk interpreter +def TclTk._callcallback(key, arg) + print("_callcallback: ", @callback[key].inspect, "\n") if $DEBUG + @callback[key]._call(arg) + # throw out callback value + # should return String to satisfy rb_eval_string() + return "" +end + +# TclTk._newname(prefix): generate unique name(String) +# prefix: prefix of the unique name +def TclTk._newname(prefix) + # generated name counter is stored in @namecnt + if !@namecnt.key?(prefix) + # first appearing prefix, initialize + @namecnt[prefix] = 1 + else + # already appeared prefix, generate next name + @namecnt[prefix] += 1 + end + return "#{prefix}#{@namecnt[prefix]}" +end + +################ + +# class TclTkInterpreter: tcl/tk interpreter +class TclTkInterpreter + + # initialize(): + def initialize() + # generate interpreter object + @ip = TclTkIp.new() + + # add ruby_fmt command to tcl interpreter + # ruby_fmt command format arguments by `format' and call `ruby' command + # (notice ruby command receives only one argument) + if $DEBUG + @ip._eval("proc ruby_fmt {fmt args} { puts \"ruby_fmt: $fmt $args\" ; set cmd [list ruby [format $fmt $args]] ; uplevel $cmd }") + else + @ip._eval("proc ruby_fmt {fmt args} { set cmd [list ruby [format $fmt $args]] ; uplevel $cmd }") + end + + # @ip._get_eval_string(*args): generate string to evaluate in tcl interpreter + # *args: script which is going to be evaluated under tcl/tk + def @ip._get_eval_string(*args) + argstr = "" + args.each{|arg| + argstr += " " if argstr != "" + # call to_eval if it is defined + if (arg.respond_to?(:to_eval)) + argstr += arg.to_eval() + else + # call to_s unless defined + argstr += arg.to_s() + end + } + return argstr + end + + # @ip._eval_args(*args): evaluate string under tcl/tk interpreter + # returns result string. + # *args: script which is going to be evaluated under tcl/tk + def @ip._eval_args(*args) + # calculate the string to eval in the interpreter + argstr = _get_eval_string(*args) + + # evaluate under the interpreter + print("_eval: \"", argstr, "\"") if $DEBUG + res = _eval(argstr) + if $DEBUG + print(" -> \"", res, "\"\n") + elsif _return_value() != 0 + print(res, "\n") + end + fail(%Q/can't eval "#{argstr}"/) if _return_value() != 0 #' + return res + end + + # generate tcl/tk command object and register in the hash + @commands = {} + # for all commands registered in tcl/tk interpreter: + @ip._eval("info command").split(/ /).each{|comname| + if comname =~ /^[.]/ + # if command is a widget (path), generate TclTkWidget, + # and register it in the hash + @commands[comname] = TclTkWidget.new(@ip, comname) + else + # otherwise, generate TclTkCommand + @commands[comname] = TclTkCommand.new(@ip, comname) + end + } + end + + # commands(): returns hash of the tcl/tk commands + def commands() + return @commands + end + + # rootwidget(): returns root widget(TclTkWidget) + def rootwidget() + return @commands["."] + end + + # _tcltkip(): returns @ip(TclTkIp) + def _tcltkip() + return @ip + end + + # method_missing(id, *args): execute undefined method as tcl/tk command + # id: method symbol + # *args: method arguments + def method_missing(id, *args) + # if command named by id registered, then execute it + if @commands.key?(id.id2name) + return @commands[id.id2name].e(*args) + else + # otherwise, exception + super + end + end +end + +# class TclTkObject: base class of the tcl/tk objects +class TclTkObject + + # initialize(ip, exp): + # ip: interpreter(TclTkIp) + # exp: tcl/tk representation + def initialize(ip, exp) + fail("type is not TclTkIp") if !ip.kind_of?(TclTkIp) + @ip = ip + @exp = exp + end + + # to_s(): returns tcl/tk representation + def to_s() + return @exp + end +end + +# class TclTkCommand: tcl/tk commands +# you should not call TclTkCommand.new() +# commands are created by TclTkInterpreter:initialize() +class TclTkCommand < TclTkObject + + # e(*args): execute command. returns String (e is for exec or eval) + # *args: command arguments + def e(*args) + return @ip._eval_args(to_s(), *args) + end +end + +# class TclTkLibCommand: tcl/tk commands in the library +class TclTkLibCommand < TclTkCommand + + # initialize(ip, name): + # ip: interpreter(TclTkInterpreter) + # name: command name (String) + def initialize(ip, name) + super(ip._tcltkip, name) + end +end + +# class TclTkVariable: tcl/tk variable +class TclTkVariable < TclTkObject + + # initialize(interp, dat): + # interp: interpreter(TclTkInterpreter) + # dat: the value to set(String) + # if nil, not initialize variable + def initialize(interp, dat) + # auto-generate tcl/tk representation (variable name) + exp = TclTk._newname("v_") + # initialize TclTkObject + super(interp._tcltkip(), exp) + # safe this for `set' command + @set = interp.commands()["set"] + # set value + set(dat) if dat + end + + # although you can set/read variables by using set in tcl/tk, + # we provide the method for accessing variables + + # set(data): set tcl/tk variable using `set' + # data: new value + def set(data) + @set.e(to_s(), data.to_s()) + end + + # get(): read tcl/tk variable(String) using `set' + def get() + return @set.e(to_s()) + end +end + +# class TclTkWidget: tcl/tk widget +class TclTkWidget < TclTkCommand + + # initialize(*args): + # *args: parameters + def initialize(*args) + if args[0].kind_of?(TclTkIp) + # in case the 1st argument is TclTkIp: + + # Wrap tcl/tk widget by TclTkWidget + # (used in TclTkInterpreter#initialize()) + + # need two arguments + fail("invalid # of parameter") if args.size != 2 + + # ip: interpreter(TclTkIp) + # exp: tcl/tk representation + ip, exp = args + + # initialize TclTkObject + super(ip, exp) + elsif args[0].kind_of?(TclTkInterpreter) + # in case 1st parameter is TclTkInterpreter: + + # generate new widget from parent widget + + # interp: interpreter(TclTkInterpreter) + # parent: parent widget + # command: widget generating tk command(label ç‰) + # *args: argument to the command + interp, parent, command, *args = args + + # generate widget name + exp = parent.to_s() + exp += "." if exp !~ /[.]$/ + exp += TclTk._newname("w_") + # initialize TclTkObject + super(interp._tcltkip(), exp) + # generate widget + res = @ip._eval_args(command, exp, *args) +# fail("can't create Widget") if res != exp + # for tk_optionMenu, it is legal res != exp + else + fail("first parameter is not TclTkInterpreter") + end + end +end + +# class TclTkCallback: tcl/tk callbacks +class TclTkCallback < TclTkObject + + # initialize(interp, pr, arg): + # interp: interpreter(TclTkInterpreter) + # pr: callback procedure(Proc) + # arg: string to pass as block parameters of pr + # bind command of tcl/tk uses % replacement for parameters + # pr can receive replaced data using block parameter + # its format is specified by arg string + # You should not specify arg for the command like + # scrollbar with -command option, which receives parameters + # without specifying any replacement + def initialize(interp, pr, arg = nil) + # auto-generate tcl/tk representation (variable name) + exp = TclTk._newname("c_") + # initialize TclTkObject + super(interp._tcltkip(), exp) + # save parameters + @pr = pr + @arg = arg + # register in the module + TclTk._addcallback(self) + end + + # to_eval(): returns string representation for @ip._eval_args + def to_eval() + if @arg + # bind replaces %s before calling ruby_fmt, so %%s is used + s = %Q/{ruby_fmt {TclTk._callcallback("#{to_s()}", "%%s")} #{@arg}}/ + else + s = %Q/{ruby_fmt {TclTk._callcallback("#{to_s()}", "%s")}}/ + end + + return s + end + + # _call(arg): invoke callback + # arg: callback parameter + def _call(arg) + @pr.call(arg) + end +end + +# class TclTkImage: tcl/tk images +class TclTkImage < TclTkCommand + + # initialize(interp, t, *args): + # generating image is done by TclTkImage.new() + # destroying is done by image delete (inconsistent, sigh) + # interp: interpreter(TclTkInterpreter) + # t: image type (photo, bitmap, etc.) + # *args: command argument + def initialize(interp, t, *args) + # auto-generate tcl/tk representation + exp = TclTk._newname("i_") + # initialize TclTkObject + super(interp._tcltkip(), exp) + # generate image + res = @ip._eval_args("image create", t, exp, *args) + fail("can't create Image") if res != exp + end +end + +# eof diff --git a/jni/ruby/ext/tk/lib/tk.rb b/jni/ruby/ext/tk/lib/tk.rb new file mode 100644 index 0000000..45f86a9 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk.rb @@ -0,0 +1,5775 @@ +# +# tk.rb - Tk interface module using tcltklib +# by Yukihiro Matsumoto <matz@netlab.jp> + +# use Shigehiro's tcltklib +require 'tcltklib' +require 'tkutil' + +# autoload +require 'tk/autoload' + +# for Mutex +require 'thread' + +class TclTkIp + # backup original (without encoding) _eval and _invoke + alias _eval_without_enc _eval + alias __eval__ _eval + alias _invoke_without_enc _invoke + alias __invoke__ _invoke + + def _ip_id_ + # for RemoteTkIp + '' + end + + alias __initialize__ initialize + private :__initialize__ + + def initialize(*args) + __initialize__(*args) + + @force_default_encoding ||= TkUtil.untrust([false]) + @encoding ||= TkUtil.untrust([nil]) + def @encoding.to_s; self.join(nil); end + end +end + +# define TkComm module (step 1: basic functions) +module TkComm + include TkUtil + extend TkUtil + + WidgetClassNames = TkUtil.untrust({}) + TkExtlibAutoloadModule = TkUtil.untrust([]) + + # None = Object.new ### --> definition is moved to TkUtil module + # def None.to_s + # 'None' + # end + # None.freeze + + #Tk_CMDTBL = {} + #Tk_WINDOWS = {} + Tk_IDs = [ + TkUtil.untrust("00000"), # [0]-cmdid + TkUtil.untrust("00000") # [1]-winid + ] + Tk_IDs.instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + # for backward compatibility + Tk_CMDTBL = Object.new + def Tk_CMDTBL.method_missing(id, *args) + TkCore::INTERP.tk_cmd_tbl.__send__(id, *args) + end + Tk_CMDTBL.freeze + Tk_WINDOWS = Object.new + def Tk_WINDOWS.method_missing(id, *args) + TkCore::INTERP.tk_windows.__send__(id, *args) + end + Tk_WINDOWS.freeze + + self.instance_eval{ + @cmdtbl = TkUtil.untrust([]) + } + + unless const_defined?(:GET_CONFIGINFO_AS_ARRAY) + # GET_CONFIGINFO_AS_ARRAY = false => returns a Hash { opt =>val, ... } + # true => returns an Array [[opt,val], ... ] + # val is a list which includes resource info. + GET_CONFIGINFO_AS_ARRAY = true + end + unless const_defined?(:GET_CONFIGINFOwoRES_AS_ARRAY) + # for configinfo without resource info; list of [opt, value] pair + # false => returns a Hash { opt=>val, ... } + # true => returns an Array [[opt,val], ... ] + GET_CONFIGINFOwoRES_AS_ARRAY = true + end + # *** ATTENTION *** + # 'current_configinfo' method always returns a Hash under all cases of above. + + def error_at + frames = caller() + frames.delete_if do |c| + c =~ %r!/tk(|core|thcore|canvas|text|entry|scrollbox)\.rb:\d+! + end + frames + end + private :error_at + + def _genobj_for_tkwidget(path) + return TkRoot.new if path == '.' + + begin + #tk_class = TkCore::INTERP._invoke('winfo', 'class', path) + tk_class = Tk.ip_invoke_without_enc('winfo', 'class', path) + rescue + return path + end + + if ruby_class = WidgetClassNames[tk_class] + ruby_class_name = ruby_class.name + # gen_class_name = ruby_class_name + 'GeneratedOnTk' + gen_class_name = ruby_class_name + classname_def = '' + else # ruby_class == nil + if Tk.const_defined?(tk_class) + Tk.const_get(tk_class) # auto_load + ruby_class = WidgetClassNames[tk_class] + end + + unless ruby_class + mods = TkExtlibAutoloadModule.find_all{|m| m.const_defined?(tk_class)} + mods.each{|mod| + begin + mod.const_get(tk_class) # auto_load + break if (ruby_class = WidgetClassNames[tk_class]) + rescue LoadError + # ignore load error + end + } + end + + unless ruby_class + std_class = 'Tk' << tk_class + if Object.const_defined?(std_class) + Object.const_get(std_class) # auto_load + ruby_class = WidgetClassNames[tk_class] + end + end + + unless ruby_class + if Tk.const_defined?('TOPLEVEL_ALIASES') && + Tk::TOPLEVEL_ALIASES.const_defined?(std_class) + Tk::TOPLEVEL_ALIASES.const_get(std_class) # auto_load + ruby_class = WidgetClassNames[tk_class] + end + end + + if ruby_class + # found + ruby_class_name = ruby_class.name + gen_class_name = ruby_class_name + classname_def = '' + else + # unknown + ruby_class_name = 'TkWindow' + gen_class_name = 'TkWidget_' + tk_class + classname_def = "WidgetClassName = '#{tk_class}'.freeze" + end + end + +################################### +=begin + if ruby_class = WidgetClassNames[tk_class] + ruby_class_name = ruby_class.name + # gen_class_name = ruby_class_name + 'GeneratedOnTk' + gen_class_name = ruby_class_name + classname_def = '' + else + mod = TkExtlibAutoloadModule.find{|m| m.const_defined?(tk_class)} + if mod + ruby_class_name = mod.name + '::' + tk_class + gen_class_name = ruby_class_name + classname_def = '' + elsif Object.const_defined?('Tk' + tk_class) + ruby_class_name = 'Tk' + tk_class + # gen_class_name = ruby_class_name + 'GeneratedOnTk' + gen_class_name = ruby_class_name + classname_def = '' + else + ruby_class_name = 'TkWindow' + # gen_class_name = ruby_class_name + tk_class + 'GeneratedOnTk' + gen_class_name = 'TkWidget_' + tk_class + classname_def = "WidgetClassName = '#{tk_class}'.freeze" + end + end +=end + +=begin + unless Object.const_defined? gen_class_name + Object.class_eval "class #{gen_class_name}<#{ruby_class_name} + #{classname_def} + end" + end + Object.class_eval "#{gen_class_name}.new('widgetname'=>'#{path}', + 'without_creating'=>true)" +=end + base = Object + gen_class_name.split('::').each{|klass| + next if klass == '' + if base.const_defined?(klass) + base = base.class_eval klass + else + base = base.class_eval "class #{klass}<#{ruby_class_name} + #{classname_def} + end + #{klass}" + end + } + base.class_eval "#{gen_class_name}.new('widgetname'=>'#{path}', + 'without_creating'=>true)" + end + private :_genobj_for_tkwidget + module_function :_genobj_for_tkwidget + + def _at(x,y=nil) + if y + "@#{Integer(x)},#{Integer(y)}" + else + "@#{Integer(x)}" + end + end + module_function :_at + + def tk_tcl2ruby(val, enc_mode = false, listobj = true) +=begin + if val =~ /^rb_out\S* (c(_\d+_)?\d+)/ + #return Tk_CMDTBL[$1] + return TkCore::INTERP.tk_cmd_tbl[$1] + #cmd_obj = TkCore::INTERP.tk_cmd_tbl[$1] + #if cmd_obj.kind_of?(Proc) || cmd_obj.kind_of?(Method) + # cmd_obj + #else + # cmd_obj.cmd + #end + end +=end + if val =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/ + return TkCore::INTERP.tk_cmd_tbl[$4] + end + #if val.include? ?\s + # return val.split.collect{|v| tk_tcl2ruby(v)} + #end + case val + when /\A@font\S+\z/ + TkFont.get_obj(val) + when /\A-?\d+\z/ + val.to_i + when /\A\.\S*\z/ + #Tk_WINDOWS[val] ? Tk_WINDOWS[val] : _genobj_for_tkwidget(val) + TkCore::INTERP.tk_windows[val]? + TkCore::INTERP.tk_windows[val] : _genobj_for_tkwidget(val) + when /\Ai(_\d+_)?\d+\z/ + TkImage::Tk_IMGTBL.mutex.synchronize{ + TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val + } + when /\A-?\d+\.?\d*(e[-+]?\d+)?\z/ + val.to_f + when /\\ / + val.gsub(/\\ /, ' ') + when /[^\\] / + if listobj + #tk_split_escstr(val).collect{|elt| + # tk_tcl2ruby(elt, enc_mode, listobj) + #} + val = _toUTF8(val) unless enc_mode + tk_split_escstr(val, false, false).collect{|elt| + tk_tcl2ruby(elt, true, listobj) + } + elsif enc_mode + _fromUTF8(val) + else + val + end + else + if enc_mode + _fromUTF8(val) + else + val + end + end + end + + private :tk_tcl2ruby + module_function :tk_tcl2ruby + #private_class_method :tk_tcl2ruby + +unless const_defined?(:USE_TCLs_LIST_FUNCTIONS) + USE_TCLs_LIST_FUNCTIONS = true +end + +if USE_TCLs_LIST_FUNCTIONS + ########################################################################### + # use Tcl function version of split_list + ########################################################################### + + def tk_split_escstr(str, src_enc=true, dst_enc=true) + str = _toUTF8(str) if src_enc + if dst_enc + TkCore::INTERP._split_tklist(str).map!{|s| _fromUTF8(s)} + else + TkCore::INTERP._split_tklist(str) + end + end + + def tk_split_sublist(str, depth=-1, src_enc=true, dst_enc=true) + # return [] if str == "" + # list = TkCore::INTERP._split_tklist(str) + str = _toUTF8(str) if src_enc + + if depth == 0 + return "" if str == "" + list = [str] + else + return [] if str == "" + list = TkCore::INTERP._split_tklist(str) + end + if list.size == 1 + # tk_tcl2ruby(list[0], nil, false) + tk_tcl2ruby(list[0], dst_enc, false) + else + list.collect{|token| tk_split_sublist(token, depth - 1, false, dst_enc)} + end + end + + def tk_split_list(str, depth=0, src_enc=true, dst_enc=true) + return [] if str == "" + str = _toUTF8(str) if src_enc + TkCore::INTERP._split_tklist(str).map!{|token| + tk_split_sublist(token, depth - 1, false, dst_enc) + } + end + + def tk_split_simplelist(str, src_enc=true, dst_enc=true) + #lst = TkCore::INTERP._split_tklist(str) + #if (lst.size == 1 && lst =~ /^\{.*\}$/) + # TkCore::INTERP._split_tklist(str[1..-2]) + #else + # lst + #end + + str = _toUTF8(str) if src_enc + if dst_enc + TkCore::INTERP._split_tklist(str).map!{|s| _fromUTF8(s)} + else + TkCore::INTERP._split_tklist(str) + end + end + + def array2tk_list(ary, enc=nil) + return "" if ary.size == 0 + + sys_enc = TkCore::INTERP.encoding + sys_enc = TclTkLib.encoding_system unless sys_enc + + dst_enc = (enc == nil)? sys_enc: enc + + dst = ary.collect{|e| + if e.kind_of? Array + s = array2tk_list(e, enc) + elsif e.kind_of? Hash + tmp_ary = [] + #e.each{|k,v| tmp_ary << k << v } + e.each{|k,v| tmp_ary << "-#{_get_eval_string(k)}" << v } + s = array2tk_list(tmp_ary, enc) + else + s = _get_eval_string(e, enc) + end + + if dst_enc != true && dst_enc != false + if (s_enc = s.instance_variable_get(:@encoding)) + s_enc = s_enc.to_s + elsif TkCore::WITH_ENCODING + s_enc = s.encoding.name + else + s_enc = sys_enc + end + dst_enc = true if s_enc != dst_enc + end + + s + } + + if sys_enc && dst_enc + dst.map!{|s| _toUTF8(s)} + ret = TkCore::INTERP._merge_tklist(*dst) + if TkCore::WITH_ENCODING + if dst_enc.kind_of?(String) + ret = _fromUTF8(ret, dst_enc) + ret.force_encoding(dst_enc) + else + ret.force_encoding('utf-8') + end + else # without encoding + if dst_enc.kind_of?(String) + ret = _fromUTF8(ret, dst_enc) + ret.instance_variable_set(:@encoding, dst_enc) + else + ret.instance_variable_set(:@encoding, 'utf-8') + end + end + ret + else + TkCore::INTERP._merge_tklist(*dst) + end + end + +else + ########################################################################### + # use Ruby script version of split_list (traditional methods) + ########################################################################### + + def tk_split_escstr(str, src_enc=true, dst_enc=true) + return [] if str == "" + list = [] + token = nil + escape = false + brace = 0 + str.split('').each {|c| + brace += 1 if c == '{' && !escape + brace -= 1 if c == '}' && !escape + if brace == 0 && c == ' ' && !escape + list << token.gsub(/^\{(.*)\}$/, '\1') if token + token = nil + else + token = (token || "") << c + end + escape = (c == '\\' && !escape) + } + list << token.gsub(/^\{(.*)\}$/, '\1') if token + list + end + + def tk_split_sublist(str, depth=-1, src_enc=true, dst_enc=true) + #return [] if str == "" + #return [tk_split_sublist(str[1..-2])] if str =~ /^\{.*\}$/ + #list = tk_split_escstr(str) + if depth == 0 + return "" if str == "" + str = str[1..-2] if str =~ /^\{.*\}$/ + list = [str] + else + return [] if str == [] + return [tk_split_sublist(str[1..-2], depth - 1)] if str =~ /^\{.*\}$/ + list = tk_split_escstr(str) + end + if list.size == 1 + tk_tcl2ruby(list[0], nil, false) + else + list.collect{|token| tk_split_sublist(token, depth - 1)} + end + end + + def tk_split_list(str, depth=0, src_enc=true, dst_enc=true) + return [] if str == "" + tk_split_escstr(str).collect{|token| + tk_split_sublist(token, depth - 1) + } + end + + def tk_split_simplelist(str, src_enc=true, dst_enc=true) + return [] if str == "" + list = [] + token = nil + escape = false + brace = 0 + str.split('').each {|c| + if c == '\\' && !escape + escape = true + token = (token || "") << c if brace > 0 + next + end + brace += 1 if c == '{' && !escape + brace -= 1 if c == '}' && !escape + if brace == 0 && c == ' ' && !escape + list << token.gsub(/^\{(.*)\}$/, '\1') if token + token = nil + else + token = (token || "") << c + end + escape = false + } + list << token.gsub(/^\{(.*)\}$/, '\1') if token + list + end + + def array2tk_list(ary, enc=nil) + ary.collect{|e| + if e.kind_of? Array + "{#{array2tk_list(e, enc)}}" + elsif e.kind_of? Hash + # "{#{e.to_a.collect{|ee| array2tk_list(ee)}.join(' ')}}" + e.each{|k,v| tmp_ary << "-#{_get_eval_string(k)}" << v } + array2tk_list(tmp_ary, enc) + else + s = _get_eval_string(e, enc) + (s.index(/\s/) || s.size == 0)? "{#{s}}": s + end + }.join(" ") + end +end + + private :tk_split_escstr, :tk_split_sublist + private :tk_split_list, :tk_split_simplelist + private :array2tk_list + + module_function :tk_split_escstr, :tk_split_sublist + module_function :tk_split_list, :tk_split_simplelist + module_function :array2tk_list + + private_class_method :tk_split_escstr, :tk_split_sublist + private_class_method :tk_split_list, :tk_split_simplelist +# private_class_method :array2tk_list + +=begin + ### --> definition is moved to TkUtil module + def _symbolkey2str(keys) + h = {} + keys.each{|key,value| h[key.to_s] = value} + h + end + private :_symbolkey2str + module_function :_symbolkey2str +=end + +=begin + ### --> definition is moved to TkUtil module + # def hash_kv(keys, enc_mode = nil, conf = [], flat = false) + def hash_kv(keys, enc_mode = nil, conf = nil) + # Hash {key=>val, key=>val, ... } or Array [ [key, val], [key, val], ... ] + # ==> Array ['-key', val, '-key', val, ... ] + dst = [] + if keys and keys != None + keys.each{|k, v| + #dst.push("-#{k}") + dst.push('-' + k.to_s) + if v != None + # v = _get_eval_string(v, enc_mode) if (enc_mode || flat) + v = _get_eval_string(v, enc_mode) if enc_mode + dst.push(v) + end + } + end + if conf + conf + dst + else + dst + end + end + private :hash_kv + module_function :hash_kv +=end + +=begin + ### --> definition is moved to TkUtil module + def bool(val) + case val + when "1", 1, 'yes', 'true' + true + else + false + end + end + + def number(val) + case val + when /^-?\d+$/ + val.to_i + when /^-?\d+\.?\d*(e[-+]?\d+)?$/ + val.to_f + else + fail(ArgumentError, "invalid value for Number:'#{val}'") + end + end + def string(val) + if val == "{}" + '' + elsif val[0] == ?{ && val[-1] == ?} + val[1..-2] + else + val + end + end + def num_or_str(val) + begin + number(val) + rescue ArgumentError + string(val) + end + end +=end + + def list(val, depth=0, enc=true) + tk_split_list(val, depth, enc, enc) + end + def simplelist(val, src_enc=true, dst_enc=true) + tk_split_simplelist(val, src_enc, dst_enc) + end + def window(val) + if val =~ /^\./ + #Tk_WINDOWS[val]? Tk_WINDOWS[val] : _genobj_for_tkwidget(val) + TkCore::INTERP.tk_windows[val]? + TkCore::INTERP.tk_windows[val] : _genobj_for_tkwidget(val) + else + nil + end + end + def image_obj(val) + if val =~ /^i(_\d+_)?\d+$/ + TkImage::Tk_IMGTBL.mutex.synchronize{ + TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val + } + else + val + end + end + def procedure(val) +=begin + if val =~ /^rb_out\S* (c(_\d+_)?\d+)/ + #Tk_CMDTBL[$1] + #TkCore::INTERP.tk_cmd_tbl[$1] + TkCore::INTERP.tk_cmd_tbl[$1].cmd +=end + if val =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/ + return TkCore::INTERP.tk_cmd_tbl[$4].cmd + else + #nil + val + end + end + private :bool, :number, :num_or_str, :num_or_nil, :string + private :list, :simplelist, :window, :image_obj, :procedure + module_function :bool, :number, :num_or_str, :num_or_nil, :string + module_function :list, :simplelist, :window, :image_obj, :procedure + + if (RUBY_VERSION.split('.').map{|n| n.to_i} <=> [1,8,7]) < 0 + def slice_ary(ary, size) + sliced = [] + wk_ary = ary.dup + until wk_ary.size.zero? + sub_ary = [] + size.times{ sub_ary << wk_ary.shift } + yield(sub_ary) if block_given? + sliced << sub_ary + end + (block_given?)? ary: sliced + end + else + def slice_ary(ary, size, &b) + if b + ary.each_slice(size, &b) + else + ary.each_slice(size).to_a + end + end + end + private :slice_ary + module_function :slice_ary + + def subst(str, *opts) + # opts := :nobackslashes | :nocommands | novariables + tk_call('subst', + *(opts.collect{|opt| + opt = opt.to_s + (opt[0] == ?-)? opt: '-' << opt + } << str)) + end + + def _toUTF8(str, encoding = nil) + TkCore::INTERP._toUTF8(str, encoding) + end + def _fromUTF8(str, encoding = nil) + TkCore::INTERP._fromUTF8(str, encoding) + end + private :_toUTF8, :_fromUTF8 + module_function :_toUTF8, :_fromUTF8 + + def _callback_entry_class?(cls) + cls <= Proc || cls <= Method || cls <= TkCallbackEntry + end + private :_callback_entry_class? + module_function :_callback_entry_class? + + def _callback_entry?(obj) + obj.kind_of?(Proc) || obj.kind_of?(Method) || obj.kind_of?(TkCallbackEntry) + end + private :_callback_entry? + module_function :_callback_entry? + +=begin + ### --> definition is moved to TkUtil module + def _get_eval_string(str, enc_mode = nil) + return nil if str == None + if str.kind_of?(TkObject) + str = str.path + elsif str.kind_of?(String) + str = _toUTF8(str) if enc_mode + elsif str.kind_of?(Symbol) + str = str.id2name + str = _toUTF8(str) if enc_mode + elsif str.kind_of?(Hash) + str = hash_kv(str, enc_mode).join(" ") + elsif str.kind_of?(Array) + str = array2tk_list(str) + str = _toUTF8(str) if enc_mode + elsif str.kind_of?(Proc) + str = install_cmd(str) + elsif str == nil + str = "" + elsif str == false + str = "0" + elsif str == true + str = "1" + elsif (str.respond_to?(:to_eval)) + str = str.to_eval() + str = _toUTF8(str) if enc_mode + else + str = str.to_s() || '' + unless str.kind_of? String + fail RuntimeError, "fail to convert the object to a string" + end + str = _toUTF8(str) if enc_mode + end + return str + end +=end +=begin + def _get_eval_string(obj, enc_mode = nil) + case obj + when Numeric + obj.to_s + when String + (enc_mode)? _toUTF8(obj): obj + when Symbol + (enc_mode)? _toUTF8(obj.id2name): obj.id2name + when TkObject + obj.path + when Hash + hash_kv(obj, enc_mode).join(' ') + when Array + (enc_mode)? _toUTF8(array2tk_list(obj)): array2tk_list(obj) + when Proc, Method, TkCallbackEntry + install_cmd(obj) + when false + '0' + when true + '1' + when nil + '' + when None + nil + else + if (obj.respond_to?(:to_eval)) + (enc_mode)? _toUTF8(obj.to_eval): obj.to_eval + else + begin + obj = obj.to_s || '' + rescue + fail RuntimeError, "fail to convert object '#{obj}' to string" + end + (enc_mode)? _toUTF8(obj): obj + end + end + end + private :_get_eval_string + module_function :_get_eval_string +=end + +=begin + ### --> definition is moved to TkUtil module + def _get_eval_enc_str(obj) + return obj if obj == None + _get_eval_string(obj, true) + end + private :_get_eval_enc_str + module_function :_get_eval_enc_str +=end + +=begin + ### --> obsolete + def ruby2tcl(v, enc_mode = nil) + if v.kind_of?(Hash) + v = hash_kv(v) + v.flatten! + v.collect{|e|ruby2tcl(e, enc_mode)} + else + _get_eval_string(v, enc_mode) + end + end + private :ruby2tcl +=end + +=begin + ### --> definition is moved to TkUtil module + def _conv_args(args, enc_mode, *src_args) + conv_args = [] + src_args.each{|arg| + conv_args << _get_eval_string(arg, enc_mode) unless arg == None + # if arg.kind_of?(Hash) + # arg.each{|k, v| + # args << '-' + k.to_s + # args << _get_eval_string(v, enc_mode) + # } + # elsif arg != None + # args << _get_eval_string(arg, enc_mode) + # end + } + args + conv_args + end + private :_conv_args +=end + + def _curr_cmd_id + #id = format("c%.4d", Tk_IDs[0]) + id = "c" + TkCore::INTERP._ip_id_ + TkComm::Tk_IDs[0] + end + def _next_cmd_id + TkComm::Tk_IDs.mutex.synchronize{ + id = _curr_cmd_id + #Tk_IDs[0] += 1 + TkComm::Tk_IDs[0].succ! + id + } + end + private :_curr_cmd_id, :_next_cmd_id + module_function :_curr_cmd_id, :_next_cmd_id + + def TkComm.install_cmd(cmd, local_cmdtbl=nil) + return '' if cmd == '' + begin + ns = TkCore::INTERP._invoke_without_enc('namespace', 'current') + ns = nil if ns == '::' # for backward compatibility + rescue + # probably, Tcl7.6 + ns = nil + end + id = _next_cmd_id + #Tk_CMDTBL[id] = cmd + if cmd.kind_of?(TkCallbackEntry) + TkCore::INTERP.tk_cmd_tbl[id] = cmd + else + TkCore::INTERP.tk_cmd_tbl[id] = TkCore::INTERP.get_cb_entry(cmd) + end + @cmdtbl = [] unless defined? @cmdtbl + TkUtil.untrust(@cmdtbl) unless @cmdtbl.tainted? + @cmdtbl.push id + + if local_cmdtbl && local_cmdtbl.kind_of?(Array) + begin + local_cmdtbl << id + rescue Exception + # ignore + end + end + + #return Kernel.format("rb_out %s", id); + if ns + 'rb_out' << TkCore::INTERP._ip_id_ << ' ' << ns << ' ' << id + else + 'rb_out' << TkCore::INTERP._ip_id_ << ' ' << id + end + end + def TkComm.uninstall_cmd(id, local_cmdtbl=nil) + #id = $1 if /rb_out\S* (c(_\d+_)?\d+)/ =~ id + id = $4 if id =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/ + + if local_cmdtbl && local_cmdtbl.kind_of?(Array) + begin + local_cmdtbl.delete(id) + rescue Exception + # ignore + end + end + @cmdtbl.delete(id) + + #Tk_CMDTBL.delete(id) + TkCore::INTERP.tk_cmd_tbl.delete(id) + end + # private :install_cmd, :uninstall_cmd + # module_function :install_cmd, :uninstall_cmd + def install_cmd(cmd) + TkComm.install_cmd(cmd, @cmdtbl) + end + def uninstall_cmd(id) + TkComm.uninstall_cmd(id, @cmdtbl) + end + +=begin + def install_win(ppath,name=nil) + if !name or name == '' + #name = format("w%.4d", Tk_IDs[1]) + #Tk_IDs[1] += 1 + name = "w" + Tk_IDs[1] + Tk_IDs[1].succ! + end + if name[0] == ?. + @path = name.dup + elsif !ppath or ppath == "." + @path = Kernel.format(".%s", name); + else + @path = Kernel.format("%s.%s", ppath, name) + end + #Tk_WINDOWS[@path] = self + TkCore::INTERP.tk_windows[@path] = self + end +=end + def install_win(ppath,name=nil) + if name + if name == '' + raise ArgumentError, "invalid wiget-name '#{name}'" + end + if name[0] == ?. + @path = '' + name + @path.freeze + return TkCore::INTERP.tk_windows[@path] = self + end + else + Tk_IDs.mutex.synchronize{ + name = "w" + TkCore::INTERP._ip_id_ + Tk_IDs[1] + Tk_IDs[1].succ! + } + end + if !ppath or ppath == '.' + @path = '.' + name + else + @path = ppath + '.' + name + end + @path.freeze + TkCore::INTERP.tk_windows[@path] = self + end + + def uninstall_win() + #Tk_WINDOWS.delete(@path) + TkCore::INTERP.tk_windows.delete(@path) + end + private :install_win, :uninstall_win + + def _epath(win) + if win.kind_of?(TkObject) + win.epath + elsif win.respond_to?(:epath) + win.epath + else + win + end + end + private :_epath +end + +# define TkComm module (step 2: event binding) +module TkComm + include TkEvent + extend TkEvent + + def tk_event_sequence(context) + if context.kind_of? TkVirtualEvent + context = context.path + end + if context.kind_of? Array + context = context.collect{|ev| + if ev.kind_of? TkVirtualEvent + ev.path + else + ev + end + }.join("><") + end + if /,/ =~ context + context = context.split(/\s*,\s*/).join("><") + else + context + end + end + + def _bind_core(mode, what, context, cmd, *args) + id = install_bind(cmd, *args) if cmd + begin + tk_call_without_enc(*(what + ["<#{tk_event_sequence(context)}>", + mode + id])) + rescue + uninstall_cmd(id) if cmd + fail + end + end + + def _bind(what, context, cmd, *args) + _bind_core('', what, context, cmd, *args) + end + + def _bind_append(what, context, cmd, *args) + _bind_core('+', what, context, cmd, *args) + end + + def _bind_remove(what, context) + tk_call_without_enc(*(what + ["<#{tk_event_sequence(context)}>", ''])) + end + + def _bindinfo(what, context=nil) + if context + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + enum_obj = tk_call_without_enc(*what+["<#{tk_event_sequence(context)}>"]).each_line + else + enum_obj = tk_call_without_enc(*what+["<#{tk_event_sequence(context)}>"]) + end + enum_obj.collect {|cmdline| +=begin + if cmdline =~ /^rb_out\S* (c(?:_\d+_)?\d+)\s+(.*)$/ + #[Tk_CMDTBL[$1], $2] + [TkCore::INTERP.tk_cmd_tbl[$1], $2] +=end + if cmdline =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/ + [TkCore::INTERP.tk_cmd_tbl[$4], $5] + else + cmdline + end + } + else + tk_split_simplelist(tk_call_without_enc(*what)).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 + + def _bind_core_for_event_class(klass, mode, what, context, cmd, *args) + id = install_bind_for_event_class(klass, cmd, *args) if cmd + begin + tk_call_without_enc(*(what + ["<#{tk_event_sequence(context)}>", + mode + id])) + rescue + uninstall_cmd(id) if cmd + fail + end + end + + def _bind_for_event_class(klass, what, context, cmd, *args) + _bind_core_for_event_class(klass, '', what, context, cmd, *args) + end + + def _bind_append_for_event_class(klass, what, context, cmd, *args) + _bind_core_for_event_class(klass, '+', what, context, cmd, *args) + end + + def _bind_remove_for_event_class(klass, what, context) + _bind_remove(what, context) + end + + def _bindinfo_for_event_class(klass, what, context=nil) + _bindinfo(what, context) + end + + private :tk_event_sequence + private :_bind_core, :_bind, :_bind_append, :_bind_remove, :_bindinfo + private :_bind_core_for_event_class, :_bind_for_event_class, + :_bind_append_for_event_class, :_bind_remove_for_event_class, + :_bindinfo_for_event_class + + #def bind(tagOrClass, context, cmd=Proc.new, *args) + # _bind(["bind", tagOrClass], context, cmd, *args) + # tagOrClass + #end + def bind(tagOrClass, context, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind(["bind", tagOrClass], context, cmd, *args) + tagOrClass + end + + #def bind_append(tagOrClass, context, cmd=Proc.new, *args) + # _bind_append(["bind", tagOrClass], context, cmd, *args) + # tagOrClass + #end + def bind_append(tagOrClass, context, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append(["bind", tagOrClass], context, cmd, *args) + tagOrClass + end + + def bind_remove(tagOrClass, context) + _bind_remove(['bind', tagOrClass], context) + tagOrClass + end + + def bindinfo(tagOrClass, context=nil) + _bindinfo(['bind', tagOrClass], context) + end + + #def bind_all(context, cmd=Proc.new, *args) + # _bind(['bind', 'all'], context, cmd, *args) + # TkBindTag::ALL + #end + def bind_all(context, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind(['bind', 'all'], context, cmd, *args) + TkBindTag::ALL + end + + #def bind_append_all(context, cmd=Proc.new, *args) + # _bind_append(['bind', 'all'], context, cmd, *args) + # TkBindTag::ALL + #end + def bind_append_all(context, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append(['bind', 'all'], context, cmd, *args) + TkBindTag::ALL + end + + def bind_remove_all(context) + _bind_remove(['bind', 'all'], context) + TkBindTag::ALL + end + + def bindinfo_all(context=nil) + _bindinfo(['bind', 'all'], context) + end +end + + +module TkCore + include TkComm + extend TkComm + + WITH_RUBY_VM = Object.const_defined?(:RubyVM) && ::RubyVM.class == Class + WITH_ENCODING = defined?(::Encoding.default_external) && true + #WITH_ENCODING = Object.const_defined?(:Encoding) && ::Encoding.class == Class + + unless self.const_defined? :INTERP + if self.const_defined? :IP_NAME + name = IP_NAME.to_s + else + #name = nil + name = $0 + end + if self.const_defined? :IP_OPTS + if IP_OPTS.kind_of?(Hash) + opts = hash_kv(IP_OPTS).join(' ') + else + opts = IP_OPTS.to_s + end + else + opts = '' + end + + # RUN_EVENTLOOP_ON_MAIN_THREAD = true + + unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD + if WITH_RUBY_VM ### check Ruby 1.9 !!!!!!! + # *** NEED TO FIX *** + case RUBY_PLATFORM + when /cygwin/ + RUN_EVENTLOOP_ON_MAIN_THREAD = true + when /darwin/ # MacOS X +=begin + ip = TclTkIp.new(name, opts) + if ip._invoke_without_enc('tk', 'windowingsystem') == 'aqua' && + (TclTkLib.get_version<=>[8,4,TclTkLib::RELEASE_TYPE::FINAL,6]) > 0 +=end + if TclTkLib::WINDOWING_SYSTEM == 'aqua' && + (TclTkLib.get_version<=>[8,4,TclTkLib::RELEASE_TYPE::FINAL,6]) > 0 + # *** KNOWN BUG *** + # Main event loop thread of TkAqua (> Tk8.4.9) must be the main + # application thread. So, ruby1.9 users must call Tk.mainloop on + # the main application thread. + # + # *** ADD (2009/05/10) *** + # In some cases (I don't know the description of conditions), + # TkAqua 8.4.7 has a same kind of hang-up trouble. + # So, if 8.4.7 or later, set RUN_EVENTLOOP_ON_MAIN_THREAD to true. + # When you want to control this mode, please call the following + # (set true/false as you want) before "require 'tk'". + # ---------------------------------------------------------- + # module TkCore; RUN_EVENTLOOP_ON_MAIN_THREAD = true; end + # ---------------------------------------------------------- + # + # *** ADD (2010/07/05) *** + # The value of TclTkLib::WINDOWING_SYSTEM is defined at compiling. + # If it is inconsistent with linked DLL, please call the following + # before "require 'tk'". + # ---------------------------------------------------------- + # require 'tcltklib' + # module TclTkLib + # remove_const :WINDOWING_SYSTEM + # WINDOWING_SYSTEM = 'x11' # or 'aqua' + # end + # ---------------------------------------------------------- + # + RUN_EVENTLOOP_ON_MAIN_THREAD = true + else + RUN_EVENTLOOP_ON_MAIN_THREAD = false +=begin + ip.delete + ip = nil +=end + end + else + RUN_EVENTLOOP_ON_MAIN_THREAD = false + end + + else # Ruby 1.8.x + RUN_EVENTLOOP_ON_MAIN_THREAD = false + end + end + + if !WITH_RUBY_VM || RUN_EVENTLOOP_ON_MAIN_THREAD ### check Ruby 1.9 !!!!!!! + INTERP = TclTkIp.new(name, opts) unless self.const_defined? :INTERP + else + INTERP_MUTEX = Mutex.new + INTERP_ROOT_CHECK = ConditionVariable.new + INTERP_THREAD = Thread.new{ + begin + #Thread.current[:interp] = interp = TclTkIp.new(name, opts) + interp = TclTkIp.new(name, opts) + rescue => e + Thread.current[:interp] = e + raise e + end + + interp.mainloop_abort_on_exception = true + Thread.current.instance_variable_set("@interp", interp) + + status = [nil] + def status.value + self[0] + end + def status.value=(val) + self[0] = val + end + + Thread.current[:status] = status + #sleep + + # like as 1.8, withdraw a root widget before calling Tk.mainloop + interp._eval <<EOS +wm withdraw . +rename wm __wm_orig__ +proc wm {subcmd win args} { + set val [eval [list __wm_orig__ $subcmd $win] $args] + if {[string equal $subcmd withdraw] && [string equal $win .]} { + rename wm {} + rename __wm_orig__ wm + } + return $val +} +proc __startup_rbtk_mainloop__ {args} { + rename __startup_rbtk_mainloop__ {} + if {[info command __wm_orig__] == "__wm_orig__"} { + rename wm {} + rename __wm_orig__ wm + if [string equal [wm state .] withdrawn] { + wm deiconify . + } + } +} +set __initial_state_of_rubytk__ 1 +trace add variable __initial_state_of_rubytk__ unset __startup_rbtk_mainloop__ + +# complete initializing +ruby {TkCore::INTERP_THREAD[:interp] = TkCore::INTERP_THREAD.instance_variable_get('@interp')} +EOS + + begin + begin + #TclTkLib.mainloop_abort_on_exception = false + #interp.mainloop_abort_on_exception = true + #Thread.current[:interp] = interp + #Thread.current[:status].value = TclTkLib.mainloop(true) + Thread.current[:status].value = interp.mainloop(true) + rescue SystemExit=>e + Thread.current[:status].value = e + rescue Exception=>e + Thread.current[:status].value = e + p e if $DEBUG + retry if interp.has_mainwindow? + ensure + INTERP_MUTEX.synchronize{ INTERP_ROOT_CHECK.broadcast } + end + + unless interp.deleted? + begin + #Thread.current[:status].value = TclTkLib.mainloop(false) + Thread.current[:status].value = interp.mainloop(false) + rescue Exception=>e + puts "ignore exception on interp: #{e.inspect}\n" if $DEBUG + end + end + + ensure + # interp must be deleted before the thread for interp is dead. + # If not, raise Tcl_Panic on Tcl_AsyncDelete because async handler + # deleted by the wrong thread. + interp.delete + end + } + + # check a Tcl/Tk interpreter is initialized + until INTERP_THREAD[:interp] + # Thread.pass + INTERP_THREAD.run + end + + # INTERP_THREAD.run + raise INTERP_THREAD[:interp] if INTERP_THREAD[:interp].kind_of? Exception + + # check an eventloop is running + while INTERP_THREAD.alive? && TclTkLib.mainloop_thread?.nil? + INTERP_THREAD.run + end + + INTERP = INTERP_THREAD[:interp] + INTERP_THREAD_STATUS = INTERP_THREAD[:status] + + # delete the interpreter and kill the eventloop thread at exit + END{ + if INTERP_THREAD.alive? + INTERP.delete + INTERP_THREAD.kill + end + } + + # (for safety's sake) force the eventloop to run + INTERP_THREAD.run + end + + def INTERP.__getip + self + end + def INTERP.default_master? + true + end + + INTERP.instance_eval{ + # @tk_cmd_tbl = TkUtil.untrust({}) + @tk_cmd_tbl = + TkUtil.untrust(Hash.new{|hash, key| + fail IndexError, "unknown command ID '#{key}'" + }) + def @tk_cmd_tbl.[]=(idx,val) + if self.has_key?(idx) && Thread.current.group != ThreadGroup::Default + fail SecurityError,"cannot change the entried command" + end + super(idx,val) + end + + @tk_windows = TkUtil.untrust({}) + + @tk_table_list = TkUtil.untrust([]) + + @init_ip_env = TkUtil.untrust([]) # table of Procs + @add_tk_procs = TkUtil.untrust([]) # table of [name, args, body] + + @force_default_encoding ||= TkUtil.untrust([false]) + @encoding ||= TkUtil.untrust([nil]) + def @encoding.to_s; self.join(nil); end + + @cb_entry_class = Class.new(TkCallbackEntry){ + class << self + def inspect + sprintf("#<Class(TkCallbackEntry):%0x>", self.__id__) + end + alias to_s inspect + end + + def initialize(ip, cmd) + @ip = ip + @cmd = cmd + end + attr_reader :ip, :cmd + def call(*args) + @ip.cb_eval(@cmd, *args) + end + def inspect + sprintf("#<cb_entry:%0x>", self.__id__) + end + alias to_s inspect + }.freeze + } + + def INTERP.cb_entry_class + @cb_entry_class + end + def INTERP.tk_cmd_tbl + @tk_cmd_tbl + end + def INTERP.tk_windows + @tk_windows + end + + class Tk_OBJECT_TABLE + def initialize(id) + @id = id + @mutex = Mutex.new + end + def mutex + @mutex + end + def method_missing(m, *args, &b) + TkCore::INTERP.tk_object_table(@id).__send__(m, *args, &b) + end + end + + def INTERP.tk_object_table(id) + @tk_table_list[id] + end + def INTERP.create_table + id = @tk_table_list.size + (tbl = {}).tainted? || TkUtil.untrust(tbl) + @tk_table_list << tbl +# obj = Object.new +# obj.instance_eval <<-EOD +# def self.method_missing(m, *args) +# TkCore::INTERP.tk_object_table(#{id}).send(m, *args) +# end +# EOD +# return obj + Tk_OBJECT_TABLE.new(id) + end + + def INTERP.get_cb_entry(cmd) + @cb_entry_class.new(__getip, cmd).freeze + end + def INTERP.cb_eval(cmd, *args) + TkUtil._get_eval_string(TkUtil.eval_cmd(cmd, *args)) + end + + def INTERP.init_ip_env(script = Proc.new) + @init_ip_env << script + script.call(self) + end + def INTERP.add_tk_procs(name, args = nil, body = nil) + if name.kind_of?(Array) + name.each{|param| self.add_tk_procs(*param)} + else + name = name.to_s + @add_tk_procs << [name, args, body] + self._invoke('proc', name, args, body) if args && body + end + end + def INTERP.remove_tk_procs(*names) + names.each{|name| + name = name.to_s + @add_tk_procs.delete_if{|elem| + elem.kind_of?(Array) && elem[0].to_s == name + } + #self._invoke('rename', name, '') + self.__invoke__('rename', name, '') + } + end + def INTERP.init_ip_internal + ip = self + @init_ip_env.each{|script| script.call(ip)} + @add_tk_procs.each{|name,args,body| ip._invoke('proc',name,args,body)} + end + end + + unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD + ### Ruby 1.9 !!!!!!!!!!!!!!!!!!!!!!!!!! + RUN_EVENTLOOP_ON_MAIN_THREAD = false + end + + WIDGET_DESTROY_HOOK = '<WIDGET_DESTROY_HOOK>' + INTERP._invoke_without_enc('event', 'add', + "<#{WIDGET_DESTROY_HOOK}>", '<Destroy>') + INTERP._invoke_without_enc('bind', 'all', "<#{WIDGET_DESTROY_HOOK}>", + install_cmd(proc{|path| + unless TkCore::INTERP.deleted? + begin + if (widget=TkCore::INTERP.tk_windows[path]) + if widget.respond_to?(:__destroy_hook__) + widget.__destroy_hook__ + end + end + rescue Exception=>e + p e if $DEBUG + end + end + }) << ' %W') + + INTERP.add_tk_procs(TclTkLib::FINALIZE_PROC_NAME, '', + "catch { bind all <#{WIDGET_DESTROY_HOOK}> {} }") + + INTERP.add_tk_procs('rb_out', 'ns args', <<-'EOL') + if [regexp {^::} $ns] { + set cmd {namespace eval $ns {ruby_cmd TkCore callback} $args} + } else { + set cmd {eval {ruby_cmd TkCore callback} $ns $args} + } + if {[set st [catch $cmd 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 +=begin + INTERP.add_tk_procs('rb_out', 'args', <<-'EOL') + if {[set st [catch {eval {ruby_cmd TkCore callback} $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 +=end +=begin + INTERP.add_tk_procs('rb_out', 'args', <<-'EOL') + #regsub -all {\\} $args {\\\\} args + #regsub -all {!} $args {\\!} args + #regsub -all "{" $args "\\{" args + regsub -all {(\\|!|\{|\})} $args {\\\1} args + if {[set st [catch {ruby [format "TkCore.callback %%Q!%s!" $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 +=end + + if !WITH_RUBY_VM || RUN_EVENTLOOP_ON_MAIN_THREAD ### check Ruby 1.9 !!!!!!! + at_exit{ INTERP.remove_tk_procs(TclTkLib::FINALIZE_PROC_NAME) } + else + at_exit{ + Tk.root.destroy + INTERP.remove_tk_procs(TclTkLib::FINALIZE_PROC_NAME) + INTERP_THREAD.kill.join + } + end + + EventFlag = TclTkLib::EventFlag + + def callback_break + fail TkCallbackBreak, "Tk callback returns 'break' status" + end + + def callback_continue + fail TkCallbackContinue, "Tk callback returns 'continue' status" + end + + def callback_return + fail TkCallbackReturn, "Tk callback returns 'return' status" + end + + def TkCore.callback(*arg) + begin + if TkCore::INTERP.tk_cmd_tbl.kind_of?(Hash) + #TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg) + normal_ret = false + ret = catch(:IRB_EXIT) do # IRB hack + retval = TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg) + normal_ret = true + retval + end + unless normal_ret + # catch IRB_EXIT + exit(ret) + end + ret + end + rescue SystemExit=>e + exit(e.status) + rescue Interrupt=>e + fail(e) + 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 >-------" + if TkCore::WITH_ENCODING + msg.force_encoding('utf-8') + else + msg.instance_variable_set(:@encoding, 'utf-8') + end + 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 + # TkCore::INTERP._set_global_var('errorInfo', msg) + # fail(e) + fail(e, msg) + end + end +=begin + def TkCore.callback(arg_str) + # arg = tk_split_list(arg_str) + arg = tk_split_simplelist(arg_str) + #_get_eval_string(TkUtil.eval_cmd(Tk_CMDTBL[arg.shift], *arg)) + #_get_eval_string(TkUtil.eval_cmd(TkCore::INTERP.tk_cmd_tbl[arg.shift], + # *arg)) + # TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg) + begin + TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg) + rescue Exception => e + raise(e, e.class.inspect + ': ' + e.message + "\n" + + "\n---< backtrace of Ruby side >-----\n" + + e.backtrace.join("\n") + + "\n---< backtrace of Tk side >-------") + end +#=begin +# cb_obj = TkCore::INTERP.tk_cmd_tbl[arg.shift] +# unless $DEBUG +# cb_obj.call(*arg) +# else +# begin +# raise 'check backtrace' +# rescue +# # ignore backtrace before 'callback' +# pos = -($!.backtrace.size) +# end +# begin +# cb_obj.call(*arg) +# rescue +# trace = $!.backtrace +# raise $!, "\n#{trace[0]}: #{$!.message} (#{$!.class})\n" + +# "\tfrom #{trace[1..pos].join("\n\tfrom ")}" +# end +# end +#=end + end +=end + + def load_cmd_on_ip(tk_cmd) + bool(tk_call('auto_load', tk_cmd)) + end + + def after(ms, cmd=Proc.new) + cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(cmdid); ret}) + after_id = tk_call_without_enc("after",ms,cmdid) + after_id.instance_variable_set('@cmdid', cmdid) + after_id + end +=begin + def after(ms, cmd=Proc.new) + crit_bup = Thread.critical + Thread.critical = true + + myid = _curr_cmd_id + cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(myid); ret}) + + Thread.critical = crit_bup + + tk_call_without_enc("after",ms,cmdid) # return id +# return +# if false #defined? Thread +# Thread.start do +# ms = Float(ms)/1000 +# ms = 10 if ms == 0 +# sleep ms/1000 +# cmd.call +# end +# else +# cmdid = install_cmd(cmd) +# tk_call("after",ms,cmdid) +# end + end +=end + + def after_idle(cmd=Proc.new) + cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(cmdid); ret}) + after_id = tk_call_without_enc('after','idle',cmdid) + after_id.instance_variable_set('@cmdid', cmdid) + after_id + end +=begin + def after_idle(cmd=Proc.new) + crit_bup = Thread.critical + Thread.critical = true + + myid = _curr_cmd_id + cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(myid); ret}) + + Thread.critical = crit_bup + + tk_call_without_enc('after','idle',cmdid) + end +=end + + def after_cancel(afterId) + tk_call_without_enc('after','cancel',afterId) + if (cmdid = afterId.instance_variable_get('@cmdid')) + afterId.instance_variable_set('@cmdid', nil) + uninstall_cmd(cmdid) + end + afterId + end + + def windowingsystem + tk_call_without_enc('tk', 'windowingsystem') + end + + def scaling(scale=nil) + if scale + tk_call_without_enc('tk', 'scaling', scale) + else + Float(number(tk_call_without_enc('tk', 'scaling'))) + end + end + def scaling_displayof(win, scale=nil) + if scale + tk_call_without_enc('tk', 'scaling', '-displayof', win, scale) + else + Float(number(tk_call_without_enc('tk', '-displayof', win, 'scaling'))) + end + end + + def inactive + Integer(tk_call_without_enc('tk', 'inactive')) + end + def inactive_displayof(win) + Integer(tk_call_without_enc('tk', 'inactive', '-displayof', win)) + end + def reset_inactive + tk_call_without_enc('tk', 'inactive', 'reset') + end + def reset_inactive_displayof(win) + tk_call_without_enc('tk', 'inactive', '-displayof', win, 'reset') + end + + def appname(name=None) + tk_call('tk', 'appname', name) + end + + def appsend_deny + tk_call('rename', 'send', '') + end + + def appsend(interp, async, *args) + if $SAFE >= 4 + fail SecurityError, "cannot send Tk commands at level 4" + elsif $SAFE >= 1 && args.find{|obj| obj.tainted?} + fail SecurityError, "cannot send tainted Tk commands at level #{$SAFE}" + end + if async != true && async != false && async != nil + args.unshift(async) + async = false + end + if async + tk_call('send', '-async', '--', interp, *args) + else + tk_call('send', '--', interp, *args) + end + end + + def rb_appsend(interp, async, *args) + if $SAFE >= 4 + fail SecurityError, "cannot send Ruby commands at level 4" + elsif $SAFE >= 1 && args.find{|obj| obj.tainted?} + fail SecurityError, "cannot send tainted Ruby commands at level #{$SAFE}" + end + if async != true && async != false && async != nil + args.unshift(async) + async = false + end + #args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"]/, '\\\\\&')} + args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"\\]/, '\\\\\&')} + # args.push(').to_s"') + # appsend(interp, async, 'ruby "(', *args) + args.push('}.call)"') + appsend(interp, async, 'ruby "TkComm._get_eval_string(proc{', *args) + end + + def appsend_displayof(interp, win, async, *args) + if $SAFE >= 4 + fail SecurityError, "cannot send Tk commands at level 4" + elsif $SAFE >= 1 && args.find{|obj| obj.tainted?} + fail SecurityError, "cannot send tainted Tk commands at level #{$SAFE}" + end + win = '.' if win == nil + if async != true && async != false && async != nil + args.unshift(async) + async = false + end + if async + tk_call('send', '-async', '-displayof', win, '--', interp, *args) + else + tk_call('send', '-displayor', win, '--', interp, *args) + end + end + + def rb_appsend_displayof(interp, win, async, *args) + if $SAFE >= 4 + fail SecurityError, "cannot send Ruby commands at level 4" + elsif $SAFE >= 1 && args.find{|obj| obj.tainted?} + fail SecurityError, "cannot send tainted Ruby commands at level #{$SAFE}" + end + win = '.' if win == nil + if async != true && async != false && async != nil + args.unshift(async) + async = false + end + #args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"]/, '\\\\\&')} + args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"\\]/, '\\\\\&')} + # args.push(').to_s"') + # appsend_displayof(interp, win, async, 'ruby "(', *args) + args.push('}.call)"') + appsend(interp, win, async, 'ruby "TkComm._get_eval_string(proc{', *args) + end + + def info(*args) + tk_call('info', *args) + end + + def mainloop(check_root = true) + if !TkCore::WITH_RUBY_VM + TclTkLib.mainloop(check_root) + + elsif TkCore::RUN_EVENTLOOP_ON_MAIN_THREAD + # if TclTkLib::WINDOWING_SYSTEM == 'aqua' && + #if TkCore::INTERP._invoke_without_enc('tk','windowingsystem')=='aqua' && + # Thread.current != Thread.main && + # (TclTkLib.get_version <=> [8,4,TclTkLib::RELEASE_TYPE::FINAL,9]) > 0 + # raise RuntimeError, + # "eventloop on TkAqua ( > Tk8.4.9 ) works on the main thread only" + #end + if Thread.current != Thread.main + raise RuntimeError, "Tk.mainloop is allowed on the main thread only" + end + TclTkLib.mainloop(check_root) + + else ### Ruby 1.9 !!!!! + unless TkCore::INTERP.default_master? + # [MultiTkIp] slave interp ? + return TkCore::INTERP._thread_tkwait('window', '.') if check_root + end + + # like as 1.8, withdraw a root widget before calling Tk.mainloop + TkCore::INTERP._eval_without_enc('catch {unset __initial_state_of_rubytk__}') + INTERP_THREAD.run + + begin + TclTkLib.set_eventloop_window_mode(true) + + # force run the eventloop + TkCore::INTERP._eval_without_enc('update') + TkCore::INTERP._eval_without_enc('catch {set __initial_state_of_rubytk__}') + INTERP_THREAD.run + if check_root + INTERP_MUTEX.synchronize{ + INTERP_ROOT_CHECK.wait(INTERP_MUTEX) + status = INTERP_THREAD_STATUS.value + if status && TkCore::INTERP.default_master? + INTERP_THREAD_STATUS.value = nil if $SAFE < 4 + raise status if status.kind_of?(Exception) + end + } + else + # INTERP_THREAD.value + begin + INTERP_THREAD.value + rescue Exception => e + raise e + end + end + rescue Exception => e + raise e + ensure + TclTkLib.set_eventloop_window_mode(false) + end + end + end + + def mainloop_thread? + # true : current thread is mainloop + # nil : there is no mainloop + # false : mainloop is running on the other thread + # ( At then, it is dangerous to call Tk interpreter directly. ) + if !TkCore::WITH_RUBY_VM || TkCore::RUN_EVENTLOOP_ON_MAIN_THREAD + ### Ruby 1.9 !!!!!!!!!!! + TclTkLib.mainloop_thread? + else + Thread.current == INTERP_THREAD + end + end + + def mainloop_exist? + TclTkLib.mainloop_thread? != nil + end + + def is_mainloop? + TclTkLib.mainloop_thread? == true + end + + def mainloop_watchdog(check_root = true) + # watchdog restarts mainloop when mainloop is dead + TclTkLib.mainloop_watchdog(check_root) + end + + def do_one_event(flag = TclTkLib::EventFlag::ALL) + TclTkLib.do_one_event(flag) + end + + def set_eventloop_tick(timer_tick) + TclTkLib.set_eventloop_tick(timer_tick) + end + + def get_eventloop_tick() + TclTkLib.get_eventloop_tick + end + + def set_no_event_wait(wait) + TclTkLib.set_no_even_wait(wait) + end + + def get_no_event_wait() + TclTkLib.get_no_eventloop_wait + end + + def set_eventloop_weight(loop_max, no_event_tick) + TclTkLib.set_eventloop_weight(loop_max, no_event_tick) + end + + def get_eventloop_weight() + TclTkLib.get_eventloop_weight + end + + def restart(app_name = nil, keys = {}) + TkCore::INTERP.init_ip_internal + + tk_call('set', 'argv0', app_name) if app_name + if keys.kind_of?(Hash) + # tk_call('set', 'argc', keys.size * 2) + tk_call('set', 'argv', hash_kv(keys).join(' ')) + end + + INTERP.restart + nil + end + + def event_generate(win, context, keys=nil) + #win = win.path if win.kind_of?(TkObject) + if context.kind_of?(TkEvent::Event) + context.generate(win, ((keys)? keys: {})) + elsif keys + tk_call_without_enc('event', 'generate', win, + "<#{tk_event_sequence(context)}>", + *hash_kv(keys, true)) + else + tk_call_without_enc('event', 'generate', win, + "<#{tk_event_sequence(context)}>") + end + nil + end + + def messageBox(keys) + tk_call('tk_messageBox', *hash_kv(keys)) + end + + def getOpenFile(keys = nil) + tk_call('tk_getOpenFile', *hash_kv(keys)) + end + def getMultipleOpenFile(keys = nil) + simplelist(tk_call('tk_getOpenFile', '-multiple', '1', *hash_kv(keys))) + end + + def getSaveFile(keys = nil) + tk_call('tk_getSaveFile', *hash_kv(keys)) + end + def getMultipleSaveFile(keys = nil) + simplelist(tk_call('tk_getSaveFile', '-multiple', '1', *hash_kv(keys))) + end + + def chooseColor(keys = nil) + tk_call('tk_chooseColor', *hash_kv(keys)) + end + + def chooseDirectory(keys = nil) + tk_call('tk_chooseDirectory', *hash_kv(keys)) + end + + def _ip_eval_core(enc_mode, cmd_string) + case enc_mode + when nil + res = INTERP._eval(cmd_string) + when false + res = INTERP._eval_without_enc(cmd_string) + when true + res = INTERP._eval_with_enc(cmd_string) + end + if INTERP._return_value() != 0 + fail RuntimeError, res, error_at + end + return res + end + private :_ip_eval_core + + def ip_eval(cmd_string) + _ip_eval_core(nil, cmd_string) + end + + def ip_eval_without_enc(cmd_string) + _ip_eval_core(false, cmd_string) + end + + def ip_eval_with_enc(cmd_string) + _ip_eval_core(true, cmd_string) + end + + def _ip_invoke_core(enc_mode, *args) + case enc_mode + when false + res = INTERP._invoke_without_enc(*args) + when nil + res = INTERP._invoke(*args) + when true + res = INTERP._invoke_with_enc(*args) + end + if INTERP._return_value() != 0 + fail RuntimeError, res, error_at + end + return res + end + private :_ip_invoke_core + + def ip_invoke(*args) + _ip_invoke_core(nil, *args) + end + + def ip_invoke_without_enc(*args) + _ip_invoke_core(false, *args) + end + + def ip_invoke_with_enc(*args) + _ip_invoke_core(true, *args) + end + + def _tk_call_core(enc_mode, *args) + ### puts args.inspect if $DEBUG + #args.collect! {|x|ruby2tcl(x, enc_mode)} + #args.compact! + #args.flatten! + args = _conv_args([], enc_mode, *args) + puts 'invoke args => ' + args.inspect if $DEBUG + ### print "=> ", args.join(" ").inspect, "\n" if $DEBUG + begin + # res = TkUtil.untrust(INTERP._invoke(*args)) + # res = INTERP._invoke(enc_mode, *args) + res = _ip_invoke_core(enc_mode, *args) + # >>>>> _invoke returns a TAINTED string <<<<< + rescue NameError => err + # err = $! + begin + args.unshift "unknown" + #res = TkUtil.untrust(INTERP._invoke(*args)) + #res = INTERP._invoke(enc_mode, *args) + res = _ip_invoke_core(enc_mode, *args) + # >>>>> _invoke returns a TAINTED string <<<<< + rescue StandardError => err2 + fail err2 unless /^invalid command/ =~ err2.message + fail err + end + end + if INTERP._return_value() != 0 + fail RuntimeError, res, error_at + end + ### print "==> ", res.inspect, "\n" if $DEBUG + return res + end + private :_tk_call_core + + def tk_call(*args) + _tk_call_core(nil, *args) + end + + def tk_call_without_enc(*args) + _tk_call_core(false, *args) + end + + def tk_call_with_enc(*args) + _tk_call_core(true, *args) + end + + def _tk_call_to_list_core(depth, arg_enc, val_enc, *args) + args = _conv_args([], arg_enc, *args) + val = _tk_call_core(false, *args) + if !depth.kind_of?(Integer) || depth == 0 + tk_split_simplelist(val, false, val_enc) + else + tk_split_list(val, depth, false, val_enc) + end + end + #private :_tk_call_to_list_core + + def tk_call_to_list(*args) + _tk_call_to_list_core(-1, nil, true, *args) + end + + def tk_call_to_list_without_enc(*args) + _tk_call_to_list_core(-1, false, false, *args) + end + + def tk_call_to_list_with_enc(*args) + _tk_call_to_list_core(-1, true, true, *args) + end + + def tk_call_to_simplelist(*args) + _tk_call_to_list_core(0, nil, true, *args) + end + + def tk_call_to_simplelist_without_enc(*args) + _tk_call_to_list_core(0, false, false, *args) + end + + def tk_call_to_simplelist_with_enc(*args) + _tk_call_to_list_core(0, true, true, *args) + end +end + + +module Tk + include TkCore + extend Tk + + TCL_VERSION = INTERP._invoke_without_enc("info", "tclversion").freeze + TCL_PATCHLEVEL = INTERP._invoke_without_enc("info", "patchlevel").freeze + + major, minor = TCL_VERSION.split('.') + TCL_MAJOR_VERSION = major.to_i + TCL_MINOR_VERSION = minor.to_i + + TK_VERSION = INTERP._invoke_without_enc("set", "tk_version").freeze + TK_PATCHLEVEL = INTERP._invoke_without_enc("set", "tk_patchLevel").freeze + + major, minor = TK_VERSION.split('.') + TK_MAJOR_VERSION = major.to_i + TK_MINOR_VERSION = minor.to_i + + JAPANIZED_TK = (INTERP._invoke_without_enc("info", "commands", + "kanji") != "").freeze + + def Tk.const_missing(sym) + case(sym) + when :TCL_LIBRARY + INTERP._invoke_without_enc('global', 'tcl_library') + INTERP._invoke("set", "tcl_library").freeze + + when :TK_LIBRARY + INTERP._invoke_without_enc('global', 'tk_library') + INTERP._invoke("set", "tk_library").freeze + + when :LIBRARY + INTERP._invoke("info", "library").freeze + + #when :PKG_PATH, :PACKAGE_PATH, :TCL_PACKAGE_PATH + # INTERP._invoke_without_enc('global', 'tcl_pkgPath') + # tk_split_simplelist(INTERP._invoke('set', 'tcl_pkgPath')) + + #when :LIB_PATH, :LIBRARY_PATH, :TCL_LIBRARY_PATH + # INTERP._invoke_without_enc('global', 'tcl_libPath') + # tk_split_simplelist(INTERP._invoke('set', 'tcl_libPath')) + + when :PLATFORM, :TCL_PLATFORM + if $SAFE >= 4 + fail SecurityError, "can't get #{sym} when $SAFE >= 4" + end + INTERP._invoke_without_enc('global', 'tcl_platform') + Hash[*tk_split_simplelist(INTERP._invoke_without_enc('array', 'get', + 'tcl_platform'))] + + when :ENV + INTERP._invoke_without_enc('global', 'env') + Hash[*tk_split_simplelist(INTERP._invoke('array', 'get', 'env'))] + + #when :AUTO_PATH #<=== + # tk_split_simplelist(INTERP._invoke('set', 'auto_path')) + + #when :AUTO_OLDPATH + # tk_split_simplelist(INTERP._invoke('set', 'auto_oldpath')) + + when :AUTO_INDEX + INTERP._invoke_without_enc('global', 'auto_index') + Hash[*tk_split_simplelist(INTERP._invoke('array', 'get', 'auto_index'))] + + when :PRIV, :PRIVATE, :TK_PRIV + priv = {} + if INTERP._invoke_without_enc('info', 'vars', 'tk::Priv') != "" + var_nam = 'tk::Priv' + else + var_nam = 'tkPriv' + end + INTERP._invoke_without_enc('global', var_nam) + Hash[*tk_split_simplelist(INTERP._invoke('array', 'get', + var_nam))].each{|k,v| + k.freeze + case v + when /^-?\d+$/ + priv[k] = v.to_i + when /^-?\d+\.?\d*(e[-+]?\d+)?$/ + priv[k] = v.to_f + else + priv[k] = v.freeze + end + } + priv + + else + raise NameError, 'uninitialized constant Tk::' + sym.id2name + end + end + + def Tk.errorInfo + INTERP._invoke_without_enc('global', 'errorInfo') + INTERP._invoke_without_enc('set', 'errorInfo') + end + + def Tk.errorCode + INTERP._invoke_without_enc('global', 'errorCode') + code = tk_split_simplelist(INTERP._invoke_without_enc('set', 'errorCode')) + case code[0] + when 'CHILDKILLED', 'CHILDSTATUS', 'CHILDSUSP' + begin + pid = Integer(code[1]) + code[1] = pid + rescue + end + end + code + end + + def Tk.has_mainwindow? + INTERP.has_mainwindow? + end + + def root + Tk::Root.new + end + + def Tk.load_tclscript(file, enc=nil) + if enc + # TCL_VERSION >= 8.5 + tk_call('source', '-encoding', enc, file) + else + tk_call('source', file) + end + end + + def Tk.load_tcllibrary(file, pkg_name=None, interp=None) + tk_call('load', file, pkg_name, interp) + end + + def Tk.unload_tcllibrary(*args) + if args[-1].kind_of?(Hash) + keys = _symbolkey2str(args.pop) + nocomp = (keys['nocomplain'])? '-nocomplain': None + keeplib = (keys['keeplibrary'])? '-keeplibrary': None + tk_call('unload', nocomp, keeplib, '--', *args) + else + tk_call('unload', *args) + end + end + + def Tk.pkgconfig_list(mod) + # Tk8.5 feature + if mod.kind_of?(Module) + if mod.respond_to?(:package_name) + pkgname = mod.package_name + elsif mod.const_defined?(:PACKAGE_NAME) + pkgname = mod::PACKAGE_NAME + else + fail NotImplementedError, 'may not be a module for a Tcl extension' + end + else + pkgname = mod.to_s + end + + pkgname = '::' << pkgname unless pkgname =~ /^::/ + + tk_split_list(tk_call(pkgname + '::pkgconfig', 'list')) + end + + def Tk.pkgconfig_get(mod, key) + # Tk8.5 feature + if mod.kind_of?(Module) + if mod.respond_to?(:package_name) + pkgname = mod.package_name + else + fail NotImplementedError, 'may not be a module for a Tcl extension' + end + else + pkgname = mod.to_s + end + + pkgname = '::' << pkgname unless pkgname =~ /^::/ + + tk_call(pkgname + '::pkgconfig', 'get', key) + end + + def Tk.tcl_pkgconfig_list + # Tk8.5 feature + Tk.pkgconfig_list('::tcl') + end + + def Tk.tcl_pkgconfig_get(key) + # Tk8.5 feature + Tk.pkgconfig_get('::tcl', key) + end + + def Tk.tk_pkgconfig_list + # Tk8.5 feature + Tk.pkgconfig_list('::tk') + end + + def Tk.tk_pkgconfig_get(key) + # Tk8.5 feature + Tk.pkgconfig_get('::tk', key) + end + + def Tk.bell(nice = false) + if nice + tk_call_without_enc('bell', '-nice') + else + tk_call_without_enc('bell') + end + nil + end + + def Tk.bell_on_display(win, nice = false) + if nice + tk_call_without_enc('bell', '-displayof', win, '-nice') + else + tk_call_without_enc('bell', '-displayof', win) + end + nil + end + + def Tk.destroy(*wins) + #tk_call_without_enc('destroy', *wins) + tk_call_without_enc('destroy', *(wins.collect{|win| + if win.kind_of?(TkWindow) + win.epath + else + win + end + })) + end + + def Tk.exit + TkCore::INTERP.has_mainwindow? && tk_call_without_enc('destroy', '.') + end + + ################################################ + + def Tk.sleep(ms = nil, id = nil) + if id + var = (id.kind_of?(TkVariable))? id: TkVarAccess.new(id.to_s) + else + var = TkVariable.new + end + + var.value = tk_call_without_enc('after', ms, proc{ var.value = 0 }) if ms + var.thread_wait + ms + end + + def Tk.wakeup(id) + ((id.kind_of?(TkVariable))? id: TkVarAccess.new(id.to_s)).value = 0 + nil + end + + ################################################ + + def Tk.pack(*args) + TkPack.configure(*args) + end + def Tk.pack_forget(*args) + TkPack.forget(*args) + end + def Tk.unpack(*args) + TkPack.forget(*args) + end + + def Tk.grid(*args) + TkGrid.configure(*args) + end + def Tk.grid_forget(*args) + TkGrid.forget(*args) + end + def Tk.ungrid(*args) + TkGrid.forget(*args) + end + + def Tk.place(*args) + TkPlace.configure(*args) + end + def Tk.place_forget(*args) + TkPlace.forget(*args) + end + def Tk.unplace(*args) + TkPlace.forget(*args) + end + + def Tk.update(idle=nil) + if idle + tk_call_without_enc('update', 'idletasks') + else + tk_call_without_enc('update') + end + end + def Tk.update_idletasks + update(true) + end + def update(idle=nil) + # only for backward compatibility (This never be recommended to use) + Tk.update(idle) + self + end + + # NOTE:: + # If no eventloop-thread is running, "thread_update" method is same + # to "update" method. Else, "thread_update" method waits to complete + # idletask operation on the eventloop-thread. + def Tk.thread_update(idle=nil) + if idle + tk_call_without_enc('thread_update', 'idletasks') + else + tk_call_without_enc('thread_update') + end + end + def Tk.thread_update_idletasks + thread_update(true) + end + + def Tk.lower_window(win, below=None) + tk_call('lower', _epath(win), _epath(below)) + nil + end + def Tk.raise_window(win, above=None) + tk_call('raise', _epath(win), _epath(above)) + nil + end + + def Tk.current_grabs(win = nil) + if win + window(tk_call_without_enc('grab', 'current', win)) + else + tk_split_list(tk_call_without_enc('grab', 'current')) + end + end + + def Tk.focus(display=nil) + if display == nil + window(tk_call_without_enc('focus')) + else + window(tk_call_without_enc('focus', '-displayof', display)) + end + end + + def Tk.focus_to(win, force=false) + if force + tk_call_without_enc('focus', '-force', win) + else + tk_call_without_enc('focus', win) + end + end + + def Tk.focus_lastfor(win) + window(tk_call_without_enc('focus', '-lastfor', win)) + end + + def Tk.focus_next(win) + TkManageFocus.next(win) + end + + def Tk.focus_prev(win) + TkManageFocus.prev(win) + end + + def Tk.strictMotif(mode=None) + bool(tk_call_without_enc('set', 'tk_strictMotif', mode)) + end + + def Tk.show_kinsoku(mode='both') + begin + if /^8\.*/ === TK_VERSION && JAPANIZED_TK + tk_split_simplelist(tk_call('kinsoku', 'show', mode)) + end + rescue + end + end + def Tk.add_kinsoku(chars, mode='both') + begin + if /^8\.*/ === TK_VERSION && JAPANIZED_TK + tk_split_simplelist(tk_call('kinsoku', 'add', mode, + *(chars.split('')))) + else + [] + end + rescue + [] + end + end + def Tk.delete_kinsoku(chars, mode='both') + begin + if /^8\.*/ === TK_VERSION && JAPANIZED_TK + tk_split_simplelist(tk_call('kinsoku', 'delete', mode, + *(chars.split('')))) + end + rescue + end + end + + def Tk.toUTF8(str, encoding = nil) + _toUTF8(str, encoding) + end + + def Tk.fromUTF8(str, encoding = nil) + _fromUTF8(str, encoding) + end +end + +########################################### +# string with Tcl's encoding +########################################### +module Tk + def Tk.subst_utf_backslash(str) + Tk::EncodedString.subst_utf_backslash(str) + end + def Tk.subst_tk_backslash(str) + Tk::EncodedString.subst_tk_backslash(str) + end + def Tk.utf_to_backslash_sequence(str) + Tk::EncodedString.utf_to_backslash_sequence(str) + end + def Tk.utf_to_backslash(str) + Tk::EncodedString.utf_to_backslash_sequence(str) + end + def Tk.to_backslash_sequence(str) + Tk::EncodedString.to_backslash_sequence(str) + end +end + + +########################################### +# convert kanji string to/from utf-8 +########################################### +if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK) + module Tk + module Encoding + extend Encoding + + TkCommandNames = ['encoding'.freeze].freeze + + ############################################# + + if TkCore::WITH_ENCODING ### Ruby 1.9 + RubyEncoding = ::Encoding + + # for saving GC cost + #ENCNAMES_CMD = ['encoding'.freeze, 'names'.freeze] + BINARY_NAME = 'binary'.freeze + UTF8_NAME = 'utf-8'.freeze + DEFAULT_EXTERNAL_NAME = RubyEncoding.default_external.name.freeze + DEFAULT_INTERNAL_NAME = RubyEncoding.default_internal.name.freeze rescue nil + + BINARY = RubyEncoding.find(BINARY_NAME) + UNKNOWN = RubyEncoding.find('ASCII-8BIT') + + ### start of creating ENCODING_TABLE + ENCODING_TABLE = TkCore::INTERP.encoding_table +=begin + ENCODING_TABLE = { + 'binary' => BINARY, + # 'UNKNOWN-8BIT' => UNKNOWN, + } + + list = TkCore::INTERP._invoke_without_enc(ENCNAMES_CMD[0], + ENCNAMES_CMD[1]) + TkCore::INTERP._split_tklist(list).each{|name| + begin + enc = RubyEncoding.find(name) + rescue ArgumentError + case name + when 'identity' + enc = BINARY + when 'shiftjis' + enc = RubyEncoding.find('Shift_JIS') + when 'unicode' + enc = RubyEncoding.find('UTF-8') + #if Tk.tk_call('set', 'tcl_platform(byteOrder)') =='littleEndian' + # enc = RubyEncoding.find('UTF-16LE') + #else + # enc = RubyEncoding.find('UTF-16BE') + #end + when 'symbol' + # single byte data + enc = RubyEncoding.find('ASCII-8BIT') ### ??? + else + # unsupported on Ruby, but supported on Tk + enc = TkCore::INTERP.create_dummy_encoding_for_tk(name) + end + end + ENCODING_TABLE[name.freeze] = enc + } +=end +=begin + def ENCODING_TABLE.get_name(enc) + orig_enc = enc + + # unles enc, use system default + # 1st: Ruby/Tk default encoding + # 2nd: Tcl/Tk default encoding + # 3rd: Ruby's default_external + enc ||= TkCore::INTERP.encoding + enc ||= TclTkLib.encoding_system + enc ||= DEFAULT_EXTERNAL_NAME + + if enc.kind_of?(RubyEncoding) + # Ruby's Encoding object + if (name = self.key(enc)) + return name + end + + # Is it new ? + list = TkCore::INTERP._invoke_without_enc(ENCNAMES_CMD[0], + ENCNAMES_CMD[1]) + TkComm.simplelist(list).each{|name| + if ((enc == RubyEncoding.find(name)) rescue false) + # new relation!! update table + self[name.freeze] = enc + return name + end + } + else + # String or Symbol ? + if self[name = enc.to_s] + return name + end + + # Is it new ? + if (enc_obj = (RubyEncoding.find(name) rescue false)) + list = TkCore::INTERP._invoke_without_enc(ENCNAMES_CMD[0], + ENCNAMES_CMD[1]) + if TkComm.simplelist(list).index(name) + # Tk's encoding name ? + self[name.freeze] = enc_obj # new relation!! update table + return name + else + # Ruby's encoding name ? + if (name = self.key(enc_obj)) + return name + end + end + end + end + + fail ArgumentError, "unsupported Tk encoding '#{orig_enc}'" + end + + def ENCODING_TABLE.get_obj(enc) + # returns the encoding object. + # If 'enc' is the encoding name on Tk only, it returns nil. + ((obj = self[self.get_name(enc)]).kind_of?(RubyEncoding))? obj: nil + end +=end + ### end of creating ENCODING_TABLE + + end + + ############################################# + + if TkCore::WITH_ENCODING + ################################ + ### Ruby 1.9 + ################################ + def force_default_encoding(mode) + TkCore::INTERP.force_default_encoding = mode + end + + def force_default_encoding? + TkCore::INTERP.force_default_encoding? + end + + def default_encoding=(enc) + TkCore::INTERP.default_encoding = Tk::Encoding::ENCODING_TABLE.get_name(enc) + end + + def encoding=(enc) + TkCore::INTERP.encoding = Tk::Encoding::ENCODING_TABLE.get_name(enc) + end + + def encoding_name + Tk::Encoding::ENCODING_TABLE.get_name(TkCore::INTERP.encoding) + end + def encoding_obj + Tk::Encoding::ENCODING_TABLE.get_obj(TkCore::INTERP.encoding) + end + alias encoding encoding_name + alias default_encoding encoding_name + + def tk_encoding_names + #TkComm.simplelist(TkCore::INTERP._invoke_without_enc(Tk::Encoding::ENCNAMES_CMD[0], Tk::Encoding::ENCNAMES_CMD[1])) + TkComm.simplelist(TkCore::INTERP._invoke_without_enc('encoding', 'names')) + end + def encoding_names + self.tk_encoding_names.find_all{|name| + Tk::Encoding::ENCODING_TABLE.get_name(name) rescue false + } + end + def encoding_objs + self.tk_encoding_names.map!{|name| + Tk::Encoding::ENCODING_TABLE.get_obj(name) rescue nil + }.compact + end + + def encoding_system=(enc) + TclTkLib.encoding_system = Tk::Encoding::ENCODING_TABLE.get_name(enc) + end + + def encoding_system_name + Tk::Encoding::ENCODING_TABLE.get_name(TclTkLib.encoding_system) + end + def encoding_system_obj + Tk::Encoding::ENCODING_TABLE.get_obj(TclTkLib.encoding_system) + end + alias encoding_system encoding_system_name + + ################################ + else + ################################ + ### Ruby 1.8- + ################################ + def force_default_encoding=(mode) + true + end + + def force_default_encoding? + true + end + + def default_encoding=(enc) + TkCore::INTERP.default_encoding = enc + end + + def encoding=(enc) + TkCore::INTERP.encoding = enc + end + + def encoding_obj + TkCore::INTERP.encoding + end + def encoding_name + TkCore::INTERP.encoding + end + alias encoding encoding_name + alias default_encoding encoding_name + + def tk_encoding_names + TkComm.simplelist(Tk.tk_call('encoding', 'names')) + end + def encoding_objs + self.tk_encoding_names + end + def encoding_names + self.tk_encoding_names + end + + def encoding_system=(enc) + TclTkLib.encoding_system = enc + end + + def encoding_system_name + TclTkLib.encoding_system + end + def encoding_system_obj + TclTkLib.encoding_system + end + alias encoding_system encoding_system_name + + ################################ + end + + def encoding_convertfrom(str, enc=nil) + enc = encoding_system_name unless enc + str = str.dup + if TkCore::WITH_ENCODING + if str.kind_of?(Tk::EncodedString) + str.__instance_variable_set('@encoding', nil) + else + str.instance_variable_set('@encoding', nil) + end + str.force_encoding('binary') + else + str.instance_variable_set('@encoding', 'binary') + end + ret = TkCore::INTERP._invoke_without_enc('encoding', 'convertfrom', + enc, str) + if TkCore::WITH_ENCODING + ret.force_encoding('utf-8') + else + Tk::UTF8_String.new(ret) + end + ret + end + alias encoding_convert_from encoding_convertfrom + + def encoding_convertto(str, enc=nil) + # str must be a UTF-8 string + enc = encoding_system_name unless enc + ret = TkCore::INTERP._invoke_without_enc('encoding', 'convertto', + enc, str) + #ret.instance_variable_set('@encoding', 'binary') + if TkCore::WITH_ENCODING + #ret.force_encoding(Tk::Encoding::ENCODING_TABLE.get_obj('binary')) + ret.force_encoding(Tk::Encoding::ENCODING_TABLE.get_obj(enc)) + end + ret + end + alias encoding_convert_to encoding_convertto + + def encoding_dirs + # Tcl8.5 feature + TkComm.simplelist(Tk.tk_call_without_enc('encoding', 'dirs')) + end + + def encoding_dirs=(dir_list) # an array or a Tcl's list string + # Tcl8.5 feature + Tk.tk_call_without_enc('encoding', 'dirs', dir_list) + end + end + + extend Encoding + end + + class TclTkIp + def force_default_encoding=(mode) + @force_default_encoding[0] = (mode)? true: false + end + + def force_default_encoding? + @force_default_encoding[0] ||= false + end + + def default_encoding=(name) + name = name.name if Tk::WITH_ENCODING && name.kind_of?(::Encoding) + @encoding[0] = name.to_s.dup + end + + # from tkencoding.rb by ttate@jaist.ac.jp + #attr_accessor :encoding + def encoding=(name) + self.force_default_encoding = true # for comaptibility + self.default_encoding = name + end + + def encoding_name + (@encoding[0])? @encoding[0].dup: nil + end + alias encoding encoding_name + alias default_encoding encoding_name + + def encoding_obj + if Tk::WITH_ENCODING + Tk::Encoding.tcl2rb_encoding(@encoding[0]) + else + (@encoding[0])? @encoding[0].dup: nil + end + end + + alias __toUTF8 _toUTF8 + alias __fromUTF8 _fromUTF8 + + if Object.const_defined?(:Encoding) && ::Encoding.class == Class + # with Encoding (Ruby 1.9+) + # + # use functions on Tcl as default. + # but when unsupported encoding on Tcl, use methods on Ruby. + # + def _toUTF8(str, enc = nil) + if enc + # use given encoding + begin + enc_name = Tk::Encoding::ENCODING_TABLE.get_name(enc) + rescue + # unknown encoding for Tk -> try to convert encoding on Ruby + str = str.dup.force_encoding(enc) + str.encode!(Tk::Encoding::UTF8_NAME) # modify self !! + return str # if no error, probably succeed converting + end + end + + enc_name ||= str.instance_variable_get(:@encoding) + + enc_name ||= + Tk::Encoding::ENCODING_TABLE.get_name(str.encoding) rescue nil + + if enc_name + # str has its encoding information + encstr = __toUTF8(str, enc_name) + encstr.force_encoding(Tk::Encoding::UTF8_NAME) + return encstr + else + # str.encoding isn't supported by Tk -> try to convert on Ruby + begin + return str.encode(Tk::Encoding::UTF8_NAME) # new string + rescue + # error -> ignore, try to use default encoding of Ruby/Tk + end + end + + #enc_name ||= + # Tk::Encoding::ENCODING_TABLE.get_name(Tk.encoding) rescue nil + enc_name ||= Tk::Encoding::ENCODING_TABLE.get_name(nil) + + # is 'binary' encoding? + if enc_name == Tk::Encoding::BINARY_NAME + return str.dup.force_encoding(Tk::Encoding::BINARY_NAME) + end + + # force default encoding? + if ! str.kind_of?(Tk::EncodedString) && self.force_default_encoding? + enc_name = Tk::Encoding::ENCODING_TABLE.get_name(Tk.default_encoding) + end + + encstr = __toUTF8(str, enc_name) + encstr.force_encoding(Tk::Encoding::UTF8_NAME) + encstr + end + def _fromUTF8(str, enc = nil) + # str must be UTF-8 or binary. + enc_name = str.instance_variable_get(:@encoding) + enc_name ||= + Tk::Encoding::ENCODING_TABLE.get_name(str.encoding) rescue nil + + # is 'binary' encoding? + if enc_name == Tk::Encoding::BINARY_NAME + return str.dup.force_encoding(Tk::Encoding::BINARY_NAME) + end + + # get target encoding name (if enc == nil, use default encoding) + begin + enc_name = Tk::Encoding::ENCODING_TABLE.get_name(enc) + rescue + # then, enc != nil + # unknown encoding for Tk -> try to convert encoding on Ruby + str = str.dup.force_encoding(Tk::Encoding::UTF8_NAME) + str.encode!(enc) # modify self !! + return str # if no error, probably succeed converting + end + + encstr = __fromUTF8(str, enc_name) + encstr.force_encoding(Tk::Encoding::ENCODING_TABLE.get_obj(enc_name)) + encstr + end + ### + else + # without Encoding (Ruby 1.8) + def _toUTF8(str, encoding = nil) + __toUTF8(str, encoding) + end + def _fromUTF8(str, encoding = nil) + __fromUTF8(str, encoding) + end + ### + end + + alias __eval _eval + alias __invoke _invoke + + def _eval(cmd) + _fromUTF8(__eval(_toUTF8(cmd))) + end + + def _invoke(*cmds) + _fromUTF8(__invoke(*(cmds.collect{|cmd| _toUTF8(cmd)}))) + end + + alias _eval_with_enc _eval + alias _invoke_with_enc _invoke + +=begin + #### --> definition is moved to TclTkIp module + + def _toUTF8(str, encoding = nil) + # decide encoding + if encoding + encoding = encoding.to_s + elsif str.kind_of?(Tk::EncodedString) && str.encoding != nil + encoding = str.encoding.to_s + elsif str.instance_variable_get(:@encoding) + encoding = str.instance_variable_get(:@encoding).to_s + elsif defined?(@encoding) && @encoding != nil + encoding = @encoding.to_s + else + encoding = __invoke('encoding', 'system') + end + + # convert + case encoding + when 'utf-8', 'binary' + str + else + __toUTF8(str, encoding) + end + end + + def _fromUTF8(str, encoding = nil) + unless encoding + if defined?(@encoding) && @encoding != nil + encoding = @encoding.to_s + else + encoding = __invoke('encoding', 'system') + end + end + + if str.kind_of?(Tk::EncodedString) + if str.encoding == 'binary' + str + else + __fromUTF8(str, encoding) + end + elsif str.instance_variable_get(:@encoding).to_s == 'binary' + str + else + __fromUTF8(str, encoding) + end + end +=end + +=begin + def _eval(cmd) + if defined?(@encoding) && @encoding != 'utf-8' + ret = if cmd.kind_of?(Tk::EncodedString) + case cmd.encoding + when 'utf-8', 'binary' + __eval(cmd) + else + __eval(_toUTF8(cmd, cmd.encoding)) + end + elsif cmd.instance_variable_get(:@encoding) == 'binary' + __eval(cmd) + else + __eval(_toUTF8(cmd, @encoding)) + end + if ret.kind_of?(String) && ret.instance_variable_get(:@encoding) == 'binary' + ret + else + _fromUTF8(ret, @encoding) + end + else + __eval(cmd) + end + end + + def _invoke(*cmds) + if defined?(@encoding) && @encoding != 'utf-8' + cmds = cmds.collect{|cmd| + if cmd.kind_of?(Tk::EncodedString) + case cmd.encoding + when 'utf-8', 'binary' + cmd + else + _toUTF8(cmd, cmd.encoding) + end + elsif cmd.instance_variable_get(:@encoding) == 'binary' + cmd + else + _toUTF8(cmd, @encoding) + end + } + ret = __invoke(*cmds) + if ret.kind_of?(String) && ret.instance_variable_get(:@encoding) == 'binary' + ret + else + _fromUTF8(ret, @encoding) + end + else + __invoke(*cmds) + end + end +=end + end + + module TclTkLib + class << self + def force_default_encoding=(mode) + TkCore::INTERP.force_default_encoding = mode + end + + def force_default_encoding? + TkCore::INTERP.force_default_encoding? + end + + def default_encoding=(name) + TkCore::INTERP.default_encoding = name + end + + alias _encoding encoding + alias _encoding= encoding= + def encoding=(name) + name = name.name if name.kind_of?(::Encoding) if Tk::WITH_ENCODING + TkCore::INTERP.encoding = name + end + + def encoding_name + TkCore::INTERP.encoding + end + alias encoding encoding_name + alias default_encoding encoding_name + + def encoding_obj + if Tk::WITH_ENCODING + Tk::Encoding.tcl2rb_encoding(TkCore::INTERP.encoding) + else + TkCore::INTERP.encoding + end + end + end + end + + # estimate encoding + unless TkCore::WITH_ENCODING + case $KCODE + when /^e/i # EUC + Tk.encoding = 'euc-jp' + Tk.encoding_system = 'euc-jp' + when /^s/i # SJIS + begin + if Tk.encoding_system == 'cp932' + Tk.encoding = 'cp932' + else + Tk.encoding = 'shiftjis' + Tk.encoding_system = 'shiftjis' + end + rescue StandardError, NameError + Tk.encoding = 'shiftjis' + Tk.encoding_system = 'shiftjis' + end + when /^u/i # UTF8 + Tk.encoding = 'utf-8' + Tk.encoding_system = 'utf-8' + else # NONE + if defined? DEFAULT_TK_ENCODING + Tk.encoding_system = DEFAULT_TK_ENCODING + end + begin + Tk.encoding = Tk.encoding_system + rescue StandardError, NameError + Tk.encoding = 'utf-8' + Tk.encoding_system = 'utf-8' + end + end + + else ### Ruby 1.9 !!!!!!!!!!!! + # loc_enc_obj = (::Encoding.find(::Encoding.locale_charmap) rescue Tk::Encoding::UNKNOWN) + loc_enc_obj = ::Encoding.find("locale") + ext_enc_obj = ::Encoding.default_external + int_enc_obj = ::Encoding.default_internal || ext_enc_obj + tksys_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(Tk.encoding_system) + # p [Tk.encoding, Tk.encoding_system, loc_enc_obj, ext_enc_obj] + +=begin + if ext_enc_obj == Tk::Encoding::UNKNOWN + if defined? DEFAULT_TK_ENCODING + if DEFAULT_TK_ENCODING.kind_of?(::Encoding) + tk_enc_name = DEFAULT_TK_ENCODING.name + tksys_enc_name = DEFAULT_TK_ENCODING.name + else + tk_enc_name = DEFAULT_TK_ENCODING + tksys_enc_name = DEFAULT_TK_ENCODING + end + else + tk_enc_name = loc_enc_obj.name + tksys_enc_name = loc_enc_obj.name + end + else + tk_enc_name = ext_enc_obj.name + tksys_enc_name = ext_enc_obj.name + end + + # Tk.encoding = tk_enc_name + Tk.default_encoding = tk_enc_name + Tk.encoding_system = tksys_enc_name +=end + + if ext_enc_obj == Tk::Encoding::UNKNOWN + if loc_enc_obj == Tk::Encoding::UNKNOWN + # use Tk.encoding_system + else + # use locale_charmap + begin + loc_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(loc_enc_obj) + if loc_enc_name && loc_enc_name != tksys_enc_name + # use locale_charmap + Tk.encoding_system = loc_enc_name + else + # use Tk.encoding_system + end + rescue ArgumentError + # unsupported encoding on Tk -> use Tk.encoding_system + end + end + else + begin + ext_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(ext_enc_obj) + if ext_enc_name && ext_enc_name != tksys_enc_name + # use default_external + Tk.encoding_system = ext_enc_name + else + # use Tk.encoding_system + end + rescue ArgumentError + # unsupported encoding on Tk -> use Tk.encoding_system + end + end + + # setup Tk.encoding + enc_name = nil + + begin + default_def = DEFAULT_TK_ENCODING + if ::Encoding.find(default_def.to_s) != Tk::Encoding::UNKNOWN + enc_name = Tk::Encoding::ENCODING_TABLE.get_name(default_def) + end + rescue NameError + # ignore + enc_name = nil + rescue ArgumentError + enc_name = nil + fail ArgumentError, + "DEFAULT_TK_ENCODING has an unknown encoding #{default_def}" + end + + unless enc_name + #if ext_enc_obj == Tk::Encoding::UNKNOWN + if int_enc_obj == Tk::Encoding::UNKNOWN + if loc_enc_obj == Tk::Encoding::UNKNOWN + # use Tk.encoding_system + enc_name = tksys_enc_name + else + # use locale_charmap + begin + loc_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(loc_enc_obj) + if loc_enc_name + # use locale_charmap + enc_name = loc_enc_name + else + # use Tk.encoding_system + enc_name = tksys_enc_name + end + rescue ArgumentError + # unsupported encoding on Tk -> use Tk.encoding_system + enc_name = tksys_enc_name + end + end + else + begin + #ext_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(ext_enc_obj) + #if ext_enc_name && ext_enc_name != tksys_enc_name + int_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(int_enc_obj) + if int_enc_name + # use default_internal + enc_name = int_enc_name + else + # use Tk.encoding_system + enc_name = tksys_enc_name + end + rescue ArgumentError + # unsupported encoding on Tk -> use Tk.encoding_system + enc_name = tksys_enc_name + end + end + end + + Tk.default_encoding = (enc_name)? enc_name: tksys_enc_name + end + +else + # dummy methods + module Tk + module Encoding + extend Encoding + + def force_default_encoding=(mode) + nil + end + + def force_default_encoding? + nil + end + + def default_encoding=(enc) + nil + end + def default_encoding + nil + end + + def encoding=(name) + nil + end + def encoding + nil + end + def encoding_names + nil + end + def encoding_system + nil + end + def encoding_system=(enc) + nil + end + + def encoding_convertfrom(str, enc=None) + str + end + alias encoding_convert_from encoding_convertfrom + + def encoding_convertto(str, enc=None) + str + end + alias encoding_convert_to encoding_convertto + def encoding_dirs + nil + end + def encoding_dirs=(dir_array) + nil + end + end + + extend Encoding + end + + class TclTkIp + attr_accessor :encoding + + alias __eval _eval + alias __invoke _invoke + + alias _eval_with_enc _eval + alias _invoke_with_enc _invoke + end +end + + +module TkBindCore + #def bind(context, cmd=Proc.new, *args) + # Tk.bind(self, context, cmd, *args) + #end + def bind(context, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + Tk.bind(self, context, cmd, *args) + end + + #def bind_append(context, cmd=Proc.new, *args) + # Tk.bind_append(self, context, cmd, *args) + #end + def bind_append(context, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + Tk.bind_append(self, context, cmd, *args) + end + + def bind_remove(context) + Tk.bind_remove(self, context) + end + + def bindinfo(context=nil) + Tk.bindinfo(self, context) + end +end + + +module TkTreatFont + def __font_optkeys + ['font'] + end + private :__font_optkeys + + def __pathname + self.path + end + private :__pathname + + ################################ + + def font_configinfo(key = nil) + optkeys = __font_optkeys + if key && !optkeys.find{|opt| opt.to_s == key.to_s} + fail ArgumentError, "unknown font option name `#{key}'" + end + + win, tag = __pathname.split(':') + + if key + pathname = [win, tag, key].join(';') + TkFont.used_on(pathname) || + TkFont.init_widget_font(pathname, *__confinfo_cmd) + elsif optkeys.size == 1 + pathname = [win, tag, optkeys[0]].join(';') + TkFont.used_on(pathname) || + TkFont.init_widget_font(pathname, *__confinfo_cmd) + else + fonts = {} + optkeys.each{|k| + k = k.to_s + pathname = [win, tag, k].join(';') + fonts[k] = + TkFont.used_on(pathname) || + TkFont.init_widget_font(pathname, *__confinfo_cmd) + } + fonts + end + end + alias fontobj font_configinfo + + def font_configure(slot) + pathname = __pathname + + slot = _symbolkey2str(slot) + + __font_optkeys.each{|optkey| + optkey = optkey.to_s + l_optkey = 'latin' << optkey + a_optkey = 'ascii' << optkey + k_optkey = 'kanji' << optkey + + if slot.key?(optkey) + fnt = slot.delete(optkey) + if fnt.kind_of?(TkFont) + slot.delete(l_optkey) + slot.delete(a_optkey) + slot.delete(k_optkey) + + fnt.call_font_configure([pathname, optkey], *(__config_cmd << {})) + next + else + if fnt + if (slot.key?(l_optkey) || + slot.key?(a_optkey) || + slot.key?(k_optkey)) + fnt = TkFont.new(fnt) + + lfnt = slot.delete(l_optkey) + lfnt = slot.delete(a_optkey) if slot.key?(a_optkey) + kfnt = slot.delete(k_optkey) + + fnt.latin_replace(lfnt) if lfnt + fnt.kanji_replace(kfnt) if kfnt + + fnt.call_font_configure([pathname, optkey], + *(__config_cmd << {})) + next + else + fnt = hash_kv(fnt) if fnt.kind_of?(Hash) + unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + tk_call(*(__config_cmd << "-#{optkey}" << fnt)) + else + begin + tk_call(*(__config_cmd << "-#{optkey}" << fnt)) + rescue + # ignore + end + end + end + end + next + end + end + + lfnt = slot.delete(l_optkey) + lfnt = slot.delete(a_optkey) if slot.key?(a_optkey) + kfnt = slot.delete(k_optkey) + + if lfnt && kfnt + TkFont.new(lfnt, kfnt).call_font_configure([pathname, optkey], + *(__config_cmd << {})) + elsif lfnt + latinfont_configure([lfnt, optkey]) + elsif kfnt + kanjifont_configure([kfnt, optkey]) + end + } + + # configure other (without font) options + tk_call(*(__config_cmd.concat(hash_kv(slot)))) if slot != {} + self + end + + def latinfont_configure(ltn, keys=nil) + if ltn.kind_of?(Array) + key = ltn[1] + ltn = ltn[0] + else + key = nil + end + + optkeys = __font_optkeys + if key && !optkeys.find{|opt| opt.to_s == key.to_s} + fail ArgumentError, "unknown font option name `#{key}'" + end + + win, tag = __pathname.split(':') + + optkeys = [key] if key + + optkeys.each{|optkey| + optkey = optkey.to_s + + pathname = [win, tag, optkey].join(';') + + if (fobj = TkFont.used_on(pathname)) + fobj = TkFont.new(fobj) # create a new TkFont object + elsif Tk::JAPANIZED_TK + fobj = fontobj # create a new TkFont object + else + ltn = hash_kv(ltn) if ltn.kind_of?(Hash) + unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + tk_call(*(__config_cmd << "-#{optkey}" << ltn)) + else + begin + tk_call(*(__config_cmd << "-#{optkey}" << ltn)) + rescue => e + # ignore + end + end + next + end + + if fobj.kind_of?(TkFont) + if ltn.kind_of?(TkFont) + conf = {} + ltn.latin_configinfo.each{|k,val| conf[k] = val} + if keys + fobj.latin_configure(conf.update(keys)) + else + fobj.latin_configure(conf) + end + else + fobj.latin_replace(ltn) + end + end + + fobj.call_font_configure([pathname, optkey], *(__config_cmd << {})) + } + self + end + alias asciifont_configure latinfont_configure + + def kanjifont_configure(knj, keys=nil) + if knj.kind_of?(Array) + key = knj[1] + knj = knj[0] + else + key = nil + end + + optkeys = __font_optkeys + if key && !optkeys.find{|opt| opt.to_s == key.to_s} + fail ArgumentError, "unknown font option name `#{key}'" + end + + win, tag = __pathname.split(':') + + optkeys = [key] if key + + optkeys.each{|optkey| + optkey = optkey.to_s + + pathname = [win, tag, optkey].join(';') + + if (fobj = TkFont.used_on(pathname)) + fobj = TkFont.new(fobj) # create a new TkFont object + elsif Tk::JAPANIZED_TK + fobj = fontobj # create a new TkFont object + else + knj = hash_kv(knj) if knj.kind_of?(Hash) + unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + tk_call(*(__config_cmd << "-#{optkey}" << knj)) + else + begin + tk_call(*(__config_cmd << "-#{optkey}" << knj)) + rescue => e + # ignore + end + end + next + end + + if fobj.kind_of?(TkFont) + if knj.kind_of?(TkFont) + conf = {} + knj.kanji_configinfo.each{|k,val| conf[k] = val} + if keys + fobj.kanji_configure(conf.update(keys)) + else + fobj.kanji_configure(conf) + end + else + fobj.kanji_replace(knj) + end + end + + fobj.call_font_configure([pathname, optkey], *(__config_cmd << {})) + } + self + end + + def font_copy(win, wintag=nil, winkey=nil, targetkey=nil) + if wintag + if winkey + fnt = win.tagfontobj(wintag, winkey).dup + else + fnt = win.tagfontobj(wintag).dup + end + else + if winkey + fnt = win.fontobj(winkey).dup + else + fnt = win.fontobj.dup + end + end + + if targetkey + fnt.call_font_configure([__pathname, targetkey], *(__config_cmd << {})) + else + fnt.call_font_configure(__pathname, *(__config_cmd << {})) + end + self + end + + def latinfont_copy(win, wintag=nil, winkey=nil, targetkey=nil) + if targetkey + fontobj(targetkey).dup.call_font_configure([__pathname, targetkey], + *(__config_cmd << {})) + else + fontobj.dup.call_font_configure(__pathname, *(__config_cmd << {})) + end + + if wintag + if winkey + fontobj.latin_replace(win.tagfontobj(wintag, winkey).latin_font_id) + else + fontobj.latin_replace(win.tagfontobj(wintag).latin_font_id) + end + else + if winkey + fontobj.latin_replace(win.fontobj(winkey).latin_font_id) + else + fontobj.latin_replace(win.fontobj.latin_font_id) + end + end + self + end + alias asciifont_copy latinfont_copy + + def kanjifont_copy(win, wintag=nil, winkey=nil, targetkey=nil) + if targetkey + fontobj(targetkey).dup.call_font_configure([__pathname, targetkey], + *(__config_cmd << {})) + else + fontobj.dup.call_font_configure(__pathname, *(__config_cmd << {})) + end + + if wintag + if winkey + fontobj.kanji_replace(win.tagfontobj(wintag, winkey).kanji_font_id) + else + fontobj.kanji_replace(win.tagfontobj(wintag).kanji_font_id) + end + else + if winkey + fontobj.kanji_replace(win.fontobj(winkey).kanji_font_id) + else + fontobj.kanji_replace(win.fontobj.kanji_font_id) + end + end + self + end +end + + +module TkConfigMethod + include TkUtil + include TkTreatFont + + def TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + @mode || false + end + def TkConfigMethod.__set_IGNORE_UNKNOWN_CONFIGURE_OPTION__!(mode) + fail SecurityError, "can't change the mode" if $SAFE>=4 + @mode = (mode)? true: false + end + + def __cget_cmd + [self.path, 'cget'] + end + private :__cget_cmd + + def __config_cmd + [self.path, 'configure'] + end + private :__config_cmd + + def __confinfo_cmd + __config_cmd + end + private :__confinfo_cmd + + def __configinfo_struct + {:key=>0, :alias=>1, :db_name=>1, :db_class=>2, + :default_value=>3, :current_value=>4} + end + private :__configinfo_struct + + def __optkey_aliases + {} + end + private :__optkey_aliases + + def __numval_optkeys + [] + end + private :__numval_optkeys + + def __numstrval_optkeys + [] + end + private :__numstrval_optkeys + + def __boolval_optkeys + ['exportselection', 'jump', 'setgrid', 'takefocus'] + end + private :__boolval_optkeys + + def __strval_optkeys + [ + 'text', 'label', 'show', 'data', 'file', + 'activebackground', 'activeforeground', 'background', + 'disabledforeground', 'disabledbackground', 'foreground', + 'highlightbackground', 'highlightcolor', 'insertbackground', + 'selectbackground', 'selectforeground', 'troughcolor' + ] + end + private :__strval_optkeys + + def __listval_optkeys + [] + end + private :__listval_optkeys + + def __numlistval_optkeys + [] + end + private :__numlistval_optkeys + + def __tkvariable_optkeys + ['variable', 'textvariable'] + end + private :__tkvariable_optkeys + + def __val2ruby_optkeys # { key=>proc, ... } + # The method is used to convert a opt-value to a ruby's object. + # When get the value of the option "key", "proc.call(value)" is called. + {} + end + private :__val2ruby_optkeys + + def __ruby2val_optkeys # { key=>proc, ... } + # The method is used to convert a ruby's object to a opt-value. + # When set the value of the option "key", "proc.call(value)" is called. + # That is, "-#{key} #{proc.call(value)}". + {} + end + private :__ruby2val_optkeys + + def __methodcall_optkeys # { key=>method, ... } + # The method is used to both of get and set. + # Usually, the 'key' will not be a widget option. + {} + end + private :__methodcall_optkeys + + def __keyonly_optkeys # { def_key=>undef_key or nil, ... } + {} + end + private :__keyonly_optkeys + + def __conv_keyonly_opts(keys) + return keys unless keys.kind_of?(Hash) + keyonly = __keyonly_optkeys + keys2 = {} + keys.each{|k, v| + optkey = keyonly.find{|kk,vv| kk.to_s == k.to_s} + if optkey + defkey, undefkey = optkey + if v + keys2[defkey.to_s] = None + elsif undefkey + keys2[undefkey.to_s] = None + else + # remove key + end + else + keys2[k.to_s] = v + end + } + keys2 + end + private :__conv_keyonly_opts + + def config_hash_kv(keys, enc_mode = nil, conf = nil) + hash_kv(__conv_keyonly_opts(keys), enc_mode, conf) + end + + ################################ + + def [](id) + cget(id) + end + + def []=(id, val) + configure(id, val) + val + end + + def cget_tkstring(option) + opt = option.to_s + fail ArgumentError, "Invalid option `#{option.inspect}'" if opt.length == 0 + tk_call_without_enc(*(__cget_cmd << "-#{opt}")) + end + + def __cget_core(slot) + orig_slot = slot + slot = slot.to_s + + if slot.length == 0 + fail ArgumentError, "Invalid option `#{orig_slot.inspect}'" + end + + alias_name, real_name = __optkey_aliases.find{|k, v| k.to_s == slot} + if real_name + slot = real_name.to_s + end + + if ( method = _symbolkey2str(__val2ruby_optkeys())[slot] ) + optval = tk_call_without_enc(*(__cget_cmd << "-#{slot}")) + begin + return method.call(optval) + rescue => e + warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG + return optval + end + end + + if ( method = _symbolkey2str(__methodcall_optkeys)[slot] ) + return self.__send__(method) + end + + case slot + when /^(#{__numval_optkeys.join('|')})$/ + begin + number(tk_call_without_enc(*(__cget_cmd << "-#{slot}"))) + rescue + nil + end + + when /^(#{__numstrval_optkeys.join('|')})$/ + num_or_str(tk_call_without_enc(*(__cget_cmd << "-#{slot}"))) + + when /^(#{__boolval_optkeys.join('|')})$/ + begin + bool(tk_call_without_enc(*(__cget_cmd << "-#{slot}"))) + rescue + nil + end + + when /^(#{__listval_optkeys.join('|')})$/ + simplelist(tk_call_without_enc(*(__cget_cmd << "-#{slot}"))) + + when /^(#{__numlistval_optkeys.join('|')})$/ + conf = tk_call_without_enc(*(__cget_cmd << "-#{slot}")) + if conf =~ /^[0-9+-]/ + list(conf) + else + conf + end + + when /^(#{__strval_optkeys.join('|')})$/ + _fromUTF8(tk_call_without_enc(*(__cget_cmd << "-#{slot}"))) + + when /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/ + fontcode = $1 + fontkey = $2 + fnt = tk_tcl2ruby(tk_call_without_enc(*(__cget_cmd << "-#{fontkey}")), true) + unless fnt.kind_of?(TkFont) + fnt = fontobj(fontkey) + end + if fontcode == 'kanji' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/ + # obsolete; just for compatibility + fnt.kanji_font + else + fnt + end + + when /^(#{__tkvariable_optkeys.join('|')})$/ + v = tk_call_without_enc(*(__cget_cmd << "-#{slot}")) + (v.empty?)? nil: TkVarAccess.new(v) + + else + tk_tcl2ruby(tk_call_without_enc(*(__cget_cmd << "-#{slot}")), true) + end + end + private :__cget_core + + def cget(slot) + unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + __cget_core(slot) + else + begin + __cget_core(slot) + rescue => e + if current_configinfo.has_key?(slot.to_s) + # error on known option + fail e + else + # unknown option + nil + end + end + end + end + def cget_strict(slot) + # never use TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + __cget_core(slot) + end + + def __configure_core(slot, value=None) + if slot.kind_of? Hash + slot = _symbolkey2str(slot) + + __optkey_aliases.each{|alias_name, real_name| + alias_name = alias_name.to_s + if slot.has_key?(alias_name) + slot[real_name.to_s] = slot.delete(alias_name) + end + } + + __methodcall_optkeys.each{|key, method| + value = slot.delete(key.to_s) + self.__send__(method, value) if value + } + + __ruby2val_optkeys.each{|key, method| + key = key.to_s + slot[key] = method.call(slot[key]) if slot.has_key?(key) + } + + __keyonly_optkeys.each{|defkey, undefkey| + conf = slot.find{|kk, vv| kk == defkey.to_s} + if conf + k, v = conf + if v + slot[k] = None + else + slot[undefkey.to_s] = None if undefkey + slot.delete(k) + end + end + } + + if (slot.find{|k, v| k =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/}) + font_configure(slot) + elsif slot.size > 0 + tk_call(*(__config_cmd.concat(hash_kv(slot)))) + end + + else + orig_slot = slot + slot = slot.to_s + if slot.length == 0 + fail ArgumentError, "Invalid option `#{orig_slot.inspect}'" + end + + alias_name, real_name = __optkey_aliases.find{|k, v| k.to_s == slot} + if real_name + slot = real_name.to_s + end + + if ( conf = __keyonly_optkeys.find{|k, v| k.to_s == slot} ) + defkey, undefkey = conf + if value + tk_call(*(__config_cmd << "-#{defkey}")) + elsif undefkey + tk_call(*(__config_cmd << "-#{undefkey}")) + end + elsif ( method = _symbolkey2str(__ruby2val_optkeys)[slot] ) + tk_call(*(__config_cmd << "-#{slot}" << method.call(value))) + elsif ( method = _symbolkey2str(__methodcall_optkeys)[slot] ) + self.__send__(method, value) + elsif (slot =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/) + if value == None + fontobj($2) + else + font_configure({slot=>value}) + end + else + tk_call(*(__config_cmd << "-#{slot}" << value)) + end + end + self + end + private :__configure_core + + def __check_available_configure_options(keys) + availables = self.current_configinfo.keys + + # add non-standard keys + availables |= __font_optkeys.map{|k| + [k.to_s, "latin#{k}", "ascii#{k}", "kanji#{k}"] + }.flatten + availables |= __methodcall_optkeys.keys.map{|k| k.to_s} + availables |= __keyonly_optkeys.keys.map{|k| k.to_s} + + keys = _symbolkey2str(keys) + keys.delete_if{|k, v| !(availables.include?(k))} + end + + def configure(slot, value=None) + unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + __configure_core(slot, value) + else + if slot.kind_of?(Hash) + begin + __configure_core(slot) + rescue + slot = __check_available_configure_options(slot) + __configure_core(slot) unless slot.empty? + end + else + begin + __configure_core(slot, value) + rescue => e + if current_configinfo.has_key?(slot.to_s) + # error on known option + fail e + else + # unknown option + nil + end + end + end + end + self + end + + def configure_cmd(slot, value) + configure(slot, install_cmd(value)) + end + + def __configinfo_core(slot = nil) + if TkComm::GET_CONFIGINFO_AS_ARRAY + if (slot && + slot.to_s =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/) + fontkey = $2 + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{fontkey}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{fontkey}")), false, true) + conf[__configinfo_struct[:key]] = + conf[__configinfo_struct[:key]][1..-1] + if ( ! __configinfo_struct[:alias] \ + || conf.size > __configinfo_struct[:alias] + 1 ) + fnt = conf[__configinfo_struct[:default_value]] + if TkFont.is_system_font?(fnt) + conf[__configinfo_struct[:default_value]] = TkNamedFont.new(fnt) + end + conf[__configinfo_struct[:current_value]] = fontobj(fontkey) + elsif ( __configinfo_struct[:alias] \ + && conf.size == __configinfo_struct[:alias] + 1 \ + && conf[__configinfo_struct[:alias]][0] == ?- ) + conf[__configinfo_struct[:alias]] = + conf[__configinfo_struct[:alias]][1..-1] + end + conf + else + if slot + slot = slot.to_s + + alias_name, real_name = __optkey_aliases.find{|k, v| k.to_s == slot} + if real_name + slot = real_name.to_s + end + + case slot + when /^(#{__val2ruby_optkeys().keys.join('|')})$/ + method = _symbolkey2str(__val2ruby_optkeys())[slot] + conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd() << "-#{slot}")), false, true) + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + optval = conf[__configinfo_struct[:default_value]] + begin + val = method.call(optval) + rescue => e + warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG + val = optval + end + conf[__configinfo_struct[:default_value]] = val + end + if ( conf[__configinfo_struct[:current_value]] ) + optval = conf[__configinfo_struct[:current_value]] + begin + val = method.call(optval) + rescue => e + warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG + val = optval + end + conf[__configinfo_struct[:current_value]] = val + end + + when /^(#{__methodcall_optkeys.keys.join('|')})$/ + method = _symbolkey2str(__methodcall_optkeys)[slot] + return [slot, '', '', '', self.__send__(method)] + + when /^(#{__numval_optkeys.join('|')})$/ + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]]) + begin + conf[__configinfo_struct[:default_value]] = + number(conf[__configinfo_struct[:default_value]]) + rescue + conf[__configinfo_struct[:default_value]] = nil + end + end + if ( conf[__configinfo_struct[:current_value]] ) + begin + conf[__configinfo_struct[:current_value]] = + number(conf[__configinfo_struct[:current_value]]) + rescue + conf[__configinfo_struct[:current_value]] = nil + end + end + + when /^(#{__numstrval_optkeys.join('|')})$/ + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]]) + conf[__configinfo_struct[:default_value]] = + num_or_str(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] ) + conf[__configinfo_struct[:current_value]] = + num_or_str(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__boolval_optkeys.join('|')})$/ + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]]) + begin + conf[__configinfo_struct[:default_value]] = + bool(conf[__configinfo_struct[:default_value]]) + rescue + conf[__configinfo_struct[:default_value]] = nil + end + end + if ( conf[__configinfo_struct[:current_value]] ) + begin + conf[__configinfo_struct[:current_value]] = + bool(conf[__configinfo_struct[:current_value]]) + rescue + conf[__configinfo_struct[:current_value]] = nil + end + end + + when /^(#{__listval_optkeys.join('|')})$/ + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]]) + conf[__configinfo_struct[:default_value]] = + simplelist(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] ) + conf[__configinfo_struct[:current_value]] = + simplelist(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__numlistval_optkeys.join('|')})$/ + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] \ + && conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ ) + conf[__configinfo_struct[:default_value]] = + list(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] \ + && conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ ) + conf[__configinfo_struct[:current_value]] = + list(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__strval_optkeys.join('|')})$/ + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) + + when /^(#{__tkvariable_optkeys.join('|')})$/ + conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]]) + v = conf[__configinfo_struct[:default_value]] + if v.empty? + conf[__configinfo_struct[:default_value]] = nil + else + conf[__configinfo_struct[:default_value]] = TkVarAccess.new(v) + end + end + if ( conf[__configinfo_struct[:current_value]] ) + v = conf[__configinfo_struct[:current_value]] + if v.empty? + conf[__configinfo_struct[:current_value]] = nil + else + conf[__configinfo_struct[:current_value]] = TkVarAccess.new(v) + end + end + + else + # conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) + # conf = tk_split_list(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), 0, false, true) + conf = tk_split_list(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), 1, false, true) + end + conf[__configinfo_struct[:key]] = + conf[__configinfo_struct[:key]][1..-1] + + if ( __configinfo_struct[:alias] \ + && conf.size == __configinfo_struct[:alias] + 1 \ + && conf[__configinfo_struct[:alias]][0] == ?- ) + conf[__configinfo_struct[:alias]] = + conf[__configinfo_struct[:alias]][1..-1] + end + + conf + + else + # ret = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*__confinfo_cmd))).collect{|conflist| + # conf = tk_split_simplelist(conflist) + ret = tk_split_simplelist(tk_call_without_enc(*__confinfo_cmd), false, false).collect{|conflist| + conf = tk_split_simplelist(conflist, false, true) + conf[__configinfo_struct[:key]] = + conf[__configinfo_struct[:key]][1..-1] + + optkey = conf[__configinfo_struct[:key]] + case optkey + when /^(#{__val2ruby_optkeys().keys.join('|')})$/ + method = _symbolkey2str(__val2ruby_optkeys())[optkey] + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + optval = conf[__configinfo_struct[:default_value]] + begin + val = method.call(optval) + rescue => e + warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG + val = optval + end + conf[__configinfo_struct[:default_value]] = val + end + if ( conf[__configinfo_struct[:current_value]] ) + optval = conf[__configinfo_struct[:current_value]] + begin + val = method.call(optval) + rescue => e + warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG + val = optval + end + conf[__configinfo_struct[:current_value]] = val + end + + when /^(#{__strval_optkeys.join('|')})$/ + # do nothing + + when /^(#{__numval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + begin + conf[__configinfo_struct[:default_value]] = + number(conf[__configinfo_struct[:default_value]]) + rescue + conf[__configinfo_struct[:default_value]] = nil + end + end + if ( conf[__configinfo_struct[:current_value]] ) + begin + conf[__configinfo_struct[:current_value]] = + number(conf[__configinfo_struct[:current_value]]) + rescue + conf[__configinfo_struct[:current_value]] = nil + end + end + + when /^(#{__numstrval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + conf[__configinfo_struct[:default_value]] = + num_or_str(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] ) + conf[__configinfo_struct[:current_value]] = + num_or_str(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__boolval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + begin + conf[__configinfo_struct[:default_value]] = + bool(conf[__configinfo_struct[:default_value]]) + rescue + conf[__configinfo_struct[:default_value]] = nil + end + end + if ( conf[__configinfo_struct[:current_value]] ) + begin + conf[__configinfo_struct[:current_value]] = + bool(conf[__configinfo_struct[:current_value]]) + rescue + conf[__configinfo_struct[:current_value]] = nil + end + end + + when /^(#{__listval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + conf[__configinfo_struct[:default_value]] = + simplelist(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] ) + conf[__configinfo_struct[:current_value]] = + simplelist(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__numlistval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] \ + && conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ ) + conf[__configinfo_struct[:default_value]] = + list(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] \ + && conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ ) + conf[__configinfo_struct[:current_value]] = + list(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__tkvariable_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + v = conf[__configinfo_struct[:default_value]] + if v.empty? + conf[__configinfo_struct[:default_value]] = nil + else + conf[__configinfo_struct[:default_value]] = TkVarAccess.new(v) + end + end + if ( conf[__configinfo_struct[:current_value]] ) + v = conf[__configinfo_struct[:current_value]] + if v.empty? + conf[__configinfo_struct[:current_value]] = nil + else + conf[__configinfo_struct[:current_value]] = TkVarAccess.new(v) + end + end + + else + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + if conf[__configinfo_struct[:default_value]].index('{') + conf[__configinfo_struct[:default_value]] = + tk_split_list(conf[__configinfo_struct[:default_value]]) + else + conf[__configinfo_struct[:default_value]] = + tk_tcl2ruby(conf[__configinfo_struct[:default_value]]) + end + end + if conf[__configinfo_struct[:current_value]] + if conf[__configinfo_struct[:current_value]].index('{') + conf[__configinfo_struct[:current_value]] = + tk_split_list(conf[__configinfo_struct[:current_value]]) + else + conf[__configinfo_struct[:current_value]] = + tk_tcl2ruby(conf[__configinfo_struct[:current_value]]) + end + end + end + + if ( __configinfo_struct[:alias] \ + && conf.size == __configinfo_struct[:alias] + 1 \ + && conf[__configinfo_struct[:alias]][0] == ?- ) + conf[__configinfo_struct[:alias]] = + conf[__configinfo_struct[:alias]][1..-1] + end + + conf + } + + __font_optkeys.each{|optkey| + optkey = optkey.to_s + fontconf = ret.assoc(optkey) + if fontconf && fontconf.size > 2 + ret.delete_if{|inf| inf[0] =~ /^(|latin|ascii|kanji)#{optkey}$/} + fnt = fontconf[__configinfo_struct[:default_value]] + if TkFont.is_system_font?(fnt) + fontconf[__configinfo_struct[:default_value]] \ + = TkNamedFont.new(fnt) + end + fontconf[__configinfo_struct[:current_value]] = fontobj(optkey) + ret.push(fontconf) + end + } + + __methodcall_optkeys.each{|optkey, m| + ret << [optkey.to_s, '', '', '', self.__send__(m)] + } + + ret + end + end + + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY + if (slot && + slot.to_s =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/) + fontkey = $2 + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{fontkey}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{fontkey}")), false, true) + conf[__configinfo_struct[:key]] = + conf[__configinfo_struct[:key]][1..-1] + + if ( ! __configinfo_struct[:alias] \ + || conf.size > __configinfo_struct[:alias] + 1 ) + fnt = conf[__configinfo_struct[:default_value]] + if TkFont.is_system_font?(fnt) + conf[__configinfo_struct[:default_value]] = TkNamedFont.new(fnt) + end + conf[__configinfo_struct[:current_value]] = fontobj(fontkey) + { conf.shift => conf } + elsif ( __configinfo_struct[:alias] \ + && conf.size == __configinfo_struct[:alias] + 1 ) + if conf[__configinfo_struct[:alias]][0] == ?- + conf[__configinfo_struct[:alias]] = + conf[__configinfo_struct[:alias]][1..-1] + end + { conf[0] => conf[1] } + else + { conf.shift => conf } + end + else + if slot + slot = slot.to_s + + alias_name, real_name = __optkey_aliases.find{|k,var| k.to_s == slot} + if real_name + slot = real_name.to_s + end + + case slot + when /^(#{__val2ruby_optkeys().keys.join('|')})$/ + method = _symbolkey2str(__val2ruby_optkeys())[slot] + conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + optval = conf[__configinfo_struct[:default_value]] + begin + val = method.call(optval) + rescue => e + warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG + val = optval + end + conf[__configinfo_struct[:default_value]] = val + end + if ( conf[__configinfo_struct[:current_value]] ) + optval = conf[__configinfo_struct[:current_value]] + begin + val = method.call(optval) + rescue => e + warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG + val = optval + end + conf[__configinfo_struct[:current_value]] = val + end + + when /^(#{__methodcall_optkeys.keys.join('|')})$/ + method = _symbolkey2str(__methodcall_optkeys)[slot] + return {slot => ['', '', '', self.__send__(method)]} + + when /^(#{__numval_optkeys.join('|')})$/ + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + begin + conf[__configinfo_struct[:default_value]] = + number(conf[__configinfo_struct[:default_value]]) + rescue + conf[__configinfo_struct[:default_value]] = nil + end + end + if ( conf[__configinfo_struct[:current_value]] ) + begin + conf[__configinfo_struct[:current_value]] = + number(conf[__configinfo_struct[:current_value]]) + rescue + conf[__configinfo_struct[:current_value]] = nil + end + end + + when /^(#{__numstrval_optkeys.join('|')})$/ + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + conf[__configinfo_struct[:default_value]] = + num_or_str(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] ) + conf[__configinfo_struct[:current_value]] = + num_or_str(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__boolval_optkeys.join('|')})$/ + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + begin + conf[__configinfo_struct[:default_value]] = + bool(conf[__configinfo_struct[:default_value]]) + rescue + conf[__configinfo_struct[:default_value]] = nil + end + end + if ( conf[__configinfo_struct[:current_value]] ) + begin + conf[__configinfo_struct[:current_value]] = + bool(conf[__configinfo_struct[:current_value]]) + rescue + conf[__configinfo_struct[:current_value]] = nil + end + end + + when /^(#{__listval_optkeys.join('|')})$/ + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + conf[__configinfo_struct[:default_value]] = + simplelist(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] ) + conf[__configinfo_struct[:current_value]] = + simplelist(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__numlistval_optkeys.join('|')})$/ + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] \ + && conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ ) + conf[__configinfo_struct[:default_value]] = + list(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] \ + && conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ ) + conf[__configinfo_struct[:current_value]] = + list(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__tkvariable_optkeys.join('|')})$/ + conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + v = conf[__configinfo_struct[:default_value]] + if v.empty? + conf[__configinfo_struct[:default_value]] = nil + else + conf[__configinfo_struct[:default_value]] = TkVarAccess.new(v) + end + end + if ( conf[__configinfo_struct[:current_value]] ) + v = conf[__configinfo_struct[:current_value]] + if v.empty? + conf[__configinfo_struct[:current_value]] = nil + else + conf[__configinfo_struct[:current_value]] = TkVarAccess.new(v) + end + end + + when /^(#{__strval_optkeys.join('|')})$/ + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) + else + # conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) + conf = tk_split_list(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), 0, false, true) + end + conf[__configinfo_struct[:key]] = + conf[__configinfo_struct[:key]][1..-1] + + if ( __configinfo_struct[:alias] \ + && conf.size == __configinfo_struct[:alias] + 1 ) + if conf[__configinfo_struct[:alias]][0] == ?- + conf[__configinfo_struct[:alias]] = + conf[__configinfo_struct[:alias]][1..-1] + end + { conf[0] => conf[1] } + else + { conf.shift => conf } + end + + else + ret = {} + # tk_split_simplelist(_fromUTF8(tk_call_without_enc(*__confinfo_cmd))).each{|conflist| + # conf = tk_split_simplelist(conflist) + tk_split_simplelist(tk_call_without_enc(*__confinfo_cmd), false, false).each{|conflist| + conf = tk_split_simplelist(conflist, false, true) + conf[__configinfo_struct[:key]] = + conf[__configinfo_struct[:key]][1..-1] + + optkey = conf[__configinfo_struct[:key]] + case optkey + when /^(#{__val2ruby_optkeys().keys.join('|')})$/ + method = _symbolkey2str(__val2ruby_optkeys())[optkey] + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + optval = conf[__configinfo_struct[:default_value]] + begin + val = method.call(optval) + rescue => e + warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG + val = optval + end + conf[__configinfo_struct[:default_value]] = val + end + if ( conf[__configinfo_struct[:current_value]] ) + optval = conf[__configinfo_struct[:current_value]] + begin + val = method.call(optval) + rescue => e + warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG + val = optval + end + conf[__configinfo_struct[:current_value]] = val + end + + when /^(#{__strval_optkeys.join('|')})$/ + # do nothing + + when /^(#{__numval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + begin + conf[__configinfo_struct[:default_value]] = + number(conf[__configinfo_struct[:default_value]]) + rescue + conf[__configinfo_struct[:default_value]] = nil + end + end + if ( conf[__configinfo_struct[:current_value]] ) + begin + conf[__configinfo_struct[:current_value]] = + number(conf[__configinfo_struct[:current_value]]) + rescue + conf[__configinfo_struct[:current_value]] = nil + end + end + + when /^(#{__numstrval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + conf[__configinfo_struct[:default_value]] = + num_or_str(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] ) + conf[__configinfo_struct[:current_value]] = + num_or_str(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__boolval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + begin + conf[__configinfo_struct[:default_value]] = + bool(conf[__configinfo_struct[:default_value]]) + rescue + conf[__configinfo_struct[:default_value]] = nil + end + end + if ( conf[__configinfo_struct[:current_value]] ) + begin + conf[__configinfo_struct[:current_value]] = + bool(conf[__configinfo_struct[:current_value]]) + rescue + conf[__configinfo_struct[:current_value]] = nil + end + end + + when /^(#{__listval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + conf[__configinfo_struct[:default_value]] = + simplelist(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] ) + conf[__configinfo_struct[:current_value]] = + simplelist(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__numlistval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] \ + && conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ ) + conf[__configinfo_struct[:default_value]] = + list(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] \ + && conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ ) + conf[__configinfo_struct[:current_value]] = + list(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__tkvariable_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + v = conf[__configinfo_struct[:default_value]] + if v.empty? + conf[__configinfo_struct[:default_value]] = nil + else + conf[__configinfo_struct[:default_value]] = TkVarAccess.new + end + end + if ( conf[__configinfo_struct[:current_value]] ) + v = conf[__configinfo_struct[:current_value]] + if v.empty? + conf[__configinfo_struct[:current_value]] = nil + else + conf[__configinfo_struct[:current_value]] = TkVarAccess.new + end + end + + else + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + if conf[__configinfo_struct[:default_value]].index('{') + conf[__configinfo_struct[:default_value]] = + tk_split_list(conf[__configinfo_struct[:default_value]]) + else + conf[__configinfo_struct[:default_value]] = + tk_tcl2ruby(conf[__configinfo_struct[:default_value]]) + end + end + if conf[__configinfo_struct[:current_value]] + if conf[__configinfo_struct[:current_value]].index('{') + conf[__configinfo_struct[:current_value]] = + tk_split_list(conf[__configinfo_struct[:current_value]]) + else + conf[__configinfo_struct[:current_value]] = + tk_tcl2ruby(conf[__configinfo_struct[:current_value]]) + end + end + end + + if ( __configinfo_struct[:alias] \ + && conf.size == __configinfo_struct[:alias] + 1 ) + if conf[__configinfo_struct[:alias]][0] == ?- + conf[__configinfo_struct[:alias]] = + conf[__configinfo_struct[:alias]][1..-1] + end + ret[conf[0]] = conf[1] + else + ret[conf.shift] = conf + end + } + + __font_optkeys.each{|optkey| + optkey = optkey.to_s + fontconf = ret[optkey] + if fontconf.kind_of?(Array) + ret.delete(optkey) + ret.delete('latin' << optkey) + ret.delete('ascii' << optkey) + ret.delete('kanji' << optkey) + fnt = fontconf[__configinfo_struct[:default_value]] + if TkFont.is_system_font?(fnt) + fontconf[__configinfo_struct[:default_value]] \ + = TkNamedFont.new(fnt) + end + fontconf[__configinfo_struct[:current_value]] = fontobj(optkey) + ret[optkey] = fontconf + end + } + + __methodcall_optkeys.each{|optkey, m| + ret[optkey.to_s] = ['', '', '', self.__send__(m)] + } + + ret + end + end + end + end + private :__configinfo_core + + def configinfo(slot = nil) + if slot && TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + begin + __configinfo_core(slot) + rescue + Array.new(__configinfo_struct.values.max).unshift(slot.to_s) + end + else + __configinfo_core(slot) + end + end + + def current_configinfo(slot = nil) + if TkComm::GET_CONFIGINFO_AS_ARRAY + if slot + org_slot = slot + begin + conf = configinfo(slot) + if ( ! __configinfo_struct[:alias] \ + || conf.size > __configinfo_struct[:alias] + 1 ) + return {conf[0] => conf[-1]} + end + slot = conf[__configinfo_struct[:alias]] + end while(org_slot != slot) + fail RuntimeError, + "there is a configure alias loop about '#{org_slot}'" + else + ret = {} + configinfo().each{|cnf| + if ( ! __configinfo_struct[:alias] \ + || cnf.size > __configinfo_struct[:alias] + 1 ) + ret[cnf[0]] = cnf[-1] + end + } + ret + end + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY + ret = {} + configinfo(slot).each{|key, cnf| + ret[key] = cnf[-1] if cnf.kind_of?(Array) + } + ret + end + end +end + +class TkObject<TkKernel + extend TkCore + include Tk + include TkConfigMethod + include TkBindCore + +### --> definition is moved to TkUtil module +# def path +# @path +# end + + def epath + @path + end + + def to_eval + @path + end + + def tk_send(cmd, *rest) + tk_call(path, cmd, *rest) + end + def tk_send_without_enc(cmd, *rest) + tk_call_without_enc(path, cmd, *rest) + end + def tk_send_with_enc(cmd, *rest) + tk_call_with_enc(path, cmd, *rest) + end + # private :tk_send, :tk_send_without_enc, :tk_send_with_enc + + def tk_send_to_list(cmd, *rest) + tk_call_to_list(path, cmd, *rest) + end + def tk_send_to_list_without_enc(cmd, *rest) + tk_call_to_list_without_enc(path, cmd, *rest) + end + def tk_send_to_list_with_enc(cmd, *rest) + tk_call_to_list_with_enc(path, cmd, *rest) + end + def tk_send_to_simplelist(cmd, *rest) + tk_call_to_simplelist(path, cmd, *rest) + end + def tk_send_to_simplelist_without_enc(cmd, *rest) + tk_call_to_simplelist_without_enc(path, cmd, *rest) + end + def tk_send_to_simplelist_with_enc(cmd, *rest) + tk_call_to_simplelist_with_enc(path, cmd, *rest) + end + + def method_missing(id, *args) + name = id.id2name + case args.length + when 1 + if name[-1] == ?= + configure name[0..-2], args[0] + args[0] + else + configure name, args[0] + self + end + when 0 + begin + cget(name) + rescue + if self.kind_of?(TkWindow) && name != "to_ary" && name != "to_str" + fail NameError, + "unknown option '#{id}' for #{self.inspect} (deleted widget?)" + else + super(id, *args) + end +# fail NameError, +# "undefined local variable or method `#{name}' for #{self.to_s}", +# error_at + end + else + super(id, *args) +# fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at + end + end + +=begin + def [](id) + cget(id) + end + + def []=(id, val) + configure(id, val) + val + end +=end + + def event_generate(context, keys=nil) + if context.kind_of?(TkEvent::Event) + context.generate(self, ((keys)? keys: {})) + elsif keys + #tk_call('event', 'generate', path, + # "<#{tk_event_sequence(context)}>", *hash_kv(keys)) + tk_call_without_enc('event', 'generate', path, + "<#{tk_event_sequence(context)}>", + *hash_kv(keys, true)) + else + #tk_call('event', 'generate', path, "<#{tk_event_sequence(context)}>") + tk_call_without_enc('event', 'generate', path, + "<#{tk_event_sequence(context)}>") + end + end + + def tk_trace_variable(v) + #unless v.kind_of?(TkVariable) + # fail(ArgumentError, "type error (#{v.class}); must be TkVariable object") + #end + v + end + private :tk_trace_variable + + def destroy + #tk_call 'trace', 'vdelete', @tk_vn, 'w', @var_id if @var_id + end +end + + +class TkWindow<TkObject + include TkWinfo + extend TkBindCore + include Tk::Wm_for_General + include Tk::Busy + + @@WIDGET_INSPECT_FULL = false + def TkWindow._widget_inspect_full_? + @@WIDGET_INSPECT_FULL + end + def TkWindow._widget_inspect_full_=(mode) + @@WIDGET_INSPECT_FULL = (mode && true) || false + end + + TkCommandNames = [].freeze + ## ==> If TkCommandNames[0] is a string (not a null string), + ## assume the string is a Tcl/Tk's create command of the widget class. + WidgetClassName = ''.freeze + # WidgetClassNames[WidgetClassName] = self + ## ==> If self is a widget class, entry to the WidgetClassNames table. + def self.to_eval + self::WidgetClassName + end + + def initialize(parent=nil, keys=nil) + if parent.kind_of? Hash + keys = _symbolkey2str(parent) + parent = keys.delete('parent') + widgetname = keys.delete('widgetname') + install_win(if parent then parent.path end, widgetname) + without_creating = keys.delete('without_creating') + # if without_creating && !widgetname + # fail ArgumentError, + # "if set 'without_creating' to true, need to define 'widgetname'" + # end + elsif keys + keys = _symbolkey2str(keys) + widgetname = keys.delete('widgetname') + install_win(if parent then parent.path end, widgetname) + without_creating = keys.delete('without_creating') + # if without_creating && !widgetname + # fail ArgumentError, + # "if set 'without_creating' to true, need to define 'widgetname'" + # end + else + install_win(if parent then parent.path end) + end + if self.method(:create_self).arity == 0 + p 'create_self has no arg' if $DEBUG + create_self unless without_creating + if keys + # tk_call @path, 'configure', *hash_kv(keys) + configure(keys) + end + else + p 'create_self has args' if $DEBUG + fontkeys = {} + methodkeys = {} + if keys + #['font', 'kanjifont', 'latinfont', 'asciifont'].each{|key| + # fontkeys[key] = keys.delete(key) if keys.key?(key) + #} + __font_optkeys.each{|key| + fkey = key.to_s + fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) + + fkey = "kanji#{key}" + fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) + + fkey = "latin#{key}" + fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) + + fkey = "ascii#{key}" + fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) + } + + __optkey_aliases.each{|alias_name, real_name| + alias_name = alias_name.to_s + if keys.has_key?(alias_name) + keys[real_name.to_s] = keys.delete(alias_name) + end + } + + __methodcall_optkeys.each{|key| + key = key.to_s + methodkeys[key] = keys.delete(key) if keys.key?(key) + } + + __ruby2val_optkeys.each{|key, method| + key = key.to_s + keys[key] = method.call(keys[key]) if keys.has_key?(key) + } + end + if without_creating && keys + #configure(keys) + configure(__conv_keyonly_opts(keys)) + else + #create_self(keys) + create_self(__conv_keyonly_opts(keys)) + end + font_configure(fontkeys) unless fontkeys.empty? + configure(methodkeys) unless methodkeys.empty? + end + end + + def create_self(keys) + # may need to override + begin + cmd = self.class::TkCommandNames[0] + fail unless (cmd.kind_of?(String) && cmd.length > 0) + rescue + fail RuntimeError, "class #{self.class} may be an abstract class" + end + + if keys and keys != None + unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + tk_call_without_enc(cmd, @path, *hash_kv(keys, true)) + else + begin + tk_call_without_enc(cmd, @path, *hash_kv(keys, true)) + rescue => e + tk_call_without_enc(cmd, @path) + keys = __check_available_configure_options(keys) + unless keys.empty? + begin + # try to configure + configure(keys) + rescue + # fail => includes options adaptable when creattion only? + begin + tk_call_without_enc('destroy', @path) + rescue + # cannot rescue options error + fail e + else + # re-create widget + tk_call_without_enc(cmd, @path, *hash_kv(keys, true)) + end + end + end + end + end + else + tk_call_without_enc(cmd, @path) + end + end + private :create_self + + def inspect + if @@WIDGET_INSPECT_FULL + super + else + str = super + str[0..(str.index(' '))] << '@path=' << @path.inspect << '>' + end + end + + def exist? + TkWinfo.exist?(self) + end + + alias subcommand tk_send + + def bind_class + @db_class || self.class() + end + + def database_classname + TkWinfo.classname(self) + end + def database_class + name = database_classname() + if WidgetClassNames[name] + WidgetClassNames[name] + else + TkDatabaseClass.new(name) + end + end + def self.database_classname + self::WidgetClassName + end + def self.database_class + WidgetClassNames[self::WidgetClassName] + end + + def pack(keys = nil) + #tk_call_without_enc('pack', epath, *hash_kv(keys, true)) + if keys + TkPack.configure(self, keys) + else + TkPack.configure(self) + end + self + end + + def pack_in(target, keys = nil) + if keys + keys = keys.dup + keys['in'] = target + else + keys = {'in'=>target} + end + #tk_call 'pack', epath, *hash_kv(keys) + TkPack.configure(self, keys) + self + end + + def pack_forget + #tk_call_without_enc('pack', 'forget', epath) + TkPack.forget(self) + self + end + alias unpack pack_forget + + def pack_config(slot, value=None) + #if slot.kind_of? Hash + # tk_call 'pack', 'configure', epath, *hash_kv(slot) + #else + # tk_call 'pack', 'configure', epath, "-#{slot}", value + #end + if slot.kind_of? Hash + TkPack.configure(self, slot) + else + TkPack.configure(self, slot=>value) + end + end + alias pack_configure pack_config + + def pack_info() + #ilist = list(tk_call('pack', 'info', epath)) + #info = {} + #while key = ilist.shift + # info[key[1..-1]] = ilist.shift + #end + #return info + TkPack.info(self) + end + + def pack_propagate(mode=None) + #if mode == None + # bool(tk_call('pack', 'propagate', epath)) + #else + # tk_call('pack', 'propagate', epath, mode) + # self + #end + if mode == None + TkPack.propagate(self) + else + TkPack.propagate(self, mode) + self + end + end + + def pack_slaves() + #list(tk_call('pack', 'slaves', epath)) + TkPack.slaves(self) + end + + def grid(keys = nil) + #tk_call 'grid', epath, *hash_kv(keys) + if keys + TkGrid.configure(self, keys) + else + TkGrid.configure(self) + end + self + end + + def grid_in(target, keys = nil) + if keys + keys = keys.dup + keys['in'] = target + else + keys = {'in'=>target} + end + #tk_call 'grid', epath, *hash_kv(keys) + TkGrid.configure(self, keys) + self + end + + def grid_anchor(anchor=None) + if anchor == None + TkGrid.anchor(self) + else + TkGrid.anchor(self, anchor) + self + end + end + + def grid_forget + #tk_call('grid', 'forget', epath) + TkGrid.forget(self) + self + end + alias ungrid grid_forget + + def grid_bbox(*args) + #list(tk_call('grid', 'bbox', epath, *args)) + TkGrid.bbox(self, *args) + end + + def grid_config(slot, value=None) + #if slot.kind_of? Hash + # tk_call 'grid', 'configure', epath, *hash_kv(slot) + #else + # tk_call 'grid', 'configure', epath, "-#{slot}", value + #end + if slot.kind_of? Hash + TkGrid.configure(self, slot) + else + TkGrid.configure(self, slot=>value) + end + end + alias grid_configure grid_config + + def grid_columnconfig(index, keys) + #tk_call('grid', 'columnconfigure', epath, index, *hash_kv(keys)) + TkGrid.columnconfigure(self, index, keys) + end + alias grid_columnconfigure grid_columnconfig + + def grid_rowconfig(index, keys) + #tk_call('grid', 'rowconfigure', epath, index, *hash_kv(keys)) + TkGrid.rowconfigure(self, index, keys) + end + alias grid_rowconfigure grid_rowconfig + + def grid_columnconfiginfo(index, slot=nil) + #if slot + # tk_call('grid', 'columnconfigure', epath, index, "-#{slot}").to_i + #else + # ilist = list(tk_call('grid', 'columnconfigure', epath, index)) + # info = {} + # while key = ilist.shift + # info[key[1..-1]] = ilist.shift + # end + # info + #end + TkGrid.columnconfiginfo(self, index, slot) + end + + def grid_rowconfiginfo(index, slot=nil) + #if slot + # tk_call('grid', 'rowconfigure', epath, index, "-#{slot}").to_i + #else + # ilist = list(tk_call('grid', 'rowconfigure', epath, index)) + # info = {} + # while key = ilist.shift + # info[key[1..-1]] = ilist.shift + # end + # info + #end + TkGrid.rowconfiginfo(self, index, slot) + end + + def grid_column(index, keys=nil) + if keys.kind_of?(Hash) + grid_columnconfigure(index, keys) + else + grid_columnconfiginfo(index, keys) + end + end + + def grid_row(index, keys=nil) + if keys.kind_of?(Hash) + grid_rowconfigure(index, keys) + else + grid_rowconfiginfo(index, keys) + end + end + + def grid_info() + #list(tk_call('grid', 'info', epath)) + TkGrid.info(self) + end + + def grid_location(x, y) + #list(tk_call('grid', 'location', epath, x, y)) + TkGrid.location(self, x, y) + end + + def grid_propagate(mode=None) + #if mode == None + # bool(tk_call('grid', 'propagate', epath)) + #else + # tk_call('grid', 'propagate', epath, mode) + # self + #end + if mode == None + TkGrid.propagate(self) + else + TkGrid.propagate(self, mode) + self + end + end + + def grid_remove() + #tk_call 'grid', 'remove', epath + TkGrid.remove(self) + self + end + + def grid_size() + #list(tk_call('grid', 'size', epath)) + TkGrid.size(self) + end + + def grid_slaves(keys = nil) + #list(tk_call('grid', 'slaves', epath, *hash_kv(args))) + TkGrid.slaves(self, keys) + end + + def place(keys) + #tk_call 'place', epath, *hash_kv(keys) + TkPlace.configure(self, keys) + self + end + + def place_in(target, keys = nil) + if keys + keys = keys.dup + keys['in'] = target + else + keys = {'in'=>target} + end + #tk_call 'place', epath, *hash_kv(keys) + TkPlace.configure(self, keys) + self + end + + def place_forget + #tk_call 'place', 'forget', epath + TkPlace.forget(self) + self + end + alias unplace place_forget + + def place_config(slot, value=None) + #if slot.kind_of? Hash + # tk_call 'place', 'configure', epath, *hash_kv(slot) + #else + # tk_call 'place', 'configure', epath, "-#{slot}", value + #end + TkPlace.configure(self, slot, value) + end + alias place_configure place_config + + def place_configinfo(slot = nil) + # for >= Tk8.4a2 ? + #if slot + # conf = tk_split_list(tk_call('place', 'configure', epath, "-#{slot}") ) + # conf[0] = conf[0][1..-1] + # conf + #else + # tk_split_simplelist(tk_call('place', + # 'configure', epath)).collect{|conflist| + # conf = tk_split_simplelist(conflist) + # conf[0] = conf[0][1..-1] + # conf + # } + #end + TkPlace.configinfo(self, slot) + end + + def place_info() + #ilist = list(tk_call('place', 'info', epath)) + #info = {} + #while key = ilist.shift + # info[key[1..-1]] = ilist.shift + #end + #return info + TkPlace.info(self) + end + + def place_slaves() + #list(tk_call('place', 'slaves', epath)) + TkPlace.slaves(self) + end + + def set_focus(force=false) + if force + tk_call_without_enc('focus', '-force', path) + else + tk_call_without_enc('focus', path) + end + self + end + alias focus set_focus + + def grab(opt = nil) + unless opt + tk_call_without_enc('grab', 'set', path) + return self + end + + case opt + when 'set', :set + tk_call_without_enc('grab', 'set', path) + return self + when 'global', :global + #return(tk_call('grab', 'set', '-global', path)) + tk_call_without_enc('grab', 'set', '-global', path) + return self + when 'release', :release + #return tk_call('grab', 'release', path) + tk_call_without_enc('grab', 'release', path) + return self + when 'current', :current + return window(tk_call_without_enc('grab', 'current', path)) + when 'status', :status + return tk_call_without_enc('grab', 'status', path) + else + return tk_call_without_enc('grab', opt, path) + end + end + + def grab_current + grab('current') + end + alias current_grab grab_current + def grab_release + grab('release') + end + alias release_grab grab_release + def grab_set + grab('set') + end + alias set_grab grab_set + def grab_set_global + grab('global') + end + alias set_global_grab grab_set_global + def grab_status + grab('status') + end + + def lower(below=None) + # below = below.epath if below.kind_of?(TkObject) + below = _epath(below) + tk_call 'lower', epath, below + self + end + alias lower_window lower + def raise(above=None) + #above = above.epath if above.kind_of?(TkObject) + above = _epath(above) + tk_call 'raise', epath, above + self + end + alias raise_window raise + + def command(cmd=nil, &b) + if cmd + configure_cmd('command', cmd) + elsif b + configure_cmd('command', Proc.new(&b)) + else + cget('command') + end + end + + def colormodel(model=None) + tk_call('tk', 'colormodel', path, model) + self + end + + def caret(keys=nil) + TkXIM.caret(path, keys) + end + + def destroy + super + children = [] + rexp = /^#{self.path}\.[^.]+$/ + TkCore::INTERP.tk_windows.each{|path, obj| + children << [path, obj] if path =~ rexp + } + if defined?(@cmdtbl) + for id in @cmdtbl + uninstall_cmd id + end + end + + children.each{|path, obj| + obj.instance_eval{ + if defined?(@cmdtbl) + for id in @cmdtbl + uninstall_cmd id + end + end + } + TkCore::INTERP.tk_windows.delete(path) + } + + begin + tk_call_without_enc('destroy', epath) + rescue + end + uninstall_win + end + + def wait_visibility(on_thread = true) + if $SAFE >= 4 + fail SecurityError, "can't wait visibility at $SAFE >= 4" + end + on_thread &= (Thread.list.size != 1) + if on_thread + INTERP._thread_tkwait('visibility', path) + else + INTERP._invoke('tkwait', 'visibility', path) + end + end + def eventloop_wait_visibility + wait_visibility(false) + end + def thread_wait_visibility + wait_visibility(true) + end + alias wait wait_visibility + alias tkwait wait_visibility + alias eventloop_wait eventloop_wait_visibility + alias eventloop_tkwait eventloop_wait_visibility + alias eventloop_tkwait_visibility eventloop_wait_visibility + alias thread_wait thread_wait_visibility + alias thread_tkwait thread_wait_visibility + alias thread_tkwait_visibility thread_wait_visibility + + def wait_destroy(on_thread = true) + if $SAFE >= 4 + fail SecurityError, "can't wait destroy at $SAFE >= 4" + end + on_thread &= (Thread.list.size != 1) + if on_thread + INTERP._thread_tkwait('window', epath) + else + INTERP._invoke('tkwait', 'window', epath) + end + end + alias wait_window wait_destroy + def eventloop_wait_destroy + wait_destroy(false) + end + alias eventloop_wait_window eventloop_wait_destroy + def thread_wait_destroy + wait_destroy(true) + end + alias thread_wait_window thread_wait_destroy + + alias tkwait_destroy wait_destroy + alias tkwait_window wait_destroy + + alias eventloop_tkwait_destroy eventloop_wait_destroy + alias eventloop_tkwait_window eventloop_wait_destroy + + alias thread_tkwait_destroy thread_wait_destroy + alias thread_tkwait_window thread_wait_destroy + + def bindtags(taglist=nil) + if taglist + fail ArgumentError, "taglist must be Array" unless taglist.kind_of? Array + tk_call('bindtags', path, taglist) + taglist + else + list(tk_call('bindtags', path)).collect{|tag| + if tag.kind_of?(String) + if cls = WidgetClassNames[tag] + cls + elsif btag = TkBindTag.id2obj(tag) + btag + else + tag + end + else + tag + end + } + end + end + + def bindtags=(taglist) + bindtags(taglist) + taglist + end + + def bindtags_shift + taglist = bindtags + tag = taglist.shift + bindtags(taglist) + tag + end + + def bindtags_unshift(tag) + bindtags(bindtags().unshift(tag)) + end +end +TkWidget = TkWindow + +# freeze core modules +#TclTkLib.freeze +#TclTkIp.freeze +#TkUtil.freeze +#TkKernel.freeze +#TkComm.freeze +#TkComm::Event.freeze +#TkCore.freeze +#Tk.freeze + +module Tk + RELEASE_DATE = '2014-10-19'.freeze + + autoload :AUTO_PATH, 'tk/variable' + autoload :TCL_PACKAGE_PATH, 'tk/variable' + autoload :PACKAGE_PATH, 'tk/variable' + autoload :TCL_LIBRARY_PATH, 'tk/variable' + autoload :LIBRARY_PATH, 'tk/variable' + autoload :TCL_PRECISION, 'tk/variable' +end + +# call setup script for Tk extension libraries (base configuration) +begin + require 'tkextlib/version.rb' + require 'tkextlib/setup.rb' +rescue LoadError + # ignore +end diff --git a/jni/ruby/ext/tk/lib/tk/after.rb b/jni/ruby/ext/tk/lib/tk/after.rb new file mode 100644 index 0000000..fac9de4 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/after.rb @@ -0,0 +1,6 @@ +# +# tk/after.rb : methods for Tcl/Tk after command +# +# $Id: after.rb 25189 2009-10-02 12:04:37Z akr $ +# +require 'tk/timer' diff --git a/jni/ruby/ext/tk/lib/tk/autoload.rb b/jni/ruby/ext/tk/lib/tk/autoload.rb new file mode 100644 index 0000000..451922c --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/autoload.rb @@ -0,0 +1,762 @@ +# +# autoload +# +############################################ +# geometry manager +module Tk + autoload :Grid, 'tk/grid' + def Grid(*args); TkGrid.configure(*args); end + + autoload :Pack, 'tk/pack' + def Pack(*args); TkPack.configure(*args); end + + autoload :Place, 'tk/place' + def Place(*args); TkPlace.configure(*args); end +end + +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 + + +############################################ +# classes on Tk module +module Tk + autoload :Busy, 'tk/busy' + + autoload :Button, 'tk/button' + + autoload :Canvas, 'tk/canvas' + + autoload :CheckButton, 'tk/checkbutton' + autoload :Checkbutton, 'tk/checkbutton' + + autoload :Entry, 'tk/entry' + + autoload :Frame, 'tk/frame' + + autoload :Label, 'tk/label' + + autoload :LabelFrame, 'tk/labelframe' + autoload :Labelframe, 'tk/labelframe' + + autoload :Listbox, 'tk/listbox' + + autoload :Menu, 'tk/menu' + autoload :MenuClone, 'tk/menu' + autoload :CloneMenu, 'tk/menu' + autoload :SystemMenu, 'tk/menu' + autoload :SysMenu_Help, 'tk/menu' + autoload :SysMenu_System, 'tk/menu' + autoload :SysMenu_Apple, 'tk/menu' + autoload :Menubutton, 'tk/menu' + autoload :MenuButton, 'tk/menu' + autoload :OptionMenubutton, 'tk/menu' + autoload :OptionMenBbutton, 'tk/menu' + + autoload :Message, 'tk/message' + + autoload :PanedWindow, 'tk/panedwindow' + autoload :Panedwindow, 'tk/panedwindow' + + autoload :RadioButton, 'tk/radiobutton' + autoload :Radiobutton, 'tk/radiobutton' + + autoload :Root, 'tk/root' + + autoload :Scale, 'tk/scale' + + autoload :Scrollbar, 'tk/scrollbar' + autoload :XScrollbar, 'tk/scrollbar' + autoload :YScrollbar, 'tk/scrollbar' + + autoload :Spinbox, 'tk/spinbox' + + autoload :Text, 'tk/text' + + autoload :Toplevel, 'tk/toplevel' +end + + +############################################ +# sub-module of Tk +module Tk + autoload :Clock, 'tk/clock' + + autoload :OptionObj, 'tk/optionobj' + + autoload :X_Scrollable, 'tk/scrollable' + autoload :Y_Scrollable, 'tk/scrollable' + autoload :Scrollable, 'tk/scrollable' + + autoload :Fontchooser, 'tk/fontchooser' + + autoload :Wm, 'tk/wm' + autoload :Wm_for_General, 'tk/wm' + + autoload :MacResource, 'tk/macpkg' + + autoload :WinDDE, 'tk/winpkg' + autoload :WinRegistry, 'tk/winpkg' + + autoload :ValidateConfigure, 'tk/validation' + autoload :ItemValidateConfigure, 'tk/validation' + + 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 + + +############################################ +# toplevel classes/modules (fixed) +autoload :TkBgError, 'tk/bgerror' + +autoload :TkBindTag, 'tk/bindtag' +autoload :TkBindTagAll, 'tk/bindtag' +autoload :TkDatabaseClass, 'tk/bindtag' + +autoload :TkConsole, 'tk/console' + +autoload :TkcItem, 'tk/canvas' +autoload :TkcArc, 'tk/canvas' +autoload :TkcBitmap, 'tk/canvas' +autoload :TkcImage, 'tk/canvas' +autoload :TkcLine, 'tk/canvas' +autoload :TkcOval, 'tk/canvas' +autoload :TkcPolygon, 'tk/canvas' +autoload :TkcRectangle, 'tk/canvas' +autoload :TkcText, 'tk/canvas' +autoload :TkcWindow, '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 :TkClipboard, 'tk/clipboard' + +autoload :TkComposite, 'tk/composite' + +autoload :TkConsole, 'tk/console' + +autoload :TkDialog, 'tk/dialog' +autoload :TkDialog2, 'tk/dialog' +autoload :TkDialogObj, 'tk/dialog' +autoload :TkWarning, 'tk/dialog' +autoload :TkWarning2, 'tk/dialog' +autoload :TkWarningObj, 'tk/dialog' + +autoload :TkEvent, 'tk/event' + +autoload :TkFont, 'tk/font' +autoload :TkNamedFont, 'tk/font' + +autoload :TkImage, 'tk/image' +autoload :TkBitmapImage, 'tk/image' +autoload :TkPhotoImage, 'tk/image' + +autoload :TkItemConfigMethod, 'tk/itemconfig' + +autoload :TkTreatItemFont, 'tk/itemfont' + +autoload :TkKinput, 'tk/kinput' + +autoload :TkSystemMenu, 'tk/menu' + +autoload :TkMenubar, 'tk/menubar' + +autoload :TkMenuSpec, 'tk/menuspec' + +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 :TkRoot, 'tk/root' + +autoload :TkScrollbox, 'tk/scrollbox' + +autoload :TkSelection, 'tk/selection' + +autoload :TkTreatTagFont, 'tk/tagfont' + +autoload :TkTextImage, 'tk/textimage' +autoload :TktImage, 'tk/textimage' + +autoload :TkTextMark, 'tk/textmark' +autoload :TkTextNamedMark, 'tk/textmark' +autoload :TkTextMarkInsert, 'tk/textmark' +autoload :TkTextMarkCurrent, 'tk/textmark' +autoload :TkTextMarkAnchor, 'tk/textmark' +autoload :TktMark, 'tk/textmark' +autoload :TktNamedMark, 'tk/textmark' +autoload :TktMarkInsert, 'tk/textmark' +autoload :TktMarkCurrent, 'tk/textmark' +autoload :TktMarkAnchor, 'tk/textmark' + +autoload :TkTextTag, 'tk/texttag' +autoload :TkTextNamedTag, 'tk/texttag' +autoload :TkTextTagSel, 'tk/texttag' +autoload :TktTag, 'tk/texttag' +autoload :TktNamedTag, 'tk/texttag' +autoload :TktTagSel, 'tk/texttag' + +autoload :TkTextWindow, 'tk/textwindow' +autoload :TktWindow, 'tk/textwindow' + +autoload :TkAfter, 'tk/timer' +autoload :TkTimer, 'tk/timer' +autoload :TkRTTimer, 'tk/timer' + +autoload :TkTextWin, 'tk/txtwin_abst' + +autoload :TkValidation, 'tk/validation' +autoload :TkValidateCommand, 'tk/validation' + +autoload :TkVariable, 'tk/variable' +autoload :TkVarAccess, 'tk/variable' + +autoload :TkVirtualEvent, 'tk/virtevent' +autoload :TkNamedVirtualEvent,'tk/virtevent' + +autoload :TkWinfo, 'tk/winfo' + +autoload :TkXIM, 'tk/xim' + + +############################################ +# toplevel classes/modules (switchable) +module Tk + @TOPLEVEL_ALIAS_TABLE = {} + @TOPLEVEL_ALIAS_TABLE[:Tk] = { + :TkButton => 'tk/button', + + :TkCanvas => 'tk/canvas', + + :TkCheckButton => 'tk/checkbutton', + :TkCheckbutton => 'tk/checkbutton', + + # :TkDialog => 'tk/dialog', + # :TkDialog2 => 'tk/dialog', + # :TkDialogObj => 'tk/dialog', + # :TkWarning => 'tk/dialog', + # :TkWarning2 => 'tk/dialog', + # :TkWarningObj => 'tk/dialog', + + :TkEntry => 'tk/entry', + + :TkFrame => 'tk/frame', + + :TkLabel => 'tk/label', + + :TkLabelFrame => 'tk/labelframe', + :TkLabelframe => 'tk/labelframe', + + :TkListbox => 'tk/listbox', + + :TkMacResource => 'tk/macpkg', + + :TkMenu => 'tk/menu', + :TkMenuClone => 'tk/menu', + :TkCloneMenu => 'tk/menu', + # :TkSystemMenu => 'tk/menu', + :TkSysMenu_Help => 'tk/menu', + :TkSysMenu_System => 'tk/menu', + :TkSysMenu_Apple => 'tk/menu', + :TkMenubutton => 'tk/menu', + :TkMenuButton => 'tk/menu', + :TkOptionMenubutton => 'tk/menu', + :TkOptionMenuButton => 'tk/menu', + + :TkMessage => 'tk/message', + + :TkPanedWindow => 'tk/panedwindow', + :TkPanedwindow => 'tk/panedwindow', + + :TkRadioButton => 'tk/radiobutton', + :TkRadiobutton => 'tk/radiobutton', + + # :TkRoot => 'tk/root', + + :TkScale => 'tk/scale', + + :TkScrollbar => 'tk/scrollbar', + :TkXScrollbar => 'tk/scrollbar', + :TkYScrollbar => 'tk/scrollbar', + + :TkSpinbox => 'tk/spinbox', + + :TkText => 'tk/text', + + :TkToplevel => 'tk/toplevel', + + :TkWinDDE => 'tk/winpkg', + :TkWinRegistry => 'tk/winpkg', + } + + @TOPLEVEL_ALIAS_OWNER = {} + + @TOPLEVEL_ALIAS_SETUP_PROC = {} + + @AUTOLOAD_FILE_SYM_TABLE = Hash.new{|h,k| h[k]={}} # TABLE[file][sym] -> obj + + @current_default_widget_set = nil + + module TOPLEVEL_ALIASES; end +end + +class Object + include Tk::TOPLEVEL_ALIASES +end + +############################################ +# methods to control default widget set +############################################ + +class << Tk + def default_widget_set + @current_default_widget_set + end + + def default_widget_set=(target) + target = target.to_sym + return target if target == @current_default_widget_set + + if (cmd = @TOPLEVEL_ALIAS_SETUP_PROC[target]) + cmd.call(target) + end + + _replace_toplevel_aliases(target) + end + + def widget_set_symbols + @TOPLEVEL_ALIAS_TABLE.keys + end + + def toplevel_aliases_on_widget_set(widget_set) + if (tbl = @TOPLEVEL_ALIAS_TABLE[widget_set.to_sym]) + tbl.collect{|k, v| (v.nil?)? nil: k}.compact + else + fail ArgumentError, "unknown widget_set #{widget_set.to_sym.inspect}" + end + end + + def __toplevel_alias_setup_proc__(*target_list, &cmd) + target_list.each{|target| @TOPLEVEL_ALIAS_SETUP_PROC[target.to_sym] = cmd} + end + + def topobj_defined?(sym) #=> alias_filename or object or false + Object.autoload?(sym) || + (Object.const_defined?(sym) && Object.const_get(sym)) + end + def topalias_defined?(sym) #=> alias_filename or object or false + Tk::TOPLEVEL_ALIASES.autoload?(sym) || + (Tk::TOPLEVEL_ALIASES.const_defined?(sym) && + Tk::TOPLEVEL_ALIASES.const_get(sym)) + end + def define_topobj(sym, obj) + if obj.kind_of? String + # obj is an autoload path + Object.autoload(sym, obj) + unless Object.autoload?(sym) + # file is autoloaded? + if @AUTOLOAD_FILE_SYM_TABLE.has_key?(obj) && + (loaded_obj = @AUTOLOAD_FILE_SYM_TABLE[obj][sym]) + Object.const_set(sym, loaded_obj) + else + fail ArgumentError, "cannot define autoload file (already loaded?)" + end + end + else + # object + Object.const_set(sym, obj) + end + end + def define_topalias(sym, obj) + if obj.kind_of? String + # obj is an autoload path + Tk::TOPLEVEL_ALIASES.autoload(sym, obj) + unless Tk::TOPLEVEL_ALIASES.autoload?(sym) + # file is autoloaded? + if @AUTOLOAD_FILE_SYM_TABLE.has_key?(obj) && + (loaded_obj = @AUTOLOAD_FILE_SYM_TABLE[obj][sym]) + Tk::TOPLEVEL_ALIASES.const_set(sym, loaded_obj) + else + fail ArgumentError, "cannot define autoload file (already loaded?)" + end + end + else + # object + Tk::TOPLEVEL_ALIASES.const_set(sym, obj) + end + end + def replace_topobj(sym, obj) #=> old_obj (alias_filename or object) or nil + if old_obj = topobj_defined?(sym) + Object.class_eval{remove_const sym} rescue nil # ignore err + end + define_topobj(sym, obj) + old_obj + end + def replace_topalias(sym, obj) #=> old_obj (alias_filename or object) or nil + if old_obj = topalias_defined?(sym) + Tk::TOPLEVEL_ALIASES.module_eval{remove_const sym} rescue nil #ignore err + end + define_topalias(sym, obj) + old_obj + end + private :topobj_defined?, :topalias_defined? + private :define_topobj, :define_topalias + private :replace_topobj, :replace_topalias + + def __regist_toplevel_aliases__(target, obj, *symbols) + # initial regist + @TOPLEVEL_ALIAS_TABLE[target = target.to_sym] ||= {} + symbols.each{|sym| + @TOPLEVEL_ALIAS_TABLE[target][sym = sym.to_sym] = obj + if !topalias_defined?(sym) || target == @current_default_widget_set + @TOPLEVEL_ALIAS_OWNER[sym] = target + replace_topalias(sym, obj) + replace_topobj(sym, obj) unless obj.kind_of?(String) # NOT autoload + end + } + end + + def regist_sym_for_loaded_file(auto, obj, sym) + @AUTOLOAD_FILE_SYM_TABLE[auto][sym] = obj + + reg = /^#{Regexp.quote(auto)}(\.rb|\.so|)$/ + @TOPLEVEL_ALIAS_TABLE.each_key{|set| + if @TOPLEVEL_ALIAS_TABLE[set][sym] =~ reg + @TOPLEVEL_ALIAS_TABLE[set][sym] = obj + if @TOPLEVEL_ALIAS_OWNER[sym].nil? || @TOPLEVEL_ALIAS_OWNER[sym] == set + replace_topalias(sym, obj) + replace_topobj(sym, obj) if set == @current_default_widget_set + end + end + } + if (f = Object.autoload?(sym)) && f =~ reg + replace_topobj(sym, obj) + end + if (f = Tk::TOPLEVEL_ALIASES.autoload?(sym)) && f =~ reg + replace_topalias(sym, obj) + end + end + private :regist_sym_for_loaded_file + + def set_topalias(target, obj, sym) + # obj is a kind of String : define autoload path + # Class : use the class object + if target == @current_default_widget_set + case @TOPLEVEL_ALIAS_OWNER[sym] + when false + # Object::sym is out of control. --> not change + # Make ALIAS::sym under control, because target widget set is current. + # Keep OWNER[sym] + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + + when target + if current_obj = topobj_defined?(sym) + if current_obj == obj + # Make current_obj under control. + # Keep Object::sym. + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + + else # current_obj != obj + if current_obj == topalias_defined?(sym) + # Change controlled object + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + replace_topobj(sym, obj) + + else # current_obj != topalias_defined?(sym) + # Maybe current_obj is defined by user. --> OWNER[sym] = faise + # Keep Object::sym. + @TOPLEVEL_ALIAS_OWNER[sym] = false + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + end + end + + else # NOT topobj_defined?(sym) + # New definition for sym at target. + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + define_topobj(sym, obj) + end + + when nil + # New definition for sym at target. + @TOPLEVEL_ALIAS_OWNER[sym] = target + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + + else # others + # Maybe planning to make sym under control. + @TOPLEVEL_ALIAS_OWNER[sym] = target + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + replace_topobj(sym, obj) + end + + else # target != @current_default_widget_set + case @TOPLEVEL_ALIAS_OWNER[sym] + when false + # Object::sym is out of control. --> not change + if topalias_defined?(sym) + # ALIAS[sym] may be defined by other widget set. + # Keep Object::sym (even if it is not defined) + # Keep ALIAS[sym]. + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + + else # NOT topalias_defined?(sym) + # Nobody controls ALIAS[sym]. + # At leaset, current widget set doesn't control ALIAS[sym]. + # Keep Object::sym (even if it is not defined) + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + define_topalias(sym, obj) + end + + when target + # Maybe change controlled object, because Object::sym is under control. + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + replace_topobj(sym, obj) + + when nil + # New definition for sym + @TOPLEVEL_ALIAS_OWNER[sym] = target + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + replace_topalias(sym, obj) + replace_topobj(sym, obj) + + else # others + # An other widget set controls sym. + # Keep Object::sym (even if it is not defined) + # Keep ALIAS[sym]. + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[target][sym] = obj + + end + end + + sym + end + private :set_topalias + + def __set_toplevel_aliases__(target, obj, *symbols) + # obj is a kind of String : define autoload path + # Class : use the class object + target = target.to_sym + symbols.each{|sym| set_topalias(target, obj, sym.to_sym)} + end + + def __set_loaded_toplevel_aliases__(autopath, target, obj, *symbols) + # autopath is an autoload file + # Currently, this method doesn't support that autoload loads + # different toplevels between <basename>.rb and <basename>.so extension. + shortpath = (autopath =~ /^(.*)(.rb|.so)$/)? $1: autopath + target = target.to_sym + symbols.map!{|sym| sym.to_sym} + + symbols.each{|sym| regist_sym_for_loaded_file(shortpath, obj, sym) } + symbols.each{|sym| set_topalias(target, obj, sym)} + end + + def backup_current_topdef(sym) + return if (current = @current_default_widget_set).nil? + + case @TOPLEVEL_ALIAS_OWNER[sym] + when false + # Object::sym is out of control. + if (cur_alias = topalias_defined?(sym)) && ! cur_alias.kind_of?(String) + @TOPLEVEL_ALIAS_TABLE[current][sym] = cur_alias + end + + when current + if cur_obj = topobj_defined?(sym) + if ! cur_obj.kind_of?(String) && (cur_alias = topalias_defined?(sym)) + if cur_alias.kind_of?(String) + # Mayby, user replaced Object::sym. + # Make Object::sym out of control. + @TOPLEVEL_ALIAS_OWNER[sym] = false + elsif cur_obj == cur_alias + # Possibley, defined normally. Backup it + @TOPLEVEL_ALIAS_TABLE[current][sym] = cur_alias + else + # Mayby, user replaced Object::sym. + # Make Object::sym out of control. + @TOPLEVEL_ALIAS_OWNER[sym] = false + end + end + else + # Mayby, user replaced Object::sym. + # Make Object::sym out of control. + @TOPLEVEL_ALIAS_OWNER[sym] = false + end + + when nil + # Object::sym is out of control. + if (cur_alias = topalias_defined?(sym)) && ! cur_alias.kind_of?(String) + # Possibley, defined normally. Backup it. + @TOPLEVEL_ALIAS_TABLE[current][sym] = cur_alias + end + else + # No authority to control Object::sym and ALIASES::sym. + # Do nothing. + end + end + private :backup_current_topdef + + def _replace_toplevel_aliases(target) + # backup + @TOPLEVEL_ALIAS_TABLE[target].each_key{|sym| + backup_current_topdef(sym) + } + + # replace + @TOPLEVEL_ALIAS_TABLE[target].each_key{|sym| + next if (obj = @TOPLEVEL_ALIAS_TABLE[target][sym]).nil? + if @TOPLEVEL_ALIAS_OWNER[sym] == false + # Object::sym is out of control. --> not change + # Keep OWNER[sym]. + replace_topalias(sym, obj) + else + # New definition + @TOPLEVEL_ALIAS_OWNER[sym] = target + replace_topalias(sym, obj) + replace_topobj(sym, obj) + end + } + + # change default_widget_set + @current_default_widget_set = target + end + private :_replace_toplevel_aliases + + def __import_toplevel_aliases__(target, *symbols) + current = @current_default_widget_set + symbols.each{|sym| + sym = sym.to_sym + if (obj = @TOPLEVEL_ALIAS_TABLE[target][sym]).nil? + # remove + @TOPLEVEL_ALIAS_TABLE[current].delete(sym) + @TOPLEVEL_ALIAS_OWNER.delete(sym) + Tk::TOPLEVEL_ALIASES.module_eval{remove_const sym} if topalias_defined?(sym) + Object.class_eval{remove_const sym} if topobj_defined?(sym) + + elsif obj == false + # remove, but OWNER[sym] <- false and not treat Object::sym + @TOPLEVEL_ALIAS_TABLE[current].delete(sym) + @TOPLEVEL_ALIAS_OWNER[sym] = false + Tk::TOPLEVEL_ALIASES.module_eval{remove_const sym} if topalias_defined?(sym) + + elsif @TOPLEVEL_ALIAS_OWNER[sym] == false + # Object::sym is out of control. --> not change + # Keep OWNER[sym]. + @TOPLEVEL_ALIAS_TABLE[current][sym] = obj + replace_topalias(sym, obj) + + else + # new definition under control + @TOPLEVEL_ALIAS_OWNER[sym] = current + @TOPLEVEL_ALIAS_TABLE[current][sym] = obj + replace_topalias(sym, obj) + replace_topobj(sym, obj) + end + } + end + + def __remove_toplevel_aliases__(*symbols) + # remove toplevel aliases of current widget set + current = @current_default_widget_set + symbols.each{|sym| + sym = sym.to_sym + @TOPLEVEL_ALIAS_TABLE[current].delete(sym) + @TOPLEVEL_ALIAS_OWNER.delete(sym) + Tk::TOPLEVEL_ALIASES.module_eval{remove_const sym} if topalias_defined?(sym) + Object.class_eval{remove_const sym} if topobj_defined?(sym) + } + end + + def __reset_toplevel_owner__(*symbols) + symbols.each{|sym| @TOPLEVEL_ALIAS_OWNER.delete(sym.to_sym)} + end + + def __disable_toplevel_control__(*symbols) + symbols.each{|sym| @TOPLEVEL_ALIAS_OWNER[sym.to_sym] = false} + end + + def __create_widget_set__(new_set, src_set={}) + new_set = new_set.to_sym + if @TOPLEVEL_ALIAS_TABLE[new_set] + fail RuntimeError, "A widget-set #{new_set.inspect} is already exist." + end + if src_set.kind_of?(Symbol) + # new_set is an alias name of existed widget set. + @TOPLEVEL_ALIAS_TABLE[new_set] = @TOPLEVEL_ALIAS_TABLE[src_set] + else + @TOPLEVEL_ALIAS_TABLE[new_set] = {} + src_set.each{|sym, obj| set_topalias(new_set, obj, sym.to_sym) } + end + end +end + + +############################################ +# setup default widget set => :Tk +Tk.default_widget_set = :Tk + + +############################################ +# depend on the version of Tcl/Tk +# major, minor, type, patchlevel = TclTkLib.get_version + +############################################ +# Ttk (Tile) support +=begin +if major > 8 || + (major == 8 && minor > 5) || + (major == 8 && minor == 5 && type >= TclTkLib::RELEASE_TYPE::BETA) + # Tcl/Tk 8.5 beta or later + Object.autoload :Ttk, 'tkextlib/tile' + Tk.autoload :Tile, 'tkextlib/tile' + + require 'tk/ttk_selector' +end +=end +Object.autoload :Ttk, 'tkextlib/tile' +Tk.autoload :Tile, 'tkextlib/tile' +require 'tk/ttk_selector' diff --git a/jni/ruby/ext/tk/lib/tk/bgerror.rb b/jni/ruby/ext/tk/lib/tk/bgerror.rb new file mode 100644 index 0000000..c82a8e0 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/bgerror.rb @@ -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 diff --git a/jni/ruby/ext/tk/lib/tk/bindtag.rb b/jni/ruby/ext/tk/lib/tk/bindtag.rb new file mode 100644 index 0000000..23b4e0b --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/bindtag.rb @@ -0,0 +1,138 @@ +# +# 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, TkUtil.untrust("00000")]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + TkCore::INTERP.init_ip_env{ + BTagID_TBL.mutex.synchronize{ BTagID_TBL.clear } + } + + def TkBindTag.id2obj(id) + BTagID_TBL.mutex.synchronize{ + (BTagID_TBL[id])? BTagID_TBL[id]: id + } + end + +=begin + def TkBindTag.new_by_name(name, *args, &b) + BTagID_TBL.mutex.synchronize{ + return BTagID_TBL[name] if BTagID_TBL[name] + } + + self.new.instance_eval{ + BTagID_TBL.mutex.synchronize{ + BTagID_TBL.delete @id + @id = name + BTagID_TBL[@id] = self + } + bind(*args, &b) if args != [] + self + } + end +=end + def TkBindTag.new_by_name(name, *args, &b) + obj = nil + BTagID_TBL.mutex.synchronize{ + if BTagID_TBL[name] + obj = BTagID_TBL[name] + else + (obj = BTagID_TBL[name] = self.allocate).instance_eval{ + @id = name + } + end + } + bind(*args, &b) if obj && args != [] + obj + end + + def initialize(*args, &b) + Tk_BINDTAG_ID.mutex.synchronize{ + # @id = Tk_BINDTAG_ID.join('') + @id = Tk_BINDTAG_ID.join(TkCore::INTERP._ip_id_) + Tk_BINDTAG_ID[1].succ! + } + BTagID_TBL.mutex.synchronize{ + 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 +=begin + def self.new(name, *args, &b) + BTagID_TBL.mutex.synchronize{ + return BTagID_TBL[name] if BTagID_TBL[name] + } + super(name, *args, &b) + end + + def initialize(name, *args, &b) + @id = name + BTagID_TBL.mutex.synchronize{ + BTagID_TBL[@id] = self + } + bind(*args, &b) if args != [] + end +=end + def self.new(name, *args, &b) + BTagID_TBL.mutex.synchronize{ + if BTagID_TBL[name] + BTagID_TBL[name] + else + BTagID_TBL[name] = self.allocate.instance_eval{ + initialize(name, *args, &b) + self + } + end + } + end + + def initialize(name, *args, &b) + @id = name + bind(*args, &b) if args != [] + end + + def inspect + #Kernel.format "#<TkDatabaseClass: %s>", @id + '#<TkDatabaseClass: ' + @id + '>' + end +end diff --git a/jni/ruby/ext/tk/lib/tk/busy.rb b/jni/ruby/ext/tk/lib/tk/busy.rb new file mode 100644 index 0000000..7f4f89f --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/busy.rb @@ -0,0 +1,118 @@ +# +# tk/busy.rb: support 'tk busy' command (Tcl/Tk8.6 or later) +# +require 'tk' + +module Tk::Busy + include TkCore + extend TkCore + extend TkItemConfigMethod +end + +class << Tk::Busy + def __item_cget_cmd(win) + # maybe need to override + ['tk', 'busy', 'cget', win.path] + end + private :__item_cget_cmd + + def __item_config_cmd(win) + # maybe need to override + ['tk', 'busy', 'configure', win.path] + end + private :__item_config_cmd + + def __item_confinfo_cmd(win) + # maybe need to override + __item_config_cmd(win) + end + private :__item_confinfo_cmd + + alias cget_tkstring itemcget_tkstring + alias cget itemcget + alias cget_strict itemcget_strict + alias configure itemconfigure + alias configinfo itemconfiginfo + alias current_configinfo current_itemconfiginfo + + private :itemcget_tkstring, :itemcget, :itemcget_strict + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo + + def method_missing(id, *args) + name = id.id2name + case args.length + when 1 + if name[-1] == ?= + configure name[0..-2], args[0] + args[0] + else + configure name, args[0] + self + end + when 0 + begin + cget(name) + rescue + super(id, *args) + end + else + super(id, *args) + end + end + + def hold(win, keys={}) + tk_call_without_enc('tk', 'busy', 'hold', win, *hash_kv(keys)) + win + end + + def forget(*wins) + tk_call_without_enc('tk', 'busy', 'forget', *wins) + self + end + + def current(pat=None) + list(tk_call('tk', 'busy', 'current', pat)) + end + + def status(win) + bool(tk_call_without_enc('tk', 'busy', 'status', win)) + end +end + +module Tk::Busy + def busy_configinfo(option=nil) + Tk::Busy.configinfo(self, option) + end + + def busy_current_configinfo(option=nil) + Tk::Busy.current_configinfo(self, option) + end + + def busy_configure(option, value=None) + Tk::Busy.configure(self, option, value) + self + end + + def busy_cget(option) + Tk::Busy.configure(self, option) + end + + def busy(keys={}) + Tk::Busy.hold(self, keys) + self + end + alias busy_hold busy + + def busy_forget + Tk::Busy.forget(self) + self + end + + def busy_current? + ! Tk::Busy.current(self.path).empty? + end + + def busy_status + Tk::Busy.status(self) + end +end diff --git a/jni/ruby/ext/tk/lib/tk/button.rb b/jni/ruby/ext/tk/lib/tk/button.rb new file mode 100644 index 0000000..65233c9 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/button.rb @@ -0,0 +1,31 @@ +# +# tk/button.rb : treat button widget +# +require 'tk' +require 'tk/label' + +class Tk::Button<Tk::Label + 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 + +#TkButton = Tk::Button unless Object.const_defined? :TkButton +#Tk.__set_toplevel_aliases__(:Tk, Tk::Button, :TkButton) +Tk.__set_loaded_toplevel_aliases__('tk/button.rb', :Tk, Tk::Button, :TkButton) diff --git a/jni/ruby/ext/tk/lib/tk/canvas.rb b/jni/ruby/ext/tk/lib/tk/canvas.rb new file mode 100644 index 0000000..f3e9a7c --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/canvas.rb @@ -0,0 +1,846 @@ +# +# tk/canvas.rb - Tk canvas classes +# by Yukihiro Matsumoto <matz@caelum.co.jp> +# +require 'tk' +require 'tk/canvastag' +require 'tk/itemconfig' +require 'tk/scrollable' + +module TkCanvasItemConfig + include TkItemConfigMethod + + def __item_strval_optkeys(id) + # maybe need to override + super(id) + [ + 'fill', 'activefill', 'disabledfill', + 'outline', 'activeoutline', 'disabledoutline' + ] + end + private :__item_strval_optkeys + + def __item_methodcall_optkeys(id) + {'coords'=>'coords'} + end + private :__item_methodcall_optkeys + + def __item_val2ruby_optkeys(id) # { key=>proc, ... } + super(id).update('window'=>proc{|i, v| window(v)}, + 'tags'=>proc{|i, v| + simplelist(v).collect{|tag| TkcTag.id2obj(self, tag)} + }) + end + private :__item_val2ruby_optkeys + + 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 :__item_pathname +end + +class Tk::Canvas<TkWindow + include TkCanvasItemConfig + include Tk::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 __numval_optkeys + super() + ['closeenough'] + end + private :__numval_optkeys + + def __boolval_optkeys + super() + ['confine'] + end + private :__boolval_optkeys + + def tagid(tag) + if tag.kind_of?(TkcItem) || tag.kind_of?(TkcTag) + tag.id + else + tag # maybe an Array of configure parameters + end + end + private :tagid + + + # create a canvas item without creating a TkcItem object + def create(type, *args) + if type.kind_of?(Class) && type < TkcItem + # do nothing + elsif TkcItem.type2class(type.to_s) + type = TkcItem.type2class(type.to_s) + else + fail ArgumentError, "type must a subclass of TkcItem class, or a string in CItemTypeToClass" + end + type.create(self, *args) + end + + def addtag(tag, mode, *args) + mode = mode.to_s + if args[0] && mode =~ /^(above|below|with(tag)?)$/ + args[0] = tagid(args[0]) + end + 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) + # _bind([path, "bind", tagid(tag)], context, cmd, *args) + # self + #end + def itembind(tag, context, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind([path, "bind", tagid(tag)], context, cmd, *args) + self + end + + #def itembind_append(tag, context, cmd=Proc.new, *args) + # _bind_append([path, "bind", tagid(tag)], context, cmd, *args) + # self + #end + def itembind_append(tag, context, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _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 + alias canvas_x canvasx + alias canvas_y canvasy + + def coords(tag, *args) + if args.empty? + tk_split_list(tk_send_without_enc('coords', tagid(tag))) + else + tk_send_without_enc('coords', tagid(tag), *(args.flatten)) + self + 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) + tbl = nil + TkcItem::CItemID_TBL.mutex.synchronize{ + tbl = TkcItem::CItemID_TBL[self.path] + } + if tbl + args.each{|tag| + find('withtag', tag).each{|item| + if item.kind_of?(TkcItem) + TkcItem::CItemID_TBL.mutex.synchronize{ + tbl.delete(item.id) + } + end + } + } + 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), tagid(tag_to_del)) + self + end + alias deltag dtag + + 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 imove(tagOrId, idx, x, y) + tk_send_without_enc('imove', tagid(tagOrId), idx, x, y) + self + end + alias i_move imove + + def index(tagOrId, idx) + number(tk_send_without_enc('index', tagid(tagOrId), idx)) + end + + def insert(tagOrId, index, string) + tk_send_without_enc('insert', tagid(tagOrId), index, + _get_eval_enc_str(string)) + self + end + +=begin + 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) + coords = key.delete('coords') + self.coords(tagOrId, coords) if coords + + 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 == 'coords' || key == :coords ) + self.coords(tagOrId, value) + elsif ( 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 'coords' + return ['coords', '', '', '', self.coords(tagOrId)] + 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) + end + + ret << ['coords', '', '', '', self.coords(tagOrId)] + end + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY + if key + case key.to_s + when 'coords' + {'coords' => ['', '', '', self.coords(tagOrId)]} + 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['coords'] = ['', '', '', self.coords(tagOrId)] + + 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 +=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, dx, dy) + tk_send_without_enc('move', tagid(tag), dx, dy) + self + end + + def moveto(tag, x, y) + # Tcl/Tk 8.6 or later + tk_send_without_enc('moveto', tagid(tag), x, y) + self + end + alias move_to moveto + + 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 rchars(tag, first, last, str_or_coords) + # Tcl/Tk 8.6 or later + str_or_coords = str_or_coords.flatten if str_or_coords.kinad_of? Array + tk_send_without_enc('rchars', tagid(tag), first, last, str_or_coords) + self + end + alias replace_chars rchars + alias replace_coords rchars + + 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, gain=None) + tk_send_without_enc('scan', 'dragto', x, y, gain) + 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 + + def create_itemobj_from_id(idnum) + id = TkcItem.id2obj(self, idnum.to_i) + return id if id.kind_of?(TkcItem) + + typename = tk_send('type', id) + unless type = TkcItem.type2class(typename) + (itemclass = typename.dup)[0,1] = typename[0,1].upcase + type = TkcItem.const_set(itemclass, Class.new(TkcItem)) + type.const_set("CItemTypeName", typename.freeze) + TkcItem::CItemTypeToClass[typename] = type + end + + canvas = self + (obj = type.allocate).instance_eval{ + @parent = @c = canvas + @path = canvas.path + @id = id + TkcItem::CItemID_TBL.mutex.synchronize{ + TkcItem::CItemID_TBL[@path] = {} unless TkcItem::CItemID_TBL[@path] + TkcItem::CItemID_TBL[@path][@id] = self + } + } + end +end + +#TkCanvas = Tk::Canvas unless Object.const_defined? :TkCanvas +#Tk.__set_toplevel_aliases__(:Tk, Tk::Canvas, :TkCanvas) +Tk.__set_loaded_toplevel_aliases__('tk/canvas.rb', :Tk, Tk::Canvas, :TkCanvas) + + +class TkcItem<TkObject + extend Tk + include TkcTagAccess + extend TkItemFontOptkeys + extend TkItemConfigOptkeys + + CItemTypeName = nil + CItemTypeToClass = {} + + CItemID_TBL = TkCore::INTERP.create_table + + TkCore::INTERP.init_ip_env{ + CItemID_TBL.mutex.synchronize{ CItemID_TBL.clear } + } + + def TkcItem.type2class(type) + CItemTypeToClass[type] + end + + def TkcItem.id2obj(canvas, id) + cpath = canvas.path + CItemID_TBL.mutex.synchronize{ + if CItemID_TBL[cpath] + CItemID_TBL[cpath][id]? CItemID_TBL[cpath][id]: id + else + id + end + } + end + + ######################################## + def self._parse_create_args(args) + fontkeys = {} + methodkeys = {} + if args[-1].kind_of? Hash + keys = _symbolkey2str(args.pop) + if args.size == 0 + args = keys.delete('coords') + unless args.kind_of?(Array) + fail "coords parameter must be given by an Array" + end + end + + #['font', 'kanjifont', 'latinfont', 'asciifont'].each{|key| + # fontkeys[key] = keys.delete(key) if keys.key?(key) + #} + __item_font_optkeys(nil).each{|key| + fkey = key.to_s + fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) + + fkey = "kanji#{key}" + fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) + + fkey = "latin#{key}" + fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) + + fkey = "ascii#{key}" + fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) + } + + __item_optkey_aliases(nil).each{|alias_name, real_name| + alias_name = alias_name.to_s + if keys.has_key?(alias_name) + keys[real_name.to_s] = keys.delete(alias_name) + end + } + + __item_methodcall_optkeys(nil).each{|key| + key = key.to_s + methodkeys[key] = keys.delete(key) if keys.key?(key) + } + + __item_ruby2val_optkeys(nil).each{|key, method| + key = key.to_s + keys[key] = method.call(keys[key]) if keys.has_key?(key) + } + + #args = args.flatten.concat(hash_kv(keys)) + args = args.flatten.concat(itemconfig_hash_kv(nil, keys)) + else + args = args.flatten + end + + [args, fontkeys, methodkeys] + end + private_class_method :_parse_create_args + + def self.create(canvas, *args) + unless self::CItemTypeName + fail RuntimeError, "#{self} is an abstract class" + end + args, fontkeys, methodkeys = _parse_create_args(args) + idnum = tk_call_without_enc(canvas.path, 'create', + self::CItemTypeName, *args) + canvas.itemconfigure(idnum, fontkeys) unless fontkeys.empty? + canvas.itemconfigure(idnum, methodkeys) unless methodkeys.empty? + idnum.to_i # 'canvas item id' is an integer number + end + ######################################## + + def initialize(parent, *args) + #unless parent.kind_of?(Tk::Canvas) + # fail ArgumentError, "expect Tk::Canvas for 1st argument" + #end + @parent = @c = parent + @path = parent.path + + @id = create_self(*args) # an integer number as 'canvas item id' + CItemID_TBL.mutex.synchronize{ + CItemID_TBL[@path] = {} unless CItemID_TBL[@path] + CItemID_TBL[@path][@id] = self + } + end + def create_self(*args) + self.class.create(@c, *args) # return an integer number as 'canvas item id' + end + private :create_self + + def id + @id + end + + def exist? + if @c.find_withtag(@id) + true + else + false + end + end + + def delete + @c.delete @id + CItemID_TBL.mutex.synchronize{ + CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path] + } + self + end + alias remove delete + alias destroy delete +end + +class TkcArc<TkcItem + CItemTypeName = 'arc'.freeze + CItemTypeToClass[CItemTypeName] = self +end + +class TkcBitmap<TkcItem + CItemTypeName = 'bitmap'.freeze + CItemTypeToClass[CItemTypeName] = self +end + +class TkcImage<TkcItem + CItemTypeName = 'image'.freeze + CItemTypeToClass[CItemTypeName] = self +end + +class TkcLine<TkcItem + CItemTypeName = 'line'.freeze + CItemTypeToClass[CItemTypeName] = self +end + +class TkcOval<TkcItem + CItemTypeName = 'oval'.freeze + CItemTypeToClass[CItemTypeName] = self +end + +class TkcPolygon<TkcItem + CItemTypeName = 'polygon'.freeze + CItemTypeToClass[CItemTypeName] = self +end + +class TkcRectangle<TkcItem + CItemTypeName = 'rectangle'.freeze + CItemTypeToClass[CItemTypeName] = self +end + +class TkcText<TkcItem + CItemTypeName = 'text'.freeze + CItemTypeToClass[CItemTypeName] = self + def self.create(canvas, *args) + if args[-1].kind_of?(Hash) + keys = _symbolkey2str(args.pop) + txt = keys['text'] + keys['text'] = _get_eval_enc_str(txt) if txt + args.push(keys) + end + super(canvas, *args) + end +end + +class TkcWindow<TkcItem + CItemTypeName = 'window'.freeze + CItemTypeToClass[CItemTypeName] = self + def self.create(canvas, *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.push(keys) + end + super(canvas, *args) + end +end diff --git a/jni/ruby/ext/tk/lib/tk/canvastag.rb b/jni/ruby/ext/tk/lib/tk/canvastag.rb new file mode 100644 index 0000000..495d92a --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/canvastag.rb @@ -0,0 +1,459 @@ +# +# tk/canvastag.rb - methods for treating canvas tags +# +require 'tk' +require 'tk/tagfont' + +module TkcTagAccess + include TkComm + include TkTreatTagFont +end + +require 'tk/canvas' + +module TkcTagAccess + def addtag(tag) + @c.addtag(tag, 'withtag', @id) + self + end + + def bbox + @c.bbox(@id) + end + + #def bind(seq, cmd=Proc.new, *args) + # @c.itembind(@id, seq, cmd, *args) + # self + #end + def bind(seq, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + @c.itembind(@id, seq, cmd, *args) + self + end + + #def bind_append(seq, cmd=Proc.new, *args) + # @c.itembind_append(@id, seq, cmd, *args) + # self + #end + def bind_append(seq, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + @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_tkstring(option) + @c.itemcget_tkstring(@id, option) + end + def cget(option) + @c.itemcget(@id, option) + end + def cget_strict(option) + @c.itemcget_strict(@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 + alias deltag dtag + + 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 imove(idx, x, y) + # Tcl/Tk 8.6 or later + @c.imove(@id, idx, x, y) + self + end + alias i_move imove + + def index(idx) + @c.index(@id, idx) + 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 moveto(x, y) + # Tcl/Tk 8.6 or later + @c.moveto(@id, x, y) + self + end + alias move_to moveto + + 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 rchars(first, last, str_or_coords) + # Tcl/Tk 8.6 or later + @c.rchars(@id, first, last, str_or_coords) + self + end + alias replace_chars rchars + alias replace_coords rchars + + 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, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + TkCore::INTERP.init_ip_env{ + CTagID_TBL.mutex.synchronize{ CTagID_TBL.clear } + } + + def TkcTag.id2obj(canvas, id) + cpath = canvas.path + CTagID_TBL.mutex.synchronize{ + if CTagID_TBL[cpath] + CTagID_TBL[cpath][id]? CTagID_TBL[cpath][id]: id + else + id + end + } + end + + def initialize(parent, mode=nil, *args) + #unless parent.kind_of?(TkCanvas) + # fail ArgumentError, "expect TkCanvas for 1st argument" + #end + @c = parent + @cpath = parent.path + Tk_CanvasTag_ID.mutex.synchronize{ + # @path = @id = Tk_CanvasTag_ID.join('') + @path = @id = Tk_CanvasTag_ID.join(TkCore::INTERP._ip_id_) + Tk_CanvasTag_ID[1].succ! + } + CTagID_TBL.mutex.synchronize{ + 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 + def id + @id + end + + def exist? + if @c.find_withtag(@id) + true + else + false + end + end + + def delete + @c.delete @id + CTagID_TBL.mutex.synchronize{ + 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, mode=nil, *args) + obj = nil + CTagID_TBL.mutex.synchronize{ + if CTagID_TBL[parent.path] && CTagID_TBL[parent.path][name] + obj = CTagID_TBL[parent.path][name] + else + # super(parent, name, *args) + (obj = self.allocate).instance_eval{ + @c = parent + @cpath = parent.path + @path = @id = name + CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath] + CTagID_TBL[@cpath][@id] = self + } + end + } + if obj && mode + tk_call_without_enc(@c.path, "addtag", @id, mode, *args) + end + obj + end + + def initialize(parent, name, mode=nil, *args) + # dummy:: not called by 'new' method + + #unless parent.kind_of?(TkCanvas) + # fail ArgumentError, "expect TkCanvas for 1st argument" + #end + @c = parent + @cpath = parent.path + @path = @id = name + + if mode + tk_call_without_enc(@c.path, "addtag", @id, mode, *args) + end + end +end +TkcNamedTag = TkcTagString + +class TkcTagAll<TkcTagString + def self.new(parent) + super(parent, 'all') + end +=begin + def initialize(parent) + #unless parent.kind_of?(TkCanvas) + # fail ArgumentError, "expect TkCanvas for 1st argument" + #end + @c = parent + @cpath = parent.path + @path = @id = 'all' + CTagID_TBL.mutex.synchronize{ + CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath] + CTagID_TBL[@cpath][@id] = self + } + end +=end +end + +class TkcTagCurrent<TkcTagString + def self.new(parent) + super(parent, 'current') + end +=begin + def initialize(parent) + #unless parent.kind_of?(TkCanvas) + # fail ArgumentError, "expect TkCanvas for 1st argument" + #end + @c = parent + @cpath = parent.path + @path = @id = 'current' + CTagID_TBL.mutex.synchronize{ + CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath] + CTagID_TBL[@cpath][@id] = self + } + end +=end +end + +class TkcGroup<TkcTag + (Tk_cGroup_ID = ['tkcg'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + #def create_self(parent, *args) + def initialize(parent, *args) + #unless parent.kind_of?(TkCanvas) + # fail ArgumentError, "expect TkCanvas for 1st argument" + #end + @c = parent + @cpath = parent.path + Tk_cGroup_ID.mutex.synchronize{ + # @path = @id = Tk_cGroup_ID.join('') + @path = @id = Tk_cGroup_ID.join(TkCore::INTERP._ip_id_) + Tk_cGroup_ID[1].succ! + } + CTagID_TBL.mutex.synchronize{ + CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath] + CTagID_TBL[@cpath][@id] = self + } + include(*args) if args != [] + end + #private :create_self + + def include(*tags) + for i in tags + #i.addtag(@id) + @c.addtag_withtag(@id, i) + end + self + end + alias add include + + def exclude(*tags) + for i in tags + #i.dtag(@id) + @c.dtag(i, @id) + end + self + end +end diff --git a/jni/ruby/ext/tk/lib/tk/checkbutton.rb b/jni/ruby/ext/tk/lib/tk/checkbutton.rb new file mode 100644 index 0000000..b744954 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/checkbutton.rb @@ -0,0 +1,32 @@ +# +# tk/checkbutton.rb : treat checkbutton widget +# +require 'tk' +require 'tk/radiobutton' + +class Tk::CheckButton<Tk::RadioButton + 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 + +Tk::Checkbutton = Tk::CheckButton +#TkCheckButton = Tk::CheckButton unless Object.const_defined? :TkCheckButton +#TkCheckbutton = Tk::Checkbutton unless Object.const_defined? :TkCheckbutton +#Tk.__set_toplevel_aliases__(:Tk, Tk::CheckButton, +# :TkCheckButton, :TkCheckbutton) +Tk.__set_loaded_toplevel_aliases__('tk/checkbutton.rb', :Tk, Tk::CheckButton, + :TkCheckButton, :TkCheckbutton) diff --git a/jni/ruby/ext/tk/lib/tk/clipboard.rb b/jni/ruby/ext/tk/lib/tk/clipboard.rb new file mode 100644 index 0000000..d4205a5 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/clipboard.rb @@ -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 diff --git a/jni/ruby/ext/tk/lib/tk/clock.rb b/jni/ruby/ext/tk/lib/tk/clock.rb new file mode 100644 index 0000000..4e9438f --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/clock.rb @@ -0,0 +1,71 @@ +# +# tk/clock.rb : methods for clock command +# +require 'tk' + +module Tk + module Clock + include Tk + extend TkCore + + def self.add(clk, *args) + tk_call_without_enc('clock','add', clk, *args).to_i + end + + def self.clicks(ms=nil) + ms = ms.to_s if ms.kind_of?(Symbol) + 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 + def self.milliseconds + tk_call_without_enc('clock','milliseconds').to_i + end + def self.microseconds + tk_call_without_enc('clock','microseconds').to_i + end + end +end diff --git a/jni/ruby/ext/tk/lib/tk/composite.rb b/jni/ruby/ext/tk/lib/tk/composite.rb new file mode 100644 index 0000000..e267c7a --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/composite.rb @@ -0,0 +1,484 @@ +# +# tk/composite.rb : +# +require 'tk' + +module TkComposite + include Tk + extend Tk + +=begin + def initialize(parent=nil, *args) + @delegates = {} + @option_methods = {} + @option_setting = {} + + if parent.kind_of? Hash + keys = _symbolkey2str(parent) + parent = keys.delete('parent') + @frame = TkFrame.new(parent) + @path = @epath = @frame.path + initialize_composite(keys) + else + @frame = TkFrame.new(parent) + @path = @epath = @frame.path + initialize_composite(*args) + end + end +=end + + def _choice_classname_of_baseframe + base_class_name = nil + + klass = WidgetClassNames[self.class::WidgetClassName] + + if klass + # WidgetClassName is a known class + #if klass <= TkFrame || klass < TkComposite + if klass <= TkFrame || klass < Tk::Frame || klass < TkComposite + # klass is valid for the base frame + if self.class <= klass + # use my classname + base_class_name = self.class.name + if base_class_name == '' + # anonymous class -> use ancestor's name + base_class_name = klass.name + end + else + # not subclass -> use WidgetClassName + base_class_name = klass.name + end + + else + # klass is invalid for the base frame + #if self.class < TkFrame || self.class.superclass < TkComposite + if self.class < TkFrame || self.class.superclass < Tk::Frame || self.class.superclass < TkComposite + # my class name is valid for the base frame -> use my classname + base_class_name = self.class.name + if base_class_name == '' + # anonymous class -> use TkFrame + base_class_name = nil + end + else + # no idea for the base frame -> use TkFrame + base_class_name = nil + end + end + + elsif self.class::WidgetClassName && ! self.class::WidgetClassName.empty? + # unknown WidgetClassName is defined -> use it for the base frame + base_class_name = self.class::WidgetClassName + + else + # no valid WidgetClassName + #if self.class < TkFrame || self.class.superclass < TkComposite + if self.class < TkFrame || self.class.superclass < Tk::Frame || self.class.superclass < TkComposite + # my class name is valid for the base frame -> use my classname + base_class_name = self.class.name + if base_class_name == '' + # anonymous class -> use TkFrame + base_class_name = nil + end + else + # no idea for the base frame -> use TkFrame + base_class_name = nil + end + end + + base_class_name + end + private :_choice_classname_of_baseframe + + # def initialize(parent=nil, *args) + def initialize(*args) + @delegates = {} + @option_methods = {} + @option_setting = {} + + if args[-1].kind_of?(Hash) + keys = _symbolkey2str(args.pop) + else + keys = {} + end + parent = args.shift + parent = keys.delete('parent') if keys.has_key?('parent') + + if keys.key?('classname') + keys['class'] = keys.delete('classname') + end + if (base_class_name = (keys.delete('class')).to_s).empty? + base_class_name = _choice_classname_of_baseframe + end + + if base_class_name + # @frame = Tk::Frame.new(parent, :class=>base_class_name) + # --> use current TkFrame class + @frame = TkFrame.new(parent, :class=>base_class_name) + else + # @frame = Tk::Frame.new(parent) + # --> use current TkFrame class + @frame = TkFrame.new(parent) + end + @path = @epath = @frame.path + + args.push(keys) unless keys.empty? + initialize_composite(*args) + end + + def database_classname + @frame.database_classname + end + + def database_class + @frame.database_class + end + + def epath + @epath + end + + def initialize_composite(*args) end + private :initialize_composite + + def inspect + str = super + str.chop << ' @epath=' << @epath.inspect << '>' + end + + def _get_opt_method_list(arg) + m_set, m_cget, m_info = arg + m_set = m_set.to_s + m_cget = m_set if !m_cget && self.method(m_set).arity == -1 + m_cget = m_cget.to_s if m_cget + m_info = m_info.to_s if m_info + [m_set, m_cget, m_info] + end + private :_get_opt_method_list + + def option_methods(*opts) + if opts.size == 1 && opts[0].kind_of?(Hash) + # {name => [m_set, m_cget, m_info], name => method} style + opts[0].each{|name, arg| + m_set, m_cget, m_info = _get_opt_method_list(arg) + @option_methods[name.to_s] = { + :set => m_set, :cget => m_cget, :info => m_info + } + } + else + # [m_set, m_cget, m_info] or method style + opts.each{|arg| + m_set, m_cget, m_info = _get_opt_method_list(arg) + @option_methods[m_set] = { + :set => m_set, :cget => m_cget, :info => m_info + } + } + end + end + + def delegate_alias(alias_opt, option, *wins) + if wins.length == 0 + fail ArgumentError, "target widgets are not given" + end + if alias_opt != option && (alias_opt == 'DEFAULT' || option == 'DEFAULT') + fail ArgumentError, "cannot alias 'DEFAULT' option" + end + alias_opt = alias_opt.to_s + option = option.to_s + if @delegates[alias_opt].kind_of?(Array) + if (elem = @delegates[alias_opt].assoc(option)) + wins.each{|w| elem[1].push(w)} + else + @delegates[alias_opt] << [option, wins] + end + else + @delegates[alias_opt] = [ [option, wins] ] + end + end + + def delegate(option, *wins) + delegate_alias(option, option, *wins) + end + + def __cget_delegates(slot) + slot = slot.to_s + + if @option_methods.include?(slot) + if @option_methods[slot][:cget] + return self.__send__(@option_methods[slot][:cget]) + else + if @option_setting[slot] + return @option_setting[slot] + else + return '' + end + end + end + + tbl = @delegates[slot] + tbl = @delegates['DEFAULT'] unless tbl + + begin + if tbl + opt, wins = tbl[-1] + opt = slot if opt == 'DEFAULT' + if wins && wins[-1] + # return wins[-1].cget(opt) + return wins[-1].cget_strict(opt) + end + end + rescue + end + + return None + end + private :__cget_delegates + + def cget_tkstring(slot) + if (ret = __cget_delegates(slot)) == None + super(slot) + else + _get_eval_string(ret) + end + end + + def cget(slot) + if (ret = __cget_delegates(slot)) == None + super(slot) + else + ret + end + end + + def cget_strict(slot) + if (ret = __cget_delegates(slot)) == None + super(slot) + else + ret + end + end + +=begin + def cget(slot) + slot = slot.to_s + + if @option_methods.include?(slot) + if @option_methods[slot][:cget] + return self.__send__(@option_methods[slot][:cget]) + else + if @option_setting[slot] + return @option_setting[slot] + else + return '' + end + end + end + + tbl = @delegates[slot] + tbl = @delegates['DEFAULT'] unless tbl + + begin + if tbl + opt, wins = tbl[-1] + opt = slot if opt == 'DEFAULT' + if wins && wins[-1] + return wins[-1].cget(opt) + end + end + rescue + end + + super(slot) + end +=end + + def configure(slot, value=None) + if slot.kind_of? Hash + slot.each{|slot,value| configure slot, value} + return self + end + + slot = slot.to_s + + if @option_methods.include?(slot) + unless @option_methods[slot][:cget] + if value.kind_of?(Symbol) + @option_setting[slot] = value.to_s + else + @option_setting[slot] = value + end + end + return self.__send__(@option_methods[slot][:set], value) + end + + tbl = @delegates[slot] + tbl = @delegates['DEFAULT'] unless tbl + + begin + if tbl + last = nil + tbl.each{|opt, wins| + opt = slot if opt == 'DEFAULT' + wins.each{|w| last = w.configure(opt, value)} + } + return last + end + rescue + end + + super(slot, value) + end + + def configinfo(slot = nil) + if TkComm::GET_CONFIGINFO_AS_ARRAY + if slot + slot = slot.to_s + if @option_methods.include?(slot) + if @option_methods[slot][:info] + return self.__send__(@option_methods[slot][:info]) + else + return [slot, '', '', '', self.cget(slot)] + end + end + + tbl = @delegates[slot] + tbl = @delegates['DEFAULT'] unless tbl + + begin + if tbl + if tbl.length == 1 + opt, wins = tbl[0] + if slot == opt || opt == 'DEFAULT' + return wins[-1].configinfo(slot) + else + info = wins[-1].configinfo(opt) + info[0] = slot + return info + end + else + opt, wins = tbl[-1] + return [slot, '', '', '', wins[-1].cget(opt)] + end + end + rescue + end + + super(slot) + + else # slot == nil + info_list = super(slot) + + tbl = @delegates['DEFAULT'] + if tbl + wins = tbl[0][1] + if wins && wins[-1] + wins[-1].configinfo.each{|info| + slot = info[0] + info_list.delete_if{|i| i[0] == slot} << info + } + end + end + + @delegates.each{|slot, tbl| + next if slot == 'DEFAULT' + if tbl.length == 1 + opt, wins = tbl[0] + next unless wins && wins[-1] + if slot == opt + info_list.delete_if{|i| i[0] == slot} << + wins[-1].configinfo(slot) + else + info = wins[-1].configinfo(opt) + info[0] = slot + info_list.delete_if{|i| i[0] == slot} << info + end + else + opt, wins = tbl[-1] + info_list.delete_if{|i| i[0] == slot} << + [slot, '', '', '', wins[-1].cget(opt)] + end + } + + @option_methods.each{|slot, m| + if m[:info] + info = self.__send__(m[:info]) + else + info = [slot, '', '', '', self.cget(slot)] + end + info_list.delete_if{|i| i[0] == slot} << info + } + + info_list + end + + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY + if slot + slot = slot.to_s + if @option_methods.include?(slot) + if @option_methods[slot][:info] + return self.__send__(@option_methods[slot][:info]) + else + return {slot => ['', '', '', self.cget(slot)]} + end + end + + tbl = @delegates[slot] + tbl = @delegates['DEFAULT'] unless tbl + + begin + if tbl + if tbl.length == 1 + opt, wins = tbl[0] + if slot == opt || opt == 'DEFAULT' + return wins[-1].configinfo(slot) + else + return {slot => wins[-1].configinfo(opt)[opt]} + end + else + opt, wins = tbl[-1] + return {slot => ['', '', '', wins[-1].cget(opt)]} + end + end + rescue + end + + super(slot) + + else # slot == nil + info_list = super(slot) + + tbl = @delegates['DEFAULT'] + if tbl + wins = tbl[0][1] + info_list.update(wins[-1].configinfo) if wins && wins[-1] + end + + @delegates.each{|slot, tbl| + next if slot == 'DEFAULT' + if tbl.length == 1 + opt, wins = tbl[0] + next unless wins && wins[-1] + if slot == opt + info_list.update(wins[-1].configinfo(slot)) + else + info_list.update({slot => wins[-1].configinfo(opt)[opt]}) + end + else + opt, wins = tbl[-1] + info_list.update({slot => ['', '', '', wins[-1].cget(opt)]}) + end + } + + @option_methods.each{|slot, m| + if m[:info] + info = self.__send__(m[:info]) + else + info = {slot => ['', '', '', self.cget(slot)]} + end + info_list.update(info) + } + + info_list + end + end + end +end diff --git a/jni/ruby/ext/tk/lib/tk/console.rb b/jni/ruby/ext/tk/lib/tk/console.rb new file mode 100644 index 0000000..64e2575 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/console.rb @@ -0,0 +1,52 @@ +# +# tk/console.rb : control the console on system without a real console +# +require 'tk' + +module TkConsole + include Tk + extend Tk + + TkCommandNames = ['console'.freeze, 'consoleinterp'.freeze].freeze + + def self.create + TkCore::INTERP._create_console + end + self.create # initialize console + + 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 + def self.maininterp_eval(tcl_script) + # + # supports a Tcl script only + # I have no idea to support a Ruby script seamlessly. + # + _fromUTF8(tk_call_without_enc('consoleinterp', 'eval', + _get_eval_enc_str(tcl_script))) + + end + def self.maininterp_record(tcl_script) + # + # supports a Tcl script only + # I have no idea to support a Ruby script seamlessly. + # + _fromUTF8(tk_call_without_enc('consoleinterp', 'record', + _get_eval_enc_str(tcl_script))) + + end +end diff --git a/jni/ruby/ext/tk/lib/tk/dialog.rb b/jni/ruby/ext/tk/lib/tk/dialog.rb new file mode 100644 index 0000000..7ef7820 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/dialog.rb @@ -0,0 +1,326 @@ +# +# tk/dialog.rb : create dialog boxes +# +require 'tk' +require 'tk/variable.rb' + +class TkDialogObj < 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(' ')+'; ' + @config << @path+'.button'+i.to_s+' configure '+ + array2tk_list(hash_kv(c))+'; ' + } + 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 != "" + @config = array2tk_list(['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 = prev_command + + 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 == "" + @bitmap = '' unless @bitmap + @default_button = keys['default'] if keys.key? 'default' + @buttons = keys['buttons'] if keys.key? 'buttons' + + @command = keys['prev_command'] if keys.key? '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 = [] unless @buttons +=begin + @buttons = @buttons.collect{|s| + if s.kind_of?(Array) + s = s.join(' ') + end + if s.include? ?\s + '{' + s + '}' + else + s + end + } +=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(' ')+';' + @config << @path+'.msg configure '+ + array2tk_list(hash_kv(@message_config))+';' + 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(' ')+';' + @config << @path+'.top configure '+ + array2tk_list(hash_kv(@msgframe_config))+';' + 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(' ')+';' + @config << @path+'.bot configure '+ + array2tk_list(hash_kv(@btnframe_config))+';' + 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(' ')+';' + @config << @path+'.bitmap configure '+ + array2tk_list(hash_kv(@bitmap_config))+';' + end + + _set_button_config(@button_configs) if @button_configs + end + private :create_self + + def show + # if @command.kind_of?(Proc) + if TkComm._callback_entry?(@command) + @command.call(self) + end + + if @default_button.kind_of?(String) + default_button = @buttons.index(@default_button) + else + default_button = @default_button + end + # default_button = '{}' if default_button == nil + 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 + # @val = Tk.ip_eval(self.class::TkCommandNames[0] + ' ' + @path + ' ' + + # @title + ' {' + @message + '} ' + @bitmap + ' ' + + # String(default_button) + ' ' + @buttons.join(' ')).to_i + @val = Tk.ip_eval(array2tk_list([ + self.class::TkCommandNames[0], + @path, @title, @message, @bitmap, + String(default_button) + ].concat(@buttons))).to_i + end + + def value + # @var.value.to_i + @val + end + + def name + (@val)? @buttons[@val]: nil + end + + ############################################################ + # # + # following methods should 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 + def prev_command + # returns nil or a Proc + return nil + end +end +TkDialog2 = TkDialogObj + +# +# TkDialog : with showing at initialize +# +class TkDialog < TkDialogObj + def self.show(*args) + self.new(*args) + end + + def initialize(*args) + super(*args) + show + end +end + + +# +# dialog for warning +# +class TkWarningObj < TkDialogObj + 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 +TkWarning2 = TkWarningObj + +class TkWarning < TkWarningObj + def self.show(*args) + self.new(*args) + end + def initialize(*args) + super(*args) + show + end +end diff --git a/jni/ruby/ext/tk/lib/tk/encodedstr.rb b/jni/ruby/ext/tk/lib/tk/encodedstr.rb new file mode 100644 index 0000000..59fbb19 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/encodedstr.rb @@ -0,0 +1,187 @@ +# +# 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) ) + enc ||= (self.class::Encoding)? + self.class::Encoding : + ((Tk.encoding)? Tk.encoding : Tk.encoding_system) + if TkCore::WITH_ENCODING + unless encobj = Tk::Encoding::ENCODING_TABLE.get_obj(enc) + fail ArgumentError, "unsupported Tk encoding '#{enc}'" + end + self.force_encoding(encobj) + else + @encoding = enc + end + end + + if TkCore::WITH_ENCODING + alias encoding_obj encoding + alias __encoding encoding + def encoding + Tk::Encoding::ENCODING_TABLE.get_name(super()) + end + else + def encoding + @encoding + end + alias encoding_obj encoding + end + + if TkCore::WITH_ENCODING + # wrapper methods for compatibility + alias __instance_variable_get instance_variable_get + alias __instance_variable_set instance_variable_set + alias __instance_eval instance_eval + alias __instance_variables instance_variables + + def instance_variable_get(key) + if (key.to_s == '@encoding') + self.encoding + else + super(key) + end + end + + def instance_variable_set(key, value) + if (key.to_s == '@encoding') + if value + self.force_encoding(value) + else + self.force_encoding(Tk::Encoding::UNKNOWN) + end + value + else + super(key, value) + end + end + + def instance_eval(*args, &b) + old_enc = @encoding = self.encoding + + ret = super(*args, &b) + + if @encoding + if @encoding != old_enc + # modified by user + self.force_encoding(@encoding) + end + remove_instance_variable(:@encoding) + else + begin + remove_instance_variable(:@encoding) + # user sets to nil -> use current default + self.force_encoding(Tk.encoding) + rescue NameError + # removed by user -> ignore, because user don't use @encoding + end + end + ret + end + end + + def instance_variables + ret = super() + ret << :@encoding # fake !! + ret + end + 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 diff --git a/jni/ruby/ext/tk/lib/tk/entry.rb b/jni/ruby/ext/tk/lib/tk/entry.rb new file mode 100644 index 0000000..d4aa03f --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/entry.rb @@ -0,0 +1,120 @@ +# +# tk/entry.rb - Tk entry classes +# by Yukihiro Matsumoto <matz@caelum.co.jp> + +require 'tk' +require 'tk/label' +require 'tk/scrollable' +require 'tk/validation' + +class Tk::Entry<Tk::Label + include X_Scrollable + include TkValidation + + TkCommandNames = ['entry'.freeze].freeze + WidgetClassName = 'Entry'.freeze + WidgetClassNames[WidgetClassName] ||= self + + #def create_self(keys) + # super(__conv_vcmd_on_hash_kv(keys)) + #end + #private :create_self + + def __strval_optkeys + super() + ['show', 'disabledbackground', 'readonlybackground'] + end + private :__strval_optkeys + + def bbox(index) + list(tk_send_without_enc('bbox', index)) + end + def cursor + number(tk_send_without_enc('index', 'insert')) + end + alias icursor cursor + def cursor=(index) + tk_send_without_enc('icursor', index) + #self + index + end + alias icursor= cursor= + def index(idx) + number(tk_send_without_enc('index', idx)) + 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 + +#TkEntry = Tk::Entry unless Object.const_defined? :TkEntry +#Tk.__set_toplevel_aliases__(:Tk, Tk::Entry, :TkEntry) +Tk.__set_loaded_toplevel_aliases__('tk/entry.rb', :Tk, Tk::Entry, :TkEntry) diff --git a/jni/ruby/ext/tk/lib/tk/event.rb b/jni/ruby/ext/tk/lib/tk/event.rb new file mode 100644 index 0000000..bf4e122 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/event.rb @@ -0,0 +1,562 @@ +# +# tk/event.rb - module for event +# + +module TkEvent +end + +######################## + +require 'tkutil' +require 'tk' unless Object.const_defined? :TkComm + +######################## + +module TkEvent + class Event < TkUtil::CallbackSubst + module Grp + KEY = 0x1 + BUTTON = 0x2 + MOTION = 0x4 + CROSSING = 0x8 + FOCUS = 0x10 + EXPOSE = 0x20 + VISIBILITY = 0x40 + CREATE = 0x80 + DESTROY = 0x100 + UNMAP = 0x200 + MAP = 0x400 + REPARENT = 0x800 + CONFIG = 0x1000 + GRAVITY = 0x2000 + CIRC = 0x4000 + PROP = 0x8000 + COLORMAP = 0x10000 + VIRTUAL = 0x20000 + ACTIVATE = 0x40000 + MAPREQ = 0x80000 + CONFIGREQ = 0x100000 + RESIZEREQ = 0x200000 + CIRCREQ = 0x400000 + + MWHEEL = KEY + + STRING_DATA = 0x80000000 # special flag for 'data' field + + ALL = 0xFFFFFFFF + + KEY_BUTTON_MOTION_VIRTUAL = (KEY|MWHEEL|BUTTON|MOTION|VIRTUAL) + KEY_BUTTON_MOTION_CROSSING = (KEY|MWHEEL|BUTTON|MOTION|CROSSING|VIRTUAL) + end + + type_data = [ + #-----+-------------------+------------------+-----------------------# + # ID | const | group_flag | context_name # + #-----+-------------------+------------------+-----------------------# + [ 2, :KeyPress, Grp::KEY, 'KeyPress', 'Key' ], + [ 3, :KeyRelease, Grp::KEY, 'KeyRelease' ], + [ 4, :ButtonPress, Grp::BUTTON, 'ButtonPress', 'Button' ], + [ 5, :ButtonRelease, Grp::BUTTON, 'ButtonRelease' ], + [ 6, :MotionNotify, Grp::MOTION, 'Motion' ], + [ 7, :EnterNotify, Grp::CROSSING, 'Enter' ], + [ 8, :LeaveNotify, Grp::CROSSING, 'Leave' ], + [ 9, :FocusIn, Grp::FOCUS, 'FocusIn' ], + [ 10, :FocusOut, Grp::FOCUS, 'FocusOut' ], + [ 11, :KeymapNotify, 0, ], + [ 12, :Expose, Grp::EXPOSE, 'Expose' ], + [ 13, :GraphicsExpose, Grp::EXPOSE, ], + [ 14, :NoExpose, 0, ], + [ 15, :VisibilityNotify, Grp::VISIBILITY, 'Visibility' ], + [ 16, :CreateNotify, Grp::CREATE, 'Create' ], + [ 17, :DestroyNotify, Grp::DESTROY, 'Destroy' ], + [ 18, :UnmapNotify, Grp::UNMAP, 'Unmap' ], + [ 19, :MapNotify, Grp::MAP, 'Map' ], + [ 20, :MapRequest, Grp::MAPREQ, 'MapRequest' ], + [ 21, :ReparentNotify, Grp::REPARENT, 'Reparent' ], + [ 22, :ConfigureNotify, Grp::CONFIG, 'Configure' ], + [ 23, :ConfigureRequest, Grp::CONFIGREQ, 'ConfigureRequest' ], + [ 24, :GravityNotify, Grp::GRAVITY, 'Gravity' ], + [ 25, :ResizeRequest, Grp::RESIZEREQ, 'ResizeRequest' ], + [ 26, :CirculateNotify, Grp::CIRC, 'Circulate' ], + [ 27, :CirculateRequest, 0, 'CirculateRequest' ], + [ 28, :PropertyNotify, Grp::PROP, 'Property' ], + [ 29, :SelectionClear, 0, ], + [ 30, :SelectionRequest, 0, ], + [ 31, :SelectionNotify, 0, ], + [ 32, :ColormapNotify, Grp::COLORMAP, 'Colormap' ], + [ 33, :ClientMessage, 0, ], + [ 34, :MappingNotify, 0, ], + [ 35, :VirtualEvent, Grp::VIRTUAL, ], + [ 36, :ActivateNotify, Grp::ACTIVATE, 'Activate' ], + [ 37, :DeactivateNotify, Grp::ACTIVATE, 'Deactivate' ], + [ 38, :MouseWheelEvent, Grp::MWHEEL, 'MouseWheel' ], + [ 39, :TK_LASTEVENT, 0, ] + ] + + module TypeNum + end + + TYPE_NAME_TBL = Hash.new + TYPE_ID_TBL = Hash.new + TYPE_GROUP_TBL = Hash.new + + type_data.each{|id, c_name, g_flag, *t_names| + TypeNum.const_set(c_name, id) + t_names.each{|t_name| t_name.freeze; TYPE_NAME_TBL[t_name] = id } + TYPE_ID_TBL[id] = t_names + TYPE_GROUP_TBL[id] = g_flag + } + + TYPE_NAME_TBL.freeze + TYPE_ID_TBL.freeze + + def self.type_id(name) + TYPE_NAME_TBL[name.to_s] + end + + def self.type_name(id) + TYPE_ID_TBL[id] && TYPE_ID_TBL[id][0] + end + + def self.group_flag(id) + TYPE_GROUP_TBL[id] || 0 + end + + ############################################# + + module StateMask + ShiftMask = (1<<0) + LockMask = (1<<1) + ControlMask = (1<<2) + Mod1Mask = (1<<3) + Mod2Mask = (1<<4) + Mod3Mask = (1<<5) + Mod4Mask = (1<<6) + Mod5Mask = (1<<7) + Button1Mask = (1<<8) + Button2Mask = (1<<9) + Button3Mask = (1<<10) + Button4Mask = (1<<11) + Button5Mask = (1<<12) + + AnyModifier = (1<<15) + + META_MASK = (AnyModifier<<1) + ALT_MASK = (AnyModifier<<2) + EXTENDED_MASK = (AnyModifier<<3) + + CommandMask = Mod1Mask + OptionMask = Mod2Mask + end + + ############################################# + + FIELD_FLAG = { + # key => flag + 'above' => Grp::CONFIG, + 'borderwidth' => (Grp::CREATE|Grp::CONFIG), + 'button' => Grp::BUTTON, + 'count' => Grp::EXPOSE, + 'data' => (Grp::VIRTUAL|Grp::STRING_DATA), + 'delta' => Grp::MWHEEL, + 'detail' => (Grp::FOCUS|Grp::CROSSING), + 'focus' => Grp::CROSSING, + 'height' => (Grp::EXPOSE|Grp::CONFIG), + 'keycode' => Grp::KEY, + 'keysym' => Grp::KEY, + 'mode' => (Grp::CROSSING|Grp::FOCUS), + 'override' => (Grp::CREATE|Grp::MAP|Grp::REPARENT|Grp::CONFIG), + 'place' => Grp::CIRC, + 'root' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING), + 'rootx' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING), + 'rooty' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING), + 'sendevent' => Grp::ALL, + 'serial' => Grp::ALL, + 'state' => (Grp::KEY_BUTTON_MOTION_VIRTUAL| + Grp::CROSSING|Grp::VISIBILITY), + 'subwindow' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING), + 'time' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING| + Grp::PROP), + 'warp' => Grp::KEY_BUTTON_MOTION_VIRTUAL, + 'width' => (Grp::EXPOSE|Grp::CREATE|Grp::CONFIG), + 'window' => (Grp::CREATE|Grp::UNMAP|Grp::MAP|Grp::REPARENT| + Grp::CONFIG|Grp::GRAVITY|Grp::CIRC), + 'when' => Grp::ALL, + 'x' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING| + Grp::EXPOSE|Grp::CREATE|Grp::CONFIG|Grp::GRAVITY| + Grp::REPARENT), + 'y' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING| + Grp::EXPOSE|Grp::CREATE|Grp::CONFIG|Grp::GRAVITY| + Grp::REPARENT), + } + + FIELD_OPERATION = { + 'root' => proc{|val| + begin + Tk.tk_call_without_enc('winfo', 'pathname', val) + val + rescue + nil + end + }, + + 'subwindow' => proc{|val| + begin + Tk.tk_call_without_enc('winfo', 'pathname', val) + val + rescue + nil + end + }, + + 'window' => proc{|val| nil} + } + + #------------------------------------------- + + def valid_fields(group_flag=nil) + group_flag = self.class.group_flag(self.type) unless group_flag + + fields = {} + FIELD_FLAG.each{|key, flag| + next if (flag & group_flag) == 0 + begin + val = self.__send__(key) + rescue + next + end + # next if !val || val == '??' + next if !val || (val == '??' && (flag & Grp::STRING_DATA)) + fields[key] = val + } + + fields + end + + def valid_for_generate(group_flag=nil) + fields = valid_fields(group_flag) + + FIELD_OPERATION.each{|key, cmd| + next unless fields.has_key?(key) + val = FIELD_OPERATION[key].call(fields[key]) + if val + fields[key] = val + else + fields.delete(key) + end + } + + fields + end + + def generate(win, modkeys={}) + klass = self.class + + if modkeys.has_key?(:type) || modkeys.has_key?('type') + modkeys = TkComm._symbolkey2str(modkeys) + type_id = modkeys.delete('type') + else + type_id = self.type + end + + type_name = klass.type_name(type_id) + unless type_name + fail RuntimeError, "type_id #{type_id} is invalid" + end + + group_flag = klass.group_flag(type_id) + + opts = valid_for_generate(group_flag) + + modkeys.each{|key, val| + if val + opts[key.to_s] = val + else + opts.delete(key.to_s) + end + } + + if group_flag != Grp::KEY + Tk.event_generate(win, type_name, opts) + else + # If type is KEY event, focus should be set to target widget. + # If not set, original widget will get the same event. + # That will make infinite loop. + w = Tk.tk_call_without_enc('focus') + begin + Tk.tk_call_without_enc('focus', win) + Tk.event_generate(win, type_name, opts) + ensure + Tk.tk_call_without_enc('focus', w) + end + end + 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 ], + # ?e + [ ?f, ?b, :focus ], + # ?g + [ ?h, ?n, :height ], + [ ?i, ?s, :win_hex ], + # ?j + [ ?k, ?n, :keycode ], + # ?l + [ ?m, ?s, :mode ], + # ?n + [ ?o, ?b, :override ], + [ ?p, ?s, :place ], + # ?q + # ?r + [ ?s, ?x, :state ], + [ ?t, ?n, :time ], + # ?u + [ ?v, ?n, :value_mask ], + [ ?w, ?n, :width ], + [ ?x, ?n, :x ], + [ ?y, ?n, :y ], + # ?z + [ ?A, ?s, :char ], + [ ?B, ?n, :borderwidth ], + # ?C + [ ?D, ?n, :wheel_delta ], + [ ?E, ?b, :send_event ], + # ?F + # ?G + # ?H + # ?I + # ?J + [ ?K, ?s, :keysym ], + # ?L + # ?M + [ ?N, ?n, :keysym_num ], + # ?O + [ ?P, ?s, :property ], + # ?Q + [ ?R, ?s, :rootwin_id ], + [ ?S, ?s, :subwindow ], + [ ?T, ?n, :type ], + # ?U + # ?V + [ ?W, ?w, :widget ], + [ ?X, ?n, :x_root ], + [ ?Y, ?n, :y_root ], + # ?Z + nil + ] + + # [ <'%' subst-key str>, <proc type char>, <instance var (accessor) name>] + # the subst-key string will be converted to a bytecode (128+idx). + LONGKEY_TBL = [ + # for example, for %CTT and %CST subst-key on tkdnd-2.0 + # ['CTT', ?l, :drop_target_type], + # ['CST', ?l, :drop_source_type], + ] + + # [ <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 + ] + +=begin + # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) + KEY_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) + end + inf + } + + PROC_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + end + inf + } +=end + + # 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) + # _setup_subst_table(KEY_TBL, LONGKEY_TBL, PROC_TBL) # if use longname-keys + + # + # NOTE: The order of parameters which passed to callback procedure is + # <extra_arg>, <extra_arg>, ... , <subst_arg>, <subst_arg>, ... + # + + # If you need support extra arguments given by Tcl/Tk, + # please override _get_extra_args_tbl + # + #def self._get_extra_args_tbl + # # return an array of convert procs + # [] + #end + +=begin + alias button num + alias delta wheel_delta + alias root rootwin_id + alias rootx x_root + alias root_x x_root + alias rooty y_root + alias root_y y_root + alias sendevent send_event +=end + ALIAS_TBL = { + :button => :num, + :data => :detail, + :delta => :wheel_delta, + :root => :rootwin_id, + :rootx => :x_root, + :root_x => :x_root, + :rooty => :y_root, + :root_y => :y_root, + :sendevent => :send_event, + :window => :widget + } + + _define_attribute_aliases(ALIAS_TBL) + + end + + ############################################### + + def install_bind_for_event_class(klass, cmd, *args) + extra_args_tbl = klass._get_extra_args_tbl + + if args.compact.size > 0 + args.map!{|arg| klass._sym2subst(arg)} + args = args.join(' ') + keys = klass._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| + ex_args = [] + extra_args_tbl.reverse_each{|conv| ex_args << conv.call(arg.pop)} + begin + TkUtil.eval_cmd(cmd, *(ex_args.concat(klass.scan_args(keys, arg)))) + rescue Exception=>e + if TkCore::INTERP.kind_of?(TclTkIp) + fail e + else + # MultiTkIp + fail Exception, "#{e.class}: #{e.message.dup}" + end + end + }) + end + elsif cmd.respond_to?(:arity) && cmd.arity == 0 # args.size == 0 + args = '' + if cmd.kind_of?(String) + id = cmd + elsif cmd.kind_of?(TkCallbackEntry) + id = install_cmd(cmd) + else + id = install_cmd(proc{ + begin + TkUtil.eval_cmd(cmd) + rescue Exception=>e + if TkCore::INTERP.kind_of?(TclTkIp) + fail e + else + # MultiTkIp + fail Exception, "#{e.class}: #{e.message.dup}" + end + end + }) + end + else + keys, args = klass._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| + ex_args = [] + extra_args_tbl.reverse_each{|conv| ex_args << conv.call(arg.pop)} + begin + TkUtil.eval_cmd(cmd, *(ex_args << klass.new(*klass.scan_args(keys, arg)))) + rescue Exception=>e + if TkCore::INTERP.kind_of?(TclTkIp) + fail e + else + # MultiTkIp + fail Exception, "#{e.class}: #{e.message.dup}" + end + end + }) + end + end + + if TkCore::INTERP.kind_of?(TclTkIp) + id + ' ' + args + else + # MultiTkIp + "if {[set st [catch {#{id} #{args}} ret]] != 0} { + if {$st == 4} { + return -code continue $ret + } elseif {$st == 3} { + return -code break $ret + } elseif {$st == 2} { + return -code return $ret + } elseif {[regexp {^Exception: (TkCallbackContinue: .*)$} \ + $ret m msg]} { + return -code continue $msg + } elseif {[regexp {^Exception: (TkCallbackBreak: .*)$} $ret m msg]} { + return -code break $msg + } elseif {[regexp {^Exception: (TkCallbackReturn: .*)$} $ret m msg]} { + return -code return $msg + } elseif {[regexp {^Exception: (\\S+: .*)$} $ret m msg]} { + return -code return $msg + } else { + return -code error $ret + } + } else { + set ret + }" + end + end + + def install_bind(cmd, *args) + install_bind_for_event_class(TkEvent::Event, cmd, *args) + end +end diff --git a/jni/ruby/ext/tk/lib/tk/font.rb b/jni/ruby/ext/tk/lib/tk/font.rb new file mode 100644 index 0000000..03db850 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/font.rb @@ -0,0 +1,2351 @@ +# +# tk/font.rb - the class to treat fonts on Ruby/Tk +# +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +class TkFont + include Tk + extend TkCore + + TkCommandNames = ['font'.freeze].freeze + + (Tk_FontID = ["@font".freeze, TkUtil.untrust("00000")]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + Tk_FontNameTBL = TkCore::INTERP.create_table + Tk_FontUseTBL = TkCore::INTERP.create_table + + TkCore::INTERP.init_ip_env{ + Tk_FontNameTBL.mutex.synchronize{ Tk_FontNameTBL.clear } + Tk_FontUseTBL.mutex.synchronize{ Tk_FontUseTBL.clear } + } + + # option_type : default => string + OptionType = Hash.new(?s) + OptionType['size'] = ?n + OptionType['pointadjust'] = ?n + OptionType['underline'] = ?b + OptionType['overstrike'] = ?b + + # metric_type : default => num_or_str + MetricType = Hash.new(?n) + MetricType['fixed'] = ?b + + # system font names + SYSTEM_FONT_NAMES = [] + def SYSTEM_FONT_NAMES.add(font_names) + (@mutex ||= Mutex.new).synchronize{ + self.replace(self | font_names.map{|name| name.to_s}) + } + end + def SYSTEM_FONT_NAMES.include?(name) + (@mutex ||= Mutex.new).synchronize{ + super(name.to_s) + } + end + + # set default font + case Tk::TK_VERSION + when /^4\..*/ + DEFAULT_LATIN_FONT_NAME = 'a14'.freeze + DEFAULT_KANJI_FONT_NAME = 'k14'.freeze + + when /^8\.[0-4]/ + if JAPANIZED_TK + begin + fontnames = tk_call('font', 'names') + case fontnames + when /defaultgui/ + # Tcl/Tk-JP for Windows + ltn = 'defaultgui' + knj = 'defaultgui' + when /Mincho:Helvetica-Bold-12/ + # Tcl/Tk-JP for UNIX/X + ltn, knj = tk_split_simplelist(tk_call('font', 'configure', + 'Mincho:Helvetica-Bold-12', + '-compound')) + else + # unknown Tcl/Tk-JP + #platform = tk_call('set', 'tcl_platform(platform)') + platform = Tk::PLATFORM['platform'] + case platform + when 'unix' + ltn = {'family'=>'Helvetica'.freeze, + 'size'=>-12, 'weight'=>'bold'.freeze} + #knj = 'k14' + #knj = '-misc-fixed-medium-r-normal--14-*-*-*-c-*-jisx0208.1983-0' + knj = '-*-fixed-bold-r-normal--12-*-*-*-c-*-jisx0208.1983-0' + when 'windows' + ltn = {'family'=>'MS Sans Serif'.freeze, 'size'=>8} + knj = 'mincho' + when 'macintosh' + ltn = 'system' + knj = 'mincho' + else # unknown + ltn = 'Helvetica' + knj = 'mincho' + end + end + rescue + ltn = 'Helvetica' + knj = 'mincho' + end + + else # not JAPANIZED_TK + begin + #platform = tk_call('set', 'tcl_platform(platform)') + platform = Tk::PLATFORM['platform'] + case platform + when 'unix' + ltn = {'family'=>'Helvetica'.freeze, + 'size'=>-12, 'weight'=>'bold'.freeze} + when 'windows' + ltn = {'family'=>'MS Sans Serif'.freeze, 'size'=>8} + when 'macintosh' + ltn = 'system' + else # unknown + ltn = 'Helvetica' + end + rescue + ltn = 'Helvetica' + end + + knj = ltn.dup + end + + DEFAULT_LATIN_FONT_NAME = ltn.freeze + DEFAULT_KANJI_FONT_NAME = knj.freeze + + when /^8\.[5-9]/, /^9\..*/ + if tk_call('font', 'names') =~ /\bTkDefaultFont\b/ + DEFAULT_LATIN_FONT_NAME = 'TkDefaultFont'.freeze + DEFAULT_KANJI_FONT_NAME = 'TkDefaultFont'.freeze + else + DEFAULT_LATIN_FONT_NAME = 'Helvetica'.freeze + DEFAULT_KANJI_FONT_NAME = 'mincho'.freeze + end + + else # unknown version + DEFAULT_LATIN_FONT_NAME = 'Helvetica'.freeze + DEFAULT_KANJI_FONT_NAME = 'mincho'.freeze + + end + + if $DEBUG + print "default latin font = "; p DEFAULT_LATIN_FONT_NAME + print "default kanji font = "; p DEFAULT_KANJI_FONT_NAME + end + + + ################################### + class DescendantFont + def initialize(compound, type) + unless compound.kind_of?(TkFont) + fail ArgumentError, "a TkFont object is expected for the 1st argument" + end + + @compound = compound + case type + when 'kanji', 'latin', 'ascii' + @type = type + when :kanji, :latin, :ascii + @type = type.to_s + else + fail ArgumentError, "unknown type '#{type}'" + end + end + + def dup + fail RuntimeError, "cannot dupulicate a descendant font" + end + def clone + fail RuntimeError, "cannot clone a descendant font" + end + + def to_eval + @compound.__send__(@type + '_font_id') + end + def font + @compound.__send__(@type + '_font_id') + end + alias font_id font + alias name font + alias to_s font + + def [](slot) + @compound.__send__(@type + '_configinfo', slot) + end + def []=(slot, value) + @compound.__send__(@type + '_configure', slot, value) + value + end + + def method_missing(id, *args) + @compound.__send__(@type + '_' + id.id2name, *args) + end + end + + + ################################### + # class methods + ################################### + def TkFont.is_system_font?(fnt) + # true --> system font which is available on the current system + # false --> not system font (or unknown system font) + # nil --> system font name, but not available on the current system + fnt = fnt.to_s + SYSTEM_FONT_NAMES.include?(fnt) && self.names.index(fnt) && true + end + + def TkFont.actual(fnt, option=nil) + fnt = '{}' if fnt == '' + if fnt.kind_of?(TkFont) + fnt.actual(option) + else + actual_core(fnt, nil, option) + end + end + def TkFont.actual_hash(fnt, option=nil) + Hash[TkFont.actual(fnt, option)] + end + + def TkFont.actual_displayof(fnt, win, option=nil) + fnt = '{}' if fnt == '' + if fnt.kind_of?(TkFont) + fnt.actual_displayof(win, option) + else + win = '.' unless win + actual_core(fnt, win, option) + end + end + def TkFont.actual_hash_displayof(fnt, option=nil) + Hash[TkFont.actual_displayof(fnt, option)] + end + + def TkFont.configure(fnt, slot, value=None) + if fnt.kind_of?(TkFont) + fnt.configure(fnt, slot, value) + else + configure_core(fnt, slot, value) + end + fnt + end + + def TkFont.configinfo(fnt, slot=nil) + if fnt.kind_of?(TkFont) + fnt.configinfo(fnt, slot) + else + configinfo_core(fnt, slot) + end + end + + def TkFont.current_configinfo(fnt, slot=nil) + if fnt.kind_of?(TkFont) + fnt.current_configinfo(fnt, slot) + else + current_configinfo_core(fnt, slot) + end + end + + def TkFont.measure(fnt, text) + fnt = '{}' if fnt == '' + if fnt.kind_of?(TkFont) + fnt.measure(text) + else + measure_core(fnt, nil, text) + end + end + + def TkFont.measure_displayof(fnt, win, text) + fnt = '{}' if fnt == '' + if fnt.kind_of?(TkFont) + fnt.measure_displayof(win, text) + else + win = '.' unless win + measure_core(fnt, win, text) + end + end + + def TkFont.metrics(fnt, option=nil) + fnt = '{}' if fnt == '' + if fnt.kind_of?(TkFont) + fnt.metrics(option) + else + metrics_core(fnt, nil, option) + end + end + def TkFont.metrics_hash(fnt, option=nil) + if option + val = TkFont.metrics(fnt, option) + case TkFont::MetricsType[option.to_s] + when ?n + val = TkComm::num_or_str(val) + when ?b + val = TkComm::bool(val) + else + # do nothing + end + return val + end + + h = Hash[TkFont.metrics(fnt)] + h.keys.each{|k| + case TkFont::MetricsType[k.to_s] + when ?n + h[k] = TkComm::num_or_str(h[k]) + when ?b + h[k] = TkComm::bool(h[k]) + else + # do nothing + end + } + h + end + + def TkFont.metrics_displayof(fnt, win, option=nil) + fnt = '{}' if fnt == '' + if fnt.kind_of?(TkFont) + font.metrics_displayof(win, option=nil) + else + win = '.' unless win + metrics_core(fnt, win, option) + end + end + def TkFont.metrics_hash_displayof(fnt, win, option=nil) + if option + val = TkFont.metrics_displayof(fnt, win, option) + case TkFont::MetricsType[option.to_s] + when ?n + val = TkComm::num_or_str(val) + when ?b + val = TkComm::bool(val) + else + # do nothing + end + return val + end + + h = Hash[TkFont.metrics_displayof(fnt, win, option)] + h.keys.each{|k| + case TkFont::MetricsType[k.to_s] + when ?n + h[k] = TkComm::num_or_str(h[k]) + when ?b + h[k] = TkComm::bool(h[k]) + else + # do nothing + end + } + h + end + + def TkFont.families(win=nil) + case (Tk::TK_VERSION) + when /^4\..*/ + ['fixed'] + + when /^8\..*/ + if win + tk_split_simplelist(tk_call('font', 'families', '-displayof', win)) + else + tk_split_simplelist(tk_call('font', 'families')) + end + end + end + + def TkFont.names + case (Tk::TK_VERSION) + when /^4\..*/ + r = ['fixed'] + r += ['a14', 'k14'] if JAPANIZED_TK + Tk_FontNameTBL.mutex.synchronize{ + Tk_FontNameTBL.each_value{|obj| r.push(obj)} + } + #r | [] + r.uniq + + when /^8\..*/ + tk_split_simplelist(tk_call('font', 'names')) + + end + end + + def TkFont.create_copy(font) + fail 'source-font must be a TkFont object' unless font.kind_of? TkFont + if TkComm::GET_CONFIGINFOwoRES_AS_ARRAY + keys = {} + font.configinfo.each{|key,value| keys[key] = value } + TkFont.new(font.latin_font_id, font.kanji_font_id, keys) + else # ! TkComm::GET_CONFIGINFOwoRES_AS_ARRAY + TkFont.new(font.latin_font_id, font.kanji_font_id, font.configinfo) + end + end + + def TkFont.get_obj(name) + name = name.to_s + if name =~ /^(@font[0-9]+)(|c|l|k)$/ + Tk_FontNameTBL.mutex.synchronize{ + Tk_FontNameTBL[$1] + } + else + Tk_FontNameTBL.mutex.synchronize{ + Tk_FontNameTBL[name] + } + end + end + + def TkFont.init_widget_font(pathname, *args) + win, tag, key = pathname.split(';') + key = 'font' if key == nil || key == '' + path = [win, tag, key].join(';') + + case (Tk::TK_VERSION) + when /^4\..*/ + regexp = /^-(|kanji)#{key} / + + conf_list = tk_split_simplelist(tk_call(*args)). + find_all{|prop| prop =~ regexp}. + collect{|prop| tk_split_simplelist(prop)} + + if conf_list.size == 0 + raise RuntimeError, "the widget may not support 'font' option" + end + + args << {} + + ltn_key = "-#{key}" + knj_key = "-kanji#{key}" + + ltn_info = conf_list.find{|conf| conf[0] == ltn_key} + ltn = ltn_info[-1] + ltn = nil if ltn == [] || ltn == "" + + knj_info = conf_list.find{|conf| conf[0] == knj_key} + knj = knj_info[-1] + knj = nil if knj == [] || knj == "" + + TkFont.new(ltn, knj).call_font_configure([path, key], *args) + + when /^8\.[0-4]/ + regexp = /^-#{key} / + + conf_list = tk_split_simplelist(tk_call(*args)). + find_all{|prop| prop =~ regexp}. + collect{|prop| tk_split_simplelist(prop)} + + if conf_list.size == 0 + raise RuntimeError, "the widget may not support 'font' option" + end + + args << {} + + optkey = "-#{key}" + + info = conf_list.find{|conf| conf[0] == optkey} + fnt = info[-1] + fnt = nil if fnt == [] || fnt == "" + + unless fnt + # create dummy + # TkFont.new(nil, nil).call_font_configure([path, key], *args) + dummy_fnt = TkFont.allocate + dummy_fnt.instance_eval{ init_dummy_fontobj() } + dummy_fnt + else + begin + compound = tk_split_simplelist( + Hash[*tk_split_simplelist(tk_call('font', 'configure', + fnt))].collect{|k,v| + [k[1..-1], v] + }.assoc('compound')[1]) + rescue + compound = [] + end + if compound == [] + if TkFont.is_system_font?(fnt) + TkNamedFont.new(fnt).call_font_configure([path, key], *args) + else + TkFont.new(fnt).call_font_configure([path, key], *args) + end + else + TkFont.new(compound[0], + compound[1]).call_font_configure([path, key], *args) + end + end + + when /^8\.[5-9]/, /^9\..*/ + regexp = /^-#{key} / + + conf_list = tk_split_simplelist(tk_call(*args)). + find_all{|prop| prop =~ regexp}. + collect{|prop| tk_split_simplelist(prop)} + + if conf_list.size == 0 + raise RuntimeError, "the widget may not support 'font' option" + end + + args << {} + + optkey = "-#{key}" + + info = conf_list.find{|conf| conf[0] == optkey} + fnt = info[-1] + fnt = nil if fnt == [] || fnt == "" + + unless fnt + # create dummy + # TkFont.new(nil, nil).call_font_configure([path, key], *args) + dummy_fnt = TkFont.allocate + dummy_fnt.instance_eval{ init_dummy_fontobj() } + dummy_fnt + else + if TkFont.is_system_font?(fnt) + TkNamedFont.new(fnt).call_font_configure([path, key], *args) + else + TkFont.new(fnt).call_font_configure([path, key], *args) + end + end + end + end + + def TkFont.used_on(path=nil) + Tk_FontUseTBL.mutex.synchronize{ + if path + Tk_FontUseTBL[path] + else + # Tk_FontUseTBL.values | [] + Tk_FontUseTBL.values.uniq + end + } + end + + def TkFont.failsafe(font) + begin + if /^8\..*/ === Tk::TK_VERSION && JAPANIZED_TK + tk_call('font', 'failsafe', font) + end + rescue + end + end + + ################################### + # instance methods + ################################### + private + ################################### + def init_dummy_fontobj + Tk_FontID.mutex.synchronize{ + @id = Tk_FontID.join(TkCore::INTERP._ip_id_) + Tk_FontID[1].succ! + } + Tk_FontNameTBL.mutex.synchronize{ + Tk_FontNameTBL[@id] = self + } + + # @latin_desscendant = nil + # @kanji_desscendant = nil + @descendant = [nil, nil] # [latin, kanji] + + case (Tk::TK_VERSION) + when /^4\..*/ + @latinfont = "" + @kanjifont = "" + if JAPANIZED_TK + @compoundfont = [[@latinfont], [@kanjifont]] + @fontslot = {'font'=>@latinfont, 'kanjifont'=>@kanjifont} + else + @compoundfont = @latinfont + @fontslot = {'font'=>@latinfont} + end + else + @latinfont = @id + 'l' + @kanjifont = @id + 'k' + @compoundfont = @id + 'c' + + if JAPANIZED_TK + tk_call('font', 'create', @latinfont, '-charset', 'iso8859') + tk_call('font', 'create', @kanjifont, '-charset', 'jisx0208.1983') + tk_call('font', 'create', @compoundfont, + '-compound', [@latinfont, @kanjifont]) + else + tk_call('font', 'create', @latinfont) + tk_call('font', 'create', @kanjifont) + tk_call('font', 'create', @compoundfont) + end + + @fontslot = {'font'=>@compoundfont} + end + + self + end + + def initialize(ltn=nil, knj=nil, keys=nil) + ltn = '{}' if ltn == '' + knj = '{}' if knj == '' + + Tk_FontID.mutex.synchronize{ + # @id = Tk_FontID.join('') + @id = Tk_FontID.join(TkCore::INTERP._ip_id_) + Tk_FontID[1].succ! + } + Tk_FontNameTBL.mutex.synchronize{ + Tk_FontNameTBL[@id] = self + } + + # @latin_desscendant = nil + # @kanji_desscendant = nil + @descendant = [nil, nil] # [latin, kanji] + + # @latinfont = @id + 'l' + # @kanjifont = @id + 'k' + # @compoundfont = @id + 'c' + # @fontslot = {} + + if knj.kind_of?(Hash) && !keys + keys = knj + knj = nil + end + + # compound font check + if Tk::TK_VERSION == '8.0' && JAPANIZED_TK + begin + compound = tk_split_simplelist(tk_call('font', 'configure', + ltn, '-compound')) + if knj == nil + if compound != [] + ltn, knj = compound + end + else + if compound != [] + ltn = compound[0] + end + compound = tk_split_simplelist(tk_call('font', 'configure', + knj, '-compound')) + if compound != [] + knj = compound[1] + end + end + rescue + end + end + + if ltn + if JAPANIZED_TK && !knj + if Tk::TK_VERSION =~ /^4..*/ + knj = DEFAULT_KANJI_FONT_NAME + else + knj = ltn + end + end + else + ltn = DEFAULT_LATIN_FONT_NAME + knj = DEFAULT_KANJI_FONT_NAME if JAPANIZED_TK && !knj + end + + create_compoundfont(ltn, knj, keys) + end + + def initialize_copy(font) + unless font.kind_of?(TkFont) + fail TypeError, '"initialize_copy should take same class object' + end + if TkComm::GET_CONFIGINFOwoRES_AS_ARRAY + keys = {} + font.configinfo.each{|key,value| keys[key] = value } + initialize(font.latin_font_id, font.kanji_font_id, keys) + else # ! TkComm::GET_CONFIGINFOwoRES_AS_ARRAY + initialize(font.latin_font_id, font.kanji_font_id, font.configinfo) + end + end + + def _get_font_info_from_hash(font) + font = _symbolkey2str(font) + foundry = (info = font['foundry'] .to_s)? info: '*' + family = (info = font['family'] .to_s)? info: '*' + weight = (info = font['weight'] .to_s)? info: '*' + slant = (info = font['slant'] .to_s)? info: '*' + swidth = (info = font['swidth'] .to_s)? info: '*' + adstyle = (info = font['adstyle'] .to_s)? info: '*' + pixels = (info = font['pixels'] .to_s)? info: '*' + points = (info = font['points'] .to_s)? info: '*' + resx = (info = font['resx'] .to_s)? info: '*' + resy = (info = font['resy'] .to_s)? info: '*' + space = (info = font['space'] .to_s)? info: '*' + avgWidth = (info = font['avgWidth'].to_s)? info: '*' + charset = (info = font['charset'] .to_s)? info: '*' + encoding = (info = font['encoding'].to_s)? info: '*' + + [foundry, family, weight, slant, swidth, adstyle, + pixels, points, resx, resy, space, avgWidth, charset, encoding] + end + + def create_latinfont_tk4x(font) + if font.kind_of? Hash + @latinfont = '-' + _get_font_info_from_hash(font).join('-') + '-' + + elsif font.kind_of? Array + finfo = {} + finfo['family'] = font[0].to_s + if font[1] + fsize = font[1].to_s + if fsize != '0' && fsize =~ /^(|\+|-)([0-9]+)$/ + if $1 == '-' + finfo['pixels'] = $2 + else + finfo['points'] = $2 + end + else + finfo['points'] = '13' + end + end + font[2..-1].each{|style| + case (style) + when 'normal' + finfo['weight'] = style + when 'bold' + finfo['weight'] = style + when 'roman' + finfo['slant'] = 'r' + when 'italic' + finfo['slant'] = 'i' + end + } + + @latinfont = '-' + _get_font_info_from_hash(finfo).join('-') + '-' + + elsif font.kind_of? TkFont + @latinfont = font.latin_font + + else + if font + @latinfont = font + else + @latinfont = DEFAULT_LATIN_FONT_NAME + end + + end + end + + def create_kanjifont_tk4x(font) + unless JAPANIZED_TK + @kanjifont = "" + return + end + + if font.kind_of? Hash + @kanjifont = '-' + _get_font_info_from_hash(font).join('-') + '-' + + elsif font.kind_of? Array + finfo = {} + finfo['family'] = font[0].to_s + if font[1] + fsize = font[1].to_s + if fsize != '0' && fsize =~ /^(|\+|-)([0-9]+)$/ + if $1 == '-' + finfo['pixels'] = $2 + else + finfo['points'] = $2 + end + else + finfo['points'] = '13' + end + end + font[2..-1].each{|style| + case (style) + when 'normal' + finfo['weight'] = style + when 'bold' + finfo['weight'] = style + when 'roman' + finfo['slant'] = 'r' + when 'italic' + finfo['slant'] = 'i' + end + } + + @kanjifont = '-' + _get_font_info_from_hash(finfo).join('-') + '-' + elsif font.kind_of? TkFont + @kanjifont = font.kanji_font_id + else + if font + @kanjifont = font + else + @kanjifont = DEFAULT_KANJI_FONT_NAME + end + end + end + + def create_compoundfont_tk4x(ltn, knj, keys) + create_latinfont(ltn) + create_kanjifont(knj) + + if JAPANIZED_TK + @compoundfont = [[@latinfont], [@kanjifont]] + @fontslot = {'font'=>@latinfont, 'kanjifont'=>@kanjifont} + # @fontslot.clear + # @fontslot['font'] = @latinfont + # @fontslot['kanjifont'] = @kanjifont + else + @compoundfont = @latinfont + @fontslot = {'font'=>@latinfont} + # @fontslot.clear + # @fontslot['font'] = @latinfont + end + end + + def create_latinfont_tk8x(font) + @latinfont = @id + 'l' + + if JAPANIZED_TK + if font.kind_of? Hash + if font[:charset] || font['charset'] + tk_call('font', 'create', @latinfont, *hash_kv(font)) + else + tk_call('font', 'create', @latinfont, + '-charset', 'iso8859', *hash_kv(font)) + end + elsif font.kind_of? Array + tk_call('font', 'create', @latinfont, '-copy', array2tk_list(font)) + tk_call('font', 'configure', @latinfont, '-charset', 'iso8859') + elsif font.kind_of? TkFont + tk_call('font', 'create', @latinfont, '-copy', font.latin_font) + elsif font + tk_call('font', 'create', @latinfont, '-copy', font, + '-charset', 'iso8859') + else + tk_call('font', 'create', @latinfont, '-charset', 'iso8859') + end + else + if font.kind_of? Hash + tk_call('font', 'create', @latinfont, *hash_kv(font)) + else + keys = {} + if font.kind_of? Array + actual_core(array2tk_list(font)).each{|key,val| keys[key] = val} + elsif font.kind_of? TkFont + actual_core(font.latin_font).each{|key,val| keys[key] = val} + elsif font + actual_core(font).each{|key,val| keys[key] = val} + end + tk_call('font', 'create', @latinfont, *hash_kv(keys)) + end + + if font && @compoundfont + keys = {} + actual_core(@latinfont).each{|key,val| keys[key] = val} + tk_call('font', 'configure', @compoundfont, *hash_kv(keys)) + end + end + end + + def create_kanjifont_tk8x(font) + @kanjifont = @id + 'k' + + if JAPANIZED_TK + if font.kind_of? Hash + if font[:charset] || font['charset'] + tk_call('font', 'create', @kanjifont, *hash_kv(font)) + else + tk_call('font', 'create', @kanjifont, + '-charset', 'jisx0208.1983', *hash_kv(font)) + end + elsif font.kind_of? Array + tk_call('font', 'create', @kanjifont, '-copy', array2tk_list(font)) + tk_call('font', 'configure', @kanjifont, '-charset', 'jisx0208.1983') + elsif font.kind_of? TkFont + tk_call('font', 'create', @kanjifont, '-copy', font.kanji_font_id) + elsif font + tk_call('font', 'create', @kanjifont, '-copy', font, + '-charset', 'jisx0208.1983') + else + tk_call('font', 'create', @kanjifont, '-charset', 'jisx0208.1983') + end + # end of JAPANIZED_TK + + else + if font.kind_of? Hash + tk_call('font', 'create', @kanjifont, *hash_kv(font)) + else + keys = {} + if font.kind_of? Array + actual_core(array2tk_list(font)).each{|key,val| keys[key] = val} + elsif font.kind_of? TkFont + actual_core(font.kanji_font_id).each{|key,val| keys[key] = val} + elsif font + actual_core(font).each{|key,val| keys[key] = val} + end + tk_call('font', 'create', @kanjifont, *hash_kv(keys)) + end + + if font && @compoundfont + keys = {} + actual_core(@kanjifont).each{|key,val| keys[key] = val} + tk_call('font', 'configure', @compoundfont, *hash_kv(keys)) + end + end + end + + def create_compoundfont_tk8x(ltn, knj, keys) + if knj + create_latinfont(ltn) + create_kanjifont(knj) + else + cfnt = ltn + create_kanjifont(cfnt) + create_latinfont(cfnt) + end + + @compoundfont = @id + 'c' + + if JAPANIZED_TK + unless keys + keys = {} + else + keys = keys.dup + end + if (tk_call('font', 'configure', @latinfont, '-underline') == '1' && + tk_call('font', 'configure', @kanjifont, '-underline') == '1' && + !keys.key?('underline')) + keys['underline'] = true + end + if (tk_call('font', 'configure', @latinfont, '-overstrike') == '1' && + tk_call('font', 'configure', @kanjifont, '-overstrike') == '1' && + !keys.key?('overstrike')) + keys['overstrike'] = true + end + + @fontslot = {'font'=>@compoundfont} + # @fontslot['font'] = @compoundfont + begin + tk_call('font', 'create', @compoundfont, + '-compound', [@latinfont, @kanjifont], *hash_kv(keys)) + rescue RuntimeError => e + if ltn == knj + if e.message =~ /kanji font .* specified/ + tk_call('font', 'delete', @latinfont) + create_latinfont(DEFAULT_LATIN_FONT_NAME) + opts = [] + Hash[*(tk_split_simplelist(tk_call('font', 'configure', + @kanjifont)))].each{|k,v| + case k + when '-size', '-weight', '-slant', '-underline', '-overstrike' + opts << k << v + end + } + tk_call('font', 'configure', @latinfont, *opts) + tk_call('font', 'create', @compoundfont, + '-compound', [@latinfont, @kanjifont], *hash_kv(keys)) + + elsif e.message =~ /ascii font .* specified/ + tk_call('font', 'delete', @kanjifont) + create_kanjifont(DEFAULT_KANJI_FONT_NAME) + opts = [] + Hash[*(tk_split_simplelist(tk_call('font', 'configure', + @latinfont)))].each{|k,v| + case k + when '-size', '-weight', '-slant', '-underline', '-overstrike' + opts << k << v + end + } + tk_call('font', 'configure', @kanjifont, *opts) + tk_call('font', 'create', @compoundfont, + '-compound', [@latinfont, @kanjifont], *hash_kv(keys)) + + else + raise e + end + else + raise e + end + end + else + tk_call('font', 'create', @compoundfont) + + latinkeys = {} + begin + actual_core(@latinfont).each{|key,val| latinkeys[key] = val} + rescue + latinkeys = {} + end + if latinkeys != {} + tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys)) + end + + if knj + compoundkeys = nil + kanjikeys = {} + begin + actual_core(@kanjifont).each{|key,val| kanjikeys[key] = val} + rescue + kanjikeys = {} + end + if kanjikeys != {} + tk_call('font', 'configure', @compoundfont, *hash_kv(kanjikeys)) + end + end + + if cfnt + if cfnt.kind_of?(Hash) + compoundkeys = cfnt.dup + else + compoundkeys = {} + actual_core(cfnt).each{|key,val| compoundkeys[key] = val} + end + compoundkeys.update(_symbolkey2str(keys)) + keys = compoundkeys + end + + @fontslot = {'font'=>@compoundfont} + # @fontslot['font'] = @compoundfont + tk_call('font', 'configure', @compoundfont, *hash_kv(keys)) + end + end + + ################################### + public + ################################### + def inspect + sprintf("#<%s:%0x:%s>", self.class.inspect, self.__id__, @compoundfont) + end + + def method_missing(id, *args) + name = id.id2name + case args.length + when 1 + if name[-1] == ?= + configure name[0..-2], args[0] + args[0] + else + configure name, args[0] + self + end + when 0 + begin + configinfo name + rescue + super(id, *args) +# fail NameError, "undefined local variable or method `#{name}' for #{self.to_s}", error_at + end + else + super(id, *args) +# fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at + end + end + + def call_font_configure(path, *args) + if path.kind_of?(Array) + # [path, optkey] + win, tag = path[0].split(';') + optkey = path[1].to_s + else + win, tag, optkey = path.split(';') + end + + fontslot = _symbolkey2str(@fontslot) + if optkey && optkey != "" + ltn = fontslot.delete('font') + knj = fontslot.delete('kanjifont') + fontslot[optkey] = ltn if ltn + fontslot["kanji#{optkey}"] = knj if knj + end + + keys = _symbolkey2str(args.pop).update(fontslot) + args.concat(hash_kv(keys)) + begin + tk_call(*args) + rescue => e + unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + fail e + end + end + Tk_FontUseTBL.mutex.synchronize{ + Tk_FontUseTBL[[win, tag, optkey].join(';')] = self + } + self + end + + def used + ret = [] + table = nil + Tk_FontUseTBL.mutex.synchronize{ + table = Tk_FontUseTBL.clone # to avoid deadlock + } + table.each{|key,value| + next unless self == value + if key.include?(';') + win, tag, optkey = key.split(';') + winobj = tk_tcl2ruby(win) + #if winobj.kind_of? TkText + if winobj.kind_of?(TkText) || winobj.kind_of?(Tk::Text) + if optkey + ret.push([winobj, winobj.tagid2obj(tag), optkey]) + else + ret.push([winobj, winobj.tagid2obj(tag)]) + end + #elsif winobj.kind_of? TkCanvas + elsif winobj.kind_of?(TkCanvas) || winobj.kind_of?(Tk::Canvas) + if (tagobj = TkcTag.id2obj(winobj, tag)).kind_of? TkcTag + if optkey + ret.push([winobj, tagobj, optkey]) + else + ret.push([winobj, tagobj]) + end + elsif (tagobj = TkcItem.id2obj(winobj, tag)).kind_of? TkcItem + if optkey + ret.push([winobj, tagobj, optkey]) + else + ret.push([winobj, tagobj]) + end + else + if optkey + ret.push([winobj, tag, optkey]) + else + ret.push([winobj, tag]) + end + end + #elsif winobj.kind_of? TkMenu + elsif winobj.kind_of?(TkMenu) || winobj.kind_of?(Tk::Menu) + if optkey + ret.push([winobj, tag, optkey]) + else + ret.push([winobj, tag]) + end + else + if optkey + ret.push([win, tag, optkey]) + else + ret.push([win, tag]) + end + end + else + ret.push(tk_tcl2ruby(key)) + end + } + ret + end + + def id + @id + end + + def to_eval + font + end + + def font + @compoundfont + end + alias font_id font + alias name font + alias to_s font + + def latin_font_id + @latinfont + end + + def latin_font + # @latinfont + if @descendant[0] # [0] -> latin + @descendant[0] + else + @descendant[0] = DescendantFont.new(self, 'latin') + end +=begin + if @latin_descendant + @latin_descendant + else + @latin_descendant = DescendantFont.new(self, 'latin') + end +=end + end + alias latinfont latin_font + + def kanji_font_id + @kanjifont + end + + def kanji_font + # @kanjifont + if @descendant[1] # [1] -> kanji + @descendant[1] + else + @descendant[1] = DescendantFont.new(self, 'kanji') + end +=begin + if @kanji_descendant + @kanji_descendant + else + @kanji_descendant = DescendantFont.new(self, 'kanji') + end +=end + end + alias kanjifont kanji_font + + def actual(option=nil) + actual_core(@compoundfont, nil, option) + end + def actual_hash(option=nil) + Hash[actual(option)] + end + + def actual_displayof(win, option=nil) + win = '.' unless win + actual_core(@compoundfont, win, option) + end + def actual_hash_displayof(win, option=nil) + Hash[actual_displayof(win, option)] + end + + def latin_actual(option=nil) + if @latinfont == nil + actual_core(@compoundfont, nil, option) # use @compoundfont + else + actual_core(@latinfont, nil, option) + end + end + def latin_actual_hash(option=nil) + Hash[latin_actual(option)] + end + + def latin_actual_displayof(win, option=nil) + win = '.' unless win + if @latinfont == nil + actual_core(@compoundfont, win, option) # use @compoundfont + else + actual_core(@latinfont, win, option) + end + end + def latin_actual_hash_displayof(win, option=nil) + Hash[latin_actual_displayof(win, option)] + end + + def kanji_actual(option=nil) + #if JAPANIZED_TK + if @kanjifont == nil + actual_core(@compoundfont, nil, option) # use @compoundfont + elsif @kanjifont != "" + actual_core(@kanjifont, nil, option) + else + actual_core_tk4x(nil, nil, option) + end + end + def kanji_actual_hash(option=nil) + Hash[kanji_actual(option)] + end + + def kanji_actual_displayof(win, option=nil) + #if JAPANIZED_TK + if @kanjifont == nil + actual_core(@compoundfont, nil, option) # use @compoundfont + elsif @kanjifont != "" + win = '.' unless win + actual_core(@kanjifont, win, option) + else + actual_core_tk4x(nil, win, option) + end + end + def kanji_actual_hash_displayof(win, option=nil) + Hash[kanji_actual_displayof(win, option)] + end + + def [](slot) + configinfo slot + end + + def []=(slot, val) + configure slot, val + val + end + + def configure(slot, value=None) + configure_core(@compoundfont, slot, value) + self + end + + def configinfo(slot=nil) + configinfo_core(@compoundfont, slot) + end + + def current_configinfo(slot=nil) + current_configinfo_core(@compoundfont, slot) + end + + def delete + delete_core + end + + def latin_configure(slot, value=None) + if JAPANIZED_TK + configure_core(@latinfont, slot, value) + else + configure(slot, value) + end + self + end + + def latin_configinfo(slot=nil) + if JAPANIZED_TK + configinfo_core(@latinfont, slot) + else + configinfo(slot) + end + end + def latin_current_configinfo(slot=nil) + Hash[latin_configinfo(slot)] + end + + def kanji_configure(slot, value=None) + #if JAPANIZED_TK + if @kanjifont == nil + configure_core(@compoundfont, slot, value) # use @compoundfont + elsif @kanjifont != "" + configure_core(@kanjifont, slot, value) + configure('size'=>configinfo('size')) # to reflect new configuration + else + #"" + configure(slot, value) + end + self + end + + def kanji_configinfo(slot=nil) + #if JAPANIZED_TK + if @kanjifont == nil + configure_core(@compoundfont, slot) # use @compoundfont + elsif @kanjifont != "" + configinfo_core(@kanjifont, slot) + else + #[] + configinfo(slot) + end + end + def kanji_current_configinfo(slot=nil) + Hash[kanji_configinfo(slot)] + end + + def replace(ltn, knj=None) + knj = ltn if knj == None + latin_replace(ltn) + kanji_replace(knj) + self + end + + def latin_replace(ltn) + if @latinfont + latin_replace_core(ltn) + reset_pointadjust + else + # not compound font -> copy properties of ltn + latinkeys = {} + begin + actual_core(ltn).each{|key,val| latinkeys[key] = val} + rescue + latinkeys = {} + end + begin + tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys)) + rescue + # not exist? (deleted?) -> create font + tk_call('font', 'create', @compoundfont, *hash_kv(latinkeys)) + end + end + + self + end + + def kanji_replace(knj) + return self unless @kanjifont # ignore + kanji_replace_core(knj) + reset_pointadjust + self + end + + def measure(text) + measure_core(@compoundfont, nil, text) + end + + def measure_displayof(win, text) + win = '.' unless win + measure_core(@compoundfont, win, text) + end + + def metrics(option=nil) + metrics_core(@compoundfont, nil, option) + end + def metrics_hash(option=nil) + if option + val = metrics(option) + case TkFont::MetricsType[option.to_s] + when ?n + val = TkComm::num_or_str(val) + when ?b + val = TkComm::bool(val) + else + # do nothing + end + return val + end + + h = Hash[metrics(option)] + h.keys.each{|k| + case TkFont::MetricsType[k.to_s] + when ?n + h[k] = TkComm::num_or_str(h[k]) + when ?b + h[k] = TkComm::bool(h[k]) + else + # do nothing + end + } + h + end + + def metrics_displayof(win, option=nil) + win = '.' unless win + metrics_core(@compoundfont, win, option) + end + def metrics_hash_displayof(win, option=nil) + if option + val = metrics_displayof(win, option) + case TkFont::MetricsType[option.to_s] + when ?n + val = TkComm::num_or_str(val) + when ?b + val = TkComm::bool(val) + else + # do nothing + end + return val + end + + h = Hash[metrics_displayof(win, option)] + h.keys.each{|k| + case TkFont::MetricsType[k.to_s] + when ?n + h[k] = TkComm::num_or_str(h[k]) + when ?b + h[k] = TkComm::bool(h[k]) + else + # do nothing + end + } + h + end + + def latin_metrics(option=nil) + if @latinfont == nil + metrics_core(@compoundfont, nil, option) # use @compoundfont + else + metrics_core(@latinfont, nil, option) + end + end + def latin_metrics_hash(option=nil) + if option + val = latin_metrics(option) + case TkFont::MetricsType[option.to_s] + when ?n + val = TkComm::num_or_str(val) + when ?b + val = TkComm::bool(val) + else + # do nothing + end + return val + end + + h = Hash[latin_metrics(option)] + h.keys.each{|k| + case TkFont::MetricsType[k.to_s] + when ?n + h[k] = TkComm::num_or_str(h[k]) + when ?b + h[k] = TkComm::bool(h[k]) + else + # do nothing + end + } + h + end + + def latin_metrics_displayof(win, option=nil) + win = '.' unless win + if @latinfont == nil + metrics_core(@compoundfont, win, option) # use @compoundfont + else + metrics_core(@latinfont, win, option) + end + end + def latin_metrics_hash_displayof(win, option=nil) + if option + val = latin_metrics_displayof(win, option) + case TkFont::MetricsType[option.to_s] + when ?n + val = TkComm::num_or_str(val) + when ?b + val = TkComm::bool(val) + else + # do nothing + end + return val + end + + h = Hash[latin_metrics_displayof(win, option)] + h.keys.each{|k| + case TkFont::MetricsType[k.to_s] + when ?n + h[k] = TkComm::num_or_str(h[k]) + when ?b + h[k] = TkComm::bool(h[k]) + else + # do nothing + end + } + h + end + + def kanji_metrics(option=nil) + if @latinfont == nil + metrics_core(@compoundfont, nil, option) # use @compoundfont + elsif JAPANIZED_TK + metrics_core(@kanjifont, nil, option) + else + metrics_core_tk4x(nil, nil, option) + end + end + def kanji_metrics_hash(option=nil) + if option + val = kanji_metrics(option) + case TkFont::MetricsType[option.to_s] + when ?n + val = TkComm::num_or_str(val) + when ?b + val = TkComm::bool(val) + else + # do nothing + end + return val + end + + h = Hash[kanji_metrics(option)] + h.keys.each{|k| + case TkFont::MetricsType[k.to_s] + when ?n + h[k] = TkComm::num_or_str(h[k]) + when ?b + h[k] = TkComm::bool(h[k]) + else + # do nothing + end + } + h + end + + def kanji_metrics_displayof(win, option=nil) + win = '.' unless win + if @latinfont == nil + metrics_core(@compoundfont, win, option) # use @compoundfont + elsif JAPANIZED_TK + metrics_core(@kanjifont, win, option) + else + metrics_core_tk4x(nil, win, option) + end + end + def kanji_metrics_hash_displayof(win, option=nil) + if option + val = kanji_metrics_displayof(win, option) + case TkFont::MetricsType[option.to_s] + when ?n + val = TkComm::num_or_str(val) + when ?b + val = TkComm::bool(val) + else + # do nothing + end + return val + end + + h = Hash[kanji_metrics_displayof(win, option)] + h.keys.each{|k| + case TkFont::MetricsType[k.to_s] + when ?n + h[k] = TkComm::num_or_str(h[k]) + when ?b + h[k] = TkComm::bool(h[k]) + else + # do nothing + end + } + h + end + + def reset_pointadjust + begin + if /^8\..*/ === Tk::TK_VERSION && JAPANIZED_TK + configure('pointadjust' => latin_actual.assoc('size')[1].to_f / + kanji_actual.assoc('size')[1].to_f ) + end + rescue + end + self + end + + ################################### + # private alias + ################################### + case (Tk::TK_VERSION) + when /^4\..*/ + alias create_latinfont create_latinfont_tk4x + alias create_kanjifont create_kanjifont_tk4x + alias create_compoundfont create_compoundfont_tk4x + + when /^8\.[0-5]/ + alias create_latinfont create_latinfont_tk8x + alias create_kanjifont create_kanjifont_tk8x + alias create_compoundfont create_compoundfont_tk8x + + else + alias create_latinfont create_latinfont_tk8x + alias create_kanjifont create_kanjifont_tk8x + alias create_compoundfont create_compoundfont_tk8x + + end + + ################################### + # public alias + ################################### + alias ascii_font latin_font + alias asciifont latinfont + alias create_asciifont create_latinfont + alias ascii_actual latin_actual + alias ascii_actual_displayof latin_actual_displayof + alias ascii_configure latin_configure + alias ascii_configinfo latin_configinfo + alias ascii_replace latin_replace + alias ascii_metrics latin_metrics + + ################################### +=begin + def dup + TkFont.new(self) + end + def clone + TkFont.new(self) + end +=end +end + +module TkFont::CoreMethods + include Tk + extend TkCore + + private + + def actual_core_tk4x(font, win=nil, option=nil) + # dummy + if option == 'pointadjust' || option == :pointadjust + 1.0 + elsif option + case TkFont::OptionType[option.to_s] + when ?n + 0 + when ?b + false + else + '' + end + else + [['family',''], ['size',0], ['weight',''], ['slant',''], + ['underline',false], ['overstrike',false], ['charset',''], + ['pointadjust',0]] + end + end + + def actual_core_tk8x(font, win=nil, option=nil) + font = '{}' if font == '' + + if option == 'compound' || option == :compound + "" + elsif option + if win + val = tk_call('font', 'actual', font, + "-displayof", win, "-#{option}") + else + val = tk_call('font', 'actual', font, "-#{option}") + end + case TkFont::OptionType[option.to_s] + when ?n + num_or_str(val) + when ?b + bool(val) + else + val + end + else + l = tk_split_simplelist(if win + tk_call('font', 'actual', font, + "-displayof", win) + else + tk_call('font', 'actual', font) + end) + r = [] + while key=l.shift + if key == '-compound' + l.shift + else + key = key[1..-1] + val = l.shift + case TkFont::OptionType[key] + when ?n + r.push [key, num_or_str(val)] + when ?b + r.push [key, bool(val)] + else + r.push [key, val] + end + end + end + r + end + end + + def configure_core_tk4x(font, slot, value=None) + #"" + self + end + + def configinfo_core_tk4x(font, option=nil) + # dummy + if TkComm::GET_CONFIGINFOwoRES_AS_ARRAY + if option == 'pointadjust' || option == :pointadjust + 1.0 + elsif option + case TkFont::OptionType[option.to_s] + when ?n + 0 + when ?b + false + else + '' + end + else + [['family',''], ['size',0], ['weight',''], ['slant',''], + ['underline',false], ['overstrike',false], ['charset',''], + ['pointadjust',1.0]] + end + else # ! TkComm::GET_CONFIGINFOwoRES_AS_ARRAY + current_configinfo_core_tk4x(font, option) + end + end + + def current_configinfo_core_tk4x(font, option=nil) + if option + case TkFont::OptionType[option.to_s] + when ?n + 0 + when ?b + false + else + '' + end + else + {'family'=>'', 'size'=>0, 'weight'=>'', 'slant'=>'', + 'underline'=>false, 'overstrike'=>false, + 'charset'=>false, 'pointadjust'=>1.0} + end + end + + def configure_core_tk8x(font, slot, value=None) + if JAPANIZED_TK + begin + padjust = tk_call('font', 'configure', font, '-pointadjust') + rescue + padjust = nil + end + else + padjust = nil + end + if slot.kind_of? Hash + if JAPANIZED_TK && (slot.key?('family') || slot.key?(:family)) + slot = _symbolkey2str(slot) + configure_core_tk8x(font, 'family', slot.delete('family')) + end + + if ((slot.key?('size') || slot.key?(:size)) && + padjust && !slot.key?('pointadjust') && !slot.key?(:pointadjust)) + tk_call('font', 'configure', font, + '-pointadjust', padjust, *hash_kv(slot)) + else + tk_call('font', 'configure', font, *hash_kv(slot)) + end + elsif (slot == 'size' || slot == :size) && padjust != nil + tk_call('font', 'configure', font, + "-#{slot}", value, '-pointadjust', padjust) + elsif JAPANIZED_TK && (slot == 'family' || slot == :family) + # coumpund font? + begin + compound = tk_split_simplelist(tk_call('font', 'configure', + font, '-compound')) + rescue + tk_call('font', 'configure', font, '-family', value) + return self + end + if compound == [] + tk_call('font', 'configure', font, '-family', value) + return self + end + ltn, knj = compound + + lfnt = tk_call('font', 'create', '-copy', ltn) + begin + tk_call('font', 'configure', lfnt, '-family', value) + latin_replace_core_tk8x(lfnt) + rescue RuntimeError => e + fail e if $DEBUG + ensure + tk_call('font', 'delete', lfnt) if lfnt != '' + end + + kfnt = tk_call('font', 'create', '-copy', knj) + begin + tk_call('font', 'configure', kfnt, '-family', value) + kanji_replace_core_tk8x(lfnt) + rescue RuntimeError => e + fail e if $DEBUG + ensure + tk_call('font', 'delete', kfnt) if kfnt != '' + end + + else + tk_call('font', 'configure', font, "-#{slot}", value) + end + self + end + + def configinfo_core_tk8x(font, option=nil) + if TkComm::GET_CONFIGINFOwoRES_AS_ARRAY + if option == 'compound' || option == :compound + "" + elsif option + val = tk_call('font', 'configure', font, "-#{option}") + case TkFont::OptionType[option.to_s] + when ?n + num_or_str(val) + when ?b + bool(val) + else + val + end + else + l = tk_split_simplelist(tk_call('font', 'configure', font)) + r = [] + while key=l.shift + if key == '-compound' + l.shift + else + key = key[1..-1] + val = l.shift + case TkFont::OptionType[key] + when ?n + r.push [key, num_or_str(val)] + when ?b + r.push [key, bool(val)] + else + r.push [key, val] + end + end + end + r + end + else # ! TkComm::GET_CONFIGINFOwoRES_AS_ARRAY + current_configinfo_core_tk8x(font, option) + end + end + + def current_configinfo_core_tk8x(font, option=nil) + if option == 'compound' + "" + elsif option + val = tk_call('font', 'configure', font, "-#{option}") + case TkFont::OptionType[option.to_s] + when ?n + num_or_str(val) + when ?b + bool(val) + else + val + end + else + l = tk_split_simplelist(tk_call('font', 'configure', font)) + h = {} + while key=l.shift + if key == '-compound' + l.shift + else + key = key[1..-1] + val = l.shift + case TkFont::OptionType[key] + when ?n + h[key] = num_or_str(val) + when ?b + h[key] = bool(val) + else + h[key] = val + end + end + end + h + end + end + + def delete_core_tk4x + TkFont::Tk_FontNameTBL.mutex.synchronize{ + TkFont::Tk_FontNameTBL.delete(@id) + } + TkFont::Tk_FontUseTBL.mutex.synchronize{ + TkFont::Tk_FontUseTBL.delete_if{|key,value| value == self} + } + end + + def delete_core_tk8x + begin + tk_call('font', 'delete', @latinfont) if @latinfont + rescue + end + begin + tk_call('font', 'delete', @kanjifont) if @kanjifont + rescue + end + begin + tk_call('font', 'delete', @compoundfont) if @compoundfont + rescue + end + TkFont::Tk_FontNameTBL.mutex.synchronize{ + TkFont::Tk_FontNameTBL.delete(@id) + } + TkFont::Tk_FontUseTBL.mutex.synchronize{ + TkFont::Tk_FontUseTBL.delete_if{|key,value| value == self} + } + end + + def latin_replace_core_tk4x(ltn) + create_latinfont_tk4x(ltn) + @compoundfont[0] = [@latinfont] if JAPANIZED_TK + @fontslot['font'] = @latinfont + table = nil + TkFont::Tk_FontUseTBL.mutex.synchronize{ + table = TkFont::Tk_FontUseTBL.clone + } + table.each{|w, fobj| + if self == fobj + begin + if w.include?(';') + win, tag, optkey = w.split(';') + optkey = 'font' if optkey == nil || optkey == '' + winobj = tk_tcl2ruby(win) +# winobj.tagfont_configure(tag, {'font'=>@latinfont}) + #if winobj.kind_of? TkText + if winobj.kind_of?(TkText) || winobj.kind_of?(Tk::Text) + tk_call(win, 'tag', 'configure', tag, "-#{optkey}", @latinfont) + #elsif winobj.kind_of? TkCanvas + elsif winobj.kind_of?(TkCanvas) || winobj.kind_of?(Tk::Canvas) + tk_call(win, 'itemconfigure', tag, "-#{optkey}", @latinfont) + #elsif winobj.kind_of? TkMenu + elsif winobj.kind_of?(TkMenu) || winobj.kind_of?(Tk::Menu) + tk_call(win, 'entryconfigure', tag, "-#{optkey}", @latinfont) + else + raise RuntimeError, "unknown widget type" + end + else +# tk_tcl2ruby(w).font_configure('font'=>@latinfont) + tk_call(w, 'configure', '-font', @latinfont) + end + rescue + TkFont::Tk_FontUseTBL.mutex.synchronize{ + TkFont::Tk_FontUseTBL.delete(w) + } + end + end + } + self + end + + def kanji_replace_core_tk4x(knj) + return self unless JAPANIZED_TK + + create_kanjifont_tk4x(knj) + @compoundfont[1] = [@kanjifont] + @fontslot['kanjifont'] = @kanjifont + table = nil + TkFont::Tk_FontUseTBL.mutex.synchronize{ + table = TkFont::Tk_FontUseTBL.clone + } + table.dup.each{|w, fobj| + if self == fobj + begin + if w.include?(';') + win, tag, optkey = w.split(';') + optkey = 'kanjifont' unless optkey + winobj = tk_tcl2ruby(win) +# winobj.tagfont_configure(tag, {'kanjifont'=>@kanjifont}) + #if winobj.kind_of? TkText + if winobj.kind_of?(TkText) || winobj.kind_of?(Tk::Text) + tk_call(win, 'tag', 'configure', tag, "-#{optkey}", @kanjifont) + #elsif winobj.kind_of? TkCanvas + elsif winobj.kind_of?(TkCanvas) || winobj.kind_of?(Tk::Canvas) + tk_call(win, 'itemconfigure', tag, "-#{optkey}", @kanjifont) + #elsif winobj.kind_of? TkMenu + elsif winobj.kind_of?(TkMenu) || winobj.kind_of?(Tk::Menu) + tk_call(win, 'entryconfigure', tag, "-#{optkey}", @latinfont) + else + raise RuntimeError, "unknown widget type" + end + else +# tk_tcl2ruby(w).font_configure('kanjifont'=>@kanjifont) + tk_call(w, 'configure', '-kanjifont', @kanjifont) + end + rescue + Tk_FontUseTBL.mutex.synchronize{ + TkFont::Tk_FontUseTBL.delete(w) + } + end + end + } + self + end + + def latin_replace_core_tk8x(ltn) + ltn = '{}' if ltn == '' + + if JAPANIZED_TK + begin + tk_call('font', 'delete', '@font_tmp') + rescue + end + begin + fnt_bup = tk_call('font', 'create', '@font_tmp', '-copy', @latinfont) + rescue + #fnt_bup = '' + fnt_bup = TkFont::DEFAULT_LATIN_FONT_NAME + end + end + + begin + tk_call('font', 'delete', @latinfont) + rescue + end + create_latinfont(ltn) + + if JAPANIZED_TK + keys = self.configinfo + tk_call('font', 'delete', @compoundfont) + begin + tk_call('font', 'create', @compoundfont, + '-compound', [@latinfont, @kanjifont], *hash_kv(keys)) +=begin + latinkeys = {} + begin + actual_core(@latinfont).each{|key,val| latinkeys[key] = val} + rescue + latinkeys = {} + end + if latinkeys != {} + tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys)) + end +=end + rescue RuntimeError => e + tk_call('font', 'delete', @latinfont) + if fnt_bup && fnt_bup != '' + tk_call('font', 'create', @latinfont, '-copy', fnt_bup) + tk_call('font', 'create', @compoundfont, + '-compound', [@latinfont, @kanjifont], *hash_kv(keys)) + tk_call('font', 'delete', fnt_bup) + else + fail e + end + end + + else + latinkeys = {} + begin + actual_core(@latinfont).each{|key,val| latinkeys[key] = val} + rescue + latinkeys = {} + end + begin + tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys)) + rescue + # not exist? (deleted?) -> create font + tk_call('font', 'create', @compoundfont, *hash_kv(latinkeys)) + end + end + self + end + + def kanji_replace_core_tk8x(knj) + knj = '{}' if knj == '' + + if JAPANIZED_TK + begin + tk_call('font', 'delete', '@font_tmp') + rescue + end + begin + fnt_bup = tk_call('font', 'create', '@font_tmp', '-copy', @kanjifont) + rescue + #fnt_bup = '' + fnt_bup = TkFont::DEFAULT_KANJI_FONT_NAME + end + end + + begin + tk_call('font', 'delete', @kanjifont) + rescue + end + create_kanjifont(knj) + + if JAPANIZED_TK + keys = self.configinfo + tk_call('font', 'delete', @compoundfont) + begin + tk_call('font', 'create', @compoundfont, + '-compound', [@latinfont, @kanjifont], *hash_kv(keys)) + rescue RuntimeError => e + tk_call('font', 'delete', @kanjifont) + if fnt_bup && fnt_bup != '' + tk_call('font', 'create', @kanjifont, '-copy', fnt_bup) + tk_call('font', 'create', @compoundfont, + '-compound', [@latinfont, @kanjifont], *hash_kv(keys)) + tk_call('font', 'delete', fnt_bup) + else + fail e + end + end + end + self + end + + def measure_core_tk4x(font, win, text) + 0 + end + + def measure_core_tk8x(font, win, text) + font = '{}' if font == '' + + if win + number(tk_call('font', 'measure', font, + '-displayof', win, text)) + else + number(tk_call('font', 'measure', font, text)) + end + end + + def metrics_core_tk4x(font, win, option=nil) + # dummy + if option + "" + else + [['ascent',[]], ['descent',[]], ['linespace',[]], ['fixed',[]]] + end + end + + def metrics_core_tk8x(font, win, option=nil) + font = '{}' if font == '' + + if option + if win + number(tk_call('font', 'metrics', font, + "-displayof", win, "-#{option}")) + else + number(tk_call('font', 'metrics', font, "-#{option}")) + end + else + l = tk_split_list(if win + tk_call('font','metrics',font,"-displayof",win) + else + tk_call('font','metrics',font) + end) + r = [] + while key=l.shift + r.push [key[1..-1], l.shift.to_i] +=begin + if key == '-fixed' # boolean value + r.push [key[1..-1], bool(l.shift)] + else + r.push [key[1..-1], l.shift.to_i] + end +=end + end + r + end + end + + ################################### + # private alias + ################################### + case (Tk::TK_VERSION) + when /^4\..*/ + alias actual_core actual_core_tk4x + alias configure_core configure_core_tk4x + alias configinfo_core configinfo_core_tk4x + alias current_configinfo_core current_configinfo_core_tk4x + alias delete_core delete_core_tk4x + alias latin_replace_core latin_replace_core_tk4x + alias kanji_replace_core kanji_replace_core_tk4x + alias measure_core measure_core_tk4x + alias metrics_core metrics_core_tk4x + + when /^8\.[0-9]/ + alias actual_core actual_core_tk8x + alias configure_core configure_core_tk8x + alias configinfo_core configinfo_core_tk8x + alias current_configinfo_core current_configinfo_core_tk8x + alias delete_core delete_core_tk8x + alias latin_replace_core latin_replace_core_tk8x + alias kanji_replace_core kanji_replace_core_tk8x + alias measure_core measure_core_tk8x + alias metrics_core metrics_core_tk8x + + else + alias actual_core actual_core_tk8x + alias configure_core configure_core_tk8x + alias configinfo_core configinfo_core_tk8x + alias current_configinfo_core current_configinfo_core_tk8x + alias delete_core delete_core_tk8x + alias latin_replace_core latin_replace_core_tk8x + alias kanji_replace_core kanji_replace_core_tk8x + alias measure_core measure_core_tk8x + alias metrics_core metrics_core_tk8x + + end +end + +class TkFont + include TkFont::CoreMethods + extend TkFont::CoreMethods +end + +class TkNamedFont < TkFont + # for built-in named fonts + def TkNamedFont.find(name) + name = name.to_s + unless (obj = Tk_FontNameTBL[name]) + obj = self.new(name) if TkFont.is_system_font?(name) + end + obj + end + + def TkNamedFont.new(name, keys=nil) + name = name.to_s + obj = nil + Tk_FontNameTBL.mutex.synchronize{ + unless (obj = Tk_FontNameTBL[name]) + (obj = self.allocate).instance_eval{ + @id = @compoundfont = name.to_s + @latinfont = nil + @kanjifont = nil + @descendant = [self, self] # [latin, kanji] : dummy + Tk_FontNameTBL[@id] = self + } + end + } + obj.instance_eval{ initialize(name, keys) } + obj + end + + ########################### + private + ########################### + def initialize(name, keys=nil) + @id = @compoundfont = name.to_s + + # if not exist named font, create it. + begin + if keys + tk_call('font', 'configure', @compoundfont, keys) + else + tk_call('font', 'configure', @compoundfont) + end + rescue + # the named font doesn't exist -> create + if keys + tk_call('font', 'create', @compoundfont, keys) + else + tk_call('font', 'create', @compoundfont) + end + end + end + + def create_latinfont(fnt) + # ignore + end + def create_kanjifont(fnt) + # ignore + end + def create_compoundfont(ltn, knj, keys) + # ignore + end + + ########################### + public + ########################### + def latin_font_id + @compoundfont + end + def kanji_font_id + @compoundfont + end +end + +####################################### +# define system font names +####################################### +if Tk::TCL_MAJOR_VERSION > 8 || + (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION >= 5) + # add standard fonts of Tcl/Tk 8.5+ + TkFont::SYSTEM_FONT_NAMES.add [ + 'TkDefaultFont', 'TkTextFont', 'TkFixedFont', 'TkMenuFont', + 'TkHeadingFont', 'TkCaptionFont', 'TkSmallCaptionFont', + 'TkIconFont', 'TkTooltipFont' + ] +end + +# platform-specific fonts +# -- windows +TkFont::SYSTEM_FONT_NAMES.add [ + 'ansifixed', 'ansi', 'device', 'oemfixed', 'systemfixed', 'system' +] + +# -- macintosh, macosx +TkFont::SYSTEM_FONT_NAMES.add ['system', 'application'] + +if Tk::TCL_MAJOR_VERSION > 8 || + (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION >= 5) + TkFont::SYSTEM_FONT_NAMES.add ['menu'] +end + +# -- macosx (Aqua theme) +if Tk::TCL_MAJOR_VERSION > 8 || + (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION >= 5) + TkFont::SYSTEM_FONT_NAMES.add [ + 'systemSystemFont', 'systemEmphasizedSystemFont', + 'systemSmallSystemFont', 'systemSmallEmphasizedSystemFont', + 'systemApplicationFont', 'systemLabelFont', 'systemViewsFont', + 'systemMenuTitleFont', 'systemMenuItemFont', 'systemMenuItemMarkFont', + 'systemMenuItemCmdKeyFont', 'systemWindowTitleFont', + 'systemPushButtonFont', 'systemUtilityWindowTitleFont', + 'systemAlertHeaderFont', 'systemToolbarFont', 'systemMiniSystemFont', + 'systemDetailSystemFont', 'systemDetailEmphasizedSystemFont' + ] +end + +####################################### +# autoload +####################################### +class TkFont + autoload :Chooser, 'tk/fontchooser' +end diff --git a/jni/ruby/ext/tk/lib/tk/fontchooser.rb b/jni/ruby/ext/tk/lib/tk/fontchooser.rb new file mode 100644 index 0000000..22d70f9 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/fontchooser.rb @@ -0,0 +1,180 @@ +# +# tk/fontchooser.rb -- "tk fontchooser" support (Tcl/Tk8.6 or later) +# +require 'tk' +require 'tk/font' + +module TkFont::Chooser + extend TkCore +end + +module Tk + Fontchooser = TkFont::Chooser +end + +class << TkFont::Chooser + def method_missing(id, *args) + name = id.id2name + case args.length + when 1 + if name[-1] == ?= + configure name[0..-2], args[0] + args[0] + else + configure name, args[0] + self + end + when 0 + begin + cget(name) + rescue + super(id, *args) + end + else + super(id, *args) + end + end + + def __configinfo_value(key, val) + case key + when 'parent' + window(val) + when 'title' + val + when 'font' + if (lst = tk_split_simplelist(val)).size == 1 + lst[0] + else + lst.map{|elem| num_or_str(elem)} + end + when 'command' + tk_tcl2ruby(val) + when 'visible' + bool(val) + else # unkown + val + end + end + private :__configinfo_value + + def configinfo(option=nil) + if !option && TkComm::GET_CONFIGINFOwoRES_AS_ARRAY + lst = tk_split_simplelist(tk_call('tk', 'fontchooser', 'configure')) + ret = [] + TkComm.slice_ary(lst, 2){|k, v| + k = k[1..-1] + ret << [k, __configinfo_value(k, v)] + } + ret + else + current_configinfo(option) + end + end + + def current_configinfo(option=nil) + if option + opt = option.to_s + fail ArgumentError, "Invalid option `#{option.inspect}'" if opt.empty? + __configinfo_value(option.to_s, tk_call('tk','fontchooser', + 'configure',"-#{opt}")) + else + lst = tk_split_simplelist(tk_call('tk', 'fontchooser', 'configure')) + ret = {} + TkComm.slice_ary(lst, 2){|k, v| + k = k[1..-1] + ret[k] = __configinfo_value(k, v) + } + ret + end + end + + def configure(option, value=None) + if option.kind_of? Hash + tk_call('tk', 'fontchooser', 'configure', + *hash_kv(_symbolkey2str(option))) + else + opt = option.to_s + fail ArgumentError, "Invalid option `#{option.inspect}'" if opt.empty? + tk_call('tk', 'fontchooser', 'configure', "-#{opt}", value) + end + self + end + + def configure_cmd(slot, value) + configure(slot, install_cmd(value)) + end + + def command(cmd=nil, &b) + if cmd + configure_cmd('command', cmd) + elsif b + configure_cmd('command', Proc.new(&b)) + else + cget('command') + end + end + + def cget(slot) + configinfo slot + end + + def [](slot) + cget slot + end + + def []=(slot, val) + configure slot, val + val + end + + def show + tk_call('tk', 'fontchooser', 'show') + self + end + + def hide + tk_call('tk', 'fontchooser', 'hide') + self + end + + def toggle + cget(:visible) ? hide: show + self + end + + def set_for(target, title="Font") + if target.kind_of? TkFont + configs = { + :font=>target.actual_hash, + :command=>proc{|fnt, *args| + target.configure(TkFont.actual_hash(fnt)) + } + } + elsif target.kind_of? Hash + # key=>value list or OptionObj + fnt = target[:font] rescue '' + fnt = fnt.actual_hash if fnt.kind_of?(TkFont) + configs = { + :font => fnt, + :command=>proc{|fnt, *args| + target[:font] = TkFont.actual_hash(fnt) + } + } + else + configs = { + :font=>target.cget_tkstring(:font), + :command=>proc{|fnt, *args| + target.font = TkFont.actual_hash_displayof(fnt, target) + } + } + end + + configs[:title] = title if title + configure(configs) + target + end + + def unset + configure(:command, nil) + end +end diff --git a/jni/ruby/ext/tk/lib/tk/frame.rb b/jni/ruby/ext/tk/lib/tk/frame.rb new file mode 100644 index 0000000..5118939 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/frame.rb @@ -0,0 +1,132 @@ +# +# tk/frame.rb : treat frame widget +# +require 'tk' + +class Tk::Frame<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 __boolval_optkeys + super() << 'container' + end + private :__boolval_optkeys + + def initialize(parent=nil, keys=nil) + my_class_name = nil + if self.class < WidgetClassNames[self.class::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, &b) + if self == WidgetClassNames[WidgetClassName] || self.name == '' + super(*args, &b) + else + TkDatabaseClass.new(self.name).bind(*args, &b) + end + end + def self.bind_append(*args, &b) + if self == WidgetClassNames[WidgetClassName] || self.name == '' + super(*args, &b) + else + TkDatabaseClass.new(self.name).bind_append(*args, &b) + 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 + +#TkFrame = Tk::Frame unless Object.const_defined? :TkFrame +#Tk.__set_toplevel_aliases__(:Tk, Tk::Frame, :TkFrame) +Tk.__set_loaded_toplevel_aliases__('tk/frame.rb', :Tk, Tk::Frame, :TkFrame) diff --git a/jni/ruby/ext/tk/lib/tk/grid.rb b/jni/ruby/ext/tk/lib/tk/grid.rb new file mode 100644 index 0000000..e1e07c4 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/grid.rb @@ -0,0 +1,279 @@ +# +# 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 + +=begin + 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) + } + if Tk::TCL_MAJOR_VERSION < 8 || + (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION <= 3) + if params[0] == '-' || params[0] == 'x' || params[0] == '^' + tk_call_without_enc('grid', *params) + else + tk_call_without_enc('grid', 'configure', *params) + end + else + tk_call_without_enc('grid', 'configure', *params) + end + end +=end + def configure(*args) + if args[-1].kind_of?(Hash) + opts = args.pop + else + opts = {} + end + fail ArgumentError, 'no widget is given' if args.empty? + params = [] + args.flatten(1).each{|win| + case win + when '-', ?- # RELATIVE PLACEMENT (increase columnspan) + params.push('-') + when /^-+$/ # RELATIVE PLACEMENT (increase columnspan) + params.concat(win.to_s.split(//)) + when '^', ?^ # RELATIVE PLACEMENT (increase rowspan) + params.push('^') + when /^\^+$/ # RELATIVE PLACEMENT (increase rowspan) + params.concat(win.to_s.split(//)) + when 'x', :x, ?x, nil, '' # RELATIVE PLACEMENT (empty column) + params.push('x') + when /^x+$/ # RELATIVE PLACEMENT (empty column) + params.concat(win.to_s.split(//)) + else + params.push(_epath(win)) + end + } + opts.each{|k, v| + params.push("-#{k}") + params.push(_epath(v)) # have to use 'epath' (hash_kv() is unavailable) + } + if Tk::TCL_MAJOR_VERSION < 8 || + (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION <= 3) + if params[0] == '-' || params[0] == 'x' || params[0] == '^' + tk_call_without_enc('grid', *params) + else + tk_call_without_enc('grid', 'configure', *params) + end + else + tk_call_without_enc('grid', 'configure', *params) + end + end + alias grid configure + + 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 + case slot + when 'uniform', :uniform + tk_call_without_enc('grid', 'columnconfigure', + master, index, "-#{slot}") + else + num_or_str(tk_call_without_enc('grid', 'columnconfigure', + master, index, "-#{slot}")) + end + else + #ilist = list(tk_call_without_enc('grid','columnconfigure',master,index)) + ilist = simplelist(tk_call_without_enc('grid', 'columnconfigure', + master, index)) + info = {} + while key = ilist.shift + case key + when 'uniform' + info[key[1..-1]] = ilist.shift + else + info[key[1..-1]] = tk_tcl2ruby(ilist.shift) + end + end + info + end + end + + def rowconfiginfo(master, index, slot=nil) + # master = master.epath if master.kind_of?(TkObject) + master = _epath(master) + if slot + case slot + when 'uniform', :uniform + tk_call_without_enc('grid', 'rowconfigure', + master, index, "-#{slot}") + else + num_or_str(tk_call_without_enc('grid', 'rowconfigure', + master, index, "-#{slot}")) + end + else + #ilist = list(tk_call_without_enc('grid', 'rowconfigure', master, index)) + ilist = simplelist(tk_call_without_enc('grid', 'rowconfigure', + master, index)) + info = {} + while key = ilist.shift + case key + when 'uniform' + info[key[1..-1]] = ilist.shift + else + info[key[1..-1]] = tk_tcl2ruby(ilist.shift) + end + end + info + end + end + + def column(master, index, keys=nil) + if keys.kind_of?(Hash) + columnconfigure(master, index, keys) + else + columnconfiginfo(master, index, keys) + end + end + + def row(master, index, keys=nil) + if keys.kind_of?(Hash) + rowconfigure(master, index, keys) + else + rowconfiginfo(master, index, keys) + 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)) + ilist = simplelist(tk_call_without_enc('grid', 'info', slave)) + info = {} + while key = ilist.shift + #info[key[1..-1]] = ilist.shift + info[key[1..-1]] = tk_tcl2ruby(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, mode=None) + # master = master.epath if master.kind_of?(TkObject) + master = _epath(master) + if mode == None + bool(tk_call_without_enc('grid', 'propagate', master)) + else + tk_call_without_enc('grid', 'propagate', master, mode) + 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, keys=nil) + # 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 :anchor, :bbox, :add, :forget, :propagate, :info + module_function :remove, :size, :slaves, :location + module_function :grid, :configure, :columnconfigure, :rowconfigure + module_function :column, :row, :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 diff --git a/jni/ruby/ext/tk/lib/tk/image.rb b/jni/ruby/ext/tk/lib/tk/image.rb new file mode 100644 index 0000000..9723839 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/image.rb @@ -0,0 +1,395 @@ +# +# 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, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + TkCore::INTERP.init_ip_env{ + Tk_IMGTBL.mutex.synchronize{ Tk_IMGTBL.clear } + } + + def self.new(keys=nil) + if keys.kind_of?(Hash) + name = nil + if keys.key?(:imagename) + name = keys[:imagename] + elsif keys.key?('imagename') + name = keys['imagename'] + end + if name + if name.kind_of?(TkImage) + obj = name + else + name = _get_eval_string(name) + obj = nil + Tk_IMGTBL.mutex.synchronize{ + obj = Tk_IMGTBL[name] + } + end + if obj + if !(keys[:without_creating] || keys['without_creating']) + keys = _symbolkey2str(keys) + keys.delete('imagename') + keys.delete('without_creating') + obj.instance_eval{ + tk_call_without_enc('image', 'create', + @type, @path, *hash_kv(keys, true)) + } + end + return obj + end + end + end + (obj = self.allocate).instance_eval{ + Tk_IMGTBL.mutex.synchronize{ + initialize(keys) + Tk_IMGTBL[@path] = self + } + } + obj + end + + def initialize(keys=nil) + @path = nil + without_creating = false + if keys.kind_of?(Hash) + keys = _symbolkey2str(keys) + @path = keys.delete('imagename') + without_creating = keys.delete('without_creating') + end + unless @path + Tk_Image_ID.mutex.synchronize{ + @path = Tk_Image_ID.join(TkCore::INTERP._ip_id_) + Tk_Image_ID[1].succ! + } + end + unless without_creating + tk_call_without_enc('image', 'create', + @type, @path, *hash_kv(keys, true)) + end + end + + def delete + Tk_IMGTBL.mutex.synchronize{ + 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_IMGTBL.mutex.synchronize{ + 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 __strval_optkeys + super() + ['maskdata', 'maskfile'] + end + private :__strval_optkeys + + def initialize(*args) + @type = 'bitmap' + super(*args) + end +end + +# A photo is an image whose pixels can display any color or be transparent. +# At present, only GIF and PPM/PGM formats are supported, but an interface +# exists to allow additional image file formats to be added easily. +# +# This class documentation is a copy from the original Tcl/Tk at +# http://www.tcl.tk/man/tcl8.5/TkCmd/photo.htm with some rewritten parts. +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 + } + keys.collect{|k,v| + ['-' << k, v] + }.flatten + end + private :_photo_hash_kv + + # Create a new image with the given options. + # == Examples of use : + # === Create an empty image of 300x200 pixels + # + # image = TkPhotoImage.new(:height => 200, :width => 300) + # + # === Create an image from a file + # + # image = TkPhotoImage.new(:file: => 'my_image.gif') + # + # == Options + # Photos support the following options: + # * :data + # Specifies the contents of the image as a string. + # * :format + # Specifies the name of the file format for the data. + # * :file + # Gives the name of a file that is to be read to supply data for the image. + # * :gamma + # Specifies that the colors allocated for displaying this image in a window + # should be corrected for a non-linear display with the specified gamma + # exponent value. + # * height + # Specifies the height of the image, in pixels. This option is useful + # primarily in situations where the user wishes to build up the contents of + # the image piece by piece. A value of zero (the default) allows the image + # to expand or shrink vertically to fit the data stored in it. + # * palette + # Specifies the resolution of the color cube to be allocated for displaying + # this image. + # * width + # Specifies the width of the image, in pixels. This option is useful + # primarily in situations where the user wishes to build up the contents of + # the image piece by piece. A value of zero (the default) allows the image + # to expand or shrink horizontally to fit the data stored in it. + def initialize(*args) + @type = 'photo' + super(*args) + end + + # Blank the image; that is, set the entire image to have no data, so it will + # be displayed as transparent, and the background of whatever window it is + # displayed in will show through. + def blank + tk_send_without_enc('blank') + self + end + + def cget_strict(option) + case option.to_s + when 'data', 'file' + tk_send 'cget', '-' << option.to_s + else + tk_tcl2ruby(tk_send('cget', '-' << option.to_s)) + end + end + + # Returns the current value of the configuration option given by option. + # Example, display name of the file from which <tt>image</tt> was created: + # puts image.cget :file + def cget(option) + unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + cget_strict(option) + else + begin + cget_strict(option) + rescue => e + if current_configinfo.has_key?(option.to_s) + # error on known option + fail e + else + # unknown option + nil + end + end + end + end + + # Copies a region from the image called source to the image called + # destination, possibly with pixel zooming and/or subsampling. If no options + # are specified, this method copies the whole of source into destination, + # starting at coordinates (0,0) in destination. The following options may be + # specified: + # + # * :from [x1, y1, x2, y2] + # Specifies a rectangular sub-region of the source image to be copied. + # (x1,y1) and (x2,y2) specify diagonally opposite corners of the rectangle. + # If x2 and y2 are not specified, the default value is the bottom-right + # corner of the source image. The pixels copied will include the left and + # top edges of the specified rectangle but not the bottom or right edges. + # If the :from option is not given, the default is the whole source image. + # * :to [x1, y1, x2, y2] + # Specifies a rectangular sub-region of the destination image to be + # affected. (x1,y1) and (x2,y2) specify diagonally opposite corners of the + # rectangle. If x2 and y2 are not specified, the default value is (x1,y1) + # plus the size of the source region (after subsampling and zooming, if + # specified). If x2 and y2 are specified, the source region will be + # replicated if necessary to fill the destination region in a tiled fashion. + # * :shrink + # Specifies that the size of the destination image should be reduced, if + # necessary, so that the region being copied into is at the bottom-right + # corner of the image. This option will not affect the width or height of + # the image if the user has specified a non-zero value for the :width or + # :height configuration option, respectively. + # * :zoom [x, y] + # Specifies that the source region should be magnified by a factor of x + # in the X direction and y in the Y direction. If y is not given, the + # default value is the same as x. With this option, each pixel in the + # source image will be expanded into a block of x x y pixels in the + # destination image, all the same color. x and y must be greater than 0. + # * :subsample [x, y] + # Specifies that the source image should be reduced in size by using only + # every xth pixel in the X direction and yth pixel in the Y direction. + # Negative values will cause the image to be flipped about the Y or X axes, + # respectively. If y is not given, the default value is the same as x. + # * :compositingrule rule + # Specifies how transparent pixels in the source image are combined with + # the destination image. When a compositing rule of <tt>overlay</tt> is set, + # the old contents of the destination image are visible, as if the source + # image were printed on a piece of transparent film and placed over the + # top of the destination. When a compositing rule of <tt>set</tt> is set, + # the old contents of the destination image are discarded and the source + # image is used as-is. The default compositing rule is <tt>overlay</tt>. + 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', src, *args) + end + self + end + + # Returns image data in the form of a string. The following options may be + # specified: + # * :background color + # If the color is specified, the data will not contain any transparency + # information. In all transparent pixels the color will be replaced by the + # specified color. + # * :format format-name + # Specifies the name of the image file format handler to be used. + # Specifically, this subcommand searches for the first handler whose name + # matches an initial substring of format-name and which has the capability + # to read this image data. If this option is not given, this subcommand + # uses the first handler that has the capability to read the image data. + # * :from [x1, y1, x2, y2] + # Specifies a rectangular region of imageName to be returned. If only x1 + # and y1 are specified, the region extends from (x1,y1) to the bottom-right + # corner of imageName. If all four coordinates are given, they specify + # diagonally opposite corners of the rectangular region, including x1,y1 + # and excluding x2,y2. The default, if this option is not given, is the + # whole image. + # * :grayscale + # If this options is specified, the data will not contain color information. + # All pixel data will be transformed into grayscale. + def data(keys={}) + tk_split_list(tk_send('data', *_photo_hash_kv(keys))) + end + + # Returns the color of the pixel at coordinates (x,y) in the image as a list + # of three integers between 0 and 255, representing the red, green and blue + # components respectively. + def get(x, y) + tk_send('get', x, y).split.collect{|n| n.to_i} + end + + def put(data, *opts) + if opts.empty? + 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 + + # Returns a boolean indicating if the pixel at (x,y) is transparent. + def get_transparency(x, y) + bool(tk_send('transparency', 'get', x, y)) + end + + # Makes the pixel at (x,y) transparent if <tt>state</tt> is true, and makes + # that pixel opaque otherwise. + def set_transparency(x, y, state) + tk_send('transparency', 'set', x, y, state) + 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 diff --git a/jni/ruby/ext/tk/lib/tk/itemconfig.rb b/jni/ruby/ext/tk/lib/tk/itemconfig.rb new file mode 100644 index 0000000..1439604 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/itemconfig.rb @@ -0,0 +1,1222 @@ +# +# tk/itemconfig.rb : control item/tag configuration of widget +# +require 'tk' +require 'tkutil' +require 'tk/itemfont.rb' + +module TkItemConfigOptkeys + include TkUtil + + def __item_optkey_aliases(id) + {} + end + private :__item_optkey_aliases + + def __item_numval_optkeys(id) + [] + end + private :__item_numval_optkeys + + def __item_numstrval_optkeys(id) + [] + end + private :__item_numstrval_optkeys + + def __item_boolval_optkeys(id) + ['exportselection', 'jump', 'setgrid', 'takefocus'] + end + private :__item_boolval_optkeys + + def __item_strval_optkeys(id) + # maybe need to override + [ + 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile', + 'activebackground', 'activeforeground', 'background', + 'disabledforeground', 'disabledbackground', 'foreground', + 'highlightbackground', 'highlightcolor', 'insertbackground', + 'selectbackground', 'selectforeground', 'troughcolor' + ] + end + private :__item_strval_optkeys + + def __item_listval_optkeys(id) + [] + end + private :__item_listval_optkeys + + def __item_numlistval_optkeys(id) + # maybe need to override + ['dash', 'activedash', 'disableddash'] + end + private :__item_numlistval_optkeys + + def __item_tkvariable_optkeys(id) + ['variable', 'textvariable'] + end + private :__item_tkvariable_optkeys + + def __item_val2ruby_optkeys(id) # { key=>method, ... } + # The method is used to convert a opt-value to a ruby's object. + # When get the value of the option "key", "method.call(id, val)" is called. + {} + end + private :__item_val2ruby_optkeys + + def __item_ruby2val_optkeys(id) # { key=>method, ... } + # The method is used to convert a ruby's object to a opt-value. + # When set the value of the option "key", "method.call(id, val)" is called. + # That is, "-#{key} #{method.call(id, value)}". + {} + end + private :__item_ruby2val_optkeys + + def __item_methodcall_optkeys(id) # { key=>method, ... } + # Use the method for both of get and set. + # Usually, the 'key' will not be a widget option. + # + # maybe need to override + # {'coords'=>'coords'} + {} + end + private :__item_methodcall_optkeys + + ################################################ + + def __item_keyonly_optkeys(id) # { def_key=>(undef_key|nil), ... } + # maybe need to override + {} + end + private :__item_keyonly_optkeys + + + def __conv_item_keyonly_opts(id, keys) + return keys unless keys.kind_of?(Hash) + keyonly = __item_keyonly_optkeys(id) + keys2 = {} + keys.each{|k, v| + optkey = keyonly.find{|kk,vv| kk.to_s == k.to_s} + if optkey + defkey, undefkey = optkey + if v + keys2[defkey.to_s] = None + else + keys2[undefkey.to_s] = None + end + else + keys2[k.to_s] = v + end + } + keys2 + end + + def itemconfig_hash_kv(id, keys, enc_mode = nil, conf = nil) + hash_kv(__conv_item_keyonly_opts(id, keys), enc_mode, conf) + end +end + +module TkItemConfigMethod + include TkUtil + include TkTreatItemFont + include TkItemConfigOptkeys + + def TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + @mode || false + end + def TkItemConfigMethod.__set_IGNORE_UNKNOWN_CONFIGURE_OPTION__!(mode) + fail SecurityError, "can't change the mode" if $SAFE>=4 + @mode = (mode)? true: false + end + + def __item_cget_cmd(id) + # maybe need to override + [self.path, 'itemcget', id] + end + private :__item_cget_cmd + + def __item_config_cmd(id) + # maybe need to override + [self.path, 'itemconfigure', id] + end + private :__item_config_cmd + + def __item_confinfo_cmd(id) + # maybe need to override + __item_config_cmd(id) + end + private :__item_confinfo_cmd + + def __item_configinfo_struct(id) + # maybe need to override + {:key=>0, :alias=>1, :db_name=>1, :db_class=>2, + :default_value=>3, :current_value=>4} + end + private :__item_configinfo_struct + + ################################################ + + def tagid(tagOrId) + # maybe need to override + tagOrId + end + + ################################################ + + + def itemcget_tkstring(tagOrId, option) + opt = option.to_s + fail ArgumentError, "Invalid option `#{option.inspect}'" if opt.length == 0 + tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{opt}")) + end + + def __itemcget_core(tagOrId, option) + orig_opt = option + option = option.to_s + + if option.length == 0 + fail ArgumentError, "Invalid option `#{orig_opt.inspect}'" + end + + alias_name, real_name = __item_optkey_aliases(tagid(tagOrId)).find{|k, v| k.to_s == option} + if real_name + option = real_name.to_s + end + + if ( method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[option] ) + optval = tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}")) + begin + return method.call(tagOrId, optval) + rescue => e + warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG + return optval + end + end + + if ( method = _symbolkey2str(__item_methodcall_optkeys(tagid(tagOrId)))[option] ) + return self.__send__(method, tagOrId) + end + + case option + when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/ + begin + number(tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}"))) + rescue + nil + end + + when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/ + num_or_str(tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}"))) + + when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/ + begin + bool(tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}"))) + rescue + nil + end + + when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/ + simplelist(tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}"))) + + when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/ + conf = tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}")) + if conf =~ /^[0-9]/ + list(conf) + else + conf + end + + when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/ + v = tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}")) + (v.empty?)? nil: TkVarAccess.new(v) + + when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/ + _fromUTF8(tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}"))) + + when /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/ + fontcode = $1 + fontkey = $2 + fnt = tk_tcl2ruby(tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{fontkey}")), true) + unless fnt.kind_of?(TkFont) + fnt = tagfontobj(tagid(tagOrId), fontkey) + end + if fontcode == 'kanji' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/ + # obsolete; just for compatibility + fnt.kanji_font + else + fnt + end + else + tk_tcl2ruby(tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}")), true) + end + end + private :__itemcget_core + + def itemcget(tagOrId, option) + unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + __itemcget_core(tagOrId, option) + else + begin + __itemcget_core(tagOrId, option) + rescue => e + begin + if __current_itemconfiginfo(tagOrId).has_key?(option.to_s) + # not tag error & option is known -> error on known option + fail e + else + # not tag error & option is unknown + nil + end + rescue + fail e # tag error + end + end + end + end + def itemcget_strict(tagOrId, option) + # never use TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + __itemcget_core(tagOrId, option) + end + + def __itemconfigure_core(tagOrId, slot, value=None) + if slot.kind_of? Hash + slot = _symbolkey2str(slot) + + __item_optkey_aliases(tagid(tagOrId)).each{|alias_name, real_name| + alias_name = alias_name.to_s + if slot.has_key?(alias_name) + slot[real_name.to_s] = slot.delete(alias_name) + end + } + + __item_methodcall_optkeys(tagid(tagOrId)).each{|key, method| + value = slot.delete(key.to_s) + self.__send__(method, tagOrId, value) if value + } + + __item_ruby2val_optkeys(tagid(tagOrId)).each{|key, method| + key = key.to_s + slot[key] = method.call(tagOrId, slot[key]) if slot.has_key?(key) + } + + __item_keyonly_optkeys(tagid(tagOrId)).each{|defkey, undefkey| + conf = slot.find{|kk, vv| kk == defkey.to_s} + if conf + k, v = conf + if v + slot[k] = None + else + slot[undefkey.to_s] = None if undefkey + slot.delete(k) + end + end + } + + if (slot.find{|k, v| k =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/}) + tagfont_configure(tagid(tagOrId), slot) + elsif slot.size > 0 + tk_call(*(__item_config_cmd(tagid(tagOrId)).concat(hash_kv(slot)))) + end + + else + orig_slot = slot + slot = slot.to_s + if slot.length == 0 + fail ArgumentError, "Invalid option `#{orig_slot.inspect}'" + end + + alias_name, real_name = __item_optkey_aliases(tagid(tagOrId)).find{|k, v| k.to_s == slot} + if real_name + slot = real_name.to_s + end + + if ( conf = __item_keyonly_optkeys(tagid(tagOrId)).find{|k, v| k.to_s == slot } ) + defkey, undefkey = conf + if value + tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{defkey}")) + elsif undefkey + tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{undefkey}")) + end + elsif ( method = _symbolkey2str(__item_ruby2val_optkeys(tagid(tagOrId)))[slot] ) + tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{slot}" << method.call(tagOrId, value))) + elsif ( method = _symbolkey2str(__item_methodcall_optkeys(tagid(tagOrId)))[slot] ) + self.__send__(method, tagOrId, value) + elsif (slot =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/) + if value == None + tagfontobj(tagid(tagOrId), $2) + else + tagfont_configure(tagid(tagOrId), {slot=>value}) + end + else + tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{slot}" << value)) + end + end + self + end + private :__itemconfigure_core + + def __check_available_itemconfigure_options(tagOrId, keys) + id = tagid(tagOrId) + + availables = self.__current_itemconfiginfo(id).keys + + # add non-standard keys + availables |= __font_optkeys.map{|k| + [k.to_s, "latin#{k}", "ascii#{k}", "kanji#{k}"] + }.flatten + availables |= __item_methodcall_optkeys(id).keys.map{|k| k.to_s} + availables |= __item_keyonly_optkeys(id).keys.map{|k| k.to_s} + + keys = _symbolkey2str(keys) + + keys.delete_if{|k, v| !(availables.include?(k))} + end + + def itemconfigure(tagOrId, slot, value=None) + unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + __itemconfigure_core(tagOrId, slot, value) + else + if slot.kind_of?(Hash) + begin + __itemconfigure_core(tagOrId, slot) + rescue + slot = __check_available_itemconfigure_options(tagOrId, slot) + __itemconfigure_core(tagOrId, slot) unless slot.empty? + end + else + begin + __itemconfigure_core(tagOrId, slot, value) + rescue => e + begin + if __current_itemconfiginfo(tagOrId).has_key?(slot.to_s) + # not tag error & option is known -> error on known option + fail e + else + # not tag error & option is unknown + nil + end + rescue + fail e # tag error + end + end + end + end + self + end + + def __itemconfiginfo_core(tagOrId, slot = nil) + if TkComm::GET_CONFIGINFO_AS_ARRAY + if (slot && slot.to_s =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/) + fontkey = $2 + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{fontkey}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{fontkey}")), false, true) + conf[__item_configinfo_struct(tagid(tagOrId))[:key]] = + conf[__item_configinfo_struct(tagid(tagOrId))[:key]][1..-1] + if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \ + || conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 ) + fnt = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] + if TkFont.is_system_font?(fnt) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkNamedFont.new(fnt) + end + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = tagfontobj(tagid(tagOrId), fontkey) + elsif ( __item_configinfo_struct(tagid(tagOrId))[:alias] \ + && conf.size == __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][0] == ?- ) + conf[__item_configinfo_struct(tagid(tagOrId))[:alias]] = + conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][1..-1] + end + conf + else + if slot + slot = slot.to_s + + alias_name, real_name = __item_optkey_aliases(tagid(tagOrId)).find{|k, v| k.to_s == slot} + if real_name + slot = real_name.to_s + end + + case slot + when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/ + method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[slot] + conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true) + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + optval = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] + begin + val = method.call(tagOrId, optval) + rescue => e + warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG + val = optval + end + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = val + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + optval = conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] + begin + val = method.call(tagOrId, optval) + rescue => e + warn("Warning:: #{e.message} (when #{method}lcall(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG + val = optval + end + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = val + end + + when /^(#{__item_methodcall_optkeys(tagid(tagOrId)).keys.join('|')})$/ + method = _symbolkey2str(__item_methodcall_optkeys(tagid(tagOrId)))[slot] + return [slot, '', '', '', self.__send__(method, tagOrId)] + + when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/ + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true) + + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + number(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil + end + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + number(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil + end + end + + when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/ + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true) + + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + num_or_str(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + num_or_str(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + + when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/ + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true) + + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + bool(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil + end + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + bool(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil + end + end + + when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/ + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true) + + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + simplelist(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + simplelist(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + + when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/ + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true) + + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =~ /^[0-9]/ ) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + list(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =~ /^[0-9]/ ) + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + list(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + + when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/ + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true) + + when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/ + conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true) + + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + v = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] + if v.empty? + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil + else + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkVarAccess.new(v) + end + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + v = conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] + if v.empty? + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil + else + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = TkVarAccess.new(v) + end + end + + else + # conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))) + conf = tk_split_list(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), 0, false, true) + end + conf[__item_configinfo_struct(tagid(tagOrId))[:key]] = + conf[__item_configinfo_struct(tagid(tagOrId))[:key]][1..-1] + + if ( __item_configinfo_struct(tagid(tagOrId))[:alias] \ + && conf.size == __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][0] == ?- ) + conf[__item_configinfo_struct(tagid(tagOrId))[:alias]] = + conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][1..-1] + end + + conf + + else + # ret = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)))))).collect{|conflist| + # conf = tk_split_simplelist(conflist) + ret = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)))), false, false).collect{|conflist| + conf = tk_split_simplelist(conflist, false, true) + conf[__item_configinfo_struct(tagid(tagOrId))[:key]] = + conf[__item_configinfo_struct(tagid(tagOrId))[:key]][1..-1] + + optkey = conf[__item_configinfo_struct(tagid(tagOrId))[:key]] + case optkey + when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/ + method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[optkey] + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + optval = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] + begin + val = method(tagOrId, optval) + rescue => e + warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG + val = optval + end + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = val + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + optval = conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] + begin + val = method.call(tagOrId, optval) + rescue => e + warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG + val = optval + end + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = val + end + + when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/ + # do nothing + + when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/ + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + number(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil + end + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + number(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil + end + end + + when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/ + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + num_or_str(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + num_or_str(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + + when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/ + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + bool(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil + end + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + bool(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil + end + end + + when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/ + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + simplelist(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + simplelist(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + + when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/ + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =~ /^[0-9]/ ) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + list(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =~ /^[0-9]/ ) + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + list(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + + when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/ + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + v = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] + if v.empty? + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil + else + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkVarAccess.new(v) + end + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + v = conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] + if v.empty? + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil + else + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = TkVarAccess.new(v) + end + end + + else + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + if conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]].index('{') + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + tk_split_list(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + else + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + tk_tcl2ruby(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + end + if conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] + if conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]].index('{') + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + tk_split_list(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + else + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + tk_tcl2ruby(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + end + end + + if ( __item_configinfo_struct(tagid(tagOrId))[:alias] \ + && conf.size == __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][0] == ?- ) + conf[__item_configinfo_struct(tagid(tagOrId))[:alias]] = + conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][1..-1] + end + + conf + } + + __item_font_optkeys(tagid(tagOrId)).each{|optkey| + optkey = optkey.to_s + fontconf = ret.assoc(optkey) + if fontconf && fontconf.size > 2 + ret.delete_if{|inf| inf[0] =~ /^(|latin|ascii|kanji)#{optkey}$/} + fnt = fontconf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] + if TkFont.is_system_font?(fnt) + fontconf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkNamedFont.new(fnt) + end + fontconf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = tagfontobj(tagid(tagOrId), optkey) + ret.push(fontconf) + end + } + + __item_methodcall_optkeys(tagid(tagOrId)).each{|optkey, method| + ret << [optkey.to_s, '', '', '', self.__send__(method, tagOrId)] + } + + ret + end + end + + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY + if (slot && slot.to_s =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/) + fontkey = $2 + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{fontkey}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{fontkey}")), false, true) + conf[__item_configinfo_struct(tagid(tagOrId))[:key]] = + conf[__item_configinfo_struct(tagid(tagOrId))[:key]][1..-1] + + if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \ + || conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 ) + fnt = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] + if TkFont.is_system_font?(fnt) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkNamedFont.new(fnt) + end + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = tagfontobj(tagid(tagOrId), fontkey) + { conf.shift => conf } + elsif ( __item_configinfo_struct(tagid(tagOrId))[:alias] \ + && conf.size == __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 ) + if conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][0] == ?- + conf[__item_configinfo_struct(tagid(tagOrId))[:alias]] = + conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][1..-1] + end + { conf[0] => conf[1] } + else + { conf.shift => conf } + end + else + if slot + slot = slot.to_s + + alias_name, real_name = __item_optkey_aliases(tagid(tagOrId)).find{|k, v| k.to_s == slot} + if real_name + slot = real_name.to_s + end + + case slot + when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/ + method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[slot] + conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true) + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + optval = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] + begin + val = method.call(tagOrId, optval) + rescue => e + warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG + val = optval + end + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = val + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + optval = conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] + begin + val = method.call(tagOrId, optval) + rescue => e + warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG + val = optval + end + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = val + end + + when /^(#{__item_methodcall_optkeys(tagid(tagOrId)).keys.join('|')})$/ + method = _symbolkey2str(__item_methodcall_optkeys(tagid(tagOrId)))[slot] + return {slot => ['', '', '', self.__send__(method, tagOrId)]} + + when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/ + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true) + + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + number(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil + end + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + number(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil + end + end + + when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/ + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true) + + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + num_or_stre(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + num_or_str(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + + when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/ + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true) + + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + bool(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil + end + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + bool(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil + end + end + + when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/ + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true) + + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + simplelist(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + simplelist(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + + when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/ + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true) + + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =~ /^[0-9]/ ) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + list(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =~ /^[0-9]/ ) + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + list(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + + when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/ + # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))) + conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true) + + when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/ + conf = tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), false, true) + + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + v = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] + if v.empty? + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil + else + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkVarAccess.new(v) + end + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + v = conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] + if v.empty? + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil + else + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = TkVarAccess.new(v) + end + end + + else + # conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))) + conf = tk_split_list(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")), 0, false, true) + end + conf[__item_configinfo_struct(tagid(tagOrId))[:key]] = + conf[__item_configinfo_struct(tagid(tagOrId))[:key]][1..-1] + + if ( __item_configinfo_struct(tagid(tagOrId))[:alias] \ + && conf.size == __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 ) + if conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][0] == ?- + conf[__item_configinfo_struct(tagid(tagOrId))[:alias]] = + conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][1..-1] + end + { conf[0] => conf[1] } + else + { conf.shift => conf } + end + + else + ret = {} + # tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)))))).each{|conflist| + # conf = tk_split_simplelist(conflist) + tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)))), false, false).each{|conflist| + conf = tk_split_simplelist(conflist, false, true) + conf[__item_configinfo_struct(tagid(tagOrId))[:key]] = + conf[__item_configinfo_struct(tagid(tagOrId))[:key]][1..-1] + + optkey = conf[__item_configinfo_struct(tagid(tagOrId))[:key]] + case optkey + when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/ + method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[optkey] + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + optval = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] + begin + val = method.call(tagOrId, optval) + rescue => e + warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG + val = optval + end + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = val + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + optval = conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] + begin + val = method.call(tagOrId, optval) + rescue => e + warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG + val = optval + end + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = val + end + + when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/ + # do nothing + + when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/ + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + number(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil + end + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + number(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil + end + end + + when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/ + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + num_or_str(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + num_or_str(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + + when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/ + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + bool(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil + end + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + bool(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil + end + end + + when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/ + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + simplelist(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + simplelist(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + + when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/ + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =~ /^[0-9]/ ) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + list(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =~ /^[0-9]/ ) + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + list(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + + when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/ + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + v = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] + if v.empty? + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil + else + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkVarAccess.new(v) + end + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + v = conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] + if v.empty? + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil + else + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = TkVarAccess.new(v) + end + end + + else + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + if conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]].index('{') + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + tk_split_list(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + else + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + tk_tcl2ruby(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + end + if conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] + if conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]].index('{') + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + tk_split_list(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + else + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + tk_tcl2ruby(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + end + end + + if ( __item_configinfo_struct(tagid(tagOrId))[:alias] \ + && conf.size == __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 ) + if conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][0] == ?- + conf[__item_configinfo_struct(tagid(tagOrId))[:alias]] = + conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][1..-1] + end + ret[conf[0]] = conf[1] + else + ret[conf.shift] = conf + end + } + + __item_font_optkeys(tagid(tagOrId)).each{|optkey| + optkey = optkey.to_s + fontconf = ret[optkey] + if fontconf.kind_of?(Array) + ret.delete(optkey) + ret.delete('latin' << optkey) + ret.delete('ascii' << optkey) + ret.delete('kanji' << optkey) + fnt = fontconf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] + if TkFont.is_system_font?(fnt) + fontconf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkNamedFont.new(fnt) + end + fontconf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = tagfontobj(tagid(tagOrId), optkey) + ret[optkey] = fontconf + end + } + + __item_methodcall_optkeys(tagid(tagOrId)).each{|optkey, method| + ret[optkey.to_s] = ['', '', '', self.__send__(method, tagOrId)] + } + + ret + end + end + end + end + private :__itemconfiginfo_core + + def itemconfiginfo(tagOrId, slot = nil) + if slot && TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + begin + __itemconfiginfo_core(tagOrId, slot) + rescue => e + begin + __itemconfiginfo_core(tagOrId) + # not tag error -> option is unknown + Array.new(__item_configinfo_struct.values.max).unshift(slot.to_s) + rescue + fail e # tag error + end + end + else + __itemconfiginfo_core(tagOrId, slot) + end + end + + def __current_itemconfiginfo(tagOrId, slot = nil) + if TkComm::GET_CONFIGINFO_AS_ARRAY + if slot + org_slot = slot + begin + conf = __itemconfiginfo_core(tagOrId, slot) + if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \ + || conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 ) + return {conf[0] => conf[-1]} + end + slot = conf[__item_configinfo_struct(tagid(tagOrId))[:alias]] + end while(org_slot != slot) + fail RuntimeError, + "there is a configure alias loop about '#{org_slot}'" + else + ret = {} + __itemconfiginfo_core(tagOrId).each{|conf| + if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \ + || conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 ) + ret[conf[0]] = conf[-1] + end + } + + ret + end + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY + ret = {} + __itemconfiginfo_core(tagOrId, slot).each{|key, conf| + ret[key] = conf[-1] if conf.kind_of?(Array) + } + ret + end + end + + def current_itemconfiginfo(tagOrId, slot = nil) + __current_itemconfiginfo(tagOrId, slot) + end +end diff --git a/jni/ruby/ext/tk/lib/tk/itemfont.rb b/jni/ruby/ext/tk/lib/tk/itemfont.rb new file mode 100644 index 0000000..b5da4fa --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/itemfont.rb @@ -0,0 +1,327 @@ +# +# tk/itemfont.rb : control font of widget items +# +require 'tk' + +module TkItemFontOptkeys + def __item_font_optkeys(id) + # maybe need to override + ['font'] + end + private :__item_font_optkeys +end + +module TkTreatItemFont + include TkItemFontOptkeys + + def __item_pathname(id) + # maybe need to override + [self.path, id].join(';') + end + private :__item_pathname + + ################################################ + + def tagfont_configinfo(tagOrId, key = nil) + optkeys = __item_font_optkeys(tagid(tagOrId)) + if key && !optkeys.find{|opt| opt.to_s == key.to_s} + fail ArgumentError, "unknown font option name `#{key}'" + end + + win, tag = __item_pathname(tagid(tagOrId)).split(';') + + if key + pathname = [win, tag, key].join(';') + TkFont.used_on(pathname) || + TkFont.init_widget_font(pathname, + *(__item_confinfo_cmd(tagid(tagOrId)))) + elsif optkeys.size == 1 + pathname = [win, tag, optkeys[0]].join(';') + TkFont.used_on(pathname) || + TkFont.init_widget_font(pathname, + *(__item_confinfo_cmd(tagid(tagOrId)))) + else + fonts = {} + optkeys.each{|key| + key = key.to_s + pathname = [win, tag, key].join(';') + fonts[key] = + TkFont.used_on(pathname) || + TkFont.init_widget_font(pathname, + *(__item_confinfo_cmd(tagid(tagOrId)))) + } + fonts + end + end + alias tagfontobj tagfont_configinfo + + def tagfont_configure(tagOrId, slot) + pathname = __item_pathname(tagid(tagOrId)) + + slot = _symbolkey2str(slot) + + __item_font_optkeys(tagid(tagOrId)).each{|optkey| + optkey = optkey.to_s + l_optkey = 'latin' << optkey + a_optkey = 'ascii' << optkey + k_optkey = 'kanji' << optkey + + if slot.key?(optkey) + fnt = slot.delete(optkey) + if fnt.kind_of?(TkFont) + slot.delete(l_optkey) + slot.delete(a_optkey) + slot.delete(k_optkey) + + fnt.call_font_configure([pathname, optkey], + *(__item_config_cmd(tagid(tagOrId)) << {})) + next + else + if fnt + if (slot.key?(l_optkey) || + slot.key?(a_optkey) || + slot.key?(k_optkey)) + fnt = TkFont.new(fnt) + + lfnt = slot.delete(l_optkey) + lfnt = slot.delete(a_optkey) if slot.key?(a_optkey) + kfnt = slot.delete(k_optkey) + + fnt.latin_replace(lfnt) if lfnt + fnt.kanji_replace(kfnt) if kfnt + + fnt.call_font_configure([pathname, optkey], + *(__item_config_cmd(tagid(tagOrId)) << {})) + next + else + fnt = hash_kv(fnt) if fnt.kind_of?(Hash) + unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << fnt)) + else + begin + tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << fnt)) + rescue => e + # ignore + end + end + end + end + next + end + end + + lfnt = slot.delete(l_optkey) + lfnt = slot.delete(a_optkey) if slot.key?(a_optkey) + kfnt = slot.delete(k_optkey) + + if lfnt && kfnt + TkFont.new(lfnt, kfnt).call_font_configure([pathname, optkey], + *(__item_config_cmd(tagid(tagOrId)) << {})) + elsif lfnt + latintagfont_configure([lfnt, optkey]) + elsif kfnt + kanjitagfont_configure([kfnt, optkey]) + end + } + + # configure other (without font) options + tk_call(*(__item_config_cmd(tagid(tagOrId)).concat(hash_kv(slot)))) if slot != {} + self + end + + def latintagfont_configure(tagOrId, ltn, keys=nil) + if ltn.kind_of?(Array) + key = ltn[1] + ltn = ltn[0] + else + key = nil + end + + optkeys = __item_font_optkeys(tagid(tagOrId)) + if key && !optkeys.find{|opt| opt.to_s == key.to_s} + fail ArgumentError, "unknown font option name `#{key}'" + end + + win, tag = __item_pathname(tagid(tagOrId)).split(';') + + optkeys = [key] if key + + optkeys.each{|optkey| + optkey = optkey.to_s + + pathname = [win, tag, optkey].join(';') + + if (fobj = TkFont.used_on(pathname)) + fobj = TkFont.new(fobj) # create a new TkFont object + elsif Tk::JAPANIZED_TK + fobj = fontobj # create a new TkFont object + else + ltn = hash_kv(ltn) if ltn.kind_of?(Hash) + unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << ltn)) + else + begin + tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << ltn)) + rescue => e + # ignore + end + end + next + 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 + + fobj.call_font_configure([pathname, optkey], *(__item_config_cmd(tagid(tagOrId)) << {})) + } + self + end + alias asciitagfont_configure latintagfont_configure + + def kanjitagfont_configure(tagOrId, knj, keys=nil) + if knj.kind_of?(Array) + key = knj[1] + knj = knj[0] + else + key = nil + end + + optkeys = __item_font_optkeys(tagid(tagOrId)) + if key && !optkeys.find{|opt| opt.to_s == key.to_s} + fail ArgumentError, "unknown font option name `#{key}'" + end + + win, tag = __item_pathname(tagid(tagOrId)).split(';') + + optkeys = [key] if key + + optkeys.each{|optkey| + optkey = optkey.to_s + + pathname = [win, tag, optkey].join(';') + + if (fobj = TkFont.used_on(pathname)) + fobj = TkFont.new(fobj) # create a new TkFont object + elsif Tk::JAPANIZED_TK + fobj = fontobj # create a new TkFont object + else + knj = hash_kv(knj) if knj.kind_of?(Hash) + unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << knj)) + else + begin + tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << knj)) + rescue => e + # ignore + end + end + next + 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 + + fobj.call_font_configure([pathname, optkey], *(__item_config_cmd(tagid(tagOrId)) << {})) + } + self + end + + def tagfont_copy(tagOrId, win, wintag=nil, winkey=nil, targetkey=nil) + if wintag + if winkey + fnt = win.tagfontobj(wintag, winkey).dup + else + fnt = win.tagfontobj(wintag).dup + end + else + if winkey + fnt = win.fontobj(winkey).dup + else + fnt = win.fontobj.dup + end + end + + if targetkey + fnt.call_font_configure([__item_pathname(tagid(tagOrId)), targetkey], + *(__item_config_cmd(tagid(tagOrId)) << {})) + else + fnt.call_font_configure(__item_pathname(tagid(tagOrId)), + *(__item_config_cmd(tagid(tagOrId)) << {})) + end + self + end + + + def latintagfont_copy(tagOrId, win, wintag=nil, winkey=nil, targetkey=nil) + if targetkey + fontobj(targetkey).dup.call_font_configure([__item_pathname(tagid(tagOrId)), targetkey], + *(__item_config_cmd(tagid(tagOrId)) << {})) + else + fontobj.dup.call_font_configure(__item_pathname(tagid(tagOrId)), + *(__item_config_cmd(tagid(tagOrId)) << {})) + end + + if wintag + if winkey + fontobj.latin_replace(win.tagfontobj(wintag, winkey).latin_font_id) + else + fontobj.latin_replace(win.tagfontobj(wintag).latin_font_id) + end + else + if winkey + fontobj.latin_replace(win.fontobj(winkey).latin_font_id) + else + fontobj.latin_replace(win.fontobj.latin_font_id) + end + end + self + end + alias asciitagfont_copy latintagfont_copy + + def kanjifont_copy(tagOrId, win, wintag=nil, winkey=nil, targetkey=nil) + if targetkey + fontobj(targetkey).dup.call_font_configure([__item_pathname(tagid(tagOrId)), targetkey], + *(__item_config_cmd(tagid(tagOrId)) << {})) + else + fontobj.dup.call_font_configure(__item_pathname(tagid(tagOrId)), + *(__item_config_cmd(tagid(tagOrId)) << {})) + end + + if wintag + if winkey + fontobj.kanji_replace(win.tagfontobj(wintag, winkey).kanji_font_id) + else + fontobj.kanji_replace(win.tagfontobj(wintag).kanji_font_id) + end + else + if winkey + fontobj.kanji_replace(win.fontobj(winkey).kanji_font_id) + else + fontobj.kanji_replace(win.fontobj.kanji_font_id) + end + end + self + end +end diff --git a/jni/ruby/ext/tk/lib/tk/kinput.rb b/jni/ruby/ext/tk/lib/tk/kinput.rb new file mode 100644 index 0000000..b63f756 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/kinput.rb @@ -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(win, style=None) + tk_call('kinput_start', win, style) + end + def kinput_start(style=None) + TkKinput.start(self, style) + end + + def TkKinput.send_spot(win) + tk_call('kinput_send_spot', win) + end + def kinput_send_spot + TkKinput.send_spot(self) + end + + def TkKinput.input_start(win, keys=nil) + tk_call('kanjiInput', 'start', win, *hash_kv(keys)) + end + def kanji_input_start(keys=nil) + TkKinput.input_start(self, keys) + end + + def TkKinput.attribute_config(win, slot, value=None) + if slot.kind_of? Hash + tk_call('kanjiInput', 'attribute', win, *hash_kv(slot)) + else + tk_call('kanjiInput', 'attribute', win, "-#{slot}", value) + end + end + def kinput_attribute_config(slot, value=None) + TkKinput.attribute_config(self, slot, value) + end + + def TkKinput.attribute_info(win, slot=nil) + if slot + conf = tk_split_list(tk_call('kanjiInput', 'attribute', + win, "-#{slot}")) + conf[0] = conf[0][1..-1] + conf + else + tk_split_list(tk_call('kanjiInput', 'attribute', win)).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(win) + tk_call('kanjiInput', 'end', win) + end + def kanji_input_end + TkKinput.input_end(self) + end +end diff --git a/jni/ruby/ext/tk/lib/tk/label.rb b/jni/ruby/ext/tk/lib/tk/label.rb new file mode 100644 index 0000000..05e430e --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/label.rb @@ -0,0 +1,22 @@ +# +# tk/label.rb : treat label widget +# +require 'tk' + +class Tk::Label<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 +end + +#TkLabel = Tk::Label unless Object.const_defined? :TkLabel +#Tk.__set_toplevel_aliases__(:Tk, Tk::Label, :TkLabel) +Tk.__set_loaded_toplevel_aliases__('tk/label.rb', :Tk, Tk::Label, :TkLabel) diff --git a/jni/ruby/ext/tk/lib/tk/labelframe.rb b/jni/ruby/ext/tk/lib/tk/labelframe.rb new file mode 100644 index 0000000..6f679e5 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/labelframe.rb @@ -0,0 +1,31 @@ +# +# tk/labelframe.rb : treat labelframe widget +# +require 'tk' +require 'tk/frame' + +class Tk::LabelFrame<Tk::Frame + 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 + + def __val2ruby_optkeys # { key=>proc, ... } + super().update('labelwidget'=>proc{|v| window(v)}) + end + private :__val2ruby_optkeys +end + +Tk::Labelframe = Tk::LabelFrame +#TkLabelFrame = Tk::LabelFrame unless Object.const_defined? :TkLabelFrame +#TkLabelframe = Tk::Labelframe unless Object.const_defined? :TkLabelframe +#Tk.__set_toplevel_aliases__(:Tk, Tk::LabelFrame, :TkLabelFrame, :TkLabelframe) +Tk.__set_loaded_toplevel_aliases__('tk/labelframe.rb', :Tk, Tk::LabelFrame, + :TkLabelFrame, :TkLabelframe) diff --git a/jni/ruby/ext/tk/lib/tk/listbox.rb b/jni/ruby/ext/tk/lib/tk/listbox.rb new file mode 100644 index 0000000..6742b21 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/listbox.rb @@ -0,0 +1,284 @@ +# +# tk/listbox.rb : treat listbox widget +# +require 'tk' +require 'tk/itemconfig' +require 'tk/scrollable' +require 'tk/txtwin_abst' + +module TkListItemConfig + include TkItemConfigMethod + + def __item_listval_optkeys(id) + [] + end + private :__item_listval_optkeys +end + +class Tk::Listbox<TkTextWin + include TkListItemConfig + 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 __tkvariable_optkeys + super() << 'listvariable' + end + private :__tkvariable_optkeys + + def tagid(id) + #id.to_s + _get_eval_string(id) + end + + 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))) + tk_split_simplelist(tk_send_without_enc('get', first, last), false, true) + 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(idx) + tk_send_without_enc('index', idx).to_i + end + + def value + get('0', 'end') + end + + def value= (vals) + unless vals.kind_of?(Array) + fail ArgumentError, 'an Array is expected' + end + tk_send_without_enc('delete', '0', 'end') + tk_send_without_enc('insert', '0', + *(vals.collect{|v| _get_eval_enc_str(v)})) + vals + end + + def clear + tk_send_without_enc('delete', '0', 'end') + self + end + alias erase clear + +=begin + 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 +end + +#TkListbox = Tk::Listbox unless Object.const_defined? :TkListbox +#Tk.__set_toplevel_aliases__(:Tk, Tk::Listbox, :TkListbox) +Tk.__set_loaded_toplevel_aliases__('tk/listbox.rb', :Tk, Tk::Listbox, + :TkListbox) diff --git a/jni/ruby/ext/tk/lib/tk/macpkg.rb b/jni/ruby/ext/tk/lib/tk/macpkg.rb new file mode 100644 index 0000000..3ca7953 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/macpkg.rb @@ -0,0 +1,80 @@ +# +# 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 Tk::MacResource +end +#TkMacResource = Tk::MacResource +#Tk.__set_toplevel_aliases__(:Tk, Tk::MacResource, :TkMacResource) +Tk.__set_loaded_toplevel_aliases__('tk/macpkg.rb', :Tk, Tk::MacResource, + :TkMacResource) + +module Tk::MacResource + extend Tk + extend Tk::MacResource + + TkCommandNames = ['resource'.freeze].freeze + + PACKAGE_NAME = 'resource'.freeze + def self.package_name + PACKAGE_NAME + end + + 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 diff --git a/jni/ruby/ext/tk/lib/tk/menu.rb b/jni/ruby/ext/tk/lib/tk/menu.rb new file mode 100644 index 0000000..bcd2500 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/menu.rb @@ -0,0 +1,718 @@ +# +# tk/menu.rb : treat menu and menubutton +# +require 'tk' +require 'tk/itemconfig' +require 'tk/menuspec' + +module TkMenuEntryConfig + include TkItemConfigMethod + + def __item_cget_cmd(id) + [self.path, 'entrycget', id] + end + private :__item_cget_cmd + + def __item_config_cmd(id) + [self.path, 'entryconfigure', id] + end + private :__item_config_cmd + + def __item_strval_optkeys(id) + super(id) << 'selectcolor' + end + private :__item_strval_optkeys + + def __item_listval_optkeys(id) + [] + end + private :__item_listval_optkeys + + def __item_val2ruby_optkeys(id) # { key=>proc, ... } + super(id).update('menu'=>proc{|i, v| window(v)}) + end + private :__item_val2ruby_optkeys + + alias entrycget_tkstring itemcget_tkstring + alias entrycget itemcget + alias entrycget_strict itemcget_strict + alias entryconfigure itemconfigure + alias entryconfiginfo itemconfiginfo + alias current_entryconfiginfo current_itemconfiginfo + + private :itemcget_tkstring, :itemcget, :itemcget_strict + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo +end + +class Tk::Menu<TkWindow + include Wm + include TkMenuEntryConfig + extend TkMenuSpec + + 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 __strval_optkeys + super() << 'selectcolor' << 'title' + end + private :__strval_optkeys + + def __boolval_optkeys + super() << 'tearoff' + end + private :__boolval_optkeys + + def self.new_menuspec(menu_spec, parent = nil, tearoff = false, keys = nil) + if parent.kind_of?(Hash) + keys = _symbolkey2str(parent) + parent = keys.delete('parent') + tearoff = keys.delete('tearoff') + elsif tearoff.kind_of?(Hash) + keys = _symbolkey2str(tearoff) + tearoff = keys.delete('tearoff') + elsif keys + keys = _symbolkey2str(keys) + else + keys = {} + end + + widgetname = keys.delete('widgetname') + _create_menu(parent, menu_spec, widgetname, tearoff, keys) + end + + def tagid(id) + #id.to_s + _get_eval_string(id) + end + + 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 clone_menu(*args) + if args[0].kind_of?(TkWindow) + parent = args.shift + else + parent = self + end + + if args[0].kind_of?(String) || args[0].kind_of?(Symbol) # menu type + type = args.shift + else + type = None # 'normal' + end + + if args[0].kind_of?(Hash) + keys = _symbolkey2str(args.shift) + else + keys = {} + end + + parent = keys.delete('parent') if keys.has_key?('parent') + type = keys.delete('type') if keys.has_key?('type') + + if keys.empty? + Tk::MenuClone.new(self, parent, type) + else + Tk::MenuClone.new(self, parent, type, keys) + end + end + + def index(idx) + ret = tk_send_without_enc('index', _get_eval_enc_str(idx)) + (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 xposition(index) + number(tk_send_without_enc('xposition', _get_eval_enc_str(index))) + end + def yposition(index) + number(tk_send_without_enc('yposition', _get_eval_enc_str(index))) + end + +=begin + 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 +end + +#TkMenu = Tk::Menu unless Object.const_defined? :TkMenu +#Tk.__set_toplevel_aliases__(:Tk, Tk::Menu, :TkMenu) +Tk.__set_loaded_toplevel_aliases__('tk/menu.rb', :Tk, Tk::Menu, :TkMenu) + + +module Tk::Menu::TkInternalFunction; end +class << Tk::Menu::TkInternalFunction + # These methods calls internal functions of Tcl/Tk. + # So, They may not work on your Tcl/Tk. + def next_menu(menu, dir='next') + dir = dir.to_s + case dir + when 'next', 'forward', 'down' + dir = 'right' + when 'previous', 'backward', 'up' + dir = 'left' + end + + Tk.tk_call('::tk::MenuNextMenu', menu, dir) + end + + def next_entry(menu, delta) + # delta is increment value of entry index. + # For example, +1 denotes 'next entry' and -1 denotes 'previous entry'. + Tk.tk_call('::tk::MenuNextEntry', menu, delta) + end +end + +class Tk::MenuClone<Tk::Menu +=begin + 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 + def initialize(src_menu, *args) + widgetname = nil + + if args[0].kind_of?(TkWindow) # parent window + parent = args.shift + else + parent = src_menu + end + + if args[0].kind_of?(String) || args[0].kind_of?(Symbol) # menu type + type = args.shift + else + type = None # 'normal' + end + + if args[0].kind_of?(Hash) + keys = _symbolkey2str(args.shift) + parent = keys.delete('parent') if keys.has_key?('parent') + widgetname = keys.delete('widgetname') + type = keys.delete('type') if keys.has_key?('type') + else + keys = nil + end + + @src_menu = src_menu + @parent = parent + @type = type + install_win(@parent.path, widgetname) + tk_call_without_enc(@src_menu.path, 'clone', @path, @type) + configure(keys) if keys && !keys.empty? + end + + def source_menu + @src_menu + end +end +Tk::CloneMenu = Tk::MenuClone +#TkMenuClone = Tk::MenuClone unless Object.const_defined? :TkMenuClone +#TkCloneMenu = Tk::CloneMenu unless Object.const_defined? :TkCloneMenu +#Tk.__set_toplevel_aliases__(:Tk, Tk::MenuClone, :TkMenuClone, :TkCloneMenu) +Tk.__set_loaded_toplevel_aliases__('tk/menu.rb', :Tk, Tk::MenuClone, + :TkMenuClone, :TkCloneMenu) + +module Tk::SystemMenu + 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 +TkSystemMenu = Tk::SystemMenu + + +class Tk::SysMenu_Help<Tk::Menu + # for all platform + include Tk::SystemMenu + SYSMENU_NAME = 'help' +end +#TkSysMenu_Help = Tk::SysMenu_Help unless Object.const_defined? :TkSysMenu_Help +#Tk.__set_toplevel_aliases__(:Tk, Tk::SysMenu_Help, :TkSysMenu_Help) +Tk.__set_loaded_toplevel_aliases__('tk/menu.rb', :Tk, Tk::SysMenu_Help, + :TkSysMenu_Help) + + +class Tk::SysMenu_System<Tk::Menu + # for Windows + include Tk::SystemMenu + SYSMENU_NAME = 'system' +end +#TkSysMenu_System = Tk::SysMenu_System unless Object.const_defined? :TkSysMenu_System +#Tk.__set_toplevel_aliases__(:Tk, Tk::SysMenu_System, :TkSysMenu_System) +Tk.__set_loaded_toplevel_aliases__('tk/menu.rb', :Tk, Tk::SysMenu_System, + :TkSysMenu_System) + + +class Tk::SysMenu_Apple<Tk::Menu + # for Machintosh + include Tk::SystemMenu + SYSMENU_NAME = 'apple' +end +#TkSysMenu_Apple = Tk::SysMenu_Apple unless Object.const_defined? :TkSysMenu_Apple +#Tk.__set_toplevel_aliases__(:Tk, Tk::SysMenu_Apple, :TkSysMenu_Apple) +Tk.__set_loaded_toplevel_aliases__('tk/menu.rb', :Tk, Tk::SysMenu_Apple, + :TkSysMenu_Apple) + + +class Tk::Menubutton<Tk::Label + TkCommandNames = ['menubutton'.freeze].freeze + WidgetClassName = 'Menubutton'.freeze + WidgetClassNames[WidgetClassName] ||= self + def create_self(keys) + if keys and keys != None + unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + # tk_call_without_enc('menubutton', @path, *hash_kv(keys, true)) + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + begin + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + rescue + tk_call_without_enc(self.class::TkCommandNames[0], @path) + keys = __check_available_configure_options(keys) + unless keys.empty? + tk_call_without_enc('destroy', @path) rescue nil + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + end + end + end + else + # tk_call_without_enc('menubutton', @path) + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self + + def __boolval_optkeys + super() << 'indicatoron' + end + private :__boolval_optkeys + +end +Tk::MenuButton = Tk::Menubutton +#TkMenubutton = Tk::Menubutton unless Object.const_defined? :TkMenubutton +#TkMenuButton = Tk::MenuButton unless Object.const_defined? :TkMenuButton +#Tk.__set_toplevel_aliases__(:Tk, Tk::Menubutton, :TkMenubutton, :TkMenuButton) +Tk.__set_loaded_toplevel_aliases__('tk/menu.rb', :Tk, Tk::Menubutton, + :TkMenubutton, :TkMenuButton) + + +class Tk::OptionMenubutton<Tk::Menubutton + 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(*args) + # args :: [parent,] [var,] [value[, ...],] [keys] + # parent --> TkWindow or nil + # var --> TkVariable or nil + # keys --> Hash + # keys[:parent] or keys['parent'] --> parent + # keys[:variable] or keys['variable'] --> var + # keys[:values] or keys['values'] --> value, ... + # other Hash keys are menubutton options + keys = {} + keys = args.pop if args[-1].kind_of?(Hash) + keys = _symbolkey2str(keys) + + parent = nil + if !args.empty? && (args[0].kind_of?(TkWindow) || args[0] == nil) + keys.delete('parent') # ignore + parent = args.shift + else + parent = keys.delete('parent') + end + + @variable = nil + if !args.empty? && (args[0].kind_of?(TkVariable) || args[0] == nil) + keys.delete('variable') # ignore + @variable = args.shift + else + @variable = keys.delete('variable') + end + @variable = TkVariable.new unless @variable + + (args = keys.delete('values') || []) if args.empty? + if args.empty? + args << @variable.value + else + @variable.value = args[0] + end + + install_win(if parent then parent.path end) + @menu = OptionMenu.new(tk_call('tk_optionMenu', + @path, @variable.id, *args)) + + configure(keys) if keys + end + + def value + @variable.value + end + + def value=(val) + @variable.value = val + 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.insert(index, 'radiobutton', 'variable'=>@variable, + 'label'=>value, 'value'=>value) + self + end + def delete(index, last=None) + @menu.delete(index, last) + self + end + def xposition(index) + @menu.xposition(index) + end + def yposition(index) + @menu.yposition(index) + end + def menu + @menu + end + def menucget(key) + @menu.cget(key) + end + def menucget_strict(key) + @menu.cget_strict(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 entrycget_strict(index, key) + @menu.entrycget_strict(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 + +Tk::OptionMenuButton = Tk::OptionMenubutton +#TkOptionMenubutton = Tk::OptionMenubutton unless Object.const_defined? :TkOptionMenubutton +#TkOptionMenuButton = Tk::OptionMenuButton unless Object.const_defined? :TkOptionMenuButton +#Tk.__set_toplevel_aliases__(:Tk, Tk::OptionMenubutton, +# :TkOptionMenubutton, :TkOptionMenuButton) +Tk.__set_loaded_toplevel_aliases__('tk/menu.rb', :Tk, Tk::OptionMenubutton, + :TkOptionMenubutton, :TkOptionMenuButton) diff --git a/jni/ruby/ext/tk/lib/tk/menubar.rb b/jni/ruby/ext/tk/lib/tk/menubar.rb new file mode 100644 index 0000000..9d5571c --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/menubar.rb @@ -0,0 +1,137 @@ +# +# tk/menubar.rb +# +# Original version: +# 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') +# +# +# OR +# +# radio_var = TkVariable.new('y') +# menu_spec = [ +# [['File', 0], +# {:label=>'Open', :command=>proc{puts('Open clicked')}, :underline=>0}, +# '---', +# ['Check_A', TkVariable.new(true), 6], +# {:type=>'checkbutton', :label=>'Check_B', +# :variable=>TkVariable.new, :underline=>6}, +# '---', +# ['Radio_X', [radio_var, 'x'], 6], +# ['Radio_Y', [radio_var, 'y'], 6], +# ['Radio_Z', [radio_var, 'z'], 6], +# '---', +# ['cascade', [ +# ['sss', proc{p 'sss'}, 0], +# ['ttt', proc{p 'ttt'}, 0], +# ['uuu', proc{p 'uuu'}, 0], +# ['vvv', proc{p 'vvv'}, 0], +# ], 0], +# '---', +# ['Quit', proc{exit}, 0]], +# [['Edit', 0], +# ['Cut', proc{puts('Cut clicked')}, 2], +# ['Copy', proc{puts('Copy clicked')}, 0], +# ['Paste', proc{puts('Paste clicked')}, 0]] +# ] +# menubar = TkMenubar.new(nil, menu_spec, +# 'tearoff'=>false, +# 'foreground'=>'grey40', +# 'activeforeground'=>'red', +# 'font'=>'Helvetia 12 bold') +# menubar.pack('side'=>'top', 'fill'=>'x') + +# See tk/menuspce.rb about the format of the menu_spec + +# To use add_menu, configuration must be done by calling configure after +# adding all menus by add_menu, not by the constructor arguments. + +require 'tk' +require 'tk/frame' +require 'tk/composite' +require 'tk/menuspec' + +class TkMenubar<Tk::Frame + include TkComposite + include TkMenuSpec + + def initialize(parent = nil, spec = nil, options = {}) + if parent.kind_of? Hash + options = parent + parent = nil + spec = (options.has_key?('spec'))? options.delete('spec'): nil + end + + _symbolkey2str(options) + menuspec_opt = {} + TkMenuSpec::MENUSPEC_OPTKEYS.each{|key| + menuspec_opt[key] = options.delete(key) if options.has_key?(key) + } + + super(parent, options) + + @menus = [] + + spec.each{|info| add_menu(info, menuspec_opt)} if spec + + options.each{|key, value| configure(key, value)} if options + end + + def add_menu(menu_info, menuspec_opt={}) + mbtn, menu = _create_menubutton(@frame, menu_info, menuspec_opt) + + submenus = _get_cascade_menus(menu).flatten + + @menus.push([mbtn, menu]) + delegate('tearoff', menu, *submenus) + delegate('foreground', mbtn, menu, *submenus) + delegate('background', mbtn, menu, *submenus) + delegate('disabledforeground', mbtn, menu, *submenus) + delegate('activeforeground', mbtn, menu, *submenus) + delegate('activebackground', mbtn, menu, *submenus) + delegate('font', mbtn, menu, *submenus) + delegate('kanjifont', mbtn, menu, *submenus) + end + + def [](index) + return @menus[index] + end +end diff --git a/jni/ruby/ext/tk/lib/tk/menuspec.rb b/jni/ruby/ext/tk/lib/tk/menuspec.rb new file mode 100644 index 0000000..cb3597e --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/menuspec.rb @@ -0,0 +1,456 @@ +# +# tk/menuspec.rb +# Hidethoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# based on tkmenubar.rb : +# Copyright (C) 1998 maeda shugo. All rights reserved. +# This file can be distributed under the terms of the Ruby. +# +# The format of the menu_spec is: +# [ menubutton_info, menubutton_info, ... ] +# +# The format of the menubutton_info is: +# [ menubutton_info, entry_info, entry_info, ... ] +# +# And each format of *_info is: +# [ +# [text, underline, configs], # menu button/entry (*1) +# [label, command, underline, accelerator, configs], # command entry +# [label, TkVar_obj, underline, accelerator, configs], # checkbutton entry +# [label, [TkVar_obj, value], +# underline, accelerator, configs], # radiobutton entry +# [label, [[...menu_info...], [...menu_info...], ...], +# underline, accelerator, configs], # cascade entry (*2) +# '---', # separator +# ... +# ] +# +# A menu_info is an array of menu entries: +# [ entry_info, entry_info, ... ] +# +# +# underline, accelerator, and configs are optional pearameters. +# Hashes are OK instead of Arrays. Then the entry type ('command', +# 'checkbutton', 'radiobutton' or 'cascade') is given by 'type' key +# (e.g. :type=>'cascade'). When type is 'cascade', an array of menu_info +# is acceptable for 'menu' key (then, create sub-menu). +# +# If the value of underline is true instead of an integer, +# check whether the text/label string contains a '&' character. +# When includes, the first '&' is removed and its following character is +# converted the corresponding 'underline' option (first '&' is removed). +# Else if the value of underline is a String or a Regexp, +# use the result of label.index(underline) as the index of underline +# (don't remove matched substring). +# +# NOTE: (*1) +# If you want to make special menus (*.help for UNIX, *.system for Win, +# and *.apple for Mac), append 'menu_name'=>name (name is 'help' for UNIX, +# 'system' for Win, and 'apple' for Mac) option to the configs hash of +# menu button/entry information. +# +# NOTE: (*2) +# If you want to configure a cascade menu, add :menu_config=>{...configs..} +# to the configs of the cascade entry. + +module TkMenuSpec + extend TkMenuSpec + + MENUSPEC_OPTKEYS = [ 'layout_proc' ] + + def _create_menu(parent, menu_info, menu_name = nil, + tearoff = false, default_opts = nil) + if tearoff.kind_of?(Hash) + default_opts = tearoff + tearoff = false + end + + if menu_name.kind_of?(Hash) + default_opts = menu_name + menu_name = nil + tearoff = false + end + + if default_opts.kind_of?(Hash) + orig_opts = _symbolkey2str(default_opts) + else + orig_opts = {} + end + + tearoff = orig_opts.delete('tearoff') if orig_opts.key?('tearoff') + tearoff = false unless tearoff # nil --> false + + if menu_name + #menu = Tk::Menu.new(parent, :widgetname=>menu_name, :tearoff=>tearoff) + # --> use current TkMenu class + menu = TkMenu.new(parent, :widgetname=>menu_name, :tearoff=>tearoff) + else + #menu = Tk::Menu.new(parent, :tearoff=>tearoff) + # --> use current TkMenu class + menu = TkMenu.new(parent, :tearoff=>tearoff) + end + + for item_info in menu_info + if item_info.kind_of?(Hash) + options = orig_opts.dup + options.update(_symbolkey2str(item_info)) + item_type = (options.delete('type') || 'command').to_s + menu_name = options.delete('menu_name') + menu_opts = orig_opts.dup + menu_opts.update(_symbolkey2str(options.delete('menu_config') || {})) + if item_type == 'cascade' && options['menu'].kind_of?(Array) + # create cascade menu + submenu = _create_menu(menu, options['menu'], menu_name, + tearoff, menu_opts) + options['menu'] = submenu + end + case options['underline'] + when String, Regexp + if options['label'] && + (idx = options['label'].index(options['underline'])) + options['underline'] = idx + else + options['underline'] = -1 + end + when true + if options['label'] && (idx = options['label'].index('&')) + options['label'] = options['label'].dup + options['label'][idx] = '' + options['underline'] = idx + else + options['underline'] = -1 + end + end + menu.add(item_type, options) + + elsif item_info.kind_of?(Array) + options = orig_opts.dup + + options['label'] = item_info[0] if item_info[0] + + case item_info[1] + when TkVariable + # checkbutton + item_type = 'checkbutton' + options['variable'] = item_info[1] + options['onvalue'] = true + options['offvalue'] = false + + when Array + # radiobutton or cascade + if item_info[1][0].kind_of?(TkVariable) + # radiobutton + item_type = 'radiobutton' + options['variable'] = item_info[1][0] + options['value'] = item_info[1][1] if item_info[1][1] + + else + # cascade + item_type = 'cascade' + menu_opts = orig_opts.dup + if item_info[4] && item_info[4].kind_of?(Hash) + opts = _symbolkey2str(item_info[4]) + menu_name = opts.delete('menu_name') + menu_config = opts.delete('menu_config') || {} + menu_opts.update(_symbolkey2str(menu_config)) + end + submenu = _create_menu(menu, item_info[1], menu_name, + tearoff, menu_opts) + options['menu'] = submenu + end + + else + # command + item_type = 'command' + options['command'] = item_info[1] if item_info[1] + end + + options['underline'] = item_info[2] if item_info[2] + options['accelerator'] = item_info[3] if item_info[3] + if item_info[4] && item_info[4].kind_of?(Hash) + opts = _symbolkey2str(item_info[4]) + if item_type == 'cascade' + opts.delete('menu_name') + opts.delete('menu_config') + end + options.update(opts) + end + + case options['underline'] + when String, Regexp + if options['label'] && + (idx = options['label'].index(options['underline'])) + options['underline'] = idx + else + options['underline'] = -1 + end + when true + if options['label'] && (idx = options['label'].index('&')) + options['label'] = options['label'].dup + options['label'][idx] = '' + options['underline'] = idx + else + options['underline'] = -1 + end + end + + menu.add(item_type, options) + + elsif /^-+$/ =~ item_info + menu.add('separator') + + else + menu.add('command', 'label' => item_info) + end + end + + menu + end + private :_create_menu + + def _use_menubar?(parent) + use_menubar = false + if parent.kind_of?(Tk::Root) || parent.kind_of?(Tk::Toplevel) + true + elsif parent.current_configinfo.has_key?('menu') + true + else + false + end + end + private :_use_menubar? + + def _create_menu_for_menubar(parent) + #unless (mbar = parent.menu).kind_of?(TkMenu) + # --> use current TkMenu class + mbar = parent.menu + unless mbar.kind_of?(Tk::Menu) || mbar.kind_of?(TkMenu) + #mbar = Tk::Menu.new(parent, :tearoff=>false) + mbar = TkMenu.new(parent, :tearoff=>false) + parent.menu(mbar) + end + mbar + end + private :_create_menu_for_menubar + + def _create_menubutton(parent, menu_info, tearoff=false, default_opts = {}) + btn_info = menu_info[0] + + if tearoff.kind_of?(Hash) + default_opts = tearoff + tearoff = false + end + + if default_opts.kind_of?(Hash) + default_opts = _symbolkey2str(default_opts) + + if default_opts.has_key?('layout_proc') + layout_proc = default_opts.delete('layout_proc') + end + + _vertical_mbar_bind_proc = proc{|m, dir| + Tk::Menu::TkInternalFunction.next_menu(m, dir) rescue nil + # ignore error when the internal function doesn't exist + } + + case layout_proc + when :vertical, 'vertical', :vertical_left, 'vertical_left' + layout_proc = proc{|_parent, _mbtn| + _mbtn.direction :right + _mbtn.pack(:side=>:top, :fill=>:x) + + menu = _mbtn.menu + menu.bind('Tab', _vertical_mbar_bind_proc, :widget, 'forward') + menu.bind('Alt-Tab', _vertical_mbar_bind_proc, :widget, 'backward') + } + when :vertical_right, 'vertical_right' + layout_proc = proc{|_parent, _mbtn| + _mbtn.direction :left + _mbtn.pack(:side=>:top, :fill=>:x) + + menu = _mbtn.menu + menu.bind('Tab', _vertical_mbar_bind_proc, :widget, 'forward') + menu.bind('Alt-Tab', _vertical_mbar_bind_proc, :widget, 'backward') + } + when :horizontal, 'horizontal' + layout_proc = proc{|_parent, _mbtn| _mbtn.pack(:side=>:left)} + else + # do nothing + end + end + + keys = (default_opts)? default_opts.dup: {} + + tearoff = keys.delete('tearoff') if keys.key?('tearoff') + tearoff = false unless tearoff # nil --> false + + if _use_menubar?(parent) && ! layout_proc + # menubar by menu entries + mbar = _create_menu_for_menubar(parent) + + menu_name = nil + + if btn_info.kind_of?(Hash) + keys.update(_symbolkey2str(btn_info)) + menu_name = keys.delete('menu_name') + keys['label'] = keys.delete('text') || '' + + case keys['underline'] + when String, Regexp + if idx = keys['label'].index(keys['underline']) + keys['underline'] = idx + else + keys['underline'] = -1 + end + when true + if idx = keys['label'].index('&') + keys['label'] = keys['label'].dup + keys['label'][idx] = '' + keys['underline'] = idx + else + keys['underline'] = -1 + end + end + + elsif btn_info.kind_of?(Array) + keys['label'] = btn_info[0] if btn_info[0] + + case btn_info[1] + when Integer + keys['underline'] = btn_info[1] + when String, Regexp + if idx = keys['label'].index(btn_info[1]) + keys['underline'] = idx + else + keys['underline'] = -1 + end + when true + if idx = keys['label'].index('&') + keys['label'] = keys['label'].dup + keys['label'][idx] = '' + keys['underline'] = idx + else + keys['underline'] = -1 + end + end + + if btn_info[2]&&btn_info[2].kind_of?(Hash) + keys.update(_symbolkey2str(btn_info[2])) + menu_name = keys.delete('menu_name') + end + + else + keys = {:label=>btn_info} + end + + menu = _create_menu(mbar, menu_info[1..-1], menu_name, + tearoff, default_opts) + menu.tearoff(tearoff) + + keys['menu'] = menu + mbar.add('cascade', keys) + + [mbar, menu] + + else + # menubar by menubuttons + #mbtn = Tk::Menubutton.new(parent) + # --> use current TkMenubutton class + mbtn = TkMenubutton.new(parent) + + menu_name = nil + + if btn_info.kind_of?(Hash) + keys.update(_symbolkey2str(btn_info)) + menu_name = keys.delete('menu_name') + keys['text'] = keys.delete('label') || '' + case keys['underline'] + when String, Regexp + if idx = keys['text'].index(keys['underline']) + keys['underline'] = idx + else + keys['underline'] = -1 + end + when true + if idx = keys['text'].index('&') + keys['text'] = keys['text'].dup + keys['text'][idx] = '' + keys['underline'] = idx + else + keys['underline'] = -1 + end + end + mbtn.configure(keys) + + elsif btn_info.kind_of?(Array) + case btn_info[1] + when String, Regexp + if btn_info[0] && (idx = btn_info[0].index(btn_info[1])) + btn_info[1] = idx + else + btn_info[1] = -1 + end + when true + if btn_info[0] && (idx = btn_info[0].index('&')) + btn_info[0] = btn_info[0].dup + btn_info[0][idx] = '' + btn_info[1] = idx + else + btn_info[1] = -1 + end + end + mbtn.configure('text', btn_info[0]) if btn_info[0] + mbtn.configure('underline', btn_info[1]) if btn_info[1] + # mbtn.configure('accelerator', btn_info[2]) if btn_info[2] + if btn_info[2]&&btn_info[2].kind_of?(Hash) + keys.update(_symbolkey2str(btn_info[2])) + menu_name = keys.delete('menu_name') + mbtn.configure(keys) + end + + else + mbtn.configure('text', btn_info) + end + + menu = _create_menu(mbtn, menu_info[1..-1], menu_name, + tearoff, default_opts) + mbtn.menu(menu) + + if layout_proc.kind_of?(Proc) || layout_proc.kind_of?(Method) + # e.g. make a vertical menubar + # :layout_proc => proc{|parent, btn| btn.pack(:side=>:top, :fill=>:x)} + layout_proc.call(parent, mbtn) + else + mbtn.pack('side' => 'left') + end + + [mbtn, menu] + end + end + private :_create_menubutton + + def _create_menubar(parent, menu_spec, tearoff = false, opts = nil) + if tearoff.kind_of?(Hash) + opts = tearoff + tearoff = false + end + tearoff = false unless tearoff # nil --> false + menu_spec.each{|menu_info| + _create_menubutton(parent, menu_info, tearoff, opts) + } + parent + end + private :_create_menubar + + def _get_cascade_menus(menu) + menus = [] + (0..(menu.index('last'))).each{|idx| + if menu.menutype(idx) == 'cascade' + submenu = menu.entrycget(idx, 'menu') + menus << [submenu, _get_cascade_menus(submenu)] + end + } + menus + end + private :_get_cascade_menus +end diff --git a/jni/ruby/ext/tk/lib/tk/message.rb b/jni/ruby/ext/tk/lib/tk/message.rb new file mode 100644 index 0000000..5f73b30 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/message.rb @@ -0,0 +1,24 @@ +# +# tk/message.rb : treat message widget +# +require 'tk' +require 'tk/label' + +class Tk::Message<Tk::Label + 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 + +#TkMessage = Tk::Message unless Object.const_defined? :TkMessage +#Tk.__set_toplevel_aliases__(:Tk, Tk::Message, :TkMessage) +Tk.__set_loaded_toplevel_aliases__('tk/message.rb', :Tk, Tk::Message, + :TkMessage) diff --git a/jni/ruby/ext/tk/lib/tk/mngfocus.rb b/jni/ruby/ext/tk/lib/tk/mngfocus.rb new file mode 100644 index 0000000..a05fb94 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/mngfocus.rb @@ -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(win) + tk_tcl2ruby(tk_call('tk_focusNext', win)) + end + def focusNext + TkManageFocus.next(self) + end + + def TkManageFocus.prev(win) + tk_tcl2ruby(tk_call('tk_focusPrev', win)) + end + def focusPrev + TkManageFocus.prev(self) + end +end diff --git a/jni/ruby/ext/tk/lib/tk/msgcat.rb b/jni/ruby/ext/tk/lib/tk/msgcat.rb new file mode 100644 index 0000000..f2d0653 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/msgcat.rb @@ -0,0 +1,299 @@ +# +# 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') + + PACKAGE_NAME = 'msgcat'.freeze + def self.package_name + PACKAGE_NAME + end + + 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 = TkUtil.untrust(Hash.new{|hash,key| hash[key] = {}}) + + 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, *args) + src_str = sprintf(src_str, *args) unless args.empty? + 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 SystemExit + exit(0) + rescue Interrupt + exit!(1) + 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 >-------" + if TkCore::WITH_ENCODING + msg.force_encoding('utf-8') + else + msg.instance_variable_set(:@encoding, 'utf-8') + end + 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) + # trans_list + self.set_translation_list(loc, *args) + 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 + super(id, *args) +# 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 + if TkCore::WITH_ENCODING + eval(IO.read(file, :encoding=>"ASCII-8BIT")) + else + eval(IO.read(file)) + end + 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 + if TkCore::WITH_ENCODING + @namespace.eval(IO.read(file, :encoding=>"ASCII-8BIT")) + else + @namespace.eval(IO.read(file)) + end + 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') + if trans_str && trans_str != None + trans_str = Tk.UTF8_String(_toUTF8(trans_str, enc)) + Tk.UTF8_String(ip_eval_without_enc("::msgcat::mcset {#{locale}} {#{_get_eval_string(src_str, true)}} {#{trans_str}}")) + else + Tk.UTF8_String(ip_eval_without_enc("::msgcat::mcset {#{locale}} {#{_get_eval_string(src_str, true)}}")) + end + end + def set_translation(locale, src_str, trans_str=None, enc='utf-8') + if trans_str && trans_str != None + trans_str = Tk.UTF8_String(_toUTF8(trans_str, enc)) + Tk.UTF8_String(@namespace.eval{ + ip_eval_without_enc("::msgcat::mcset {#{locale}} {#{_get_eval_string(src_str, true)}} {#{trans_str}}") + }) + else + Tk.UTF8_String(@namespace.eval{ + ip_eval_without_enc("::msgcat::mcset {#{locale}} {#{_get_eval_string(src_str, true)}}") + }) + end + 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_String(_toUTF8(trans, enc)) + else + list << _get_eval_string(src, true) << '' + end + } + #number(tk_call_without_enc('::msgcat::mcmset', locale, list)) + number(ip_eval_without_enc("::msgcat::mcmset {#{locale}} {#{_get_eval_string(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) + ip_eval_without_enc("::msgcat::mcmset {#{locale}} {#{_get_eval_string(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 diff --git a/jni/ruby/ext/tk/lib/tk/namespace.rb b/jni/ruby/ext/tk/lib/tk/namespace.rb new file mode 100644 index 0000000..0119ba5 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/namespace.rb @@ -0,0 +1,546 @@ +# +# 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, TkUtil.untrust("00000")]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + Tk_NsCode_RetObjID_TBL = TkCore::INTERP.create_table + + TkCore::INTERP.init_ip_env{ + Tk_Namespace_ID_TBL.mutex.synchronize{ Tk_Namespace_ID_TBL.clear } + Tk_NsCode_RetObjID_TBL.mutex.synchronize{ Tk_NsCode_RetObjID_TBL.clear } + } + + def TkNamespace.id2obj(id) + Tk_Namespace_ID_TBL.mutex.synchronize{ + Tk_Namespace_ID_TBL[id]? Tk_Namespace_ID_TBL[id]: id + } + end + + ##################################### + + class Ensemble < TkObject + def __cget_cmd + ['namespace', 'ensemble', 'configure', self.path] + end + private :__cget_cmd + + def __config_cmd + ['namespace', 'ensemble', 'configure', self.path] + end + private :__config_cmd + + def __configinfo_struct + {:key=>0, :alias=>nil, :db_name=>nil, :db_class=>nil, + :default_value=>nil, :current_value=>2} + end + private :__configinfo_struct + + def __boolval_optkeys + ['prefixes'] + end + private :__boolval_optkeys + + def __listval_optkeys + ['map', 'subcommands', 'unknown'] + end + private :__listval_optkeys + + def self.exist?(ensemble) + bool(tk_call('namespace', 'ensemble', 'exists', ensemble)) + end + + def initialize(keys = {}) + @ensemble = @path = tk_call('namespace', 'ensemble', 'create', keys) + end + + def cget(slot) + if slot == :namespace || slot == 'namespace' + ns = super(slot) + Tk_Namespace_ID_TBL.mutex.synchronize{ + if TkNamespace::Tk_Namespace_ID_TBL.key?(ns) + TkNamespace::Tk_Namespace_ID_TBL[ns] + else + ns + end + } + else + super(slot) + end + end + def cget_strict(slot) + if slot == :namespace || slot == 'namespace' + ns = super(slot) + Tk_Namespace_ID_TBL.mutex.synchronize{ + if TkNamespace::Tk_Namespace_ID_TBL.key?(ns) + TkNamespace::Tk_Namespace_ID_TBL[ns] + else + ns + end + } + else + super(slot) + end + end + + def configinfo(slot = nil) + if slot + if slot == :namespace || slot == 'namespace' + val = super(slot) + Tk_Namespace_ID_TBL.mutex.synchronize{ + if TkNamespace::Tk_Namespace_ID_TBL.key?(val) + val = TkNamespace::Tk_Namespace_ID_TBL[val] + end + } + else + val = super(slot) + end + + if TkComm::GET_CONFIGINFO_AS_ARRAY + [slot.to_s, val] + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY + {slot.to_s => val} + end + + else + info = super() + + if TkComm::GET_CONFIGINFO_AS_ARRAY + Tk_Namespace_ID_TBL.mutex.synchronize{ + info.map!{|inf| + if inf[0] == 'namespace' && + TkNamespace::Tk_Namespace_ID_TBL.key?(inf[-1]) + [inf[0], TkNamespace::Tk_Namespace_ID_TBL[inf[-1]]] + else + inf + end + } + } + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY + val = info['namespace'] + Tk_Namespace_ID_TBL.mutex.synchronize{ + if TkNamespace::Tk_Namespace_ID_TBL.key?(val) + info['namespace'] = TkNamespace::Tk_Namespace_ID_TBL[val] + end + } + end + + info + end + end + + def exists? + bool(tk_call('namespace', 'ensemble', 'exists', @path)) + end + end + + ##################################### + + 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, true))? 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, true))? 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, true))? 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, use_obj_id = false) + @scope = scope + ' ' + @use_obj_id = use_obj_id + end + def path + @scope + end + def to_eval + @scope + end + def call(*args) + ret = TkCore::INTERP._eval_without_enc(@scope + array2tk_list(args)) + if @use_obj_id + ret = TkNamespace::Tk_NsCode_RetObjID_TBL.delete(ret.to_i) + end + ret + end + end + + ##################################### + + def install_cmd(cmd) + lst = tk_split_simplelist(super(cmd), false, false) + if lst[1] =~ /^::/ + lst[1] = @fullname + else + lst.insert(1, @fullname) + end + TkCore::INTERP._merge_tklist(*lst) + 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, true))? 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, true))? 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, true))? 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 + Tk_Namespace_ID.mutex.synchronize{ + # name = Tk_Namespace_ID.join('') + name = Tk_Namespace_ID.join(TkCore::INTERP._ip_id_) + 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.mutex.synchronize{ + 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 + Tk_Namespace_ID_TBL.mutex.synchronize{ + if Tk_Namespace_ID_TBL.key?(ns) + Tk_Namespace_ID_TBL[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 +=begin + 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 +=end + def code(script = Proc.new) + if script.kind_of?(String) + cmd = proc{|*args| + ret = ScopeArgs.new(@fullname,*args).instance_eval(script) + id = ret.object_id + TkNamespace::Tk_NsCode_RetObjID_TBL[id] = ret + id + } + elsif script.kind_of?(Proc) + cmd = proc{|*args| + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + obj = ScopeArgs.new(@fullname,*args) + ret = obj.instance_exec(obj, &script) + else + ret = ScopeArgs.new(@fullname,*args).instance_eval(&script) + end + id = ret.object_id + TkNamespace::Tk_NsCode_RetObjID_TBL[id] = ret + id + } + else + fail ArgumentError, "String or Proc is expected" + end + TkNamespace::NsCode.new(tk_call_without_enc('namespace', 'code', + _get_eval_string(cmd, false)), + true) + end + + def self.current_path + tk_call('namespace', 'current') + end + def current_path + @fullname + end + + def self.current + ns = self.current_path + Tk_Namespace_ID_TBL.mutex.synchronize{ + if Tk_Namespace_ID_TBL.key?(ns) + Tk_Namespace_ID_TBL[ns] + else + ns + end + } + end + def current_namespace + # ns_tk_call('namespace', 'current') + # @fullname + self + end + alias current current_namespace + + def self.delete(*ns_list) + tk_call('namespace', 'delete', *ns_list) + ns_list.each{|ns| + Tk_Namespace_ID_TBL.mutex.synchronize{ + if ns.kind_of?(TkNamespace) + Tk_Namespace_ID_TBL.delete(ns.path) + else + Tk_Namespace_ID_TBL.delete(ns.to_s) + end + } + } + 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(namespace).eval(cmd, *args) + end +=begin + 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]) + uninstall_cmd(_fromUTF8(TkCore::INTERP._split_tklist(_toUTF8(code_obj.path))[-1])) + tk_tcl2ruby(ret) + end +=end + def eval(cmd = Proc.new, *args) + code_obj = code(cmd) + ret = code_obj.call(*args) + uninstall_cmd(_fromUTF8(TkCore::INTERP._split_tklist(_toUTF8(code_obj.path))[-1])) + ret + end + + def self.exist?(ns) + bool(tk_call('namespace', 'exists', ns)) + end + def exist? + TkNamespece.exist?(@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.inscope(@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) + Tk_Namespace_ID_TBL.mutex.synchronize{ + if Tk_Namespace_ID_TBL.key?(ns) + Tk_Namespace_ID_TBL[ns] + else + ns + end + } + end + def parent + tk_call('namespace', 'parent', @fullname) + end + + def self.get_path + tk_call('namespace', 'path') + end + def self.set_path(*namespace_list) + tk_call('namespace', 'path', array2tk_list(namespace_list)) + end + def set_path + tk_call('namespace', 'path', @fullname) + end + + def self.qualifiers(str) + tk_call('namespace', 'qualifiers', str) + end + + def self.tail(str) + tk_call('namespace', 'tail', str) + end + + def self.upvar(namespace, *var_pairs) + tk_call('namespace', 'upvar', namespace, *(var_pairs.flatten)) + end + def upvar(*var_pairs) + TkNamespace.inscope(@fullname, *(var_pairs.flatten)) + end + + def self.get_unknown_handler + tk_tcl2ruby(tk_call('namespace', 'unknown')) + end + def self.set_unknown_handler(cmd = Proc.new) + tk_call('namespace', 'unknown', cmd) + 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 + +TkNamespace::Global = TkNamespace.new('::') diff --git a/jni/ruby/ext/tk/lib/tk/optiondb.rb b/jni/ruby/ext/tk/lib/tk/optiondb.rb new file mode 100644 index 0000000..0f3be30 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/optiondb.rb @@ -0,0 +1,377 @@ +# +# tk/optiondb.rb : treat option database +# +require 'tk' + +module TkOptionDB + include Tk + extend Tk + + TkCommandNames = ['option'.freeze].freeze + (CmdClassID = ['CMD_CLASS'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + 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 + alias read_file readfile + module_function :add, :clear, :get, :readfile, :read_file + + 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)? Tk.encoding : Tk.encoding_system) + + unless f_enc + f_enc = i_enc + end + + ent = [] + cline = '' + open(file, 'r') {|f| + while line = f.gets + #cline += line.chomp! + cline.concat(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 + + @@resource_proc_class.const_set(:CARRIER, '.'.freeze) + + @@resource_proc_class.instance_variable_set('@method_tbl', + TkCore::INTERP.create_table) + @@resource_proc_class.instance_variable_set('@add_method', false) + @@resource_proc_class.instance_variable_set('@safe_mode', 4) + + class << @@resource_proc_class + private :new + +=begin + CARRIER = '.'.freeze + METHOD_TBL = TkCore::INTERP.create_table + ADD_METHOD = false + SAFE_MODE = 4 +=end + +=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] + res_proc, proc_str = @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) + unless TkComm._callback_entry?(res_proc) + #if id == :new || !(self::METHOD_TBL.has_key?(id) || self::ADD_METHOD) + if id == :new || !(@method_tbl.has_key?(id) || @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) + eval("$SAFE = #{@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] + @method_tbl[id] = [res_proc, proc_source] + end + res_proc.call(*args) + end + + private :__check_proc_string__, :method_missing + end + @@resource_proc_class.freeze + +=begin + 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 +=end + def __create_new_class(klass, func, safe = 4, add = false, parent = nil) + if klass.kind_of?(TkWindow) + carrier = klass.path + CmdClassID.mutex.synchronize{ + klass = CmdClassID.join(TkCore::INTERP._ip_id_) + CmdClassID[1].succ! + } + parent = nil # ignore parent + else + klass = klass.to_s if klass.kind_of?(Symbol) + unless (?A..?Z) === klass[0] + fail ArgumentError, "bad string '#{klass}' for class name" + end + if parent == nil + install_win(nil) + elsif parent.kind_of?(TkWindow) + install_win(parent.path) + 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) + end + + unless func.kind_of?(Array) + fail ArgumentError, "method-list must be Array" + end + func_str = func.join(' ') + + if parent.kind_of?(Class) && parent <= @@resource_proc_class + cmd_klass = Class.new(parent) + else + cmd_klass = Class.new(TkOptionDB.module_eval('@@resource_proc_class')) + end + cmd_klass.const_set(:CARRIER, carrier.dup.freeze) + + cmd_klass.instance_variable_set('@method_tbl', TkCore::INTERP.create_table) + cmd_klass.instance_variable_set('@add_method', add) + cmd_klass.instance_variable_set('@safe_mode', safe) + func.each{|f| + cmd_klass.instance_variable_get('@method_tbl')[f.to_s.intern] = nil + } +=begin + cmd_klass.const_set(:METHOD_TBL, TkCore::INTERP.create_table) + cmd_klass.const_set(:ADD_METHOD, add) + cmd_klass.const_set(:SAFE_MODE, safe) + func.each{|f| cmd_klass::METHOD_TBL[f.to_s.intern] = nil } +=end + + cmd_klass + 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 + def __null_method(*args); nil; end + [ :class_eval, :name, :superclass, :clone, :dup, :autoload, :autoload?, + :ancestors, :const_defined?, :const_get, :const_set, :const_missing, + :class_variables, :constants, :included_modules, :instance_methods, + :method_defined?, :module_eval, :private_instance_methods, + :protected_instance_methods, :public_instance_methods, + :singleton_methods, :remove_const, :remove_method, :undef_method, + :to_s, :inspect, :display, :method, :methods, :respond_to?, + :instance_variable_get, :instance_variable_set, :instance_method, + :instance_eval, :instance_exec, :instance_variables, :kind_of?, :is_a?, + :private_methods, :protected_methods, :public_methods ].each{|m| + alias_method(m, :__null_method) + } + 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(){ + TkOptionDB.new_proc_class(klass, func, safe, add, self, &b) + } + end + module_function :new_proc_class_random +end +TkOption = TkOptionDB +TkResourceDB = TkOptionDB diff --git a/jni/ruby/ext/tk/lib/tk/optionobj.rb b/jni/ruby/ext/tk/lib/tk/optionobj.rb new file mode 100644 index 0000000..29b06da --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/optionobj.rb @@ -0,0 +1,212 @@ +# +# tk/optionobj.rb : control options for a group of widgets +# +# NOTE: If you want to use key-only option (no value), +# use Tk::None for the value of the key-only option. +# +# e.g. hash_kv({'aaa'=>1, 'bbb'=>Tk::None, 'ccc'=>3}) +# => ["-aaa", 1, "-bbb", "-ccc", 3] +# +require 'tk' + +module Tk + class OptionObj < Hash + include TkUtil + + def initialize(hash = nil) + super() + @observ = [] + update_without_notify(_symbolkey2str(hash)) if hash + end + + def observ_info + @observ.dup + end + + def observs + @observ.collect{|win| + if win.kind_of?(Array) + win[0] + else + win + end + } + end + + def _remove_win(win) + if win.kind_of?(Array) + widget, method = win + @observ.delete_if{|x| + if x.kind_of?(Array) + x[0] == widget + else + x == widget + end + } + else + @observ.delete_if{|x| + if x.kind_of?(Array) + x[0] == win + else + x == win + end + } + end + end + private :_remove_win + + def assign(*wins) + # win := + # widget #==> call widget.configure(hash) + # [widget] #==> call widget.configure(hash) + # [widget, nil, {src=>target, ... }] + # #==> call widget.configure(hash) + # with converting hash-key + # [widget, method] #==> call widget.method(hash) + # [widget, method, {src=>target, ... }] + # #==> call widget.method(hash) + # with converting hash-key + # [widget [receiver, method, arg, ... ]] + # #==> call receiver.method(arg, ... , hash) + # [widget [receiver, method, arg, ... ], {src=>target, ... }] + # #==> call receiver.method(arg, ... , hash) + # with onverting hash-key + # + # src := option_name_on_optobj + # + # target := + # nil #==> not use the src + # option_name_on_target_widget + # [ option_name_on_target_widget, ... ] + # #==> set all of them + # + wins.each{|win| + _remove_win(win) + @observ << win + notify(win) + } + self + end + + def unassign(*wins) + wins.each{|win| + _remove_win(win) + } + self + end + + def notify(target = nil) + if target + targets = [target] + elsif @observ.empty? + return self + else + targets = @observ.dup + end + + return self if empty? + + org_hash = _symbolkey2str(self) + + targets.each{|win| + widget = receiver = win + hash = org_hash + begin + if win.kind_of?(Array) + widget, method, conv_tbl = win + receiver = widget + + if conv_tbl + hash = {} + org_hash.each{|key, val| + key = conv_tbl[key] if conv_tbl.key?(key) + next unless key + if key.kind_of?(Array) + key.each{|k| hash[k] = val} + else + hash[key] = val + end + } + end + + if method.kind_of?(Array) + receiver, method, *args = method + receiver.__send__(method, *(args << hash)) + elsif method + widget.__send__(method, hash) + else + widget.configure(hash) + end + + else + widget.configure(self) + end + rescue => e + if ( ( widget.kind_of?(TkObject) \ + && widget.respond_to?('exist?') \ + && ! receiver.exist? ) \ + || ( receiver.kind_of?(TkObject) \ + && receiver.respond_to?('exist?') \ + && ! receiver.exist? ) ) + @observ.delete(win) + else + fail e + end + end + } + + self + end + alias apply notify + + def +(hash) + unless hash.kind_of?(Hash) + fail ArgumentError, "expect a Hash" + end + new_obj = self.dup + new_obj.update_without_notify(_symbolkey2str(hash)) + new_obj + end + + alias update_without_notify update + + def update(hash) + update_without_notify(_symbolkey2str(hash)) + notify + end + + def configure(key, value=nil) + if key.kind_of?(Hash) + update(key) + else + store(key,value) + end + end + + def [](key) + super(key.to_s) + end + alias cget [] + + def store(key, val) + key = key.to_s + super(key, val) + notify + end + def []=(key, val) + store(key,val) + end + + def replace(hash) + super(_symbolkey2str(hash)) + notify + end + + def default(opt) + fail RuntimeError, "unknown option `#{opt}'" + end + private :default + + undef :default= + end +end diff --git a/jni/ruby/ext/tk/lib/tk/pack.rb b/jni/ruby/ext/tk/lib/tk/pack.rb new file mode 100644 index 0000000..220a38e --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/pack.rb @@ -0,0 +1,107 @@ +# +# tk/pack.rb : control pack geometry manager +# +require 'tk' + +module TkPack + include Tk + extend Tk + + TkCommandNames = ['pack'.freeze].freeze + +=begin + 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 +=end + def configure(*args) + if args[-1].kind_of?(Hash) + opts = args.pop + else + opts = {} + end + fail ArgumentError, 'no widget is given' if args.empty? + params = [] + args.flatten(1).each{|win| params.push(_epath(win))} + opts.each{|k, v| + params.push("-#{k}") + params.push(_epath(v)) # have to use 'epath' (hash_kv() is unavailable) + } + tk_call_without_enc("pack", 'configure', *params) + end + alias pack configure + + 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, mode=None) + # master = master.epath if master.kind_of?(TkObject) + master = _epath(master) + if mode == None + bool(tk_call_without_enc('pack', 'propagate', master)) + else + tk_call_without_enc('pack', 'propagate', master, mode) + 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 :pack, :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 diff --git a/jni/ruby/ext/tk/lib/tk/package.rb b/jni/ruby/ext/tk/lib/tk/package.rb new file mode 100644 index 0000000..0c32973 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/package.rb @@ -0,0 +1,143 @@ +# +# 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 if_needed(pkg, ver, *arg, &b) + size = arg.size + + if size==0 && !b + # proc info + procedure(tk_call('package', 'ifneeded', pkg, ver)) + + elsif size==0 && b + # set proc + cmd = proc(&b) + tk_call('package', 'ifneeded', pkg, ver, cmd) + cmd + + elsif size==1 && !b + # set proc + cmd = arg[0] + if cmd + tk_call('package', 'ifneeded', pkg, ver, cmd) + cmd + else + # remove proc + tk_call('package', 'ifneeded', pkg, ver, '') + nil + end + + else + fail ArgumentError, 'too many arguments' + end + end + + def names + tk_split_simplelist(tk_call('package', 'names')) + end + + def provide(package, version=nil) + if version + tk_call('package', 'provide', package, version) + end + if (ret = tk_call('package', 'provide', package)) == '' + nil + else + ret + end + end + + def present(package, version=None) + begin + tk_call('package', 'present', package, version) + rescue => e + fail e.class, 'TkPackage ' << e.message + end + end + + def present_exact(package, version) + begin + tk_call('package', 'present', '-exact', package, version) + rescue => e + fail e.class, 'TkPackage ' << e.message + end + end + + def require(package, version=None) + begin + tk_call('package', 'require', package, version) + rescue => e + fail e.class, 'TkPackage ' << e.message + end + end + + def require_exact(package, version) + begin + tk_call('package', 'require', '-exact', package, version) + rescue => e + fail e.class, 'TkPackage ' << e.message + end + end + + def unknown_proc(*arg, &b) + size = arg.size + + if size==0 && !b + # proc info + procedure(tk_call('package', 'unknown')) + + elsif size==0 && b + # set proc + cmd = proc(&b) + tk_call('package', 'unknown', cmd) + cmd + + elsif size==1 && !b + # set proc + cmd = arg[0] + if cmd + tk_call('package', 'unknown', cmd) + cmd + else + # remove proc + tk_call('package', 'unknown', '') + nil + end + + else + fail ArgumentError, 'too many arguments' + end + 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 + + def prefer(setting = None) + tk_call('package', 'prefer', setting) + end +end diff --git a/jni/ruby/ext/tk/lib/tk/palette.rb b/jni/ruby/ext/tk/lib/tk/palette.rb new file mode 100644 index 0000000..9462bb0 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/palette.rb @@ -0,0 +1,55 @@ +# +# 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[0].to_a.flatten if args[0].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(win, colors) + if not colors.kind_of?(Hash) + fail "2nd arg need to be Hash" + end + + tk_call('global', "tkPalette") + colors.each{|key, value| + begin + if win.cget(key) == tk_call('set', "tkPalette(#{key})") + win[key] = colors[key] + end + rescue + # ignore + end + } + + TkWinfo.children(win).each{|w| TkPalette.recolorTree(w, colors)} + end + + def recolorTree(colors) + TkPalette.recolorTree(self, colors) + end +end diff --git a/jni/ruby/ext/tk/lib/tk/panedwindow.rb b/jni/ruby/ext/tk/lib/tk/panedwindow.rb new file mode 100644 index 0000000..0440780 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/panedwindow.rb @@ -0,0 +1,260 @@ +# +# tk/panedwindow.rb : treat panedwindow +# +require 'tk' + +class Tk::PanedWindow<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, x, y) + 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_strict(win, key) + # win = win.epath if win.kind_of?(TkObject) + win = _epath(win) + tk_tcl2ruby(tk_send_without_enc('panecget', win, "-#{key}")) + end + def panecget(win, key) + unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + panecget_strict(win, key) + else + begin + panecget_strict(win, key) + rescue => e + begin + if current_paneconfiginfo(win).has_key?(option.to_s) + # not tag error & option is known -> error on known option + fail e + else + # not tag error & option is unknown + nil + end + rescue + fail e # tag error + end + end + end + 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 = tk_split_list(tk_send_without_enc('paneconfigure', + win, "-#{key}"), + false, true) + conf[0] = conf[0][1..-1] + if conf[0] == 'hide' + conf[3] = bool(conf[3]) unless conf[3].empty? + conf[4] = bool(conf[4]) unless conf[4].empty? + end + conf + else + #tk_split_simplelist(tk_send_without_enc('paneconfigure', + # win)).collect{|conflist| + # conf = tk_split_simplelist(conflist) + tk_split_simplelist(tk_send_without_enc('paneconfigure', win), + false, false).collect{|conflist| + conf = tk_split_simplelist(conflist, false, true) + conf[0] = conf[0][1..-1] + if conf[3] + if conf[0] == 'hide' + conf[3] = bool(conf[3]) unless conf[3].empty? + elsif conf[3].index('{') + conf[3] = tk_split_list(conf[3]) + else + conf[3] = tk_tcl2ruby(conf[3]) + end + end + if conf[4] + if conf[0] == 'hide' + conf[4] = bool(conf[4]) unless conf[4].empty? + elsif 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}")) + conf = tk_split_list(tk_send_without_enc('paneconfigure', + win, "-#{key}"), + false, true) + key = conf.shift[1..-1] + if key == 'hide' + conf[2] = bool(conf[2]) unless conf[2].empty? + conf[3] = bool(conf[3]) unless conf[3].empty? + end + { key => conf } + else + ret = {} + #tk_split_simplelist(tk_send_without_enc('paneconfigure', + # win)).each{|conflist| + # conf = tk_split_simplelist(conflist) + tk_split_simplelist(tk_send_without_enc('paneconfigure', win), + false, false).each{|conflist| + conf = tk_split_simplelist(conflist, false, true) + key = conf.shift[1..-1] + if key + if key == 'hide' + conf[2] = bool(conf[2]) unless conf[2].empty? + elsif conf[2].index('{') + conf[2] = tk_split_list(conf[2]) + else + conf[2] = tk_tcl2ruby(conf[2]) + end + end + if conf[3] + if key == 'hide' + conf[3] = bool(conf[3]) unless conf[3].empty? + elsif 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 + +Tk::Panedwindow = Tk::PanedWindow +#TkPanedWindow = Tk::PanedWindow unless Object.const_defined? :TkPanedWindow +#TkPanedwindow = Tk::Panedwindow unless Object.const_defined? :TkPanedwindow +#Tk.__set_toplevel_aliases__(:Tk, Tk::PanedWindow, +# :TkPanedWindow, :TkPanedwindow) +Tk.__set_loaded_toplevel_aliases__('tk/panedwindow.rb', :Tk, Tk::PanedWindow, + :TkPanedWindow, :TkPanedwindow) diff --git a/jni/ruby/ext/tk/lib/tk/place.rb b/jni/ruby/ext/tk/lib/tk/place.rb new file mode 100644 index 0000000..109d866 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/place.rb @@ -0,0 +1,128 @@ +# +# 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 + alias place configure + + 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 = tk_split_simplelist(tk_call_without_enc('place', 'configure', + win, "-#{slot}") ) + conf[0] = conf[0][1..-1] + conf[1] = tk_tcl2ruby(conf[1]) + conf[2] = tk_tcl2ruby(conf[1]) + conf[3] = tk_tcl2ruby(conf[1]) + conf[4] = tk_tcl2ruby(conf[1]) + conf + else + tk_split_simplelist(tk_call_without_enc('place', 'configure', + win)).collect{|conflist| + #conf = list(conflist) + conf = simplelist(conflist).collect!{|inf| tk_tcl2ruby(inf)} + 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 = tk_split_simplelist(tk_call_without_enc('place', 'configure', + win, "-#{slot}") ) + # { conf[0][1..-1] => conf[1] } + { conf[0][1..-1] => tk_tcl2ruby(conf[4]) } + else + ret = {} + #tk_split_list(tk_call_without_enc('place','configure',win)).each{|conf| + tk_split_simplelist(tk_call_without_enc('place', 'configure', + win)).each{|conf_list| + #ret[conf[0][1..-1]] = conf[1] + conf = simplelist(conf_list) + ret[conf[0][1..-1]] = tk_tcl2ruby(conf[4]) + } + ret + end + 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)) + ilist = simplelist(tk_call_without_enc('place', 'info', win)) + info = {} + while key = ilist.shift + #info[key[1..-1]] = ilist.shift + info[key[1..-1]] = tk_tcl2ruby(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 :place, :configure, :configinfo, :current_configinfo + module_function :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 diff --git a/jni/ruby/ext/tk/lib/tk/radiobutton.rb b/jni/ruby/ext/tk/lib/tk/radiobutton.rb new file mode 100644 index 0000000..627df6d --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/radiobutton.rb @@ -0,0 +1,73 @@ +# +# tk/radiobutton.rb : treat radiobutton widget +# +require 'tk' +require 'tk/button' + +class Tk::RadioButton<Tk::Button + 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 __boolval_optkeys + super() << 'indicatoron' + end + private :__boolval_optkeys + + def __strval_optkeys + super() << 'selectcolor' + end + private :__strval_optkeys + + def __ruby2val_optkeys # { key=>proc, ... } + { + 'variable'=>proc{|v| tk_trace_variable(v)} # for backward compatibility + } + end + private :__ruby2val_optkeys + + + def deselect + tk_send_without_enc('deselect') + self + end + def select + tk_send_without_enc('select') + self + end + + def get_value + var = tk_send_without_enc('cget', '-variable') + if TkVariable::USE_TCLs_SET_VARIABLE_FUNCTIONS + _fromUTF8(INTERP._get_global_var(var)) + else + INTERP._eval(Kernel.format('global %s; set %s', var, var)) + end + end + + def set_value(val) + var = tk_send_without_enc('cget', '-variable') + if TkVariable::USE_TCLs_SET_VARIABLE_FUNCTIONS + _fromUTF8(INTERP._set_global_var(var, _get_eval_string(val, true))) + else + s = '"' + _get_eval_string(val).gsub(/[\[\]$"\\]/, '\\\\\&') + '"' + INTERP._eval(Kernel.format('global %s; set %s %s', var, var, s)) + end + end +end + +Tk::Radiobutton = Tk::RadioButton +#TkRadioButton = Tk::RadioButton unless Object.const_defined? :TkRadioButton +#TkRadiobutton = Tk::Radiobutton unless Object.const_defined? :TkRadiobutton +#Tk.__set_toplevel_aliases__(:Tk, Tk::RadioButton, +# :TkRadioButton, :TkRadiobutton) +Tk.__set_loaded_toplevel_aliases__('tk/radiobutton.rb', :Tk, Tk::RadioButton, + :TkRadioButton, :TkRadiobutton) diff --git a/jni/ruby/ext/tk/lib/tk/root.rb b/jni/ruby/ext/tk/lib/tk/root.rb new file mode 100644 index 0000000..b4f0bd1 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/root.rb @@ -0,0 +1,95 @@ +# +# tk/root.rb : treat root widget +# +require 'tk' +require 'tk/wm' +require 'tk/menuspec' + +class Tk::Root<TkWindow + include Wm + include TkMenuSpec + + def __methodcall_optkeys # { key=>method, ... } + TOPLEVEL_METHODCALL_OPTKEYS + end + private :__methodcall_optkeys + + def Root.new(keys=nil, &b) + unless TkCore::INTERP.tk_windows['.'] + TkCore::INTERP.tk_windows['.'] = + super(:without_creating=>true, :widgetname=>'.'){} + end + root = TkCore::INTERP.tk_windows['.'] + + keys = _symbolkey2str(keys) + + # wm commands + root.instance_eval{ + __methodcall_optkeys.each{|key, method| + value = keys.delete(key.to_s) + self.__send__(method, value) if value + } + } + + if keys # wm commands ( for backward comaptibility ) + keys.each{|k,v| + if v.kind_of? Array + root.__send__(k,*v) + else + root.__send__(k,v) + end + } + end + + if block_given? + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + root.instance_exec(root, &b) + else + root.instance_eval(&b) + end + end + root + end + + WidgetClassName = 'Tk'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def self.to_eval + # self::WidgetClassName + '.' + end + + def create_self + @path = '.' + end + private :create_self + + def path + "." + end + + def add_menu(menu_info, tearoff=false, opts=nil) + # See tk/menuspec.rb for menu_info. + # opts is a hash of default configs for all of cascade menus. + # Configs of menu_info can override it. + if tearoff.kind_of?(Hash) + opts = tearoff + tearoff = false + end + _create_menubutton(self, menu_info, tearoff, opts) + end + + def add_menubar(menu_spec, tearoff=false, opts=nil) + # See tk/menuspec.rb for menu_spec. + # opts is a hash of default configs for all of cascade menus. + # Configs of menu_spec can override it. + menu_spec.each{|info| add_menu(info, tearoff, opts)} + self.menu + end + + def Root.destroy + TkCore::INTERP._invoke('destroy', '.') + end +end + +TkRoot = Tk::Root unless Object.const_defined? :TkRoot diff --git a/jni/ruby/ext/tk/lib/tk/scale.rb b/jni/ruby/ext/tk/lib/tk/scale.rb new file mode 100644 index 0000000..0bdcead --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/scale.rb @@ -0,0 +1,112 @@ +# +# tk/scale.rb : treat scale widget +# +require 'tk' + +class Tk::Scale<TkWindow + TkCommandNames = ['scale'.freeze].freeze + WidgetClassName = 'Scale'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def create_self(keys) + if keys and keys != None + if keys.key?('command') && ! keys['command'].kind_of?(String) + cmd = keys.delete('command') + keys['command'] = proc{|val| cmd.call(val.to_f)} + end + unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + #tk_call_without_enc('scale', @path, *hash_kv(keys, true)) + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + begin + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + rescue + tk_call_without_enc(self.class::TkCommandNames[0], @path) + keys = __check_available_configure_options(keys) + unless keys.empty? + begin + tk_call_without_enc('destroy', @path) + rescue + # cannot destroy + configure(keys) + else + # re-create widget + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + end + end + end + end + else + #tk_call_without_enc('scale', @path) + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self + + def __strval_optkeys + super() << 'label' + end + private :__strval_optkeys + + 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 + +#TkScale = Tk::Scale unless Object.const_defined? :TkScale +#Tk.__set_toplevel_aliases__(:Tk, Tk::Scale, :TkScale) +Tk.__set_loaded_toplevel_aliases__('tk/scale.rb', :Tk, Tk::Scale, :TkScale) diff --git a/jni/ruby/ext/tk/lib/tk/scrollable.rb b/jni/ruby/ext/tk/lib/tk/scrollable.rb new file mode 100644 index 0000000..96959b7 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/scrollable.rb @@ -0,0 +1,82 @@ +# +# tk/scrollable.rb : module for scrollable widget +# +require 'tk' + +module Tk + module XScrollable + def xscrollcommand(cmd=Proc.new) + configure_cmd 'xscrollcommand', cmd + # Tk.update # avoid scrollbar trouble + self + 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 xview_moveto(*index) + xview('moveto', *index) + end + def xview_scroll(*index) + xview('scroll', *index) + end + + def xscrollbar(bar=nil) + if bar + @xscrollbar = bar + @xscrollbar.orient 'horizontal' + self.xscrollcommand {|*arg| @xscrollbar.set(*arg)} + @xscrollbar.command {|*arg| self.xview(*arg)} + Tk.update # avoid scrollbar trouble + end + @xscrollbar + end + end + + module YScrollable + def yscrollcommand(cmd=Proc.new) + configure_cmd 'yscrollcommand', cmd + # Tk.update # avoid scrollbar trouble + self + 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 yview_moveto(*index) + yview('moveto', *index) + end + def yview_scroll(*index) + yview('scroll', *index) + end + + def yscrollbar(bar=nil) + if bar + @yscrollbar = bar + @yscrollbar.orient 'vertical' + self.yscrollcommand {|*arg| @yscrollbar.set(*arg)} + @yscrollbar.command {|*arg| self.yview(*arg)} + Tk.update # avoid scrollbar trouble + end + @yscrollbar + end + end + + X_Scrollable = XScrollable + Y_Scrollable = YScrollable + + module Scrollable + include XScrollable + include YScrollable + end +end diff --git a/jni/ruby/ext/tk/lib/tk/scrollbar.rb b/jni/ruby/ext/tk/lib/tk/scrollbar.rb new file mode 100644 index 0000000..c0ac201 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/scrollbar.rb @@ -0,0 +1,183 @@ +# +# tk/scrollbar.rb : treat scrollbar widget +# +require 'tk' + +class Tk::Scrollbar<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 + unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + #tk_call_without_enc('scrollbar', @path, *hash_kv(keys, true)) + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + begin + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + rescue + tk_call_without_enc(self.class::TkCommandNames[0], @path) + keys = __check_available_configure_options(keys) + unless keys.empty? + begin + tk_call_without_enc('destroy', @path) + rescue + # cannot destroy + configure(keys) + else + # re-create widget + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + end + end + end + end + else + #tk_call_without_enc('scrollbar', @path) + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self + + def propagate_set(src_win, first, last) + self.set(first, last) + if self.orient == 'horizontal' + @assigned.each{|w| w.xview('moveto', first) if w != src_win} + else # 'vertical' + @assigned.each{|w| w.yview('moveto', first) if w != src_win} + end + end + + 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.propagate_set(w, first, last)} + else # 'vertical' + w.yscrollcommand proc{|first, last| self.propagate_set(w, first, last)} + end + } + Tk.update # avoid scrollbar trouble + 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 configure(*args) + ret = super(*args) + # Tk.update # avoid scrollbar trouble + ret + 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 + + def moveto(fraction) + tk_send_without_enc('moveto', fraction) + self + end + + def scroll(*args) + tk_send_without_enc('scroll', *args) + self + end + + def scroll_units(num) + scroll(num, 'units') + self + end + + def scroll_pages(num) + scroll(num, 'pages') + self + end +end + +#TkScrollbar = Tk::Scrollbar unless Object.const_defined? :TkScrollbar +#Tk.__set_toplevel_aliases__(:Tk, Tk::Scrollbar, :TkScrollbar) +Tk.__set_loaded_toplevel_aliases__('tk/scrollbar.rb', :Tk, Tk::Scrollbar, + :TkScrollbar) + + +class Tk::XScrollbar<Tk::Scrollbar + def create_self(keys) + keys = {} unless keys + keys['orient'] = 'horizontal' + super(keys) + end + private :create_self +end + +#TkXScrollbar = Tk::XScrollbar unless Object.const_defined? :TkXScrollbar +#Tk.__set_toplevel_aliases__(:Tk, Tk::XScrollbar, :TkXScrollbar) +Tk.__set_loaded_toplevel_aliases__('tk/scrollbar.rb', :Tk, Tk::XScrollbar, + :TkXScrollbar) + + +class Tk::YScrollbar<Tk::Scrollbar + def create_self(keys) + keys = {} unless keys + keys['orient'] = 'vertical' + super(keys) + end + private :create_self +end + +#TkYScrollbar = Tk::YScrollbar unless Object.const_defined? :TkYScrollbar +#Tk.__set_toplevel_aliases__(:Tk, Tk::YScrollbar, :TkYScrollbar) +Tk.__set_loaded_toplevel_aliases__('tk/scrollbar.rb', :Tk, Tk::YScrollbar, + :TkYScrollbar) diff --git a/jni/ruby/ext/tk/lib/tk/scrollbox.rb b/jni/ruby/ext/tk/lib/tk/scrollbox.rb new file mode 100644 index 0000000..d20742a --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/scrollbox.rb @@ -0,0 +1,39 @@ +# +# tk/scrollbox.rb - Tk Listbox with Scrollbar +# as an example of Composite Widget +# by Yukihiro Matsumoto <matz@netlab.co.jp> +# +require 'tk' +require 'tk/listbox' + +class TkScrollbox<Tk::Listbox + include TkComposite + def initialize_composite(keys=nil) + #list = Tk::Listbox.new(@frame) + # -> use current TkListbox class + list = TkListbox.new(@frame) + #scroll = Tk::Scrollbar.new(@frame) + # -> use current TkScrollbar class + scroll = TkScrollbar.new(@frame) + @path = list.path + +=begin + 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' +=end + list.yscrollbar(scroll) + list.pack('side'=>'left','fill'=>'both','expand'=>'yes') + 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 diff --git a/jni/ruby/ext/tk/lib/tk/selection.rb b/jni/ruby/ext/tk/lib/tk/selection.rb new file mode 100644 index 0000000..ba0a6f4 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/selection.rb @@ -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 diff --git a/jni/ruby/ext/tk/lib/tk/spinbox.rb b/jni/ruby/ext/tk/lib/tk/spinbox.rb new file mode 100644 index 0000000..f2917d6 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/spinbox.rb @@ -0,0 +1,144 @@ +# +# tk/spinbox.rb - Tk spinbox classes +# by Yukihiro Matsumoto <matz@caelum.co.jp> +# +require 'tk' +require 'tk/entry' + +class Tk::Spinbox<Tk::Entry + TkCommandNames = ['spinbox'.freeze].freeze + WidgetClassName = 'Spinbox'.freeze + WidgetClassNames[WidgetClassName] ||= self + + class SpinCommand < TkValidateCommand + class ValidateArgs < TkUtil::CallbackSubst + KEY_TBL = [ + [ ?d, ?s, :direction ], + [ ?s, ?e, :current ], + [ ?W, ?w, :widget ], + nil + ] + + PROC_TBL = [ + [ ?s, TkComm.method(:string) ], + [ ?w, TkComm.method(:window) ], + + [ ?e, proc{|val| + #enc = Tk.encoding + enc = ((Tk.encoding)? Tk.encoding : Tk.encoding_system) + if enc + Tk.fromUTF8(TkComm::string(val), enc) + else + TkComm::string(val) + end + } + ], + + nil + ] + +=begin + # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) + KEY_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) + end + inf + } + + PROC_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + end + inf + } +=end + + _setup_subst_table(KEY_TBL, PROC_TBL); + + def self.ret_val(val) + (val)? '1': '0' + end + end + + def self._config_keys + ['command'] + end + end + + def __validation_class_list + super() << SpinCommand + end + + Tk::ValidateConfigure.__def_validcmd(binding, SpinCommand) + + #def create_self(keys) + # tk_call_without_enc('spinbox', @path) + # if keys and keys != None + # configure(keys) + # end + #end + #private :create_self + + def __boolval_optkeys + super() << 'wrap' + end + private :__boolval_optkeys + + def __strval_optkeys + super() << 'buttonbackground' << 'format' + end + private :__strval_optkeys + + def __listval_optkeys + super() << 'values' + end + private :__listval_optkeys + + def identify(x, y) + tk_send_without_enc('identify', x, y) + end + + def invoke(elem) + tk_send_without_enc('invoke', elem) + self + end + + def spinup + begin + tk_send_without_enc('invoke', 'buttonup') + rescue RuntimeError => e + # old version of element? + begin + tk_send_without_enc('invoke', 'spinup') + rescue + fail e + end + end + self + end + + def spindown + begin + tk_send_without_enc('invoke', 'buttondown') + rescue RuntimeError => e + # old version of element? + begin + tk_send_without_enc('invoke', 'spinup') + rescue + fail e + end + end + self + end + + def set(str) + _fromUTF8(tk_send_without_enc('set', _get_eval_enc_str(str))) + end +end + +#TkSpinbox = Tk::Spinbox unless Object.const_defined? :TkSpinbox +#Tk.__set_toplevel_aliases__(:Tk, Tk::Spinbox, :TkSpinbox) +Tk.__set_loaded_toplevel_aliases__('tk/spinbox.rb', :Tk, Tk::Spinbox, + :TkSpinbox) diff --git a/jni/ruby/ext/tk/lib/tk/tagfont.rb b/jni/ruby/ext/tk/lib/tk/tagfont.rb new file mode 100644 index 0000000..a180739 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/tagfont.rb @@ -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(win, wintag=nil) + @parent.tagfont_copy(@id, win, wintag) + self + end + + def latinfont_copy(win, wintag=nil) + @parent.latintagfont_copy(@id, win, wintag) + self + end + alias asciifont_copy latinfont_copy + + def kanjifont_copy(win, wintag=nil) + @parent.kanjitagfont_copy(@id, win, wintag) + self + end +end diff --git a/jni/ruby/ext/tk/lib/tk/text.rb b/jni/ruby/ext/tk/lib/tk/text.rb new file mode 100644 index 0000000..c18b384 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/text.rb @@ -0,0 +1,1604 @@ +# +# tk/text.rb - Tk text classes +# by Yukihiro Matsumoto <matz@caelum.co.jp> +require 'tk' +require 'tk/itemfont' +require 'tk/itemconfig' +require 'tk/scrollable' +require 'tk/txtwin_abst' + +module TkTextTagConfig + include TkTreatItemFont + include TkItemConfigMethod + + def __item_cget_cmd(id) # id := [ type, tagOrId ] + [self.path, id[0], 'cget', id[1]] + end + private :__item_cget_cmd + + def __item_config_cmd(id) # id := [ type, tagOrId ] + [self.path, id[0], 'configure', id[1]] + end + private :__item_config_cmd + + def __item_pathname(id) + if id.kind_of?(Array) + id = tagid(id[1]) + end + [self.path, id].join(';') + end + private :__item_pathname + + def tag_cget_tkstring(tagOrId, option) + itemcget_tkstring(['tag', tagOrId], option) + end + def tag_cget(tagOrId, option) + itemcget(['tag', tagOrId], option) + end + def tag_cget_strict(tagOrId, option) + itemcget_strict(['tag', tagOrId], option) + end + def tag_configure(tagOrId, slot, value=None) + itemconfigure(['tag', tagOrId], slot, value) + end + def tag_configinfo(tagOrId, slot=nil) + itemconfiginfo(['tag', tagOrId], slot) + end + def current_tag_configinfo(tagOrId, slot=nil) + current_itemconfiginfo(['tag', tagOrId], slot) + end + + def window_cget_tkstring(tagOrId, option) + itemcget_tkstring(['window', tagOrId], option) + end + def window_cget(tagOrId, option) + itemcget(['window', tagOrId], option) + end + def window_cget_strict(tagOrId, option) + itemcget_strict(['window', tagOrId], option) + end + def window_configure(tagOrId, slot, value=None) + itemconfigure(['window', tagOrId], slot, value) + end + def window_configinfo(tagOrId, slot=nil) + itemconfiginfo(['window', tagOrId], slot) + end + def current_window_configinfo(tagOrId, slot=nil) + current_itemconfiginfo(['window', tagOrId], slot) + end + + private :itemcget_tkstring, :itemcget, :itemcget_strict + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo +end + +class Tk::Text<TkTextWin + ItemConfCMD = ['tag'.freeze, 'configure'.freeze].freeze + #include TkTreatTextTagFont + include TkTextTagConfig + include Scrollable + + ####################################### + + module IndexModMethods + def +(mod) + return chars(mod) if mod.kind_of?(Numeric) + + mod = mod.to_s + if mod =~ /^\s*[+-]?\d/ + Tk::Text::IndexString.new(String.new(id) << ' + ' << mod) + else + Tk::Text::IndexString.new(String.new(id) << ' ' << mod) + end + end + + def -(mod) + return chars(-mod) if mod.kind_of?(Numeric) + + mod = mod.to_s + if mod =~ /^\s*[+-]?\d/ + Tk::Text::IndexString.new(String.new(id) << ' - ' << mod) + elsif mod =~ /^\s*[-]\s+(\d.*)$/ + Tk::Text::IndexString.new(String.new(id) << ' - -' << $1) + else + Tk::Text::IndexString.new(String.new(id) << ' ' << mod) + end + end + + def chars(mod) + fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer) + if mod < 0 + Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' chars') + else + Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' chars') + end + end + alias char chars + + def display_chars(mod) + # Tk8.5 feature + fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer) + if mod < 0 + Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display chars') + else + Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display chars') + end + end + alias display_char display_chars + + def any_chars(mod) + # Tk8.5 feature + fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer) + if mod < 0 + Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any chars') + else + Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any chars') + end + end + alias any_char any_chars + + def indices(mod) + # Tk8.5 feature + fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer) + if mod < 0 + Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' indices') + else + Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' indices') + end + end + + def display_indices(mod) + # Tk8.5 feature + fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer) + if mod < 0 + Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display indices') + else + Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display indices') + end + end + + def any_indices(mod) + # Tk8.5 feature + fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer) + if mod < 0 + Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any indices') + else + Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any indices') + end + end + + def lines(mod) + fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer) + if mod < 0 + Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' lines') + else + Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' lines') + end + end + alias line lines + + def display_lines(mod) + # Tk8.5 feature + fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer) + if mod < 0 + Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display_lines') + else + Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display lines') + end + end + alias display_line display_lines + + def any_lines(mod) + # Tk8.5 feature + fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer) + if mod < 0 + Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any_lines') + else + Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any lines') + end + end + alias any_line any_lines + + def linestart + Tk::Text::IndexString.new(String.new(id) << ' linestart') + end + def lineend + Tk::Text::IndexString.new(String.new(id) << ' lineend') + end + + def display_linestart + # Tk8.5 feature + Tk::Text::IndexString.new(String.new(id) << ' display linestart') + end + def display_lineend + # Tk8.5 feature + Tk::Text::IndexString.new(String.new(id) << ' display lineend') + end + + def wordstart + Tk::Text::IndexString.new(String.new(id) << ' wordstart') + end + def wordend + Tk::Text::IndexString.new(String.new(id) << ' wordend') + end + + def display_wordstart + # Tk8.5 feature + Tk::Text::IndexString.new(String.new(id) << ' display wordstart') + end + def display_wordend + # Tk8.5 feature + Tk::Text::IndexString.new(String.new(id) << ' display wordend') + end + end + + class IndexString < String + include IndexModMethods + + def self.at(x,y) + self.new("@#{x},#{y}") + end + + def self.new(str) + if str.kind_of?(String) + super(str) + elsif str.kind_of?(Symbol) + super(str.to_s) + else + str + end + end + + def id + self + end + end + + ####################################### + + TkCommandNames = ['text'.freeze].freeze + WidgetClassName = 'Text'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def self.new(*args, &block) + obj = super(*args){} + obj.init_instance_variable + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + obj.instance_exec(obj, &block) if defined? yield + else + obj.instance_eval(&block) if defined? yield + end + obj + end + + def init_instance_variable + @cmdtbl = [] + @tags = {} + end + + def __destroy_hook__ + TkTextTag::TTagID_TBL.mutex.synchronize{ + TkTextTag::TTagID_TBL.delete(@path) + } + TkTextTag::TMarkID_TBL.mutex.synchronize{ + TkTextMark::TMarkID_TBL.delete(@path) + } + end + + def create_self(keys) + #if keys and keys != None + # #tk_call_without_enc('text', @path, *hash_kv(keys, true)) + # tk_call_without_enc(self.class::TkCommandNames[0], @path, + # *hash_kv(keys, true)) + #else + # #tk_call_without_enc('text', @path) + # tk_call_without_enc(self.class::TkCommandNames[0], @path) + #end + super(keys) + init_instance_variable + end + private :create_self + + def __strval_optkeys + super() << 'inactiveseletcionbackground' + end + private :__strval_optkeys + + def self.at(x, y) + Tk::Text::IndexString.at(x, y) + end + + def at(x, y) + Tk::Text::IndexString.at(x, y) + end + + def index(idx) + Tk::Text::IndexString.new(tk_send_without_enc('index', + _get_eval_enc_str(idx))) + end + + def get_displaychars(*index) + # Tk8.5 feature + get('-displaychars', *index) + end + + def value + _fromUTF8(tk_send_without_enc('get', "1.0", "end - 1 char")) + end + + def value= (val) + tk_send_without_enc('delete', "1.0", 'end') + tk_send_without_enc('insert', "1.0", _get_eval_enc_str(val)) + val + end + + def clear + tk_send_without_enc('delete', "1.0", 'end') + self + end + alias erase clear + + def _addcmd(cmd) + @cmdtbl.push cmd + end + + def _addtag(name, obj) + @tags[name] = obj + end + + def tagid(tag) + if tag.kind_of?(TkTextTag) \ + || tag.kind_of?(TkTextMark) \ + || tag.kind_of?(TkTextImage) \ + || tag.kind_of?(TkTextWindow) + tag.id + else + tag # maybe an Array of configure parameters + end + end + private :tagid + + def tagid2obj(tagid) + if @tags[tagid] + @tags[tagid] + else + tagid + end + end + + def tag_names(index=None) + #tk_split_simplelist(_fromUTF8(tk_send_without_enc('tag', 'names', _get_eval_enc_str(index)))).collect{|elt| + tk_split_simplelist(tk_send_without_enc('tag', 'names', _get_eval_enc_str(index)), false, true).collect{|elt| + tagid2obj(elt) + } + end + + def mark_names + #tk_split_simplelist(_fromUTF8(tk_send_without_enc('mark', 'names'))).collect{|elt| + tk_split_simplelist(tk_send_without_enc('mark', 'names'), false, true).collect{|elt| + tagid2obj(elt) + } + end + + def mark_gravity(mark, direction=nil) + if direction + tk_send_without_enc('mark', 'gravity', + _get_eval_enc_str(mark), direction) + self + else + tk_send_without_enc('mark', 'gravity', _get_eval_enc_str(mark)) + end + end + + def mark_set(mark, index) + tk_send_without_enc('mark', 'set', _get_eval_enc_str(mark), + _get_eval_enc_str(index)) + self + end + alias set_mark mark_set + + def mark_unset(*marks) + tk_send_without_enc('mark', 'unset', + *(marks.collect{|mark| _get_eval_enc_str(mark)})) + self + end + alias unset_mark mark_unset + + def mark_next(index) + tagid2obj(_fromUTF8(tk_send_without_enc('mark', 'next', + _get_eval_enc_str(index)))) + end + alias next_mark mark_next + + def mark_previous(index) + tagid2obj(_fromUTF8(tk_send_without_enc('mark', 'previous', + _get_eval_enc_str(index)))) + end + alias previous_mark mark_previous + + def image_cget_strict(index, slot) + case slot.to_s + when 'text', 'label', 'show', 'data', 'file' + _fromUTF8(tk_send_without_enc('image', 'cget', + _get_eval_enc_str(index), "-#{slot}")) + else + tk_tcl2ruby(_fromUTF8(tk_send_without_enc('image', 'cget', + _get_eval_enc_str(index), + "-#{slot}"))) + end + end + + def image_cget(index, slot) + unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + image_cget_strict(index, slot) + else + begin + image_cget_strict(index, slot) + rescue => e + begin + if current_image_configinfo(index).has_key?(slot.to_s) + # not tag error & option is known -> error on known option + fail e + else + # not tag error & option is unknown + nil + end + rescue + fail e # tag error + end + end + end + end + + def image_configure(index, slot, value=None) + if slot.kind_of?(Hash) + _fromUTF8(tk_send_without_enc('image', 'configure', + _get_eval_enc_str(index), + *hash_kv(slot, true))) + else + _fromUTF8(tk_send_without_enc('image', 'configure', + _get_eval_enc_str(index), + "-#{slot}", + _get_eval_enc_str(value))) + end + self + end + + def image_configinfo(index, slot = nil) + if TkComm::GET_CONFIGINFO_AS_ARRAY + if slot + case slot.to_s + when 'text', 'label', 'show', 'data', 'file' + #conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"))) + conf = tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), false, true) + else + #conf = tk_split_list(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"))) + conf = tk_split_list(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), 0, false, true) + end + conf[0] = conf[0][1..-1] + conf + else + # tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)))).collect{|conflist| + # conf = tk_split_simplelist(conflist) + tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)), false, false).collect{|conflist| + conf = tk_split_simplelist(conflist, false, true) + conf[0] = conf[0][1..-1] + case conf[0] + when 'text', 'label', 'show', 'data', 'file' + 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 + } + end + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY + if slot + case slot.to_s + when 'text', 'label', 'show', 'data', 'file' + #conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"))) + conf = tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), false, true) + else + #conf = tk_split_list(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"))) + conf = tk_split_list(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), 0, false, true) + end + key = conf.shift[1..-1] + { key => conf } + else + ret = {} + #tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)))).each{|conflist| + # conf = tk_split_simplelist(conflist) + tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)), false, false).each{|conflist| + conf = tk_split_simplelist(conflist, false, true) + key = conf.shift[1..-1] + case key + when 'text', 'label', 'show', 'data', 'file' + 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 + } + ret + end + end + end + + def current_image_configinfo(index, slot = nil) + if TkComm::GET_CONFIGINFO_AS_ARRAY + if slot + conf = image_configinfo(index, slot) + {conf[0] => conf[4]} + else + ret = {} + image_configinfo(index).each{|conf| + ret[conf[0]] = conf[4] if conf.size > 2 + } + ret + end + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY + ret = {} + image_configinfo(index, slot).each{|k, conf| + ret[k] = conf[-1] if conf.kind_of?(Array) + } + ret + end + end + + def image_names + #tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'names'))).collect{|elt| + tk_split_simplelist(tk_send_without_enc('image', 'names'), false, true).collect{|elt| + tagid2obj(elt) + } + end + + def set_insert(index) + tk_send_without_enc('mark','set','insert', _get_eval_enc_str(index)) + self + end + + def set_current(index) + tk_send_without_enc('mark','set','current', _get_eval_enc_str(index)) + self + end + + def insert(index, chars, *tags) + if tags[0].kind_of?(Array) + # multiple chars-taglist argument :: str, [tag,...], str, [tag,...], ... + args = [chars] + while tags.size > 0 + args << tags.shift.collect{|x|_get_eval_string(x)}.join(' ') # taglist + args << tags.shift if tags.size > 0 # chars + end + super(index, *args) + else + # single chars-taglist argument :: str, tag, tag, ... + if tags.size == 0 + super(index, chars) + else + super(index, chars, tags.collect{|x|_get_eval_string(x)}.join(' ')) + end + end + end + + def destroy + @tags = {} unless @tags + @tags.each_value do |t| + t.destroy + end + super() + end + + def backspace + self.delete 'insert' + end + + def bbox(index) + list(tk_send_without_enc('bbox', _get_eval_enc_str(index))) + end + + def compare(idx1, op, idx2) + bool(tk_send_without_enc('compare', _get_eval_enc_str(idx1), + op, _get_eval_enc_str(idx2))) + end + + def count(idx1, idx2, *opts) + # opts are Tk8.5 feature + cnt = 0 + args = opts.collect{|opt| + str = opt.to_s + cnt += 1 if str != 'update' + '-' + str + } + args << _get_eval_enc_str(idx1) << _get_eval_enc_str(idx2) + if cnt <= 1 + number(tk_send_without_enc('count', *opts)) + else + list(tk_send_without_enc('count', *opts)) + end + end + + def count_info(idx1, idx2, update=true) + # Tk8.5 feature + opts = [ + :chars, :displaychars, :displayindices, :displaylines, + :indices, :lines, :xpixels, :ypixels + ] + if update + lst = count(idx1, idx2, :update, *opts) + else + lst = count(idx1, idx2, *opts) + end + info = {} + opts.each_with_index{|key, idx| info[key] = lst[idx]} + info + end + + def peer_names() + # Tk8.5 feature + list(tk_send_without_enc('peer', 'names')) + end + + def replace(idx1, idx2, *opts) + tk_send('replace', idx1, idx2, *opts) + self + end + + def debug + bool(tk_send_without_enc('debug')) + end + def debug=(boolean) + tk_send_without_enc('debug', boolean) + #self + boolean + end + + def dlineinfo(index) + list(tk_send_without_enc('dlineinfo', _get_eval_enc_str(index))) + end + + def modified? + bool(tk_send_without_enc('edit', 'modified')) + end + def modified(mode) + tk_send_without_enc('edit', 'modified', mode) + self + end + def modified=(mode) + modified(mode) + mode + end + + def edit_redo + tk_send_without_enc('edit', 'redo') + self + end + def edit_reset + tk_send_without_enc('edit', 'reset') + self + end + def edit_separator + tk_send_without_enc('edit', 'separator') + self + end + def edit_undo + tk_send_without_enc('edit', 'undo') + self + end + + def xview_pickplace(index) + tk_send_without_enc('xview', '-pickplace', _get_eval_enc_str(index)) + self + end + + def yview_pickplace(index) + tk_send_without_enc('yview', '-pickplace', _get_eval_enc_str(index)) + self + end + + def text_copy + # Tk8.4 feature + tk_call_without_enc('tk_textCopy', @path) + self + end + + def text_cut + # Tk8.4 feature + tk_call_without_enc('tk_textCut', @path) + self + end + + def text_paste + # Tk8.4 feature + tk_call_without_enc('tk_textPaste', @path) + self + end + + def tag_add(tag, index1, index2=None) + tk_send_without_enc('tag', 'add', _get_eval_enc_str(tag), + _get_eval_enc_str(index1), + _get_eval_enc_str(index2)) + self + end + alias addtag tag_add + alias add_tag tag_add + + def tag_delete(*tags) + tk_send_without_enc('tag', 'delete', + *(tags.collect{|tag| _get_eval_enc_str(tag)})) + TkTextTag::TTagID_TBL.mutex.synchronize{ + if TkTextTag::TTagID_TBL[@path] + tags.each{|tag| + if tag.kind_of?(TkTextTag) + TkTextTag::TTagID_TBL[@path].delete(tag.id) + else + TkTextTag::TTagID_TBL[@path].delete(tag) + end + } + end + } + self + end + alias deltag tag_delete + alias delete_tag tag_delete + + #def tag_bind(tag, seq, cmd=Proc.new, *args) + # _bind([@path, 'tag', 'bind', tag], seq, cmd, *args) + # self + #end + def tag_bind(tag, seq, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind([@path, 'tag', 'bind', tag], seq, cmd, *args) + self + end + + #def tag_bind_append(tag, seq, cmd=Proc.new, *args) + # _bind_append([@path, 'tag', 'bind', tag], seq, cmd, *args) + # self + #end + def tag_bind_append(tag, seq, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append([@path, 'tag', 'bind', tag], seq, cmd, *args) + self + end + + def tag_bind_remove(tag, seq) + _bind_remove([@path, 'tag', 'bind', tag], seq) + self + end + + def tag_bindinfo(tag, context=nil) + _bindinfo([@path, 'tag', 'bind', tag], context) + end + +=begin + def tag_cget(tag, key) + case key.to_s + when 'text', 'label', 'show', 'data', 'file' + tk_call_without_enc(@path, 'tag', 'cget', + _get_eval_enc_str(tag), "-#{key}") + when 'font', 'kanjifont' + #fnt = tk_tcl2ruby(tk_send('tag', 'cget', tag, "-#{key}")) + fnt = tk_tcl2ruby(_fromUTF8(tk_send_without_enc('tag','cget',_get_eval_enc_str(tag),'-font'))) + unless fnt.kind_of?(TkFont) + fnt = tagfontobj(tag, 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(@path,'tag','cget',_get_eval_enc_str(tag),"-#{key}"))) + end + end + + def tag_configure(tag, key, val=None) + if key.kind_of?(Hash) + key = _symbolkey2str(key) + if ( key['font'] || key['kanjifont'] \ + || key['latinfont'] || key['asciifont'] ) + tagfont_configure(tag, key) + else + tk_send_without_enc('tag', 'configure', _get_eval_enc_str(tag), + *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(tag) + else + tagfont_configure(tag, {key=>val}) + end + else + tk_send_without_enc('tag', 'configure', _get_eval_enc_str(tag), + "-#{key}", _get_eval_enc_str(val)) + end + end + self + end + + def tag_configinfo(tag, key=nil) + if TkComm::GET_CONFIGINFO_AS_ARRAY + if key + case key.to_s + when 'text', 'label', 'show', 'data', 'file' + conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}"))) + when 'font', 'kanjifont' + conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}"))) + conf[4] = tagfont_configinfo(tag, conf[4]) + else + conf = tk_split_list(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}"))) + end + conf[0] = conf[0][1..-1] + conf + else + ret = tk_split_simplelist(_fromUTF8(tk_send('tag','configure',_get_eval_enc_str(tag)))).collect{|conflist| + conf = tk_split_simplelist(conflist) + conf[0] = conf[0][1..-1] + case conf[0] + when 'text', 'label', 'show', 'data', 'file' + 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(tag, 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', 'data', 'file' + conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}"))) + when 'font', 'kanjifont' + conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}"))) + conf[4] = tagfont_configinfo(tag, conf[4]) + else + conf = tk_split_list(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}"))) + end + key = conf.shift[1..-1] + { key => conf } + else + ret = {} + tk_split_simplelist(_fromUTF8(tk_send('tag','configure',_get_eval_enc_str(tag)))).each{|conflist| + conf = tk_split_simplelist(conflist) + key = conf.shift[1..-1] + case key + when 'text', 'label', 'show', 'data', 'file' + 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(tag, fontconf[3]) + ret['font'] = fontconf + end + ret + end + end + end + + def current_tag_configinfo(tag, key=nil) + if TkComm::GET_CONFIGINFO_AS_ARRAY + if key + conf = tag_configinfo(tag, key) + {conf[0] => conf[4]} + else + ret = {} + tag_configinfo(tag).each{|conf| + ret[conf[0]] = conf[4] if conf.size > 2 + } + ret + end + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY + ret = {} + tag_configinfo(tag, key).each{|k, conf| + ret[k] = conf[-1] if conf.kind_of?(Array) + } + ret + end + end +=end + + def tag_raise(tag, above=None) + tk_send_without_enc('tag', 'raise', _get_eval_enc_str(tag), + _get_eval_enc_str(above)) + self + end + + def tag_lower(tag, below=None) + tk_send_without_enc('tag', 'lower', _get_eval_enc_str(tag), + _get_eval_enc_str(below)) + self + end + + def tag_remove(tag, *indices) + tk_send_without_enc('tag', 'remove', _get_eval_enc_str(tag), + *(indices.collect{|idx| _get_eval_enc_str(idx)})) + self + end + + def tag_ranges(tag) + #l = tk_split_simplelist(tk_send_without_enc('tag', 'ranges', + # _get_eval_enc_str(tag))) + l = tk_split_simplelist(tk_send_without_enc('tag', 'ranges', + _get_eval_enc_str(tag)), + false, true) + r = [] + while key=l.shift + r.push [Tk::Text::IndexString.new(key), Tk::Text::IndexString.new(l.shift)] + end + r + end + + def tag_nextrange(tag, first, last=None) + simplelist(tk_send_without_enc('tag', 'nextrange', + _get_eval_enc_str(tag), + _get_eval_enc_str(first), + _get_eval_enc_str(last))).collect{|idx| + Tk::Text::IndexString.new(idx) + } + end + + def tag_prevrange(tag, first, last=None) + simplelist(tk_send_without_enc('tag', 'prevrange', + _get_eval_enc_str(tag), + _get_eval_enc_str(first), + _get_eval_enc_str(last))).collect{|idx| + Tk::Text::IndexString.new(idx) + } + end + +=begin + def window_cget(index, slot) + case slot.to_s + when 'text', 'label', 'show', 'data', 'file' + _fromUTF8(tk_send_without_enc('window', 'cget', + _get_eval_enc_str(index), "-#{slot}")) + when 'font', 'kanjifont' + #fnt = tk_tcl2ruby(tk_send('window', 'cget', index, "-#{slot}")) + fnt = tk_tcl2ruby(_fromUTF8(tk_send_without_enc('window', 'cget', _get_eval_enc_str(index), '-font'))) + unless fnt.kind_of?(TkFont) + fnt = tagfontobj(index, fnt) + end + if slot.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('window', 'cget', _get_eval_enc_str(index), "-#{slot}"))) + end + end + + def window_configure(index, slot, value=None) + if index.kind_of?(TkTextWindow) + index.configure(slot, value) + else + if slot.kind_of?(Hash) + slot = _symbolkey2str(slot) + win = slot['window'] + # slot['window'] = win.epath if win.kind_of?(TkWindow) + slot['window'] = _epath(win) if win + if slot['create'] + p_create = slot['create'] + if p_create.kind_of?(Proc) +#=begin + slot['create'] = install_cmd(proc{ + id = p_create.call + if id.kind_of?(TkWindow) + id.epath + else + id + end + }) +#=end + slot['create'] = install_cmd(proc{_epath(p_create.call)}) + end + end + tk_send_without_enc('window', 'configure', + _get_eval_enc_str(index), + *hash_kv(slot, true)) + else + if slot == 'window' || slot == :window + # id = value + # value = id.epath if id.kind_of?(TkWindow) + value = _epath(value) + end + if slot == 'create' || slot == :create + p_create = value + if p_create.kind_of?(Proc) +#=begin + value = install_cmd(proc{ + id = p_create.call + if id.kind_of?(TkWindow) + id.epath + else + id + end + }) +#=end + value = install_cmd(proc{_epath(p_create.call)}) + end + end + tk_send_without_enc('window', 'configure', + _get_eval_enc_str(index), + "-#{slot}", _get_eval_enc_str(value)) + end + end + self + end + + def window_configinfo(win, slot = nil) + if TkComm::GET_CONFIGINFO_AS_ARRAY + if slot + case slot.to_s + when 'text', 'label', 'show', 'data', 'file' + conf = tk_split_simplelist(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win), "-#{slot}"))) + else + conf = tk_split_list(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win), "-#{slot}"))) + end + conf[0] = conf[0][1..-1] + conf + else + tk_split_simplelist(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win)))).collect{|conflist| + conf = tk_split_simplelist(conflist) + conf[0] = conf[0][1..-1] + case conf[0] + when 'text', 'label', 'show', 'data', 'file' + 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 + } + end + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY + if slot + case slot.to_s + when 'text', 'label', 'show', 'data', 'file' + conf = tk_split_simplelist(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win), "-#{slot}"))) + else + conf = tk_split_list(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win), "-#{slot}"))) + end + key = conf.shift[1..-1] + { key => conf } + else + ret = {} + tk_split_simplelist(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win)))).each{|conflist| + conf = tk_split_simplelist(conflist) + key = conf.shift[1..-1] + case key + when 'text', 'label', 'show', 'data', 'file' + 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 + } + ret + end + end + end + + def current_window_configinfo(win, slot = nil) + if TkComm::GET_CONFIGINFO_AS_ARRAY + if slot + conf = window_configinfo(win, slot) + {conf[0] => conf[4]} + else + ret = {} + window_configinfo(win).each{|conf| + ret[conf[0]] = conf[4] if conf.size > 2 + } + ret + end + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY + ret = {} + window_configinfo(win, slot).each{|k, conf| + ret[k] = conf[-1] if conf.kind_of?(Array) + } + ret + end + end +=end + + def window_names + # tk_split_simplelist(_fromUTF8(tk_send_without_enc('window', 'names'))).collect{|elt| + tk_split_simplelist(tk_send_without_enc('window', 'names'), false, true).collect{|elt| + tagid2obj(elt) + } + end + + def _ktext_length(txt) + if TkCore::WITH_ENCODING ### Ruby 1.9 !!!!!!!!!!!!! + return txt.length + end + ########################### + + if $KCODE !~ /n/i + return txt.gsub(/[^\Wa-zA-Z_\d]/, ' ').length + end + + # $KCODE == 'NONE' + if JAPANIZED_TK + tk_call_without_enc('kstring', 'length', + _get_eval_enc_str(txt)).to_i + else + begin + tk_call_without_enc('encoding', 'convertto', 'ascii', + _get_eval_enc_str(txt)).length + rescue StandardError, NameError + # sorry, I have no plan + txt.length + end + end + end + private :_ktext_length + + def tksearch(*args) + # call 'search' subcommand of text widget + # args ::= [<array_of_opts>] <pattern> <start_index> [<stop_index>] + # If <pattern> is regexp, then it must be a regular expression of Tcl + nocase = false + if args[0].kind_of?(Array) + opts = args.shift.collect{|opt| + s_opt = opt.to_s + nocase = true if s_opt == 'nocase' + '-' + s_opt + } + else + opts = [] + end + + if args[0].kind_of?(Regexp) + regexp = args.shift + if !nocase && (regexp.options & Regexp::IGNORECASE) != 0 + opts << '-nocase' + end + args.unshift(regexp.source) + end + + opts << '--' + + ret = tk_send('search', *(opts + args)) + if ret == "" + nil + else + Tk::Text::IndexString.new(ret) + end + end + + def tksearch_with_count(*args) + # call 'search' subcommand of text widget + # args ::= [<array_of_opts>] <var> <pattern> <start_index> [<stop_index>] + # If <pattern> is regexp, then it must be a regular expression of Tcl + nocase = false + if args[0].kind_of?(Array) + opts = args.shift.collect{|opt| + s_opt = opt.to_s + nocase = true if s_opt == 'nocase' + '-' + s_opt + } + else + opts = [] + end + + opts << '-count' << args.shift + + if args[0].kind_of?(Regexp) + regexp = args.shift + if !nocase && (regexp.options & Regexp::IGNORECASE) != 0 + opts << '-nocase' + end + args.unshift(regexp.source) + end + + opts << '--' + + ret = tk_send('search', *(opts + args)) + if ret == "" + nil + else + Tk::Text::IndexString.new(ret) + end + end + + def search_with_length(pat,start,stop=None) + pat = pat.chr if pat.kind_of?(Integer) + if stop != None + return ["", 0] if compare(start,'>=',stop) + txt = get(start,stop) + if (pos = txt.index(pat)) + match = $& + #pos = txt[0..(pos-1)].split('').length if pos > 0 + pos = _ktext_length(txt[0..(pos-1)]) if pos > 0 + if pat.kind_of?(String) + #return [index(start + " + #{pos} chars"), pat.split('').length] + return [index(start + " + #{pos} chars"), + _ktext_length(pat), pat.dup] + else + #return [index(start + " + #{pos} chars"), $&.split('').length] + return [index(start + " + #{pos} chars"), + _ktext_length(match), match] + end + else + return ["", 0] + end + else + txt = get(start,'end - 1 char') + if (pos = txt.index(pat)) + match = $& + #pos = txt[0..(pos-1)].split('').length if pos > 0 + pos = _ktext_length(txt[0..(pos-1)]) if pos > 0 + if pat.kind_of?(String) + #return [index(start + " + #{pos} chars"), pat.split('').length] + return [index(start + " + #{pos} chars"), + _ktext_length(pat), pat.dup] + else + #return [index(start + " + #{pos} chars"), $&.split('').length] + return [index(start + " + #{pos} chars"), + _ktext_length(match), match] + end + else + txt = get('1.0','end - 1 char') + if (pos = txt.index(pat)) + match = $& + #pos = txt[0..(pos-1)].split('').length if pos > 0 + pos = _ktext_length(txt[0..(pos-1)]) if pos > 0 + if pat.kind_of?(String) + #return [index("1.0 + #{pos} chars"), pat.split('').length] + return [index("1.0 + #{pos} chars"), + _ktext_length(pat), pat.dup] + else + #return [index("1.0 + #{pos} chars"), $&.split('').length] + return [index("1.0 + #{pos} chars"), _ktext_length(match), match] + end + else + return ["", 0] + end + end + end + end + + def search(pat,start,stop=None) + search_with_length(pat,start,stop)[0] + end + + def rsearch_with_length(pat,start,stop=None) + pat = pat.chr if pat.kind_of?(Integer) + if stop != None + return ["", 0] if compare(start,'<=',stop) + txt = get(stop,start) + if (pos = txt.rindex(pat)) + match = $& + #pos = txt[0..(pos-1)].split('').length if pos > 0 + pos = _ktext_length(txt[0..(pos-1)]) if pos > 0 + if pat.kind_of?(String) + #return [index(stop + " + #{pos} chars"), pat.split('').length] + return [index(stop + " + #{pos} chars"), _ktext_length(pat), pat.dup] + else + #return [index(stop + " + #{pos} chars"), $&.split('').length] + return [index(stop + " + #{pos} chars"), _ktext_length(match), match] + end + else + return ["", 0] + end + else + txt = get('1.0',start) + if (pos = txt.rindex(pat)) + match = $& + #pos = txt[0..(pos-1)].split('').length if pos > 0 + pos = _ktext_length(txt[0..(pos-1)]) if pos > 0 + if pat.kind_of?(String) + #return [index("1.0 + #{pos} chars"), pat.split('').length] + return [index("1.0 + #{pos} chars"), _ktext_length(pat), pat.dup] + else + #return [index("1.0 + #{pos} chars"), $&.split('').length] + return [index("1.0 + #{pos} chars"), _ktext_length(match), match] + end + else + txt = get('1.0','end - 1 char') + if (pos = txt.rindex(pat)) + match = $& + #pos = txt[0..(pos-1)].split('').length if pos > 0 + pos = _ktext_length(txt[0..(pos-1)]) if pos > 0 + if pat.kind_of?(String) + #return [index("1.0 + #{pos} chars"), pat.split('').length] + return [index("1.0 + #{pos} chars"), _ktext_length(pat), pat.dup] + else + #return [index("1.0 + #{pos} chars"), $&.split('').length] + return [index("1.0 + #{pos} chars"), _ktext_length(match), match] + end + else + return ["", 0] + end + end + end + end + + def rsearch(pat,start,stop=None) + rsearch_with_length(pat,start,stop)[0] + end + + def dump(type_info, *index, &block) + if type_info.kind_of?(Symbol) + type_info = [ type_info.to_s ] + elsif type_info.kind_of?(String) + type_info = [ type_info ] + end + args = type_info.collect{|inf| '-' + inf} + args << '-command' << block if block + str = tk_send('dump', *(args + index)) + result = [] + sel = nil + i = 0 + while i < str.size + # retrieve key + idx = str.index(/ /, i) + result.push str[i..(idx-1)] + i = idx + 1 + + # retrieve value + case result[-1] + when 'text' + if str[i] == ?{ + # text formed as {...} + val, i = _retrieve_braced_text(str, i) + result.push val + else + # text which may contain backslahes + val, i = _retrieve_backslashed_text(str, i) + result.push val + end + else + idx = str.index(/ /, i) + val = str[i..(idx-1)] + case result[-1] + when 'mark' + case val + when 'insert' + result.push TkTextMarkInsert.new(self) + when 'current' + result.push TkTextMarkCurrent.new(self) + when 'anchor' + result.push TkTextMarkAnchor.new(self) + else + result.push tk_tcl2ruby(val) + end + when 'tagon' + if val == 'sel' + if sel + result.push sel + else + result.push TkTextTagSel.new(self) + end + else + result.push tk_tcl2ruby(val) + end + when 'tagoff' + result.push tk_tcl2ruby(val) + when 'window' + result.push tk_tcl2ruby(val) + when 'image' + result.push tk_tcl2ruby(val) + end + i = idx + 1 + end + + # retrieve index + idx = str.index(/ /, i) + if idx + result.push(Tk::Text::IndexString.new(str[i..(idx-1)])) + i = idx + 1 + else + result.push(Tk::Text::IndexString.new(str[i..-1])) + break + end + end + + kvis = [] + until result.empty? + kvis.push [result.shift, result.shift, result.shift] + end + kvis # result is [[key1, value1, index1], [key2, value2, index2], ...] + end + + def _retrieve_braced_text(str, i) + cnt = 0 + idx = i + while idx < str.size + case str[idx] + when ?{ + cnt += 1 + when ?} + cnt -= 1 + if cnt == 0 + break + end + end + idx += 1 + end + return str[i+1..idx-1], idx + 2 + end + private :_retrieve_braced_text + + def _retrieve_backslashed_text(str, i) + j = i + idx = nil + loop { + idx = str.index(/ /, j) + if str[idx-1] == ?\\ + j += 1 + else + break + end + } + val = str[i..(idx-1)] + val.gsub!(/\\( |\{|\})/, '\1') + return val, idx + 1 + end + private :_retrieve_backslashed_text + + def dump_all(*index, &block) + dump(['all'], *index, &block) + end + def dump_mark(*index, &block) + dump(['mark'], *index, &block) + end + def dump_tag(*index, &block) + dump(['tag'], *index, &block) + end + def dump_text(*index, &block) + dump(['text'], *index, &block) + end + def dump_window(*index, &block) + dump(['window'], *index, &block) + end + def dump_image(*index, &block) + dump(['image'], *index, &block) + end +end + +#TkText = Tk::Text unless Object.const_defined? :TkText +#Tk.__set_toplevel_aliases__(:Tk, Tk::Text, :TkText) +Tk.__set_loaded_toplevel_aliases__('tk/text.rb', :Tk, Tk::Text, :TkText) + + +####################################### + +class Tk::Text::Peer < Tk::Text + # Tk8.5 feature + def initialize(text, parent=nil, keys={}) + unless text.kind_of?(Tk::Text) + fail ArgumentError, "Tk::Text is expected for 1st argument" + end + @src_text = text + super(parent, keys) + end + + def create_self(keys) + if keys and keys != None + tk_call_without_enc(@src_text.path, 'peer', 'create', + @path, *hash_kv(keys, true)) + else + tk_call_without_enc(@src_text.path, 'peer', 'create', @path) + end + end + private :create_self +end diff --git a/jni/ruby/ext/tk/lib/tk/textimage.rb b/jni/ruby/ext/tk/lib/tk/textimage.rb new file mode 100644 index 0000000..99027a0 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/textimage.rb @@ -0,0 +1,88 @@ +# +# tk/textimage.rb - treat Tk text image object +# +require 'tk' +require 'tk/text' + +class TkTextImage<TkObject + include Tk::Text::IndexModMethods + + def initialize(parent, index, keys) + #unless parent.kind_of?(Tk::Text) + # fail ArgumentError, "expect Tk::Text for 1st argument" + #end + @t = parent + if index == 'end' || 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)).freeze + @path.gravity = 'right' + end + + def id + Tk::Text::IndexString.new(@id) + end + def mark + @path + end + + def [](slot) + cget(slot) + end + def []=(slot, value) + configure(slot, value) + value + end + + def cget(slot) + @t.image_cget(@index, slot) + end + + def cget_strict(slot) + @t.image_cget_strict(@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', 'cget', @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 + +TktImage = TkTextImage diff --git a/jni/ruby/ext/tk/lib/tk/textmark.rb b/jni/ruby/ext/tk/lib/tk/textmark.rb new file mode 100644 index 0000000..d1888c5 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/textmark.rb @@ -0,0 +1,204 @@ +# +# tk/textmark.rb - methods for treating text marks +# +require 'tk' +require 'tk/text' + +class TkTextMark<TkObject + include Tk::Text::IndexModMethods + + TMarkID_TBL = TkCore::INTERP.create_table + + (Tk_TextMark_ID = ['mark'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + TkCore::INTERP.init_ip_env{ + TMarkID_TBL.mutex.synchronize{ TMarkID_TBL.clear } + } + + def TkTextMark.id2obj(text, id) + tpath = text.path + TMarkID_TBL.mutex.synchronize{ + if TMarkID_TBL[tpath] + TMarkID_TBL[tpath][id]? TMarkID_TBL[tpath][id]: id + else + id + end + } + end + + def initialize(parent, index) + #unless parent.kind_of?(Tk::Text) + # fail ArgumentError, "expect Tk::Text for 1st argument" + #end + @parent = @t = parent + @tpath = parent.path + Tk_TextMark_ID.mutex.synchronize{ + # @path = @id = Tk_TextMark_ID.join('') + @path = @id = Tk_TextMark_ID.join(TkCore::INTERP._ip_id_).freeze + Tk_TextMark_ID[1].succ! + } + TMarkID_TBL.mutex.synchronize{ + TMarkID_TBL[@id] = self + TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath] + TMarkID_TBL[@tpath][@id] = self + } + tk_call_without_enc(@t.path, 'mark', 'set', @id, + _get_eval_enc_str(index)) + @t._addtag id, self + end + + def id + Tk::Text::IndexString.new(@id) + end + + def exist? + #if ( tk_split_simplelist(_fromUTF8(tk_call_without_enc(@t.path, 'mark', 'names'))).find{|id| id == @id } ) + if ( tk_split_simplelist(tk_call_without_enc(@t.path, 'mark', 'names'), false, true).find{|id| id == @id } ) + true + else + false + end + end + +=begin + # move to Tk::Text::IndexModMethods module + def +(mod) + return chars(mod) if mod.kind_of?(Numeric) + + mod = mod.to_s + if mod =~ /^\s*[+-]?\d/ + Tk::Text::IndexString.new(@id + ' + ' + mod) + else + Tk::Text::IndexString.new(@id + ' ' + mod) + end + end + + def -(mod) + return chars(-mod) if mod.kind_of?(Numeric) + + mod = mod.to_s + if mod =~ /^\s*[+-]?\d/ + Tk::Text::IndexString.new(@id + ' - ' + mod) + elsif mod =~ /^\s*[-]\s+(\d.*)$/ + Tk::Text::IndexString.new(@id + ' - -' + $1) + else + Tk::Text::IndexString.new(@id + ' ' + mod) + end + end +=end + + def pos + @t.index(@id) + end + + def pos=(where) + set(where) + 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 +TktMark = TkTextMark + +class TkTextNamedMark<TkTextMark + def self.new(parent, name, index=nil) + TMarkID_TBL.mutex.synchronize{ + if TMarkID_TBL[parent.path] && TMarkID_TBL[parent.path][name] + obj = TMarkID_TBL[parent.path][name] + else + # super(parent, name, *args) + (obj = self.allocate).instance_eval{ + @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] + @t._addtag @id, self + } + obj + end + + if obj && index + tk_call_without_enc(parent.path, 'mark', 'set', name, + _get_eval_enc_str(index)) + end + obj + } + end + + def initialize(parent, name, index=nil) + # dummy:: not called by 'new' method + + #unless parent.kind_of?(Tk::Text) + # fail ArgumentError, "expect Tk::Text for 1st argument" + #end + @parent = @t = parent + @tpath = parent.path + @path = @id = name + tk_call_without_enc(@t.path, 'mark', 'set', @id, + _get_eval_enc_str(index)) if index + @t._addtag @id, self + end +end +TktNamedMark = TkTextNamedMark + +class TkTextMarkInsert<TkTextNamedMark + def self.new(parent,*args) + super(parent, 'insert', *args) + end +end +TktMarkInsert = TkTextMarkInsert + +class TkTextMarkCurrent<TkTextNamedMark + def self.new(parent,*args) + super(parent, 'current', *args) + end +end +TktMarkCurrent = TkTextMarkCurrent + +class TkTextMarkAnchor<TkTextNamedMark + def self.new(parent,*args) + super(parent, 'anchor', *args) + end +end +TktMarkAnchor = TkTextMarkAnchor diff --git a/jni/ruby/ext/tk/lib/tk/texttag.rb b/jni/ruby/ext/tk/lib/tk/texttag.rb new file mode 100644 index 0000000..9669201 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/texttag.rb @@ -0,0 +1,321 @@ +# +# tk/texttag.rb - methods for treating text tags +# +require 'tk' +require 'tk/text' +require 'tk/tagfont' + +class TkTextTag<TkObject + include TkTreatTagFont + include Tk::Text::IndexModMethods + + TTagID_TBL = TkCore::INTERP.create_table + + (Tk_TextTag_ID = ['tag'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + TkCore::INTERP.init_ip_env{ + TTagID_TBL.mutex.synchronize{ TTagID_TBL.clear } + } + + def TkTextTag.id2obj(text, id) + tpath = text.path + TTagID_TBL.mutex.synchronize{ + if TTagID_TBL[tpath] + TTagID_TBL[tpath][id]? TTagID_TBL[tpath][id]: id + else + id + end + } + end + + def initialize(parent, *args) + #unless parent.kind_of?(TkText) + # fail ArgumentError, "expect TkText for 1st argument" + #end + @parent = @t = parent + @tpath = parent.path + Tk_TextTag_ID.mutex.synchronize{ + # @path = @id = Tk_TextTag_ID.join('') + @path = @id = Tk_TextTag_ID.join(TkCore::INTERP._ip_id_).freeze + Tk_TextTag_ID[1].succ! + } + TTagID_TBL.mutex.synchronize{ + TTagID_TBL[@id] = self + TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath] + TTagID_TBL[@tpath][@id] = self + } + #tk_call @t.path, "tag", "configure", @id, *hash_kv(keys) + if args != [] + keys = args.pop + if keys.kind_of?(Hash) + add(*args) if args != [] + configure(keys) + else + args.push keys + add(*args) + end + end + @t._addtag id, self + end + + def id + Tk::Text::IndexString.new(@id) + end + + def exist? + #if ( tk_split_simplelist(_fromUTF8(tk_call_without_enc(@t.path, 'tag', 'names'))).find{|id| id == @id } ) + if ( tk_split_simplelist(tk_call_without_enc(@t.path, 'tag', 'names'), false, true).find{|id| id == @id } ) + true + else + false + end + end + + def first + Tk::Text::IndexString.new(@id + '.first') + end + + def last + Tk::Text::IndexString.new(@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 [Tk::Text::IndexString.new(key), Tk::Text::IndexString.new(l.shift)] + end + r + end + + def nextrange(first, last=None) + simplelist(tk_call_without_enc(@t.path, 'tag', 'nextrange', @id, + _get_eval_enc_str(first), + _get_eval_enc_str(last))).collect{|idx| + Tk::Text::IndexString.new(idx) + } + end + + def prevrange(first, last=None) + simplelist(tk_call_without_enc(@t.path, 'tag', 'prevrange', @id, + _get_eval_enc_str(first), + _get_eval_enc_str(last))).collect{|idx| + Tk::Text::IndexString.new(idx) + } + end + + def [](key) + cget key + end + + def []=(key,val) + configure key, val + val + end + + def cget_tkstring(key) + @t.tag_cget_tkstring @id, key + end + def cget(key) + @t.tag_cget @id, key + end + def cget_strict(key) + @t.tag_cget_strict @id, key + end +=begin + 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 +=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) + # _bind([@t.path, 'tag', 'bind', @id], seq, cmd, *args) + # self + #end + def bind(seq, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind([@t.path, 'tag', 'bind', @id], seq, cmd, *args) + self + end + + #def bind_append(seq, cmd=Proc.new, *args) + # _bind_append([@t.path, 'tag', 'bind', @id], seq, cmd, *args) + # self + #end + def bind_append(seq, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _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.mutex.synchronize{ + TTagID_TBL[@tpath].delete(@id) if TTagID_TBL[@tpath] + } + self + end +end +TktTag = TkTextTag + +class TkTextNamedTag<TkTextTag + def self.new(parent, name, *args) + tagobj = nil + TTagID_TBL.mutex.synchronize{ + if TTagID_TBL[parent.path] && TTagID_TBL[parent.path][name] + tagobj = TTagID_TBL[parent.path][name] + else + # super(parent, name, *args) + (tagobj = self.allocate).instance_eval{ + @parent = @t = parent + @tpath = parent.path + @path = @id = name + TTagID_TBL[@id] = self + TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath] + TTagID_TBL[@tpath][@id] = self unless TTagID_TBL[@tpath][@id] + @t._addtag @id, self + } + end + } + + if args != [] + keys = args.pop + if keys.kind_of?(Hash) + tagobj.add(*args) if args != [] + tagobj.configure(keys) + else + args.push keys + tagobj.add(*args) + end + end + + tagobj + end + + def initialize(parent, name, *args) + # dummy:: not called by 'new' method + + #unless parent.kind_of?(Tk::Text) + # fail ArgumentError, "expect Tk::Text for 1st argument" + #end + @parent = @t = parent + @tpath = parent.path + @path = @id = name + + #if mode + # tk_call @t.path, "addtag", @id, *args + #end + if args != [] + keys = args.pop + if keys.kind_of?(Hash) + add(*args) if args != [] + configure(keys) + else + args.push keys + add(*args) + end + end + @t._addtag @id, self + end +end +TktNamedTag = TkTextNamedTag + +class TkTextTagSel<TkTextNamedTag + def self.new(parent, *args) + super(parent, 'sel', *args) + end +end +TktTagSel = TkTextTagSel diff --git a/jni/ruby/ext/tk/lib/tk/textwindow.rb b/jni/ruby/ext/tk/lib/tk/textwindow.rb new file mode 100644 index 0000000..49327b2 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/textwindow.rb @@ -0,0 +1,154 @@ +# +# tk/textwindow.rb - treat Tk text window object +# +require 'tk' +require 'tk/text' + +class TkTextWindow<TkObject + include Tk::Text::IndexModMethods + + def initialize(parent, index, keys = {}) + #unless parent.kind_of?(Tk::Text) + # fail ArgumentError, "expect Tk::Text for 1st argument" + #end + @t = parent + if index == 'end' || 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) + if TkComm._callback_entry?(@p_create) +=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)) + @path.gravity = 'right' + end + + def id + Tk::Text::IndexString.new(_epath(@id)) + end + def mark + @path + end + + def [](slot) + cget(slot) + end + def []=(slot, value) + configure(slot, value) + value + end + + def cget(slot) + @t.window_cget(@index, slot) + end + def cget_strict(slot) + @t.window_cget_strict(@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) + if TkComm._callback_entry?(@p_create) + 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 + +TktWindow = TkTextWindow diff --git a/jni/ruby/ext/tk/lib/tk/timer.rb b/jni/ruby/ext/tk/lib/tk/timer.rb new file mode 100644 index 0000000..fb2e088 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/timer.rb @@ -0,0 +1,669 @@ +# +# tk/timer.rb : methods for Tcl/Tk after command +# +# $Id: timer.rb 25189 2009-10-02 12:04:37Z akr $ +# +require 'tk' + +class TkTimer + include TkCore + extend TkCore + + TkCommandNames = ['after'.freeze].freeze + + (Tk_CBID = ['a'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + Tk_CBTBL = TkUtil.untrust({}) + + 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.start(*args, &b) + self.new(*args, &b).start + end + + def self.callback(obj_id) + 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 + @after_id = nil + begin + @return_value = @current_proc.call(self) + rescue SystemExit + exit(0) + rescue Interrupt + exit!(1) + rescue Exception => e + if @cancel_on_exception && + @cancel_on_exception.find{|exc| e.kind_of?(exc)} + cancel + @return_value = e + @in_callback = false + 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) + if TkCore::INTERP.deleted? + self.cancel + return self + end + @after_script = "rb_after #{@id}" + @current_args = args + @current_script = [sleep, @after_script] + @after_id = tk_call_without_enc('after', 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 + __at_end__ + 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 + __at_end__ + return + end + end + + @current_args = args + + # if @sleep_time.kind_of?(Proc) + if TkComm._callback_entry?(@sleep_time) + 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, &b) + Tk_CBID.mutex.synchronize{ + # @id = Tk_CBID.join('') + @id = Tk_CBID.join(TkCore::INTERP._ip_id_) + Tk_CBID[1].succ! + } + + @wait_var = TkVariable.new(0) + + @at_end_proc = nil + + @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). + + if b + case args.size + when 0 + add_procs(b) + when 1 + args << -1 << b + else + args << b + end + end + + 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 __at_end__ + @at_end_proc.call(self) if @at_end_proc + @wait_var.value = 0 # for wait + end + private :__at_end__ + + 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_interval(interval) + #if interval != 'idle' && interval != :idle \ + # && !interval.kind_of?(Integer) && !interval.kind_of?(Proc) + if interval != 'idle' && interval != :idle \ + && !interval.kind_of?(Integer) && !TkComm._callback_entry?(interval) + fail ArgumentError, "expect Integer or Proc" + end + @sleep_time = interval + end + + def set_procs(interval, loop_exec, *procs) + #if interval != 'idle' && interval != :idle \ + # && !interval.kind_of?(Integer) && !interval.kind_of?(Proc) + if interval != 'idle' && interval != :idle \ + && !interval.kind_of?(Integer) && !TkComm._callback_entry?(interval) + fail ArgumentError, "expect Integer or Proc for 1st argument" + end + @sleep_time = interval + + @loop_proc = [] + procs.each{|e| + # if e.kind_of?(Proc) + if TkComm._callback_entry?(e) + @loop_proc.push([e]) + else + @loop_proc.push(e) + end + } + @proc_max = @loop_proc.size + @current_pos = 0 + + if loop_exec.kind_of?(Integer) && loop_exec < 0 + @loop_exec = -1 + elsif loop_exec == true + @loop_exec = -1 + elsif loop_exec == nil || loop_exec == false || loop_exec == 0 + @loop_exec = 0 + else + if not loop_exec.kind_of?(Integer) + fail ArgumentError, "expect Integer for 2nd argument" + end + @loop_exec = loop_exec + end + @do_loop = @loop_exec + + self + end + + def add_procs(*procs) + procs.each{|e| + # if e.kind_of?(Proc) + if TkComm._callback_entry?(e) + @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) + if TkComm._callback_entry?(e) + @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=nil, init_proc=nil, *init_args, &b) + # set parameters for 'restart' + sleep = @init_sleep unless sleep + + if sleep != 'idle' && sleep != :idle && !sleep.kind_of?(Integer) + fail ArgumentError, "expect Integer or 'idle' for 1st argument" + end + + @init_sleep = sleep + @init_proc = init_proc + @init_args = init_args + + @init_proc = b if !@init_proc && b + @init_proc = proc{|*args| } if @init_sleep > 0 && !@init_proc + + self + end + + def start(*init_args, &b) + return nil if @running + + Tk_CBTBL[@id] = self + @do_loop = @loop_exec + @current_pos = 0 + @return_value = nil + @after_id = nil + + @init_sleep = 0 + @init_proc = nil + @init_args = nil + + argc = init_args.size + if argc > 0 + sleep = init_args.shift + if sleep != 'idle' && sleep != :idle && !sleep.kind_of?(Integer) + fail ArgumentError, "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 > 2 + + @init_proc = b if !@init_proc && b + @init_proc = proc{|*args| } if @init_sleep > 0 && !@init_proc + + @current_sleep = @init_sleep + @running = true + if @init_proc + # if not @init_proc.kind_of?(Proc) + if !TkComm._callback_entry?(@init_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 + @current_script = [] + + @set_next = false if @in_callback + + self + end + + def restart(*restart_args, &b) + cancel if @running + if restart_args.empty? && !b + start(@init_sleep, @init_proc, *@init_args) + else + start(*restart_args, &b) + end + end + + def cancel + @running = false + # @wait_var.value = 0 + __at_end__ + 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 + return restart() if @current_script.empty? + sleep, cmd = @current_script + fail RuntimeError, "no procedure to continue" unless cmd + if wait + unless wait.kind_of?(Integer) + fail ArgumentError, "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 at_end(*arg, &b) + if arg.empty? + if b + @at_end_proc = b + else + # no proc + return @at_end_proc + end + else + fail ArgumentError, "wrong number of arguments" if arg.length != 1 || b + @at_end_proc = arg[0] + end + self + 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 + + +class TkRTTimer < TkTimer + DEFAULT_OFFSET_LIST_SIZE = 5 + + def initialize(*args, &b) + super(*args, &b) + + @offset_list = Array.new(DEFAULT_OFFSET_LIST_SIZE){ [0, 0] } + @offset_s = 0 + @offset_u = 0 + @est_time = nil + end + + def start(*args, &b) + return nil if @running + @est_time = nil + @cb_start_time = Time.now + super(*args, &b) + end + + def cancel + super() + @est_time = nil + @cb_start_time = Time.now + self + end + alias stop cancel + + def continue(wait=nil) + fail RuntimeError, "is already running" if @running + @cb_start_time = Time.now + super(wait) + end + + def set_interval(interval) + super(interval) + @est_time = nil + end + + def _offset_ave + size = 0 + d_sec = 0; d_usec = 0 + @offset_list.each_with_index{|offset, idx| + # weight = 1 + weight = idx + 1 + size += weight + d_sec += offset[0] * weight + d_usec += offset[1] * weight + } + offset_s, mod = d_sec.divmod(size) + offset_u = ((mod * 1000000 + d_usec) / size.to_f).round + [offset_s, offset_u] + end + private :_offset_ave + + 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 + __at_end__ + 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 + __at_end__ + return + end + end + + @current_args = args + + cmd, *cmd_args = @loop_proc[@current_pos] + @current_pos += 1 + @current_proc = cmd + + @offset_s, @offset_u = _offset_ave + + if TkComm._callback_entry?(@sleep_time) + sleep = @sleep_time.call(self) + else + sleep = @sleep_time + end + + if @est_time + @est_time = Time.at(@est_time.to_i, @est_time.usec + sleep*1000) + else + @est_time = Time.at(@cb_start_time.to_i, + @cb_start_time.usec + sleep*1000) + end + + now = Time.now + real_sleep = ((@est_time.to_i - now.to_i + @offset_s)*1000.0 + + (@est_time.usec - now.usec + @offset_u)/1000.0).round + if real_sleep <= 0 + real_sleep = 0 + @offset_s = now.to_i + @offset_u = now.usec + end + @current_sleep = real_sleep + + set_callback(real_sleep, cmd_args) + end + + def cb_call + if @est_time + @offset_list.shift + + @cb_start_time = Time.now + + if @current_sleep == 0 + @offset_list.push([ + @offset_s - @cb_start_time.to_i, + @offset_u - @cb_start_time.usec + ]) + else + @offset_list.push([ + @offset_s + (@est_time.to_i - @cb_start_time.to_i), + @offset_u + (@est_time.usec - @cb_start_time.usec) + ]) + end + end + + @cb_cmd.call + end +end diff --git a/jni/ruby/ext/tk/lib/tk/tk_mac.rb b/jni/ruby/ext/tk/lib/tk/tk_mac.rb new file mode 100644 index 0000000..77bb234 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/tk_mac.rb @@ -0,0 +1,158 @@ +# +# tk/tk_mac.rb : Access Mac-Specific functionality on OS X from Tk +# (supported by Tk8.6 or later) +# +# ATTENTION !! +# This is NOT TESTED. Because I have no test-environment. +# +require 'tk' + +module Tk + module Mac + end +end + +module Tk::Mac + extend TkCore + + # event handler callbacks + def self.def_ShowPreferences(cmd=Proc.new) + ip_eval("proc ::tk::mac::ShowPreferences {} { #{install_cmd(cmd)} }") + nil + end + + def self.def_OpenApplication(cmd=Proc.new) + ip_eval("proc ::tk::mac::OpenApplication {} { #{install_cmd(cmd)} }") + nil + end + + def self.def_ReopenApplication(cmd=Proc.new) + ip_eval("proc ::tk::mac::ReopenApplication {} { #{install_cmd(cmd)} }") + nil + end + + def self.def_OpenDocument(cmd=Proc.new) + ip_eval("proc ::tk::mac::OpenDocument {args} { eval #{install_cmd(cmd)} $args }") + nil + end + + def self.def_PrintDocument(cmd=Proc.new) + ip_eval("proc ::tk::mac::PrintDocument {args} { eval #{install_cmd(cmd)} $args }") + nil + end + + def self.def_Quit(cmd=Proc.new) + ip_eval("proc ::tk::mac::Quit {} { #{install_cmd(cmd)} }") + nil + end + + def self.def_OnHide(cmd=Proc.new) + ip_eval("proc ::tk::mac::OnHide {} { #{install_cmd(cmd)} }") + nil + end + + def self.def_OnShow(cmd=Proc.new) + ip_eval("proc ::tk::mac::OnShow {} { #{install_cmd(cmd)} }") + nil + end + + def self.def_ShowHelp(cmd=Proc.new) + ip_eval("proc ::tk::mac::ShowHelp {} { #{install_cmd(cmd)} }") + nil + end + + + # additional dialogs + def self.standardAboutPanel + tk_call('::tk::mac::standardAboutPanel') + nil + end + + + # system configuration + def self.useCompatibilityMetrics(mode) + tk_call('::tk::mac::useCompatibilityMetrics', mode) + nil + end + + def self.CGAntialiasLimit(limit) + tk_call('::tk::mac::CGAntialiasLimit', limit) + nil + end + + def self.antialiasedtext(num) + tk_call('::tk::mac::antialiasedtext', num) + nil + end + + def self.useThemedToplevel(mode) + tk_call('::tk::mac::useThemedToplevel', mode) + nil + end + +end + +class Tk::Mac::IconBitmap < TkImage + TkCommandNames = ['::tk::mac::iconBitmap'].freeze + + def self.new(width, height, keys) + if keys.kind_of?(Hash) + name = nil + if keys.key?(:imagename) + name = keys[:imagename] + elsif keys.key?('imagename') + name = keys['imagename'] + end + if name + if name.kind_of?(TkImage) + obj = name + else + name = _get_eval_string(name) + obj = nil + Tk_IMGTBL.mutex.synchronize{ + obj = Tk_IMGTBL[name] + } + end + if obj + if !(keys[:without_creating] || keys['without_creating']) + keys = _symbolkey2str(keys) + keys.delete('imagename') + keys.delete('without_creating') + obj.instance_eval{ + tk_call_without_enc('::tk::mac::iconBitmap', + @path, width, height, *hash_kv(keys, true)) + } + end + return obj + end + end + end + (obj = self.allocate).instance_eval{ + Tk_IMGTBL.mutex.synchronize{ + initialize(width, height, keys) + Tk_IMGTBL[@path] = self + } + } + obj + end + + def initialize(width, height, keys) + @path = nil + without_creating = false + if keys.kind_of?(Hash) + keys = _symbolkey2str(keys) + @path = keys.delete('imagename') + without_creating = keys.delete('without_creating') + end + unless @path + Tk_Image_ID.mutex.synchronize{ + @path = Tk_Image_ID.join(TkCore::INTERP._ip_id_) + Tk_Image_ID[1].succ! + } + end + unless without_creating + tk_call_without_enc('::tk::mac::iconBitmap', + @path, width, height, *hash_kv(keys, true)) + end + end +end diff --git a/jni/ruby/ext/tk/lib/tk/toplevel.rb b/jni/ruby/ext/tk/lib/tk/toplevel.rb new file mode 100644 index 0000000..30ef009 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/toplevel.rb @@ -0,0 +1,264 @@ +# +# tk/toplevel.rb : treat toplevel widget +# +require 'tk' +require 'tk/wm' +require 'tk/menuspec' + +class Tk::Toplevel<TkWindow + include Wm + include TkMenuSpec + + 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 __boolval_optkeys + super() << 'container' + end + private :__boolval_optkeys + + def __strval_optkeys + super() << 'screen' + end + private :__strval_optkeys + + def __val2ruby_optkeys # { key=>proc, ... } + super().update('menu'=>proc{|v| window(v)}) + end + private :__val2ruby_optkeys + + def __methodcall_optkeys # { key=>method, ... } + TOPLEVEL_METHODCALL_OPTKEYS + end + private :__methodcall_optkeys + + def _wm_command_option_chk(keys) + keys = {} unless keys + new_keys = {} + wm_cmds = {} + + conf_methods = _symbolkey2str(__methodcall_optkeys()) + + keys.each{|k,v| # k is a String + if conf_methods.key?(k) + wm_cmds[conf_methods[k]] = v + elsif 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 + keys['class'] = @classname = @classname.id + elsif @classname + @db_class = TkDatabaseClass.new(@classname) + keys['class'] = @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 + keys['class'] = @classname = @classname.id + elsif @classname + @db_class = TkDatabaseClass.new(@classname) + keys['class'] = @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 add_menu(menu_info, tearoff=false, opts=nil) + # See tk/menuspec.rb for menu_info. + # opts is a hash of default configs for all of cascade menus. + # Configs of menu_info can override it. + if tearoff.kind_of?(Hash) + opts = tearoff + tearoff = false + end + _create_menubutton(self, menu_info, tearoff, opts) + end + + def add_menubar(menu_spec, tearoff=false, opts=nil) + # See tk/menuspec.rb for menu_spec. + # opts is a hash of default configs for all of cascade menus. + # Configs of menu_spec can override it. + menu_spec.each{|info| add_menu(info, tearoff, opts)} + self.menu + end + + def self.database_class + if self == WidgetClassNames[WidgetClassName] || self.name == '' + self + else + TkDatabaseClass.new(self.name) + end + end + def self.database_classname + self.database_class.name + end + + def self.bind(*args, &b) + if self == WidgetClassNames[WidgetClassName] || self.name == '' + super(*args, &b) + else + TkDatabaseClass.new(self.name).bind(*args, &b) + end + end + def self.bind_append(*args, &b) + if self == WidgetClassNames[WidgetClassName] || self.name == '' + super(*args, &b) + else + TkDatabaseClass.new(self.name).bind_append(*args, &b) + 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 + +#TkToplevel = Tk::Toplevel unless Object.const_defined? :TkToplevel +#Tk.__set_toplevel_aliases__(:Tk, Tk::Toplevel, :TkToplevel) +Tk.__set_loaded_toplevel_aliases__('tk/toplevel.rb', :Tk, Tk::Toplevel, + :TkToplevel) diff --git a/jni/ruby/ext/tk/lib/tk/ttk_selector.rb b/jni/ruby/ext/tk/lib/tk/ttk_selector.rb new file mode 100644 index 0000000..cc9e992 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/ttk_selector.rb @@ -0,0 +1,98 @@ +# +# ttk_selector +# +###################################### +# toplevel classes/modules +module Tk + @TOPLEVEL_ALIAS_TABLE[:Ttk] = { + :TkButton => 'tkextlib/tile/tbutton', + + :TkCheckbutton => 'tkextlib/tile/tcheckbutton', + :TkCheckButton => 'tkextlib/tile/tcheckbutton', + + # :TkDialog => 'tkextlib/tile/dialog', + + :TkEntry => 'tkextlib/tile/tentry', + + :TkCombobox => 'tkextlib/tile/tcombobox', + + :TkFrame => 'tkextlib/tile/tframe', + + :TkLabel => 'tkextlib/tile/tlabel', + + :TkLabelframe => 'tkextlib/tile/tlabelframe', + :TkLabelFrame => 'tkextlib/tile/tlabelframe', + + :TkMenubutton => 'tkextlib/tile/tmenubutton', + :TkMenuButton => 'tkextlib/tile/tmenubutton', + + :TkNotebook => 'tkextlib/tile/tnotebook', + + # :TkPaned => 'tkextlib/tile/tpaned', + :TkPanedwindow => 'tkextlib/tile/tpaned', + :TkPanedWindow => 'tkextlib/tile/tpaned', + + :TkProgressbar => 'tkextlib/tile/tprogressbar', + + :TkRadiobutton => 'tkextlib/tile/tradiobutton', + :TkRadioButton => 'tkextlib/tile/tradiobutton', + + :TkScale => 'tkextlib/tile/tscale', + # :TkProgress => 'tkextlib/tile/tscale', + + :TkScrollbar => 'tkextlib/tile/tscrollbar', + :TkXScrollbar => 'tkextlib/tile/tscrollbar', + :TkYScrollbar => 'tkextlib/tile/tscrollbar', + + :TkSeparator => 'tkextlib/tile/tseparator', + + :TkSizeGrip => 'tkextlib/tile/sizegrip', + :TkSizegrip => 'tkextlib/tile/sizegrip', + + # :TkSquare => 'tkextlib/tile/tsquare', + + :TkTreeview => 'tkextlib/tile/treeview', + } + + # @TOPLEVEL_ALIAS_TABLE[:Tile] = @TOPLEVEL_ALIAS_TABLE[:Ttk] + Tk.__create_widget_set__(:Tile, :Ttk) + + ############################################ + # depend on the version of Tcl/Tk + major, minor, type, patchlevel = TclTkLib.get_version + + # ttk::spinbox is supported on Tcl/Tk8.6b1 or later + if ([major,minor,type,patchlevel] <=> + [8,6,TclTkLib::RELEASE_TYPE::BETA,1]) >= 0 + @TOPLEVEL_ALIAS_TABLE[:Ttk].update( + :TkSpinbox => 'tkextlib/tile/tspinbox' + ) + end + + ################################################ + # register some Ttk widgets as default + # (Ttk is a standard library on Tcl/Tk8.5+) + @TOPLEVEL_ALIAS_TABLE[:Ttk].each{|sym, file| + #unless Tk::TOPLEVEL_ALIASES.autoload?(sym) || Tk::TOPLEVEL_ALIASES.const_defined?(sym) + # @TOPLEVEL_ALIAS_OWNER[sym] = :Ttk + # Tk::TOPLEVEL_ALIASES.autoload(sym, file) + #end + Tk.__regist_toplevel_aliases__(:Ttk, file, sym) + } + + ################################################ + + # @TOPLEVEL_ALIAS_SETUP_PROC[:Tile] = + # @TOPLEVEL_ALIAS_SETUP_PROC[:Ttk] = proc{|mod| + # unless Tk.autoload?(:Tile) || Tk.const_defined?(:Tile) + # Object.autoload :Ttk, 'tkextlib/tile' + # Tk.autoload :Tile, 'tkextlib/tile' + # end + # } + Tk.__toplevel_alias_setup_proc__(:Ttk, :Tile){|mod| + unless Tk.autoload?(:Tile) || Tk.const_defined?(:Tile) + Object.autoload :Ttk, 'tkextlib/tile' + Tk.autoload :Tile, 'tkextlib/tile' + end + } +end diff --git a/jni/ruby/ext/tk/lib/tk/txtwin_abst.rb b/jni/ruby/ext/tk/lib/tk/txtwin_abst.rb new file mode 100644 index 0000000..540f806 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/txtwin_abst.rb @@ -0,0 +1,39 @@ +# +# tk/txtwin_abst.rb : TkTextWin abstruct class +# +require 'tk' + +class TkTextWin<TkWindow + TkCommandNames = [].freeze + #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 diff --git a/jni/ruby/ext/tk/lib/tk/validation.rb b/jni/ruby/ext/tk/lib/tk/validation.rb new file mode 100644 index 0000000..0ebd5c5 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/validation.rb @@ -0,0 +1,397 @@ +# +# tk/validation.rb - validation support module for entry, spinbox, and so on +# +require 'tk' + +module Tk + module ValidateConfigure + def self.__def_validcmd(scope, klass, keys=nil) + keys = klass._config_keys unless keys + keys.each{|key| + eval("def #{key}(*args, &b) + __validcmd_call(#{klass.name}, '#{key}', *args, &b) + end", scope) + } + end + + def __validcmd_call(klass, key, *args, &b) + return cget(key) if args.empty? && !b + + cmd = (b)? proc(&b) : args.shift + + if cmd.kind_of?(klass) + configure(key, cmd) + elsif !args.empty? + configure(key, [cmd, args]) + else + configure(key, cmd) + end + end + + def __validation_class_list + # maybe need to override + [] + end + + def __get_validate_key2class + k2c = {} + __validation_class_list.each{|klass| + klass._config_keys.each{|key| + k2c[key.to_s] = klass + } + } + k2c + end + + def __conv_vcmd_on_hash_kv(keys) + key2class = __get_validate_key2class + + keys = _symbolkey2str(keys) + key2class.each{|key, klass| + if keys[key].kind_of?(Array) + cmd, *args = keys[key] + #keys[key] = klass.new(cmd, args.join(' ')) + keys[key] = klass.new(cmd, *args) + # elsif keys[key].kind_of?(Proc) || keys[key].kind_of?(Method) + elsif TkComm._callback_entry?(keys[key]) + keys[key] = klass.new(keys[key]) + end + } + keys + end + + def create_self(keys) + super(__conv_vcmd_on_hash_kv(keys)) + end + private :create_self + + def configure(slot, value=TkComm::None) + if slot.kind_of?(Hash) + super(__conv_vcmd_on_hash_kv(slot)) + else + super(__conv_vcmd_on_hash_kv(slot=>value)) + end + self + end +=begin + def configure(slot, value=TkComm::None) + key2class = __get_validate_key2class + + if slot.kind_of?(Hash) + slot = _symbolkey2str(slot) + key2class.each{|key, klass| + if slot[key].kind_of?(Array) + cmd, *args = slot[key] + slot[key] = klass.new(cmd, args.join(' ')) + elsif slot[key].kind_of?(Proc) || slot[key].kind_of?(Method) + slot[key] = klass.new(slot[key]) + end + } + super(slot) + + else + slot = slot.to_s + if (klass = key2class[slot]) + if value.kind_of?(Array) + cmd, *args = value + value = klass.new(cmd, args.join(' ')) + elsif value.kind_of?(Proc) || value.kind_of?(Method) + value = klass.new(value) + end + end + super(slot, value) + end + + self + end +=end + end + + module ItemValidateConfigure + def self.__def_validcmd(scope, klass, keys=nil) + keys = klass._config_keys unless keys + keys.each{|key| + eval("def item_#{key}(id, *args, &b) + __item_validcmd_call(#{klass.name}, '#{key}', id, *args, &b) + end", scope) + } + end + + def __item_validcmd_call(tagOrId, klass, key, *args, &b) + return itemcget(tagid(tagOrId), key) if args.empty? && !b + + cmd = (b)? proc(&b) : args.shift + + if cmd.kind_of?(klass) + itemconfigure(tagid(tagOrId), key, cmd) + elsif !args.empty? + itemconfigure(tagid(tagOrId), key, [cmd, args]) + else + itemconfigure(tagid(tagOrId), key, cmd) + end + end + + def __item_validation_class_list(id) + # maybe need to override + [] + end + + def __get_item_validate_key2class(id) + k2c = {} + __item_validation_class_list(id).each{|klass| + klass._config_keys.each{|key| + k2c[key.to_s] = klass + } + } + end + + def __conv_item_vcmd_on_hash_kv(keys) + key2class = __get_item_validate_key2class(tagid(tagOrId)) + + keys = _symbolkey2str(keys) + key2class.each{|key, klass| + if keys[key].kind_of?(Array) + cmd, *args = keys[key] + #keys[key] = klass.new(cmd, args.join(' ')) + keys[key] = klass.new(cmd, *args) + # elsif keys[key].kind_of?(Proc) || keys[key].kind_of?(Method) + elsif TkComm._callback_entry?(keys[key]) + keys[key] = klass.new(keys[key]) + end + } + keys + end + + def itemconfigure(tagOrId, slot, value=TkComm::None) + if slot.kind_of?(Hash) + super(__conv_item_vcmd_on_hash_kv(slot)) + else + super(__conv_item_vcmd_on_hash_kv(slot=>value)) + end + self + end +=begin + def itemconfigure(tagOrId, slot, value=TkComm::None) + key2class = __get_item_validate_key2class(tagid(tagOrId)) + + if slot.kind_of?(Hash) + slot = _symbolkey2str(slot) + key2class.each{|key, klass| + if slot[key].kind_of?(Array) + cmd, *args = slot[key] + slot[key] = klass.new(cmd, args.join(' ')) + elsif slot[key].kind_of?(Proc) || slot[key].kind_of?(Method) + slot[key] = klass.new(slot[key]) + end + } + super(slot) + + else + slot = slot.to_s + if (klass = key2class[slot]) + if value.kind_of?(Array) + cmd, *args = value + value = klass.new(cmd, args.join(' ')) + elsif value.kind_of?(Proc) || value.kind_of?(Method) + value = klass.new(value) + end + end + super(slot, value) + end + + self + end +=end + end +end + +class TkValidateCommand + include TkComm + extend TkComm + + 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 + enc = ((Tk.encoding)? Tk.encoding : Tk.encoding_system) + 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 + ] + +=begin + # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) + KEY_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) + end + inf + } + + PROC_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + end + inf + } +=end + + _setup_subst_table(KEY_TBL, PROC_TBL); + + # + # NOTE: The order of parameters which passed to callback procedure is + # <extra_arg>, <extra_arg>, ... , <subst_arg>, <subst_arg>, ... + # + + #def self._get_extra_args_tbl + # # return an array of convert procs + # [] + #end + + def self.ret_val(val) + (val)? '1': '0' + end + end + + ############################################### + + def self._config_keys + # array of config-option key (string or symbol) + ['vcmd', 'validatecommand', 'invcmd', 'invalidcommand'] + end + + def _initialize_for_cb_class(klass, cmd = Proc.new, *args) + extra_args_tbl = klass._get_extra_args_tbl + + if args.compact.size > 0 + args.map!{|arg| klass._sym2subst(arg)} + args = args.join(' ') + keys = klass._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| + ex_args = [] + extra_args_tbl.reverse_each{|conv| ex_args << conv.call(arg.pop)} + klass.ret_val(cmd.call( + *(ex_args.concat(klass.scan_args(keys, arg))) + )) + }) + ' ' + args + end + else + keys, args = klass._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| + ex_args = [] + extra_args_tbl.reverse_each{|conv| ex_args << conv.call(arg.pop)} + klass.ret_val(cmd.call( + *(ex_args << klass.new(*klass.scan_args(keys, arg))) + )) + }) + ' ' + args + end + end + end + + def initialize(cmd = Proc.new, *args) + _initialize_for_cb_class(self.class::ValidateArgs, cmd, *args) + end + + def to_eval + @id + end +end + +module TkValidation + include Tk::ValidateConfigure + + class ValidateCmd < TkValidateCommand + module Action + Insert = 1 + Delete = 0 + Others = -1 + Focus = -1 + Forced = -1 + Textvariable = -1 + TextVariable = -1 + end + end + + ##################################### + + def __validation_class_list + super() << ValidateCmd + end + + Tk::ValidateConfigure.__def_validcmd(binding, ValidateCmd) + +=begin + 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 +=end +# def validatecommand(*args, &b) +# __validcmd_call(ValidateCmd, 'validatecommand', *args, &b) +# end +# alias vcmd validatecommand + +=begin + 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 +=end +# def invalidcommand(*args, &b) +# __validcmd_call(ValidateCmd, 'invalidcommand', *args, &b) +# end +# alias invcmd invalidcommand +end diff --git a/jni/ruby/ext/tk/lib/tk/variable.rb b/jni/ruby/ext/tk/lib/tk/variable.rb new file mode 100644 index 0000000..0487b03 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/variable.rb @@ -0,0 +1,1799 @@ +# +# 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, TkUtil.untrust("00000")]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + TkCore::INTERP.init_ip_env{ + TkVar_CB_TBL.mutex.synchronize{ TkVar_CB_TBL.clear } + TkVar_ID_TBL.mutex.synchronize{ TkVar_ID_TBL.clear } + } + + major, minor, type, patchlevel = TclTkLib.get_version + USE_OLD_TRACE_OPTION_STYLE = (major < 8) || (major == 8 && minor < 4) + + #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(id, name1, name2, op) + #name1,name2,op = tk_split_list(args) + #name1,name2,op = tk_split_simplelist(args) + if cb_obj = TkVar_CB_TBL[id] + #_get_eval_string(TkVar_CB_TBL[name1].trace_callback(name2,op)) + begin + _get_eval_string(cb_obj.trace_callback(name2, op)) + rescue SystemExit + exit(0) + rescue Interrupt + exit!(1) + 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 >-------" + if TkCore::WITH_ENCODING + msg.force_encoding('utf-8') + else + msg.instance_variable_set(:@encoding, 'utf-8') + end + 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 self.new_hash(val = {}) + if val.kind_of?(Hash) + self.new(val) + else + fail ArgumentError, 'Hash is expected' + end + end + + # + # default_value is available only when the variable is an assoc array. + # + def default_value(val=nil, &b) + if b + @def_default = :proc + @default_val = proc(&b) + else + @def_default = :val + @default_val = val + end + self + end + def set_default_value(val) + @def_default = :val + @default_val = val + self + end + alias default_value= set_default_value + def default_proc(cmd = Proc.new) + @def_default = :proc + @default_val = cmd + self + end + + def undef_default + @default_val = nil + @def_default = false + self + end + + def default_value_type + @type + end + def default_element_value_type(idxs) + if idxs.kind_of?(Array) + index = idxs.collect{|idx| _get_eval_string(idx, true)}.join(',') + else + index = _get_eval_string(idxs, true) + end + @element_type[index] + end + + def _set_default_value_type_core(type, idxs) + if type.kind_of?(Class) + if type == NilClass + type = nil + elsif type == Numeric + type = :numeric + elsif type == TrueClass || type == FalseClass + type = :bool + elsif type == String + type = :string + elsif type == Symbol + type = :symbol + elsif type == Array + type = :list + elsif type <= TkVariable + type = :variable + elsif type <= TkWindow + type = :window + elsif TkComm._callback_entry_class?(type) + type = :procedure + else + type = nil + end + else + case(type) + when nil + type = nil + when :numeric, 'numeric' + type = :numeric + when true, false, :bool, 'bool' + type = :bool + when :string, 'string' + type = :string + when :symbol, 'symbol' + type = :symbol + when :list, 'list' + type = :list + when :numlist, 'numlist' + type = :numlist + when :variable, 'variable' + type = :variable + when :window, 'window' + type = :window + when :procedure, 'procedure' + type = :procedure + else + return _set_default_value_type_core(type.class, idxs) + end + end + if idxs + if idxs.kind_of?(Array) + index = idxs.collect{|idx| _get_eval_string(idx, true)}.join(',') + else + index = _get_eval_string(idxs, true) + end + @element_type[index] = type + else + @type = type + end + type + end + private :_set_default_value_type_core + + def set_default_value_type(type) + _set_default_value_type_core(type, nil) + self + end + alias default_value_type= set_default_value_type + + def set_default_element_value_type(idxs, type) + _set_default_value_type_core(type, idxs) + self + end + + def _to_default_type(val, idxs = nil) + if idxs + if idxs.kind_of?(Array) + index = idxs.collect{|idx| _get_eval_string(idx, true)}.join(',') + else + index = _get_eval_string(idxs, true) + end + type = @element_type[index] + else + type = @type + end + return val unless type + if val.kind_of?(Hash) + val.keys.each{|k| val[k] = _to_default_type(val[k], idxs) } + val + else + begin + case(type) + when :numeric + number(val) + when :bool + TkComm.bool(val) + when :string + val + when :symbol + val.intern + when :list + tk_split_simplelist(val) + when :numlist + tk_split_simplelist(val).collect!{|v| number(v)} + when :variable + TkVarAccess.new(val) + when :window + TkComm.window(val) + when :procedure + TkComm.procedure(val) + else + val + end + rescue + val + end + end + end + private :_to_default_type + + def _to_default_element_type(idxs, val) + _to_default_type(val, idxs) + end + private :_to_default_element_type + + def initialize(val="", type=nil) + # @id = Tk_VARIABLE_ID.join('') + begin + Tk_VARIABLE_ID.mutex.synchronize{ + @id = Tk_VARIABLE_ID.join(TkCore::INTERP._ip_id_) + Tk_VARIABLE_ID[1].succ! + } + end until INTERP._invoke_without_enc('info', 'globals', @id).empty? + + TkVar_ID_TBL.mutex.synchronize{ + TkVar_ID_TBL[@id] = self + } + + @var = @id + @elem = nil + + @def_default = false + @default_val = nil + + @trace_var = nil + @trace_elem = nil + @trace_opts = nil + + @type = nil + var = self + @element_type = Hash.new{|k,v| var.default_value_type } + + self.default_value_type = type + + # teach Tk-ip that @id is global var + INTERP._invoke_without_enc('global', @id) + #INTERP._invoke('global', @id) + + # create and init + if val.kind_of?(Hash) + # assoc-array variable + self[''] = 0 + self.clear + end + 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 ref(*idxs) + # "#{@id}(#{idxs.collect{|idx| _get_eval_string(idx)}.join(',')})" + TkVarAccess.new("#{@id}(#{idxs.collect{|idx| _get_eval_string(idx)}.join(',')})") + end + + def is_hash? + #ITNERP._eval("global #{@id}; array exist #{@id}") == '1' + INTERP._invoke_without_enc('global', @id) + # INTERP._invoke_without_enc('array', 'exist', @id) == '1' + TkComm.bool(INTERP._invoke_without_enc('array', 'exist', @id)) + end + + def is_scalar? + ! is_hash? + end + + def exist?(*elems) + INTERP._invoke_without_enc('global', @id) + if elems.empty? + TkComm.bool(tk_call('info', 'exist', @id)) + else + # array + index = elems.collect{|idx| _get_eval_string(idx, true)}.join(',') + TkComm.bool(tk_call('info', 'exist', "#{@id}")) && + TkComm.bool(tk_call('info', 'exist', "#{@id}(#{index})")) + end + 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}")) + INTERP._invoke_without_enc('global', @id) + #tk_split_simplelist(INTERP._fromUTF8(INTERP._invoke_without_enc('array', 'names', @id))) + tk_split_simplelist(INTERP._invoke_without_enc('array', 'names', @id), + false, true) + end + + def size + INTERP._invoke_without_enc('global', @id) + TkComm.number(INTERP._invoke_without_enc('array', 'size', @id)) + end + + def clear + if (is_scalar?) + fail RuntimeError, 'cannot clear a scalar variable' + end + keys.each{|k| unset(k)} + self + end + + def update(hash) + if (is_scalar?) + fail RuntimeError, 'cannot update a scalar variable' + end + hash.each{|k,v| self[k] = v} + self + 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' + INTERP._invoke_without_enc('global', @id) + # if INTERP._invoke('array', 'exist', @id) == '1' + if TkComm.bool(INTERP._invoke('array', 'exist', @id)) + #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) + val = val._value if !@type && @type != :variable && val.kind_of?(TkVariable) + if val.kind_of?(Hash) + self.clear + 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) +=begin + 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 +=end +# _fromUTF8(INTERP._set_global_var(@id, array2tk_list(val, true))) + 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 _element_value(*idxs) + index = idxs.collect{|idx| _get_eval_string(idx, true)}.join(',') + begin + _fromUTF8(INTERP._get_global_var2(@id, index)) + rescue => e + case @def_default + when :proc + @default_val.call(self, *idxs) + when :val + @default_val + else + fail e + end + end + #_fromUTF8(INTERP._get_global_var2(@id, 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 []=(*args) + val = args.pop + type = default_element_value_type(args) + val = val._value if !type && type != :variable && val.kind_of?(TkVariable) + index = args.collect{|idx| _get_eval_string(idx, true)}.join(',') + _fromUTF8(INTERP._set_global_var2(@id, index, _get_eval_string(val, true))) + #_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(*elems) + if elems.empty? + INTERP._unset_global_var(@id) + else + index = elems.collect{|idx| _get_eval_string(idx, true)}.join(',') + INTERP._unset_global_var2(@id, index) + 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) + val = val._value if !@type && @type != :variable && val.kind_of?(TkVariable) + 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, true))} + #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, true)}.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 _element_value(*idxs) + index = idxs.collect{|idx| _get_eval_string(idx)}.join(',') + begin + INTERP._eval(Kernel.format('global %s; set %s(%s)', @id, @id, index)) + rescue => e + case @def_default + when :proc + @default_val.call(self, *idxs) + when :val + @default_val + else + fail e + end + end + #INTERP._eval(Kernel.format('global %s; set %s(%s)', @id, @id, 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 []=(*args) + val = args.pop + type = default_element_value_type(args) + val = val._value if !type && type != :variable && val.kind_of?(TkVariable) + index = args.collect{|idx| _get_eval_string(idx)}.join(',') + INTERP._eval(Kernel.format('global %s; set %s(%s) %s', @id, @id, + index, _get_eval_string(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(*elems) + if elems.empty? + INTERP._eval(Kernel.format('global %s; unset %s', @id, @id)) + #INTERP._eval(Kernel.format('unset %s', @id)) + #INTERP._eval('unset ' + @id) + else + index = elems.collect{|idx| _get_eval_string(idx, true)}.join(',') + INTERP._eval(Kernel.format('global %s; unset %s(%s)', @id, @id, index)) + #INTERP._eval(Kernel.format('global %s; unset %s(%s)', + # @id, @id, _get_eval_string(elem))) + #INTERP._eval(Kernel.format('unset %s(%s)', @id, tk_tcl2ruby(elem))) + #INTERP._eval('unset ' + @id + '(' + _get_eval_string(elem) + ')') + end + end + alias remove unset + +end + + protected :_value, :_element_value + + def value + _to_default_type(_value) + end + + def [](*idxs) + _to_default_element_type(idxs, _element_value(*idxs)) + end + + def set_value(val) + self.value = val + self + end + + def to_hash + hash = {} + self.keys.each{|k| + hash[k] = self[k] + } + hash + end + + def set_element_value(idxs, val) + if idxs.kind_of?(Array) + self[*idxs]=val + else + self[idxs]=val + end + self + end + + def set_value_type(val) + self.default_value_type = val.class + self.value = val + self + end + + alias value_type= set_value_type + + def set_element_value_type(idxs, val) + self.set_default_element_value_type(idxs, val.class) + if idxs.kind_of?(Array) + self[*idxs]=val + else + self[idxs]=val + end + self + end + + def numeric + number(_value) + end + def numeric_element(*idxs) + number(_element_value(*idxs)) + end + def set_numeric(val) + case val + when Numeric + self.value=(val) + when TkVariable + self.value=(val.numeric) + else + raise ArgumentError, "Numeric is expected" + end + self + end + alias numeric= set_numeric + def set_numeric_element(idxs, val) + case val + when Numeric + val + when TkVariable + val = val.numeric + else + raise ArgumentError, "Numeric is expected" + end + if idxs.kind_of?(Array) + self[*idxs]=val + else + self[idxs]=val + end + self + end + def set_numeric_type(val) + @type = :numeric + self.numeric=(val) + self + end + alias numeric_type= set_numeric_type + def set_numeric_element_type(idxs, val) + self.set_default_element_value_type(idxs, :numeric) + self.set_numeric_element(idxs, val) + end + + def bool + TkComm.bool(_value) +=begin + # see Tcl_GetBoolean man-page + case _value.downcase + when '0', 'false', 'no', 'off' + false + else + true + end +=end + end + def bool_element(*idxs) + TkComm.bool(_element_value(*idxs)) + end + def set_bool(val) + if ! val + self.value = '0' + else + case val.to_s.downcase + when 'false', '0', 'no', 'off' + self.value = '0' + else + self.value = '1' + end + end + self + end + alias bool= set_bool + def set_bool_element(idxs, val) + if ! val + val = '0' + else + case val.to_s.downcase + when 'false', '0', 'no', 'off' + val = '0' + else + val = '1' + end + end + if idxs.kind_of?(Array) + self[*idxs]=val + else + self[idxs]=val + end + self + end + def set_bool_type(val) + @type = :bool + self.bool=(val) + self + end + alias bool_type= set_bool_type + def set_bool_element_type(idxs, val) + self.set_default_element_value_type(idxs, :bool) + self.set_bool_element(idxs, val) + end + + def variable + # keeps a Tcl's variable name + TkVarAccess.new(self._value) + end + def variable_element(*idxs) + TkVarAccess.new(_element_value(*idxs)) + end + def set_variable(var) + var = var.id if var.kind_of?(TkVariable) + self.value = var + self + end + alias variable= set_variable + def set_variable_element(idxs, var) + var = var.id if var.kind_of?(TkVariable) + if idxs.kind_of?(Array) + self[*idxs]=var + else + self[idxs]=var + end + self + end + def set_variable_type(var) + @type = :variable + var = var.id if var.kind_of?(TkVariable) + self.value = var + self + end + alias variable_type= set_variable_type + def set_variable_element_type(idxs, var) + self.set_default_element_value_type(idxs, :variable) + self.set_variable_element(idxs, var) + end + + def window + TkComm.window(self._value) + end + def window_element(*idxs) + TkComm.window(_element_value(*idxs)) + end + def set_window(win) + win = win._value if win.kind_of?(TkVariable) + self.value = win + self + end + alias window= set_window + def set_window_element(idxs, win) + win = win._value if win.kind_of?(TkVariable) + if idxs.kind_of?(Array) + self[*idxs]=win + else + self[idxs]=win + end + self + end + def set_window_type(win) + @type = :window + self.window=(win) + self + end + alias window_type= set_window_type + def set_window_element_type(idxs, win) + self.set_default_element_value_type(idxs, :window) + self.set_window_element(idxs, win) + end + + def procedure + TkComm.procedure(self._value) + end + def procedure_element(*idxs) + TkComm.procedure(_element_value(*idxs)) + end + def set_procedure(cmd) + self.value = cmd + self + end + alias procedure= set_procedure + def set_procedure_element(idxs, cmd) + cmd = cmd._value if cmd.kind_of?(TkVariable) + if idxs.kind_of?(Array) + self[*idxs]=cmd + else + self[idxs]=cmd + end + self + end + def set_procedure_type(cmd) + @type = :procedure + self.procedure=(cmd) + self + end + alias procedure_type= set_procedure_type + def set_procedure_element_type(idxs, cmd) + self.set_default_element_value_type(idxs, :procedure) + self.set_proceure_element(idxs, cmd) + end + + def to_proc + cmd = self.procedure + if cmd.respond_to?(:call) + cmd + else + # cmd is a String + cmd.to_sym.to_proc + end + end + + def to_i + number(_value).to_i + end + alias to_int to_i + def element_to_i(*idxs) + number(_element_value(*idxs)).to_i + end + + def to_f + number(_value).to_f + end + def element_to_f(*idxs) + number(_element_value(*idxs)).to_f + end + + def to_s + #string(value).to_s + _value + end + alias string to_s + alias to_str to_s + def element_to_s(*idxs) + _element_value(*idxs) + end + def string_element(*idxs) + _element_value(*idxs) + end + def set_string(val) + val = val._value if val.kind_of?(TkVariable) + self.value=val + self + end + alias string= set_string + def set_string_element(idxs, val) + val = val._value if val.kind_of?(TkVariable) + if idxs.kind_of?(Array) + self[*idxs]=val + else + self[idxs]=val + end + self + end + def set_string_type(val) + @type = :string + self.string=(val) + self + end + alias string_type= set_string_type + def set_string_element_type(idxs, val) + self.set_default_element_value_type(idxs, :string) + self.set_string_element(idxs, val) + end + + def to_sym + _value.intern + end + alias symbol to_sym + def element_to_sym(*idxs) + _element_value(*idxs).intern + end + alias symbol_element element_to_sym + def set_symbol(val) + val = val._value if val.kind_of?(TkVariable) + self.value=val + self + end + alias symbol= set_symbol + def set_symbol_element(idxs, val) + val = val._value if val.kind_of?(TkVariable) + if idxs.kind_of?(Array) + self[*idxs]=val + else + self[idxs]=val + end + self + end + def set_symbol_type(val) + @type = :symbol + self.value=(val) + self + end + alias symbol_type= set_symbol_type + def set_symbol_element_type(idxs, val) + self.set_default_element_value_type(idxs, :symbol) + self.set_symbol_element(idxs, val) + end + + def list + #tk_split_list(value) + tk_split_simplelist(_value) + end + alias to_a list + alias to_ary list + def list_element(*idxs) + tk_split_simplelist(_element_value(*idxs)) + end + alias element_to_a list_element + + def numlist + list.collect!{|val| number(val)} + end + def numlist_element(*idxs) + list_element(*idxs).collect!{|val| number(val)} + end + + def set_list(val) + case val + when Array + self.value=(val) + when TkVariable + self.value=(val.list) + else + raise ArgumentError, "Array is expected" + end + self + end + alias list= set_list + + alias set_numlist set_list + alias numlist= set_numlist + + def set_list_element(idxs, val) + case val + when Array + val + when TkVariable + val = val.list + else + raise ArgumentError, "Array is expected" + end + if idxs.kind_of?(Array) + self[*idxs]=val + else + self[idxs]=val + end + self + end + alias set_numlist_element set_list_element + + def set_list_type(val) + @type = :list + self.list=(val) + self + end + alias list_type= set_list_type + def set_list_element_type(idxs, val) + self.set_default_element_value_type(idxs, :list) + self.set_list_element(idxs, val) + end + def set_numlist_type(val) + @type = :numlist + self.numlist=(val) + self + end + alias numlist_type= set_numlist_type + def set_numlist_element_type(idxs, val) + self.set_default_element_value_type(idxs, :numlist) + self.set_numlist_element(idxs, val) + end + + def lappend(*elems) + tk_call('lappend', @id, *elems) + self + end + def element_lappend(idxs, *elems) + if idxs.kind_of?(Array) + idxs = idxs.collect{|idx| _get_eval_string(idx, true)}.join(',') + end + tk_call('lappend', "#{@id}(#{idxs})", *elems) + self + end + + def lindex(idx) + tk_call('lindex', self._value, idx) + end + alias lget lindex + def element_lindex(elem_idxs, idx) + if elem_idxs.kind_of?(Array) + val = _element_value(*elem_idxs) + else + val = _element_value(elem_idxs) + end + tk_call('lindex', val, idx) + end + alias element_lget element_lindex + + def lget_i(idx) + number(lget(idx)).to_i + end + def element_lget_i(elem_idxs, idx) + number(element_lget(elem_idxs, idx)).to_i + end + + def lget_f(idx) + number(lget(idx)).to_f + end + def element_lget_f(elem_idxs, idx) + number(element_lget(elem_idxs, idx)).to_f + end + + def lset(idx, val) + tk_call('lset', @id, idx, val) + self + end + def element_lset(elem_idxs, idx, val) + if elem_idxs.kind_of?(Array) + idxs = elem_idxs.collect{|i| _get_eval_string(i, true)}.join(',') + end + tk_call('lset', "#{@id}(#{idxs})", idx, val) + self + 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 Numeric + [other, self.numeric] + when Array + [other, self.to_a] + else + [other, self._value] + end + end + + def +@ + self.numeric + end + def -@ + -(self.numeric) + 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) + num_or_str(self._value) * other + #begin + # number(self._value) * other + #rescue + # self._value * other + #end + end + def /(other) + number(self._value) / other + end + def %(other) + num_or_str(self._value) % 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) + self._value == other._value + 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 + # false if self is not an assoc array + self._value == other + else + # false + self._value == _get_eval_string(other) + end + end + + def ===(other) + if other.kind_of?(TkVariable) + self.id == other.id + else + super + 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 + elsif other.kind_of?(Numeric) + begin + return self.numeric <=> other + rescue + return self._value <=> other.to_s + end + elsif other.kind_of?(Array) + return self.list <=> other + 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 _check_trace_opt(opts) + if opts.kind_of?(Array) + opt_str = opts.map{|s| s.to_s}.join(' ') + else + opt_str = opts.to_s + end + + fail ArgumentError, 'null trace option' if opt_str.empty? + + if opt_str =~ /[^arwu\s]/ + # new format (Tcl/Tk8.4+?) + if opts.kind_of?(Array) + opt_ary = opts.map{|opt| opt.to_s.strip} + else + opt_ary = opt_str.split(/\s+|\|/) + opt_ary.delete('') + end + if USE_OLD_TRACE_OPTION_STYLE + opt_ary.uniq.map{|opt| + case opt + when 'array' + 'a' + when 'read' + 'r' + when 'write' + 'w' + when 'unset' + 'u' + else + fail ArgumentError, "unsupported trace option '#{opt}' on Tcl/Tk#{Tk::TCL_PATCHLEVEL}" + end + }.join + else + opt_ary + end + else + # old format + opt_ary = opt_str.delete('^arwu').split(//).uniq + if USE_OLD_TRACE_OPTION_STYLE + opt_ary.join + else + opt_ary.map{|c| + case c + when 'a' + 'array' + when 'r' + 'read' + when 'w' + 'write' + when 'u' + 'unset' + end + } + end + end + end + private :_check_trace_opt + + def trace(opts, cmd = Proc.new) + opts = _check_trace_opt(opts) + (@trace_var ||= []).unshift([opts,cmd]) + + if @trace_opts == nil + TkVar_CB_TBL[@id] = self + @trace_opts = opts.dup + if USE_OLD_TRACE_OPTION_STYLE + Tk.tk_call_without_enc('trace', 'variable', + @id, @trace_opts, 'rb_var ' << @id) + else + Tk.tk_call_without_enc('trace', 'add', 'variable', + @id, @trace_opts, 'rb_var ' << @id) + end + else + newopts = @trace_opts.dup + if USE_OLD_TRACE_OPTION_STYLE + opts.each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)} + if newopts != @trace_opts + Tk.tk_call_without_enc('trace', 'vdelete', + @id, @trace_opts, 'rb_var ' << @id) + @trace_opts.replace(newopts) + Tk.tk_call_without_enc('trace', 'variable', + @id, @trace_opts, 'rb_var ' << @id) + end + else + newopts |= opts + unless (newopts - @trace_opts).empty? + Tk.tk_call_without_enc('trace', 'remove', 'variable', + @id, @trace_opts, 'rb_var ' << @id) + @trace_opts.replace(newopts) + Tk.tk_call_without_enc('trace', 'add', 'variable', + @id, @trace_opts, 'rb_var ' << @id) + end + end + end + + self + end + + def trace_element(elem, opts, cmd = Proc.new) + if @elem + fail(RuntimeError, + "invalid for a TkVariable which denotes an element of Tcl's array") + end + + opts = _check_trace_opt(opts) + + ((@trace_elem ||= {})[elem] ||= []).unshift([opts,cmd]) + + if @trace_opts == nil + TkVar_CB_TBL[@id] = self + @trace_opts = opts.dup + if USE_OLD_TRACE_OPTION_STYLE + Tk.tk_call_without_enc('trace', 'add', 'variable', + @id, @trace_opts, 'rb_var ' << @id) + else + Tk.tk_call_without_enc('trace', 'variable', + @id, @trace_opts, 'rb_var ' << @id) + end + else + newopts = @trace_opts.dup + if USE_OLD_TRACE_OPTION_STYLE + opts.each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)} + if newopts != @trace_opts + Tk.tk_call_without_enc('trace', 'vdelete', + @id, @trace_opts, 'rb_var ' << @id) + @trace_opts.replace(newopts) + Tk.tk_call_without_enc('trace', 'variable', + @id, @trace_opts, 'rb_var ' << @id) + end + else + newopts |= opts + unless (newopts - @trace_opts).empty? + Tk.tk_call_without_enc('trace', 'remove', 'variable', + @id, @trace_opts, 'rb_var ' << @id) + @trace_opts.replace(newopts) + Tk.tk_call_without_enc('trace', 'add', 'variable', + @id, @trace_opts, 'rb_var ' << @id) + end + end + end + + self + end + + def trace_info + return [] unless @trace_var + @trace_var.dup + end + alias trace_vinfo trace_info + + def trace_info_for_element(elem) + if @elem + fail(RuntimeError, + "invalid for a TkVariable which denotes an element of Tcl's array") + end + return [] unless @trace_elem + return [] unless @trace_elem[elem] + @trace_elem[elem].dup + end + alias trace_vinfo_for_element trace_info_for_element + + def trace_remove(opts,cmd) + return self unless @trace_var.kind_of? Array + + opts = _check_trace_opt(opts) + + idx = -1 + if USE_OLD_TRACE_OPTION_STYLE + newopts = '' + @trace_var.each_with_index{|e, i| + if idx < 0 && e[1] == cmd + diff = false + ['a', 'r', 'w', 'u'].each{|c| + break if (diff = e[0].index(c) ^ opts.index(c)) + } + unless diff + #find + idx = i + next + end + end + e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)} + } + else + newopts = [] + @trace_var.each_with_index{|e, i| + if idx < 0 && e[1] == cmd && + e[0].size == opts.size && (e[0] - opts).empty? + # find + idx = i + next + end + newopts |= e[0] + } + end + + if idx >= 0 + @trace_var.delete_at(idx) + else + return self + end + + (@trace_elem ||= {}).each{|elem| + @trace_elem[elem].each{|e| + if USE_OLD_TRACE_OPTION_STYLE + e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)} + else + newopts |= e[0] + end + } + } + + if USE_OLD_TRACE_OPTION_STYLE + diff = false + @trace_opts.each_byte{|c| break if (diff = ! newopts.index(c))} + if diff + Tk.tk_call_without_enc('trace', 'vdelete', + @id, @trace_opts, 'rb_var ' << @id) + @trace_opts.replace(newopts) + unless @trace_opts.empty? + Tk.tk_call_without_enc('trace', 'variable', + @id, @trace_opts, 'rb_var ' << @id) + end + end + else + unless (@trace_opts - newopts).empty? + Tk.tk_call_without_enc('trace', 'remove', 'variable', + @id, @trace_opts, 'rb_var ' << @id) + @trace_opts.replace(newopts) + unless @trace_opts.empty? + Tk.tk_call_without_enc('trace', 'add', 'variable', + @id, @trace_opts, 'rb_var ' << @id) + end + end + end + + self + end + alias trace_delete trace_remove + alias trace_vdelete trace_remove + + def trace_remove_for_element(elem,opts,cmd) + if @elem + fail(RuntimeError, + "invalid for a TkVariable which denotes an element of Tcl's array") + end + return self unless @trace_elem.kind_of? Hash + return self unless @trace_elem[elem].kind_of? Array + + opts = _check_trace_opt(opts) + + idx = -1 + if USE_OLD_TRACE_OPTION_STYLE + @trace_elem[elem].each_with_index{|e, i| + if idx < 0 && e[1] == cmd + diff = false + ['a', 'r', 'w', 'u'].each{|c| + break if (diff = e[0].index(c) ^ opts.index(c)) + } + unless diff + #find + idx = i + next + end + end + } + else + @trace_elem[elem].each_with_index{|e, i| + if idx < 0 && e[1] == cmd && + e[0].size == opts.size && (e[0] - opts).empty? + # find + idx = i + next + end + } + end + + if idx >= 0 + @trace_elem[elem].delete_at(idx) + else + return self + end + + if USE_OLD_TRACE_OPTION_STYLE + newopts = '' + @trace_var.each{|e| + e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)} + } + @trace_elem.each{|elem| + @trace_elem[elem].each{|e| + e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)} + } + } + else + newopts = [] + @trace_var.each{|e| + newopts |= e[0] + } + @trace_elem.each{|elem| + @trace_elem[elem].each{|e| + e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)} + } + } + end + + if USE_OLD_TRACE_OPTION_STYLE + diff = false + @trace_opts.each_byte{|c| break if (diff = ! newopts.index(c))} + if diff + Tk.tk_call_without_enc('trace', 'vdelete', + @id, @trace_opts, 'rb_var ' << @id) + @trace_opts.replace(newopts) + unless @trace_opts.empty? + Tk.tk_call_without_enc('trace', 'variable', + @id, @trace_opts, 'rb_var ' << @id) + end + end + else + unless (@trace_opts - newopts).empty? + Tk.tk_call_without_enc('trace', 'remove', 'variable', + @id, @trace_opts, 'rb_var ' << @id) + @trace_opts.replace(newopts) + unless @trace_opts.empty? + Tk.tk_call_without_enc('trace', 'add', 'variable', + @id, @trace_opts, 'rb_var ' << @id) + end + end + end + + self + end + alias trace_delete_for_element trace_remove_for_element + alias trace_vdelete_for_element trace_remove_for_element +end + +class TkVarAccess<TkVariable + def self.new(name, *args) + if name.kind_of?(TkVariable) + name.value = args[0] unless args.empty? + return name + end + + name = name.to_s + v = nil + TkVar_ID_TBL.mutex.synchronize{ + if v = TkVar_ID_TBL[name] + v.value = args[0] unless args.empty? + return v + else + (v = self.allocate).instance_eval{ + @id = name + TkVar_ID_TBL[@id] = self + @var = @id + } + end + } + + v.instance_eval{ initialize(name, *args) } + v + end + + def self.new_hash(name, *args) + if name.kind_of?(TkVariable) + unless name.is_hash? + fail ArgumentError, "already exist as a scalar variable" + end + name.value = args[0] unless args.empty? + return name + end + + name = name.to_s + v = nil + TkVar_ID_TBL.mutex.synchronize{ + if v = TkVar_ID_TBL[name] + unless v.is_hash? + fail ArgumentError, "already exist as a scalar variable" + end + v.value = args[0] unless args.empty? + return v + else + (v = self.allocate).instance_eval{ + @id = name + TkVar_ID_TBL[@id] = self + @var = @id + } + end + } + + INTERP._invoke_without_enc('global', name) + if args.empty? && INTERP._invoke_without_enc('array', 'exist', name) == '0' + v.instance_eval{ initialize(name, {}) } # force creating + else + v.instance_eval{ initialize(name, *args) } + end + v + end + + def initialize(varname, val=nil) + # @id = varname + # TkVar_ID_TBL[@id] = self + + # @var = @id + @elem = nil + + @def_default = false + @default_val = nil + + @trace_var = nil + @trace_elem = nil + @trace_opts = nil + + @type = nil + var = self + @element_type = Hash.new{|k,v| var.default_value_type } + + # is an element? + if @id =~ /^([^(]+)\((.+)\)$/ + # is an element --> var == $1, elem == $2 + @var = $1 + @elem = $2 + end + + # teach Tk-ip that @id is global var + INTERP._invoke_without_enc('global', @var) +=begin + begin + INTERP._invoke_without_enc('global', @id) + rescue => e + if @id =~ /^(.+)\([^()]+\)$/ + # is an element --> varname == $1 + INTERP._invoke_without_enc('global', $1) + else + fail e + end + end +=end + + if val + if val.kind_of?(Hash) + # assoc-array variable + self[''] = 0 + self.clear + end + #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 + INTERP._invoke_without_enc('global', 'auto_path') + auto_path = INTERP._invoke('set', 'auto_path') + rescue => e + begin + INTERP._invoke_without_enc('global', 'env') + auto_path = INTERP._invoke('set', 'env(TCLLIBPATH)') + rescue => e + 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 diff --git a/jni/ruby/ext/tk/lib/tk/virtevent.rb b/jni/ruby/ext/tk/lib/tk/virtevent.rb new file mode 100644 index 0000000..c11e969 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/virtevent.rb @@ -0,0 +1,139 @@ +# +# 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, TkUtil.untrust("00000")]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + TkVirtualEventTBL = TkCore::INTERP.create_table + + TkCore::INTERP.init_ip_env{ + TkVirtualEventTBL.mutex.synchronize{ TkVirtualEventTBL.clear } + } + + class PreDefVirtEvent<self + def self.new(event, *sequences) + if event =~ /^<(<.*>)>$/ + event = $1 + elsif event !~ /^<.*>$/ + event = '<' + event + '>' + end + TkVirtualEvent::TkVirtualEventTBL.mutex.synchronize{ + if TkVirtualEvent::TkVirtualEventTBL.has_key?(event) + TkVirtualEvent::TkVirtualEventTBL[event] + else + # super(event, *sequences) + (obj = self.allocate).instance_eval{ + initialize(event, *sequences) + TkVirtualEvent::TkVirtualEventTBL[@id] = self + } + end + } + end + + def initialize(event, *sequences) + @path = @id = event + _add_sequences(sequences) + end + end + + def TkVirtualEvent.getobj(event) + obj = nil + TkVirtualEventTBL.mutex.synchronize{ + 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) + TkVirtualEventID.mutex.synchronize{ + # @path = @id = '<' + TkVirtualEventID.join('') + '>' + @path = @id = '<' + TkVirtualEventID.join(TkCore::INTERP._ip_id_) + '>' + TkVirtualEventID[1].succ! + } + _add_sequences(sequences) + end + + def _add_sequences(seq_ary) + unless seq_ary.empty? + tk_call_without_enc('event', 'add', "<#{@id}>", + *(seq_ary.collect{|seq| + "<#{tk_event_sequence(seq)}>" + }) ) + end + self + end + private :_add_sequences + + def add(*sequences) + if sequences != [] + _add_sequences(sequences) + TkVirtualEventTBL.mutex.synchronize{ + TkVirtualEventTBL[@id] = self + } + end + self + end + + def delete(*sequences) + if sequences.empty? + tk_call_without_enc('event', 'delete', "<#{@id}>") + TkVirtualEventTBL.mutex.synchronize{ + TkVirtualEventTBL.delete(@id) + } + else + tk_call_without_enc('event', 'delete', "<#{@id}>", + *(sequences.collect{|seq| + "<#{tk_event_sequence(seq)}>" + }) ) + if tk_call_without_enc('event','info',"<#{@id}>").empty? + TkVirtualEventTBL.mutex.synchronize{ + TkVirtualEventTBL.delete(@id) + } + end + end + self + end + + def info + tk_call_without_enc('event','info',"<#{@id}>").split(/\s+/).collect!{|seq| + lst = seq.scan(/<*[^<>]+>*/).collect!{|subseq| + case (subseq) + when /^<<[^<>]+>>$/ + TkVirtualEvent.getobj(subseq[1..-2]) + when /^<[^<>]+>$/ + subseq[1..-2] + else + subseq.split('') + end + }.flatten + (lst.size == 1) ? lst[0] : lst + } + end +end + +TkNamedVirtualEvent = TkVirtualEvent::PreDefVirtEvent diff --git a/jni/ruby/ext/tk/lib/tk/winfo.rb b/jni/ruby/ext/tk/lib/tk/winfo.rb new file mode 100644 index 0000000..b10cfe6 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/winfo.rb @@ -0,0 +1,392 @@ +# +# tk/winfo.rb : methods for winfo command +# +module TkWinfo +end + +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(win) + number(tk_call_without_enc('winfo', 'cells', win)) + end + def winfo_cells + TkWinfo.cells self + end + + def TkWinfo.children(win) + list(tk_call_without_enc('winfo', 'children', win)) + end + def winfo_children + TkWinfo.children self + end + + def TkWinfo.classname(win) + tk_call_without_enc('winfo', 'class', win) + end + def winfo_classname + TkWinfo.classname self + end + alias winfo_class winfo_classname + + def TkWinfo.colormapfull(win) + bool(tk_call_without_enc('winfo', 'colormapfull', win)) + 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(win) + number(tk_call_without_enc('winfo', 'depth', win)) + end + def winfo_depth + TkWinfo.depth self + end + + def TkWinfo.exist?(win) + bool(tk_call_without_enc('winfo', 'exists', win)) + end + def winfo_exist? + TkWinfo.exist? self + end + + def TkWinfo.fpixels(win, dist) + number(tk_call_without_enc('winfo', 'fpixels', win, dist)) + end + def winfo_fpixels(dist) + TkWinfo.fpixels self, dist + end + + def TkWinfo.geometry(win) + tk_call_without_enc('winfo', 'geometry', win) + end + def winfo_geometry + TkWinfo.geometry self + end + + def TkWinfo.height(win) + number(tk_call_without_enc('winfo', 'height', win)) + end + def winfo_height + TkWinfo.height self + end + + def TkWinfo.id(win) + tk_call_without_enc('winfo', 'id', win) + end + def winfo_id + TkWinfo.id self + end + + def TkWinfo.interps(win=nil) + if win + #tk_split_simplelist(tk_call_without_enc('winfo', 'interps', + # '-displayof', win)) + tk_split_simplelist(tk_call_without_enc('winfo', 'interps', + '-displayof', win), + false, true) + else + #tk_split_simplelist(tk_call_without_enc('winfo', 'interps')) + tk_split_simplelist(tk_call_without_enc('winfo', 'interps'), + false, true) + end + end + def winfo_interps + TkWinfo.interps self + end + + def TkWinfo.mapped?(win) + bool(tk_call_without_enc('winfo', 'ismapped', win)) + end + def winfo_mapped? + TkWinfo.mapped? self + end + + def TkWinfo.manager(win) + tk_call_without_enc('winfo', 'manager', win) + end + def winfo_manager + TkWinfo.manager self + end + + def TkWinfo.appname(win) + tk_call('winfo', 'name', win) + end + def winfo_appname + TkWinfo.appname self + end + + def TkWinfo.parent(win) + window(tk_call_without_enc('winfo', 'parent', win)) + 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(win, dist) + number(tk_call_without_enc('winfo', 'pixels', win, dist)) + end + def winfo_pixels(dist) + TkWinfo.pixels self, dist + end + + def TkWinfo.reqheight(win) + number(tk_call_without_enc('winfo', 'reqheight', win)) + end + def winfo_reqheight + TkWinfo.reqheight self + end + + def TkWinfo.reqwidth(win) + number(tk_call_without_enc('winfo', 'reqwidth', win)) + end + def winfo_reqwidth + TkWinfo.reqwidth self + end + + def TkWinfo.rgb(win, color) + list(tk_call_without_enc('winfo', 'rgb', win, color)) + end + def winfo_rgb(color) + TkWinfo.rgb self, color + end + + def TkWinfo.rootx(win) + number(tk_call_without_enc('winfo', 'rootx', win)) + end + def winfo_rootx + TkWinfo.rootx self + end + + def TkWinfo.rooty(win) + number(tk_call_without_enc('winfo', 'rooty', win)) + end + def winfo_rooty + TkWinfo.rooty self + end + + def TkWinfo.screen(win) + tk_call('winfo', 'screen', win) + end + def winfo_screen + TkWinfo.screen self + end + + def TkWinfo.screencells(win) + number(tk_call_without_enc('winfo', 'screencells', win)) + end + def winfo_screencells + TkWinfo.screencells self + end + + def TkWinfo.screendepth(win) + number(tk_call_without_enc('winfo', 'screendepth', win)) + end + def winfo_screendepth + TkWinfo.screendepth self + end + + def TkWinfo.screenheight (win) + number(tk_call_without_enc('winfo', 'screenheight', win)) + end + def winfo_screenheight + TkWinfo.screenheight self + end + + def TkWinfo.screenmmheight(win) + number(tk_call_without_enc('winfo', 'screenmmheight', win)) + end + def winfo_screenmmheight + TkWinfo.screenmmheight self + end + + def TkWinfo.screenmmwidth(win) + number(tk_call_without_enc('winfo', 'screenmmwidth', win)) + end + def winfo_screenmmwidth + TkWinfo.screenmmwidth self + end + + def TkWinfo.screenvisual(win) + tk_call_without_enc('winfo', 'screenvisual', win) + end + def winfo_screenvisual + TkWinfo.screenvisual self + end + + def TkWinfo.screenwidth(win) + number(tk_call_without_enc('winfo', 'screenwidth', win)) + end + def winfo_screenwidth + TkWinfo.screenwidth self + end + + def TkWinfo.server(win) + tk_call('winfo', 'server', win) + end + def winfo_server + TkWinfo.server self + end + + def TkWinfo.toplevel(win) + window(tk_call_without_enc('winfo', 'toplevel', win)) + end + def winfo_toplevel + TkWinfo.toplevel self + end + + def TkWinfo.visual(win) + tk_call_without_enc('winfo', 'visual', win) + end + def winfo_visual + TkWinfo.visual self + end + + def TkWinfo.visualid(win) + tk_call_without_enc('winfo', 'visualid', win) + end + def winfo_visualid + TkWinfo.visualid self + end + + def TkWinfo.visualsavailable(win, includeids=false) + if includeids + list(tk_call_without_enc('winfo', 'visualsavailable', + win, "includeids")) + else + list(tk_call_without_enc('winfo', 'visualsavailable', win)) + end + end + def winfo_visualsavailable(includeids=false) + TkWinfo.visualsavailable self, includeids + end + + def TkWinfo.vrootheight(win) + number(tk_call_without_enc('winfo', 'vrootheight', win)) + end + def winfo_vrootheight + TkWinfo.vrootheight self + end + + def TkWinfo.vrootwidth(win) + number(tk_call_without_enc('winfo', 'vrootwidth', win)) + end + def winfo_vrootwidth + TkWinfo.vrootwidth self + end + + def TkWinfo.vrootx(win) + number(tk_call_without_enc('winfo', 'vrootx', win)) + end + def winfo_vrootx + TkWinfo.vrootx self + end + + def TkWinfo.vrooty(win) + number(tk_call_without_enc('winfo', 'vrooty', win)) + end + def winfo_vrooty + TkWinfo.vrooty self + end + + def TkWinfo.width(win) + number(tk_call_without_enc('winfo', 'width', win)) + end + def winfo_width + TkWinfo.width self + end + + def TkWinfo.x(win) + number(tk_call_without_enc('winfo', 'x', win)) + end + def winfo_x + TkWinfo.x self + end + + def TkWinfo.y(win) + number(tk_call_without_enc('winfo', 'y', win)) + end + def winfo_y + TkWinfo.y self + end + + def TkWinfo.viewable(win) + bool(tk_call_without_enc('winfo', 'viewable', win)) + end + def winfo_viewable + TkWinfo.viewable self + end + + def TkWinfo.pointerx(win) + number(tk_call_without_enc('winfo', 'pointerx', win)) + end + def winfo_pointerx + TkWinfo.pointerx self + end + + def TkWinfo.pointery(win) + number(tk_call_without_enc('winfo', 'pointery', win)) + end + def winfo_pointery + TkWinfo.pointery self + end + + def TkWinfo.pointerxy(win) + list(tk_call_without_enc('winfo', 'pointerxy', win)) + end + def winfo_pointerxy + TkWinfo.pointerxy self + end +end diff --git a/jni/ruby/ext/tk/lib/tk/winpkg.rb b/jni/ruby/ext/tk/lib/tk/winpkg.rb new file mode 100644 index 0000000..80e0439 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/winpkg.rb @@ -0,0 +1,156 @@ +# +# 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 Tk::WinDDE +end +#TkWinDDE = Tk::WinDDE +#Tk.__set_toplevel_aliases__(:Tk, Tk::WinDDE, :TkWinDDE) +Tk.__set_loaded_toplevel_aliases__('tk/winpkg.rb', :Tk, Tk::WinDDE, :TkWinDDE) + +module Tk::WinDDE + extend Tk + extend Tk::WinDDE + + TkCommandNames = ['dde'.freeze].freeze + + PACKAGE_NAME = 'dde'.freeze + def self.package_name + PACKAGE_NAME + end + + 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) # dde 1.2 + + 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 + else + tk_call('dde', 'servername', *args) + 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 Tk::WinRegistry +end +#TkWinRegistry = Tk::WinRegistry +#Tk.__set_toplevel_aliases__(:Tk, Tk::WinRegistry, :TkWinRegistry) +Tk.__set_loaded_toplevel_aliases__('tk/winpkg.rb', :Tk, Tk::WinRegistry, + :TkWinRegistry) + +module Tk::WinRegistry + extend Tk + extend Tk::WinRegistry + + 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 diff --git a/jni/ruby/ext/tk/lib/tk/wm.rb b/jni/ruby/ext/tk/lib/tk/wm.rb new file mode 100644 index 0000000..fcd5a2c --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/wm.rb @@ -0,0 +1,552 @@ +# +# tk/wm.rb : methods for wm command +# +require 'tk' + +module Tk + module Wm + #include TkComm + extend TkCore + + TkCommandNames = ['wm'.freeze].freeze + + TOPLEVEL_METHODCALL_OPTKEYS = {} + + def Wm.aspect(win, *args) + if args.length == 0 + list(tk_call_without_enc('wm', 'aspect', win.epath)) + else + args = args[0] if args.length == 1 && args[0].kind_of?(Array) + tk_call('wm', 'aspect', win.epath, *args) + win + end + end + def aspect(*args) + Wm.aspect(self, *args) + end + alias wm_aspect aspect + TOPLEVEL_METHODCALL_OPTKEYS['aspect'] = 'aspect' + + def Wm.attributes(win, slot=nil,value=TkComm::None) + if slot == nil + lst = tk_split_list(tk_call('wm', 'attributes', win.epath)) + info = {} + while key = lst.shift + info[key[1..-1]] = lst.shift + end + info + elsif slot.kind_of? Hash + tk_call('wm', 'attributes', win.epath, *hash_kv(slot)) + win + elsif value == TkComm::None + tk_call('wm', 'attributes', win.epath, "-#{slot}") + else + tk_call('wm', 'attributes', win.epath, "-#{slot}", value) + win + end + end + def attributes(slot=nil,value=TkComm::None) + Wm.attributes(self, slot, value) + end + alias wm_attributes attributes + TOPLEVEL_METHODCALL_OPTKEYS['attributes'] = 'attributes' + + def Wm.client(win, name=TkComm::None) + if name == TkComm::None + tk_call('wm', 'client', win.epath) + else + name = '' if name == nil + tk_call('wm', 'client', win.epath, name) + win + end + end + def client(name=TkComm::None) + Wm.client(self, name) + end + alias wm_client client + TOPLEVEL_METHODCALL_OPTKEYS['client'] = 'client' + + def Wm.colormapwindows(win, *args) + if args.size == 0 + list(tk_call_without_enc('wm', 'colormapwindows', win.epath)) + else + args = args[0] if args.length == 1 && args[0].kind_of?(Array) + tk_call_without_enc('wm', 'colormapwindows', win.epath, *args) + win + end + end + def colormapwindows(*args) + Wm.colormapwindows(self, *args) + end + alias wm_colormapwindows colormapwindows + TOPLEVEL_METHODCALL_OPTKEYS['colormapwindows'] = 'colormapwindows' + + def Wm.command(win, value=nil) + if value + tk_call('wm', 'command', win.epath, value) + win + else + #procedure(tk_call('wm', 'command', win.epath)) + tk_call('wm', 'command', win.epath) + end + end + def wm_command(value=nil) + Wm.command(self, value) + end + TOPLEVEL_METHODCALL_OPTKEYS['wm_command'] = 'wm_command' + + def Wm.deiconify(win, ex = true) + if ex + tk_call_without_enc('wm', 'deiconify', win.epath) + else + Wm.iconify(win) + end + win + end + def deiconify(ex = true) + Wm.deiconify(self, ex) + end + alias wm_deiconify deiconify + + def Wm.focusmodel(win, mode = nil) + if mode + tk_call_without_enc('wm', 'focusmodel', win.epath, mode) + win + else + tk_call_without_enc('wm', 'focusmodel', win.epath) + end + end + def focusmodel(mode = nil) + Wm.focusmodel(self, mode) + end + alias wm_focusmodel focusmodel + TOPLEVEL_METHODCALL_OPTKEYS['focusmodel'] = 'focusmodel' + + def Wm.forget(win) + # Tcl/Tk 8.5+ + # work with dockable frames + tk_call_without_enc('wm', 'forget', win.epath) + win + end + def wm_forget + Wm.forget(self) + end + + def Wm.frame(win) + tk_call_without_enc('wm', 'frame', win.epath) + end + def frame + Wm.frame(self) + end + alias wm_frame frame + + def Wm.geometry(win, geom=nil) + if geom + tk_call_without_enc('wm', 'geometry', win.epath, geom) + win + else + tk_call_without_enc('wm', 'geometry', win.epath) + end + end + def geometry(geom=nil) + Wm.geometry(self, geom) + end + alias wm_geometry geometry + TOPLEVEL_METHODCALL_OPTKEYS['geometry'] = 'geometry' + + def Wm.grid(win, *args) + if args.size == 0 + list(tk_call_without_enc('wm', 'grid', win.epath)) + else + args = args[0] if args.length == 1 && args[0].kind_of?(Array) + tk_call_without_enc('wm', 'grid', win.epath, *args) + win + end + end + def wm_grid(*args) + Wm.grid(self, *args) + end + TOPLEVEL_METHODCALL_OPTKEYS['wm_grid'] = 'wm_grid' + + def Wm.group(win, leader = nil) + if leader + tk_call('wm', 'group', win.epath, leader) + win + else + window(tk_call('wm', 'group', win.epath)) + end + end + def group(leader = nil) + Wm.group(self, leader) + end + alias wm_group group + TOPLEVEL_METHODCALL_OPTKEYS['group'] = 'group' + + def Wm.iconbitmap(win, bmp=nil) + if bmp + tk_call_without_enc('wm', 'iconbitmap', win.epath, bmp) + win + else + image_obj(tk_call_without_enc('wm', 'iconbitmap', win.epath)) + end + end + def iconbitmap(bmp=nil) + Wm.iconbitmap(self, bmp) + end + alias wm_iconbitmap iconbitmap + TOPLEVEL_METHODCALL_OPTKEYS['iconbitmap'] = 'iconbitmap' + + def Wm.iconphoto(win, *imgs) + if imgs.empty? + win.instance_eval{ + @wm_iconphoto = nil unless defined? @wm_iconphoto + return @wm_iconphoto + } + end + + imgs = imgs[0] if imgs.length == 1 && imgs[0].kind_of?(Array) + tk_call_without_enc('wm', 'iconphoto', win.epath, *imgs) + win.instance_eval{ @wm_iconphoto = imgs } + win + end + def iconphoto(*imgs) + Wm.iconphoto(self, *imgs) + end + alias wm_iconphoto iconphoto + TOPLEVEL_METHODCALL_OPTKEYS['iconphoto'] = 'iconphoto' + + def Wm.iconphoto_default(win, *imgs) + imgs = imgs[0] if imgs.length == 1 && imgs[0].kind_of?(Array) + tk_call_without_enc('wm', 'iconphoto', win.epath, '-default', *imgs) + win + end + def iconphoto_default(*imgs) + Wm.iconphoto_default(self, *imgs) + end + alias wm_iconphoto_default iconphoto_default + + def Wm.iconify(win, ex = true) + if ex + tk_call_without_enc('wm', 'iconify', win.epath) + else + Wm.deiconify(win) + end + win + end + def iconify(ex = true) + Wm.iconify(self, ex) + end + alias wm_iconify iconify + + def Wm.iconmask(win, bmp=nil) + if bmp + tk_call_without_enc('wm', 'iconmask', win.epath, bmp) + win + else + image_obj(tk_call_without_enc('wm', 'iconmask', win.epath)) + end + end + def iconmask(bmp=nil) + Wm.iconmask(self, bmp) + end + alias wm_iconmask iconmask + TOPLEVEL_METHODCALL_OPTKEYS['iconmask'] = 'iconmask' + + def Wm.iconname(win, name=nil) + if name + tk_call('wm', 'iconname', win.epath, name) + win + else + tk_call('wm', 'iconname', win.epath) + end + end + def iconname(name=nil) + Wm.iconname(self, name) + end + alias wm_iconname iconname + TOPLEVEL_METHODCALL_OPTKEYS['iconname'] = 'iconname' + + def Wm.iconposition(win, *args) + if args.size == 0 + list(tk_call_without_enc('wm', 'iconposition', win.epath)) + else + args = args[0] if args.length == 1 && args[0].kind_of?(Array) + tk_call_without_enc('wm', 'iconposition', win.epath, *args) + win + end + end + def iconposition(*args) + Wm.iconposition(self, *args) + end + alias wm_iconposition iconposition + TOPLEVEL_METHODCALL_OPTKEYS['iconposition'] = 'iconposition' + + def Wm.iconwindow(win, iconwin = nil) + if iconwin + tk_call_without_enc('wm', 'iconwindow', win.epath, iconwin) + win + else + w = tk_call_without_enc('wm', 'iconwindow', win.epath) + (w == '')? nil: window(w) + end + end + def iconwindow(iconwin = nil) + Wm.iconwindow(self, iconwin) + end + alias wm_iconwindow iconwindow + TOPLEVEL_METHODCALL_OPTKEYS['iconwindow'] = 'iconwindow' + + def Wm.manage(win) + # Tcl/Tk 8.5+ feature + tk_call_without_enc('wm', 'manage', win.epath) + win + end + def wm_manage + Wm.manage(self) + end +=begin + def Wm.manage(win, use_id = nil) + # Tcl/Tk 8.5+ feature + # -------------------------------------------------------------- + # In the future release, I want to support to embed the 'win' + # into the container which has window-id 'use-id'. + # It may give users frexibility on controlling their GUI. + # However, it may be difficult for current Tcl/Tk (Tcl/Tk8.5.1), + # because it seems to require to modify Tcl/Tk's source code. + # -------------------------------------------------------------- + if use_id + tk_call_without_enc('wm', 'manage', win.epath, '-use', use_id) + else + tk_call_without_enc('wm', 'manage', win.epath) + end + win + end +=end + + def Wm.maxsize(win, *args) + if args.size == 0 + list(tk_call_without_enc('wm', 'maxsize', win.epath)) + else + args = args[0] if args.length == 1 && args[0].kind_of?(Array) + tk_call_without_enc('wm', 'maxsize', win.epath, *args) + win + end + end + def maxsize(*args) + Wm.maxsize(self, *args) + end + alias wm_maxsize maxsize + TOPLEVEL_METHODCALL_OPTKEYS['maxsize'] = 'maxsize' + + def Wm.minsize(win, *args) + if args.size == 0 + list(tk_call_without_enc('wm', 'minsize', win.epath)) + else + args = args[0] if args.length == 1 && args[0].kind_of?(Array) + tk_call_without_enc('wm', 'minsize', win.path, *args) + win + end + end + def minsize(*args) + Wm.minsize(self, *args) + end + alias wm_minsize minsize + TOPLEVEL_METHODCALL_OPTKEYS['minsize'] = 'minsize' + + def Wm.overrideredirect(win, mode=TkComm::None) + if mode == TkComm::None + bool(tk_call_without_enc('wm', 'overrideredirect', win.epath)) + else + tk_call_without_enc('wm', 'overrideredirect', win.epath, mode) + win + end + end + def overrideredirect(mode=TkComm::None) + Wm.overrideredirect(self, mode) + end + alias wm_overrideredirect overrideredirect + TOPLEVEL_METHODCALL_OPTKEYS['overrideredirect'] = 'overrideredirect' + + def Wm.positionfrom(win, who=TkComm::None) + if who == TkComm::None + r = tk_call_without_enc('wm', 'positionfrom', win.epath) + (r == "")? nil: r + else + tk_call_without_enc('wm', 'positionfrom', win.epath, who) + win + end + end + def positionfrom(who=TkComm::None) + Wm.positionfrom(self, who) + end + alias wm_positionfrom positionfrom + TOPLEVEL_METHODCALL_OPTKEYS['positionfrom'] = 'positionfrom' + + def Wm.protocol(win, name=nil, cmd=nil, &b) + if cmd + tk_call_without_enc('wm', 'protocol', win.epath, name, cmd) + win + elsif b + tk_call_without_enc('wm', 'protocol', win.epath, name, proc(&b)) + win + elsif name + result = tk_call_without_enc('wm', 'protocol', win.epath, name) + (result == "")? nil : tk_tcl2ruby(result) + else + tk_split_simplelist(tk_call_without_enc('wm', 'protocol', win.epath)) + end + end + def protocol(name=nil, cmd=nil, &b) + Wm.protocol(self, name, cmd, &b) + end + alias wm_protocol protocol + + def Wm.protocols(win, kv=nil) + unless kv + ret = {} + Wm.protocol(win).each{|name| + ret[name] = Wm.protocol(win, name) + } + return ret + end + + unless kv.kind_of?(Hash) + fail ArgumentError, 'expect a hash of protocol=>command' + end + kv.each{|k, v| Wm.protocol(win, k, v)} + win + end + def protocols(kv=nil) + Wm.protocols(self, kv) + end + alias wm_protocols protocols + TOPLEVEL_METHODCALL_OPTKEYS['protocols'] = 'protocols' + + def Wm.resizable(win, *args) + if args.length == 0 + list(tk_call_without_enc('wm', 'resizable', win.epath)).map!{|e| bool(e)} + else + args = args[0] if args.length == 1 && args[0].kind_of?(Array) + tk_call_without_enc('wm', 'resizable', win.epath, *args) + win + end + end + def resizable(*args) + Wm.resizable(self, *args) + end + alias wm_resizable resizable + TOPLEVEL_METHODCALL_OPTKEYS['resizable'] = 'resizable' + + def Wm.sizefrom(win, who=TkComm::None) + if who == TkComm::None + r = tk_call_without_enc('wm', 'sizefrom', win.epath) + (r == "")? nil: r + else + tk_call_without_enc('wm', 'sizefrom', win.epath, who) + win + end + end + def sizefrom(who=TkComm::None) + Wm.sizefrom(self, who) + end + alias wm_sizefrom sizefrom + TOPLEVEL_METHODCALL_OPTKEYS['sizefrom'] = 'sizefrom' + + def Wm.stackorder(win) + list(tk_call('wm', 'stackorder', win.epath)) + end + def stackorder + Wm.stackorder(self) + end + alias wm_stackorder stackorder + + def Wm.stackorder_isabove(win, target) + bool(tk_call('wm', 'stackorder', win.epath, 'isabove', target)) + end + def Wm.stackorder_is_above(win, target) + Wm.stackorder_isabove(win, target) + end + def stackorder_isabove(target) + Wm.stackorder_isabove(self, target) + end + alias stackorder_is_above stackorder_isabove + alias wm_stackorder_isabove stackorder_isabove + alias wm_stackorder_is_above stackorder_isabove + + def Wm.stackorder_isbelow(win, target) + bool(tk_call('wm', 'stackorder', win.epath, 'isbelow', target)) + end + def Wm.stackorder_is_below(win, target) + Wm.stackorder_isbelow(win, target) + end + def stackorder_isbelow(target) + Wm.stackorder_isbelow(self, target) + end + alias stackorder_is_below stackorder_isbelow + alias wm_stackorder_isbelow stackorder_isbelow + alias wm_stackorder_is_below stackorder_isbelow + + def Wm.state(win, st=nil) + if st + tk_call_without_enc('wm', 'state', win.epath, st) + win + else + tk_call_without_enc('wm', 'state', win.epath) + end + end + def state(st=nil) + Wm.state(self, st) + end + alias wm_state state + TOPLEVEL_METHODCALL_OPTKEYS['state'] = 'state' + + def Wm.title(win, str=nil) + if str + tk_call('wm', 'title', win.epath, str) + win + else + tk_call('wm', 'title', win.epath) + end + end + def title(str=nil) + Wm.title(self, str) + end + alias wm_title title + TOPLEVEL_METHODCALL_OPTKEYS['title'] = 'title' + + def Wm.transient(win, master=nil) + if master + tk_call_without_enc('wm', 'transient', win.epath, master) + win + else + window(tk_call_without_enc('wm', 'transient', win.epath)) + end + end + def transient(master=nil) + Wm.transient(self, master) + end + alias wm_transient transient + TOPLEVEL_METHODCALL_OPTKEYS['transient'] = 'transient' + + def Wm.withdraw(win, ex = true) + if ex + tk_call_without_enc('wm', 'withdraw', win.epath) + else + Wm.deiconify(win) + end + win + end + def withdraw(ex = true) + Wm.withdraw(self, ex) + end + alias wm_withdraw withdraw + end + + module Wm_for_General + Wm.instance_methods.each{|m| + if (m = m.to_s) =~ /^wm_(.*)$/ + eval "def #{m}(*args, &b); Tk::Wm.#{$1}(self, *args, &b); end" + end + } + end +end diff --git a/jni/ruby/ext/tk/lib/tk/xim.rb b/jni/ruby/ext/tk/lib/tk/xim.rb new file mode 100644 index 0000000..c0126c5 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tk/xim.rb @@ -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, win = nil) + if value == None + if win + bool(tk_call_without_enc('tk', 'useinputmethods', + '-displayof', win)) + else + bool(tk_call_without_enc('tk', 'useinputmethods')) + end + else + if win + bool(tk_call_without_enc('tk', 'useinputmethods', + '-displayof', win, value)) + else + bool(tk_call_without_enc('tk', 'useinputmethods', value)) + end + end + end + + def TkXIM.useinputmethods_displayof(win, value = None) + TkXIM.useinputmethods(value, win) + end + + def TkXIM.caret(win, keys=nil) + if keys + tk_call_without_enc('tk', 'caret', win, *hash_kv(keys)) + self + else + lst = tk_split_list(tk_call_without_enc('tk', 'caret', win)) + info = {} + while key = lst.shift + info[key[1..-1]] = lst.shift + end + info + end + end + + def TkXIM.configure(win, slot, value=None) + begin + if /^8\.*/ === Tk::TK_VERSION && JAPANIZED_TK + if slot.kind_of? Hash + tk_call('imconfigure', win, *hash_kv(slot)) + else + tk_call('imconfigure', win, "-#{slot}", value) + end + end + rescue + end + end + + def TkXIM.configinfo(win, 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', win, "-#{slot}")) + conf[0] = conf[0][1..-1] + conf + else + tk_split_list(tk_call('imconfigure', win)).collect{|conf| + conf[0] = conf[0][1..-1] + conf + } + end + else + [] + end + rescue + [] + end + else # ! TkComm::GET_CONFIGINFOwoRES_AS_ARRAY + TkXIM.current_configinfo(win, slot) + end + end + + def TkXIM.current_configinfo(win, slot=nil) + begin + if /^8\.*/ === Tk::TK_VERSION && JAPANIZED_TK + if slot + conf = tk_split_list(tk_call('imconfigure', win, "-#{slot}")) + { conf[0][1..-1] => conf[1] } + else + ret = {} + tk_split_list(tk_call('imconfigure', win)).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 diff --git a/jni/ruby/ext/tk/lib/tkafter.rb b/jni/ruby/ext/tk/lib/tkafter.rb new file mode 100644 index 0000000..f659458 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkafter.rb @@ -0,0 +1,4 @@ +# +# tkafter.rb - load tk/after.rb +# +require 'tk/timer' diff --git a/jni/ruby/ext/tk/lib/tkbgerror.rb b/jni/ruby/ext/tk/lib/tkbgerror.rb new file mode 100644 index 0000000..deba7a5 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkbgerror.rb @@ -0,0 +1,4 @@ +# +# tkbgerror.rb - load tk/bgerror.rb +# +require 'tk/bgerror' diff --git a/jni/ruby/ext/tk/lib/tkcanvas.rb b/jni/ruby/ext/tk/lib/tkcanvas.rb new file mode 100644 index 0000000..9524614 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkcanvas.rb @@ -0,0 +1,4 @@ +# +# tkcanvas.rb - load tk/canvas.rb +# +require 'tk/canvas' diff --git a/jni/ruby/ext/tk/lib/tkclass.rb b/jni/ruby/ext/tk/lib/tkclass.rb new file mode 100644 index 0000000..9918ce6 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkclass.rb @@ -0,0 +1,47 @@ +# +# tkclass.rb - Tk classes +# Date: 2000/11/27 09:23:36 +# by Yukihiro Matsumoto <matz@caelum.co.jp> +# +# $Id: tkclass.rb 25189 2009-10-02 12:04:37Z akr $ + +require "tk" + +TopLevel = TkToplevel +Frame = TkFrame +Label = TkLabel +Button = TkButton +Radiobutton = TkRadioButton +Checkbutton = TkCheckButton +Message = TkMessage +Entry = TkEntry +Spinbox = TkSpinbox +Text = TkText +Scale = TkScale +Scrollbar = TkScrollbar +Listbox = TkListbox +Menu = TkMenu +Menubutton = TkMenubutton +Canvas = TkCanvas +Arc = TkcArc +Bitmap = TkcBitmap +Line = TkcLine +Oval = TkcOval +Polygon = TkcPolygon +Rectangle = TkcRectangle +TextItem = TkcText +WindowItem = TkcWindow +BitmapImage = TkBitmapImage +PhotoImage = TkPhotoImage +Selection = TkSelection +Winfo = TkWinfo +Pack = TkPack +Grid = TkGrid +Place = TkPlace +Variable = TkVariable +Font = TkFont +VirtualEvent = TkVirtualEvent + +def Mainloop + Tk.mainloop +end diff --git a/jni/ruby/ext/tk/lib/tkconsole.rb b/jni/ruby/ext/tk/lib/tkconsole.rb new file mode 100644 index 0000000..9960ddb --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkconsole.rb @@ -0,0 +1,4 @@ +# +# tkconsole.rb - load tk/console.rb +# +require 'tk/console' diff --git a/jni/ruby/ext/tk/lib/tkdialog.rb b/jni/ruby/ext/tk/lib/tkdialog.rb new file mode 100644 index 0000000..bec5e5d --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkdialog.rb @@ -0,0 +1,4 @@ +# +# tkdialog.rb - load tk/dialog.rb +# +require 'tk/dialog' diff --git a/jni/ruby/ext/tk/lib/tkentry.rb b/jni/ruby/ext/tk/lib/tkentry.rb new file mode 100644 index 0000000..2dcfcab --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkentry.rb @@ -0,0 +1,4 @@ +# +# tkentry.rb - load tk/entry.rb +# +require 'tk/entry' diff --git a/jni/ruby/ext/tk/lib/tkextlib/ICONS.rb b/jni/ruby/ext/tk/lib/tkextlib/ICONS.rb new file mode 100644 index 0000000..18d84c0 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/ICONS.rb @@ -0,0 +1,13 @@ +# +# ICONS support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/ICONS/setup.rb' + +# load library +require 'tkextlib/ICONS/icons' diff --git a/jni/ruby/ext/tk/lib/tkextlib/ICONS/icons.rb b/jni/ruby/ext/tk/lib/tkextlib/ICONS/icons.rb new file mode 100644 index 0000000..bd3180a --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/ICONS/icons.rb @@ -0,0 +1,129 @@ +# +# tkextlib/ICONS/icons.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/ICONS/setup.rb' + +# TkPackage.require('icons', '1.0') +TkPackage.require('icons') + +module Tk + class ICONS < TkImage + extend Tk + + PACKAGE_NAME = 'icons'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('icons') + rescue + '' + end + end + + def self.create(*args) # icon, icon, ..., ?option=>value, ...? + if args[-1].kind_of?(Hash) + keys = args.pop + icons = simplelist(tk_call('::icons::icons', 'create', + *(hash_kv(keys) << (args.flatten)))) + else + icons = simplelist(tk_call('::icons::icons', 'create', + args.flatten)) + end + + icons.collect{|icon| self.new(icon, :without_creating=>true)} + end + + def self.delete(*icons) # icon, icon, ... + icons = icons.flatten + return if icons.empty? + icons.map!{|icon| + if icon.kind_of?(Tk::ICONS) + Tk_IMGTBL.delete(icon.path) + icon.name + elsif icon.to_s =~ /^::icon::(.*)/ + name = $1 + Tk_IMGTBL.delete(icon) + name + else + Tk_IMGTBL.delete("::icon::#{icon}") + icon + end + } + tk_call('::icons::icons', 'delete', icons) + end + + def self.query(*args) # icon, icon, ..., ?option=>value, ...? + if args[-1].kind_of?(Hash) + keys = args.pop + simplelist(tk_call('::icons::icons', 'query', + *(hash_kv(keys) << (args.flatten)))) + else + simplelist(tk_call('::icons::icons', 'query', args.flatten)) + end . map{|inf| list(inf) } + end + + ########################################## + + class << self + alias _new new + + def new(name, keys=nil) + if obj = Tk_IMGTBL["::icon::#{name}"] + if keys + keys = _symbolkey2str(keys) + unless keys.delete('without_creating') + tk_call('::icons::icons', 'create', *(hash_kv(keys) << obj.name)) + end + end + else + obj = _new(name, keys) + end + obj + end + end + + ########################################## + + def initialize(name, keys=nil) + if name.kind_of?(String) && name =~ /^::icon::(.+)$/ + @name = $1 + @path = name + else + @name = name.to_s + @path = "::icon::#{@name}" + end + keys = _symbolkey2str(keys) + unless keys.delete('without_creating') + tk_call('::icons::icons', 'create', *(hash_kv(keys) << @name)) + end + Tk_IMGTBL[@path] = self + end + + def name + @name + end + + def delete + Tk_IMGTBL.delete(@path) + tk_call('::icons::icons', 'delete', @name) + self + end + + def query(keys={}) + list(simplelist(tk_call('::icons::icons', 'query', + *(hash_kv(keys) << @name)) + )[0]) + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/ICONS/setup.rb b/jni/ruby/ext/tk/lib/tkextlib/ICONS/setup.rb new file mode 100644 index 0000000..ee406c6 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/ICONS/setup.rb @@ -0,0 +1,8 @@ +# +# setup.rb -- setup script before calling TkPackage.require() +# +# If you need some setup operations (for example, add a library path +# to the library search path) before using Tcl/Tk library packages +# wrapped by Ruby scripts in this directory, please write the setup +# operations in this file. +# diff --git a/jni/ruby/ext/tk/lib/tkextlib/SUPPORT_STATUS b/jni/ruby/ext/tk/lib/tkextlib/SUPPORT_STATUS new file mode 100644 index 0000000..de51c51 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/SUPPORT_STATUS @@ -0,0 +1,193 @@ + + [ current support status of Tcl/Tk extensions ] + + *** RELEASE_DATE of the libraries => see 'tkextlib/version.rb' *** + +The following list shows *CURRENT* status when this file was modified +at last. If you want to add other Tcl/Tk extensions to the planed list +(or change its status position), please request them at the ruby-talk, +ruby-list, or ruby-dev ML. Although we cannot promise to support your +requests, we'll try to do. + +If you want to check that wrapper libraries are ready to use on your +environment, please execute 'pkg_checker.rb' with no arguments. The +script may give you some hints about that. + + + ***** IMPORTANT NOTE ********************************************** + + 'support' means that Ruby/Tk's wrapper libraries are released. + 'not support' does *NOT* mean that the extension doesn't work + on Ruby/Tk. + + The version number of each extension means the latest version + which is checked its feature. That is, it does NOT means only + version of working. Library files maybe include some features + which is included in the former version but removed from the + latest, and maybe able to support the later version then the + shown version. + + Even if the status of the extension is 'not support', you can + control the functions/widgets of the extension without wrapper + libraries by Tk.tk_call(), Tk.ip_eval(), and so on. + + If you cannot use installed Tcl/Tk extension, please check the + followings. + + (1) On your Tcl/Tk, does the extension work? + + (2) Do DLL libraries of the extension exist on DLL load-path? + (See also "<ruby archive>/ext/tcltklib/README.ActiveTcl") + + (3) Is the Tcl library directory of the extension included in + library search-path of the Tcl interpreter linked Ruby/Tk? + + The check results may request you to do some setup operations + before using the extension. If so, then please write the step + of setup operations into the "setup.rb" file in the directory + of the wrapper libraries for the extension (It is the wrapper + libraries have the standard structure of the libraries in this + directory). The "setup" file is required before requiring the + Tcl library package (TkPackage.require(<libname>)). + + ******************************************************************* + + +===< support with some examples (may be beta quality) >======================= + +Tcllib 1.11.1 +Tklib 0.5 http://sourceforge.net/projects/tcllib ==> tcllib + ( partial support; primary support target is Tklib) + +IWidgets 4.0.2 http://sourceforge.net/projects/incrtcl ==> iwidgets + +BWidget 1.8 [ CVS/Hd(2009-07-02) ] + http://sourceforge.net/projects/tcllib ==> bwidget + +TkTable 2.10 http://sourceforge.net/projects/tktable ==> tktable + * see also <http://www.korus.hu/~fery/ruby/tktable.rb> + written by Ferenc Engard (ferenc@engard.hu) + +Vu widgets 2.3.0 http://sourceforge.net/projects/tktable ==> vu + +TkHTML 2.0 http://www.hwaci.com/sw/tkhtml/ ==> tkHTML + +ICONS 1.0 http://www.satisoft.com/tcltk/icons/ ==> ICONS + +TkImg 1.3 http://sourceforge.net/projects/tkimg ==> tkimg + + +BLT 2.4z http://sourceforge.net/projects/blt ==> blt + +TkTreeCtrl 2.2.9 + http://tktreectrl.sourceforge.net/ ==> treectrl + +Tile 0.8.3/8.6b1 + http://sourceforge.net/projects/tktable ==> tile + + + +===< support (may be alpha or beta quality) >================================= + +IncrTcl CVS/Hd(2008-12-15) + http://sourceforge.net/projects/incrtcl ==> itcl, itk + +TclX CVS/Hd(2008-12-15) + http://sourceforge.net/projects/tclx + ==> tclx (partial support; infox command and + XPG/3 message catalogs only) + +Trofs 0.4.4 http://math.nist.gov/~DPorter/tcltk/trofs/ + + + +===< possibly available (not tested; alpha quality) >========================= + +winico 0.6 + http://sourceforge.net/projects/tktable + ==> winico (win32 only) + +TkTrans latest(2004-10-11) + http://www2.cmp.uea.ac.uk/~fuzz/tktrans/default.html + ==> tktrans (win32 only) + +TkDND 1.0a2 http://sourceforge.net/projects/tkdnd ==> tkDND + + + +===< plan to support (alpha quality libraries may be included) >============== + +GraphViz *** http://www.graphviz.org/ + +Tkgeomap *** http://tkgeomap.sourceforge.net/index.html + + + +===< not determined to supprt or not >======================================== + +Tix *** http://tixlibrary.sourceforge.net/ + +TkZinc *** http://www.tkzinc.org/ + +Wbc *** http://home.t-online.de/home/csaba.nemethi/ + +Mentry *** http://home.t-online.de/home/csaba.nemethi/ + +Tablelist *** http://home.t-online.de/home/csaba.nemethi/ + +ANIGIF *** http://cardtable.sourceforge.net/tcltk/ + +IMG_ROTATE *** http://cardtable.sourceforge.net/tcltk/ + +TclVfs *** http://sourceforge.net/projects/tclvfs/ + +vfwtcl *** http://sourceforge.net/projects/avicaptcl + * Win32 only + +multicast *** http://sourceforge.net/projects/avicaptcl + * Win32 only + +XBit *** http://www.geocities.com/~chengye/ + * current implementation is for Windows only + +QuickTimeTcl *** http://hem.fyristorg.com/matben/qt/ + * works under Mac OS (8,9,X) or Windows + + + +===< may not support (already exist, out of Ruby/Tk scope, and so on) >======= + +TkCon *** http://sourceforge.net/projects/tkcon + +Expect *** http://sourceforge.net/projects/expect + +TclXML *** http://sourceforge.net/projects/tclxml + +TclXSLT *** http://sourceforge.net/projects/tclxml + +TclDOM *** http://sourceforge.net/projects/tclxml + +TclSOAP *** http://sourceforge.net/projects/tclsoap + +Snack *** http://www.speech.kth.se/~kare/snack2.2.tar.gz + * use Snack for Ruby + (see http://rbsnack.sourceforge.net/) + +Tcom *** http://www.vex.net/~cthuang/tcom/ + +tDOM *** http://www.tdom.org + +Mk4tcl *** http://www.equi4.com/metakit/tcl.html + +Memchan *** http://sourceforge.net/projects/memchan + +XOTcl *** http://www.xotcl.org/ + + +===< tool (may not supprt) >================================================== + +tbcload/tclcompiler + *** http://www.tcl.tk/software/tclpro/ + + +(End of List) diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt.rb b/jni/ruby/ext/tk/lib/tkextlib/blt.rb new file mode 100644 index 0000000..8b132e4 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt.rb @@ -0,0 +1,189 @@ +# +# BLT support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/variable' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/blt/setup.rb' + +# load all image format handlers +#TkPackage.require('BLT', '2.4') +TkPackage.require('BLT') + +module Tk + module BLT + TkComm::TkExtlibAutoloadModule.unshift(self) + # Require autoload-symbols which is a same name as widget classname. + # Those are used at TkComm._genobj_for_tkwidget method. + + extend TkCore + + VERSION = tk_call('set', 'blt_version') + PATCH_LEVEL = tk_call('set', 'blt_patchLevel') + + begin + lib = TkCore::INTERP._invoke('set', 'blt_library') + rescue + lib = '' + end + LIBRARY = TkVarAccess.new('blt_library', lib) + + begin + lib = TkCore::INTERP._invoke('set', 'blt_libPath') + rescue + lib = '' + end + LIB_PATH = TkVarAccess.new('blt_libPath', lib) + + PACKAGE_NAME = 'BLT'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('BLT') + rescue + '' + end + end + + #################################################### + + def self.beep(percent = 50) + tk_call('::blt::beep', percent) + end + + def self.bgexec(*args) + if args[0].kind_of?(TkVariable) + var = args.shift + else + var = TkVariable.new + end + params = [var] + + params.concat(hash_kv(args.shift, true)) if args[0].kind_of?(Hash) + + params << '--' if args[0] =~ /^\s*-[^-]/ + params.concat(args) + + tk_call('::blt::bgexec', *params) + var + end + + def self.detach_bgexec(*args) + if args[0].kind_of?(TkVariable) + var = args.shift + else + var = TkVariable.new + end + params = [var] + + params.concat(hash_kv(args.shift, true)) if args[0].kind_of?(Hash) + + params << '--' if args[0] =~ /^\s*-[^-]/ + params.concat(args) + params << '&' + + [var, tk_split_list(tk_call('::blt::bgexec', *params))] + end + + def self.bltdebug(lvl = nil) + if lvl + tk_call('::blt::bltdebug', lvl) + else + number(tk_call('::blt::bltdebug')) + end + end + + def self.crc32_file(name) + tk_call_without_enc('::blt::crc32', name) + end + def self.crc32_data(dat) + tk_call_without_enc('::blt::crc32', '-data', dat) + end + + #################################################### + + def self.active_legend(graph) + tk_call_without_enc('Blt_ActiveLegend', graph) + end + def self.crosshairs(graph) + tk_call_without_enc('Blt_Crosshairs', graph) + end + def self.zoom_stack(graph) + tk_call_without_enc('Blt_ZoomStack', graph) + end + def self.print_key(graph) + tk_call_without_enc('Blt_PrintKey', graph) + end + def self.closest_point(graph) + tk_call_without_enc('Blt_ClosestPoint', graph) + end + + module GraphCommand + def active_legend + tk_call_without_enc('Blt_ActiveLegend', @path) + self + end + def crosshairs + tk_call_without_enc('Blt_Crosshairs', @path) + self + end + def zoom_stack + tk_call_without_enc('Blt_ZoomStack', @path) + self + end + def print_key + tk_call_without_enc('Blt_PrintKey', @path) + self + end + def closest_point + tk_call_without_enc('Blt_ClosestPoint', @path) + self + end + end + + #################################################### + + autoload :PlotComponent,'tkextlib/blt/component.rb' + + autoload :Barchart, 'tkextlib/blt/barchart.rb' + autoload :Bitmap, 'tkextlib/blt/bitmap.rb' + autoload :Busy, 'tkextlib/blt/busy.rb' + autoload :Container, 'tkextlib/blt/container.rb' + autoload :CutBuffer, 'tkextlib/blt/cutbuffer.rb' + autoload :DragDrop, 'tkextlib/blt/dragdrop.rb' + autoload :EPS, 'tkextlib/blt/eps.rb' + autoload :Htext, 'tkextlib/blt/htext.rb' + autoload :Graph, 'tkextlib/blt/graph.rb' + autoload :Spline, 'tkextlib/blt/spline.rb' + autoload :Stripchart, 'tkextlib/blt/stripchart.rb' + autoload :Table, 'tkextlib/blt/table.rb' + autoload :Tabnotebook, 'tkextlib/blt/tabnotebook.rb' + autoload :Tabset, 'tkextlib/blt/tabset.rb' + autoload :Ted, 'tkextlib/blt/ted.rb' + autoload :Tile, 'tkextlib/blt/tile.rb' + autoload :Tree, 'tkextlib/blt/tree.rb' + autoload :TreeView, 'tkextlib/blt/treeview.rb' + autoload :Hiertable, 'tkextlib/blt/treeview.rb' + # Hierbox is obsolete + autoload :Vector, 'tkextlib/blt/vector.rb' + autoload :VectorAccess, 'tkextlib/blt/vector.rb' + autoload :Watch, 'tkextlib/blt/watch.rb' + autoload :Winop, 'tkextlib/blt/winop.rb' + autoload :WinOp, 'tkextlib/blt/winop.rb' + + # Unix only + autoload :DnD, 'tkextlib/blt/unix_dnd.rb' + + # Windows only + autoload :Printer, 'tkextlib/blt/win_printer.rb' + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/barchart.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/barchart.rb new file mode 100644 index 0000000..a86b91c --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/barchart.rb @@ -0,0 +1,79 @@ +# +# tkextlib/blt/barchart.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/blt.rb' +require 'tkextlib/blt/component.rb' + +module Tk::BLT + class Barchart < TkWindow + TkCommandNames = ['::blt::barchart'.freeze].freeze + WidgetClassName = 'Barchart'.freeze + WidgetClassNames[WidgetClassName] ||= self + + include PlotComponent + include GraphCommand + + def __boolval_optkeys + ['bufferelements', 'buffergraph', 'invertxy'] + end + private :__boolval_optkeys + + def __strval_optkeys + ['text', 'label', 'title', 'file', + 'background', 'plotbackground'] + end + private :__strval_optkeys + + def __tkvariable_optkeys + super() << 'colormap' << 'fontmap' + end + private :__tkvariable_optkeys + +=begin + BarElement_ID = ['blt_barchart_bar'.freeze, TkUtil.untrust('00000')].freeze + + def bar(elem=nil, keys={}) + if elem.kind_of?(Hash) + keys = elem + elem = nil + end + unless elem + elem = BarElement_ID.join(TkCore::INTERP._ip_id_).freeze + BarElement_ID[1].succ! + end + tk_send('bar', elem, keys) + Element.new(self, elem, :without_creating=>true) + end +=end + + def extents(item) + num_or_str(tk_send_without_enc('extents', item)) + end + + def invtransform(x, y) + list(tk_send_without_enc('invtransform', x, y)) + end + + def inside(x, y) + bool(tk_send_without_enc('inside', x, y)) + end + + def metafile(file=None) + # Windows only + tk_send('metafile', file) + self + end + + def snap(output, keys={}) + tk_send_without_enc('snap', *(hash_kv(keys, false) + output)) + self + end + + def transform(x, y) + list(tk_send_without_enc('transform', x, y)) + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/bitmap.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/bitmap.rb new file mode 100644 index 0000000..3254b63 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/bitmap.rb @@ -0,0 +1,112 @@ +# +# tkextlib/blt/bitmap.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/blt.rb' + +module Tk::BLT + class Bitmap < TkObject + extend TkCore + + TkCommandNames = ['::blt::bitmap'.freeze].freeze + + BITMAP_ID_TBL = TkCore::INTERP.create_table + + (BITMAP_ID = ['blt_bitmap_id'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + TkCore::INTERP.init_ip_env{ + BITMAP_ID_TBL.mutex.synchronize{ BITMAP_ID_TBL.clear } + } + + def self.data(name) + dat = tk_simple_list(tk_call('::blt::bitmap', 'data', name)) + [ tk_split_list(dat[0]), tk_simple_list(dat[1]) ] + end + + def self.exist?(name) + bool(tk_call('::blt::bitmap', 'exists', name)) + end + + def self.height(name) + number(tk_call('::blt::bitmap', 'height', name)) + end + + def self.width(name) + number(tk_call('::blt::bitmap', 'width', name)) + end + + def self.source(name) + tk_simple_list(tk_call('::blt::bitmap', 'source', name)) + end + + ################################# + + class << self + alias _new new + + def new(data, keys={}) + _new(:data, nil, data, keys) + end + alias define new + + def new_with_name(name, data, keys={}) + _new(:data, name, data, keys) + end + alias define_with_name new_with_name + + def compose(text, keys={}) + _new(:text, nil, text, keys) + end + + def compose_with_name(name, text, keys={}) + _new(:text, name, text, keys) + end + end + + def initialize(type, name, data, keys = {}) + if name + @id = name + else + BITMAP_ID.mutex.synchronize{ + @id = BITMAP_ID.join(TkCore::INTERP._ip_id_) + BITMAP_ID[1].succ! + } + BITMAP_ID_TBL.mutex.synchronize{ + BITMAP_ID_TBL[@id] = self + } + end + + @path = @id + + unless bool(tk_call('::blt::bitmap', 'exists', @id)) + if type == :text + tk_call('::blt::bitmap', 'compose', @id, data, *hash_kv(keys)) + else # :data + tk_call('::blt::bitmap', 'define', @id, data, *hash_kv(keys)) + end + end + end + + def exist? + bool(tk_call('::blt::bitmap', 'exists', @id)) + end + + def height + number(tk_call('::blt::bitmap', 'height', @id)) + end + + def width + number(tk_call('::blt::bitmap', 'width', @id)) + end + + def source + tk_simple_list(tk_call('::blt::bitmap', 'source', @id)) + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/busy.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/busy.rb new file mode 100644 index 0000000..b5287fb --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/busy.rb @@ -0,0 +1,83 @@ +# +# tkextlib/blt/busy.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/itemconfig.rb' +require 'tkextlib/blt.rb' + +module Tk::BLT + module Busy + extend TkCore + extend TkItemConfigMethod + + TkCommandNames = ['::blt::busy'.freeze].freeze + + ########################### + + class Shield < TkWindow + def self.shield_path(win) + win = window(win) unless win.kind_of?(TkWindow) + if win.kind_of?(Tk::Toplevel) + win.path + '._Busy' + else + win.path + '_Busy' + end + end + + def initialize(win) + @path = self.class.shield_path(win) + end + end + + def self.shield_path(win) + Tk::BLT::Busy::Shield.shield_path(win) + end + end +end + +class << Tk::BLT::Busy + def __item_config_cmd(win) + ['::blt::busy', 'configure', win] + end + private :__item_config_cmd + + undef itemcget + undef itemcget_tkstring + alias configure itemconfigure + alias configinfo itemconfiginfo + alias current_configinfo current_itemconfiginfo + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo + + ################################## + + def hold(win, keys={}) + tk_call('::blt::busy', 'hold', win, *hash_kv(keys)) + end + + def release(*wins) + tk_call('::blt::busy', 'release', *wins) + end + + def forget(*wins) + tk_call('::blt::busy', 'forget', *wins) + end + + def is_busy(pat=None) + tk_split_list(tk_call('::blt::busy', 'isbusy', pat)) + end + + def names(pat=None) + tk_split_list(tk_call('::blt::busy', 'names', pat)) + end + alias windows names + + def check(win) + bool(tk_call('::blt::busy', 'check', win)) + end + + def status(win) + bool(tk_call('::blt::busy', 'status', win)) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/component.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/component.rb new file mode 100644 index 0000000..c7ea213 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/component.rb @@ -0,0 +1,2218 @@ +# +# tkextlib/blt/component.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/blt.rb' + +module Tk::BLT + module PlotComponent + include TkItemConfigMethod + + module OptKeys + def __item_font_optkeys(id) + ['font', 'tickfont', 'titlefont'] + end + private :__item_font_optkeys + + def __item_numstrval_optkeys(id) + ['xoffset', 'yoffset'] + end + private :__item_numstrval_optkeys + + def __item_boolval_optkeys(id) + ['hide', 'under', 'descending', 'logscale', 'loose', 'showticks', + 'titlealternate', 'scalesymbols', 'minor', 'raised', + 'center', 'decoration', 'landscape', 'maxpect'] + end + private :__item_boolval_optkeys + + def __item_strval_optkeys(id) + ['text', 'label', 'limits', 'title', + 'show', 'file', 'maskdata', 'maskfile', + 'color', 'titlecolor', 'fill', 'outline', 'offdash'] + end + private :__item_strval_optkeys + + def __item_listval_optkeys(id) + ['bindtags'] + end + private :__item_listval_optkeys + + def __item_numlistval_optkeys(id) + ['dashes', 'majorticks', 'minorticks'] + end + private :__item_numlistval_optkeys + + def __item_tkvariable_optkeys(id) + ['variable', 'textvariable', 'colormap', 'fontmap'] + end + private :__item_tkvariable_optkeys + end + + include OptKeys + + def __item_cget_cmd(id) + if id.kind_of?(Array) + # id := [ type, name ] + [self.path, id[0], 'cget', id[1]] + else + [self.path, id, 'cget'] + end + end + private :__item_cget_cmd + + def __item_config_cmd(id) + if id.kind_of?(Array) + # id := [ type, name, ... ] + type, *names = id + [self.path, type, 'configure'].concat(names) + else + [self.path, id, 'configure'] + end + end + private :__item_config_cmd + + def __item_pathname(id) + if id.kind_of?(Array) + id = tagid(id[1]) + end + [self.path, id].join(';') + end + private :__item_pathname + + def axis_cget_tkstring(id, option) + ret = itemcget_tkstring(['axis', tagid(id)], option) + end + def axis_cget(id, option) + ret = itemcget(['axis', tagid(id)], option) + end + def axis_cget_strict(id, option) + ret = itemcget_strict(['axis', tagid(id)], option) + end + def axis_configure(*args) + slot = args.pop + if slot.kind_of?(Hash) + value = None + slot = _symbolkey2str(slot) + if cmd = slot.delete('command') + slot['command'] = proc{|w, tick| + cmd.call(TkComm.window(w), TkComm.num_or_str(tick)) + } + end + else + value = slot + slot = args.pop + if slot == :command || slot == 'command' + cmd = value + value = proc{|w, tick| + cmd.call(TkComm.window(w), TkComm.num_or_str(tick)) + } + end + end + id_list = args.flatten.collect!{|id| tagid(id)}.unshift('axis') + itemconfigure(id_list, slot, value) + end + def axis_configinfo(id, slot=nil) + itemconfiginfo(['axis', tagid(id)], slot) + end + def current_axis_configinfo(id, slot=nil) + current_itemconfiginfo(['axis', tagid(id)], slot) + end + + def crosshairs_cget_tkstring(option) + itemcget_tkstring('crosshairs', option) + end + def crosshairs_cget(option) + itemcget('crosshairs', option) + end + def crosshairs_cget_strict(option) + itemcget_strict('crosshairs', option) + end + def crosshairs_configure(slot, value=None) + itemconfigure('crosshairs', slot, value) + end + def crosshairs_configinfo(slot=nil) + itemconfiginfo('crosshairs', slot) + end + def current_crosshairs_configinfo(slot=nil) + current_itemconfiginfo('crosshairs', slot) + end + + def element_cget_tkstring(id, option) + itemcget_tkstring(['element', tagid(id)], option) + end + def element_cget(id, option) + itemcget(['element', tagid(id)], option) + end + def element_cget_strict(id, option) + itemcget_strict(['element', tagid(id)], option) + end + def element_configure(*args) + slot = args.pop + if slot.kind_of?(Hash) + value = None + else + value = slot + slot = args.pop + end + id_list = args.flatten.collect!{|id| tagid(id)}.unshift('element') + itemconfigure(id_list, slot, value) + end + def element_configinfo(id, slot=nil) + itemconfiginfo(['element', tagid(id)], slot) + end + def current_element_configinfo(id, slot=nil) + current_itemconfiginfo(['element', tagid(id)], slot) + end + + def bar_cget_tkstring(id, option) + itemcget_tkstring(['bar', tagid(id)], option) + end + def bar_cget(id, option) + itemcget(['bar', tagid(id)], option) + end + def bar_cget_strict(id, option) + itemcget_strict(['bar', tagid(id)], option) + end + def bar_configure(*args) + slot = args.pop + if slot.kind_of?(Hash) + value = None + else + value = slot + slot = args.pop + end + id_list = args.flatten.collect!{|id| tagid(id)}.unshift('bar') + itemconfigure(id_list, slot, value) + end + def bar_configinfo(id, slot=nil) + itemconfiginfo(['bar', tagid(id)], slot) + end + def current_bar_configinfo(id, slot=nil) + current_itemconfiginfo(['bar', tagid(id)], slot) + end + + def line_cget_tkstring(id, option) + itemcget_tkstring(['line', tagid(id)], option) + end + def line_cget(id, option) + itemcget(['line', tagid(id)], option) + end + def line_cget_strict(id, option) + itemcget_strict(['line', tagid(id)], option) + end + def line_configure(*args) + slot = args.pop + if slot.kind_of?(Hash) + value = None + else + value = slot + slot = args.pop + end + id_list = args.flatten.collect!{|id| tagid(id)}.unshift('line') + itemconfigure(id_list, slot, value) + end + def line_configinfo(id, slot=nil) + itemconfiginfo(['line', tagid(id)], slot) + end + def current_line_configinfo(id, slot=nil) + current_itemconfiginfo(['line', tagid(id)], slot) + end + + def gridline_cget_tkstring(option) + itemcget_tkstring('grid', option) + end + def gridline_cget(option) + itemcget('grid', option) + end + def gridline_cget_strict(option) + itemcget_strict('grid', option) + end + def gridline_configure(slot, value=None) + itemconfigure('grid', slot, value) + end + def gridline_configinfo(slot=nil) + itemconfiginfo('grid', slot) + end + def current_gridline_configinfo(slot=nil) + current_itemconfiginfo('grid', slot) + end + + def legend_cget_tkstring(option) + itemcget_tkstring('legend', option) + end + def legend_cget(option) + itemcget('legend', option) + end + def legend_cget_strict(option) + itemcget_strict('legend', option) + end + def legend_configure(slot, value=None) + itemconfigure('legend', slot, value) + end + def legend_configinfo(slot=nil) + itemconfiginfo('legend', slot) + end + def current_legend_configinfo(slot=nil) + current_itemconfiginfo('legend', slot) + end + + def pen_cget_tkstring(id, option) + itemcget_tkstring(['pen', tagid(id)], option) + end + def pen_cget(id, option) + itemcget(['pen', tagid(id)], option) + end + def pen_cget_strict(id, option) + itemcget_strict(['pen', tagid(id)], option) + end + def pen_configure(*args) + slot = args.pop + if slot.kind_of?(Hash) + value = None + else + value = slot + slot = args.pop + end + id_list = args.flatten.collect!{|id| tagid(id)}.unshift('pen') + itemconfigure(id_list, slot, value) + end + def pen_configinfo(id, slot=nil) + itemconfiginfo(['pen', tagid(id)], slot) + end + def current_pen_configinfo(id, slot=nil) + current_itemconfiginfo(['pen', tagid(id)], slot) + end + + def postscript_cget_tkstring(option) + itemcget_tkstring('postscript', option) + end + def postscript_cget(option) + itemcget('postscript', option) + end + def postscript_cget_strict(option) + itemcget_strict('postscript', option) + end + def postscript_configure(slot, value=None) + itemconfigure('postscript', slot, value) + end + def postscript_configinfo(slot=nil) + itemconfiginfo('postscript', slot) + end + def current_postscript_configinfo(slot=nil) + current_itemconfiginfo('postscript', slot) + end + + def marker_cget_tkstring(id, option) + itemcget_tkstring(['marker', tagid(id)], option) + end + def marker_cget(id, option) + itemcget(['marker', tagid(id)], option) + end + def marker_cget_strict(id, option) + itemcget_strict(['marker', tagid(id)], option) + end + def marker_configure(*args) + slot = args.pop + if slot.kind_of?(Hash) + value = None + else + value = slot + slot = args.pop + end + id_list = args.flatten.collect!{|id| tagid(id)}.unshift('marker') + itemconfigure(id_list, slot, value) + end + def marker_configinfo(id, slot=nil) + itemconfiginfo(['marker', tagid(id)], slot) + end + def current_marker_configinfo(id, slot=nil) + current_itemconfiginfo(['marker', tagid(id)], slot) + end + + alias __itemcget_tkstring itemcget_tkstring + alias __itemcget itemcget + alias __itemcget_strict itemcget_strict + alias __itemconfiginfo itemconfiginfo + alias __current_itemconfiginfo current_itemconfiginfo + private :__itemcget_tkstring, :__itemcget, :__itemconfiginfo, :__current_itemconfiginfo + + def itemcget_tkstring(tagOrId, option) + __itemcget_tkstring(tagid(tagOrId), option) + end + def itemcget_strict(tagOrId, option) + ret = __itemcget(tagid(tagOrId), option) + if option == 'bindtags' || option == :bindtags + ret.collect{|tag| TkBindTag.id2obj(tag)} + else + ret + end + end + def itemcget(tagOrId, option) + unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + itemcget_strict(tagOrId, option) + else + begin + itemcget_strict(tagOrId, option) + rescue => e + begin + if current_itemconfiginfo(tagOrId).has_key?(option.to_s) + # error on known option + fail e + else + # unknown option + nil + end + rescue + fail e # tag error + end + end + end + end + def itemconfiginfo(tagOrId, slot = nil) + ret = __itemconfiginfo(tagid(tagOrId), slot) + + if TkComm::GET_CONFIGINFO_AS_ARRAY + if slot + if slot == 'bindtags' || slot == :bindtags + ret[-2] = ret[-2].collect{|tag| TkBindTag.id2obj(tag)} + ret[-1] = ret[-1].collect{|tag| TkBindTag.id2obj(tag)} + end + else + if (inf = ret.assoc('bindtags')) + inf[-2] = inf[-2].collect{|tag| TkBindTag.id2obj(tag)} + inf[-1] = inf[-1].collect{|tag| TkBindTag.id2obj(tag)} + end + end + + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY + if (inf = ret['bindtags']) + inf[-2] = inf[-2].collect{|tag| TkBindTag.id2obj(tag)} + inf[-1] = inf[-1].collect{|tag| TkBindTag.id2obj(tag)} + ret['bindtags'] = inf + end + end + + ret + end + def current_itemconfiginfo(tagOrId, slot = nil) + ret = __current_itemconfiginfo(tagid(tagOrId), slot) + + if (val = ret['bindtags']) + ret['bindtags'] = val.collect{|tag| TkBindTag.id2obj(tag)} + end + + ret + end + + private :itemcget_tkstring, :itemcget, :itemcget_strict + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo + + ################# + + class Axis < TkObject + (OBJ_ID = ['blt_chart_axis'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + AxisID_TBL = TkCore::INTERP.create_table + + TkCore::INTERP.init_ip_env{ + AxisID_TBL.mutex.synchronize{ AxisID_TBL.clear } + } + + def self.id2obj(chart, id) + cpath = chart.path + AxisID_TBL.mutex.synchronize{ + return id unless AxisID_TBL[cpath] + AxisID_TBL[cpath][id]? AxisID_TBL[cpath][id]: id + } + end + + def self.new(chart, axis=nil, keys={}) + if axis.kind_of?(Hash) + keys = axis + axis = nil + end + if keys + keys = _symbolkey2str(keys) + not_create = keys.delete('without_creating') + else + not_create = false + end + + obj = nil + AxisID_TBL.mutex.synchronize{ + chart_path = chart.path + AxisID_TBL[chart_path] ||= {} + if axis && AxisID_TBL[chart_path][axis] + obj = AxisID_TBL[chart_path][axis] + else + (obj = self.allocate).instance_eval{ + if axis + @axis = @id = axis.to_s + else + OBJ_ID.mutex.synchronize{ + @axis = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze + OBJ_ID[1].succ! + } + end + @path = @id + @parent = @chart = chart + @cpath = @chart.path + Axis::AxisID_TBL[@cpath][@axis] = self + unless not_create + tk_call(@chart, 'axis', 'create', @axis, keys) + return obj + end + } + end + } + + obj.configure(keys) if obj && ! keys.empty? + obj + end + + def initialize(chart, axis=nil, keys={}) + # dummy:: not called by 'new' method + + if axis.kind_of?(Hash) + keys = axis + axis = nil + end + if axis + @axis = @id = axis.to_s + else + OBJ_ID.mutex.synchronize{ + @axis = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze + OBJ_ID[1].succ! + } + end + @path = @id + @parent = @chart = chart + @cpath = @chart.path + # Axis::AxisID_TBL[@cpath][@axis] = self + keys = _symbolkey2str(keys) + unless keys.delete('without_creating') + # @chart.axis_create(@axis, keys) + tk_call(@chart, 'axis', 'create', @axis, keys) + end + end + + def id + @id + end + + def to_eval + @id + end + + def cget_tkstring(option) + @chart.axis_cget_tkstring(@id, option) + end + def cget(option) + @chart.axis_cget(@id, option) + end + def cget_strict(option) + @chart.axis_cget_strict(@id, option) + end + def configure(key, value=None) + @chart.axis_configure(@id, key, value) + self + end + def configinfo(key=nil) + @chart.axis_configinfo(@id, key) + end + def current_configinfo(key=nil) + @chart.current_axis_configinfo(@id, key) + end + + def command(cmd=nil, &b) + if cmd + configure('command', cmd) + elsif b + configure('command', Proc.new(&b)) + else + cget('command') + end + end + + def delete + @chart.axis_delete(@id) + self + end + + def invtransform(val) + @chart.axis_invtransform(@id, val) + end + + def limits + @chart.axis_limits(@id) + end + + def name + @axis + end + + def transform(val) + @chart.axis_transform(@id, val) + end + + def view + @chart.axis_view(@id) + self + end + + def use(name=None) # if @id == xaxis | x2axis | yaxis | y2axis + @chart.axis_use(@id, name) + end + + def use_as(axis) # axis := xaxis | x2axis | yaxis | y2axis + @chart.axis_use(axis, @id) + end + end + + ################# + + class Crosshairs < TkObject + CrosshairsID_TBL = TkCore::INTERP.create_table + + TkCore::INTERP.init_ip_env{ + CrosshairsID_TBL.mutex.synchronize{ CrosshairsID_TBL.clear } + } + + def self.new(chart, keys={}) + obj = nil + CrosshairsID_TBL.mutex.synchronize{ + unless (obj = CrosshairsID_TBL[chart.path]) + (obj = self.allocate).instance_eval{ + @parent = @chart = chart + @cpath = @chart.path + @path = @id = 'crosshairs' + Crosshairs::CrosshairsID_TBL[@cpath] = self + } + end + } + chart.crosshair_configure(keys) if obj && ! keys.empty? + obj + end + + def initialize(chart, keys={}) + # dummy:: not called by 'new' method + + @parent = @chart = chart + @cpath = @chart.path + # Crosshairs::CrosshairsID_TBL[@cpath] = self + @chart.crosshair_configure(keys) unless keys.empty? + @path = @id = 'crosshairs' + end + + def id + @id + end + + def to_eval + @id + end + + def cget_tkstring(option) + @chart.crosshair_cget_tkstring(option) + end + def cget(option) + @chart.crosshair_cget(option) + end + def cget_strict(option) + @chart.crosshair_cget_strict(option) + end + def configure(key, value=None) + @chart.crosshair_configure(key, value) + self + end + def configinfo(key=nil) + @chart.crosshair_configinfo(key) + end + def current_configinfo(key=nil) + @chart.current_crosshair_configinfo(key) + end + + def off + @chart.crosshair_off + self + end + def on + @chart.crosshair_on + self + end + def toggle + @chart.crosshair_toggle + self + end + end + + ################# + + class Element < TkObject + extend Tk + extend TkItemFontOptkeys + extend TkItemConfigOptkeys + + extend Tk::BLT::PlotComponent::OptKeys + + ElementTypeName = 'element' + ElementTypeToClass = { ElementTypeName=>self } + + ElementID_TBL = TkCore::INTERP.create_table + + TkCore::INTERP.init_ip_env{ + ElementID_TBL.mutex.synchronize{ ElementID_TBL.clear } + } + + (OBJ_ID = ['blt_chart_element'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + def Element.type2class(type) + ElementTypeToClass[type] + end + + def Element.id2obj(chart, id) + cpath = chart.path + ElementID_TBL.mutex.synchronize{ + return id unless ElementID_TBL[cpath] + ElementID_TBL[cpath][id]? ElementID_TBL[cpath][id]: id + } + end + + def self.new(chart, element=nil, keys={}) + if element.kind_of?(Hash) + keys = element + element = nil + end + if keys + keys = _symbolkey2str(keys) + not_create = keys.delete('without_creating') + else + not_create = false + end + + obj = nil + ElementID_TBL.mutex.synchronize{ + chart_path = chart.path + ElementID_TBL[chart_path] ||= {} + if element && ElementID_TBL[chart_path][element] + obj = ElementID_TBL[chart_path][element] + else + (obj = self.allocate).instance_eval{ + if element + @element = @id = element.to_s + else + OBJ_ID.mutex.synchronize{ + @element = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze + OBJ_ID[1].succ! + } + end + @path = @id + @parent = @chart = chart + @cpath = @chart.path + @typename = self.class::ElementTypeName + Element::ElementID_TBL[@cpath][@element] = self + unless not_create + tk_call(@chart, @typename, 'create', @element, keys) + return obj + end + } + end + } + + obj.configure(keys) if obj && ! keys.empty? + obj + end + + def initialize(chart, element=nil, keys={}) + # dummy:: not called by 'new' method + + if element.kind_of?(Hash) + keys = element + element = nil + end + if element + @element = @id = element.to_s + else + OBJ_ID.mutex.synchronize{ + @element = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze + OBJ_ID[1].succ! + } + end + @path = @id + @parent = @chart = chart + @cpath = @chart.path + @typename = self.class::ElementTypeName + # Element::ElementID_TBL[@cpath][@element] = self + keys = _symbolkey2str(keys) + unless keys.delete('without_creating') + # @chart.element_create(@element, keys) + tk_call(@chart, @typename, 'create', @element, keys) + end + end + + def id + @id + end + + def to_eval + @id + end + + def cget_tkstring(option) + # @chart.element_cget(@id, option) + @chart.__send__(@typename + '_cget_tkstring', @id, option) + end + def cget(option) + # @chart.element_cget(@id, option) + @chart.__send__(@typename + '_cget', @id, option) + end + def cget_strict(option) + @chart.__send__(@typename + '_cget_strict', @id, option) + end + def configure(key, value=None) + # @chart.element_configure(@id, key, value) + @chart.__send__(@typename + '_configure', @id, key, value) + self + end + def configinfo(key=nil) + # @chart.element_configinfo(@id, key) + @chart.__send__(@typename + '_configinfo', @id, key) + end + def current_configinfo(key=nil) + # @chart.current_element_configinfo(@id, key) + @chart.__send__('current_' << @typename << '_configinfo', @id, key) + end + + def activate(*args) + @chart.element_activate(@id, *args) + end + + def closest(x, y, var, keys={}) + # @chart.element_closest(x, y, var, @id, keys) + @chart.__send__(@typename + '_closest', x, y, var, @id, keys) + end + + def deactivate + @chart.element_deactivate(@id) + self + end + + def delete + @chart.element_delete(@id) + self + end + + def exist? + @chart.element_exist?(@id) + end + + def name + @element + end + + def type + @chart.element_type(@id) + end + end + + class Bar < Element + ElementTypeName = 'bar'.freeze + ElementTypeToClass[ElementTypeName] = self + end + class Line < Element + ElementTypeName = 'line'.freeze + ElementTypeToClass[ElementTypeName] = self + end + + ################# + + class GridLine < TkObject + GridLineID_TBL = TkCore::INTERP.create_table + TkCore::INTERP.init_ip_env{ + GridLineID_TBL.mutex.synchronize{ GridLineID_TBL.clear } + } + + def self.new(chart, keys={}) + obj = nil + GridLineID_TBL.mutex.synchronize{ + unless (obj = GridLineID_TBL[chart.path]) + (obj = self.allocate).instance_eval{ + @parent = @chart = chart + @cpath = @chart.path + @path = @id = 'grid' + GridLine::GridLineID_TBL[@cpath] = self + } + end + } + chart.gridline_configure(keys) if obj && ! keys.empty? + obj + end + + def initialize(chart, keys={}) + # dummy:: not called by 'new' method + + @parent = @chart = chart + @cpath = @chart.path + # GridLine::GridLineID_TBL[@cpath] = self + @chart.gridline_configure(keys) unless keys.empty? + @path = @id = 'grid' + end + + def id + @id + end + + def to_eval + @id + end + + def cget_tkstring(option) + @chart.gridline_cget_tkstring(option) + end + def cget(option) + @chart.gridline_cget(option) + end + def cget_strict(option) + @chart.gridline_cget_strict(option) + end + def configure(key, value=None) + @chart.gridline_configure(key, value) + self + end + def configinfo(key=nil) + @chart.gridline_configinfo(key) + end + def current_configinfo(key=nil) + @chart.current_gridline_configinfo(key) + end + + def off + @chart.gridline_off + self + end + def on + @chart.gridline_on + self + end + def toggle + @chart.gridline_toggle + self + end + end + + ################# + + class Legend < TkObject + LegendID_TBL = TkCore::INTERP.create_table + + TkCore::INTERP.init_ip_env{ + LegendID_TBL.mutex.synchronize{ LegendID_TBL.clear } + } + + def self.new(chart, keys={}) + obj = nil + LegenedID_TBL.mutex.synchronize{ + unless (obj = LegenedID_TBL[chart.path]) + (obj = self.allocate).instance_eval{ + @parent = @chart = chart + @cpath = @chart.path + @path = @id = 'crosshairs' + Legend::LegenedID_TBL[@cpath] = self + } + end + } + chart.legend_configure(keys) if obj && ! keys.empty? + obj + end + + def initialize(chart, keys={}) + # dummy:: not called by 'new' method + + @parent = @chart = chart + @cpath = @chart.path + # Legend::LegendID_TBL[@cpath] = self + @chart.legend_configure(keys) unless keys.empty? + @path = @id = 'legend' + end + + def id + @id + end + + def to_eval + @id + end + + def cget_tkstring(option) + @chart.legend_cget_tkstring(option) + end + def cget(option) + @chart.legend_cget(option) + end + def cget_strict(option) + @chart.legend_cget_strict(option) + end + def configure(key, value=None) + @chart.legend_configure(key, value) + self + end + def configinfo(key=nil) + @chart.legend_configinfo(key) + end + def current_configinfo(key=nil) + @chart.current_legend_configinfo(key) + end + + def activate(*args) + @chart.legend_activate(*args) + end + + def deactivate(*args) + @chart.legend_deactivate(*args) + end + + def get(pos, y=nil) + @chart.legend_get(pos, y) + end + end + + ################# + + class Pen < TkObject + (OBJ_ID = ['blt_chart_pen'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + PenID_TBL = TkCore::INTERP.create_table + + TkCore::INTERP.init_ip_env{ + PenID_TBL.mutex.synchronize{ PenID_TBL.clear } + } + + def self.id2obj(chart, id) + cpath = chart.path + PenID_TBL.mutex.synchronize{ + return id unless PenID_TBL[cpath] + PenID_TBL[cpath][id]? PenID_TBL[cpath][id]: id + } + end + + def self.new(chart, pen=nil, keys={}) + if pen.kind_of?(Hash) + keys = pen + pen = nil + end + if keys + keys = _symbolkey2str(keys) + not_create = keys.delete('without_creating') + else + not_create = false + end + + obj = nil + PenID_TBL.mutex.synchronize{ + chart_path = chart.path + PenID_TBL[chart_path] ||= {} + if pen && PenID_TBL[chart_path][pen] + obj = PenID_TBL[chart_path][pen] + else + (obj = self.allocate).instance_eval{ + if pen + @pen = @id = pen.to_s + else + OBJ_ID.mutex.synchronize{ + @pen = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze + OBJ_ID[1].succ! + } + end + @path = @id + @parent = @chart = chart + @cpath = @chart.path + Pen::PenID_TBL[@cpath][@pen] = self + unless not_create + tk_call(@chart, 'pen', 'create', @pen, keys) + return obj + end + } + end + } + + obj.configure(keys) if obj && ! keys.empty? + obj + end + + def initialize(chart, pen=nil, keys={}) + if pen.kind_of?(Hash) + keys = pen + pen = nil + end + if pen + @pen = @id = pen.to_s + else + OBJ_ID.mutex.synchronize{ + @pen = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze + OBJ_ID[1].succ! + } + end + @path = @id + @parent = @chart = chart + @cpath = @chart.path + Pen::PenID_TBL[@cpath][@pen] = self + keys = _symbolkey2str(keys) + unless keys.delete('without_creating') + # @chart.pen_create(@pen, keys) + tk_call(@chart, 'pen', 'create', @pen, keys) + end + end + + def id + @id + end + + def to_eval + @id + end + + def cget_tkstring(option) + @chart.pen_cget_tkstring(@id, option) + end + def cget(option) + @chart.pen_cget(@id, option) + end + def cget_strict(option) + @chart.pen_cget_strict(@id, option) + end + def configure(key, value=None) + @chart.pen_configure(@id, key, value) + self + end + def configinfo(key=nil) + @chart.pen_configinfo(@id, key) + end + def current_configinfo(key=nil) + @chart.current_pen_configinfo(@id, key) + end + + def delete + @chart.pen_delete(@id) + self + end + + def name + @pen + end + end + + ################# + + class Postscript < TkObject + PostscriptID_TBL = TkCore::INTERP.create_table + + TkCore::INTERP.init_ip_env{ + PostscriptID_TBL.mutex.synchronize{ PostscriptID_TBL.clear } + } + + def self.new(chart, keys={}) + obj = nil + PostscriptID_TBL.mutex.synchronize{ + unless (obj = PostscriptID_TBL[chart.path]) + (obj = self.allocate).instance_eval{ + @parent = @chart = chart + @cpath = @chart.path + @path = @id = 'postscript' + Postscript::PostscriptID_TBL[@cpath] = self + } + end + } + chart.postscript_configure(keys) if obj && ! keys.empty? + obj + end + + def initialize(chart, keys={}) + # dummy:: not called by 'new' method + + @parent = @chart = chart + @cpath = @chart.path + # Postscript::PostscriptID_TBL[@cpath] = self + @chart.postscript_configure(keys) unless keys.empty? + @path = @id = 'postscript' + end + + def id + @id + end + + def to_eval + @id + end + + def cget_tkstring(option) + @chart.postscript_cget_tkstring(option) + end + def cget(option) + @chart.postscript_cget(option) + end + def cget_strict(option) + @chart.postscript_cget_strict(option) + end + def configure(key, value=None) + @chart.postscript_configure(key, value) + self + end + def configinfo(key=nil) + @chart.postscript_configinfo(key) + end + def current_configinfo(key=nil) + @chart.current_postscript_configinfo(key) + end + + def output(file=nil, keys={}) + if file.kind_of?(Hash) + keys = file + file = nil + end + + ret = @chart.postscript_output(file, keys) + + if file + self + else + ret + end + end + end + + ################# + class Marker < TkObject + extend Tk + extend TkItemFontOptkeys + extend TkItemConfigOptkeys + + extend Tk::BLT::PlotComponent::OptKeys + + MarkerTypeName = nil + MarkerTypeToClass = {} + MarkerID_TBL = TkCore::INTERP.create_table + + TkCore::INTERP.init_ip_env{ + MarkerID_TBL.mutex.synchronize{ MarkerID_TBL.clear } + } + + def Marker.type2class(type) + MarkerTypeToClass[type] + end + + def Marker.id2obj(chart, id) + cpath = chart.path + MarkerID_TBL.mutex.synchronize{ + if MarkerID_TBL[cpath] + MarkerID_TBL[cpath][id]? MarkerID_TBL[cpath][id]: id + else + id + end + } + end + + def self._parse_create_args(keys) + fontkeys = {} + methodkeys = {} + if keys.kind_of? Hash + keys = _symbolkey2str(keys) + + __item_font_optkeys(nil).each{|key| + fkey = key.to_s + fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) + + fkey = "kanji#{key}" + fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) + + fkey = "latin#{key}" + fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) + + fkey = "ascii#{key}" + fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) + } + + __item_optkey_aliases(nil).each{|alias_name, real_name| + alias_name = alias_name.to_s + if keys.has_key?(alias_name) + keys[real_name.to_s] = keys.delete(alias_name) + end + } + + __item_methodcall_optkeys(nil).each{|key| + key = key.to_s + methodkeys[key] = keys.delete(key) if keys.key?(key) + } + + __item_ruby2val_optkeys(nil).each{|key, method| + key = key.to_s + keys[key] = method.call(keys[key]) if keys.has_key?(key) + } + + args = itemconfig_hash_kv(nil, keys) + else + args = [] + end + + [args, fontkeys, methodkeys] + end + private_class_method :_parse_create_args + + def self.create(chart, keys={}) + unless self::MarkerTypeName + fail RuntimeError, "#{self} is an abstract class" + end + args, fontkeys, methodkeys = _parse_create_args(keys) + idnum = tk_call_without_enc(chart.path, 'marker', 'create', + self::MarkerTypeName, *args) + chart.marker_configure(idnum, fontkeys) unless fontkeys.empty? + chart.marker_configure(idnum, methodkeys) unless methodkeys.empty? + idnum.to_i # 'item id' is an integer number + end + + def self.create_type(chart, type, keys={}) + args, fontkeys, methodkeys = _parse_create_args(keys) + idnum = tk_call_without_enc(chart.path, 'marker', 'create', + type, *args) + chart.marker_configure(idnum, fontkeys) unless fontkeys.empty? + chart.marker_configure(idnum, methodkeys) unless methodkeys.empty? + id = idnum.to_i # 'item id' is an integer number + obj = self.allocate + obj.instance_eval{ + @parent = @chart = chart + @cpath = chart.path + @id = id + Tk::BLT::PlotComponent::Marker::MarkerID_TBL.mutex.synchronize{ + Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath] ||= {} + Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath][@id] = self + } + } + obj + end + + def initialize(parent, *args) + @parent = @chart = parent + @cpath = parent.path + + @path = @id = create_self(*args) # an integer number as 'item id' + Tk::BLT::PlotComponent::Marker::MarkerID_TBL.mutex.synchronize{ + Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath] ||= {} + Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath][@id] = self + } + end + def create_self(*args) + self.class.create(@chart, *args) # return an integer as 'item id' + end + private :create_self + + def id + @id + end + + def to_eval + @id + end + + def cget_tkstring(option) + @chart.marker_cget_tkstring(@id, option) + end + def cget(option) + @chart.marker_cget(@id, option) + end + def cget_strict(option) + @chart.marker_cget_strict(@id, option) + end + def configure(key, value=None) + @chart.marker_configure(@id, key, value) + self + end + def configinfo(key=nil) + @chart.marker_configinfo(@id, key) + end + def current_configinfo(key=nil) + @chart.current_marker_configinfo(@id, key) + end + + def after(target=None) + @chart.marker_after(@id, target) + end + + def before(target=None) + @chart.marker_before(@id, target) + end + + def delete + @chart.marker_delete(@id) + end + + def exist? + @chart.marker_exist(@id) + end + + def type + @chart.marker_type(@id) + end + end + + class TextMarker < Marker + MarkerTypeName = 'text'.freeze + MarkerTypeToClass[MarkerTypeName] = self + end + class LineMarker < Marker + MarkerTypeName = 'line'.freeze + MarkerTypeToClass[MarkerTypeName] = self + end + class BitmapMarker < Marker + MarkerTypeName = 'bitmap'.freeze + MarkerTypeToClass[MarkerTypeName] = self + end + class ImageMarker < Marker + MarkerTypeName = 'image'.freeze + MarkerTypeToClass[MarkerTypeName] = self + end + class PolygonMarker < Marker + MarkerTypeName = 'polygon'.freeze + MarkerTypeToClass[MarkerTypeName] = self + end + class WindowMarker < Marker + MarkerTypeName = 'window'.freeze + MarkerTypeToClass[MarkerTypeName] = self + end + + ################# + + def __destroy_hook__ + Axis::AxisID_TBL.delete(@path) + Crosshairs::CrosshairsID_TBL.delete(@path) + Element::ElementID_TBL.delete(@path) + GridLine::GridLineID_TBL.delete(@path) + Legend::LegendID_TBL.delete(@path) + Pen::PenID_TBL.delete(@path) + Postscript::PostscriptID_TBL.delete(@path) + Marker::MarkerID_TBL.delete(@path) + super() + end + + ################# + + def tagid(tag) + if tag.kind_of?(Axis) || + tag.kind_of?(Crosshairs) || + tag.kind_of?(Element) || + tag.kind_of?(GridLine) || + tag.kind_of?(Legend) || + tag.kind_of?(Pen) || + tag.kind_of?(Postscript) || + tag.kind_of?(Marker) + tag.id + else + tag # maybe an Array of configure parameters + end + end + + def _component_bind(target, tag, context, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind([path, target, 'bind', tagid(tag)], context, cmd, *args) + self + end + def _component_bind_append(target, tag, context, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append([path, target, 'bind', tagid(tag)], context, cmd, *args) + self + end + def _component_bind_remove(target, tag, context) + _bind_remove([path, target, 'bind', tagid(tag)], context) + self + end + def _component_bindinfo(target, tag, context=nil) + _bindinfo([path, target, 'bind', tagid(tag)], context) + end + private :_component_bind, :_component_bind_append + private :_component_bind_remove, :_component_bindinfo + + def axis_bind(tag, context, *args) + _component_bind('axis', tag, context, *args) + end + def axis_bind_append(tag, context, *args) + _component_bind_append('axis', tag, context, *args) + end + def axis_bind_remove(tag, context) + _component_bind_remove('axis', tag, context) + end + def axis_bindinfo(tag, context=nil) + _component_bindinfo('axis', tag, context) + end + + def element_bind(tag, context, *args) + _component_bind('element', tag, context, *args) + end + def element_bind_append(tag, context, *args) + _component_bind_append('element', tag, context, *args) + end + def element_bind_remove(tag, context) + _component_bind_remove('element', tag, context) + end + def element_bindinfo(tag, context=nil) + _component_bindinfo('element', tag, context) + end + + def bar_bind(tag, context, *args) + _component_bind('bar', tag, context, *args) + end + def bar_bind_append(tag, context, *args) + _component_bind_append('bar', tag, context, *args) + end + def bar_bind_remove(tag, context) + _component_bind_remove('bar', tag, context) + end + def bar_bindinfo(tag, context=nil) + _component_bindinfo('bar', tag, context) + end + + def line_bind(tag, context, *args) + _component_bind('line', tag, context, *args) + end + def line_bind_append(tag, context, *args) + _component_bind_append('line', tag, context, *args) + end + def line_bind_remove(tag, context) + _component_bind_remove('line', tag, context) + end + def line_bindinfo(tag, context=nil) + _component_bindinfo('line', tag, context) + end + + def legend_bind(tag, context, *args) + _component_bind('legend', tag, context, *args) + end + def legend_bind_append(tag, context, *args) + _component_bind_append('legend', tag, context, *args) + end + def legend_bind_remove(tag, context) + _component_bind_remove('legend', tag, context) + end + def legend_bindinfo(tag, context=nil) + _component_bindinfo('legend', tag, context) + end + + def marker_bind(tag, context, *args) + _component_bind('marker', tag, context, *args) + end + def marker_bind_append(tag, context, *args) + _component_bind_append('marker', tag, context, *args) + end + def marker_bind_remove(tag, context) + _component_bind_remove('marker', tag, context) + end + def marker_bindinfo(tag, context=nil) + _component_bindinfo('marker', tag, context) + end + + ################### + + def axis_create(id=nil, keys={}) + # tk_send('axis', 'create', tagid(id), keys) + Tk::BLT::PlotComponent::Axis.new(self, tagid(id), keys) + end + def axis_delete(*ids) + tk_send('axis', 'delete', *(ids.collect{|id| tagid(id)})) + self + end + def axis_invtransform(id, val) + list(tk_send('axis', 'invtransform', tagid(id), val)) + end + def axis_limits(id) + list(tk_send('axis', 'limits', tagid(id))) + end + def axis_names(*pats) + simplelist(tk_send('axis', 'names', + *(pats.collect{|pat| tagid(pat)}))).collect{|axis| + Tk::BLT::PlotComponent::Axis.id2obj(self, axis) + } + end + def axis_transform(id, val) + list(tk_send('axis', 'transform', tagid(id), val)) + end + def axis_view(id) + tk_send('axis', 'view', tagid(id)) + self + end + def axis_use(id, target=nil) + if target + Tk::BLT::PlotComponent::Axis.id2obj(self, + tk_send('axis', 'use', + tagid(id), tagid(target))) + else + Tk::BLT::PlotComponent::Axis.id2obj(self, + tk_send('axis', 'use', tagid(id))) + end + end + + ################### + + def crosshairs_off + tk_send_without_enc('crosshairs', 'off') + self + end + def crosshairs_on + tk_send_without_enc('crosshairs', 'on') + self + end + def crosshairs_toggle + tk_send_without_enc('crosshairs', 'toggle') + self + end + + ################### + + def element_create(id=nil, keys={}) + # tk_send('element', 'create', tagid(id), keys) + Tk::BLT::PlotComponent::Element.new(self, tagid(id), keys) + end + def element_activate(*args) + if args.empty? + list(tk_send('element', 'activate')).collect{|elem| + Tk::BLT::PlotComponent::Element.id2obj(self, elem) + } + else + # id, *indices + id = args.shift + tk_send('element', 'activate', tagid(id), *args) + end + end + def element_closest(x, y, var, *args) + if args[-1].kind_of?(Hash) + keys = args.pop + bool(tk_send('element', 'closest', x, y, var, + *(hash_kv(keys).concat(args.collect{|id| tagid(id)})))) + else + bool(tk_send('element', 'closest', x, y, var, + *(args.collect{|id| tagid(id)}))) + end + end + def element_deactivate(*ids) + tk_send('element', 'deactivate', *(ids.collect{|id| tagid(id)})) + self + end + def element_delete(*ids) + tk_send('element', 'delete', *(ids.collect{|id| tagid(id)})) + self + end + def element_exist?(id) + bool(tk_send('element', 'exists', tagid(id))) + end + def element_names(*pats) + simplelist(tk_send('element', 'names', + *(pats.collect{|pat| tagid(pat)}))).collect{|elem| + Tk::BLT::PlotComponent::Element.id2obj(self, elem) + } + end + def element_show(*names) + if names.empty? + simplelist(tk_send('element', 'show')) + else + tk_send('element', 'show', *(names.collect{|n| tagid(n)})) + self + end + end + def element_type(id) + tk_send('element', 'type', tagid(id)) + end + + ################### + + def bar_create(id=nil, keys={}) + # tk_send('bar', 'create', tagid(id), keys) + Tk::BLT::PlotComponent::Bar.new(self, tagid(id), keys) + end + alias bar bar_create + def bar_activate(*args) + if args.empty? + list(tk_send('bar', 'activate')).collect{|elem| + Tk::BLT::PlotComponent::Element.id2obj(self, elem) + } + else + # id, *indices + id = args.shift + tk_send('bar', 'activate', tagid(id), *args) + end + end + def bar_closest(x, y, var, *args) + if args[-1].kind_of?(Hash) + keys = args.pop + bool(tk_send('bar', 'closest', x, y, var, + *(hash_kv(keys).concat(args.collect{|id| tagid(id)})))) + else + bool(tk_send('bar', 'closest', x, y, var, + *(args.collect{|id| tagid(id)}))) + end + end + def bar_deactivate(*ids) + tk_send('bar', 'deactivate', *(ids.collect{|id| tagid(id)})) + self + end + def bar_delete(*ids) + tk_send('bar', 'delete', *(ids.collect{|id| tagid(id)})) + self + end + def bar_exist?(id) + bool(tk_send('bar', 'exists', tagid(id))) + end + def bar_names(*pats) + simplelist(tk_send('bar', 'names', + *(pats.collect{|pat| tagid(pat)}))).collect{|elem| + Tk::BLT::PlotComponent::Element.id2obj(self, elem) + } + end + def bar_show(*names) + if names.empty? + simplelist(tk_send('bar', 'show')) + else + tk_send('bar', 'show', *(names.collect{|n| tagid(n)})) + self + end + end + def bar_type(id) + tk_send('bar', 'type', tagid(id)) + end + + ################### + + def line_create(id=nil, keys={}) + # tk_send('line', 'create', tagid(id), keys) + Tk::BLT::PlotComponent::Line.new(self, tagid(id), keys) + end + alias bar line_create + def line_activate(*args) + if args.empty? + list(tk_send('line', 'activate')).collect{|elem| + Tk::BLT::PlotComponent::Element.id2obj(self, elem) + } + else + # id, *indices + id = args.shift + tk_send('line', 'activate', tagid(id), *args) + end + end + def line_closest(x, y, var, *args) + if args[-1].kind_of?(Hash) + keys = args.pop + bool(tk_send('line', 'closest', x, y, var, + *(hash_kv(keys).concat(args.collect{|id| tagid(id)})))) + else + bool(tk_send('line', 'closest', x, y, var, + *(args.collect{|id| tagid(id)}))) + end + end + def line_deactivate(*ids) + tk_send('line', 'deactivate', *(ids.collect{|id| tagid(id)})) + self + end + def line_delete(*ids) + tk_send('line', 'delete', *(ids.collect{|id| tagid(id)})) + self + end + def line_exist?(id) + bool(tk_send('line', 'exists', tagid(id))) + end + def line_names(*pats) + simplelist(tk_send('line', 'names', + *(pats.collect{|pat| tagid(pat)}))).collect{|elem| + Tk::BLT::PlotComponent::Element.id2obj(self, elem) + } + end + def line_show(*names) + if names.empty? + simplelist(tk_send('line', 'show')) + else + tk_send('line', 'show', *(names.collect{|n| tagid(n)})) + self + end + end + def line_type(id) + tk_send('line', 'type', tagid(id)) + end + + ################### + + def gridline_off + tk_send_without_enc('grid', 'off') + self + end + def gridline_on + tk_send_without_enc('grid', 'on') + self + end + def gridline_toggle + tk_send_without_enc('grid', 'toggle') + self + end + + ################### + + def legend_window_create(parent=nil, keys=nil) + if parent.kind_of?(Hash) + keys = _symbolkey2str(parent) + parent = keys.delete('parent') + widgetname = keys.delete('widgetname') + keys.delete('without_creating') + elsif keys + keys = _symbolkey2str(keys) + widgetname = keys.delete('widgetname') + keys.delete('without_creating') + end + + legend = self.class.new(parent, :without_creating=>true, + :widgetname=>widgetname) + class << legend + def __destroy_hook__ + TkCore::INTERP.tk_windows.delete(@path) + end + end + + if keys + self.legend_configure(keys.update('position'=>legend)) + else + self.legend_configure('position'=>legend) + end + legend + end + + def legend_activate(*pats) + list(tk_send('legend', 'activate', + *(pats.collect{|pat| tagid(pat)}))).collect{|elem| + Tk::BLT::PlotComponent::Element.id2obj(self, elem) + } + end + def legend_deactivate(*pats) + list(tk_send('legend', 'deactivate', + *(pats.collect{|pat| tagid(pat)}))).collect{|elem| + Tk::BLT::PlotComponent::Element.id2obj(self, elem) + } + end + def legend_get(pos, y=nil) + if y + Tk::BLT::PlotComponent::Element.id2obj(self, + tk_send('legend', 'get', + _at(pos, y))) + else + Tk::BLT::PlotComponent::Element.id2obj(self, + tk_send('legend', 'get', pos)) + end + end + + ################### + + def pen_create(id=nil, keys={}) + # tk_send('pen', 'create', tagid(id), keys) + Tk::BLT::PlotComponent::Pen.new(self, tagid(id), keys) + end + def pen_delete(*ids) + tk_send('pen', 'delete', *(ids.collect{|id| tagid(id)})) + self + end + def pen_names(*pats) + simplelist(tk_send('pen', 'names', + *(pats.collect{|pat| tagid(pat)}))).collect{|pen| + Tk::BLT::PlotComponent::Pen.id2obj(self, pen) + } + end + + ################### + + def postscript_output(file=nil, keys={}) + if file.kind_of?(Hash) + keys = file + file = nil + end + + if file + tk_send('postscript', 'output', file, keys) + self + else + tk_send('postscript', 'output', keys) + end + end + + ################### + + def marker_create(type, keys={}) + case type + when :text, 'text' + Tk::BLT::PlotComponent::TextMarker.new(self, keys) + when :line, 'line' + Tk::BLT::PlotComponent::LineMarker.new(self, keys) + when :bitmap, 'bitmap' + Tk::BLT::PlotComponent::BitmapMarker.new(self, keys) + when :image, 'image' + Tk::BLT::PlotComponent::ImageMarker.new(self, keys) + when :polygon, 'polygon' + Tk::BLT::PlotComponent::PolygonMarker.new(self, keys) + when :window, 'window' + Tk::BLT::PlotComponent::WindowMarker.new(self, keys) + else + if type.kind_of?(Tk::BLT::PlotComponent::Marker) + type.new(self, keys) + else + Tk::BLT::PlotComponent::Marker.create_type(self, type, keys) + end + end + end + def marker_after(id, target=nil) + if target + tk_send_without_enc('marker', 'after', tagid(id), tagid(target)) + else + tk_send_without_enc('marker', 'after', tagid(id)) + end + self + end + def marker_before(id, target=None) + if target + tk_send_without_enc('marker', 'before', tagid(id), tagid(target)) + else + tk_send_without_enc('marker', 'before', tagid(id)) + end + self + end + def marker_delete(*ids) + tk_send('marker', 'delete', *(ids.collect{|id| tagid(id)})) + self + end + def marker_exist?(id) + bool(tk_send('marker', 'exists', tagid(id))) + end + def marker_names(*pats) + simplelist(tk_send('marker', 'names', + *(pats.collect{|pat| tagid(pat)}))).collect{|id| + Tk::BLT::PlotComponent::Marker.id2obj(self, id) + } + end + def marker_type(id) + tk_send('marker', 'type', tagid(id)) + end + + ################### + + def xaxis_cget_tkstring(option) + itemcget_tkstring('xaxis', option) + end + def xaxis_cget(option) + itemcget('xaxis', option) + end + def xaxis_cget_strict(option) + itemcget_strict('xaxis', option) + end + def xaxis_configure(slot, value=None) + if slot.kind_of?(Hash) + slot = _symbolkey2str(slot) + if cmd = slot.delete('command') + slot['command'] = proc{|w, tick| + cmd.call(TkComm.window(w), TkComm.num_or_str(tick)) + } + end + elsif slot == :command || slot == 'command' + cmd = value + value = proc{|w, tick| + cmd.call(TkComm.window(w), TkComm.num_or_str(tick)) + } + end + itemconfigure('xaxis', slot, value) + end + def xaxis_configinfo(slot=nil) + itemconfiginfo('xaxis', slot) + end + def current_xaxis_configinfo(slot=nil) + current_itemconfiginfo('xaxis', slot) + end + def xaxis_bind(context, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind([path, 'xaxis', 'bind'], context, cmd, *args) + self + end + def xaxis_bind_append(context, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append([path, 'xaxis', 'bind'], context, cmd, *args) + self + end + def xaxis_bind_remove(context) + _bind_remove([path, 'xaxis', 'bind'], context) + self + end + def xaxis_bindinfo(context=nil) + _bindinfo([path, 'xaxis', 'bind'], context) + end + def xaxis_invtransform(val) + list(tk_send('xaxis', 'invtransform', val)) + end + def xaxis_limits + list(tk_send('xaxis', 'limits')) + end + def xaxis_transform(val) + list(tk_send('xaxis', 'transform', val)) + end + def xaxis_use(target=nil) + if target + Tk::BLT::PlotComponent::Axis.id2obj(self, + tk_send('xaxis', 'use', + tagid(target))) + else + Tk::BLT::PlotComponent::Axis.id2obj(self, tk_send('xaxis', 'use')) + end + end + + def x2axis_cget_tkstring(option) + itemcget_tkstring('x2axis', option) + end + def x2axis_cget(option) + itemcget('x2axis', option) + end + def x2axis_cget_strict(option) + itemcget_strict('x2axis', option) + end + def x2axis_configure(slot, value=None) + if slot.kind_of?(Hash) + slot = _symbolkey2str(slot) + if cmd = slot.delete('command') + slot['command'] = proc{|w, tick| + cmd.call(TkComm.window(w), TkComm.num_or_str(tick)) + } + end + elsif slot == :command || slot == 'command' + cmd = value + value = proc{|w, tick| + cmd.call(TkComm.window(w), TkComm.num_or_str(tick)) + } + end + itemconfigure('x2axis', slot, value) + end + def x2axis_configinfo(slot=nil) + itemconfiginfo('x2axis', slot) + end + def current_x2axis_configinfo(slot=nil) + current_itemconfiginfo('x2axis', slot) + end + def x2axis_bind(context, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind([path, 'x2axis', 'bind'], context, cmd, *args) + self + end + def x2axis_bind_append(context, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append([path, 'x2axis', 'bind'], context, cmd, *args) + self + end + def x2axis_bind_remove(context) + _bind_remove([path, 'x2axis', 'bind'], context) + self + end + def x2axis_bindinfo(context=nil) + _bindinfo([path, 'x2axis', 'bind'], context) + end + def x2axis_invtransform(val) + list(tk_send('x2axis', 'invtransform', val)) + end + def x2axis_limits + list(tk_send('x2axis', 'limits')) + end + def x2axis_transform(val) + list(tk_send('x2axis', 'transform', val)) + end + def x2axis_use(target=nil) + if target + Tk::BLT::PlotComponent::Axis.id2obj(self, + tk_send('x2axis', 'use', + tagid(target))) + else + Tk::BLT::PlotComponent::Axis.id2obj(self, tk_send('x2axis', 'use')) + end + end + + def yaxis_cget_tkstring(option) + itemcget_tkstring('yaxis', option) + end + def yaxis_cget(option) + itemcget('yaxis', option) + end + def yaxis_cget_strict(option) + itemcget_strict('yaxis', option) + end + def yaxis_configure(slot, value=None) + if slot.kind_of?(Hash) + slot = _symbolkey2str(slot) + if cmd = slot.delete('command') + slot['command'] = proc{|w, tick| + cmd.call(TkComm.window(w), TkComm.num_or_str(tick)) + } + end + elsif slot == :command || slot == 'command' + cmd = value + value = proc{|w, tick| + cmd.call(TkComm.window(w), TkComm.num_or_str(tick)) + } + end + itemconfigure('yaxis', slot, value) + end + def yaxis_configinfo(slot=nil) + itemconfiginfo('yaxis', slot) + end + def current_yaxis_configinfo(slot=nil) + current_itemconfiginfo('yaxis', slot) + end + def yaxis_bind(context, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind([path, 'yaxis', 'bind'], context, cmd, *args) + self + end + def yaxis_bind_append(context, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append([path, 'yaxis', 'bind'], context, cmd, *args) + self + end + def yaxis_bind_remove(context) + _bind_remove([path, 'yaxis', 'bind'], context) + self + end + def yaxis_bindinfo(context=nil) + _bindinfo([path, 'yaxis', 'bind'], context) + end + def yaxis_invtransform(val) + list(tk_send('yaxis', 'invtransform', val)) + end + def yaxis_limits + list(tk_send('yaxis', 'limits')) + end + def yaxis_transform(val) + list(tk_send('yaxis', 'transform', val)) + end + def yaxis_use(target=nil) + if target + Tk::BLT::PlotComponent::Axis.id2obj(self, + tk_send('yaxis', 'use', + tagid(target))) + else + Tk::BLT::PlotComponent::Axis.id2obj(self, tk_send('yaxis', 'use')) + end + end + + def y2axis_cget_tkstring(option) + itemcget_tkstring('y2axis', option) + end + def y2axis_cget(option) + itemcget('y2axis', option) + end + def y2axis_cget_strict(option) + itemcget_strict('y2axis', option) + end + def y2axis_configure(slot, value=None) + if slot.kind_of?(Hash) + slot = _symbolkey2str(slot) + if cmd = slot.delete('command') + slot['command'] = proc{|w, tick| + cmd.call(TkComm.window(w), TkComm.num_or_str(tick)) + } + end + elsif slot == :command || slot == 'command' + cmd = value + value = proc{|w, tick| + cmd.call(TkComm.window(w), TkComm.num_or_str(tick)) + } + end + itemconfigure('y2axis', slot, value) + end + def y2axis_configinfo(slot=nil) + axis_configinfo('y2axis', slot) + end + def current_y2axis_configinfo(slot=nil) + current_itemconfiginfo('y2axis', slot) + end + def y2axis_bind(context, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind([path, 'y2axis', 'bind'], context, cmd, *args) + self + end + def y2axis_bind_append(context, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append([path, 'y2axis', 'bind'], context, cmd, *args) + self + end + def y2axis_bind_remove(context) + _bind_remove([path, 'y2axis', 'bind'], context) + self + end + def y2axis_bindinfo(context=nil) + _bindinfo([path, 'y2axis', 'bind'], context) + end + def y2axis_invtransform(val) + list(tk_send('y2axis', 'invtransform', val)) + end + def y2axis_limits + list(tk_send('y2axis', 'limits')) + end + def y2axis_transform(val) + list(tk_send('y2axis', 'transform', val)) + end + def y2axis_use(target=nil) + if target + Tk::BLT::PlotComponent::Axis.id2obj(self, + tk_send('y2axis', 'use', + tagid(target))) + else + Tk::BLT::PlotComponent::Axis.id2obj(self, tk_send('y2axis', 'use')) + end + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/container.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/container.rb new file mode 100644 index 0000000..be05828 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/container.rb @@ -0,0 +1,28 @@ +# +# tkextlib/blt/container.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/blt.rb' + +module Tk::BLT + class Container < TkWindow + TkCommandNames = ['::blt::container'.freeze].freeze + WidgetClassName = 'Container'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() << 'name' + end + private :__strval_optkeys + + def find_command(pat) + Hash[*simplelist(tk_send_without_enc('find', '-command', pat))] + end + + def find_name(pat) + Hash[*simplelist(tk_send_without_enc('find', '-name', pat))] + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/cutbuffer.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/cutbuffer.rb new file mode 100644 index 0000000..1cc39df --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/cutbuffer.rb @@ -0,0 +1,23 @@ +# +# tkextlib/blt/cutbuffer.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/blt.rb' + +module Tk::BLT + module CutBuffer + TkCommandNames = ['::blt::cutbuffer'.freeze].freeze + + def self.get(num = 0) + Tk.tk_call('::blt::cutbuffer', 'get', num) + end + def self.rotate(count = 1) + Tk.tk_call('::blt::cutbuffer', 'rotate', count) + end + def self.set(val, num = 0) + Tk.tk_call('::blt::cutbuffer', 'set', val, num) + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/dragdrop.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/dragdrop.rb new file mode 100644 index 0000000..aa5c565 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/dragdrop.rb @@ -0,0 +1,269 @@ +# +# tkextlib/blt/dragdrop.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/itemconfig' +require 'tkextlib/blt.rb' + +module Tk::BLT + module DragDrop + extend TkCore + + TkCommandNames = ['::blt::drag&drop'.freeze].freeze + + class Token < TkWindow + WidgetClassName = 'DragDropToken'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def initialize(arg) + if arg.kind_of?(Hash) # arg is a hash includes the widgetpath of token + arg = _symbolkey2str(arg) + install_win(nil, arg['widgetname']) + else # arg is a drag&drop source + tk_call('::blt::drag&drop', 'source', arg) + install_win(nil, tk_call('::blt::drag&drop', 'token', arg)) + end + end + end + + ################################### + + extend TkItemConfigMethod + extend Tk::ValidateConfigure + + class << self + def __item_config_cmd(id) # id := ['source'|'target', win] + ['::blt::drag&drop', id[0], id[1]] + end + private :__item_config_cmd + + def __item_boolval_optkeys(id) + super(id) << 'selftarget' + end + private :__item_boolval_optkeys + + def __item_listval_optkeys(id) + super(id) << 'send' + end + private :__item_listval_optkeys + + def __item_strval_optkeys(id) + super(id) << 'rejectbg' << 'rejectfg' << 'tokenbg' + end + private :__item_strval_optkeys + + undef itemcget + undef itemcget_tkstring + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo + + def source_configure(win, slot, value=None) + itemconfigure(['source', win], slot, value) + end + def source_configinfo(win, slot=nil) + itemconfiginfo(['source', win], slot) + end + def current_source_configinfo(win, slot=nil) + current_itemconfiginfo(['source', win], slot) + end + end + + class PackageCommand < TkValidateCommand + class ValidateArgs < TkUtil::CallbackSubst + KEY_TBL = [ + [ ?t, ?w, :token ], + [ ?W, ?w, :widget ], + nil + ] + + PROC_TBL = [ + [ ?w, TkComm.method(:window) ], + nil + ] + +=begin + # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) + KEY_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) + end + inf + } + + PROC_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + end + inf + } +=end + + _setup_subst_table(KEY_TBL, PROC_TBL) + + def self.ret_val(val) + val + end + end + + def self._config_keys + ['packagecmd'] + end + end + + class SiteCommand < TkValidateCommand + class ValidateArgs < TkUtil::CallbackSubst + KEY_TBL = [ + [ ?s, ?b, :compatible ], + [ ?t, ?w, :token ], + nil + ] + + PROC_TBL = [ + [ ?b, TkComm.method(:bool) ], + [ ?w, TkComm.method(:window) ], + nil + ] + +=begin + # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) + KEY_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) + end + inf + } + + PROC_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + end + inf + } +=end + + _setup_subst_table(KEY_TBL, PROC_TBL) + + def self.ret_val(val) + val + end + end + + def self._config_keys + ['sitecmd'] + end + end + + def self.__validation_class_list + super() << PackageCommand << SiteCommand + end + + class << self + Tk::ValidateConfigure.__def_validcmd(binding, PackageCommand) + Tk::ValidateConfigure.__def_validcmd(binding, SiteCommand) + end + + ################################### + + class DnD_Handle < TkUtil::CallbackSubst + KEY_TBL = [ + [ ?i, ?s, :ip_name ], + [ ?v, ?v, :value ], + [ ?W, ?w, :widget ], + nil + ] + + PROC_TBL = [ + [ ?i, TkComm.method(:string) ], + [ ?v, TkComm.method(:tk_tcl2ruby) ], + [ ?w, TkComm.method(:window) ], + nil + ] + +=begin + # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) + KEY_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) + end + inf + } + + PROC_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + end + inf + } +=end + + _setup_subst_table(KEY_TBL, PROC_TBL) + end + + def self.source_handler(win, datatype, cmd=Proc.new, *args) + _bind_for_event_class(DnD_Handle, + ['::blt::drag&drop', 'source', win, 'handler'], + cmd, *args) + end + + def self.target_handler(win, datatype, cmd=Proc.new, *args) + _bind_for_event_class(DnD_Handle, + ['::blt::drag&drop', 'target', win, 'handler'], + cmd, *args) + end + + ################################### + + def self.init_source(win) + tk_call('::blt::drag&drop', 'source', win) + end + + def self.source() + list(tk_call('::blt::drag&drop', 'source')) + end + + def self.source_handler_list(win) + simplelist(tk_call('::blt::drag&drop', 'source', win, 'handler')) + end + def self.source_handler_info(win, type) + tk_tcl2ruby(tk_call('::blt::drag&drop', 'source', win, 'handler', type)) + end + + def self.target + list(tk_call('::blt::drag&drop', 'target')) + end + def self.target_handler_list(win) + simplelist(tk_call('::blt::drag&drop', 'target', win, 'handler')) + end + + def self.handle_target(win, type, val=None) + tk_call('::blt::drag&drop', 'target', win, 'handle', type, val) + end + + def self.token(win) + window(tk_call('::blt::drag&drop', 'token', win)) + end + + def self.drag(win, x, y) + tk_call('::blt::drag&drop', 'drag', win, x, y) + end + def self.drop(win, x, y) + tk_call('::blt::drag&drop', 'drop', win, x, y) + end + + def self.errors(cmd=Proc.new) + tk_call('::blt::drag&drop', 'errors', cmd) + end + + def self.active + bool(tk_call('::blt::drag&drop', 'active')) + end + + def self.location(x=None, y=None) + list(tk_call('::blt::drag&drop', 'location', x, y)) + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/eps.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/eps.rb new file mode 100644 index 0000000..0dba87a --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/eps.rb @@ -0,0 +1,32 @@ +# +# tkextlib/blt/eps.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/canvas' +require 'tkextlib/blt.rb' + +module Tk::BLT + class EPS < TkcItem + CItemTypeName = 'eps'.freeze + CItemTypeToClass[CItemTypeName] = self + end +end + +class Tk::Canvas + alias __BLT_EPS_item_strval_optkeys __item_strval_optkeys + def __item_strval_optkeys(id) + __BLT_EPS_item_strval_optkeys(id) + [ + 'shadowcolor', 'title', 'titlecolor' + ] + end + private :__item_strval_optkeys + + alias __BLT_EPS_item_boolval_optkeys __item_boolval_optkeys + def __item_boolval_optkeys(id) + __BLT_EPS_item_boolval_optkeys(id) + ['showimage'] + end + private :__item_boolval_optkeys +end + diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/graph.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/graph.rb new file mode 100644 index 0000000..6bd4424 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/graph.rb @@ -0,0 +1,67 @@ +# +# tkextlib/blt/graph.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/blt.rb' +require 'tkextlib/blt/component.rb' + +module Tk::BLT + class Graph < TkWindow + TkCommandNames = ['::blt::graph'.freeze].freeze + WidgetClassName = 'Graph'.freeze + WidgetClassNames[WidgetClassName] ||= self + + include PlotComponent + include GraphCommand + + def __boolval_optkeys + ['bufferelements', 'invertxy'] + end + private :__boolval_optkeys + + def __strval_optkeys + ['text', 'label', 'title', 'file', 'plotbackground'] + end + private :__strval_optkeys + +=begin + BarElement_ID = ['blt_graph_bar'.freeze, TkUtil.untrust('00000')].freeze + + def bar(elem=nil, keys={}) + if elem.kind_of?(Hash) + keys = elem + elem = nil + end + unless elem + elem = BarElement_ID.join(TkCore::INTERP._ip_id_).freeze + BarElement_ID[1].succ! + end + tk_send('bar', elem, keys) + Element.new(self, elem, :without_creating=>true) + end +=end + + def extents(item) + num_or_str(tk_send_without_enc('extents', item)) + end + + def invtransform(x, y) + list(tk_send_without_enc('invtransform', x, y)) + end + + def inside(x, y) + bool(tk_send_without_enc('inside', x, y)) + end + + def snap(output, keys={}) + tk_send_without_enc('snap', *(hash_kv(keys, false) + output)) + self + end + + def transform(x, y) + list(tk_send_without_enc('transform', x, y)) + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/htext.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/htext.rb new file mode 100644 index 0000000..878bd99 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/htext.rb @@ -0,0 +1,112 @@ +# +# tkextlib/blt/htext.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/itemconfig.rb' +require 'tkextlib/blt.rb' + +module Tk::BLT + class Htext<TkWindow + Htext_Var = TkVarAccess.new_hash('htext') + Htext_Widget = TkVarAccess.new('htext(widget)', :window) + Htext_File = TkVarAccess.new('htext(file)') + Htext_Line = TkVarAccess.new('htext(line)') + + include TkItemConfigMethod + include Scrollable + + TkCommandNames = ['::blt::htext'.freeze].freeze + WidgetClassName = 'Htext'.freeze + WidgetClassNames[WidgetClassName] ||= self + + alias window_cget_tkstring itemcget_tkstring + alias window_cget itemcget + alias window_cget_strict itemcget_strict + alias window_configure itemconfigure + alias window_configuinfo itemconfiginfo + alias current_window_configuinfo current_itemconfiginfo + + def __strval_optkeys + super() << 'filename' + end + private :__strval_optkeys + + def append(win, keys={}) + tk_send('append', _epath(win), keys) + self + end + + def goto_line(idx) + tk_send_without_enc('gotoline', idx) + self + end + def current_line + number(tk_send_without_enc('gotoline')) + end + + def index(str) + number(tk_send('index', str)) + end + + def line_pos(str) + tk_send('linepos', str) + end + + def range(from=None, to=None) + tk_send_without_enc('range', from, to) + end + + def scan_mark(pos) + tk_send_without_enc('scan', 'mark', pos) + self + end + + def scan_dragto(pos) + tk_send_without_enc('scan', 'dragto', pos) + self + end + + def search(pat, from=None, to=None) + num = number(tk_send('search', pat, from, to)) + (num < 0)? nil: num + 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_line(index) + tk_send_without_enc('selection', 'line', index) + self + end + def selection_present() + bool(tk_send_without_enc('selection', 'present')) + end + def selection_range(first, last) + tk_send_without_enc('selection', 'range', first, last) + self + end + def selection_to(index) + tk_send_without_enc('selection', 'to', index) + self + end + def selection_word(index) + tk_send_without_enc('selection', 'word', index) + self + end + + def windows(pat=None) + list(tk_send('windows', pat)) + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/setup.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/setup.rb new file mode 100644 index 0000000..ee406c6 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/setup.rb @@ -0,0 +1,8 @@ +# +# setup.rb -- setup script before calling TkPackage.require() +# +# If you need some setup operations (for example, add a library path +# to the library search path) before using Tcl/Tk library packages +# wrapped by Ruby scripts in this directory, please write the setup +# operations in this file. +# diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/spline.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/spline.rb new file mode 100644 index 0000000..9f75a0b --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/spline.rb @@ -0,0 +1,23 @@ +# +# tkextlib/blt/spline.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/blt.rb' + +module Tk::BLT + module Spline + extend TkCore + + TkCommandNames = ['::blt::spline'.freeze].freeze + + def self.natural(x, y, sx, sy) + tk_call('::blt::spline', 'natural', x, y, sx, sy) + end + + def self.quadratic(x, y, sx, sy) + tk_call('::blt::spline', 'quadratic', x, y, sx, sy) + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/stripchart.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/stripchart.rb new file mode 100644 index 0000000..74093f1 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/stripchart.rb @@ -0,0 +1,74 @@ +# +# tkextlib/blt/stripchart.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/blt.rb' +require 'tkextlib/blt/component.rb' + +module Tk::BLT + class Stripchart < TkWindow + TkCommandNames = ['::blt::stripchart'.freeze].freeze + WidgetClassName = 'Stripchart'.freeze + WidgetClassNames[WidgetClassName] ||= self + + include PlotComponent + include GraphCommand + + def __boolval_optkeys + ['bufferelements', 'buffergraph', 'invertxy'] + end + private :__boolval_optkeys + + def __strval_optkeys + ['text', 'label', 'title', 'file', + 'background', 'plotbackground'] + end + private :__strval_optkeys + +=begin + BarElement_ID = ['blt_stripchart_bar'.freeze, TkUtil.untrust('00000')].freeze + + def bar(elem=nil, keys={}) + if elem.kind_of?(Hash) + keys = elem + elem = nil + end + unless elem + elem = BarElement_ID.join(TkCore::INTERP._ip_id_).freeze + BarElement_ID[1].succ! + end + tk_send('bar', elem, keys) + Element.new(self, elem, :without_creating=>true) + end +=end + + def extents(item) + num_or_str(tk_send_without_enc('extents', item)) + end + + def invtransform(x, y) + list(tk_send_without_enc('invtransform', x, y)) + end + + def inside(x, y) + bool(tk_send_without_enc('inside', x, y)) + end + + def metafile(file=None) + # Windows only + tk_send('metafile', file) + self + end + + def snap(output, keys={}) + tk_send_without_enc('snap', *(hash_kv(keys, false) + output)) + self + end + + def transform(x, y) + list(tk_send_without_enc('transform', x, y)) + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/table.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/table.rb new file mode 100644 index 0000000..205e29e --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/table.rb @@ -0,0 +1,412 @@ +# +# tkextlib/blt/table.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/itemconfig.rb' +require 'tkextlib/blt.rb' + +module Tk::BLT + module Table + include Tk + extend Tk + extend TkItemConfigMethod + + TkCommandNames = ['::blt::table'.freeze].freeze + + module TableContainer + def blt_table_add(*args) + Tk::BLT::Table.add(self, *args) + self + end + + def blt_table_arrange() + Tk::BLT::Table.arrange(self) + self + end + + def blt_table_cget_tkstring(*args) + Tk::BLT::Table.cget_tkstring(self, *args) + end + def blt_table_cget(*args) + Tk::BLT::Table.cget(self, *args) + end + def blt_table_cget_strict(*args) + Tk::BLT::Table.cget_strict(self, *args) + end + + def blt_table_configure(*args) + Tk::BLT::Table.configure(self, *args) + self + end + + def blt_table_configinfo(*args) + Tk::BLT::Table.configinfo(self, *args) + end + + def blt_table_current_configinfo(*args) + Tk::BLT::Table.current_configinfo(self, *args) + end + + def blt_table_locate(x, y) + Tk::BLT::Table.locate(self, x, y) + end + + def blt_table_delete(*args) + Tk::BLT::Table.delete(self, *args) + self + end + + def blt_table_extents(item) + Tk::BLT::Table.extents(self, item) + end + + def blt_table_insert(*args) + Tk::BLT::Table.insert(self, *args) + self + end + + def blt_table_insert_before(*args) + Tk::BLT::Table.insert_before(self, *args) + self + end + + def blt_table_insert_after(*args) + Tk::BLT::Table.insert_after(self, *args) + self + end + + def blt_table_join(first, last) + Tk::BLT::Table.join(self, first, last) + self + end + + def blt_table_save() + Tk::BLT::Table.save(self) + end + + def blt_table_search(*args) + Tk::BLT::Table.search(self, *args) + end + + def blt_table_split(*args) + Tk::BLT::Table.split(self, *args) + self + end + + def blt_table_itemcget_tkstring(*args) + Tk::BLT::Table.itemcget_tkstring(self, *args) + end + def blt_table_itemcget(*args) + Tk::BLT::Table.itemcget(self, *args) + end + def blt_table_itemcget_strict(*args) + Tk::BLT::Table.itemcget_strict(self, *args) + end + + def blt_table_itemconfigure(*args) + Tk::BLT::Table.itemconfigure(self, *args) + self + end + + def blt_table_itemconfiginfo(*args) + Tk::BLT::Table.itemconfiginfo(self, *args) + end + + def blt_table_current_itemconfiginfo(*args) + Tk::BLT::Table.current_itemconfiginfo(self, *args) + end + + def blt_table_iteminfo(item) + Tk::BLT::Table.iteminfo(self, item) + end + end + end +end + + +############################################ +class << Tk::BLT::Table + def __item_cget_cmd(id) # id := [ container, item ] + win = (id[0].kind_of?(TkWindow))? id[0].path: id[0].to_s + ['::blt::table', 'cget', win, id[1]] + end + private :__item_cget_cmd + + def __item_config_cmd(id) # id := [ container, item, ... ] + container, *items = id + win = (container.kind_of?(TkWindow))? container.path: container.to_s + ['::blt::table', 'configure', win, *items] + end + private :__item_config_cmd + + def __item_pathname(id) + win = (id[0].kind_of?(TkWindow))? id[0].path: id[0].to_s + win + ';' + end + private :__item_pathname + + alias __itemcget_tkstring itemcget_tkstring + alias __itemcget itemcget + alias __itemcget_strict itemcget_strict + alias __itemconfigure itemconfigure + alias __itemconfiginfo itemconfiginfo + alias __current_itemconfiginfo current_itemconfiginfo + + private :__itemcget_tkstring, :__itemcget, :__itemcget_strict + private :__itemconfigure, :__itemconfiginfo, :__current_itemconfiginfo + + def __boolval_optkeys + super() << 'propagate' + end + private :__boolval_optkeys + + def tagid(tag) + if tag.kind_of?(Array) + case tag[0] + when Integer + # [row, col] + tag.join(',') + when :c, :C, 'c', 'C', :r, :R, 'r', 'R' + # c0 or r1 or C*, and so on + tag.collect{|elem| elem.to_s}.join('') + else + tag + end + elsif tag.kind_of?(TkWindow) + _epath(tag) + else + tag + end + end + + def tagid2obj(tagid) + tagid + end + + ############################################ + + def cget_tkstring(container, option) + __itemcget_tkstring([container], option) + end + def cget(container, option) + __itemcget([container], option) + end + def cget_strict(container, option) + __itemcget_strict([container], option) + end + + def configure(container, *args) + __itemconfigure([container], *args) + end + + def configinfo(container, *args) + __itemconfiginfo([container], *args) + end + + def current_configinfo(container, *args) + __current_itemconfiginfo([container], *args) + end + + def itemcget_tkstring(container, item, option) + __itemcget_tkstring([container, tagid(item)], option) + end + def itemcget(container, item, option) + __itemcget([container, tagid(item)], option) + end + def itemcget_strict(container, item, option) + __itemcget_strict([container, tagid(item)], option) + end + + def itemconfigure(container, *args) + if args[-1].kind_of?(Hash) + # container, item, item, ... , hash_optkeys + keys = args.pop + fail ArgumentError, 'no item is given' if args.empty? + id = [container] + args.each{|item| id << tagid(item)} + __itemconfigure(id, keys) + else + # container, item, item, ... , option, value + val = args.pop + opt = args.pop + fail ArgumentError, 'no item is given' if args.empty? + id = [container] + args.each{|item| id << tagid(item)} + __itemconfigure(id, opt, val) + end + container + end + + def itemconfiginfo(container, *args) + slot = args[-1] + if slot.kind_of?(String) || slot.kind_of?(Symbol) + slot = slot.to_s + if slot[0] == ?. || slot =~ /^\d+,\d+$/ || slot =~ /^(c|C|r|R)(\*|\d+)/ + # widget || row,col || Ci or Ri + slot = nil + else + # option + slot = args.pop + end + else + slot = nil + end + + fail ArgumentError, 'no item is given' if args.empty? + + id = [container] + args.each{|item| id << tagid(item)} + __itemconfiginfo(id, slot) + end + + def current_itemconfiginfo(container, *args) + slot = args[-1] + if slot.kind_of?(String) || slot.kind_of?(Symbol) + slot = slot.to_s + if slot[0] == ?. || slot =~ /^\d+,\d+$/ || slot =~ /^(c|C|r|R)(\*|\d+)/ + # widget || row,col || Ci or Ri + slot = nil + else + # option + slot = args.pop + end + else + slot = nil + end + + fail ArgumentError, 'no item is given' if args.empty? + + id = [container] + args.each{|item| id << tagid(item)} + __current_itemconfiginfo(id, slot) + end + + def info(container) + ret = {} + inf = list(tk_call('::blt::table', 'info', container)) + until inf.empty? + opt = inf.slice!(0..1) + ret[opt[1..-1]] = opt[1] + end + ret + end + + def iteminfo(container, item) + inf = list(tk_call('::blt::table', 'info', container, tagid(item)).chomp) + + ret = [] + until inf.empty? || (inf[0].kind_of?(String) && inf[0] =~ /^-/) + ret << inf.shift + end + + if inf.length > 1 + keys = {} + while inf.length > 1 + opt = inf.slice!(0..1) + keys[opt[0][1..-1]] = opt[1] + end + ret << keys + end + + ret + end + + ############################################ + + def create_container(container) + tk_call('::blt::table', container) + begin + class << container + include Tk::BLT::Table::TableContainer + end + rescue + warn('fail to include TableContainer methods (frozen object?)') + end + container + end + + def add(container, *args) + if args.empty? + tk_call('::blt::table', container) + else + args = args.collect{|arg| + if arg.kind_of?(TkWindow) + _epath(arg) + elsif arg.kind_of?(Array) # index + arg.join(',') + else + arg + end + } + tk_call('::blt::table', container, *args) + end + container + end + + def arrange(container) + tk_call('::blt::table', 'arrange', container) + container + end + + def delete(container, *args) + tk_call('::blt::table', 'delete', container, *args) + end + + def extents(container, item) + ret = [] + inf = list(tk_call('::blt::table', 'extents', container, item)) + ret << inf.slice!(0..4) until inf.empty? + ret + end + + def forget(*wins) + wins = wins.collect{|win| _epath(win)} + tk_call('::blt::table', 'forget', *wins) + end + + def insert(container, *args) + tk_call('::blt::table', 'insert', container, *args) + end + + def insert_before(container, *args) + tk_call('::blt::table', 'insert', container, '-before', *args) + end + + def insert_after(container, *args) + tk_call('::blt::table', 'insert', container, '-after', *args) + end + + def join(container, first, last) + tk_call('::blt::table', 'join', container, first, last) + end + + def locate(container, x, y) + tk_call('::blt::table', 'locate', container, x, y) + end + + def containers(arg={}) + list(tk_call('::blt::table', 'containers', *hash_kv(arg))) + end + + def containers_pattern(pat) + list(tk_call('::blt::table', 'containers', '-pattern', pat)) + end + + def containers_slave(win) + list(tk_call('::blt::table', 'containers', '-slave', win)) + end + + def save(container) + tk_call('::blt::table', 'save', container) + end + + def search(container, keys={}) + list(tk_call('::blt::table', 'containers', *hash_kv(keys))) + end + + def split(container, *args) + tk_call('::blt::table', 'split', container, *args) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/tabnotebook.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/tabnotebook.rb new file mode 100644 index 0000000..82936c6 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/tabnotebook.rb @@ -0,0 +1,110 @@ +# +# tkextlib/blt/tabnotebook.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/blt.rb' +require 'tkextlib/blt/tabset.rb' + +module Tk::BLT + class Tabnotebook < Tabset + TkCommandNames = ['::blt::tabnotebook'.freeze].freeze + WidgetClassName = 'Tabnotebook'.freeze + WidgetClassNames[WidgetClassName] ||= self + + class Tab < Tk::BLT::Tabset::Tab + def self.new(parent, pos=nil, name=nil, keys={}) + if pos.kind_of?(Hash) + keys = pos + name = nil + pos = nil + end + if name.kind_of?(Hash) + keys = name + name = nil + end + obj = nil + TabID_TBL.mutex.synchronize{ + if name && TabID_TBL[parent.path] && TabID_TBL[parent.path][name] + obj = TabID_TBL[parent.path][name] + if pos + if pos.to_s == 'end' + obj.move_after('end') + else + obj.move_before(pos) + end + end + obj.configure if keys && ! keys.empty? + else + (obj = self.allocate).instance_eval{ + initialize(parent, pos, name, keys) + TabID_TBL[@tpath] = {} unless TabID_TBL[@tpath] + TabID_TBL[@tpath][@id] = self + } + end + } + obj + end + + def initialize(parent, pos, name, keys) + @t = parent + @tpath = parent.path + if name + @path = @id = name + unless (list(tk_call(@tpath, 'tab', 'names', @id)).empty?) + if pos + idx = tk_call(@tpath, 'index', @id) + if pos.to_s == 'end' + tk_call(@tpath, 'move', idx, 'after', 'end') + else + tk_call(@tpath, 'move', idx, 'before', pos) + end + end + tk_call(@tpath, 'tab', 'configure', @id, keys) + else + fail ArgumentError, "can't find tab \"#{@id}\" in #{@t}" + end + else + pos = 'end' unless pos + @path = @id = tk_call(@tpath, 'insert', pos, keys) + end + end + end + + ####################################### + + def get_tab(index) + if (idx = tk_send_without_enc('id', tagindex(index))).empty? + nil + else + Tk::BLT::Tabset::Tab.id2obj(self, idx) + end + end + alias get_id get_tab + + def get_tabobj(index) + if (idx = tk_send_without_enc('id', tagindex(index))).empty? + nil + else + Tk::BLT::Tabnotebook::Tab.new(self, nil, idx) + end + end + + alias index_name index + + def insert(pos=nil, keys={}) + if pos.kind_of?(Hash) + keys = pos + pos = nil + end + pos = 'end' if pos.nil? + Tk::BLT::Tabnotebook::Tab.new(self, nil, + tk_send('insert', tagindex(pos), keys)) + + end + undef :insert_tabs + + undef :tab_pageheight, :tab_pagewidth + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/tabset.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/tabset.rb new file mode 100644 index 0000000..c4716c7 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/tabset.rb @@ -0,0 +1,504 @@ +# +# tkextlib/blt/tabset.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/blt.rb' + +module Tk::BLT + class Tabset < TkWindow + class Tab < TkObject + include TkTreatItemFont + + TabID_TBL = TkCore::INTERP.create_table + + (TabsetTab_ID = ['blt_tabset_tab'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + TkCore::INTERP.init_ip_env{ + TabID_TBL.mutex.synchronize{ TabID_TBL.clear } + } + + def self.id2obj(tabset, id) + tpath = tabset.path + TabID_TBL.mutex.synchronize{ + if TabID_TBL[tpath] + TabID_TBL[tpath][id]? TabID_TBL[tpath][id]: id + else + id + end + } + end + + def self.new(parent, pos=nil, name=nil, keys={}) + if pos.kind_of?(Hash) + keys = pos + name = nil + pos = nil + end + if name.kind_of?(Hash) + keys = name + name = nil + end + obj = nil + TabID_TBL.mutex.synchronize{ + if name && TabID_TBL[parent.path] && TabID_TBL[parent.path][name] + obj = TabID_TBL[parent.path][name] + if pos + if pos.to_s == 'end' + obj.move_after('end') + else + obj.move_before(pos) + end + end + obj.configure if keys && ! keys.empty? + else + (obj = self.allocate).instance_eval{ + initialize(parent, pos, name, keys) + TabID_TBL[@tpath] = {} unless TabID_TBL[@tpath] + TabID_TBL[@tpath][@id] = self + } + end + } + obj + end + + def initialize(parent, pos, name, keys) + @t = parent + @tpath = parent.path + if name + @path = @id = name + unless (list(tk_call(@tpath, 'tab', 'names', @id)).empty?) + if pos + idx = tk_call(@tpath, 'index', '-name', @id) + if pos.to_s == 'end' + tk_call(@tpath, 'move', idx, 'after', 'end') + else + tk_call(@tpath, 'move', idx, 'before', pos) + end + end + tk_call(@tpath, 'tab', 'configure', @id, keys) + else + pos = 'end' unless pos + tk_call(@tpath, 'insert', pos, @id, keys) + end + else + pos = 'end' unless pos + TabsetTab_ID.mutex.synchronize{ + @path = @id = TabsetTab_ID.join(TkCore::INTERP._ip_id_) + TabsetTab_ID[1].succ! + } + tk_call(@tpath, 'insert', pos, @id, keys) + end + end + + #def bind(context, cmd=Proc.new, *args) + # @t.tab_bind(@id, context, cmd, *args) + # self + #end + def bind(context, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + @t.tab_bind(@id, context, cmd, *args) + self + end + #def bind_append(context, cmd=Proc.new, *args) + # @t.tab_bind_append(@id, context, cmd, *args) + # self + #end + def bind_append(context, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + @t.tab_bind_append(@id, context, cmd, *args) + self + end + def bind_remove(context) + @t.tab_bind_remove(@id, context) + self + end + def bindinfo(context=nil) + @t.tab_bindinfo(@id, context) + end + + def cget_tkstring(*args) + @t.tab_cget_tkstring(@id, *args) + end + def cget(*args) + @t.tab_cget(@id, *args) + end + def cget_strict(*args) + @t.tab_cget_strict(@id, *args) + end + def configure(*args) + @t.tab_configure(@id, *args) + end + def configinfo(*args) + @t.tab_configinfo(@id, *args) + end + def current_configinfo(*args) + @t.current_tab_configinfo(@id, *args) + end + + def delete() + @t.delete(@id) + TabID_TBL.mutex.synchronize{ + TabID_TBL[@tpath].delete(@id) + } + self + end + + def get_name() + @id.dup + end + + def focus() + @t.focus(self.index) + end + + def index() + @t.index_name(@id) + end + + def invoke() + @t.invoke(self.index) + end + + def move_before(idx) + @t.move_before(self.index, idx) + end + def move_after(idx) + @t.move_after(self.index, idx) + end + + def perforation_highlight(mode) + @t.perforation_highlight(self.index, mode) + end + def perforation_invoke() + @t.perforation_invoke(self.index) + end + + def see() + @t.see(self.index) + end + + def tearoff(name=None) + @t.tab_tearoff(self.index, *args) + end + end + + ######################################## + + class NamedTab < Tab + def self.new(parent, name) + super(parent, nil, name, {}) + end + end + + ######################################## + + include X_Scrollable + include TkItemConfigMethod + + TkCommandNames = ['::blt::tabset'.freeze].freeze + WidgetClassName = 'Tabset'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __destroy_hook__ + Tk::BLT::Tabset::Tab::TabID_TBL.mutex.synchronize{ + Tk::BLT::Tabset::Tab::TabID_TBL.delete(@path) + } + end + + ######################################## + + def __boolval_optkeys + super() << 'samewidth' << 'tearoff' + end + private :__strval_optkeys + + def __strval_optkeys + super() << 'tabbackground' << 'tabforeground' + end + private :__strval_optkeys + + def __item_cget_cmd(id) + [self.path, 'tab', 'cget', id] + end + private :__item_cget_cmd + + def __item_config_cmd(id) + [self.path, 'tab', 'configure', id] + end + private :__item_config_cmd + + def __item_pathname(tagOrId) + if tagOrId.kind_of?(Tk::BLT::Tabset::Tab) + self.path + ';' + tagOrId.id.to_s + else + self.path + ';' + tagOrId.to_s + end + end + private :__item_pathname + + alias tab_cget_tkstring itemcget_tkstring + alias tab_cget itemcget + alias tab_cget_strict itemcget_strict + alias tab_configure itemconfigure + alias tab_configinfo itemconfiginfo + alias current_tab_configinfo current_itemconfiginfo + + def __item_strval_optkeys(id) + super(id) << 'shadow' + end + private :__item_strval_optkeys + + def tagid(tab) + if tab.kind_of?(Tk::BLT::Tabset::Tab) + tab.id + else + tab + end + end + + def tagindex(tab) + if tab.kind_of?(Tk::BLT::Tabset::Tab) + tab.index + else + tab + end + end + + ######################################## + + def activate(index) + tk_send('activate', tagindex(index)) + self + end + alias highlight activate + + #def tabbind(tag, context, cmd=Proc.new, *args) + # _bind([path, "bind", tagid(tag)], context, cmd, *args) + # self + #end + def tabbind(tag, context, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind([path, "bind", tagid(tag)], context, cmd, *args) + self + end + #def tabbind_append(tag, context, cmd=Proc.new, *args) + # _bind_append([path, "bind", tagid(tag)], context, cmd, *args) + # self + #end + def tabbind_append(tag, context, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append([path, "bind", tagid(tag)], context, cmd, *args) + self + end + def tabbind_remove(tag, context) + _bind_remove([path, "bind", tagid(tag)], context) + self + end + def tabbindinfo(tag, context=nil) + _bindinfo([path, "bind", tagid(tag)], context) + end + + def delete(first, last=None) + tk_send('delete', tagindex(first), tagindex(last)) + if first.kind_of?(Tk::BLT::Tabset::Tab) + TabID_TBL.mutex.synchronize{ + TabID_TBL[@path].delete(first.id) + } + end + # middle tabs of the range are unknown + if last.kind_of?(Tk::BLT::Tabset::Tab) + TabID_TBL.mutex.synchronize{ + TabID_TBL[@path].delete(last.id) + } + end + self + end + + def focus(index) + tk_send('focus', tagindex(index)) + self + end + + def get_tab(index) + if (idx = tk_send_without_enc('get', tagindex(index))).empty? + nil + else + Tk::BLT::Tabset::Tab.id2obj(self, idx) + end + end + def get_tabobj(index) + if (idx = tk_send_without_enc('get', tagindex(index))).empty? + nil + else + Tk::BLT::Tabset::Tab.new(self, nil, name, {}) + end + end + + def index(str) + num_or_str(tk_send('index', str)) + end + def index_name(tab) + num_or_str(tk_send('index', '-name', tagid(tab))) + end + + def insert(pos, tab, keys={}) + pos = 'end' if pos.nil? + Tk::BLT::Tabset::Tab.new(self, tagindex(pos), tagid(tab), keys) + end + def insert_tabs(pos, *tabs) + pos = 'end' if pos.nil? + if tabs[-1].kind_of?(Hash) + keys = tabs.pop + else + keys = {} + end + fail ArgumentError, 'no tabs is given' if tabs.empty? + tabs.map!{|tab| tagid(tab)} + tk_send('insert', tagindex(pos), *(tabs + [keys])) + tabs.collect{|tab| Tk::BLT::Tabset::Tab.new(self, nil, tagid(tab))} + end + + def invoke(index) + tk_send('invoke', tagindex(index)) + end + + def move_before(index, base_idx) + tk_send('move', tagindex(index), 'before', tagindex(base_idx)) + self + end + def move_after(index, base_idx) + tk_send('move', tagindex(index), 'after', tagindex(base_idx)) + self + end + + def nearest(x, y) + Tk::BLT::Tabset::Tab.id2obj(self, num_or_str(tk_send_without_enc('nearest', x, y))) + end + + def perforation_activate(mode) + tk_send('perforation', 'activate', mode) + self + end + def perforation_highlight(index, *args) + if args.empty? + # index --> mode + tk_send('perforation', 'highlight', index) + elsif args.size == 1 + # args[0] --> mode + tk_send('perforation', 'highlight', tagindex(index), args[0]) + else # Error: call to get Tcl's error message + tk_send('perforation', 'highlight', tagindex(index), *args) + end + self + end + def perforation_invoke(index=nil) + if index + tk_send('perforation', 'invoke', tagindex(index)) + else + tk_send('perforation', 'invoke') + end + 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('see', tagindex(index)) + self + end + + def size() + number(tk_send_without_enc('size')) + end + + def select(index) + tk_send('select', tagindex(index)) + self + end + + def tab_dockall + tk_send('tab', 'dockall') + self + end + + def tab_names(pat=None) + simplelist(tk_send('tab', 'names', pat)).collect{|name| + Tk::BLT::Tabset::Tab.id2obj(self, name) + } + end + + def tab_objs(pat=None) + simplelist(tk_send('tab', 'names', pat)).collect{|name| + Tk::BLT::Tabset::Tab.new(self, nil, name, {}) + } + end + + def tab_ids(pat=None) + simplelist(tk_send('tab', 'names', pat)) + end + + def tab_pageheight + number(tk_send('tab', 'pageheight')) + end + + def tab_pagewidth + number(tk_send('tab', 'pagewidth')) + end + + def tab_tearoff(index, parent=None) + window(tk_send('tab', 'tearoff', tagindex(index), parent)) + end + + def xscrollcommand(cmd=Proc.new) + configure_cmd 'scrollcommand', cmd + self + end + alias scrollcommand xscrollcommand + + def xview(*index) + if index.empty? + list(tk_send_without_enc('view')) + else + tk_send_without_enc('view', *index) + self + end + end + alias view xview + alias view_moveto xview_moveto + alias view_scroll xview_scroll + + alias scrollbar xscrollbar + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/ted.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/ted.rb new file mode 100644 index 0000000..53ab9ac --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/ted.rb @@ -0,0 +1,68 @@ +# +# tkextlib/blt/ted.rb +# +# *** This is alpha version, because there is no document on BLT. *** +# +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/blt.rb' + +module Tk::BLT + module Ted + extend TkCore + + TkCommandNames = ['::blt::ted'.freeze].freeze + + ############################## + + extend TkItemConfigMethod + + class << self + def __item_cget_cmd(id) + ['::blt::ted', 'cget', id] + end + private :__item_cget_cmd + + def __item_config_cmd(id) + ['::blt::ted', 'configure', id] + end + private :__item_config_cmd + + private :itemcget_tkstring, :itemcget, :itemcget_strict + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo + + def cget_tkstring(master, option) + itemcget_tkstring(master, option) + end + def cget(master, option) + itemcget(master, option) + end + def cget_strict(master, option) + itemcget_strict(master, option) + end + def configure(master, slot, value=None) + itemconfigure(master, slot, value) + end + def configinfo(master, slot=nil) + itemconfiginfo(master, slot) + end + def current_configinfo(master, slot=nil) + current_itemconfiginfo(master, slot) + end + end + + ############################## + + def self.edit(master, *args) + tk_call('::blt::ted', 'edit', master, *args) + end + def self.rep(master, *args) + tk_call('::blt::ted', 'rep', master, *args) + end + def self.select(master, *args) + tk_call('::blt::ted', 'select', master, *args) + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/tile.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/tile.rb new file mode 100644 index 0000000..c67cafd --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/tile.rb @@ -0,0 +1,25 @@ +# +# tkextlib/blt/tile.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/blt.rb' + +module Tk::BLT + module Tile + TkComm::TkExtlibAutoloadModule.unshift(self) + # Require autoload-symbols which is a same name as widget classname. + # Those are used at TkComm._genobj_for_tkwidget method. + + autoload :Button, 'tkextlib/blt/tile/button.rb' + autoload :CheckButton, 'tkextlib/blt/tile/checkbutton.rb' + autoload :Checkbutton, 'tkextlib/blt/tile/checkbutton.rb' + autoload :Radiobutton, 'tkextlib/blt/tile/radiobutton.rb' + autoload :RadioButton, 'tkextlib/blt/tile/radiobutton.rb' + autoload :Frame, 'tkextlib/blt/tile/frame.rb' + autoload :Label, 'tkextlib/blt/tile/label.rb' + autoload :Scrollbar, 'tkextlib/blt/tile/scrollbar.rb' + autoload :Toplevel, 'tkextlib/blt/tile/toplevel.rb' + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/tile/button.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/tile/button.rb new file mode 100644 index 0000000..2e0863c --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/tile/button.rb @@ -0,0 +1,16 @@ +# +# tkextlib/blt/tile/button.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/button' +require 'tkextlib/blt/tile.rb' + +module Tk::BLT + module Tile + class Button < Tk::Button + TkCommandNames = ['::blt::tile::button'.freeze].freeze + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/tile/checkbutton.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/tile/checkbutton.rb new file mode 100644 index 0000000..da230b5 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/tile/checkbutton.rb @@ -0,0 +1,17 @@ +# +# tkextlib/blt/tile/checkbutton.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/checkbutton' +require 'tkextlib/blt/tile.rb' + +module Tk::BLT + module Tile + class CheckButton < Tk::CheckButton + TkCommandNames = ['::blt::tile::checkbutton'.freeze].freeze + end + Checkbutton = CheckButton + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/tile/frame.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/tile/frame.rb new file mode 100644 index 0000000..5434af4 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/tile/frame.rb @@ -0,0 +1,16 @@ +# +# tkextlib/blt/tile/frame.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/frame' +require 'tkextlib/blt/tile.rb' + +module Tk::BLT + module Tile + class Frame < Tk::Frame + TkCommandNames = ['::blt::tile::frame'.freeze].freeze + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/tile/label.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/tile/label.rb new file mode 100644 index 0000000..f370c14 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/tile/label.rb @@ -0,0 +1,16 @@ +# +# tkextlib/blt/tile/label.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/label' +require 'tkextlib/blt/tile.rb' + +module Tk::BLT + module Tile + class Label < Tk::Label + TkCommandNames = ['::blt::tile::label'.freeze].freeze + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/tile/radiobutton.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/tile/radiobutton.rb new file mode 100644 index 0000000..814f9a5 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/tile/radiobutton.rb @@ -0,0 +1,17 @@ +# +# tkextlib/blt/tile/radiobutton.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/radiobutton' +require 'tkextlib/blt/tile.rb' + +module Tk::BLT + module Tile + class RadioButton < Tk::RadioButton + TkCommandNames = ['::blt::tile::radiobutton'.freeze].freeze + end + Radiobutton = RadioButton + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/tile/scrollbar.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/tile/scrollbar.rb new file mode 100644 index 0000000..2ae871d --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/tile/scrollbar.rb @@ -0,0 +1,16 @@ +# +# tkextlib/blt/tile/scrollbar.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/scrollbar' +require 'tkextlib/blt/tile.rb' + +module Tk::BLT + module Tile + class Scrollbar < Tk::Scrollbar + TkCommandNames = ['::blt::tile::scrollbar'.freeze].freeze + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/tile/toplevel.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/tile/toplevel.rb new file mode 100644 index 0000000..76d5f86 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/tile/toplevel.rb @@ -0,0 +1,16 @@ +# +# tkextlib/blt/tile/toplevel.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/toplevel' +require 'tkextlib/blt/tile.rb' + +module Tk::BLT + module Tile + class Toplevel < Tk::Toplevel + TkCommandNames = ['::blt::tile::toplevel'.freeze].freeze + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/tree.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/tree.rb new file mode 100644 index 0000000..1a3563e --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/tree.rb @@ -0,0 +1,1058 @@ +# +# tkextlib/blt/tree.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/blt.rb' + +module Tk::BLT + class Tree < TkObject + TkCommandNames = ['::blt::tree'.freeze].freeze + + ################################### + + class Node < TkObject + TreeNodeID_TBL = TkCore::INTERP.create_table + + TkCore::INTERP.init_ip_env{ + TreeNodeID_TBL.mutex.synchronize{ TreeNodeID_TBL.clear } + } + + def self.id2obj(tree, id) + tpath = tree.path + TreeNodeID_TBL.mutex.synchronize{ + if TreeNodeID_TBL[tpath] + if TreeNodeID_TBL[tpath][id] + TreeNodeID_TBL[tpath][id] + else + begin + # self.new(tree, nil, 'node'=>Integer(id)) + id = Integer(id) + if bool(tk_call(@tpath, 'exists', id)) + (obj = self.allocate).instance_eval{ + @parent = @tree = tree + @tpath = tpath + @path = @id = id + TreeNodeID_TBL[@tpath] = {} unless TreeNodeID_TBL[@tpath] + TreeNodeID_TBL[@tpath][@id] = self + } + obj + else + id + end + rescue + id + end + end + else + id + end + } + end + + def self.new(tree, parent, keys={}) + keys = _symbolkey2str(keys) + tpath = tree.path + + TreeNodeID_TBL.mutex.synchronize{ + TreeNodeID_TBL[tpath] ||= {} + if (id = keys['node']) && (obj = TreeNodeID_TBL[tpath][id]) + keys.delete('node') + tk_call(tree.path, 'move', id, parent, keys) if parent + return obj + end + + (obj = self.allocate).instance_eval{ + initialize(tree, parent, keys) + TreeNodeID_TBL[tpath][@id] = self + } + obj + } + end + + def initialize(tree, parent, keys={}) + @parent = @tree = tree + @tpath = @parent.path + + if (id = keys['node']) && bool(tk_call(@tpath, 'exists', id)) + @path = @id = id + keys.delete('node') + tk_call(@tpath, 'move', @id, parent, keys) if parent + else + parent = tk_call(@tpath, 'root') unless parent + @path = @id = tk_call(@tpath, 'insert', parent, keys) + end + end + + def id + @id + end + + def apply(keys={}) + @tree.apply(@id, keys) + self + end + + def children() + @tree.children(@id) + end + + def copy(parent, keys={}) + @tree.copy(@id, parent, keys) + end + def copy_to(dest_tree, parent, keys={}) + @tree.copy_to(@id, dest_tree, parent, keys) + end + + def degree() + @tree.degree(@id) + end + + def delete() + @tree.delete(@id) + self + end + + def depth() + @tree.depth(@id) + end + + def dump() + @tree.dump(@id) + end + + def dump_to_file(file) + @tree.dump_to_file(@id, file) + self + end + + def exist?(keys={}) + @tree.exist?(@id, keys) + end + + def find(keys={}) + @tree.find(@id, keys) + end + + def find_child(label) + @tree.find_child(@id, label) + end + + def first_child() + @tree.first_child(@id) + end + + def get() + @tree.get(@id) + end + def get_value(key, default_val=None) + @tree.get_value(@id, key, default_val) + end + + def index() + @tree.index(@id) + end + + def leaf?() + @tree.leaf?(@id) + end + def link?() + @tree.link?(@id) + end + def root?() + @tree.root?(@id) + end + + def keys() + @tree.keys(@id) + end + + def label(text = nil) + @tree.label(@id, nil) + end + def label=(text) + @tree.label(@id, text) + end + + def last_child() + @tree.last_child(@id) + end + + def move(dest, keys={}) + @tree.keys(@id, dest, keys) + self + end + + def next() + @tree.next(@id) + end + + def next_sibling() + @tree.next_sibling(@id) + end + + def parent() + @tree.parent(@id) + end + + def fullpath() + @tree.fullpath(@id) + end + + def position() + @tree.position(@id) + end + + def previous() + @tree.previous(@id) + end + + def prev_sibling() + @tree.prev_sibling(@id) + end + + def restore(str, keys={}) + @tree.restore(@id, str, keys) + self + end + def restore_overwrite(str, keys={}) + @tree.restore_overwrite(@id, str, keys) + self + end + + def restore_from_file(file, keys={}) + @tree.restore_from_file(@id, file, keys) + self + end + def restore_overwrite_from_file(file, keys={}) + @tree.restore_overwrite_from_file(@id, file, keys) + self + end + + def root() + @tree.root(@id) + self + end + + def set(data) + @tree.set(@id, data) + self + end + + def size() + @tree.size(@id) + end + + def sort(keys={}) + @tree.sort(@id, keys) + self + end + + def type(key) + @tree.type(@id, key) + end + + def unset(*keys) + @tree.unset(@id, *keys) + self + end + + def values(key=None) + @tree.values(@id, key) + end + end + + ################################### + + class Tag < TkObject + TreeTagID_TBL = TkCore::INTERP.create_table + + TkCore::INTERP.init_ip_env{ + TreeTagID_TBL.mutex.synchronize{ TreeTagID_TBL.clear } + } + + (TreeTag_ID = ['blt_tree_tag'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + def self.id2obj(tree, id) + tpath = tree.path + TreeTagID_TBL.mutex.synchronize{ + if TreeTagID_TBL[tpath] + if TreeTagID_TBL[tpath][id] + TreeTagID_TBL[tpath][id] + else + begin + # self.new(tree, id) + (obj = self.allocate).instance_eval{ + @parent = @tree = tree + @tpath = @parent.path + @path = @id = id.dup.freeze if id + TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath] + TreeTagID_TBL[@tpath][@id] = self + } + obj + rescue + id + end + end + else + id + end + } + end + + def initialize(tree, tag_str = nil) + @parent = @tree = tree + @tpath = @parent.path + + if tag_str + @path = @id = tag_str.dup.freeze + else + TreeTag_ID.mutex.synchronize{ + @path = @id = TreeTag_ID.join(TkCore::INTERP._ip_id_) + TreeTag_ID[1].succ! + } + end + TreeTagID_TBL.mutex.synchronize{ + TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath] + TreeTagID_TBL[@tpath][@id] = self + } + end + + def id + @id + end + + def add(*nodes) + tk_call(@tpath, 'tag', 'add', @id, *nodes) + self + end + + def delete(*nodes) + tk_call(@tpath, 'tag', 'delete', @id, *nodes) + self + end + + def forget() + tk_call(@tpath, 'tag', 'forget', @id) + TreeTagID_TBL.mutex.synchronize{ + TreeTagID_TBL[@tpath].delete(@id) + } + self + end + + def nodes() + simplelist(tk_call(@tpath, 'tag', 'nodes', @id)).collect{|node| + Tk::BLT::Tree::Node.id2obj(@path, node) + } + end + + def set(node) + tk_call(@tpath, 'tag', 'set', node, @id) + self + end + + def unset(node) + tk_call(@tpath, 'tag', 'unset', node, @id) + self + end + end + + ################################### + + class Notify < TkObject + NotifyID_TBL = TkCore::INTERP.create_table + + TkCore::INTERP.init_ip_env{ + NotifyID_TBL.mutex.synchronize{ NotifyID_TBL.clear } + } + + def self.id2obj(tree, id) + tpath = tree.path + NotifyID_TBL.mutex.synchronize{ + if NotifyID_TBL[tpath] + if NotifyID_TBL[tpath][id] + NotifyID_TBL[tpath][id] + else + (obj = self.allocate).instance_eval{ + @parent = @tree = tree + @tpath = @parent.path + @path = @id = id + NotifyID_TBL[@tpath] ||= {} + NotifyID_TBL[@tpath][@id] = self + } + obj + end + else + return id + end + } + end + + def self.new(tree, *args, &b) + NotifyID_TBL.mutex.synchronize{ + if tree.kind_of?(Array) + # not create + tpath = tree[0].path + NotifyID_TBL[tpath] ||= {} + unless (obj = NotifyID_TBL[tpath][tree[1]]) + (NotifyID_TBL[tpath][tree[1]] = + obj = self.allocate).instance_eval{ + @parent = @tree = tree[0] + @tpath = @parent.path + @path = @id = tree[1] + } + end + return obj + end + + (obj = self.allocate).instance_eval{ + initialize(tree, *args, &b) + NotifyID_TBL[@tpath] ||= {} + NotifyID_TBL[@tpath][@id] = self + } + return obj + } + end + + def initialize(tree, *args, &b) + @parent = @tree = tree + @tpath = @parent.path + + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) + cmd = args.shift + # elsif args[-1].kind_of?(Proc) || args[-1].kind_of?(Method) + elsif TkComm._callback_entry?(args[-1]) + cmd = args.pop + elsif b + cmd = Proc.new(&b) + else + fail ArgumentError, "lack of 'command' argument" + end + + args = args.collect{|arg| '-' << arg.to_s} + + args << proc{|id, type| + cmd.call(Tk::BLT::Tree::Node.id2obj(@tree, id), + ((type[0] == ?-)? type[1..-1]: type)) + } + + @path = @id = tk_call(@tpath, 'notify', 'create', *args) + end + + def id + @id + end + + def delete() + tk_call(@tpath, 'notify', 'delete', @id) + NotifyID_TBL.mutex.synchronize{ + NotifyID_TBL[@tpath].delete(@id) + } + self + end + + def info() + lst = simplelist(tk_call(@tpath, 'notify', 'info', id)) + lst[0] = Tk::BLT::Tree::Notify.id2obj(@tree, lst[0]) + lst[1] = simplelist(lst[1]).collect{|flag| flag[1..-1]} + lst[2] = tk_tcl2ruby(lst[2]) + lst + end + end + + ################################### + + class Trace < TkObject + TraceID_TBL = TkCore::INTERP.create_table + + TkCore::INTERP.init_ip_env{ + TraceID_TBL.mutex.synchronize{ TraceID_TBL.clear } + } + + def self.id2obj(tree, id) + tpath = tree.path + TraceID_TBL.mutex.synchronize{ + if TraceID_TBL[tpath] + if TraceID_TBL[tpath][id] + TraceID_TBL[tpath][id] + else + begin + # self.new([tree, id]) + (obj = self.allocate).instance_eval{ + @parent = @tree = tree + @tpath = @parent.path + @path = @id = node # == traceID + TraceID_TBL[@tpath] ||= {} + TraceID_TBL[@tpath][@id] = self + } + obj + rescue + id + end + end + else + id + end + } + end + + def self.new(tree, *args, &b) + TraceID_TBL.mutex.synchronize{ + if tree.kind_of?(Array) + # not create + tpath = tree[0].path + TraceID_TBL[tpath] ||= {} + unless (obj = TraceID_TBL[tpath][tree[1]]) + (TraceID_TBL[tpath][tree[1]] = + obj = self.allocate).instance_eval{ + @parent = @tree = tree + @tpath = @parent.path + @path = @id = tree[1] # == traceID + } + end + return obj + end + + # super(true, tree, *args, &b) + (obj = self.allocate).instance_eval{ + initialize(tree, *args, &b) + TraceID_TBL[@tpath] ||= {} + TraceID_TBL[@tpath][@id] = self + } + return obj + } + end + + def initialize(tree, node, key, opts, cmd=nil, &b) + @parent = @tree = tree + @tpath = @parent.path + + if !cmd + if b + cmd = Proc.new(&b) + else + fail ArgumentError, "lack of 'command' argument" + end + end + + @path = @id = tk_call(@tpath, 'trace', 'create', node, key, opts, + proc{|t, id, k, ops| + tobj = Tk::BLT::Tree.id2obj(t) + if tobj.kind_of?(Tk::BLT::Tree) + nobj = Tk::BLT::Tree::Node.id2obj(tobj, id) + else + nobj = id + end + cmd.call(tobj, nobj, k, ops) + }) + end + + def id + @id + end + + def delete() + tk_call(@tpath, 'trace', 'delete', @id) + TraceID_TBL.mutex.synchronize{ + TraceID_TBL[tpath].delete(@id) + } + self + end + + def info() + lst = simplelist(tk_call(@tpath, 'trace', 'info', id)) + lst[0] = Tk::BLT::Tree::Trace.id2obj(@tree, lst[0]) + lst[2] = simplelist(lst[2]) + lst[3] = tk_tcl2ruby(lst[3]) + lst + end + end + + ################################### + + TreeID_TBL = TkCore::INTERP.create_table + + (Tree_ID = ['blt_tree'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + def __keyonly_optkeys + { + # apply / find command + 'invert'=>nil, 'leafonly'=>nil, 'nocase'=>nil, + + # apply / find / sort command + 'path'=>nil, + + # copy / restore / restorefile command + 'overwrite'=>nil, + + # copy command + 'recurse'=>nil, 'tags'=>nil, + + # sort command + 'ascii'=>nil, 'decreasing'=>nil, 'disctionary'=>nil, + 'integer'=>nil, 'real'=>nil, 'recurse'=>nil, 'reorder'=>nil, + } + end + + def self.id2obj(id) + TreeID_TBL.mutex.synchronize{ + TreeID_TBL[id]? TreeID_TBL[id]: id + } + end + + def self.names(pat = None) + simplelist(tk_call('::blt::tree', 'names', pat)).collect{|name| + id2obj(name) + } + end + + def self.destroy(*names) + tk_call('::blt::tree', 'destroy', + *(names.collect{|n| (n.kind_of?(Tk::BLT::Tree))? n.id: n }) ) + end + + def self.new(name = nil) + TreeID_TBL.mutex.synchronize{ + if name && TreeID_TBL[name] + TreeID_TBL[name] + else + (obj = self.allocate).instance_eval{ + initialize(name) + TreeID_TBL[@id] = self + } + obj + end + } + end + + def initialzie(name = nil) + if name + @path = @id = name + else + Tree_ID.mutex.synchronize{ + @path = @id = Tree_ID.join(TkCore::INTERP._ip_id_) + Tree_ID[1].succ! + } + end + + tk_call('::blt::tree', 'create', @id) + end + + def __destroy_hook__ + Tk::BLT::Tree::Node::TreeNodeID_TBL.mutex.synchronize{ + Tk::BLT::Tree::Node::TreeNodeID_TBL.delete(@path) + } + Tk::BLT::Tree::Tag::TreeTagID_TBL.mutex.synchronize{ + Tk::BLT::Tree::Tag::TreeTagID_TBL.delete(@path) + } + Tk::BLT::Tree::Notify::NotifyID_TBL.mutex.synchronize{ + Tk::BLT::Tree::Notify::NotifyID_TBL.delete(@path) + } + Tk::BLT::Tree::Trace::TraceID_TBL.mutex.synchronize{ + Tk::BLT::Tree::Trace::TraceID_TBL.delete(@path) + } + end + + def tagid(tag) + if tag.kind_of?(Tk::BLT::Tree::Node) || + tag.kind_of?(Tk::BLT::Tree::Tag) || + tag.kind_of?(Tk::BLT::Tree::Notify) || + tag.kind_of?(Tk::BLT::Tree::Trace) + tag.id + else + tag # maybe an Array of configure parameters + end + end + + def destroy() + tk_call('::blt::tree', 'destroy', @id) + self + end + + def ancestor(node1, node2) + Tk::BLT::Tree::Node.id2obj(self, tk_call('::blt::tree', 'ancestor', + tagid(node1), tagid(node2))) + end + + def apply(node, keys={}) + tk_call('::blt::tree', 'apply', tagid(node), __conv_keyonly_opts(keys)) + self + end + + def attach(tree_obj) + tk_call('::blt::tree', 'attach', tree_obj) + self + end + + def children(node) + simplelist(tk_call('::blt::tree', 'children', tagid(node))).collect{|n| + Tk::BLT::Tree::Node.id2obj(self, n) + } + end + + def copy(src, parent, keys={}) + id = tk_call('::blt::tree', 'copy', tagid(src), tagid(parent), + __conv_keyonly_opts(keys)) + Tk::BLT::Tree::Node.new(self, nil, 'node'=>id) + end + def copy_to(src, dest_tree, parent, keys={}) + return copy(src, parent, keys={}) unless dest_tree + + id = tk_call('::blt::tree', 'copy', tagid(src), dest_tree, + tagid(parent), __conv_keyonly_opts(keys)) + Tk::BLT::Tree::Node.new(dest_tree, nil, 'node'=>id) + end + + def degree(node) + number(tk_call('::blt::tree', 'degree', tagid(node))) + end + + def delete(*nodes) + tk_call('::blt::tree', 'delete', *(nodes.collect{|node| tagid(node)})) + Tk::BLT::Tree::Node::TreeNodeID_TBL.mutex.synchronize{ + nodes.each{|node| + if node.kind_of?(Tk::BLT::Tree::Node) + Tk::BLT::Tree::Node::TreeNodeID_TBL[@path].delete(node.id) + else + Tk::BLT::Tree::Node::TreeNodeID_TBL[@path].delete(node.to_s) + end + } + } + self + end + + def depth(node) + number(tk_call('::blt::tree', 'depth', tagid(node))) + end + + def dump(node) + simplelist(tk_call('::blt::tree', 'dump', tagid(node))).collect{|n| + simplelist(n) + } + end + + def dump_to_file(node, file) + tk_call('::blt::tree', 'dumpfile', tagid(node), file) + self + end + + def exist?(node, key=None) + bool(tk_call('::blt::tree', 'exists', tagid(node), key)) + end + + def find(node, keys={}) + simplelist(tk_call('::blt::tree', 'find', tagid(node), + __conv_keyonly_opts(keys))).collect{|n| + Tk::BLT::Tree::Node.id2obj(self, n) + } + end + + def find_child(node, label) + ret = tk_call('::blt::tree', 'findchild', tagid(node), label) + (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret) + end + + def first_child(node) + ret = tk_call('::blt::tree', 'firstchild', tagid(node)) + (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret) + end + + def get(node) + Hash[*simplelist(tk_call('::blt::tree', 'get', tagid(node)))] + end + def get_value(node, key, default_val=None) + tk_call('::blt::tree', 'get', tagid(node), key, default_val) + end + + def index(node) + Tk::BLT::Tree::Node.id2obj(self, + tk_call('::blt::tree', 'index', tagid(node))) + end + + def insert(parent, keys={}) + id = tk_call('::blt::tree', 'insert', tagid(parent), keys) + Tk::BLT::Tree::Node.new(self, nil, 'node'=>id) + end + + def ancestor?(node1, node2) + bool(tk_call('::blt::tree', 'is', 'ancestor', + tagid(node1), tagid(node2))) + end + def before?(node1, node2) + bool(tk_call('::blt::tree', 'is', 'before', + tagid(node1), tagid(node2))) + end + def leaf?(node) + bool(tk_call('::blt::tree', 'is', 'leaf', tagid(node))) + end + def link?(node) + bool(tk_call('::blt::tree', 'is', 'link', tagid(node))) + end + def root?(node) + bool(tk_call('::blt::tree', 'is', 'root', tagid(node))) + end + + def keys(node, *nodes) + if nodes.empty? + simplelist(tk_call('blt::tree', 'keys', tagid(node))) + else + simplelist(tk_call('blt::tree', 'keys', tagid(node), + *(nodes.collect{|n| tagid(n)}))).collect{|lst| + simplelist(lst) + } + end + end + + def label(node, text=nil) + if text + tk_call('::blt::tree', 'label', tagid(node), text) + text + else + tk_call('::blt::tree', 'label', tagid(node)) + end + end + + def last_child(node) + ret = tk_call('::blt::tree', 'lastchild', tagid(node)) + (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret) + end + + def link(parent, node, keys={}) + ret = tk_call('::blt::tree', 'link', tagid(parent), tagid(node), + __conv_keyonly_opts(keys)) + (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret) + end + + def move(node, dest, keys={}) + tk_call('::blt::tree', 'move', tagid(node), tagid(dest), keys) + self + end + + def next(node) + ret = tk_call('::blt::tree', 'next', tagid(node)) + (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret) + end + + def next_sibling(node) + ret = tk_call('::blt::tree', 'nextsibling', tagid(node)) + (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret) + end + + def notify_create(*args, &b) + Tk::BLT::Tree::Notify.new(self, *args, &b) + end + + def notify_delete(id) + if id.kind_of?(Tk::BLT::Tree::Notify) + id.delete + else + tk_call(@path, 'notify', 'delete', id) + Tk::BLT::Tree::Notify::NotifyID_TBL.mutex.synchronize{ + Tk::BLT::Tree::Notify::NotifyID_TBL[@path].delete(id.to_s) + } + end + self + end + + def notify_info(id) + lst = simplelist(tk_call(@path, 'notify', 'info', tagid(id))) + lst[0] = Tk::BLT::Tree::Notify.id2obj(self, lst[0]) + lst[1] = simplelist(lst[1]).collect{|flag| flag[1..-1]} + lst[2] = tk_tcl2ruby(lst[2]) + lst + end + + def notify_names() + tk_call(@path, 'notify', 'names').collect{|id| + Tk::BLT::Tree::Notify.id2obj(self, id) + } + end + + def parent(node) + ret = tk_call('::blt::tree', 'parent', tagid(node)) + (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret) + end + + def fullpath(node) + tk_call('::blt::tree', 'path', tagid(node)) + end + + def position(node) + number(tk_call('::blt::tree', 'position', tagid(node))) + end + + def previous(node) + ret = tk_call('::blt::tree', 'previous', tagid(node)) + (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret) + end + + def prev_sibling(node) + ret = tk_call('::blt::tree', 'prevsibling', tagid(node)) + (ret == '-1')? nil: Tk::BLT::Tree::Node.id2obj(self, ret) + end + + def restore(node, str, keys={}) + tk_call('::blt::tree', 'restore', tagid(node), str, + __conv_keyonly_opts(keys)) + self + end + def restore_overwrite(node, str, keys={}) + keys = __conv_keyonly_opts(keys) + keys.delete('overwrite') + keys.delete(:overwrite) + tk_call('::blt::tree', 'restore', tagid(node), str, '-overwrite', keys) + self + end + + def restore_from_file(node, file, keys={}) + tk_call('::blt::tree', 'restorefile', tagid(node), file, + __conv_keyonly_opts(keys)) + self + end + def restore_overwrite_from_file(node, file, keys={}) + keys = __conv_keyonly_opts(keys) + keys.delete('overwrite') + keys.delete(:overwrite) + tk_call('::blt::tree', 'restorefile', tagid(node), file, + '-overwrite', keys) + self + end + + def root(node=None) + Tk::BLT::Tree::Node.id2obj(self, tk_call('::blt::tree', 'root', + tagid(node))) + end + + def set(node, data) + unless data.kind_of?(Hash) + fail ArgumentError, 'Hash is expected for data' + end + args = [] + data.each{|k, v| args << k << v} + tk_call('::blt::tree', 'set', tagid(node), *args) + self + end + + def size(node) + number(tk_call('::blt::tree', 'size', tagid(node))) + end + + def sort(node, keys={}) + tk_call('::blt::tree', 'sort', tagid(node), __conv_keyonly_opts(keys)) + self + end + + def tag_add(tag, *nodes) + tk_call(@path, 'tag', 'add', tagid(tag), *(nodes.collect{|n| tagid(n)})) + self + end + + def tag_delete(tag, *nodes) + tk_call(@path, 'tag', 'delete', tagid(tag), + *(nodes.collect{|n| tagid(n)})) + self + end + + def tag_forget(tag) + tag = tag.id if tag.kind_of?(Tk::BLT::Tree::Tag) + tk_call(@path, 'tag', 'forget', tag) + TreeTagID_TBL.mutex.synchronize{ + TreeTagID_TBL[@path].delete(tag) + } + self + end + + def tag_get(node, *patterns) + simplelist(tk_call(@tpath, 'tag', 'get', tagid(node), + *(patterns.collect{|pat| tagid(pat)}))).collect{|str| + Tk::BLT::Tree::Tag.id2obj(self, str) + } + end + + def tag_names(node = None) + simplelist(tk_call(@tpath, 'tag', 'names', tagid(node))).collect{|str| + Tk::BLT::Tree::Tag.id2obj(self, str) + } + end + + def tag_nodes(tag) + simplelist(tk_call(@tpath, 'tag', 'nodes', tagid(tag))).collect{|node| + Tk::BLT::Tree::Node.id2obj(self, node) + } + end + + def tag_set(node, *tags) + tk_call(@path, 'tag', 'set', tagid(node), *(tags.collect{|t| tagid(t)})) + self + end + + def tag_unset(node, *tags) + tk_call(@path, 'tag', 'unset', tagid(node), + *(tags.collect{|t| tagid(t)})) + self + end + + def trace_create(*args, &b) + Tk::BLT::Tree::Trace.new(self, *args, &b) + end + +=begin + def trace_delete(*args) + args.each{|id| + if id.kind_of?(Tk::BLT::Tree::Trace) + id.delete + else + tk_call(@path, 'trace', 'delete', id) + Tk::BLT::Tree::Trace::TraceID_TBL[@path].delete(id.to_s) + end + self + } + end +=end + def trace_delete(*args) + args = args.collect{|id| tagid(id)} + tk_call(@path, 'trace', 'delete', *args) + Tk::BLT::Tree::Trace::TraceID_TBL.mutex.synchronize{ + args.each{|id| Tk::BLT::Tree::Trace::TraceID_TBL[@path].delete(id.to_s)} + } + self + end + + def trace_info(id) + lst = simplelist(tk_call(@path, 'trace', 'info', tagid(id))) + lst[0] = Tk::BLT::Tree::Trace.id2obj(self, lst[0]) + lst[2] = simplelist(lst[2]) + lst[3] = tk_tcl2ruby(lst[3]) + lst + end + + def trace_names() + tk_call(@path, 'trace', 'names').collect{|id| + Tk::BLT::Tree::Trace.id2obj(self, id) + } + end + + def type(node, key) + tk_call('::blt::tree', 'type', tagid(node), key) + end + + def unset(node, *keys) + tk_call('::blt::tree', 'unset', tagid(node), *keys) + self + end + + def values(node, key=None) + simplelist(tk_call('::blt::tree', 'values', tagid(node), key)) + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/treeview.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/treeview.rb new file mode 100644 index 0000000..38d9041 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/treeview.rb @@ -0,0 +1,1287 @@ +# +# tkextlib/blt/treeview.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/blt.rb' +require 'tk/validation.rb' + +module Tk::BLT + class Treeview < TkWindow + module ConfigMethod + end + + module TagOrID_Methods + end + + class Node < TkObject + end + + class Tag < TkObject + end + end + + class Hiertable < Treeview + end +end + +###################################### + +module Tk::BLT::Treeview::ConfigMethod + include TkItemConfigMethod + + def __item_boolval_optkeys(id) + case id + when Array + # id := [ 'column', name ] + ['edit', 'hide'] + when 'sort' + ['decreasing'] + else + [] + end + end + private :__item_boolval_optkeys + + def __item_strval_optkeys(id) + case id + when Array + # id := [ 'column', name ] + super() << 'titleforeground' << 'titleshadow' + when 'sort' + ['decreasing'] + else + [] + end + end + private :__item_strval_optkeys + + def __item_listval_optkeys(id) + case id + when 'entry' + ['bindtags'] + else + [] + end + end + private :__item_listval_optkeys + + def __item_cget_cmd(id) + if id.kind_of?(Array) + # id := [ type, name ] + [self.path, id[0], 'cget', id[1]] + else + [self.path, id, 'cget'] + end + end + private :__item_cget_cmd + + def __item_config_cmd(id) + if id.kind_of?(Array) + # id := [ type, name ] + [self.path, id[0], 'configure', id[1]] + else + [self.path, id, 'configure'] + end + end + private :__item_config_cmd + + def __item_pathname(id) + if id.kind_of?(Array) + id = tagid(id[1]) + end + [self.path, id].join(';') + end + private :__item_pathname + + def column_cget_tkstring(name, option) + itemcget_tkstring(['column', name], option) + end + def column_cget(name, option) + itemcget(['column', name], option) + end + def column_cget_strict(name, option) + itemcget_strict(['column', name], option) + end + def column_configure(name, slot, value=None) + itemconfigure(['column', name], slot, value) + end + def column_configinfo(name, slot=nil) + itemconfiginfo(['column', name], slot) + end + def current_column_configinfo(name, slot=nil) + current_itemconfiginfo(['column', name], slot) + end + + def button_cget_tkstring(option) + itemcget_tkstring('button', option) + end + def button_cget(option) + itemcget('button', option) + end + def button_cget_strict(option) + itemcget_strict('button', option) + end + def button_configure(slot, value=None) + itemconfigure('button', slot, value) + end + def button_configinfo(slot=nil) + itemconfiginfo('button', slot) + end + def current_button_configinfo(slot=nil) + current_itemconfiginfo('button', slot) + end + + def entry_cget_tkstring(option) + itemcget_tkstring('entry', option) + end + def entry_cget(option) + ret = itemcget('entry', option) + if option == 'bindtags' || option == :bindtags + ret.collect{|tag| TkBindTag.id2obj(tag)} + else + ret + end + end + def entry_cget_strict(option) + ret = itemcget_strict('entry', option) + if option == 'bindtags' || option == :bindtags + ret.collect{|tag| TkBindTag.id2obj(tag)} + else + ret + end + end + def entry_configure(slot, value=None) + itemconfigure('entry', slot, value) + end + def entry_configinfo(slot=nil) + ret = itemconfiginfo('entry', slot) + + if TkComm::GET_CONFIGINFO_AS_ARRAY + if slot + if slot == 'bindtags' || slot == :bindtags + ret[-2] = ret[-2].collect{|tag| TkBindTag.id2obj(tag)} + ret[-1] = ret[-1].collect{|tag| TkBindTag.id2obj(tag)} + end + else + inf = ret.assoc('bindtags') + inf[-2] = inf[-2].collect{|tag| TkBindTag.id2obj(tag)} + inf[-1] = inf[-1].collect{|tag| TkBindTag.id2obj(tag)} + end + + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY + if (inf = ret['bindtags']) + inf[-2] = inf[-2].collect{|tag| TkBindTag.id2obj(tag)} + inf[-1] = inf[-1].collect{|tag| TkBindTag.id2obj(tag)} + ret['bindtags'] = inf + end + end + + ret + end + def current_entry_configinfo(slot=nil) + ret = current_itemconfiginfo('entry', slot) + + if (val = ret['bindtags']) + ret['bindtags'] = val.collect{|tag| TkBindTag.id2obj(tag)} + end + + ret + end + + def sort_cget_tkstring(option) + itemcget_tkstring('sort', option) + end + def sort_cget(option) + itemcget('sort', option) + end + def sort_cget_strict(option) + itemcget_strict('sort', option) + end + def sort_configure(slot, value=None) + itemconfigure('sort', slot, value) + end + def sort_configinfo(slot=nil) + itemconfiginfo('sort', slot) + end + def current_sort_configinfo(slot=nil) + current_itemconfiginfo('sort', slot) + end + + def text_cget_tkstring(option) + itemcget_tkstring('text', option) + end + def text_cget(option) + itemcget('text', option) + end + def text_cget_strict(option) + itemcget_strict('text', option) + end + def text_configure(slot, value=None) + itemconfigure('text', slot, value) + end + def text_configinfo(slot=nil) + itemconfiginfo('text', slot) + end + def current_text_configinfo(slot=nil) + current_itemconfiginfo('text', slot) + end + + private :itemcget_tkstring, :itemcget, :itemcget_strict + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo +end + +class Tk::BLT::Treeview + TkCommandNames = ['::blt::treeview'.freeze].freeze + WidgetClassName = 'TreeView'.freeze + WidgetClassNames[WidgetClassName] ||= self + + include Scrollable + include ValidateConfigure + include ItemValidateConfigure + include Tk::BLT::Treeview::ConfigMethod + + ######################## + + def __boolval_optkeys + ['autocreate', 'allowduplicates', 'exportselection', 'flat', 'hideroot', + 'newtags', 'showtitles', 'sortselection'] + end + private :__boolval_optkeys + + def __strval_optkeys + super() + ['focusforeground', 'linecolor', 'separator', 'trim'] + end + private :__strval_optkeys + + ######################## + + class OpenCloseCommand < TkValidateCommand + class ValidateArgs < TkUtil::CallbackSubst + KEY_TBL = [ + [ ?W, ?w, :widget ], + [ ?p, ?s, :name ], + [ ?P, ?s, :fullpath ], + [ ?#, ?x, :node_id ], + nil + ] + + PROC_TBL = [ + [ ?x, TkComm.method(:num_or_str) ], + [ ?s, TkComm.method(:string) ], + [ ?w, TkComm.method(:window) ], + nil + ] + +=begin + # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) + KEY_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) + end + inf + } + + PROC_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + end + inf + } +=end + + _setup_subst_table(KEY_TBL, PROC_TBL); + + def self.ret_val(val) + val + end + end + + def self._config_keys + ['opencommand', 'closecomand'] + end + end + + def __validation_class_list + super() << OpenCloseCommand + end + + Tk::ValidateConfigure.__def_validcmd(binding, OpenCloseCommand) + + ######################## + + def __item_validation_class_list(id) + case id + when 'entry' + super(id) << OpenCloseCommand + else + super(id) + end + end + + Tk::ItemValidateConfigure.__def_validcmd(binding, OpenCloseCommand) + + ######################## + + def __destroy_hook__ + Tk::BLT::Treeview::Node::TreeNodeID_TBL.mutex.synchronize{ + Tk::BLT::Treeview::Node::TreeNodeID_TBL.delete(@path) + } + Tk::BLT::Treeview::Tag::TreeTagID_TBL.mutex.synchronize{ + Tk::BLT::Treeview::Tag::TreeTagID_TBL.delete(@path) + } + end + + def tagid(tag) + if tag.kind_of?(Tk::BLT::Treeview::Node) \ + || tag.kind_of?(Tk::BLT::Treeview::Tag) + tag.id + else + tag # maybe an Array of configure parameters + end + end + private :tagid + + def tagid2obj(tagid) + if tagid.kind_of?(Integer) + Tk::BLT::Treeview::Node.id2obj(self, tagid.to_s) + elsif tagid.kind_of?(String) + if tagid =~ /^\d+$/ + Tk::BLT::Treeview::Node.id2obj(self, tagid) + else + Tk::BLT::Treeview::Tag.id2obj(self, tagid) + end + else + tagid + end + end + + def bbox(*tags) + list(tk_send('bbox', *(tags.collect{|tag| tagid(tag)}))) + end + + def screen_bbox(*tags) + list(tk_send('bbox', '-screen', *(tags.collect{|tag| tagid(tag)}))) + end + + def tag_bind(tag, seq, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind([@path, 'bind', tagid(tag)], seq, cmd, *args) + self + end + def tag_bind_append(tag, seq, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append([@path, 'bind', tagid(tag)], seq, cmd, *args) + self + end + def tag_bind_remove(tag, seq) + _bind_remove([@path, 'bind', tagid(tag)], seq) + self + end + def tag_bindinfo(tag, seq=nil) + _bindinfo([@path, 'bind', tagid(tag)], seq) + end + + def button_activate(tag) + tk_send('button', 'activate', tagid(tag)) + self + end + + def button_bind(tag, seq, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind([@path, 'button', 'bind', tagid(tag)], seq, cmd, *args) + self + end + def button_bind_append(tag, seq, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append([@path, 'button', 'bind', tagid(tag)], seq, cmd, *args) + self + end + def button_bind_remove(tag, seq) + _bind_remove([@path, 'button', 'bind', tagid(tag)], seq) + self + end + def button_bindinfo(tag, seq=nil) + _bindinfo([@path, 'button', 'bind', tagid(tag)], seq) + end + + def close(*tags) + tk_send('close', *(tags.collect{|tag| tagid(tag)})) + self + end + def close_recurse(*tags) + tk_send('close', '-recurse', *(tags.collect{|tag| tagid(tag)})) + self + end + + def column_activate(column=None) + if column == None + tk_send('column', 'activate') + else + tk_send('column', 'activate', column) + self + end + end + + def column_delete(*fields) + tk_send('column', 'delete', *fields) + self + end + def column_insert(pos, field, *opts) + tk_send('column', 'insert', pos, field, *opts) + self + end + def column_invoke(field) + tk_send('column', 'invoke', field) + self + end + def column_move(name, dest) + tk_send('column', 'move', name, dest) + self + end + def column_names() + simplelist(tk_send('column', 'names')) + end + def column_nearest(x, y=None) + tk_send('column', 'nearest', x, y) + end + + def curselection + simplelist(tk_send('curselection')).collect{|id| tagid2obj(id)} + end + + def delete(*tags) + tk_send('delete', *(tags.collect{|tag| tagid(tag)})) + self + end + + def entry_activate(tag) + tk_send('entry', 'activate', tagid(tag)) + self + end + def entry_children(tag, first=None, last=None) + simplelist(tk_send('entry', 'children', tagid(tag), + first, last)).collect{|id| tagid2obj(id)} + end + def entry_delete(tag, first=None, last=None) + tk_send('entry', 'delete', tagid(tag), first, last) + end + def entry_before?(tag1, tag2) + bool(tk_send('entry', 'isbefore', tagid(tag1), tagid(tag2))) + end + def entry_hidden?(tag) + bool(tk_send('entry', 'ishidden', tagid(tag))) + end + def entry_open?(tag) + bool(tk_send('entry', 'isopen', tagid(tag))) + end + + def entry_size(tag) + number(tk_send('entry', 'size', tagid(tag))) + end + def entry_size_recurse(tag) + number(tk_send('entry', 'size', '-recurse', tagid(tag))) + end + + def _search_flags(keys) + keys = _symbolkey2str(keys) + keys['exact'] = None if keys.delete('exact') + keys['glob'] = None if keys.delete('glob') + keys['regexp'] = None if keys.delete('regexp') + keys['nonmatching'] = None if keys.delete('nonmatching') + end + private :_search_flags + + ################################ + + class FindExecFlagValue < TkValidateCommand + class ValidateArgs < TkUtil::CallbackSubst + KEY_TBL = [ + [ ?W, ?w, :widget ], + [ ?p, ?s, :name ], + [ ?P, ?s, :fullpath ], + [ ?#, ?x, :node_id ], + nil + ] + + PROC_TBL = [ + [ ?x, TkComm.method(:num_or_str) ], + [ ?s, TkComm.method(:string) ], + [ ?w, TkComm.method(:window) ], + nil + ] + +=begin + # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) + KEY_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) + end + inf + } + + PROC_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + end + inf + } +=end + + _setup_subst_table(KEY_TBL, PROC_TBL); + + def self.ret_val(val) + val + end + end + + def self._config_keys + [] + end + end + + def _find_exec_flag_value(val) + if val.kind_of?(Array) + cmd, *args = val + #FindExecFlagValue.new(cmd, args.join(' ')) + FindExecFlagValue.new(cmd, *args) + elsif TkComm._callback_entry?(val) + FindExecFlagValue.new(val) + else + val + end + end + + ################################ + + def find(first, last, keys={}) + keys = _search_flags(keys) + keys['exec'] = _find_exec_flag_value(keys['exec']) if keys.key?('exec') + args = hash_kv(keys) << '--' << tagid(first) << tagid(last) + simplelist(tk_send('find', *args)).collect{|id| tagid2obj(id)} + end + + def tag_focus(tag) + tk_send('focus', tagid(tag)) + self + end + def get(*tags) + simplelist(tk_send('get', *(tags.collect{|tag| tagid(tag)}))) + end + def get_full(*tags) + simplelist(tk_send('get', '-full', *(tags.collect{|tag| tagid(tag)}))) + end + + def hide(*tags) + if tags[-1].kind_of?(Hash) + keys = tags.pop + else + keys = {} + end + keys = _search_flags(keys) + args = hash_kv(keys) << '--' + args.concat(tags.collect{|t| tagid(t)}) + tk_send('hide', *args) + self + end + + def index(str) + tagid2obj(tk_send('index', str)) + end + def index_at(tag, str) + tagid2obj(tk_send('index', '-at', tagid(tag), str)) + end + def index_at_path(tag, str) + tagid2obj(tk_send('index', '-at', tagid(tag), '-path', str)) + end + + def insert(pos, parent=nil, keys={}) + Tk::BLT::Treeview::Node.new(pos, parent, keys) + end + def insert_at(tag, pos, parent=nil, keys={}) + if parent.kind_of?(Hash) + keys = parent + parent = nil + end + + keys = _symbolkey2str(keys) + keys['at'] = tagid(tag) + + Tk::BLT::Treeview::Node.new(pos, parent, keys) + end + + def move_before(tag, dest) + tk_send('move', tagid(tag), 'before', tagid(dest)) + self + end + def move_after(tag, dest) + tk_send('move', tagid(tag), 'after', tagid(dest)) + self + end + def move_into(tag, dest) + tk_send('move', tagid(tag), 'into', tagid(dest)) + self + end + + def nearest(x, y, var=None) + tagid2obj(tk_send('nearest', x, y, var)) + end + + def open(*tags) + tk_send('open', *(tags.collect{|tag| tagid(tag)})) + self + end + def open_recurse(*tags) + tk_send('open', '-recurse', *(tags.collect{|tag| tagid(tag)})) + self + end + + def range(first, last) + simplelist(tk_send('range', tagid(first), tagid(last))).collect{|id| + tagid2obj(id) + } + end + def range_open(first, last) + simplelist(tk_send('range', '-open', + tagid(first), tagid(last))).collect{|id| + tagid2obj(id) + } + 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(tag) + tk_send_without_enc('see', tagid(tag)) + self + end + def see_anchor(anchor, tag) + tk_send_without_enc('see', '-anchor', anchor, tagid(tag)) + self + end + + def selection_anchor(tag) + tk_send_without_enc('selection', 'anchor', tagid(tag)) + self + end + def selection_cancel() + tk_send_without_enc('selection', 'cancel') + self + end + def selection_clear(first, last=None) + tk_send_without_enc('selection', 'clear', tagid(first), tagid(last)) + self + end + def selection_clear_all() + tk_send_without_enc('selection', 'clearall') + self + end + def selection_mark(tag) + tk_send_without_enc('selection', 'mark', tagid(tag)) + self + end + def selection_include?(tag) + bool(tk_send('selection', 'include', tagid(tag))) + end + def selection_present?() + bool(tk_send('selection', 'present')) + end + def selection_set(first, last=None) + tk_send_without_enc('selection', 'set', tagid(first), tagid(last)) + self + end + def selection_toggle(first, last=None) + tk_send_without_enc('selection', 'toggle', tagid(first), tagid(last)) + self + end + + def show(*tags) + if tags[-1].kind_of?(Hash) + keys = tags.pop + else + keys = {} + end + keys = _search_flags(keys) + args = hash_kv(keys) << '--' + args.concat(tags.collect{|t| tagid(t)}) + tk_send('show', *args) + self + end + + def sort_auto(mode) + tk_send('sort', 'auto', mode) + self + end + def sort_auto=(mode) + tk_send('sort', 'auto', mode) + mode + end + def sort_auto? + bool(tk_send('sort', 'auto')) + end + def sort_once(*tags) + tk_send('sort', 'once', *(tags.collect{|tag| tagid(tag)})) + self + end + def sort_once_recurse(*tags) + tk_send('sort', 'once', '-recurse', *(tags.collect{|tag| tagid(tag)})) + self + end + + def tag_add(tag, *ids) + tk_send('tag', 'add', tagid(tag), *ids) + self + end + def tag_delete(tag, *ids) + tk_send('tag', 'delete', tagid(tag), *ids) + self + end + def tag_forget(tag) + tk_send('tag', 'forget', tagid(tag)) + self + end + def tag_names(id=nil) + id = (id)? tagid(id): None + + simplelist(tk_send('tag', 'nodes', id)).collect{|tag| + Tk::BLT::Treeview::Tag.id2obj(self, tag) + } + end + def tag_nodes(tag) + simplelist(tk_send('tag', 'nodes', tagid(tag))).collect{|id| + Tk::BLT::Treeview::Node.id2obj(self, id) + } + end + + def text_apply + tk_send('text', 'apply') + self + end + def text_cancel + tk_send('text', 'cancel') + self + end + + def text_delete(first, last) + tk_send('text', 'delete', first, last) + self + end + def text_get(x, y) + tk_send('text', 'get', x, y) + end + def text_get_root(x, y) + tk_send('text', 'get', '-root', x, y) + end + def text_icursor(idx) + tk_send('text', 'icursor', idx) + self + end + def text_index(idx) + num_or_str(tk_send('text', 'index', idx)) + end + def text_insert(idx, str) + tk_send('text', 'insert', idx, str) + self + end + + def text_selection_adjust(idx) + tk_send('text', 'selection', 'adjust', idx) + self + end + def text_selection_clear + tk_send('text', 'selection', 'clear') + self + end + def text_selection_from(idx) + tk_send('text', 'selection', 'from', idx) + self + end + def text_selection_present + num_or_str(tk_send('text', 'selection', 'present')) + end + def text_selection_range(start, last) + tk_send('text', 'selection', 'range', start, last) + self + end + def text_selection_to(idx) + tk_send('text', 'selection', 'to', idx) + self + end + + def toggle(tag) + tk_send('toggle', tagid(tag)) + self + end +end + +###################################### + +module Tk::BLT::Treeview::TagOrID_Methods + def bbox + @tree.bbox(self) + end + def screen_bbox + @tree.screen_bbox(self) + end + + def bind(seq, *args) + @tree.tag_bind(self, seq, *args) + self + end + def bind_append(seq, *args) + @tree.tag_bind_append(self, seq, *args) + self + end + def bind_remove(seq) + @tree.tag_bind_remove(self, seq) + self + end + def bindinfo(seq=nil) + @tree.tag_bindinfo(self, seq) + end + + def button_activate + @tree.button_activate(self) + self + end + + def button_bind(seq, *args) + @tree.button_bind(self, seq, *args) + self + end + def button_bind_append(seq, *args) + @tree.button_bind_append(self, seq, *args) + self + end + def button_bind_remove(seq) + @tree.button_bind_remove(self, seq) + self + end + def button_bindinfo(seq=nil) + @tree.button_bindinfo(self, seq) + end + + def close + @tree.close(self) + self + end + def close_recurse + @tree.close_recurse(self) + self + end + + def delete + @tree.delete(self) + self + end + + def entry_activate + @tree.entry_activate(self) + self + end + def entry_children(first=None, last=None) + @tree.entry_children(self, first, last) + end + def entry_delete(first=None, last=None) + @tree.entry_delete(self, first, last) + end + def entry_before?(tag) + @tree.entry_before?(self, tag) + end + def entry_hidden? + @tree.entry_before?(self) + end + def entry_open? + @tree.entry_open?(self) + end + + def entry_size + @tree.entry_size(self) + end + def entry_size_recurse + @tree.entry_size_recurse(self) + end + + def focus + @tree.tag_focus(self) + self + end + + def get + @tree.get(self) + end + def get_full + @tree.get_full(self) + end + + def hide + @tree.hide(self) + self + end + + def index(str) + @tree.index_at(self, str) + end + def index_path(str) + @tree.index_at_path(self, str) + end + + def insert(pos, parent=nil, keys={}) + @tree.insert_at(self, pos, parent, keys) + end + + def move_before(dest) + @tree.move_before(self, dest) + self + end + def move_after(dest) + @tree.move_after(self, dest) + self + end + def move_into(dest) + @tree.move_into(self, dest) + self + end + + def open + @tree.open(self) + self + end + def open_recurse + @tree.open_recurse(self) + self + end + + def range_to(tag) + @tree.range(self, tag) + end + def range_open_to(tag) + @tree.range(self, tag) + end + + def see + @tree.see(self) + self + end + def see_anchor(anchor) + @tree.see_anchor(anchor, self) + self + end + + def selection_anchor + @tree.selection_anchor(self) + self + end + def selection_clear + @tree.selection_clear(self) + self + end + def selection_mark + @tree.selection_mark(self) + self + end + def selection_include? + @tree.selection_include?(self) + end + def selection_set + @tree.selection_set(self) + self + end + def selection_toggle + @tree.selection_toggle(self) + self + end + + def show + @tree.show(self) + self + end + + def sort_once + @tree.sort_once(self) + self + end + def sort_once_recurse + @tree.sort_once_recurse(self) + self + end + + def toggle + @tree.toggle(self) + self + end +end + +###################################### + +class Tk::BLT::Treeview::Node < TkObject + include Tk::BLT::Treeview::TagOrID_Methods + + TreeNodeID_TBL = TkCore::INTERP.create_table + + (TreeNode_ID = ['blt_treeview_node'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + TkCore::INTERP.init_ip_env{ + TreeNodeID_TBL.mutex.synchronize{ TreeNodeID_TBL.clear } + } + + def self.id2obj(tree, id) + tpath = tree.path + TreeNodeID_TBL.mutex.synchronize{ + if TreeNodeID_TBL[tpath] + if TreeNodeID_TBL[tpath][id] + TreeNodeID_TBL[tpath][id] + else + begin + # self.new(tree, nil, nil, 'node'=>Integer(id)) + unless (tk_call(@tpath, 'get', id)).empty? + id = Integer(id) + (obj = self.allocate).instance_eval{ + @parent = @tree = tree + @tpath = @parent.path + @path = @id = id + TreeNodeID_TBL[@tpath] ||= {} + TreeNodeID_TBL[@tpath][@id] = self + } + obj + else + id + end + rescue + id + end + end + else + id + end + } + end + + def self.new(tree, pos, parent=nil, keys={}) + if parent.kind_of?(Hash) + keys = parent + parent = nil + end + + keys = _symbolkey2str(keys) + tpath = tree.path + + TreeNodeID_TBL.mutex.synchronize{ + TreeNodeID_TBL[tpath] ||= {} + if (id = keys['node']) && (obj = TreeNodeID_TBL[tpath][id]) + keys.delete('node') + tk_call(tree.path, 'move', id, pos, parent) if parent + return obj + end + + #super(tree, pos, parent, keys) + (obj = self.allocate).instance_eval{ + initialize(tree, pos, parent, keys) + TreeNodeID_TBL[tpath][@id] = self + } + obj + } + end + + def initialize(tree, pos, parent, keys) + @parent = @tree = tree + @tpath = @parent.path + + if (id = keys['node']) + # if tk_call(@tpath, 'get', id).empty? + # fail RuntimeError, "not exist the node '#{id}'" + # end + @path = @id = id + tk_call(@tpath, 'move', @id, pos, tagid(parent)) if parent + configure(keys) if keys && ! keys.empty? + else + name = nil + TreeNode_ID.mutex.synchronize{ + name = TreeNode_ID.join(TkCore::INTERP._ip_id_).freeze + TreeNode_ID[1].succ! + } + + at = keys.delete['at'] + + if parent + if parent.kind_of?(Tk::BLT::Treeview::Node) || + parent.kind_of?(Tk::BLT::Treeview::Tag) + path = [get_full(parent.id)[0], name] + at = nil # ignore 'at' option + else + path = [parent.to_s, name] + end + else + path = name + end + + if at + @id = tk_call(@tpath, 'insert', '-at', tagid(at), pos, path, keys) + else + @id = tk_call(@tpath, 'insert', pos, path, keys) + end + @path = @id + end + end + + def id + @id + end +end + +###################################### + +class Tk::BLT::Treeview::Tag < TkObject + include Tk::BLT::Treeview::TagOrID_Methods + + TreeTagID_TBL = TkCore::INTERP.create_table + + (TreeTag_ID = ['blt_treeview_tag'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + TkCore::INTERP.init_ip_env{ + TreeTagID_TBL.mutex.synchronize{ TreeTagID_TBL.clear } + } + + def self.id2obj(tree, name) + tpath = tree.path + TreeTagID_TBL.mutex.synchronize{ + if TreeTagID_TBL[tpath] + if TreeTagID_TBL[tpath][name] + TreeTagID_TBL[tpath][name] + else + #self.new(tree, name) + (obj = self.allocate).instance_eval{ + @parent = @tree = tree + @tpath = @parent.path + @path = @id = name + TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath] + TreeTagID_TBL[@tpath][@id] = self + } + obj + end + else + id + end + } + end + + def self.new_by_name(tree, name, *ids) + TreeTagID_TBL.mutex.synchronize{ + unless (obj = TreeTagID_TBL[tree.path][name]) + (obj = self.allocate).instance_eval{ + initialize(tree, name, ids) + TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath] + TreeTagID_TBL[@tpath][@id] = self + } + end + obj + } + end + + def self.new(tree, *ids) + TreeTagID_TBL.mutex.synchronize{ + (obj = self.allocate).instance_eval{ + if tree.kind_of?(Array) + initialize(tree[0], tree[1], ids) + else + initialize(tree, nil, ids) + end + TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath] + TreeTagID_TBL[@tpath][@id] = self + } + obj + } + end + + def initialize(tree, name, ids) + @parent = @tree = tree + @tpath = @parent.path + + if name + @path = @id = name + else + TreeTag_ID.mutex.synchronize{ + @path = @id = TreeTag_ID.join(TkCore::INTERP._ip_id_).freeze + TreeTag_ID[1].succ! + } + end + + unless ids.empty? + tk_call(@tpath, 'tag', 'add', @id, *(ids.collect{|id| tagid(id)})) + end + end + + def tagid(tag) + if tag.kind_of?(Tk::BLT::Treeview::Node) \ + || tag.kind_of?(Tk::BLT::Treeview::Tag) + tag.id + else + tag + end + end + private :tagid + + def id + @id + end + + def add(*ids) + tk_call(@tpath, 'tag', 'add', @id, *(ids{|id| tagid(id)})) + self + end + + def remove(*ids) + tk_call(@tpath, 'tag', 'delete', @id, *(ids{|id| tagid(id)})) + self + end + + def forget + tk_call(@tpath, 'tag', 'forget', @id) + self + end + + def nodes + simplelist(tk_call(@tpath, 'tag', 'nodes', @id)).collect{|id| + Tk::BLT::Treeview::Node.id2obj(@tree, id) + } + end +end + +class Tk::BLT::Hiertable + TkCommandNames = ['::blt::hiertable'.freeze].freeze + WidgetClassName = 'Hiertable'.freeze + WidgetClassNames[WidgetClassName] ||= self +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/unix_dnd.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/unix_dnd.rb new file mode 100644 index 0000000..8996f7c --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/unix_dnd.rb @@ -0,0 +1,141 @@ +# +# tkextlib/blt/unix_dnd.rb +# +# *** This is alpha version, because there is no document on BLT. *** +# +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/blt.rb' + +module Tk::BLT + module DnD + extend TkCore + + TkCommandNames = ['::blt::dnd'.freeze].freeze + + ############################## + + extend TkItemConfigMethod + + class << self + def __item_cget_cmd(id) + ['::blt::dnd', *id] + end + private :__item_cget_cmd + + def __item_config_cmd(id) + ['::blt::dnd', *id] + end + private :__item_config_cmd + + private :itemcget_tkstring, :itemcget, :itemcget_strict + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo + + def cget_tkstring(win, option) + itemcget_tkstring(['cget', win], option) + end + def cget(win, option) + itemcget(['cget', win], option) + end + def cget_strict(win, option) + itemcget_strict(['cget', win], option) + end + def configure(win, slot, value=None) + itemconfigure(['configure', win], slot, value) + end + def configinfo(win, slot=nil) + itemconfiginfo(['configure', win], slot) + end + def current_configinfo(win, slot=nil) + current_itemconfiginfo(['configure', win], slot) + end + + def token_cget_tkstring(win, option) + itemcget_tkstring(['token', 'cget', win], option) + end + def token_cget(win, option) + itemcget(['token', 'cget', win], option) + end + def token_cget_strict(win, option) + itemcget_strict(['token', 'cget', win], option) + end + def token_configure(win, slot, value=None) + itemconfigure(['token', 'configure', win], slot, value) + end + def token_configinfo(win, slot=nil) + itemconfiginfo(['token', 'configure', win], slot) + end + def current_token_configinfo(win, slot=nil) + current_itemconfiginfo(['token', 'configure', win], slot) + end + + def token_windowconfigure(win, slot, value=None) + itemconfigure(['token', 'window', win], slot, value) + end + def token_windowconfiginfo(win, slot=nil) + itemconfiginfo(['token', 'window', win], slot) + end + def current_token_windowconfiginfo(win, slot=nil) + current_itemconfiginfo(['token', 'window', win], slot) + end + end + + ############################## + + def self.cancel(win) + tk_call('::blt::dnd', 'cancel', *wins) + end + def self.delete(*wins) + tk_call('::blt::dnd', 'delete', *wins) + end + def self.delete_source(*wins) + tk_call('::blt::dnd', 'delete', '-source', *wins) + end + def self.delete_target(*wins) + tk_call('::blt::dnd', 'delete', '-target', *wins) + end + def self.drag(win, x, y, token=None) + tk_call('::blt::dnd', 'drag', win, x, y, token) + end + def self.drop(win, x, y, token=None) + tk_call('::blt::dnd', 'drop', win, x, y, token) + end + def self.get_data(win, fmt=nil, cmd=nil) + if fmt + tk_call('::blt::dnd', 'getdata', win, fmt, cmd) + else + list(tk_call('::blt::dnd', 'getdata', win)) + end + end + def self.names(pat=None) + list(tk_call('::blt::dnd', 'names', pat)) + end + def self.source_names(pat=None) + list(tk_call('::blt::dnd', 'names', '-source', pat)) + end + def self.target_names(pat=None) + list(tk_call('::blt::dnd', 'names', '-target', pat)) + end + def self.pull(win, fmt) + tk_call('::blt::dnd', 'pull', win, fmt) + end + def self.register(win, keys={}) + tk_call('::blt::dnd', 'register', win, keys) + end + def self.select(win, x, y, timestamp) + tk_call('::blt::dnd', 'select', win, x, y, timestamp) + end + def self.set_data(win, fmt=nil, cmd=nil) + if fmt + tk_call('::blt::dnd', 'setdata', win, fmt, cmd) + else + list(tk_call('::blt::dnd', 'setdata', win)) + end + end + def self.token(*args) + tk_call('::blt::dnd', 'token', *args) + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/vector.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/vector.rb new file mode 100644 index 0000000..742e901 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/vector.rb @@ -0,0 +1,256 @@ +# +# tkextlib/blt/vector.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/blt.rb' + +module Tk::BLT + class Vector < TkVariable + TkCommandNames = ['::blt::vector'.freeze].freeze + + def self.create(*args) + tk_call('::blt::vector', 'create', *args) + end + + def self.destroy(*args) + tk_call('::blt::vector', 'destroy', *args) + end + + def self.expr(expression) + tk_call('::blt::vector', 'expr', expression) + end + + def self.names(pat=None) + list = simplelist(tk_call('::blt::vector', 'names', pat)) + TkVar_ID_TBL.mutex.synchronize{ + list.collect{|name| + if TkVar_ID_TBL[name] + TkVar_ID_TBL[name] + elsif name[0..1] == '::' && TkVar_ID_TBL[name[2..-1]] + TkVar_ID_TBL[name[2..-1]] + else + name + end + } + } + end + + #################################### + + def initialize(size=nil, keys={}) + if size.kind_of?(Hash) + keys = size + size = nil + end + if size.kind_of?(Array) + # [first, last] + size = size.join(':') + end + if size + @id = TkCore::INTERP._invoke('::blt::vector', 'create', + "#auto(#{size})", *hash_kv(keys)) + else + @id = TkCore::INTERP._invoke('::blt::vector', 'create', + "#auto", *hash_kv(keys)) + end + + TkVar_ID_TBL.mutex.synchronize{ + TkVar_ID_TBL[@id] = self + } + + @def_default = false + @default_val = nil + + @trace_var = nil + @trace_elem = nil + @trace_opts = nil + + # teach Tk-ip that @id is global var + TkCore::INTERP._invoke_without_enc('global', @id) + end + + def destroy + tk_call('::blt::vector', 'destroy', @id) + end + + def inspect + '#<Tk::BLT::Vector: ' + @id + '>' + end + + def to_s + @id + end + + def *(item) + list(tk_call(@id, '*', item)) + end + + def +(item) + list(tk_call(@id, '+', item)) + end + + def -(item) + list(tk_call(@id, '-', item)) + end + + def /(item) + list(tk_call(@id, '/', item)) + end + + def append(*vectors) + tk_call(@id, 'append', *vectors) + end + + def binread(channel, len=None, keys={}) + if len.kind_of?(Hash) + keys = len + len = None + end + keys = _symbolkey2str(keys) + keys['swap'] = None if keys.delete('swap') + tk_call(@id, 'binread', channel, len, keys) + end + + def clear() + tk_call(@id, 'clear') + self + end + + def delete(*indices) + tk_call(@id, 'delete', *indices) + self + end + + def dup_vector(vec) + tk_call(@id, 'dup', vec) + self + end + + def expr(expression) + tk_call(@id, 'expr', expression) + self + end + + def index(idx, val=None) + number(tk_call(@id, 'index', idx, val)) + end + + def [](idx) + index(idx) + end + + def []=(idx, val) + index(idx, val) + end + + def length() + number(tk_call(@id, 'length')) + end + + def length=(size) + number(tk_call(@id, 'length', size)) + end + + def merge(*vectors) + tk_call(@id, 'merge', *vectors) + self + end + + def normalize(vec=None) + tk_call(@id, 'normalize', vec) + self + end + + def notify(keyword) + tk_call(@id, 'notify', keyword) + self + end + + def offset() + number(tk_call(@id, 'offset')) + end + + def offset=(val) + number(tk_call(@id, 'offset', val)) + end + + def random() + tk_call(@id, 'random') + end + + def populate(vector, density=None) + tk_call(@id, 'populate', vector, density) + self + end + + def range(first, last=None) + list(tk_call(@id, 'range', first, last)) + end + + def search(val1, val2=None) + list(tk_call(@id, 'search', val1, val2)) + end + + def set(item) + tk_call(@id, 'set', item) + self + end + + def seq(start, finish=None, step=None) + tk_call(@id, 'seq', start, finish, step) + self + end + + def sort(*vectors) + tk_call(@id, 'sort', *vectors) + self + end + + def sort_reverse(*vectors) + tk_call(@id, 'sort', '-reverse', *vectors) + self + end + + def split(*vectors) + tk_call(@id, 'split', *vectors) + self + end + + def variable(var) + tk_call(@id, 'variable', var) + self + end + end + + class VectorAccess < Vector + def self.new(name) + TkVar_ID_TBL.mutex.synchronize{ + if TkVar_ID_TBL[name] + TkVar_ID_TBL[name] + else + (obj = self.allocate).instance_eval{ + initialize(name) + TkVar_ID_TBL[@id] = self + } + obj + end + } + end + + def initialize(vec_name) + @id = vec_name + + @def_default = false + @default_val = nil + + @trace_var = nil + @trace_elem = nil + @trace_opts = nil + + # teach Tk-ip that @id is global var + TkCore::INTERP._invoke_without_enc('global', @id) + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/watch.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/watch.rb new file mode 100644 index 0000000..292623f --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/watch.rb @@ -0,0 +1,175 @@ +# +# tkextlib/blt/watch.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/blt.rb' + +module Tk::BLT + class Watch < TkObject + extend TkCore + + TkCommandNames = ['::blt::watch'.freeze].freeze + + WATCH_ID_TBL = TkCore::INTERP.create_table + + (BLT_WATCH_ID = ['blt_watch_id'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + TkCore::INTERP.init_ip_env{ + WATCH_ID_TBL.mutex.synchronize{ WATCH_ID_TBL.clear } + } + + def self.names(state = None) + lst = tk_split_list(tk_call('::blt::watch', 'names', state)) + WATCH_ID_TBL.mutex.synchronize{ + lst.collect{|name| + WATCH_ID_TBL[name] || name + } + } + end + + def __numval_optkeys + ['maxlevel'] + end + private :__numval_optkeys + + def __boolval_optkeys + ['active'] + end + private :__boolval_optkeys + + def __config_cmd + ['::blt::watch', 'configure', self.path] + end + private :__config_cmd + + def initialize(name = nil, keys = {}) + if name.kind_of?(Hash) + keys = name + name = nil + end + + if name + @id = name.to_s + else + BLT_WATCH_ID.mutex.synchronize{ + @id = BLT_WATCH_ID.join(TkCore::INTERP._ip_id_) + BLT_WATCH_ID[1].succ! + } + end + + @path = @id + + WATCH_ID_TBL.mutex.synchronize{ + WATCH_ID_TBL[@id] = self + } + tk_call('::blt::watch', 'create', @id, *hash_kv(keys)) + end + + def activate + tk_call('::blt::watch', 'activate', @id) + self + end + def deactivate + tk_call('::blt::watch', 'deactivate', @id) + self + end + def delete + tk_call('::blt::watch', 'delete', @id) + self + end + def info + ret = [] + lst = tk_split_simplelist(tk_call('::blt::watch', 'info', @id)) + until lst.empty? + k, v, *lst = lst + k = k[1..-1] + case k + when /^(#{__strval_optkeys.join('|')})$/ + # do nothing + + when /^(#{__numval_optkeys.join('|')})$/ + begin + v = number(v) + rescue + v = nil + end + + when /^(#{__numstrval_optkeys.join('|')})$/ + v = num_or_str(v) + + when /^(#{__boolval_optkeys.join('|')})$/ + begin + v = bool(v) + rescue + v = nil + end + + when /^(#{__listval_optkeys.join('|')})$/ + v = simplelist(v) + + when /^(#{__numlistval_optkeys.join('|')})$/ + v = list(v) + + else + if v.index('{') + v = tk_split_list(v) + else + v = tk_tcl2ruby(v) + end + end + + ret << [k, v] + end + + ret + end + def configinfo(slot = nil) + if slot + slot = slot.to_s + v = cget(slot) + if TkComm::GET_CONFIGINFO_AS_ARRAY + [slot, v] + else + {slot=>v} + end + else + if TkComm::GET_CONFIGINFO_AS_ARRAY + info + else + Hash[*(info.flatten)] + end + end + end + def cget_strict(key) + key = key.to_s + begin + info.assoc(key)[1] + rescue + fail ArgumentError, "unknown option '#{key}'" + end + end + def cget(key) + unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + cget_strict(key) + else + begin + cget_strict(key) + rescue => e + if current_configinfo.has_key?(key.to_s) + # error on known option + fail e + else + # unknown option + nil + end + end + end + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/win_printer.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/win_printer.rb new file mode 100644 index 0000000..7ac6a0d --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/win_printer.rb @@ -0,0 +1,61 @@ +# +# tkextlib/blt/win_printer.rb +# +# *** Windows only *** +# +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/blt.rb' + +module Tk::BLT + class Printer < TkObject + extend TkCore + + TkCommandNames = ['::blt::printer'.freeze].freeze + + def self.enum(attribute) + simplelist(tk_call('::blt::printer', 'enum', attribute)) + end + + def self.names(pat=None) + simplelist(tk_call('::blt::printer', 'names', pat)) + end + + def self.open(printer) + self.new(printer) + end + + ################################# + + def initialize(printer) + @printer_id = tk_call('::blt::printer', 'open', printer) + end + + def close + tk_call('::blt::print', 'close', @printer_id) + self + end + def get_attrs(var) + tk_call('::blt::print', 'getattrs', @printer_id, var) + var + end + def set_attrs(var) + tk_call('::blt::print', 'setattrs', @printer_id, var) + self + end + def snap(win) + tk_call('::blt::print', 'snap', @printer_id, win) + self + end + def write(str) + tk_call('::blt::print', 'write', @printer_id, str) + self + end + def write_with_title(title, str) + tk_call('::blt::print', 'write', @printer_id, title, str) + self + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/blt/winop.rb b/jni/ruby/ext/tk/lib/tkextlib/blt/winop.rb new file mode 100644 index 0000000..03bdb60 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/blt/winop.rb @@ -0,0 +1,107 @@ +# +# tkextlib/blt/winop.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/blt.rb' + +module Tk::BLT + module Winop + extend TkCore + + TkCommandNames = ['::blt::winop'.freeze].freeze + end + WinOp = Winop +end + +class << Tk::BLT::Winop + def changes(win) + tk_call('::blt::winop', 'changes', win) + end + + def colormap(win) + Hash[*list(tk_call('::blt::winop', 'colormap', win))] + end + + def convolve(src, dest, filter) + tk_call('::blt::winop', 'convolve', src, dest, filter) + end + + def image_convolve(src, dest, filter) + tk_call('::blt::winop', 'image', 'convolve', src, dest, filter) + end + def image_gradient(photo, left, right, type) + tk_call('::blt::winop', 'image', 'gradient', photo, left, right, type) + end + def image_read_jpeg(file, photo) + tk_call('::blt::winop', 'image', 'readjpeg', file, photo) + end + def image_resample(src, dest, horiz_filter=None, vert_filter=None) + tk_call('::blt::winop', 'image', 'resample', + src, dest, horiz_filter, vert_filter) + end + def image_rotate(src, dest, angle) + tk_call('::blt::winop', 'image', 'rotate', src, dest, angle) + end + def image_snap(win, photo, width=None, height=None) + tk_call('::blt::winop', 'image', 'snap', win, photo, width, height) + end + def image_subsample(src, dest, x, y, width, height, + horiz_filter=None, vert_filter=None) + tk_call('::blt::winop', 'image', 'subsample', + src, dest, x, y, width, height, horiz_filter, vert_filter) + end + + def quantize(src, dest, colors) + tk_call('::blt::winop', 'quantize', src, dest, colors) + end + + def query() + tk_call('::blt::winop', 'query') + end + + def read_jpeg(file, photo) + tk_call('::blt::winop', 'readjpeg', file, photo) + end + + def resample(src, dest, horiz_filter=None, vert_filter=None) + tk_call('::blt::winop', 'resample', + src, dest, horiz_filter, vert_filter) + end + + def subsample(src, dest, x, y, width, height, + horiz_filter=None, vert_filter=None) + tk_call('::blt::winop', 'subsample', + src, dest, x, y, width, height, horiz_filter, vert_filter) + end + + def raise(*wins) + tk_call('::blt::winop', 'raise', *wins) + end + + def lower(*wins) + tk_call('::blt::winop', 'lower', *wins) + end + + def map(*wins) + tk_call('::blt::winop', 'map', *wins) + end + + def unmap(*wins) + tk_call('::blt::winop', 'unmap', *wins) + end + + def move(win, x, y) + tk_call('::blt::winop', 'move', win, x, y) + end + + def snap(win, photo) + tk_call('::blt::winop', 'snap', win, photo) + end + + def warpto(win = None) + tk_call('::blt::winop', 'warpto', win) + end + alias warp_to warpto +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget.rb new file mode 100644 index 0000000..7a1eff5 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget.rb @@ -0,0 +1,153 @@ +# +# BWidget extension support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/bwidget/setup.rb' + +# load all image format handlers +#TkPackage.require('BWidget', '1.7') +TkPackage.require('BWidget') + +module Tk + module BWidget + TkComm::TkExtlibAutoloadModule.unshift(self) + # Require autoload-symbols which is a same name as widget classname. + # Those are used at TkComm._genobj_for_tkwidget method. + + extend TkCore + + LIBRARY = tk_call('set', '::BWIDGET::LIBRARY') + + PACKAGE_NAME = 'BWidget'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('BWidget') + rescue + '' + end + end + + def self.XLFDfont(cmd, *args) + if args[-1].kind_of?(Hash) + keys = args.pop + args.concat(hash_kv(keys)) + end + tk_call('BWidget::XLFDfont', cmd, *args) + end + + def self.assert(exp, msg=None) + tk_call('BWidget::assert', exp, msg) + end + + def self.badOptionString(type, value, list) + tk_call('BWidget::badOptionString', type, value, list) + end + + def self.bindMouseWheel(widget) + tk_call('BWidget::bindMouseWheel', widget) + end + + def self.classes(klass) + list(tk_call('BWidget::classes', klass)) + end + + def self.clonename(menu) + tk_call('BWidget::clonename', menu) + end + + def self.focus(opt, path) + tk_call('BWidget::focus', opt, path) + end + + def self.get3dcolor(path, bgcolor) + tk_call('BWidget::get3dcolor', path, bgcolor) + end + + def self.getname(name) + tk_call('BWidget::getname', name) + end + + def self.grab(opt, path) + tk_call('BWidget::grab', opt, path) + end + + def self.inuse(klass) + bool(tk_call('BWidget::inuse', klass)) + end + + def self.library(klass, *klasses) + tk_call('BWidget::library', klass, *klasses) + end + + def self.lreorder(list, neworder) + tk_call('BWidget::lreorder', list, neworder) + end + + def self.parsetext(text) + tk_call('BWidget::parsetext', text) + end + + def self.place(path, w, h, *args) + if args[-1].kind_of?(Hash) + keys = args.pop + args.concat(hash_kv(keys)) + end + tk_call('BWidget::place', path, w, h, *(args.flatten)) + end + + def self.write(file, mode=None) + tk_call('BWidget::write', file, mode) + end + + def self.wrongNumArgsString(str) + tk_call('BWidget::wrongNumArgsString', str) + end + + #################################################### + + autoload :ArrowButton, 'tkextlib/bwidget/arrowbutton' + autoload :Bitmap, 'tkextlib/bwidget/bitmap' + autoload :Button, 'tkextlib/bwidget/button' + autoload :ButtonBox, 'tkextlib/bwidget/buttonbox' + autoload :ComboBox, 'tkextlib/bwidget/combobox' + autoload :Dialog, 'tkextlib/bwidget/dialog' + autoload :DragSite, 'tkextlib/bwidget/dragsite' + autoload :DropSite, 'tkextlib/bwidget/dropsite' + autoload :DynamicHelp, 'tkextlib/bwidget/dynamichelp' + autoload :Entry, 'tkextlib/bwidget/entry' + autoload :Label, 'tkextlib/bwidget/label' + autoload :LabelEntry, 'tkextlib/bwidget/labelentry' + autoload :LabelFrame, 'tkextlib/bwidget/labelframe' + autoload :ListBox, 'tkextlib/bwidget/listbox' + autoload :MainFrame, 'tkextlib/bwidget/mainframe' + autoload :MessageDlg, 'tkextlib/bwidget/messagedlg' + autoload :NoteBook, 'tkextlib/bwidget/notebook' + autoload :PagesManager, 'tkextlib/bwidget/pagesmanager' + autoload :PanedWindow, 'tkextlib/bwidget/panedwindow' + autoload :PasswdDlg, 'tkextlib/bwidget/passwddlg' + autoload :ProgressBar, 'tkextlib/bwidget/progressbar' + autoload :ProgressDlg, 'tkextlib/bwidget/progressdlg' + autoload :ScrollableFrame, 'tkextlib/bwidget/scrollableframe' + autoload :ScrolledWindow, 'tkextlib/bwidget/scrolledwindow' + autoload :ScrollView, 'tkextlib/bwidget/scrollview' + autoload :SelectColor, 'tkextlib/bwidget/selectcolor' + autoload :SelectFont, 'tkextlib/bwidget/selectfont' + autoload :Separator, 'tkextlib/bwidget/separator' + autoload :SpinBox, 'tkextlib/bwidget/spinbox' + autoload :TitleFrame, 'tkextlib/bwidget/titleframe' + autoload :Tree, 'tkextlib/bwidget/tree' + autoload :Widget, 'tkextlib/bwidget/widget' + + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/arrowbutton.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/arrowbutton.rb new file mode 100644 index 0000000..13fe9e5 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/arrowbutton.rb @@ -0,0 +1,21 @@ +# +# tkextlib/bwidget/arrowbutton.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/bwidget.rb' +require 'tkextlib/bwidget/button' + +module Tk + module BWidget + class ArrowButton < Tk::BWidget::Button + end + end +end + +class Tk::BWidget::ArrowButton + TkCommandNames = ['ArrowButton'.freeze].freeze + WidgetClassName = 'ArrowButton'.freeze + WidgetClassNames[WidgetClassName] ||= self +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/bitmap.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/bitmap.rb new file mode 100644 index 0000000..6cfde20 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/bitmap.rb @@ -0,0 +1,21 @@ +# +# tkextlib/bwidget/bitmap.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' +require 'tk/image' +require 'tkextlib/bwidget.rb' + +module Tk + module BWidget + class Bitmap < TkPhotoImage + end + end +end + +class Tk::BWidget::Bitmap + def initialize(name) + @path = tk_call_without_enc('Bitmap::get', name) + Tk_IMGTBL[@path] = self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/button.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/button.rb new file mode 100644 index 0000000..e139fb6 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/button.rb @@ -0,0 +1,31 @@ +# +# tkextlib/bwidget/button.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/button' +require 'tkextlib/bwidget.rb' + +module Tk + module BWidget + class Button < Tk::Button + end + end +end + +class Tk::BWidget::Button + TkCommandNames = ['Button'.freeze].freeze + WidgetClassName = 'Button'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() << 'helptext' + end + private :__strval_optkeys + + def __tkvariable_optkeys + super() << 'helpvar' + end + private :__tkvariable_optkeys +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/buttonbox.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/buttonbox.rb new file mode 100644 index 0000000..a6de33c --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/buttonbox.rb @@ -0,0 +1,90 @@ +# +# tkextlib/bwidget/buttonbox.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/bwidget.rb' +require 'tkextlib/bwidget/button' + +module Tk + module BWidget + class ButtonBox < TkWindow + end + end +end + +class Tk::BWidget::ButtonBox + TkCommandNames = ['ButtonBox'.freeze].freeze + WidgetClassName = 'ButtonBox'.freeze + WidgetClassNames[WidgetClassName] ||= self + + include TkItemConfigMethod + + def __boolval_optkeys + super() << 'homogeneous' + end + private :__boolval_optkeys + + def tagid(tagOrId) + if tagOrId.kind_of?(Tk::BWidget::Button) + name = tagOrId[:name] + return index(name) unless name.empty? + end + if tagOrId.kind_of?(Tk::Button) + return index(tagOrId[:text]) + end + # index(tagOrId.to_s) + index(_get_eval_string(tagOrId)) + end + + def add(keys={}, &b) + win = window(tk_send('add', *hash_kv(keys))) + if b + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + win.instance_exec(self, &b) + else + win.instance_eval(&b) + end + end + win + end + + def delete(idx) + tk_send('delete', tagid(idx)) + self + end + + def index(idx) + if idx.kind_of?(Tk::BWidget::Button) + name = idx[:name] + idx = name unless name.empty? + end + if idx.kind_of?(Tk::Button) + idx = idx[:text] + end + number(tk_send('index', idx.to_s)) + end + + def insert(idx, keys={}, &b) + win = window(tk_send('insert', tagid(idx), *hash_kv(keys))) + if b + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + win.instance_exec(self, &b) + else + win.instance_eval(&b) + end + end + win + end + + def invoke(idx) + tk_send('invoke', tagid(idx)) + self + end + + def set_focus(idx) + tk_send('setfocus', tagid(idx)) + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/combobox.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/combobox.rb new file mode 100644 index 0000000..16143df --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/combobox.rb @@ -0,0 +1,62 @@ +# +# tkextlib/bwidget/combobox.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/entry' +require 'tkextlib/bwidget.rb' +require 'tkextlib/bwidget/listbox' +require 'tkextlib/bwidget/spinbox' + +module Tk + module BWidget + class ComboBox < Tk::BWidget::SpinBox + end + end +end + +class Tk::BWidget::ComboBox + include Scrollable + + TkCommandNames = ['ComboBox'.freeze].freeze + WidgetClassName = 'ComboBox'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __boolval_optkeys + super() << 'autocomplete' << 'autopost' + end + private :__boolval_optkeys + + def get_listbox(&b) + win = window(tk_send_without_enc('getlistbox')) + if b + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + win.instance_exec(self, &b) + else + win.instance_eval(&b) + end + end + win + end + + def clear_value + tk_send_without_enc('clearvalue') + self + end + alias clearvalue clear_value + + def icursor(idx) + tk_send_without_enc('icursor', idx) + end + + def post + tk_send_without_enc('post') + self + end + + def unpost + tk_send_without_enc('unpost') + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/dialog.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/dialog.rb new file mode 100644 index 0000000..3b0656f --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/dialog.rb @@ -0,0 +1,194 @@ +# +# tkextlib/bwidget/dialog.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/frame' +require 'tkextlib/bwidget.rb' +require 'tkextlib/bwidget/buttonbox' + +module Tk + module BWidget + class Dialog < TkWindow + end + end +end + +class Tk::BWidget::Dialog + TkCommandNames = ['Dialog'.freeze].freeze + WidgetClassName = 'Dialog'.freeze + WidgetClassNames[WidgetClassName] ||= self + + include TkItemConfigMethod + + def __numstrval_optkeys + super() << 'buttonwidth' + end + private :__numstrval_optkeys + + def __strval_optkeys + super() << 'title' << 'geometry' + end + private :__strval_optkeys + + def __boolval_optkeys + super() << 'transient' << 'homogeneous' + end + private :__boolval_optkeys + + def initialize(parent=nil, keys=nil) + @relative = '' + if parent.kind_of?(Hash) + keys = _symbolkey2str(parent) + @relative = keys['parent'] if keys.key?('parent') + @relative = keys.delete('relative') if keys.key?('relative') + super(keys) + elsif keys + keys = _symbolkey2str(keys) + @relative = keys.delete('parent') if keys.key?('parent') + @relative = keys.delete('relative') if keys.key?('relative') + super(parent, keys) + else + super(parent) + end + end + + def create_self(keys) + cmd = self.class::TkCommandNames[0] + if keys and keys != None + tk_call_without_enc(cmd, @path, '-parent', @relative, + *hash_kv(keys, true)) + else + tk_call_without_enc(cmd, @path, '-parent', @relative) + end + end + + def cget_tkstring(slot) + if slot.to_s == 'relative' + super('parent') + else + super(slot) + end + end + def cget_strict(slot) + if slot.to_s == 'relative' + super('parent') + else + super(slot) + end + end + def cget(slot) + if slot.to_s == 'relative' + super('parent') + else + super(slot) + end + end + + def configure(slot, value=None) + if slot.kind_of?(Hash) + slot = _symbolkey2str(slot) + slot['parent'] = slot.delete('relative') if slot.key?('relative') + super(slot) + else + if slot.to_s == 'relative' + super('parent', value) + else + super(slot, value) + end + end + end + + def configinfo(slot=nil) + if slot + if slot.to_s == 'relative' + super('parent') + else + super(slot) + end + else + ret = super() + if TkComm::GET_CONFIGINFO_AS_ARRAY + ret << ['relative', 'parent'] + else + ret['relative'] = 'parent' + end + end + end + + def tagid(tagOrId) + if tagOrId.kind_of?(Tk::BWidget::Button) + name = tagOrId[:name] + return index(name) unless name.empty? + end + if tagOrId.kind_of?(Tk::Button) + return index(tagOrId[:text]) + end + # index(tagOrId.to_s) + index(_get_eval_string(tagOrId)) + end + + def add(keys={}, &b) + win = window(tk_send('add', *hash_kv(keys))) + if b + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + win.instance_exec(self, &b) + else + win.instance_eval(&b) + end + end + win + end + + def get_frame(&b) + win = window(tk_send('getframe')) + if b + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + win.instance_exec(self, &b) + else + win.instance_eval(&b) + end + end + win + end + + def get_buttonbox(&b) + win = window(@path + '.bbox') + if b + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + win.instance_exec(self, &b) + else + win.instance_eval(&b) + end + end + win + end + + def draw(focus_win=None) + tk_send('draw', focus_win) + end + + def enddialog(ret) + tk_send('enddialog', ret) + end + + def index(idx) + get_buttonbox.index(idx) + end + + def invoke(idx) + tk_send('invoke', tagid(idx)) + self + end + + def set_focus(idx) + tk_send('setfocus', tagid(idx)) + self + end + + def withdraw + tk_send('withdraw') + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/dragsite.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/dragsite.rb new file mode 100644 index 0000000..4d4de17 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/dragsite.rb @@ -0,0 +1,31 @@ +# +# tkextlib/bwidget/dragsite.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/bwidget.rb' + +module Tk + module BWidget + module DragSite + end + end +end + +module Tk::BWidget::DragSite + include Tk + extend Tk + + def self.include(klass, type, event) + tk_call('DragSite::include', klass, type, event) + end + + def self.register(path, keys={}) + tk_call('DragSite::register', path, *hash_kv(keys)) + end + + def self.set_drag(path, subpath, initcmd, endcmd, force=None) + tk_call('DragSite::setdrag', path, subpath, initcmd, endcmd, force) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/dropsite.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/dropsite.rb new file mode 100644 index 0000000..e5e98fb --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/dropsite.rb @@ -0,0 +1,39 @@ +# +# tkextlib/bwidget/dropsite.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/bwidget.rb' + +module Tk + module BWidget + module DropSite + end + end +end + +module Tk::BWidget::DropSite + include Tk + extend Tk + + def self.include(klass, type) + tk_call('DropSite::include', klass, type) + end + + def self.register(path, keys={}) + tk_call('DropSite::register', path, *hash_kv(keys)) + end + + def self.set_cursor(cursor) + tk_call('DropSite::setcursor', cursor) + end + + def self.set_drop(path, subpath, dropover, drop, force=None) + tk_call('DropSite::setdrop', path, subpath, dropover, drop, force) + end + + def self.set_operation(op) + tk_call('DropSite::setoperation', op) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/dynamichelp.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/dynamichelp.rb new file mode 100644 index 0000000..846e580 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/dynamichelp.rb @@ -0,0 +1,63 @@ +# +# tkextlib/bwidget/dynamichelp.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/bwidget.rb' + +module Tk + module BWidget + module DynamicHelp + end + end +end + +module Tk::BWidget::DynamicHelp + include Tk + extend Tk + + def self.__pathname + 'DynamicHelp::configure' + end + + def __strval_optkeys + super() << 'topbackground' + end + private :__strval_optkeys + + def self.__cget_cmd + ['DynamicHelp::configure'] + end + + def self.__config_cmd + ['DynamicHelp::configure'] + end + + def self.cget_strict(slot) + slot = slot.to_s + info = {} + self.current_configinfo.each{|k,v| info[k.to_s] = v if k.to_s == slot} + fail RuntimeError, "unknown option \"-#{slot}\"" if info.empty? + info.values[0] + end + def self.cget(slot) + self.current_configinfo(slot).values[0] + end + + def self.add(widget, keys={}) + tk_call('DynamicHelp::add', widget, *hash_kv(keys)) + end + + def self.delete(widget) + tk_call('DynamicHelp::delete', widget) + end + + def self.include(klass, type) + tk_call('DynamicHelp::include', klass, type) + end + + def self.sethelp(path, subpath, force=None) + tk_call('DynamicHelp::sethelp', path, subpath, force) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/entry.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/entry.rb new file mode 100644 index 0000000..8dc4496 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/entry.rb @@ -0,0 +1,43 @@ +# +# tkextlib/bwidget/entry.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/entry' +require 'tkextlib/bwidget.rb' + +module Tk + module BWidget + class Entry < Tk::Entry + end + end +end + +class Tk::BWidget::Entry + include Scrollable + + TkCommandNames = ['Entry'.freeze].freeze + WidgetClassName = 'Entry'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() << 'helptext' << 'insertbackground' + end + private :__strval_optkeys + + def __boolval_optkeys + super() << 'dragenabled' << 'dropenabled' << 'editable' + end + private :__boolval_optkeys + + def __tkvariable_optkeys + super() << 'helpvar' + end + private :__tkvariable_optkeys + + def invoke + tk_send_without_enc('invoke') + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/label.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/label.rb new file mode 100644 index 0000000..e8d9352 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/label.rb @@ -0,0 +1,41 @@ +# +# tkextlib/bwidget/label.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/label' +require 'tkextlib/bwidget.rb' + +module Tk + module BWidget + class Label < Tk::Label + end + end +end + +class Tk::BWidget::Label + TkCommandNames = ['Label'.freeze].freeze + WidgetClassName = 'Label'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() << 'helptext' + end + private :__strval_optkeys + + def __boolval_optkeys + super() << 'dragenabled' << 'dropenabled' + end + private :__boolval_optkeys + + def __tkvariable_optkeys + super() << 'helpvar' + end + private :__tkvariable_optkeys + + def set_focus + tk_send_without_enc('setfocus') + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/labelentry.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/labelentry.rb new file mode 100644 index 0000000..16e7b46 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/labelentry.rb @@ -0,0 +1,80 @@ +# +# tkextlib/bwidget/labelentry.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/entry' +require 'tkextlib/bwidget.rb' +require 'tkextlib/bwidget/labelframe' +require 'tkextlib/bwidget/entry' + +module Tk + module BWidget + class LabelEntry < Tk::Entry + end + end +end + +class Tk::BWidget::LabelEntry + include Scrollable + + TkCommandNames = ['LabelEntry'.freeze].freeze + WidgetClassName = 'LabelEntry'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() << 'helptext' << 'insertbackground' << 'entryfg' << 'entrybg' + end + private :__strval_optkeys + + def __tkvariable_optkeys + super() << 'helpvar' + end + private :__tkvariable_optkeys + + def __font_optkeys + super() << 'labelfont' + end + private :__font_optkeys + + #def entrybind(*args) + # _bind([path, 'bind'], *args) + # self + #end + def entrybind(context, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind([path, 'bind'], context, cmd, *args) + self + end + + #def entrybind_append(*args) + # _bind_append([path, 'bind'], *args) + # self + #end + def entrybind_append(context, *args) + #if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append([path, 'bind'], context, cmd, *args) + self + end + + def entrybind_remove(*args) + _bind_remove([path, 'bind'], *args) + self + end + + def entrybindinfo(*args) + _bindinfo([path, 'bind'], *args) + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/labelframe.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/labelframe.rb new file mode 100644 index 0000000..0710f21 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/labelframe.rb @@ -0,0 +1,52 @@ +# +# tkextlib/bwidget/labelframe.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/frame' +require 'tkextlib/bwidget.rb' +require 'tkextlib/bwidget/label' + +module Tk + module BWidget + class LabelFrame < TkWindow + end + end +end + +class Tk::BWidget::LabelFrame + TkCommandNames = ['LabelFrame'.freeze].freeze + WidgetClassName = 'LabelFrame'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() << 'helptext' + end + private :__strval_optkeys + + def __boolval_optkeys + super() << 'dragenabled' << 'dropenabled' + end + private :__boolval_optkeys + + def __tkvariable_optkeys + super() << 'helpvar' + end + private :__tkvariable_optkeys + + def self.align(*args) + tk_call('LabelFrame::align', *args) + end + def get_frame(&b) + win = window(tk_send_without_enc('getframe')) + if b + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + win.instance_exec(self, &b) + else + win.instance_eval(&b) + end + end + win + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/listbox.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/listbox.rb new file mode 100644 index 0000000..930491c --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/listbox.rb @@ -0,0 +1,361 @@ +# +# tkextlib/bwidget/listbox.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/canvas' +require 'tkextlib/bwidget.rb' + +module Tk + module BWidget + class ListBox < TkWindow + # is NOT a subclass of a listbox widget class. + # because it constructed on a canvas widget. + + class Item < TkObject + end + end + end +end + +class Tk::BWidget::ListBox + include TkItemConfigMethod + include Scrollable + + TkCommandNames = ['ListBox'.freeze].freeze + WidgetClassName = 'ListBox'.freeze + WidgetClassNames[WidgetClassName] ||= self + + class Event_for_Items < TkEvent::Event + def self._get_extra_args_tbl + [ + TkComm.method(:string) # item idenfier + ] + end + end + + def __boolval_optkeys + super() << 'autofocus' << 'dragenabled' << 'dropenabled' << 'selectfill' + end + private :__boolval_optkeys + + def tagid(tag) + if tag.kind_of?(Tk::BWidget::ListBox::Item) + tag.id + else + # tag + _get_eval_string(tag) + end + end + + #def imagebind(*args) + # _bind_for_event_class(Event_for_Items, [path, 'bindImage'], *args) + # self + #end + def imagebind(context, *args) + #if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_for_event_class(Event_for_Items, [path, 'bindImage'], + context, cmd, *args) + self + end + + #def imagebind_append(*args) + # _bind_append_for_event_class(Event_for_Items, [path, 'bindImage'], *args) + # self + #end + def imagebind_append(context, *args) + #if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append_for_event_class(Event_for_Items, [path, 'bindImage'], + context, cmd, *args) + self + end + + def imagebind_remove(*args) + _bind_remove_for_event_class(Event_for_Items, [path, 'bindImage'], *args) + self + end + + def imagebindinfo(*args) + _bindinfo_for_event_class(Event_for_Items, [path, 'bindImage'], *args) + end + + #def textbind(*args) + # _bind_for_event_class(Event_for_Items, [path, 'bindText'], *args) + # self + #end + def textbind(context, *args) + #if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_for_event_class(Event_for_Items, [path, 'bindText'], + context, cmd, *args) + self + end + + #def textbind_append(*args) + # _bind_append_for_event_class(Event_for_Items, [path, 'bindText'], *args) + # self + #end + def textbind_append(context, *args) + #if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append_for_event_class(Event_for_Items, [path, 'bindText'], + context, cmd, *args) + self + end + + def textbind_remove(*args) + _bind_remove_for_event_class(Event_for_Items, [path, 'bindText'], *args) + self + end + + def textbindinfo(*args) + _bindinfo_for_event_class(Event_for_Items, [path, 'bindText'], *args) + end + + def delete(*args) + tk_send('delete', *args) + self + end + + def edit(item, text, *args) + tk_send('edit', tagid(item), text, *args) + self + end + + def exist?(item) + bool(tk_send('exists', tagid(item))) + end + + def index(item) + num_or_str(tk_send('index', tagid(item))) + end + + def insert(idx, item, keys={}) + tk_send('insert', idx, tagid(item), *hash_kv(keys)) + self + end + + def get_item(idx) + tk_send('items', idx) + end + + def items(first=None, last=None) + list(tk_send('items', first, last)) + end + + def move(item, idx) + tk_send('move', tagid(item), idx) + self + end + + def reorder(neworder) + tk_send('reorder', neworder) + self + end + + def see(item) + tk_send('see', tagid(item)) + self + end + + def selection_clear + tk_send_without_enc('selection', 'clear') + self + end + + def selection_set(*args) + tk_send_without_enc('selection', 'set', + *(args.collect{|item| tagid(item)})) + self + end + + def selection_add(*args) + tk_send_without_enc('selection', 'add', + *(args.collect{|item| tagid(item)})) + self + end + + def selection_remove(*args) + tk_send_without_enc('selection', 'remove', + *(args.collect{|item| tagid(item)})) + self + end + + def selection_get(*args) + simplelist(tk_send_without_enc('selection', 'get')).collect{|item| + Tk::BWidget::ListBox::Item.id2obj(self, item) + } + end +end + +class Tk::BWidget::ListBox::Item + include TkTreatTagFont + + ListItem_TBL = TkCore::INTERP.create_table + + (ListItem_ID = ['bw:item'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + TkCore::INTERP.init_ip_env{ + ListItem_TBL.mutex.synchronize{ ListItem_TBL.clear } + } + + def self.id2obj(lbox, id) + lpath = lbox.path + ListItem_TBL.mutex.synchronize{ + if ListItem_TBL[lpath] + ListItem_TBL[lpath][id]? ListItem_TBL[lpath][id]: id + else + id + end + } + end + + def initialize(lbox, *args) + if lbox.kind_of?(Tk::BWidget::ListBox) + @listbox = lbox + else + fail RuntimeError, + "expect Tk::BWidget::ListBox or Tk::BWidget::ListBox::Item for 1st argument" + end + + if args[-1].kind_of?(Hash) + keys = _symbolkey2str(args.pop) + else + keys = {} + end + + index = keys.delete('index') + unless args.empty? + index = args.shift + end + index = 'end' unless index + + unless args.empty? + fail RuntimeError, 'too much arguments' + end + + @lpath = @listbox.path + + if keys.key?('itemname') + @path = @id = keys.delete('itemname') + else + ListItem_ID.mutex.synchronize{ + @path = @id = ListItem_ID.join(TkCore::INTERP._ip_id_) + ListItem_ID[1].succ! + } + end + + ListItem_TBL.mutex.synchronize{ + ListItem_TBL[@id] = self + ListItem_TBL[@lpath] = {} unless ListItem_TBL[@lpath] + ListItem_TBL[@lpath][@id] = self + } + + @listbox.insert(index, @id, keys) + end + + def listbox + @listbox + end + + def id + @id + end + + def [](key) + cget(key) + end + + def []=(key, val) + configure(key, val) + val + end + + def cget_tkstring(key) + @listbox.itemcget_tkstring(@id, key) + end + def cget(key) + @listbox.itemcget(@id, key) + end + def cget_strict(key) + @listbox.itemcget_strict(@id, key) + end + + def configure(key, val=None) + @listbox.itemconfigure(@id, key, val) + end + + def configinfo(key=nil) + @listbox.itemconfiginfo(@id, key) + end + + def current_configinfo(key=nil) + @listbox.current_itemconfiginfo(@id, key) + end + + def delete + @listbox.delete(@id) + self + end + + def edit(*args) + @listbox.edit(@id, *args) + self + end + + def exist? + @listbox.exist?(@id) + end + + def index + @listbox.index(@id) + end + + def move(index) + @listbox.move(@id, index) + end + + def see + @listbox.see(@id) + end + + def selection_add + @listbox.selection_add(@id) + end + + def selection_remove + @listbox.selection_remove(@id) + end + + def selection_set + @listbox.selection_set(@id) + end + + def selection_toggle + @listbox.selection_toggle(@id) + end +end + diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/mainframe.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/mainframe.rb new file mode 100644 index 0000000..92253bd --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/mainframe.rb @@ -0,0 +1,132 @@ +# +# tkextlib/bwidget/mainframe.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/frame' +require 'tkextlib/bwidget.rb' +require 'tkextlib/bwidget/progressbar' + +module Tk + module BWidget + class MainFrame < TkWindow + end + end +end + +class Tk::BWidget::MainFrame + TkCommandNames = ['MainFrame'.freeze].freeze + WidgetClassName = 'MainFrame'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() << 'progressfg' + end + private :__strval_optkeys + + def __tkvariable_optkeys + super() << 'progressvar' + end + private :__tkvariable_optkeys + + def __val2ruby_optkeys # { key=>proc, ... } + # The method is used to convert a opt-value to a ruby's object. + # When get the value of the option "key", "proc.call(value)" is called. + { + 'menu'=>proc{|v| simplelist(v).collect!{|elem| simplelist(v)}} + } + end + private :__val2ruby_optkeys + + def add_indicator(keys={}, &b) + win = window(tk_send('addindicator', *hash_kv(keys))) + if b + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + win.instance_exec(self, &b) + else + win.instance_eval(&b) + end + end + win + end + + def add_toolbar(&b) + win = window(tk_send('addtoolbar')) + if b + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + win.instance_exec(self, &b) + else + win.instance_eval(&b) + end + end + win + end + + def get_frame(&b) + win = window(tk_send('getframe')) + if b + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + win.instance_exec(self, &b) + else + win.instance_eval(&b) + end + end + win + end + + def get_indicator(idx, &b) + win = window(tk_send('getindicator', idx)) + if b + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + win.instance_exec(self, &b) + else + win.instance_eval(&b) + end + end + win + end + + def get_menu(menu_id, &b) + win = window(tk_send('getmenu', menu_id)) + if b + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + win.instance_exec(self, &b) + else + win.instance_eval(&b) + end + end + win + end + + def get_toolbar(idx, &b) + win = window(tk_send('gettoolbar', idx)) + if b + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + win.instance_exec(self, &b) + else + win.instance_eval(&b) + end + end + win + end + + def get_menustate(tag) + tk_send('getmenustate', tag) # return state name string + end + + def set_menustate(tag, state) + tk_send('setmenustate', tag, state) + self + end + + def show_statusbar(name) + tk_send('showstatusbar', name) + self + end + + def show_toolbar(idx, mode) + tk_send('showtoolbar', idx, mode) + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/messagedlg.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/messagedlg.rb new file mode 100644 index 0000000..7b62614 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/messagedlg.rb @@ -0,0 +1,192 @@ +# +# tkextlib/bwidget/messagedlg.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/bwidget.rb' +require 'tkextlib/bwidget/dialog.rb' + +module Tk + module BWidget + class MessageDlg < TkWindow + end + end +end + +class Tk::BWidget::MessageDlg + TkCommandNames = ['MessageDlg'.freeze].freeze + WidgetClassName = 'MessageDlg'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def initialize(parent=nil, keys=nil) + @relative = '' + if parent.kind_of?(Hash) + keys = _symbolkey2str(parent) + @relative = keys['parent'] if keys.key?('parent') + @relative = keys.delete('relative') if keys.key?('relative') + super(keys) + elsif keys + keys = _symbolkey2str(keys) + @relative = keys.delete('parent') if keys.key?('parent') + @relative = keys.delete('relative') if keys.key?('relative') + super(parent, keys) + else + super(parent) + end + end + + def create_self(keys) + # NOT create widget. + # Because the widget no longer exist when returning from creation. + @keys = _symbolkey2str(keys).update('parent'=>@relative) + @info = nil + end + private :create_self + + def __strval_optkeys + super() << 'message' << 'title' + end + private :__strval_optkeys + + def __listval_optkeys + super() << 'buttons' + end + private :__listval_optkeys + + def cget(slot) + slot = slot.to_s + if slot == 'relative' + slot = 'parent' + end + if winfo_exist? + val = super(slot) + @keys[slot] = val + end + @keys[slot] + end + def cget_strict(slot) + slot = slot.to_s + if slot == 'relative' + slot = 'parent' + end + if winfo_exist? + val = super(slot) + @keys[slot] = val + end + @keys[slot] + end + + def configure(slot, value=None) + if winfo_exist? + super(slot, value) + end + if slot.kind_of?(Hash) + slot = _symbolkey2str(slot) + slot['parent'] = slot.delete('relative') if slot.key?('relative') + @keys.update(slot) + + if @info + # update @info + slot.each{|k, v| + if TkComm::GET_CONFIGINFO_AS_ARRAY + if (inf = @info.assoc(k)) + inf[-1] = v + else + @info << [k, '', '', '', v] + end + else + if (inf = @info[k]) + inf[-1] = v + else + @info[k] = ['', '', '', v] + end + end + } + end + + else # ! Hash + slot = slot.to_s + slot = 'parent' if slot == 'relative' + @keys[slot] = value + + if @info + # update @info + if TkComm::GET_CONFIGINFO_AS_ARRAY + if (inf = @info.assoc(slot)) + inf[-1] = value + else + @info << [slot, '', '', '', value] + end + else + if (inf = @info[slot]) + inf[-1] = value + else + @info[slot] = ['', '', '', value] + end + end + end + end + + self + end + + def configinfo(slot=nil) + if winfo_exist? + @info = super() + if TkComm::GET_CONFIGINFO_AS_ARRAY + @info << ['relative', 'parent'] + else + @info['relative'] = 'parent' + end + end + + if TkComm::GET_CONFIGINFO_AS_ARRAY + if @info + if winfo_exist? + # update @keys + @info.each{|inf| @keys[inf[0]] = inf[-1] if inf.size > 2 } + end + else + @info = [] + @keys.each{|k, v| + @info << [k, '', '', '', v] + } + @info << ['relative', 'parent'] + end + + if slot + @info.asoc(slot.to_s).dup + else + @info.dup + end + + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY + if @info + if winfo_exist? + # update @keys + @info.each{|k, inf| @keys[k] = inf[-1] if inf.size > 2 } + end + else + @info = {} + @keys.each{|k, v| + @info[k] = ['', '', '', v] + } + @info['relative'] = 'parent' + end + + if slot + @info[slot.to_s].dup + else + @info.dup + end + end + end + + def create + # return the index of the pressed button, or nil if it is destroyed + ret = num_or_str(tk_call(self.class::TkCommandNames[0], + @path, *hash_kv(@keys))) + (ret < 0)? nil: ret + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/notebook.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/notebook.rb new file mode 100644 index 0000000..ed28bcd --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/notebook.rb @@ -0,0 +1,166 @@ +# +# tkextlib/bwidget/notebook.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/frame' +require 'tkextlib/bwidget.rb' + +module Tk + module BWidget + class NoteBook < TkWindow + end + end +end + +class Tk::BWidget::NoteBook + include TkItemConfigMethod + + TkCommandNames = ['NoteBook'.freeze].freeze + WidgetClassName = 'NoteBook'.freeze + WidgetClassNames[WidgetClassName] ||= self + + class Event_for_Tabs < TkEvent::Event + def self._get_extra_args_tbl + [ + TkComm.method(:string) # page idenfier + ] + end + end + + def __boolval_optkeys + super() << 'homogeneous' + end + private :__boolval_optkeys + + def tagid(id) + if id.kind_of?(TkWindow) + #id.path + id.epath + elsif id.kind_of?(TkObject) + id.to_eval + else + # id.to_s + _get_eval_string(id) + end + end + + #def tabbind(*args) + # _bind_for_event_class(Event_for_Tabs, [path, 'bindtabs'], *args) + # self + #end + def tabbind(context, *args) + #if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_for_event_class(Event_for_Tabs, [path, 'bindtabs'], + context, cmd, *args) + self + end + + #def tabbind_append(*args) + # _bind_append_for_event_class(Event_for_Tabs, [path, 'bindtabs'], *args) + # self + #end + def tabbind_append(context, *args) + #if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append_for_event_class(Event_for_Tabs, [path, 'bindtabs'], + context, cmd, *args) + self + end + + def tabbind_remove(*args) + _bind_remove_for_event_class(Event_for_Tabs, [path, 'bindtabs'], *args) + self + end + + def tabbindinfo(*args) + _bindinfo_for_event_class(Event_for_Tabs, [path, 'bindtabs'], *args) + end + + def add(page, &b) + win = window(tk_send('add', tagid(page))) + if b + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + win.instance_exec(self, &b) + else + win.instance_eval(&b) + end + end + win + end + + def compute_size + tk_send('compute_size') + self + end + + def delete(page, destroyframe=None) + tk_send('delete', tagid(page), destroyframe) + self + end + + def get_frame(page, &b) + win = window(tk_send('getframe', tagid(page))) + if b + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + win.instance_exec(self, &b) + else + win.instance_eval(&b) + end + end + win + end + + def index(page) + num_or_str(tk_send('index', tagid(page))) + end + + def insert(index, page, keys={}, &b) + win = window(tk_send('insert', index, tagid(page), *hash_kv(keys))) + if b + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + win.instance_exec(self, &b) + else + win.instance_eval(&b) + end + end + win + end + + def move(page, index) + tk_send('move', tagid(page), index) + self + end + + def get_page(page) + tk_send('pages', page) + end + + def pages(first=None, last=None) + list(tk_send('pages', first, last)) + end + + def raise(page=nil) + if page + tk_send('raise', page) + self + else + tk_send('raise') + end + end + + def see(page) + tk_send('see', page) + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/pagesmanager.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/pagesmanager.rb new file mode 100644 index 0000000..31bbf1f --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/pagesmanager.rb @@ -0,0 +1,73 @@ +# +# tkextlib/bwidget/pagesmanager.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/frame' +require 'tkextlib/bwidget.rb' + +module Tk + module BWidget + class PagesManager < TkWindow + end + end +end + +class Tk::BWidget::PagesManager + TkCommandNames = ['PagesManager'.freeze].freeze + WidgetClassName = 'PagesManager'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def tagid(id) + # id.to_s + _get_eval_string(id) + end + + def add(page, &b) + win = window(tk_send('add', tagid(page))) + if b + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + win.instance_exec(self, &b) + else + win.instance_eval(&b) + end + end + win + end + + def compute_size + tk_send('compute_size') + self + end + + def delete(page) + tk_send('delete', tagid(page)) + self + end + + def get_frame(page, &b) + win = window(tk_send('getframe', tagid(page))) + if b + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + win.instance_exec(self, &b) + else + win.instance_eval(&b) + end + end + win + end + + def get_page(page) + tk_send('pages', page) + end + + def pages(first=None, last=None) + list(tk_send('pages', first, last)) + end + + def raise(page=None) + tk_send('raise', page) + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/panedwindow.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/panedwindow.rb new file mode 100644 index 0000000..54cf06c --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/panedwindow.rb @@ -0,0 +1,42 @@ +# +# tkextlib/bwidget/panedwindow.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/frame' +require 'tkextlib/bwidget.rb' + +module Tk + module BWidget + class PanedWindow < TkWindow + end + end +end + +class Tk::BWidget::PanedWindow + TkCommandNames = ['PanedWindow'.freeze].freeze + WidgetClassName = 'PanedWindow'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() << 'activator' + end + private :__strval_optkeys + + def add(keys={}) + window(tk_send('add', *hash_kv(keys))) + end + + def get_frame(idx, &b) + win = window(tk_send_without_enc('getframe', idx)) + if b + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + win.instance_exec(self, &b) + else + win.instance_eval(&b) + end + end + win + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/panelframe.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/panelframe.rb new file mode 100644 index 0000000..1cbf914 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/panelframe.rb @@ -0,0 +1,67 @@ +# +# tkextlib/bwidget/panelframe.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/frame' +require 'tkextlib/bwidget.rb' + +module Tk + module BWidget + class PanelFrame < TkWindow + end + end +end + +class Tk::BWidget::PanelFrame + TkCommandNames = ['PanelFrame'.freeze].freeze + WidgetClassName = 'PanelFrame'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() + ['panelforeground', 'panelbackground'] + end + private :__strval_optkeys + + def add(win, keys={}) + tk_send('add', win, keys) + self + end + + def delete(*wins) + tk_send('delete', *wins) + self + end + + def get_frame(&b) + win = window(tk_send_without_enc('getframe')) + if b + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + win.instance_exec(self, &b) + else + win.instance_eval(&b) + end + end + win + end + + def items + simplelist(tk_send('items')).map{|w| window(w)} + end + + def remove(*wins) + tk_send('remove', *wins) + self + end + + def remove_with_destroy(*wins) + tk_send('remove', '-destroy', *wins) + self + end + + def delete(*wins) # same to 'remove_with_destroy' + tk_send('delete', *wins) + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/passwddlg.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/passwddlg.rb new file mode 100644 index 0000000..ea50c87 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/passwddlg.rb @@ -0,0 +1,44 @@ +# +# tkextlib/bwidget/passwddlg.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/bwidget.rb' +require 'tkextlib/bwidget/messagedlg' + +module Tk + module BWidget + class PasswdDlg < Tk::BWidget::MessageDlg + end + end +end + +class Tk::BWidget::PasswdDlg + TkCommandNames = ['PasswdDlg'.freeze].freeze + WidgetClassName = 'PasswdDlg'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() << 'loginhelptext' << 'loginlabel' << 'logintext' << + 'passwdlabel' << 'passwdtext' + end + private :__strval_optkeys + + def __boolval_optkeys + super() << 'passwdeditable' << 'homogeneous' + end + private :__boolval_optkeys + + def __tkvariable_optkeys + super() << 'loginhelpvar' << 'logintextvariable' << + 'passwdhelpvar' << 'passwdtextvariable' + end + private :__tkvariable_optkeys + + def create + login, passwd = simplelist(tk_call(self.class::TkCommandNames[0], + @path, *hash_kv(@keys))) + [login, passwd] + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/progressbar.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/progressbar.rb new file mode 100644 index 0000000..18eb673 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/progressbar.rb @@ -0,0 +1,20 @@ +# +# tkextlib/bwidget/progressbar.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/bwidget.rb' + +module Tk + module BWidget + class ProgressBar < TkWindow + end + end +end + +class Tk::BWidget::ProgressBar + TkCommandNames = ['ProgressBar'.freeze].freeze + WidgetClassName = 'ProgressBar'.freeze + WidgetClassNames[WidgetClassName] ||= self +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/progressdlg.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/progressdlg.rb new file mode 100644 index 0000000..0c0c454 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/progressdlg.rb @@ -0,0 +1,58 @@ +# +# tkextlib/bwidget/progressdlg.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/variable' +require 'tkextlib/bwidget.rb' +require 'tkextlib/bwidget/progressbar' +require 'tkextlib/bwidget/messagedlg' + +module Tk + module BWidget + class ProgressDlg < Tk::BWidget::MessageDlg + end + end +end + +class Tk::BWidget::ProgressDlg + TkCommandNames = ['ProgressDlg'.freeze].freeze + WidgetClassName = 'ProgressDlg'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def create_self(keys) + # NOT create widget for reusing the object + super(keys) + @keys['textvariable'] = TkVariable.new unless @keys.key?('textvariable') + @keys['variable'] = TkVariable.new unless @keys.key?('variable') + end + + def textvariable + @keys['textvariable'] + end + + def text + @keys['textvariable'].value + end + + def text= (txt) + @keys['textvariable'].value = txt + end + + def variable + @keys['variable'] + end + + def value + @keys['variable'].value + end + + def value= (val) + @keys['variable'].value = val + end + + def create + window(tk_call(self.class::TkCommandNames[0], @path, *hash_kv(@keys))) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/scrollableframe.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/scrollableframe.rb new file mode 100644 index 0000000..5bd00d6 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/scrollableframe.rb @@ -0,0 +1,40 @@ +# +# tkextlib/bwidget/scrollableframe.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/frame' +require 'tkextlib/bwidget.rb' + +module Tk + module BWidget + class ScrollableFrame < TkWindow + end + end +end + +class Tk::BWidget::ScrollableFrame + include Scrollable + + TkCommandNames = ['ScrollableFrame'.freeze].freeze + WidgetClassName = 'ScrollableFrame'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def get_frame(&b) + win = window(tk_send_without_enc('getframe')) + if b + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + win.instance_exec(self, &b) + else + win.instance_eval(&b) + end + end + win + end + + def see(win, vert=None, horiz=None) + tk_send_without_enc('see', win, vert, horiz) + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb new file mode 100644 index 0000000..ea5a18c --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb @@ -0,0 +1,48 @@ +# +# tkextlib/bwidget/scrolledwindow.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/frame' +require 'tkextlib/bwidget.rb' + +module Tk + module BWidget + class ScrolledWindow < TkWindow + end + end +end + +class Tk::BWidget::ScrolledWindow + TkCommandNames = ['ScrolledWindow'.freeze].freeze + WidgetClassName = 'ScrolledWindow'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() << 'sides' + end + private :__strval_optkeys + + def __boolval_optkeys + super() << 'managed' + end + private :__boolval_optkeys + + def get_frame(&b) + win = window(tk_send_without_enc('getframe')) + if b + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + win.instance_exec(self, &b) + else + win.instance_eval(&b) + end + end + win + end + + def set_widget(win) + tk_send_without_enc('setwidget', win) + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/scrollview.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/scrollview.rb new file mode 100644 index 0000000..ab27bc9 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/scrollview.rb @@ -0,0 +1,25 @@ +# +# tkextlib/bwidget/scrollview.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/bwidget.rb' + +module Tk + module BWidget + class ScrollView < TkWindow + end + end +end + +class Tk::BWidget::ScrollView + TkCommandNames = ['ScrollView'.freeze].freeze + WidgetClassName = 'ScrollView'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() << 'fill' + end + private :__strval_optkeys +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/selectcolor.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/selectcolor.rb new file mode 100644 index 0000000..456175e --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/selectcolor.rb @@ -0,0 +1,73 @@ +# +# tkextlib/bwidget/selectcolor.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/bwidget.rb' +require 'tkextlib/bwidget/messagedlg' + +module Tk + module BWidget + class SelectColor < Tk::BWidget::MessageDlg + class Dialog < Tk::BWidget::SelectColor + end + class Menubutton < Tk::Menubutton + end + MenuButton = Menubutton + end + end +end + +class Tk::BWidget::SelectColor + extend Tk + + TkCommandNames = ['SelectColor'.freeze].freeze + WidgetClassName = 'SelectColor'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def dialog(keys={}) + newkeys = @keys.dup + newkeys.update(_symbolkey2str(keys)) + tk_call('SelectColor::dialog', @path, *hash_kv(newkeys)) + end + + def menu(*args) + if args[-1].kind_of?(Hash) + keys = args.pop + else + keys = {} + end + place = args.flatten + newkeys = @keys.dup + newkeys.update(_symbolkey2str(keys)) + tk_call('SelectColor::menu', @path, place, *hash_kv(newkeys)) + end + + def self.set_color(idx, color) + tk_call('SelectColor::setcolor', idx, color) + end +end + +class Tk::BWidget::SelectColor::Dialog + def create_self(keys) + super(keys) + @keys['type'] = 'dialog' + end + + def create + @keys['type'] = 'dialog' # 'dialog' type returns color + tk_call(Tk::BWidget::SelectColor::TkCommandNames[0], + @path, *hash_kv(@keys)) + end +end + +class Tk::BWidget::SelectColor::Menubutton + def create_self(keys) + keys = {} unless keys + keys = _symbolkey2str(keys) + keys['type'] = 'menubutton' # 'toolbar' type returns widget path + window(tk_call(Tk::BWidget::SelectColor::TkCommandNames[0], + @path, *hash_kv(keys))) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/selectfont.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/selectfont.rb new file mode 100644 index 0000000..23419cb --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/selectfont.rb @@ -0,0 +1,91 @@ +# +# tkextlib/bwidget/selectfont.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/bwidget.rb' +require 'tkextlib/bwidget/messagedlg' + +module Tk + module BWidget + class SelectFont < Tk::BWidget::MessageDlg + class Dialog < Tk::BWidget::SelectFont + end + class Toolbar < TkWindow + end + end + end +end + +class Tk::BWidget::SelectFont + extend Tk + + TkCommandNames = ['SelectFont'.freeze].freeze + WidgetClassName = 'SelectFont'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() << 'sampletext' << 'title' + end + private :__strval_optkeys + + def __boolval_optkeys + super() << 'nosizes' + end + private :__boolval_optkeys + + def __font_optkeys + [] # without fontobj operation + end + private :__font_optkeys + + def create + tk_call(self.class::TkCommandNames[0], @path, *hash_kv(@keys)) + end + + def self.load_font + tk_call('SelectFont::loadfont') + end +end + +class Tk::BWidget::SelectFont::Dialog + def __font_optkeys + [] # without fontobj operation + end + + def create_self(keys) + super(keys) + @keys['type'] = 'dialog' + end + + def configure(slot, value=None) + if slot.kind_of?(Hash) + slot.delete['type'] + slot.delete[:type] + return self if slot.empty? + else + return self if slot == 'type' || slot == :type + end + super(slot, value) + end + + def create + @keys['type'] = 'dialog' # 'dialog' type returns font name + tk_call(Tk::BWidget::SelectFont::TkCommandNames[0], @path, *hash_kv(@keys)) + end +end + +class Tk::BWidget::SelectFont::Toolbar + def __font_optkeys + [] # without fontobj operation + end + + def create_self(keys) + keys = {} unless keys + keys = _symbolkey2str(keys) + keys['type'] = 'toolbar' # 'toolbar' type returns widget path + window(tk_call(Tk::BWidget::SelectFont::TkCommandNames[0], + @path, *hash_kv(keys))) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/separator.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/separator.rb new file mode 100644 index 0000000..6d92321 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/separator.rb @@ -0,0 +1,20 @@ +# +# tkextlib/bwidget/separator.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/bwidget.rb' + +module Tk + module BWidget + class Separator < TkWindow + end + end +end + +class Tk::BWidget::Separator + TkCommandNames = ['Separator'.freeze].freeze + WidgetClassName = 'Separator'.freeze + WidgetClassNames[WidgetClassName] ||= self +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/setup.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/setup.rb new file mode 100644 index 0000000..ee406c6 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/setup.rb @@ -0,0 +1,8 @@ +# +# setup.rb -- setup script before calling TkPackage.require() +# +# If you need some setup operations (for example, add a library path +# to the library search path) before using Tcl/Tk library packages +# wrapped by Ruby scripts in this directory, please write the setup +# operations in this file. +# diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/spinbox.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/spinbox.rb new file mode 100644 index 0000000..0a45b04 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/spinbox.rb @@ -0,0 +1,98 @@ +# +# tkextlib/bwidget/entry.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/bwidget.rb' +require 'tkextlib/bwidget/arrowbutton' +require 'tkextlib/bwidget/entry' + +module Tk + module BWidget + class SpinBox < Tk::Entry + end + end +end + +class Tk::BWidget::SpinBox + include Scrollable + + TkCommandNames = ['SpinBox'.freeze].freeze + WidgetClassName = 'SpinBox'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() << 'helptext' << 'insertbackground' << 'entryfg' << 'entrybg' + end + private :__strval_optkeys + + def __boolval_optkeys + super() << 'dragenabled' << 'dropenabled' << 'editable' + end + private :__boolval_optkeys + + def __listval_optkeys + super() << 'values' + end + private :__listval_optkeys + + def __tkvariable_optkeys + super() << 'helpvar' + end + private :__tkvariable_optkeys + + #def entrybind(*args) + # _bind([path, 'bind'], *args) + # self + #end + def entrybind(context, *args) + #if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind([path, 'bind'], context, cmd, *args) + self + end + + #def entrybind_append(*args) + # _bind_append([path, 'bind'], *args) + # self + #end + def entrybind_append(context, *args) + #if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append([path, 'bind'], context, cmd, *args) + self + end + + def entrybind_remove(*args) + _bind_remove([path, 'bind'], *args) + self + end + + def entrybindinfo(*args) + _bindinfo([path, 'bind'], *args) + self + end + + def get_index_of_value + number(tk_send_without_enc('getvalue')) + end + alias get_value get_index_of_value + alias get_value_index get_index_of_value + + def set_value_by_index(idx) + idx = "@#{idx}" if idx.kind_of?(Integer) + tk_send_without_enc('setvalue', idx) + self + end + alias set_value set_value_by_index + alias set_index_value set_value_by_index +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/statusbar.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/statusbar.rb new file mode 100644 index 0000000..5c5dd43 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/statusbar.rb @@ -0,0 +1,62 @@ +# +# tkextlib/bwidget/statusbar.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/frame' +require 'tkextlib/bwidget.rb' + +module Tk + module BWidget + class StatusBar < TkWindow + end + end +end + +class Tk::BWidget::StatusBar + TkCommandNames = ['StatusBar'.freeze].freeze + WidgetClassName = 'StatusBar'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __boolval_optkeys + super() << 'showresize' << 'showseparator' << 'showresizesep' + end + private :__boolval_optkeys + + def add(win, keys={}) + tk_send('add', win, keys) + self + end + + def remove(*wins) + tk_send('remove', *wins) + self + end + + def remove_with_destroy(*wins) + tk_send('remove', '-destroy', *wins) + self + end + + def delete(*wins) # same to 'remove_with_destroy' + tk_send('delete', *wins) + self + end + + def get_frame(&b) + win = window(tk_send_without_enc('getframe')) + if b + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + win.instance_exec(self, &b) + else + win.instance_eval(&b) + end + end + win + end + + def items + simplelist(tk_send('items')).map{|w| window(w)} + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/titleframe.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/titleframe.rb new file mode 100644 index 0000000..7187911 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/titleframe.rb @@ -0,0 +1,33 @@ +# +# tkextlib/bwidget/titleframe.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/frame' +require 'tkextlib/bwidget.rb' + +module Tk + module BWidget + class TitleFrame < TkWindow + end + end +end + +class Tk::BWidget::TitleFrame + TkCommandNames = ['TitleFrame'.freeze].freeze + WidgetClassName = 'TitleFrame'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def get_frame(&b) + win = window(tk_send_without_enc('getframe')) + if b + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + win.instance_exec(self, &b) + else + win.instance_eval(&b) + end + end + win + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/tree.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/tree.rb new file mode 100644 index 0000000..089c482 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/tree.rb @@ -0,0 +1,500 @@ +# +# tkextlib/bwidget/tree.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/canvas' +require 'tkextlib/bwidget.rb' + +module Tk + module BWidget + class Tree < TkWindow + class Node < TkObject + end + end + end +end + +class Tk::BWidget::Tree + include TkItemConfigMethod + include Scrollable + + TkCommandNames = ['Tree'.freeze].freeze + WidgetClassName = 'Tree'.freeze + WidgetClassNames[WidgetClassName] ||= self + + class Event_for_Items < TkEvent::Event + def self._get_extra_args_tbl + [ + TkComm.method(:string) # item idenfier + ] + end + end + + def __strval_optkeys + super() << 'crossfill' << 'linesfill' + end + private :__strval_optkeys + + def __boolval_optkeys + super() << 'dragenabled' << 'dropenabled' << + 'redraw' << 'selectfill' << 'showlines' + end + private :__boolval_optkeys + + def __tkvariable_optkeys + super() << 'helpvar' + end + private :__tkvariable_optkeys + + def tagid(tag) + if tag.kind_of?(Tk::BWidget::Tree::Node) + tag.id + else + # tag + _get_eval_string(tag) + end + end + + def areabind(context, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_for_event_class(Event_for_Items, [path, 'bindArea'], + context, cmd, *args) + self + end + + def areabind_append(context, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append_for_event_class(Event_for_Items, [path, 'bindArea'], + context, cmd, *args) + self + end + + def areabind_remove(*args) + _bind_remove_for_event_class(Event_for_Items, [path, 'bindArea'], *args) + self + end + + def areabindinfo(*args) + _bindinfo_for_event_class(Event_for_Items, [path, 'bindArea'], *args) + end + + #def imagebind(*args) + # _bind_for_event_class(Event_for_Items, [path, 'bindImage'], *args) + # self + #end + def imagebind(context, *args) + #if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_for_event_class(Event_for_Items, [path, 'bindImage'], + context, cmd, *args) + self + end + + #def imagebind_append(*args) + # _bind_append_for_event_class(Event_for_Items, [path, 'bindImage'], *args) + # self + #end + def imagebind_append(context, *args) + #if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append_for_event_class(Event_for_Items, [path, 'bindImage'], + context, cmd, *args) + self + end + + def imagebind_remove(*args) + _bind_remove_for_event_class(Event_for_Items, [path, 'bindImage'], *args) + self + end + + def imagebindinfo(*args) + _bindinfo_for_event_class(Event_for_Items, [path, 'bindImage'], *args) + end + + #def textbind(*args) + # _bind_for_event_class(Event_for_Items, [path, 'bindText'], *args) + # self + #end + def textbind(context, *args) + #if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_for_event_class(Event_for_Items, [path, 'bindText'], + context, cmd, *args) + self + end + + #def textbind_append(*args) + # _bind_append_for_event_class(Event_for_Items, [path, 'bindText'], *args) + # self + #end + def textbind_append(context, *args) + #if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append_for_event_class(Event_for_Items, [path, 'bindText'], + context, cmd, *args) + self + end + + def textbind_remove(*args) + _bind_remove_for_event_class(Event_for_Items, [path, 'bindText'], *args) + self + end + + def textbindinfo(*args) + _bindinfo_for_event_class(Event_for_Items, [path, 'bindText'], *args) + end + + def close_tree(node, recurse=None) + tk_send('closetree', tagid(node), recurse) + self + end + + def delete(*args) + tk_send('delete', *(args.collect{|node| tagid(node)})) + self + end + + def edit(node, text, *args) + tk_send('edit', tagid(node), text, *args) + self + end + + def exist?(node) + bool(tk_send('exists', tagid(node))) + end + + def find(findinfo, confine=None) + Tk::BWidget::Tree::Node.id2obj(self, tk_send(findinfo, confine)) + end + def find_position(x, y, confine=None) + self.find(_at(x,y), confine) + end + def find_line(linenum) + self.find(linenum) + end + + def index(node) + num_or_str(tk_send('index', tagid(node))) + end + + def insert(idx, parent, node, keys={}) + tk_send('insert', idx, tagid(parent), tagid(node), *hash_kv(keys)) + self + end + + def line(node) + number(tk_send('line', tagid(node))) + end + + def move(parent, node, idx) + tk_send('move', tagid(parent), tagid(node), idx) + self + end + + def get_node(node, idx) + Tk::BWidget::Tree::Node.id2obj(self, tk_send('nodes', tagid(node), idx)) + end + + def nodes(node, first=None, last=None) + simplelist(tk_send('nodes', tagid(node), first, last)).collect{|node| + Tk::BWidget::Tree::Node.id2obj(self, node) + } + end + + def open?(node) + bool(self.itemcget(tagid(node), 'open')) + end + + def open_tree(node, recurse=None) + tk_send('opentree', tagid(node), recurse) + self + end + + def parent(node) + Tk::BWidget::Tree::Node.id2obj(self, tk_send('parent', tagid(node))) + end + + def reorder(node, neworder) + tk_send('reorder', tagid(node), neworder) + self + end + + def see(node) + tk_send('see', tagid(node)) + self + end + + def selection_add(*args) + tk_send_without_enc('selection', 'add', + *(args.collect{|node| tagid(node)})) + self + end + + def selection_clear + tk_send_without_enc('selection', 'clear') + self + end + + def selection_get + list(tk_send_without_enc('selection', 'get')) + end + + def selection_include?(*args) + bool(tk_send_without_enc('selection', 'get', + *(args.collect{|node| tagid(node)}))) + end + + def selection_range(*args) + tk_send_without_enc('selection', 'range', + *(args.collect{|node| tagid(node)})) + self + end + + def selection_remove(*args) + tk_send_without_enc('selection', 'remove', + *(args.collect{|node| tagid(node)})) + self + end + + def selection_set(*args) + tk_send_without_enc('selection', 'set', + *(args.collect{|node| tagid(node)})) + self + end + + def selection_toggle(*args) + tk_send_without_enc('selection', 'toggle', + *(args.collect{|node| tagid(node)})) + self + end + + def toggle(node) + tk_send_without_enc('toggle', tagid(node)) + self + end + + def visible(node) + bool(tk_send_without_enc('visible', tagid(node))) + end +end + +class Tk::BWidget::Tree::Node + include TkTreatTagFont + + TreeNode_TBL = TkCore::INTERP.create_table + + (TreeNode_ID = ['bw:node'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + TkCore::INTERP.init_ip_env{ + TreeNode_TBL.mutex.synchronize{ TreeNode_TBL.clear } + } + + def self.id2obj(tree, id) + tpath = tree.path + TreeNode_TBL.mutex.synchronize{ + if TreeNode_TBL[tpath] + TreeNode_TBL[tpath][id]? TreeNode_TBL[tpath][id]: id + else + id + end + } + end + + def initialize(tree, *args) + if tree.kind_of?(Tk::BWidget::Tree) + @tree = tree + parent = args.shift + if parent.kind_of?(Tk::BWidget::Tree::Node) + if parent.tree.path != @tree.path + fail RuntimeError, 'tree of parent node is not match' + end + end + elsif tree.kind_of?(Tk::BWidget::Tree::Node) + @tree = tree.tree + parent = tree.parent + else + fail RuntimeError, + "expect Tk::BWidget::Tree or Tk::BWidget::Tree::Node for 1st argument" + end + + if args[-1].kind_of?(Hash) + keys = _symbolkey2str(args.pop) + else + keys = {} + end + + index = keys.delete('index') + unless args.empty? + index = args.shift + end + index = 'end' unless index + + unless args.empty? + fail RuntimeError, 'too much arguments' + end + + @tpath = @tree.path + + if keys.key?('nodename') + @path = @id = keys.delete('nodename') + else + TreeNode_ID.mutex.synchronize{ + @path = @id = TreeNode_ID.join(TkCore::INTERP._ip_id_) + TreeNode_ID[1].succ! + } + end + + TreeNode_TBL.mutex.synchronize{ + TreeNode_TBL[@id] = self + TreeNode_TBL[@tpath] = {} unless TreeNode_TBL[@tpath] + TreeNode_TBL[@tpath][@id] = self + } + + @tree.insert(index, parent, @id, keys) + end + + def tree + @tree + end + + def id + @id + end + + def [](key) + cget(key) + end + + def []=(key, val) + configure(key, val) + val + end + + def cget_tkstring(key) + @tree.itemcget_tkstring(@id, key) + end + def cget(key) + @tree.itemcget(@id, key) + end + def cget_strict(key) + @tree.itemcget_strict(@id, key) + end + + def configure(key, val=None) + @tree.itemconfigure(@id, key, val) + end + + def configinfo(key=nil) + @tree.itemconfiginfo(@id, key) + end + + def current_configinfo(key=nil) + @tree.current_itemconfiginfo(@id, key) + end + + def close_tree(recurse=None) + @tree.close_tree(@id, recurse) + self + end + + def delete + @tree.delete(@id) + self + end + + def edit(*args) + @tree.edit(@id, *args) + self + end + + def exist? + @tree.exist?(@id) + end + + def index + @tree.index(@id) + end + + def move(index, parent=nil) + if parent + @tree.move(parent, @id, index) + else + @tree.move(self.parent, @id, index) + end + end + + def open_tree(recurse=None) + @tree.open_tree(@id, recurse) + self + end + + def open? + bool(@tree.itemcget(@id, 'open')) + end + + def parent + @tree.parent(@id) + end + + def reorder(neworder) + @tree.reorder(@id, neworder) + end + + def see + @tree.see(@id) + end + + def selection_add + @tree.selection_add(@id) + end + + def selection_remove + @tree.selection_remove(@id) + end + + def selection_set + @tree.selection_set(@id) + end + + def selection_toggle + @tree.selection_toggle(@id) + end + + def toggle + @tree.toggle(@id) + end + + def visible + @tree.visible(@id) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/bwidget/widget.rb b/jni/ruby/ext/tk/lib/tkextlib/bwidget/widget.rb new file mode 100644 index 0000000..a93364b --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/bwidget/widget.rb @@ -0,0 +1,129 @@ +# +# tkextlib/bwidget/widget.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/bwidget.rb' + +module Tk + module BWidget + module Widget + end + end +end + +module Tk::BWidget::Widget + include Tk + extend Tk + + def self.__pathname + 'Widget::configure' + end + + def self.__cget_cmd + ['Widget::cget'] + end + + def self.__config_cmd + ['Widget::configure'] + end + + def self.cget_strict(slot) + slot = slot.to_s + info = {} + self.current_configinfo.each{|k,v| info[k.to_s] = v if k.to_s == slot} + fail RuntimeError, "unknown option \"-#{slot}\"" if info.empty? + info.values[0] + end + def self.cget(slot) + self.current_configinfo(slot).values[0] + end + + def self.add_map(klass, subclass, subpath, opts) + tk_call('Widget::addmap', klass, subclass, subpath, opts) + end + + def self.bwinclude(klass, subclass, subpath, *args) + tk_call('Widget::bwinclude', klass, subclass, subpath, *args) + end + + def self.create(klass, path, rename=None, &b) + win = window(tk_call('Widget::create', klass, path, rename)) + if b + if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! + win.instance_exec(self, &b) + else + win.instance_eval(&b) + end + end + win + end + + def self.declare(klass, optlist) + tk_call('Widget::declare', klass, optlist) + end + + def self.define(klass, filename, *args) + tk_call('Widget::define', klass, filename, *args) + end + + def self.destroy(win) + tk_call('Widget::destroy', _epath(win)) + end + + def self.focus_next(win) + tk_call('Widget::focusNext', win) + end + + def self.focus_ok(win) + tk_call('Widget::focusOk', win) + end + + def self.focus_prev(win) + tk_call('Widget::focusPrev', win) + end + + def self.generate_doc(dir, widgetlist) + tk_call('Widget::generate-doc', dir, widgetlist) + end + + def self.generate_widget_doc(klass, iscmd, file) + tk_call('Widget::generate-widget-doc', klass, iscmd, file) + end + + def self.get_option(win, option) + tk_call('Widget::getoption', win, option) + end + + def self.get_variable(win, varname, my_varname=None) + tk_call('Widget::getVariable', win, varname, my_varname) + end + + def self.has_changed(win, option, pvalue) + tk_call('Widget::hasChanged', win, option, pvalue) + end + + def self.init(klass, win, options) + tk_call('Widget::init', klass, win, options) + end + + def self.set_option(win, option, value) + tk_call('Widget::setoption', win, option, value) + end + + def self.sub_cget_strict(win, subwidget) + tk_call('Widget::subcget', win, subwidget) + end + def self.sub_cget(win, subwidget) + self.sub_cget_strict(win, subwidget) + end + + def self.sync_options(klass, subclass, subpath, options) + tk_call('Widget::syncoptions', klass, subclass, subpath, options) + end + + def self.tkinclude(klass, tkwidget, subpath, *args) + tk_call('Widget::tkinclude', klass, tkwidget, subpath, *args) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/itcl.rb b/jni/ruby/ext/tk/lib/tkextlib/itcl.rb new file mode 100644 index 0000000..1d6ecf0 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/itcl.rb @@ -0,0 +1,13 @@ +# +# [incr Tcl] support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/itcl/setup.rb' + +# load library +require 'tkextlib/itcl/incr_tcl.rb' diff --git a/jni/ruby/ext/tk/lib/tkextlib/itcl/incr_tcl.rb b/jni/ruby/ext/tk/lib/tkextlib/itcl/incr_tcl.rb new file mode 100644 index 0000000..8f6bb33 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/itcl/incr_tcl.rb @@ -0,0 +1,178 @@ +# +# tkextlib/itk/incr_tcl.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' + +# call setup script +require 'tkextlib/itcl.rb' + +# TkPackage.require('Itcl', '3.2') +TkPackage.require('Itcl') + +module Tk + module Itcl + include Tk + extend Tk + + LIBRARY = TkVarAccess.new('::itcl::library') + PURIST = TkVarAccess.new('::itcl::purist') + + VERSION = TkCore::INTERP._invoke("set", "::itcl::version").freeze + PATCHLEVEL = TkCore::INTERP._invoke("set", "::itcl::patchLevel").freeze + + PACKAGE_NAME = 'Itcl'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('Itcl') + rescue + '' + end + end + + ############################################## + + class ItclObject < TkObject + ITCL_CLASSNAME = ''.freeze + + (ITCL_OBJ_ID = ['itclobj'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + ITCL_OBJ_TBL = TkUtil.untrust({}) + + def initialize(*args) + if (@klass = self.class::ITCL_CLASSNAME).empty? + fail RuntimeError, 'unknown itcl class (abstract class?)' + end + Tk::Itcl::ItclObject::ITCL_OBJ_ID.mutex.synchronize{ + @id = Tk::Itcl::ItclObject::TCL_OBJ_ID.join(TkCore::INTERP._ip_id_) + Tk::Itcl::ItclObject::ITCL_OBJ_ID[1].succ! + } + @path = @id + end + + def self.call_proc(name, *args) + tk_call("#{ITCL_CLASSNAME}::#{cmd}", *args) + end + + def call_method(name, *args) + tk_call(@path, name, *args) + end + + def isa(klass) + bool(tk_call(@path, 'isa', klass)) + end + alias itcl_kind_of? isa + + def info_class + tk_call(@path, 'info', 'class') + end + + def info_inherit + simplelist(tk_call(@path, 'info', 'inherit')) + end + + def info_heritage + list(tk_call(@path, 'info', 'heritage')) + end + + def info_function(*args) + if args[-1].kind_of?(Array) + params = args.pop + params.each{|param| + param = param.to_s + args << ( (param[0] == ?-)? param: "-#{param}" ) + } + end + list(tk_call(@path, 'info', 'function', *args)) + end + + def info_variable(*args) + if args[-1].kind_of?(Array) + params = args.pop + params.each{|param| + param = param.to_s + args << ( (param[0] == ?-)? param: "-#{param}" ) + } + end + list(tk_call(@path, 'info', 'variable', *args)) + end + end + + ############################################## + + def self.body(klass, func, args, body) + tk_call('::itcl::body', "#{klass}::#{func}", args, body) + end + + def self.code(cmd, *args) + tk_call('::itcl::code', cmd, *args) + end + + def self.code_in_namespace(namespace, cmd, *args) + tk_call('::itcl::code', '-namespace', namespace, cmd, *args) + end + + def self.configbody(klass, var, body) + tk_call('::itcl::configbody', "#{klass}::#{var}", body) + end + + def self.create_itcl_class(name, body) + TkCore::INTERP._invoke('::itcl::class', name, body) + klass = Class.new(Tk::Itcl::ItclObject) + klass.const_set('ITCL_CLASSNAME', name.dup.freeze) + klass + end + + def self.delete_itcl_class(*names) + tk_call('::itcl::delete', 'class', *names) + end + + def self.delete_itcl_object(*names) + tk_call('::itcl::delete', 'object', *names) + end + + def self.delete_namespace(*names) + tk_call('::itcl::delete', 'namespace', *names) + end + + def self.ensemble(name, *args) + tk_call('::itcl::ensemble', name, *args) + end + + def self.find_classes(pat=None) + simplelist(tk_call('::itcl::find', 'classes', pat)) + end + + def self.find_objects(*args) + simplelist(tk_call('::itcl::find', 'objects', *args)) + end + + def self.is_itcl_class(target) + bool(tk_call('::itcl::is', 'class', target)) + end + + def self.is_itcl_object(target) + bool(tk_call('::itcl::is', 'object', target)) + end + + def self.create_local_obj(klass, name, *args) + tk_call('::itcl::local', klass, name, *args) + end + + def self.is_itcl_instance(klass, target) + bool(tk_call('::itcl::is', 'object', '-class', klass, target)) + end + + def self.scope(var) + tk_call('::itcl::scope', var) + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/itcl/setup.rb b/jni/ruby/ext/tk/lib/tkextlib/itcl/setup.rb new file mode 100644 index 0000000..70b38e4 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/itcl/setup.rb @@ -0,0 +1,13 @@ +# +# setup.rb -- setup script before calling TkPackage.require() +# +# If you need some setup operations (for example, add a library path +# to the library search path) before using Tcl/Tk library packages +# wrapped by Ruby scripts in this directory, please write the setup +# operations in this file. +# + + +# set [incr Tcl] library directory + +# ENV['ITCL_LIBRARY'] = '/usr/local/ActiveTcl/lib/itcl3.2/' diff --git a/jni/ruby/ext/tk/lib/tkextlib/itk.rb b/jni/ruby/ext/tk/lib/tkextlib/itk.rb new file mode 100644 index 0000000..7492bd3 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/itk.rb @@ -0,0 +1,13 @@ +# +# [incr Tk] support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/itk/setup.rb' + +# load library +require 'tkextlib/itk/incr_tk.rb' diff --git a/jni/ruby/ext/tk/lib/tkextlib/itk/incr_tk.rb b/jni/ruby/ext/tk/lib/tkextlib/itk/incr_tk.rb new file mode 100644 index 0000000..989585e --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/itk/incr_tk.rb @@ -0,0 +1,446 @@ +# +# tkextlib/itk/incr_tk.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/menuspec' +require 'tkextlib/itcl.rb' + +# call setup script +require 'tkextlib/itk.rb' + +#TkPackage.require('Itk', '3.2') +TkPackage.require('Itk') + +module Tk + module Itk + include Tk + extend Tk + + LIBRARY = TkVarAccess.new('::itk::library') + + PACKAGE_NAME = 'Itk'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('Itk') + rescue + '' + end + end + + def self.usual(arg, *args) + tk_call('::itk::usual', arg, *args) + end + + def self.usual_names + list(tk_call('::itk::usual')) + end + + ############################ + + class Archetype < TkWindow + TkCommandNames = [].freeze + # WidgetClassName = 'Archetype'.freeze + # WidgetClassNames[WidgetClassName] = self + + def self.to_eval + '::itk::' << self::WidgetClassName + end + + def __destroy_hook__ + Tk::Itk::Component::ComponentID_TBL.delete(self.path) + end + + #### [incr Tk] public methods + def component + simplelist(tk_send('component')) + end + + def component_path(name) + window(tk_send('component', name)) + end + alias component_widget component_path + + def component_invoke(name, cmd, *args) + window(tk_send('component', name, cmd, *args)) + end + + def component_obj(*names) + names = component if names.empty? + names.collect{|name| Tk::Itk::Component.new(self.path, name) } + end + + #### [incr Tk] protected methods +=begin + def itk_component_add(visibility, name, create_cmds, option_cmds=None) + args = [] + visibility.each{|v| v = v.to_s; args << ( (v[0] == ?-)? v: "-#{v}" )} + args << '--' << name << create_cmd << option_cmds + tk_call('itk_component', 'add', *args) + end + + def itk_component_delete(*names) + tk_call('itk_component', 'delete', *names) + end + + def itk_initialize(keys={}) + tk_call('itk_initialize', keys) + end + + def itk_option_add(*args) + tk_call('itk_option', 'add', *args) + end + + def itk_option_define(name, resource, klass, init, config=None) + tk_call('itk_option', 'define', name, resource, klass, init, config) + end + + def itk_option_remove(*args) + tk_call('itk_option', 'remove', *args) + end +=end + end + + ############################ + + class Toplevel < Archetype + TkCommandNames = ['::itk::Toplevel'].freeze + WidgetClassName = 'Toplevel'.freeze + WidgetClassNames[WidgetClassName] ||= self + + include Wm + include TkMenuSpec + + def __strval_optkeys + super() << 'title' + end + private :__strval_optkeys + end + + ############################ + + class Widget < Archetype + TkCommandNames = ['::itk::Widget'].freeze + WidgetClassName = 'Widget'.freeze + WidgetClassNames[WidgetClassName] ||= self + end + + + ############################ + + class Component < TkObject + def __cget_cmd + [self.master, 'component', self.name, 'cget'] + end + private :__cget_cmd + + def __config_cmd + [self.master, 'component', self.name, 'configure'] + end + private :__config_cmd + + ComponentID_TBL = TkCore::INTERP.create_table + + (Itk_Component_ID = ['itk:component'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + TkCore::INTERP.init_ip_env{ + ComponentID_TBL.mutex.synchronize{ ComponentID_TBL.clear } + } + + def self.id2obj(master, id) + if master.kind_of?(TkObject) + master = master.path + else + master = master.to_s + end + ComponentID_TBL.mutex.synchronize{ + if ComponentID_TBL.key?(master) + (ComponentID_TBL[master].key?(id))? ComponentID_TBL[master][id]: id + else + id + end + } + end + + def self.new(master, component=nil) + if master.kind_of?(TkObject) + master = master.path + else + master = master.to_s + end + + if component.kind_of?(Tk::Itk::Component) + component = component.name + elsif component + component = component.to_s + else + Itk_Component_ID.mutex.synchronize{ + component = Itk_Component_ID.join(TkCore::INTERP._ip_id_) + Itk_Component_ID[1].succ! + } + end + + ComponentID_TBL.mutex.synchronize{ + if ComponentID_TBL.key?(master) + if ComponentID_TBL[master].key?(component) + return ComponentID_TBL[master][component] + end + else + ComponentID_TBL[master] = {} + end + } + + super(master, component) + end + + def initialize(master, component) + @master = master + @component = component + + ComponentID_TBL.mutex.synchronize{ + ComponentID_TBL[@master][@component] = self + } + + begin + @widget = window(tk_call(@master, 'component', @component)) + @path = @widget.path + rescue + @widget = nil + @path = nil + end + end + + def path + unless @path + begin + @widget = window(tk_call(@master, 'component', @component)) + @path = @widget.path + rescue + fail RuntimeError, 'component is not assigned to a widget' + end + end + @path + end + + def epath + path() + end + + def to_eval + path() + end + + def master + @master + end + + def name + @component + end + + def widget + unless @widget + begin + @widget = window(tk_call(@master, 'component', @component)) + @path = @widget.path + rescue + fail RuntimeError, 'component is not assigned to a widget' + end + end + @widget + end + + def widget_class + unless @widget + begin + @widget = window(tk_call(@master, 'component', @component)) + @path = @widget.path + @widget.classname + rescue + nil + end + end + end + + def method_missing(id, *args) + name = id.id2name + + # try 1 : component command + begin + return tk_call(@master, 'component', @component, name, *args) + rescue + end + + # try 2 : component configure + len = args.length + begin + case len + when 1 + if name[-1] == ?= + return configure(name[0..-2], args[0]) + else + return configure(name, args[0]) + end + when 0 + return cget(name) + end + rescue + end + + # try 3 : widget method or widget configure + begin + unless @widget + @widget = window(tk_call(@master, 'component', @component)) + @path = @widget.path + end + @widget.__send__(id, *args) + rescue + end + + # unknown method + super(id, *args) + # fail RuntimeError, "unknown method '#{name}' for #{self.inspect}" + end + + def tk_send(cmd, *rest) + begin + tk_call(@master, 'component', @component, cmd, *rest) + rescue + unless @path + begin + @widget = window(tk_call(@master, 'component', @component)) + @path = @widget.path + rescue + fail RuntimeError, 'component is not assigned to a widget' + end + end + tk_call(@path, cmd, *rest) + end + end + + def tk_send_without_enc(cmd, *rest) + begin + tk_call_without_enc(@master, 'component', @component, cmd, *rest) + rescue + unless @path + begin + @widget = window(tk_call(@master, 'component', @component)) + @path = @widget.path + rescue + fail RuntimeError, 'component is not assigned to a widget' + end + end + tk_call_without_enc(@path, cmd, *rest) + end + end + + def tk_send_with_enc(cmd, *rest) + begin + tk_call_with_enc(@master, 'component', @component, cmd, *rest) + rescue + unless @path + begin + @widget = window(tk_call(@master, 'component', @component)) + @path = @widget.path + rescue + fail RuntimeError, 'component is not assigned to a widget' + end + end + tk_call_with_enc(@path, cmd, *rest) + end + end + + #def bind(*args) + # unless @widget + # begin + # @widget = window(tk_call(@master, 'component', @component)) + # @path = @widget.path + # rescue + # fail RuntimeError, 'component is not assigned to a widget' + # end + # end + # @widget.bind(*args) + #end + def bind(context, *args) + unless @widget + begin + @widget = window(tk_call(@master, 'component', @component)) + @path = @widget.path + rescue + fail RuntimeError, 'component is not assigned to a widget' + end + end + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + @widget.bind(context, cmd, *args) + end + + #def bind_append(*args) + # unless @widget + # begin + # @widget = window(tk_call(@master, 'component', @component)) + # @path = @widget.path + # rescue + # fail RuntimeError, 'component is not assigned to a widget' + # end + # end + # @widget.bind_append(*args) + #end + def bind_append(context, *args) + unless @widget + begin + @widget = window(tk_call(@master, 'component', @component)) + @path = @widget.path + rescue + fail RuntimeError, 'component is not assigned to a widget' + end + end + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + @widget.bind_append(context, cmd, *args) + end + + def bind_remove(*args) + unless @widget + begin + @widget = window(tk_call(@master, 'component', @component)) + @path = @widget.path + rescue + fail RuntimeError, 'component is not assigned to a widget' + end + end + @widget.bind_remove(*args) + end + + def bindinfo(*args) + unless @widget + begin + @widget = window(tk_call(@master, 'component', @component)) + @path = @widget.path + rescue + fail RuntimeError, 'component is not assigned to a widget' + end + end + @widget.bindinfo(*args) + end + + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/itk/setup.rb b/jni/ruby/ext/tk/lib/tkextlib/itk/setup.rb new file mode 100644 index 0000000..544926e --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/itk/setup.rb @@ -0,0 +1,13 @@ +# +# setup.rb -- setup script before calling TkPackage.require() +# +# If you need some setup operations (for example, add a library path +# to the library search path) before using Tcl/Tk library packages +# wrapped by Ruby scripts in this directory, please write the setup +# operations in this file. +# + + +# set [incr Tk] library directory + +# ENV['ITK_LIBRARY'] = '/usr/local/ActiveTcl/lib/itk3.2/' diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets.rb new file mode 100644 index 0000000..ebd4cf7 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets.rb @@ -0,0 +1,94 @@ +# +# [incr Widgets] support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/itcl' +require 'tkextlib/itk' + +# call setup script for general 'tkextlib' libraries +#require 'tkextlib/setup.rb' + +# call setup script +#require 'tkextlib/iwidgets/setup.rb' + +# load all image format handlers +#TkPackage.require('Iwidgets', '4.0') +TkPackage.require('Iwidgets') + +module Tk + module Iwidgets + TkComm::TkExtlibAutoloadModule.unshift(self) + + extend TkCore + + PACKAGE_NAME = 'Iwidgets'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('Iwidgets') + rescue + '' + end + end + + #################################################### + + autoload :Buttonbox, 'tkextlib/iwidgets/buttonbox' + autoload :Calendar, 'tkextlib/iwidgets/calendar' + autoload :Canvasprintbox, 'tkextlib/iwidgets/canvasprintbox' + autoload :Canvasprintdialog, 'tkextlib/iwidgets/canvasprintdialog' + autoload :Checkbox, 'tkextlib/iwidgets/checkbox' + autoload :Combobox, 'tkextlib/iwidgets/combobox' + autoload :Dateentry, 'tkextlib/iwidgets/dateentry' + autoload :Datefield, 'tkextlib/iwidgets/datefield' + autoload :Dialog, 'tkextlib/iwidgets/dialog' + autoload :Dialogshell, 'tkextlib/iwidgets/dialogshell' + autoload :Disjointlistbox, 'tkextlib/iwidgets/disjointlistbox' + autoload :Entryfield, 'tkextlib/iwidgets/entryfield' + autoload :Extbutton, 'tkextlib/iwidgets/extbutton' + autoload :Extfileselectionbox, 'tkextlib/iwidgets/extfileselectionbox' + autoload :Extfileselectiondialog,'tkextlib/iwidgets/extfileselectiondialog' + autoload :Feedback, 'tkextlib/iwidgets/feedback' + autoload :Fileselectionbox, 'tkextlib/iwidgets/fileselectionbox' + autoload :Fileselectiondialog, 'tkextlib/iwidgets/fileselectiondialog' + autoload :Finddialog, 'tkextlib/iwidgets/finddialog' + autoload :Hierarchy, 'tkextlib/iwidgets/hierarchy' + autoload :Hyperhelp, 'tkextlib/iwidgets/hyperhelp' + autoload :Labeledframe, 'tkextlib/iwidgets/labeledframe' + autoload :Labeledwidget, 'tkextlib/iwidgets/labeledwidget' + autoload :Mainwindow, 'tkextlib/iwidgets/mainwindow' + autoload :Menubar, 'tkextlib/iwidgets/menubar' + autoload :Messagebox, 'tkextlib/iwidgets/messagebox' + autoload :Messagedialog, 'tkextlib/iwidgets/messagedialog' + autoload :Notebook, 'tkextlib/iwidgets/notebook' + autoload :Optionmenu, 'tkextlib/iwidgets/optionmenu' + autoload :Panedwindow, 'tkextlib/iwidgets/panedwindow' + autoload :Pushbutton, 'tkextlib/iwidgets/pushbutton' + autoload :Promptdialog, 'tkextlib/iwidgets/promptdialog' + autoload :Radiobox, 'tkextlib/iwidgets/radiobox' + autoload :Scrolledcanvas, 'tkextlib/iwidgets/scrolledcanvas' + autoload :Scrolledframe, 'tkextlib/iwidgets/scrolledframe' + autoload :Scrolledhtml, 'tkextlib/iwidgets/scrolledhtml' + autoload :Scrolledlistbox, 'tkextlib/iwidgets/scrolledlistbox' + autoload :Scrolledtext, 'tkextlib/iwidgets/scrolledtext' + autoload :Scrolledwidget, 'tkextlib/iwidgets/scrolledwidget' + autoload :Selectionbox, 'tkextlib/iwidgets/selectionbox' + autoload :Selectiondialog, 'tkextlib/iwidgets/selectiondialog' + autoload :Shell, 'tkextlib/iwidgets/shell' + autoload :Spindate, 'tkextlib/iwidgets/spindate' + autoload :Spinint, 'tkextlib/iwidgets/spinint' + autoload :Spinner, 'tkextlib/iwidgets/spinner' + autoload :Spintime, 'tkextlib/iwidgets/spintime' + autoload :Tabnotebook, 'tkextlib/iwidgets/tabnotebook' + autoload :Tabset, 'tkextlib/iwidgets/tabset' + autoload :Timeentry, 'tkextlib/iwidgets/timeentry' + autoload :Timefield, 'tkextlib/iwidgets/timefield' + autoload :Toolbar, 'tkextlib/iwidgets/toolbar' + autoload :Watch, 'tkextlib/iwidgets/watch' + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/buttonbox.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/buttonbox.rb new file mode 100644 index 0000000..91e06d1 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/buttonbox.rb @@ -0,0 +1,121 @@ +# +# tkextlib/iwidgets/buttonbox.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Buttonbox < Tk::Itk::Widget + end + end +end + +class Tk::Iwidgets::Buttonbox + TkCommandNames = ['::iwidgets::buttonbox'.freeze].freeze + WidgetClassName = 'Buttonbox'.freeze + WidgetClassNames[WidgetClassName] ||= self + + #################################### + + include TkItemConfigMethod + + def __item_cget_cmd(id) + [self.path, 'buttoncget', id] + end + private :__item_cget_cmd + + def __item_config_cmd(id) + [self.path, 'buttonconfigure', id] + end + private :__item_config_cmd + + def __item_boolval_optkeys(id) + super(id) << 'defaultring' + end + private :__item_boolval_optkeys + + def tagid(tagOrId) + if tagOrId.kind_of?(Tk::Itk::Component) + tagOrId.name + else + #_get_eval_string(tagOrId) + tagOrId + end + end + + alias buttoncget_tkstring itemcget_tkstring + alias buttoncget itemcget + alias buttoncget_strict itemcget_strict + alias buttonconfigure itemconfigure + alias buttonconfiginfo itemconfiginfo + alias current_buttonconfiginfo current_itemconfiginfo + + private :itemcget_tkstring, :itemcget, :itemcget_strict + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo + + #################################### + + def add(tag=nil, keys={}) + if tag.kind_of?(Hash) + keys = tag + tag = nil + end + if tag + tag = Tk::Itk::Component.new(self, tagid(tag)) + else + tag = Tk::Itk::Component.new(self) + end + tk_call(@path, 'add', tagid(tag), *hash_kv(keys)) + tag + end + + def default(idx) + tk_call(@path, 'default', index(idx)) + self + end + + def delete(idx) + tk_call(@path, 'delete', index(idx)) + self + end + + def hide(idx) + tk_call(@path, 'hide', index(idx)) + self + end + + def index(idx) + number(tk_call(@path, 'index', tagid(idx))) + end + + def insert(idx, tag=nil, keys={}) + if tag.kind_of?(Hash) + keys = tag + tag = nil + end + if tag + tag = Tk::Itk::Component.new(self, tagid(tag)) + else + tag = Tk::Itk::Component.new(self) + end + tk_call(@path, 'insert', index(idx), tagid(tag), *hash_kv(keys)) + tag + end + + def invoke(idx=nil) + if idx + tk_call(@path, 'invoke', index(idx)) + else + tk_call(@path, 'invoke') + end + self + end + + def show(idx) + tk_call(@path, 'show', index(idx)) + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/calendar.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/calendar.rb new file mode 100644 index 0000000..a5478c7 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/calendar.rb @@ -0,0 +1,125 @@ +# +# tkextlib/iwidgets/calendar.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Calendar < Tk::Itk::Widget + end + end +end + +class Tk::Iwidgets::Calendar + TkCommandNames = ['::iwidgets::calendar'.freeze].freeze + WidgetClassName = 'Calendar'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() + [ + 'buttonforeground', 'outline', 'selectcolor', + 'weekdaybackground', 'weekendbackground' + ] + end + private :__strval_optkeys + + def __listval_optkeys + super() << 'days' + end + private :__listval_optkeys + + def __font_optkeys + super() + ['currentdatefont', 'datefont', 'dayfont', 'titlefont'] + end + private :__font_optkeys + + #################################### + + include Tk::ValidateConfigure + + class CalendarCommand < TkValidateCommand + #class CalCmdArgs < TkUtil::CallbackSubst + class ValidateArgs < TkUtil::CallbackSubst + KEY_TBL = [ [?d, ?s, :date], nil ] + PROC_TBL = [ [?s, TkComm.method(:string) ], nil ] + +=begin + # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) + KEY_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) + end + inf + } + + PROC_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + end + inf + } +=end + + _setup_subst_table(KEY_TBL, PROC_TBL); + + def self.ret_val(val) + val + end + end + + def self._config_keys + # array of config-option key (string or symbol) + ['command'] + end + + #def initialize(cmd = Proc.new, *args) + # _initialize_for_cb_class(CalCmdArgs, cmd, *args) + #end + end + + def __validation_class_list + super() << CalendarCommand + end + + Tk::ValidateConfigure.__def_validcmd(binding, CalendarCommand) +=begin + def command(cmd = Proc.new, args = nil) + if cmd.kind_of?(CalendarCommand) + configure('command', cmd) + elsif args + configure('command', [cmd, args]) + else + configure('command', cmd) + end + end +=end + + #################################### + + def get_string + tk_call(@path, 'get', '-string') + end + alias get get_string + + def get_clicks + number(tk_call(@path, 'get', '-clicks')) + end + + def select(date) + tk_call(@path, 'select', date) + self + end + + def show(date) + tk_call(@path, 'show', date) + self + end + def show_now + tk_call(@path, 'show', 'now') + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/canvasprintbox.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/canvasprintbox.rb new file mode 100644 index 0000000..398eec3 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/canvasprintbox.rb @@ -0,0 +1,53 @@ +# +# tkextlib/iwidgets/canvasprintbox.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Canvasprintbox < Tk::Itk::Widget + end + end +end + +class Tk::Iwidgets::Canvasprintbox + TkCommandNames = ['::iwidgets::canvasprintbox'.freeze].freeze + WidgetClassName = 'Canvasprintbox'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() << 'filename' + end + private :__strval_optkeys + + def __boolval_optkeys + super() << 'stretch' + end + private :__boolval_optkeys + + def get_output + tk_call(@path, 'getoutput') + end + + def print + bool(tk_call(@path, 'print')) + end + + def refresh + tk_call(@path, 'refresh') + self + end + + def set_canvas(win) + tk_call(@path, 'setcanvas', win) + self + end + + def stop + tk_call(@path, 'stop') + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/canvasprintdialog.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/canvasprintdialog.rb new file mode 100644 index 0000000..e64d815 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/canvasprintdialog.rb @@ -0,0 +1,38 @@ +# +# tkextlib/iwidgets/canvasprintdialog.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Canvasprintdialog < Tk::Iwidgets::Dialog + end + end +end + +class Tk::Iwidgets::Canvasprintdialog + TkCommandNames = ['::iwidgets::canvasprintdialog'.freeze].freeze + WidgetClassName = 'Canvasprintdialog'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def get_output + tk_call(@path, 'getoutput') + end + + def print + bool(tk_call(@path, 'print')) + end + + def refresh + tk_call(@path, 'refresh') + self + end + + def set_canvas(win) + tk_call(@path, 'setcanvas', win) + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/checkbox.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/checkbox.rb new file mode 100644 index 0000000..a7476c8 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/checkbox.rb @@ -0,0 +1,130 @@ +# +# tkextlib/iwidgets/checkbox.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Checkbox < Tk::Iwidgets::Labeledframe + end + end +end + +class Tk::Iwidgets::Checkbox + TkCommandNames = ['::iwidgets::checkbox'.freeze].freeze + WidgetClassName = 'Checkbox'.freeze + WidgetClassNames[WidgetClassName] ||= self + + #################################### + + include TkItemConfigMethod + + def __item_cget_cmd(id) + [self.path, 'buttoncget', id] + end + private :__item_cget_cmd + + def __item_config_cmd(id) + [self.path, 'buttonconfigure', id] + end + private :__item_config_cmd + + def __item_boolval_optkeys(id) + super(id) << 'defaultring' + end + private :__item_boolval_optkeys + + def tagid(tagOrId) + if tagOrId.kind_of?(Tk::Itk::Component) + tagOrId.name + else + #_get_eval_string(tagOrId) + tagOrId + end + end + + alias buttoncget_tkstring itemcget_tkstring + alias buttoncget itemcget + alias buttoncget_strict itemcget_strict + alias buttonconfigure itemconfigure + alias buttonconfiginfo itemconfiginfo + alias current_buttonconfiginfo current_itemconfiginfo + + private :itemcget_tkstring, :itemcget, :itemcget_strict + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo + + #################################### + + def add(tag=nil, keys={}) + if tag.kind_of?(Hash) + keys = tag + tag = nil + end + if tag + tag = Tk::Itk::Component.new(self, tagid(tag)) + else + tag = Tk::Itk::Component.new(self) + end + tk_call(@path, 'add', tagid(tag), *hash_kv(keys)) + tag + end + + def delete(idx) + tk_call(@path, 'delete', index(idx)) + self + end + + def deselect(idx) + tk_call(@path, 'deselect', index(idx)) + self + end + + def flash(idx) + tk_call(@path, 'flash', index(idx)) + self + end + + def get_tags + simplelist(tk_call_without_enc(@path, 'get')) + end + + def get_objs + simplelist(tk_call_without_enc(@path, 'get')).collect{|id| + Tk::Itk::Component.id2obj(self, id) + } + end + + def get(idx=nil) + if idx + bool(tk_call_without_enc(@path, 'get', index(idx))) + else + get_tags + end + end + + def index(idx) + number(tk_call(@path, 'index', tagid(idx))) + end + + def insert(idx, tag=nil, keys={}) + if tag.kind_of?(Hash) + keys = tag + tag = nil + end + if tag + tag = Tk::Itk::Component.new(self, tagid(tag)) + else + tag = Tk::Itk::Component.new(self) + end + tk_call(@path, 'insert', index(idx), tagid(tag), *hash_kv(keys)) + tag + end + + def select(idx) + tk_call(@path, 'select', index(idx)) + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/combobox.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/combobox.rb new file mode 100644 index 0000000..82dcf25 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/combobox.rb @@ -0,0 +1,104 @@ +# +# tkextlib/iwidgets/combobox.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Combobox < Tk::Iwidgets::Entryfield + end + end +end + +class Tk::Iwidgets::Combobox + TkCommandNames = ['::iwidgets::combobox'.freeze].freeze + WidgetClassName = 'Combobox'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __boolval_optkeys + super() << 'completion' << 'dropdown' << 'editable' << 'unique' + end + private :__boolval_optkeys + + def clear(component=None) + tk_call(@path, 'clear', component) + self + end + + def delete_list(first, last=None) + tk_call(@path, 'delete', 'list', first, last) + self + end + + def delete_entry(first, last=None) + tk_call(@path, 'delete', 'entry', first, last) + self + end + + def get_list_contents(index) + tk_call(@path, 'get', index) + end + + def insert_list(idx, *elems) + tk_call(@path, 'insert', 'list', idx, *elems) + self + end + + def insert_entry(idx, *elems) + tk_call(@path, 'insert', 'entry', idx, *elems) + self + end + + # listbox methods + def size + tk_send_without_enc('size').to_i + end + def see(index) + tk_send_without_enc('see', index) + self + 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 + + # scrolledlistbox methods + def get_curselection + tk_call(@path, 'getcurselection') + end + def justify(dir) + tk_call(@path, 'justify', dir) + self + end + def sort(*params, &b) + # see 'lsort' man page about params + if b + tk_call(@path, 'sort', '-command', proc(&b), *params) + else + tk_call(@path, 'sort', *params) + end + self + end + def sort_ascending + tk_call(@path, 'sort', 'ascending') + self + end + def sort_descending + tk_call(@path, 'sort', 'descending') + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/dateentry.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/dateentry.rb new file mode 100644 index 0000000..98a0051 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/dateentry.rb @@ -0,0 +1,20 @@ +# +# tkextlib/iwidgets/dateentry.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Dateentry < Tk::Iwidgets::Datefield + end + end +end + +class Tk::Iwidgets::Dateentry + TkCommandNames = ['::iwidgets::dateentry'.freeze].freeze + WidgetClassName = 'Dateentry'.freeze + WidgetClassNames[WidgetClassName] ||= self +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/datefield.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/datefield.rb new file mode 100644 index 0000000..50d5405 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/datefield.rb @@ -0,0 +1,58 @@ +# +# tkextlib/iwidgets/datefield.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Datefield < Tk::Iwidgets::Labeledwidget + end + end +end + +class Tk::Iwidgets::Datefield + TkCommandNames = ['::iwidgets::datefield'.freeze].freeze + WidgetClassName = 'Datefield'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __boolval_optkeys + super() << 'gmt' + end + private :__boolval_optkeys + + def __strval_optkeys + super() << 'textbackground' + end + private :__strval_optkeys + + def __font_optkeys + super() << 'textfont' + end + private :__font_optkeys + + def get_string + tk_call(@path, 'get', '-string') + end + alias get get_string + + def get_clicks + number(tk_call(@path, 'get', '-clicks')) + end + + def valid? + bool(tk_call(@path, 'isvalid')) + end + alias isvalid? valid? + + def show(date=None) + tk_call(@path, 'show', date) + self + end + def show_now + tk_call(@path, 'show', 'now') + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/dialog.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/dialog.rb new file mode 100644 index 0000000..2d554ca --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/dialog.rb @@ -0,0 +1,20 @@ +# +# tkextlib/iwidgets/dialog.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Dialog < Tk::Iwidgets::Dialogshell + end + end +end + +class Tk::Iwidgets::Dialog + TkCommandNames = ['::iwidgets::dialog'.freeze].freeze + WidgetClassName = 'Dialog'.freeze + WidgetClassNames[WidgetClassName] ||= self +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/dialogshell.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/dialogshell.rb new file mode 100644 index 0000000..e880594 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/dialogshell.rb @@ -0,0 +1,121 @@ +# +# tkextlib/iwidgets/dialogshell.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Dialogshell < Tk::Iwidgets::Shell + end + end +end + +class Tk::Iwidgets::Dialogshell + TkCommandNames = ['::iwidgets::dialogshell'.freeze].freeze + WidgetClassName = 'Dialogshell'.freeze + WidgetClassNames[WidgetClassName] ||= self + + #################################### + + include TkItemConfigMethod + + def __item_cget_cmd(id) + [self.path, 'buttoncget', id] + end + private :__item_cget_cmd + + def __item_config_cmd(id) + [self.path, 'buttonconfigure', id] + end + private :__item_config_cmd + + def __item_boolval_optkeys(id) + super(id) << 'defaultring' + end + private :__item_boolval_optkeys + + def tagid(tagOrId) + if tagOrId.kind_of?(Tk::Itk::Component) + tagOrId.name + else + #_get_eval_string(tagOrId) + tagOrId + end + end + + alias buttoncget_tkstring itemcget_tkstring + alias buttoncget itemcget + alias buttoncget_strict itemcget_strict + alias buttonconfigure itemconfigure + alias buttonconfiginfo itemconfiginfo + alias current_buttonconfiginfo current_itemconfiginfo + + private :itemcget_tkstring, :itemcget, :itemcget_strict + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo + + #################################### + + def add(tag=nil, keys={}) + if tag.kind_of?(Hash) + keys = tag + tag = nil + end + if tag + tag = Tk::Itk::Component.new(self, tagid(tag)) + else + tag = Tk::Itk::Component.new(self) + end + tk_call(@path, 'add', tagid(tag), *hash_kv(keys)) + tag + end + + def default(idx) + tk_call(@path, 'default', index(idx)) + self + end + + def delete(idx) + tk_call(@path, 'delete', index(idx)) + self + end + + def hide(idx) + tk_call(@path, 'hide', index(idx)) + self + end + + def index(idx) + number(tk_call(@path, 'index', tagid(idx))) + end + + def insert(idx, tag=nil, keys={}) + if tag.kind_of?(Hash) + keys = tag + tag = nil + end + if tag + tag = Tk::Itk::Component.new(self, tagid(tag)) + else + tag = Tk::Itk::Component.new(self) + end + tk_call(@path, 'insert', index(idx), tagid(tag), *hash_kv(keys)) + tag + end + + def invoke(idx=nil) + if idx + tk_call(@path, 'invoke', index(idx)) + else + tk_call(@path, 'invoke') + end + self + end + + def show(idx) + tk_call(@path, 'show', index(idx)) + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/disjointlistbox.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/disjointlistbox.rb new file mode 100644 index 0000000..07ab025 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/disjointlistbox.rb @@ -0,0 +1,50 @@ +# +# tkextlib/iwidgets/disjointlistbox.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Disjointlistbox < Tk::Itk::Widget + end + end +end + +class Tk::Iwidgets::Disjointlistbox + TkCommandNames = ['::iwidgets::disjointlistbox'.freeze].freeze + WidgetClassName = 'Disjointlistbox'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() << 'lhslabeltext' << 'rhslabeltext' << 'lhsbuttonlabel' << 'rhsbuttonlabel' + end + private :__strval_optkeys + + def set_lhs(*items) + tk_call(@path, 'setlhs', items) + self + end + def set_rhs(*items) + tk_call(@path, 'setrhs', items) + self + end + + def get_lhs + simplelist(tk_call(@path, 'getlhs')) + end + def get_rhs + simplelist(tk_call(@path, 'getrhs')) + end + + def insert_lhs(*items) + tk_call(@path, 'insertlhs', items) + self + end + def insert_rhs(*items) + tk_call(@path, 'insertrhs', items) + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/entryfield.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/entryfield.rb new file mode 100644 index 0000000..3e7149a --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/entryfield.rb @@ -0,0 +1,185 @@ +# +# tkextlib/iwidgets/entryfield.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Entryfield < Tk::Iwidgets::Labeledwidget + end + end +end + +class Tk::Iwidgets::Entryfield + TkCommandNames = ['::iwidgets::entryfield'.freeze].freeze + WidgetClassName = 'Entryfield'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __font_optkeys + super() << 'textfont' + end + private :__font_optkeys + + #################################### + + include Tk::ValidateConfigure + + class EntryfieldValidate < TkValidateCommand + #class CalCmdArgs < TkUtil::CallbackSubst + class ValidateArgs < TkUtil::CallbackSubst + KEY_TBL = [ + [ ?c, ?s, :char ], + [ ?P, ?s, :post ], + [ ?S, ?s, :current ], + [ ?W, ?w, :widget ], + nil + ] + PROC_TBL = [ + [ ?s, TkComm.method(:string) ], + [ ?w, TkComm.method(:window) ], + nil + ] + +=begin + # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) + KEY_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) + end + inf + } + + PROC_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + end + inf + } +=end + + _setup_subst_table(KEY_TBL, PROC_TBL); + end + + def self._config_keys + ['validate', 'invalid'] + end + end + + def __validation_class_list + super() << EntryfieldValidate + end + + Tk::ValidateConfigure.__def_validcmd(binding, EntryfieldValidate) +=begin + def validate(cmd = Proc.new, args = nil) + if cmd.kind_of?(ValidateCmd) + configure('validate', cmd) + elsif args + configure('validate', [cmd, args]) + else + configure('validate', cmd) + end + end + + def invalid(cmd = Proc.new, args = nil) + if cmd.kind_of?(ValidateCmd) + configure('invalid', cmd) + elsif args + configure('invalid', [cmd, args]) + else + configure('invalid', cmd) + end + end +=end + + #################################### + + def clear + tk_call(@path, 'clear') + self + end + + def delete(first, last=None) + tk_send_without_enc('delete', first, last) + self + 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 cursor=(index) + tk_send_without_enc('icursor', index) + #self + index + end + alias icursor cursor= + + 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 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 + + # based on tk/scrollable.rb + def xview(*index) + if index.size == 0 + list(tk_send_without_enc('xview')) + else + tk_send_without_enc('xview', *index) + self + end + end + def xview_moveto(*index) + xview('moveto', *index) + end + def xview_scroll(*index) + xview('scroll', *index) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/extbutton.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/extbutton.rb new file mode 100644 index 0000000..e744fba --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/extbutton.rb @@ -0,0 +1,40 @@ +# +# tkextlib/iwidgets/extbutton.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Extbutton < Tk::Itk::Widget + end + end +end + +class Tk::Iwidgets::Extbutton + TkCommandNames = ['::iwidgets::extbutton'.freeze].freeze + WidgetClassName = 'Extbutton'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() << 'bitmapforeground' << 'ringbackground' + end + private :__strval_optkeys + + def __boolval_optkeys + super() << 'defaultring' + end + private :__boolval_optkeys + + def invoke + tk_call(@path, 'invoke') + self + end + + def flash + tk_call(@path, 'flash') + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/extfileselectionbox.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/extfileselectionbox.rb new file mode 100644 index 0000000..2ff15bb --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/extfileselectionbox.rb @@ -0,0 +1,46 @@ +# +# tkextlib/iwidgets/extfileselectionbox.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Extfileselectionbox < Tk::Itk::Widget + end + end +end + +class Tk::Iwidgets::Extfileselectionbox + TkCommandNames = ['::iwidgets::extfileselectionbox'.freeze].freeze + WidgetClassName = 'Extfileselectionbox'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() + [ + 'dirslabel', 'fileslabel', 'filterlabel', 'mask', 'nomatchstring', + 'selectionlabel' + ] + end + private :__strval_optkeys + + def __boolval_optkeys + super() + ['dirson', 'fileson', 'filteron', 'selectionon'] + end + private :__boolval_optkeys + + def child_site + window(tk_call(@path, 'childsite')) + end + + def filter + tk_call(@path, 'filter') + self + end + + def get + tk_call(@path, 'get') + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/extfileselectiondialog.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/extfileselectiondialog.rb new file mode 100644 index 0000000..509fdcf --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/extfileselectiondialog.rb @@ -0,0 +1,33 @@ +# +# tkextlib/iwidgets/extfileselectiondialog.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Extfileselectiondialog < Tk::Iwidgets::Dialog + end + end +end + +class Tk::Iwidgets::Extfileselectiondialog + TkCommandNames = ['::iwidgets::extfileselectiondialog'.freeze].freeze + WidgetClassName = 'Extfileselectiondialog'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def child_site + window(tk_call(@path, 'childsite')) + end + + def filter + tk_call(@path, 'filter') + self + end + + def get + tk_call(@path, 'get') + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/feedback.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/feedback.rb new file mode 100644 index 0000000..29d04c8 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/feedback.rb @@ -0,0 +1,35 @@ +# +# tkextlib/iwidgets/feedback.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Feedback < Tk::Iwidgets::Labeledwidget + end + end +end + +class Tk::Iwidgets::Feedback + TkCommandNames = ['::iwidgets::feedback'.freeze].freeze + WidgetClassName = 'Feedback'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() << 'barcolor' + end + private :__strval_optkeys + + def reset + tk_call(@path, 'reset') + self + end + + def step(inc=1) + tk_call(@path, 'step', inc) + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/fileselectionbox.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/fileselectionbox.rb new file mode 100644 index 0000000..a425b53 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/fileselectionbox.rb @@ -0,0 +1,46 @@ +# +# tkextlib/iwidgets/fileselectionbox.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Fileselectionbox < Tk::Itk::Widget + end + end +end + +class Tk::Iwidgets::Fileselectionbox + TkCommandNames = ['::iwidgets::fileselectionbox'.freeze].freeze + WidgetClassName = 'Fileselectionbox'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() + [ + 'directory', 'dirslabel', 'fileslabel', 'filterlabel', 'mask', + 'nomatchstring', 'selectionlabel' + ] + end + private :__strval_optkeys + + def __boolval_optkeys + super() + ['dirson', 'fileson', 'filteron', 'selectionon'] + end + private :__boolval_optkeys + + def child_site + window(tk_call(@path, 'childsite')) + end + + def filter + tk_call(@path, 'filter') + self + end + + def get + tk_call(@path, 'get') + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/fileselectiondialog.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/fileselectiondialog.rb new file mode 100644 index 0000000..ebcdaf8 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/fileselectiondialog.rb @@ -0,0 +1,33 @@ +# +# tkextlib/iwidgets/fileselectiondialog.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Fileselectiondialog < Tk::Iwidgets::Dialog + end + end +end + +class Tk::Iwidgets::Fileselectiondialog + TkCommandNames = ['::iwidgets::fileselectiondialog'.freeze].freeze + WidgetClassName = 'Fileselectiondialog'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def child_site + window(tk_call(@path, 'childsite')) + end + + def filter + tk_call(@path, 'filter') + self + end + + def get + tk_call(@path, 'get') + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/finddialog.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/finddialog.rb new file mode 100644 index 0000000..3d522e0 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/finddialog.rb @@ -0,0 +1,42 @@ +# +# tkextlib/iwidgets/finddialog.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Finddialog < Tk::Iwidgets::Dialogshell + end + end +end + +class Tk::Iwidgets::Finddialog + TkCommandNames = ['::iwidgets::finddialog'.freeze].freeze + WidgetClassName = 'Finddialog'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() + [ + 'patternbackground', 'patternforeground', + 'searchbackground', 'searchforeground' + ] + end + private :__strval_optkeys + + def __val2ruby_optkeys # { key=>proc, ... } + super().update('textwidget'=>proc{|v| window(v)}) + end + private :__val2ruby_optkeys + + def clear + tk_call(@path, 'clear') + self + end + + def find + tk_call(@path, 'find') + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb new file mode 100644 index 0000000..cb9301d --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb @@ -0,0 +1,365 @@ +# +# tkextlib/iwidgets/hierarchy.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/text' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Hierarchy < Tk::Iwidgets::Scrolledwidget + end + end +end + +class Tk::Iwidgets::Hierarchy + ItemConfCMD = ['tag'.freeze, 'configure'.freeze].freeze + include TkTextTagConfig + + TkCommandNames = ['::iwidgets::hierarchy'.freeze].freeze + WidgetClassName = 'Hierarchy'.freeze + WidgetClassNames[WidgetClassName] ||= self + + #################################### + + include Tk::ValidateConfigure + + class QueryCommand < TkValidateCommand + class ValidateArgs < TkUtil::CallbackSubst + KEY_TBL = [ [?n, ?s, :node], nil ] + PROC_TBL = [ [?s, TkComm.method(:string) ], nil ] + +=begin + # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) + KEY_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) + end + inf + } + + PROC_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + end + inf + } +=end + + _setup_subst_table(KEY_TBL, PROC_TBL); + + def self.ret_val(val) + val + end + end + + def self._config_keys + # array of config-option key (string or symbol) + ['querycommand'] + end + end + + class IndicatorCommand < TkValidateCommand + class ValidateArgs < TkUtil::CallbackSubst + KEY_TBL = [ + [ ?n, ?s, :node ], + [ ?s, ?b, :status ], + nil + ] + + PROC_TBL = [ + [ ?s, TkComm.method(:string) ], + [ ?b, TkComm.method(:bool) ], + nil + ] + +=begin + # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) + KEY_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) + end + inf + } + + PROC_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + end + inf + } +=end + + _setup_subst_table(KEY_TBL, PROC_TBL); + + def self.ret_val(val) + val + end + end + + def self._config_keys + # array of config-option key (string or symbol) + ['iconcommand', 'icondblcommand', 'imagedblcommand'] + end + end + + class IconCommand < TkValidateCommand + class ValidateArgs < TkUtil::CallbackSubst + KEY_TBL = [ + [ ?n, ?s, :node ], + [ ?i, ?s, :icon ], + nil + ] + PROC_TBL = [ [ ?s, TkComm.method(:string) ], nil ] + +=begin + # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) + KEY_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) + end + inf + } + + PROC_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + end + inf + } +=end + + _setup_subst_table(KEY_TBL, PROC_TBL); + + def self.ret_val(val) + val + end + end + + def self._config_keys + # array of config-option key (string or symbol) + ['dblclickcommand', 'imagecommand', 'selectcommand'] + end + end + + def __validation_class_list + super() << QueryCommand << IndicatorCommand << IconCommand + end + + Tk::ValidateConfigure.__def_validcmd(binding, QueryCommand) + Tk::ValidateConfigure.__def_validcmd(binding, IndicatorCommand) + Tk::ValidateConfigure.__def_validcmd(binding, IconCommand) + + #################################### + + def __boolval_optkeys + super() << 'alwaysquery' << 'expanded' << 'filter' + end + private :__boolval_optkeys + + def __strval_optkeys + super() << 'markbackground' << 'markforeground' << 'textbackground' + end + private :__strval_optkeys + + def __font_optkeys + super() << 'textfont' + end + private :__font_optkeys + + def clear + tk_call(@path, 'clear') + self + end + + def collapse(node) + tk_call(@path, 'collapse') + self + end + + def current + tk_call(@path, 'current') + end + + def draw(mode=None) + case mode + when None + # do nothing + when 'now', :now + mode = '-now' + when 'eventually', :eventually + mode = '-eventually' + when String, Symbol + mode = mode.to_s + mode = '-' << mode if mode[0] != ?- + end + tk_call(@path, 'draw', mode) + end + + def expand(node) + tk_call(@path, 'expand', node) + self + end + + def expanded?(node) + bool(tk_call(@path, 'expanded', node)) + end + + def exp_state + list(tk_call(@path, 'expState')) + end + alias expand_state exp_state + alias expanded_list exp_state + + def mark_clear + tk_call(@path, 'mark', 'clear') + self + end + def mark_add(*nodes) + tk_call(@path, 'mark', 'add', *nodes) + self + end + def mark_remove(*nodes) + tk_call(@path, 'mark', 'remove', *nodes) + self + end + def mark_get + list(tk_call(@path, 'mark', 'get')) + end + + def refresh(node) + tk_call(@path, 'refresh', node) + self + end + + def prune(node) + tk_call(@path, 'prune', node) + self + end + + def selection_clear + tk_call(@path, 'selection', 'clear') + self + end + def selection_add(*nodes) + tk_call(@path, 'selection', 'add', *nodes) + self + end + def selection_remove(*nodes) + tk_call(@path, 'selection', 'remove', *nodes) + self + end + def selection_get + list(tk_call(@path, 'selection', 'get')) + end + + def toggle(node) + tk_call(@path, 'toggle', node) + self + end + + # based on Tk::Text widget + + def bbox(index) + list(tk_send_without_enc('bbox', _get_eval_enc_str(index))) + end + + def compare(idx1, op, idx2) + bool(tk_send_without_enc('compare', _get_eval_enc_str(idx1), + op, _get_eval_enc_str(idx2))) + end + + def debug + bool(tk_send_without_enc('debug')) + end + def debug=(boolean) + tk_send_without_enc('debug', boolean) + #self + boolean + end + + def delete(first, last=None) + tk_send_without_enc('delete', first, last) + self + end + + def dlineinfo(index) + list(tk_send_without_enc('dlineinfo', _get_eval_enc_str(index))) + end + + def get(*index) + _fromUTF8(tk_send_without_enc('get', *index)) + end + + def index(index) + tk_send_without_enc('index', _get_eval_enc_str(index)) + end + + def insert(index, chars, *tags) + if tags[0].kind_of? Array + # multiple chars-taglist argument :: str, [tag,...], str, [tag,...], ... + args = [chars] + while tags.size > 0 + args << tags.shift.collect{|x|_get_eval_string(x)}.join(' ') # taglist + args << tags.shift if tags.size > 0 # chars + end + super(index, *args) + else + # single chars-taglist argument :: str, tag, tag, ... + if tags.size == 0 + super(index, chars) + else + super(index, chars, tags.collect{|x|_get_eval_string(x)}.join(' ')) + end + end + 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 + + # based on tk/scrollable.rb + def xview(*index) + if index.size == 0 + list(tk_send_without_enc('xview')) + else + tk_send_without_enc('xview', *index) + self + end + end + def xview_moveto(*index) + xview('moveto', *index) + end + def xview_scroll(*index) + xview('scroll', *index) + 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 yview_moveto(*index) + yview('moveto', *index) + end + def yview_scroll(*index) + yview('scroll', *index) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/hyperhelp.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/hyperhelp.rb new file mode 100644 index 0000000..d4ea1aa --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/hyperhelp.rb @@ -0,0 +1,50 @@ +# +# tkextlib/iwidgets/hyperhelp.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Hyperhelp < Tk::Iwidgets::Shell + end + end +end + +class Tk::Iwidgets::Hyperhelp + TkCommandNames = ['::iwidgets::hyperhelp'.freeze].freeze + WidgetClassName = 'Hyperhelp'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() << 'helpdir' + end + private :__strval_optkeys + + def __listval_optkeys + super() << 'topics' + end + private :__listval_optkeys + + def show_topic(topic) + tk_call(@path, 'showtopic', topic) + self + end + + def follow_link(href) + tk_call(@path, 'followlink', href) + self + end + + def forward + tk_call(@path, 'forward') + self + end + + def back + tk_call(@path, 'back') + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/labeledframe.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/labeledframe.rb new file mode 100644 index 0000000..6595398 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/labeledframe.rb @@ -0,0 +1,39 @@ +# +# tkextlib/iwidgets/labeledframe.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Labeledframe < Tk::Itk::Archetype + end + end +end + +class Tk::Iwidgets::Labeledframe + TkCommandNames = ['::iwidgets::labeledframe'.freeze].freeze + WidgetClassName = 'Labeledframe'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() << 'labeltext' + end + private :__strval_optkeys + + def __tkvariable_optkeys + super() << 'labelvariable' + end + private :__tkvariable_optkeys + + def __font_optkeys + super() << 'labelfont' + end + private :__font_optkeys + + def child_site + window(tk_call(@path, 'childsite')) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/labeledwidget.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/labeledwidget.rb new file mode 100644 index 0000000..d36d428 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/labeledwidget.rb @@ -0,0 +1,45 @@ +# +# tkextlib/iwidgets/labeledwidget.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Labeledwidget < Tk::Itk::Widget + end + end +end + +class Tk::Iwidgets::Labeledwidget + extend TkCore + + TkCommandNames = ['::iwidgets::labeledwidget'.freeze].freeze + WidgetClassName = 'Labeledwidget'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() << 'labeltext' + end + private :__strval_optkeys + + def __tkvariable_optkeys + super() << 'labelvariable' + end + private :__tkvariable_optkeys + + def __font_optkeys + super() << 'labelfont' + end + private :__font_optkeys + + def self.alignlabels(*wins) + tk_call('::iwidgets::Labeledwidget::alignlabels', *wins) + end + + def child_site + window(tk_call(@path, 'childsite')) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/mainwindow.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/mainwindow.rb new file mode 100644 index 0000000..ebf4802 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/mainwindow.rb @@ -0,0 +1,67 @@ +# +# tkextlib/iwidgets/mainwindow.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Mainwindow < Tk::Iwidgets::Shell + end + end +end + +class Tk::Iwidgets::Mainwindow + TkCommandNames = ['::iwidgets::mainwindow'.freeze].freeze + WidgetClassName = 'Mainwindow'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __boolval_optkeys + super() << 'helpline' << 'statusline' + end + private :__boolval_optkeys + + def __strval_optkeys + super() << 'menubarbackground' << 'menubarforeground' << 'toolbarforeground' + end + private :__strval_optkeys + + def __font_optkeys + super() << 'menubarfont' << 'toolbarfont' + end + private :__font_optkeys + + def child_site + window(tk_call(@path, 'childsite')) + end + + def menubar(*args) + unless args.empty? + tk_call(@path, 'menubar', *args) + end + window(tk_call(@path, 'menubar')) + end + + def mousebar(*args) + unless args.empty? + tk_call(@path, 'mousebar', *args) + end + window(tk_call(@path, 'mousebar')) + end + + def msgd(*args) + unless args.empty? + tk_call(@path, 'msgd', *args) + end + window(tk_call(@path, 'msgd')) + end + + def toolbar(*args) + unless args.empty? + tk_call(@path, 'toolbar', *args) + end + window(tk_call(@path, 'toolbar')) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/menubar.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/menubar.rb new file mode 100644 index 0000000..f9a17d0 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/menubar.rb @@ -0,0 +1,212 @@ +# +# tkextlib/iwidgets/menubar.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Menubar < Tk::Itk::Widget + end + end +end + +class Tk::Iwidgets::Menubar + TkCommandNames = ['::iwidgets::menubar'.freeze].freeze + WidgetClassName = 'Menubar'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() << 'menubuttons' + end + private :__strval_optkeys + + def __tkvariable_optkeys + super() << 'helpvariable' + end + private :__tkvariable_optkeys + + #################################### + + include TkItemConfigMethod + + def __item_cget_cmd(id) + [self.path, 'menucget', id] + end + private :__item_cget_cmd + + def __item_config_cmd(id) + [self.path, 'menuconfigure', id] + end + private :__item_config_cmd + + def __item_strval_optkeys(id) + super(id) << 'selectcolor' + end + private :__item_strval_optkeys + + def __item_tkvariable_optkeys(id) + super(id) << 'helpstr' + end + private :__item_tkvariable_optkeys + + def tagid(tagOrId) + if tagOrId.kind_of?(Tk::Itk::Component) + tagOrId.name + else + #_get_eval_string(tagOrId) + tagOrId + end + end + + alias menucget_tkstring itemcget_tkstring + alias menucget itemcget + alias menucget_strict itemcget_strict + alias menuconfigure itemconfigure + alias menuconfiginfo itemconfiginfo + alias current_menuconfiginfo current_itemconfiginfo + + private :itemcget_tkstring, :itemcget, :itemcget_strict + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo + + #################################### + + def __methodcall_optkeys + {'menubuttons'=>'menubuttons'} + end + + def menubuttons(val = nil) + unless val + return tk_call(@path, 'cget', '-menubuttons') + end + + tk_call(@path, 'configure', '-menubuttons', _parse_menu_spec(val)) + self + end + + def _parse_menu_spec(menu_spec) + ret = '' + menu_spec.each{|spec| + next unless spec + + if spec.kind_of?(Hash) + args = [spec] + type = 'options' + else + type, *args = spec + end + + type = type.to_s + case type + when 'options' + keys = args[0] + ary = [type] + ary.concat(hash_kv(keys)) + ret << array2tk_list(ary) << "\n" + + when 'menubutton', 'cascade' + name, keys = args + if keys + ary = [type, name] + keys = _symbolkey2str(keys) + keys['menu'] = _parse_menu_spec(keys['menu']) if keys.key?('menu') + ary.concat(hash_kv(keys)) + ret << array2tk_list(ary) << "\n" + else + ret << array2tk_list([type, name]) << "\n" + end + + else + name, keys = args + if keys + ary = [type, name] + ary.concat(hash_kv(keys)) + ret << array2tk_list(ary) << "\n" + else + ret << array2tk_list([type, name]) << "\n" + end + end + } + ret + end + + #################################### + + def add(type, tag=nil, keys={}) + if tag.kind_of?(Hash) + keys = tag + tag = nil + end + if tag + tag = Tk::Itk::Component.new(self, tagid(tag)) + else + tag = Tk::Itk::Component.new(self) + end + keys = _symbolkey2str(keys) + keys['menu'] = _parse_menu_spec(keys['menu']) if keys.key?('menu') + tk_call(@path, 'add', type, tagid(tag), *hash_kv(keys)) + tag + end + + def delete(path1, path2=nil) + if path2 + else + tk_call(@path, 'delete', index(idx)) + end + self + end + + def index(idx) + number(tk_call(@path, 'index', tagid(idx))) + end + + def insert(idx, type, tag=nil, keys={}) + if tag.kind_of?(Hash) + keys = tag + tag = nil + end + if tag + tag = Tk::Itk::Component.new(self, tagid(tag)) + else + tag = Tk::Itk::Component.new(self) + end + keys = _symbolkey2str(keys) + keys['menu'] = _parse_menu_spec(keys['menu']) if keys.key?('menu') + tk_call(@path, 'insert', index(idx), type, tagid(tag), *hash_kv(keys)) + tag + end + + def invoke(idx) + tk_call(@path, 'invoke', index(idx)) + self + end + + def menupath(pat) + if (win = tk_call(@path, 'path', pat)) == '-1' + return nil + end + window(win) + end + def menupath_glob(pat) + if (win = tk_call(@path, 'path', '-glob', pat)) == '-1' + return nil + end + window(win) + end + def menupath_tclregexp(pat) + if (win = tk_call(@path, 'path', '-regexp', pat)) == '-1' + return nil + end + window(win) + end + + def type(path) + tk_call(@path, 'type', path) + end + + def yposition(path) + number(tk_call(@path, 'yposition', path)) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/messagebox.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/messagebox.rb new file mode 100644 index 0000000..6adb53d --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/messagebox.rb @@ -0,0 +1,93 @@ +# +# tkextlib/iwidgets/messagebox.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Messagebox < Tk::Iwidgets::Scrolledwidget + end + end +end + +class Tk::Iwidgets::Messagebox + TkCommandNames = ['::iwidgets::messagebox'.freeze].freeze + WidgetClassName = 'Messagebox'.freeze + WidgetClassNames[WidgetClassName] ||= self + + #################################### + + include TkItemConfigMethod + + def __item_cget_cmd(id) + [self.path, 'type', 'cget', id] + end + private :__item_cget_cmd + + def __item_config_cmd(id) + [self.path, 'type', 'configure', id] + end + private :__item_config_cmd + + def tagid(tagOrId) + if tagOrId.kind_of?(Tk::Itk::Component) + tagOrId.name + else + #_get_eval_string(tagOrId) + tagOrId + end + end + + def __item_boolval_optkeys(id) + super(id) << 'bell' << 'show' + end + private :__item_boolval_optkeys + + alias typecget_tkstring itemcget_tkstring + alias typecget itemcget + alias typecget_strict itemcget_strict + alias typeconfigure itemconfigure + alias typeconfiginfo itemconfiginfo + alias current_typeconfiginfo current_itemconfiginfo + + private :itemcget_tkstring, :itemcget, :itemcget_strict + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo + + #################################### + + def __strval_optkeys + super() << 'filename' << 'savedir' + end + private :__strval_optkeys + + def type_add(tag=nil, keys={}) + if tag.kind_of?(Hash) + keys = tag + tag = nil + end + unless tag + tag = Tk::Itk::Component.new(self) + end + tk_call(@path, 'type', 'add', tagid(tag), *hash_kv(keys)) + tag + end + + def clear + tk_call(@path, 'clear') + self + end + + def export(file) + tk_call(@path, 'export', file) + self + end + + def issue(string, type=None, *args) + tk_call(@path, 'issue', string, tagid(type), *args) + self + end + +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/messagedialog.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/messagedialog.rb new file mode 100644 index 0000000..9aa5900 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/messagedialog.rb @@ -0,0 +1,20 @@ +# +# tkextlib/iwidgets/messagedialog.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Messagedialog < Tk::Iwidgets::Dialog + end + end +end + +class Tk::Iwidgets::Messagedialog + TkCommandNames = ['::iwidgets::messagedialog'.freeze].freeze + WidgetClassName = 'Messagedialog'.freeze + WidgetClassNames[WidgetClassName] ||= self +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/notebook.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/notebook.rb new file mode 100644 index 0000000..7ed4126 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/notebook.rb @@ -0,0 +1,175 @@ +# +# tkextlib/iwidgets/notebook.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Notebook < Tk::Itk::Widget + end + end +end + +class Tk::Iwidgets::Notebook + TkCommandNames = ['::iwidgets::notebook'.freeze].freeze + WidgetClassName = 'Notebook'.freeze + WidgetClassNames[WidgetClassName] ||= self + + #################################### + + include TkItemConfigMethod + + def __item_cget_cmd(id) + [self.path, 'pagecget', id] + end + private :__item_cget_cmd + + def __item_config_cmd(id) + [self.path, 'pageconfigure', id] + end + private :__item_config_cmd + + def tagid(tagOrId) + if tagOrId.kind_of?(Tk::Itk::Component) + tagOrId.name + else + #_get_eval_string(tagOrId) + tagOrId + end + end + + alias pagecget_tkstring itemcget_tkstring + alias pagecget itemcget + alias pagecget_strict itemcget_strict + alias pageconfigure itemconfigure + alias pageconfiginfo itemconfiginfo + alias current_pageconfiginfo current_itemconfiginfo + + private :itemcget_tkstring, :itemcget, :itemcget_strict + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo + + #################################### + + def __boolval_optkeys + super() << 'auto' + end + private :__boolval_optkeys + + def add(keys={}) + window(tk_call(@path, 'add', *hash_kv(keys))) + end + + def child_site_list + list(tk_call(@path, 'childsite')) + end + + def child_site(idx) + if (new_idx = self.index(idx)) < 0 + new_idx = tagid(idx) + end + window(tk_call(@path, 'childsite', new_idx)) + end + + def delete(idx1, idx2=nil) + if (new_idx1 = self.index(idx1)) < 0 + new_idx1 = tagid(idx1) + end + if idx2 + if (new_idx2 = self.index(idx2)) < 0 + new_idx2 = tagid(idx2) + end + tk_call(@path, 'delete', new_idx1, new_idx2) + else + tk_call(@path, 'delete', new_idx1) + end + self + end + + def index(idx) + number(tk_call(@path, 'index', tagid(idx))) + end + + def insert(idx, keys={}) + if (new_idx = self.index(idx)) < 0 + new_idx = tagid(idx) + end + window(tk_call(@path, 'insert', new_idx, *hash_kv(keys))) + end + + def next + tk_call(@path, 'next') + self + end + + def prev + tk_call(@path, 'prev') + self + end + + def select(idx) + if (new_idx = self.index(idx)) < 0 + new_idx = tagid(idx) + end + tk_call(@path, 'select', new_idx) + self + end + + def scrollcommand(cmd=Proc.new) + configure_cmd 'scrollcommand', cmd + self + end + alias xscrollcommand scrollcommand + alias yscrollcommand scrollcommand + + def xscrollbar(bar=nil) + if bar + @scrollbar = bar + @scrollbar.orient 'horizontal' + self.scrollcommand {|*arg| @scrollbar.set(*arg)} + @scrollbar.command {|*arg| self.xview(*arg)} + Tk.update # avoid scrollbar trouble + end + @scrollbar + end + def yscrollbar(bar=nil) + if bar + @scrollbar = bar + @scrollbar.orient 'vertical' + self.scrollcommand {|*arg| @scrollbar.set(*arg)} + @scrollbar.command {|*arg| self.yview(*arg)} + Tk.update # avoid scrollbar trouble + end + @scrollbar + end + alias scrollbar yscrollbar + + def view(*idxs) + if idxs.size == 0 + idx = num_or_str(tk_send_without_enc('view')) + if idx.kind_of?(Fixnum) && idx < 0 + nil + else + idx + end + else + tk_send_without_enc('view', *idxs) + self + end + end + alias xview view + alias yview view + + def view_moveto(*idxs) + view('moveto', *idxs) + end + alias xview_moveto view_moveto + alias yview_moveto view_moveto + def view_scroll(index, what='pages') + view('scroll', index, what) + end + alias xview_scroll view_scroll + alias yview_scroll view_scroll +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/optionmenu.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/optionmenu.rb new file mode 100644 index 0000000..57a3cc7 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/optionmenu.rb @@ -0,0 +1,92 @@ +# +# tkextlib/iwidgets/optionmenu.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Optionmenu < Tk::Iwidgets::Labeledwidget + end + end +end + +class Tk::Iwidgets::Optionmenu + TkCommandNames = ['::iwidgets::optionmenu'.freeze].freeze + WidgetClassName = 'Optionmenu'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __boolval_optkeys + super() << 'cyclicon' + end + private :__boolval_optkeys + + def delete(first, last=nil) + if last + tk_call(@path, 'delete', first, last) + else + tk_call(@path, 'delete', first) + end + self + end + + def disable(idx) + tk_call(@path, 'disable', idx) + self + end + + def enable(idx) + tk_call(@path, 'enable', idx) + self + end + + def get(first=nil, last=nil) + if last + simplelist(tk_call(@path, 'get', first, last)) + elsif first + tk_call(@path, 'get', first) + else + tk_call(@path, 'get') + end + end + def get_range(first, last) + get(first, last) + end + def get_selected + get() + end + + def index(idx) + number(tk_call(@path, 'index', idx)) + end + + def insert(idx, *args) + tk_call(@path, 'insert', idx, *args) + self + end + + def select(idx) + tk_call(@path, 'select', idx) + self + end + + def sort(*params, &b) + # see 'lsort' man page about params + if b + tk_call(@path, 'sort', '-command', proc(&b), *params) + else + tk_call(@path, 'sort', *params) + end + self + end + def sort_ascending + tk_call(@path, 'sort', 'ascending') + self + end + def sort_descending + tk_call(@path, 'sort', 'descending') + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/panedwindow.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/panedwindow.rb new file mode 100644 index 0000000..65463cc --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/panedwindow.rb @@ -0,0 +1,134 @@ +# +# tkextlib/iwidgets/panedwindow.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Panedwindow < Tk::Itk::Widget + end + end +end + +class Tk::Iwidgets::Panedwindow + TkCommandNames = ['::iwidgets::panedwindow'.freeze].freeze + WidgetClassName = 'Panedwindow'.freeze + WidgetClassNames[WidgetClassName] ||= self + + #################################### + + include TkItemConfigMethod + + def __item_cget_cmd(id) + [self.path, 'panecget', id] + end + private :__item_cget_cmd + + def __item_config_cmd(id) + [self.path, 'paneconfigure', id] + end + private :__item_config_cmd + + def tagid(tagOrId) + if tagOrId.kind_of?(Tk::Itk::Component) + tagOrId.name + else + #_get_eval_string(tagOrId) + tagOrId + end + end + + alias panecget_tkstring itemcget_tkstring + alias panecget itemcget + alias panecget_strict itemcget_strict + alias paneconfigure itemconfigure + alias paneconfiginfo itemconfiginfo + alias current_paneconfiginfo current_itemconfiginfo + + private :itemcget_tkstring, :itemcget, :itemcget_strict + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo + + #################################### + + def __boolval_optkeys + super() << 'showhandle' + end + private :__boolval_optkeys + + def add(tag=nil, keys={}) + if tag.kind_of?(Hash) + keys = tag + tag = nil + end + if tag + tag = Tk::Itk::Component.new(self, tagid(tag)) + else + tag = Tk::Itk::Component.new(self) + end + window(tk_call(@path, 'add', tagid(tag), *hash_kv(keys))) + tag + end + + def child_site_list + list(tk_call(@path, 'childsite')) + end + + def child_site(idx) + window(tk_call(@path, 'childsite', index(idx))) + end + + def delete(idx) + tk_call(@path, 'delete', index(idx)) + self + end + + def fraction(*percentages) + tk_call(@path, 'fraction', *percentages) + self + end + + def hide(idx) + tk_call(@path, 'hide', index(idx)) + self + end + + def index(idx) + number(tk_call(@path, 'index', tagid(idx))) + end + + def insert(idx, tag=nil, keys={}) + if tag.kind_of?(Hash) + keys = tag + tag = nil + end + if tag + tag = Tk::Itk::Component.new(self, tagid(tag)) + else + tag = Tk::Itk::Component.new(self) + end + window(tk_call(@path, 'insert', index(idx), tagid(tag), *hash_kv(keys))) + tag + end + + def invoke(idx=nil) + if idx + tk_call(@path, 'invoke', index(idx)) + else + tk_call(@path, 'invoke') + end + self + end + + def reset + tk_call(@path, 'reset') + self + end + + def show(idx) + tk_call(@path, 'show', index(idx)) + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/promptdialog.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/promptdialog.rb new file mode 100644 index 0000000..7c7ff7a --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/promptdialog.rb @@ -0,0 +1,131 @@ +# +# tkextlib/iwidgets/promptdialog.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Promptdialog < Tk::Iwidgets::Dialog + end + end +end + +class Tk::Iwidgets::Promptdialog + TkCommandNames = ['::iwidgets::promptdialog'.freeze].freeze + WidgetClassName = 'Promptdialog'.freeze + WidgetClassNames[WidgetClassName] ||= self + + # index method is not available, because it shows index of the entry field + def default(name) + tk_call(@path, 'default', tagid(name)) + self + end + + def hide(name) + tk_call(@path, 'hide', tagid(name)) + self + end + + def invoke(name=nil) + if name + tk_call(@path, 'invoke', tagid(name)) + else + tk_call(@path, 'invoke') + end + self + end + + def show(name) + tk_call(@path, 'show', tagid(name)) + self + end + + + # based on Tk::Iwidgets::Entryfield + def clear + tk_call(@path, 'clear') + self + end + + def delete(first, last=None) + tk_send_without_enc('delete', first, last) + self + 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 cursor=(index) + tk_send_without_enc('icursor', index) + #self + index + end + alias icursor cursor= + + def index(idx) + number(tk_send_without_enc('index', idx)) + end + + def insert(pos,text) + tk_send_without_enc('insert', pos, _get_eval_enc_str(text)) + 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 xview(*index) + if index.size == 0 + list(tk_send_without_enc('xview')) + else + tk_send_without_enc('xview', *index) + self + end + end + def xview_moveto(*index) + xview('moveto', *index) + end + def xview_scroll(*index) + xview('scroll', *index) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/pushbutton.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/pushbutton.rb new file mode 100644 index 0000000..ae56788 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/pushbutton.rb @@ -0,0 +1,35 @@ +# +# tkextlib/iwidgets/pushbutton.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Pushbutton < Tk::Itk::Widget + end + end +end + +class Tk::Iwidgets::Pushbutton + TkCommandNames = ['::iwidgets::pushbutton'.freeze].freeze + WidgetClassName = 'Pushbutton'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __boolval_optkeys + super() << 'defaultring' + end + private :__boolval_optkeys + + def invoke + tk_call_without_enc(@path, 'invoke') + self + end + + def flash + tk_call_without_enc(@path, 'flash') + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/radiobox.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/radiobox.rb new file mode 100644 index 0000000..2118177 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/radiobox.rb @@ -0,0 +1,121 @@ +# +# tkextlib/iwidgets/radiobox.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Radiobox < Tk::Iwidgets::Labeledframe + end + end +end + +class Tk::Iwidgets::Radiobox + TkCommandNames = ['::iwidgets::radiobox'.freeze].freeze + WidgetClassName = 'Radiobox'.freeze + WidgetClassNames[WidgetClassName] ||= self + + #################################### + + include TkItemConfigMethod + + def __item_cget_cmd(id) + [self.path, 'buttoncget', id] + end + private :__item_cget_cmd + + def __item_config_cmd(id) + [self.path, 'buttonconfigure', id] + end + private :__item_config_cmd + + def __item_boolval_optkeys(id) + super(id) << 'defaultring' + end + private :__item_boolval_optkeys + + def tagid(tagOrId) + if tagOrId.kind_of?(Tk::Itk::Component) + tagOrId.name + else + #_get_eval_string(tagOrId) + tagOrId + end + end + + alias buttoncget_tkstring itemcget_tkstring + alias buttoncget itemcget + alias buttoncget_strict itemcget_strict + alias buttonconfigure itemconfigure + alias buttonconfiginfo itemconfiginfo + alias current_buttonconfiginfo current_itemconfiginfo + + private :itemcget_tkstring, :itemcget, :itemcget_strict + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo + + #################################### + + def add(tag=nil, keys={}) + if tag.kind_of?(Hash) + keys = tag + tag = nil + end + if tag + tag = Tk::Itk::Component.new(self, tagid(tag)) + else + tag = Tk::Itk::Component.new(self) + end + tk_call(@path, 'add', tagid(tag), *hash_kv(keys)) + tag + end + + def delete(idx) + tk_call(@path, 'delete', index(idx)) + self + end + + def deselect(idx) + tk_call(@path, 'deselect', index(idx)) + self + end + + def flash(idx) + tk_call(@path, 'flash', index(idx)) + self + end + + def get_tag + ((tag = tk_call_without_enc(@path, 'get')).empty?)? nil: tag + end + alias get get_tag + + def get_obj + (tag = get_tag)? Tk::Itk::Component.id2obj(self, tag): nil + end + + def index(idx) + number(tk_call(@path, 'index', tagid(idx))) + end + + def insert(idx, tag=nil, keys={}) + if tag.kind_of?(Hash) + keys = tag + tag = nil + end + if tag + tag = Tk::Itk::Component.new(self, tagid(tag)) + else + tag = Tk::Itk::Component.new(self) + end + tk_call(@path, 'insert', index(idx), tagid(tag), *hash_kv(keys)) + tag + end + + def select(idx) + tk_call(@path, 'select', index(idx)) + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/scopedobject.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/scopedobject.rb new file mode 100644 index 0000000..056cd85 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/scopedobject.rb @@ -0,0 +1,24 @@ +# +# tkextlib/iwidgets/buttonbox.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Scopedobject < TkObject + end + end +end + +class Tk::Iwidgets::Scopedobject + TkCommandNames = ['::iwidgets::scopedobject'.freeze].freeze + WidgetClassName = 'Scopedobject'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def initialize(obj_name, keys={}) + @path = tk_call(self.class::TkCommandNames[0], obj_name, *hash_kv(keys)) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb new file mode 100644 index 0000000..4dea2f2 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb @@ -0,0 +1,353 @@ +# +# tkextlib/iwidgets/scrolledcanvas.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/canvas' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Scrolledcanvas < Tk::Iwidgets::Scrolledwidget + end + end +end + +class Tk::Iwidgets::Scrolledcanvas + TkCommandNames = ['::iwidgets::scrolledcanvas'.freeze].freeze + WidgetClassName = 'Scrolledcanvas'.freeze + WidgetClassNames[WidgetClassName] ||= self + + ################################ + + def __boolval_optkeys + super() << 'autoresize' + end + private :__boolval_optkeys + + def __strval_optkeys + super() << 'textbackground' + end + private :__strval_optkeys + + def initialize(*args) + super(*args) + @canvas = component_widget('canvas') + end + + def method_missing(id, *args) + if @canvas.respond_to?(id) + @canvas.__send__(id, *args) + else + super(id, *args) + end + end + + ################################ + + def child_site + window(tk_call(@path, 'childsite')) + end + + def justify(dir) + tk_call(@path, 'justify', dir) + self + end + + ########################## + include TkCanvasItemConfig + + def tagid(tag) + if tag.kind_of?(TkcItem) || tag.kind_of?(TkcTag) + tag.id + elsif tag.kind_of?(Tk::Itk::Component) + tag.name + else + tag # maybe an Array of configure parameters + end + end + private :tagid + + # create a canvas item without creating a TkcItem object + def create(type, *args) + type.create(self, *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) + # _bind([path, "bind", tagid(tag)], context, cmd, *args) + # self + #end + def itembind(tag, context, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind([path, "bind", tagid(tag)], context, cmd, *args) + self + end + + #def itembind_append(tag, context, cmd=Proc.new, *args) + # _bind_append([path, "bind", tagid(tag)], context, cmd, *args) + # self + #end + def itembind_append(tag, context, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _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)) + self + 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) + tbl = nil + TkcItem::CItemID_TBL.mutex.synchronize{ + tbl = TkcItem::CItemID_TBL[self.path] + } + if tbl + find('withtag', *args).each{|item| + if item.kind_of?(TkcItem) + TkcItem::CItemID_TBL.mutex.synchronize{ + tbl.delete(item.id) + } + end + } + 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, idx) + number(tk_send_without_enc('index', tagid(tagOrId), idx)) + end + + def insert(tagOrId, index, string) + tk_send_without_enc('insert', tagid(tagOrId), index, + _get_eval_enc_str(string)) + self + 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 + + def xview(*index) + if index.size == 0 + list(tk_send_without_enc('xview')) + else + tk_send_without_enc('xview', *index) + self + end + end + def xview_moveto(*index) + xview('moveto', *index) + end + def xview_scroll(*index) + xview('scroll', *index) + 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 yview_moveto(*index) + yview('moveto', *index) + end + def yview_scroll(*index) + yview('scroll', *index) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/scrolledframe.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/scrolledframe.rb new file mode 100644 index 0000000..7b7b95d --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/scrolledframe.rb @@ -0,0 +1,59 @@ +# +# tkextlib/iwidgets/scrolledframe.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Scrolledframe < Tk::Iwidgets::Scrolledwidget + end + end +end + +class Tk::Iwidgets::Scrolledframe + TkCommandNames = ['::iwidgets::scrolledframe'.freeze].freeze + WidgetClassName = 'Scrolledframe'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def child_site + window(tk_call(@path, 'childsite')) + end + + def justify(dir) + tk_call(@path, 'justify', dir) + self + 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 xview_moveto(*index) + xview('moveto', *index) + end + def xview_scroll(*index) + xview('scroll', *index) + 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 yview_moveto(*index) + yview('moveto', *index) + end + def yview_scroll(*index) + yview('scroll', *index) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/scrolledhtml.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/scrolledhtml.rb new file mode 100644 index 0000000..dc2966b --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/scrolledhtml.rb @@ -0,0 +1,58 @@ +# +# tkextlib/iwidgets/scrolledhtml.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Scrolledhtml < Tk::Iwidgets::Scrolledtext + end + end +end + +class Tk::Iwidgets::Scrolledhtml + TkCommandNames = ['::iwidgets::scrolledhtml'.freeze].freeze + WidgetClassName = 'Scrolledhtml'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __boolval_optkeys + super() << 'update' + end + private :__boolval_optkeys + + def __strval_optkeys + super() << 'fontname' << 'link' << 'alink' << 'textbackground' + end + private :__strval_optkeys + + def __font_optkeys + super() << 'fixedfont' + end + private :__font_optkeys + + def import(href) + tk_call(@path, 'import', href) + self + end + + def import_link(href) + tk_call(@path, 'import', '-link', href) + self + end + + def pwd + tk_call(@path, 'pwd') + end + + def render(htmltext, workdir=None) + tk_call(@path, 'render', htmltext, workdir) + self + end + + def title + tk_call(@path, 'title') + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb new file mode 100644 index 0000000..20a4cd1 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb @@ -0,0 +1,207 @@ +# +# tkextlib/iwidgets/scrolledlistbox.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/listbox' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Scrolledlistbox < Tk::Iwidgets::Scrolledwidget + end + end +end + +class Tk::Iwidgets::Scrolledlistbox + TkCommandNames = ['::iwidgets::scrolledlistbox'.freeze].freeze + WidgetClassName = 'Scrolledlistbox'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() << 'textbackground' + end + private :__strval_optkeys + + def __tkvariable_optkeys + super() << 'listvariable' + end + private :__tkvariable_optkeys + + def __font_optkeys + super() << 'textfont' + end + private :__font_optkeys + + ################################ + + def initialize(*args) + super(*args) + @listbox = component_widget('listbox') + end + + def method_missing(id, *args) + if @listbox.respond_to?(id) + @listbox.__send__(id, *args) + else + super(id, *args) + end + end + + ################################ + + def clear + tk_call(@path, 'clear') + self + end + + def get_curselection + tk_call(@path, 'getcurselection') + end + + def justify(dir) + tk_call(@path, 'justify', dir) + self + end + + def selected_item_count + number(tk_call(@path, 'selecteditemcount')) + end + + def sort(*params, &b) + # see 'lsort' man page about params + if b + tk_call(@path, 'sort', '-command', proc(&b), *params) + else + tk_call(@path, 'sort', *params) + end + self + end + def sort_ascending + tk_call(@path, 'sort', 'ascending') + self + end + def sort_descending + tk_call(@path, 'sort', 'descending') + self + end + + ##################################### + + 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 + + ##################################### + + include TkListItemConfig + + def tagid(tag) + if tag.kind_of?(Tk::Itk::Component) + tag.name + else + super(tag) + end + end + private :tagid + + ##################################### + + 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))) + tk_split_simplelist(tk_send_without_enc('get', first, last), + false, true) + 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(idx) + tk_send_without_enc('index', idx).to_i + 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 xview_moveto(*index) + xview('moveto', *index) + end + def xview_scroll(*index) + xview('scroll', *index) + 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 yview_moveto(*index) + yview('moveto', *index) + end + def yview_scroll(*index) + yview('scroll', *index) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb new file mode 100644 index 0000000..69b7d31 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb @@ -0,0 +1,568 @@ +# +# tkextlib/iwidgets/scrolledtext.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/text' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Scrolledtext < Tk::Iwidgets::Scrolledwidget + end + end +end + +class Tk::Iwidgets::Scrolledtext + TkCommandNames = ['::iwidgets::scrolledtext'.freeze].freeze + WidgetClassName = 'Scrolledtext'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() << 'textbackground' + end + private :__strval_optkeys + + def __font_optkeys + super() << 'textfont' + end + private :__font_optkeys + + ################################ + + def initialize(*args) + super(*args) + @text = component_widget('text') + end + + def method_missing(id, *args) + if @text.respond_to?(id) + @text.__send__(id, *args) + else + super(id, *args) + end + end + + ################################ + + def child_site + window(tk_call(@path, 'childsite')) + end + + def clear + tk_call(@path, 'clear') + self + end + + def import(file, idx=nil) + if idx + tk_call(@path, 'import', file, index(idx)) + else + tk_call(@path, 'import', file) + end + self + end + + def export(file) + tk_call(@path, 'export', file) + self + end + + ##################################### + + include TkTextTagConfig + + def tagid(tag) + if tag.kind_of?(Tk::Itk::Component) + tag.name + else + super(tag) + end + end + private :tagid + + def bbox(index) + list(tk_send('bbox', index)) + end + def compare(idx1, op, idx2) + bool(tk_send_without_enc('compare', _get_eval_enc_str(idx1), + op, _get_eval_enc_str(idx2))) + end + + def debug + bool(tk_send_without_enc('debug')) + end + def debug=(boolean) + tk_send_without_enc('debug', boolean) + #self + boolean + end + + def delete(first, last=None) + tk_send_without_enc('delete', first, last) + self + end + + def dlineinfo(index) + list(tk_send_without_enc('dlineinfo', _get_eval_enc_str(index))) + end + + def get(*index) + _fromUTF8(tk_send_without_enc('get', *index)) + end + def get_displaychars(*index) + # Tk8.5 feature + get('-displaychars', *index) + end + + def image_cget_tkstring(index, slot) + _fromUTF8(tk_send_without_enc('image', 'cget', + _get_eval_enc_str(index), "-#{slot.to_s}")) + end + def image_cget_strict(index, slot) + case slot.to_s + when 'text', 'label', 'show', 'data', 'file' + _fromUTF8(tk_send_without_enc('image', 'cget', + _get_eval_enc_str(index), "-#{slot}")) + else + tk_tcl2ruby(_fromUTF8(tk_send_without_enc('image', 'cget', + _get_eval_enc_str(index), + "-#{slot}"))) + end + end + def image_cget(index, slot) + unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + image_cget_strict(index, slot) + else + begin + image_cget_strict(index, slot) + rescue => e + begin + if current_image_configinfo.has_key?(slot.to_s) + # error on known option + fail e + else + # unknown option + nil + end + rescue + fail e # tag error + end + end + end + end + + def image_configure(index, slot, value=None) + if slot.kind_of? Hash + _fromUTF8(tk_send_without_enc('image', 'configure', + _get_eval_enc_str(index), + *hash_kv(slot, true))) + else + _fromUTF8(tk_send_without_enc('image', 'configure', + _get_eval_enc_str(index), + "-#{slot}", + _get_eval_enc_str(value))) + end + self + end + + def image_configinfo(index, slot = nil) + if TkComm::GET_CONFIGINFO_AS_ARRAY + if slot + case slot.to_s + when 'text', 'label', 'show', 'data', 'file' + #conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"))) + conf = tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), false, true) + else + #conf = tk_split_list(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"))) + conf = tk_split_list(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), 0, false, true) + end + conf[0] = conf[0][1..-1] + conf + else + #tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)))).collect{|conflist| + # conf = tk_split_simplelist(conflist) + tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)), false, false).collect{|conflist| + conf = tk_split_simplelist(conflist, false, true) + conf[0] = conf[0][1..-1] + case conf[0] + when 'text', 'label', 'show', 'data', 'file' + 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 + } + end + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY + if slot + case slot.to_s + when 'text', 'label', 'show', 'data', 'file' + #conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"))) + conf = tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), false, true) + else + #conf = tk_split_list(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"))) + conf = tk_split_list(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), 0, false, true) + end + key = conf.shift[1..-1] + { key => conf } + else + ret = {} + #tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)))).each{|conflist| + # conf = tk_split_simplelist(conflist) + tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)), false, false).each{|conflist| + conf = tk_split_simplelist(conflist, false, true) + key = conf.shift[1..-1] + case key + when 'text', 'label', 'show', 'data', 'file' + 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 + } + ret + end + end + end + + def current_image_configinfo(index, slot = nil) + if TkComm::GET_CONFIGINFO_AS_ARRAY + if slot + conf = image_configinfo(index, slot) + {conf[0] => conf[4]} + else + ret = {} + image_configinfo(index).each{|conf| + ret[conf[0]] = conf[4] if conf.size > 2 + } + ret + end + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY + ret = {} + image_configinfo(index, slot).each{|k, conf| + ret[k] = conf[-1] if conf.kind_of?(Array) + } + ret + end + end + + def image_names + #tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'names'))).collect{|elt| + tk_split_simplelist(tk_send_without_enc('image', 'names'), false, true).collect{|elt| + tagid2obj(elt) + } + end + + def index(idx) + tk_send_without_enc('index', _get_eval_enc_str(idx)) + end + + def insert(index, *args) + tk_send('insert', index, *args) + self + end + + def mark_names + #tk_split_simplelist(_fromUTF8(tk_send_without_enc('mark', 'names'))).collect{|elt| + tk_split_simplelist(tk_send_without_enc('mark', 'names'), false, true).collect{|elt| + tagid2obj(elt) + } + end + + def mark_gravity(mark, direction=nil) + if direction + tk_send_without_enc('mark', 'gravity', + _get_eval_enc_str(mark), direction) + self + else + tk_send_without_enc('mark', 'gravity', _get_eval_enc_str(mark)) + end + end + + def mark_set(mark, index) + tk_send_without_enc('mark', 'set', _get_eval_enc_str(mark), + _get_eval_enc_str(index)) + self + end + alias set_mark mark_set + + def mark_unset(*marks) + tk_send_without_enc('mark', 'unset', + *(marks.collect{|mark| _get_eval_enc_str(mark)})) + self + end + alias unset_mark mark_unset + + def mark_next(index) + tagid2obj(_fromUTF8(tk_send_without_enc('mark', 'next', + _get_eval_enc_str(index)))) + end + alias next_mark mark_next + + def mark_previous(index) + tagid2obj(_fromUTF8(tk_send_without_enc('mark', 'previous', + _get_eval_enc_str(index)))) + end + alias previous_mark mark_previous + + 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 _ktext_length(txt) + if TkCore::WITH_ENCODING ### Ruby 1.9 !!!!!!!!!!!!! + return txt.length + end + ########################### + + if $KCODE !~ /n/i + return txt.gsub(/[^\Wa-zA-Z_\d]/, ' ').length + end + + # $KCODE == 'NONE' + if JAPANIZED_TK + tk_call_without_enc('kstring', 'length', + _get_eval_enc_str(txt)).to_i + else + begin + tk_call_without_enc('encoding', 'convertto', 'ascii', + _get_eval_enc_str(txt)).length + rescue StandardError, NameError + # sorry, I have no plan + txt.length + end + end + end + private :_ktext_length + + def tksearch(*args) + # call 'search' subcommand of text widget + # args ::= [<array_of_opts>] <pattern> <start_index> [<stop_index>] + # If <pattern> is regexp, then it must be a regular expression of Tcl + if args[0].kind_of?(Array) + opts = args.shift.collect{|opt| '-' + opt.to_s } + else + opts = [] + end + + opts << '--' + + ret = tk_send('search', *(opts + args)) + if ret == "" + nil + else + ret + end + end + + def tksearch_with_count(*args) + # call 'search' subcommand of text widget + # args ::= [<array_of_opts>] <var> <pattern> <start_index> [<stop_index>] + # If <pattern> is regexp, then it must be a regular expression of Tcl + if args[0].kind_of?(Array) + opts = args.shift.collect{|opt| '-' + opt.to_s } + else + opts = [] + end + + opts << '-count' << args.shift << '--' + + ret = tk_send('search', *(opts + args)) + if ret == "" + nil + else + ret + end + end + + def search_with_length(pat,start,stop=None) + pat = pat.chr if pat.kind_of? Integer + if stop != None + return ["", 0] if compare(start,'>=',stop) + txt = get(start,stop) + if (pos = txt.index(pat)) + match = $& + #pos = txt[0..(pos-1)].split('').length if pos > 0 + pos = _ktext_length(txt[0..(pos-1)]) if pos > 0 + if pat.kind_of? String + #return [index(start + " + #{pos} chars"), pat.split('').length] + return [index(start + " + #{pos} chars"), + _ktext_length(pat), pat.dup] + else + #return [index(start + " + #{pos} chars"), $&.split('').length] + return [index(start + " + #{pos} chars"), + _ktext_length(match), match] + end + else + return ["", 0] + end + else + txt = get(start,'end - 1 char') + if (pos = txt.index(pat)) + match = $& + #pos = txt[0..(pos-1)].split('').length if pos > 0 + pos = _ktext_length(txt[0..(pos-1)]) if pos > 0 + if pat.kind_of? String + #return [index(start + " + #{pos} chars"), pat.split('').length] + return [index(start + " + #{pos} chars"), + _ktext_length(pat), pat.dup] + else + #return [index(start + " + #{pos} chars"), $&.split('').length] + return [index(start + " + #{pos} chars"), + _ktext_length(match), match] + end + else + txt = get('1.0','end - 1 char') + if (pos = txt.index(pat)) + match = $& + #pos = txt[0..(pos-1)].split('').length if pos > 0 + pos = _ktext_length(txt[0..(pos-1)]) if pos > 0 + if pat.kind_of? String + #return [index("1.0 + #{pos} chars"), pat.split('').length] + return [index("1.0 + #{pos} chars"), + _ktext_length(pat), pat.dup] + else + #return [index("1.0 + #{pos} chars"), $&.split('').length] + return [index("1.0 + #{pos} chars"), _ktext_length(match), match] + end + else + return ["", 0] + end + end + end + end + + def search(pat,start,stop=None) + search_with_length(pat,start,stop)[0] + end + + def rsearch_with_length(pat,start,stop=None) + pat = pat.chr if pat.kind_of? Integer + if stop != None + return ["", 0] if compare(start,'<=',stop) + txt = get(stop,start) + if (pos = txt.rindex(pat)) + match = $& + #pos = txt[0..(pos-1)].split('').length if pos > 0 + pos = _ktext_length(txt[0..(pos-1)]) if pos > 0 + if pat.kind_of? String + #return [index(stop + " + #{pos} chars"), pat.split('').length] + return [index(stop + " + #{pos} chars"), _ktext_length(pat), pat.dup] + else + #return [index(stop + " + #{pos} chars"), $&.split('').length] + return [index(stop + " + #{pos} chars"), _ktext_length(match), match] + end + else + return ["", 0] + end + else + txt = get('1.0',start) + if (pos = txt.rindex(pat)) + match = $& + #pos = txt[0..(pos-1)].split('').length if pos > 0 + pos = _ktext_length(txt[0..(pos-1)]) if pos > 0 + if pat.kind_of? String + #return [index("1.0 + #{pos} chars"), pat.split('').length] + return [index("1.0 + #{pos} chars"), _ktext_length(pat), pat.dup] + else + #return [index("1.0 + #{pos} chars"), $&.split('').length] + return [index("1.0 + #{pos} chars"), _ktext_length(match), match] + end + else + txt = get('1.0','end - 1 char') + if (pos = txt.rindex(pat)) + match = $& + #pos = txt[0..(pos-1)].split('').length if pos > 0 + pos = _ktext_length(txt[0..(pos-1)]) if pos > 0 + if pat.kind_of? String + #return [index("1.0 + #{pos} chars"), pat.split('').length] + return [index("1.0 + #{pos} chars"), _ktext_length(pat), pat.dup] + else + #return [index("1.0 + #{pos} chars"), $&.split('').length] + return [index("1.0 + #{pos} chars"), _ktext_length(match), match] + end + else + return ["", 0] + end + end + end + end + + def rsearch(pat,start,stop=None) + rsearch_with_length(pat,start,stop)[0] + end + + def see(index) + tk_send_without_enc('see', index) + self + 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 xview_moveto(*index) + xview('moveto', *index) + end + def xview_scroll(*index) + xview('scroll', *index) + 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 yview_moveto(*index) + yview('moveto', *index) + end + def yview_scroll(*index) + yview('scroll', *index) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/scrolledwidget.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/scrolledwidget.rb new file mode 100644 index 0000000..5ecd2d7 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/scrolledwidget.rb @@ -0,0 +1,20 @@ +# +# tkextlib/iwidgets/scrolledwidget.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Scrolledwidget < Tk::Iwidgets::Labeledwidget + end + end +end + +class Tk::Iwidgets::Scrolledwidget + TkCommandNames = ['::iwidgets::scrolledwidget'.freeze].freeze + WidgetClassName = 'Scrolledwidget'.freeze + WidgetClassNames[WidgetClassName] ||= self +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/selectionbox.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/selectionbox.rb new file mode 100644 index 0000000..eb8fe3a --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/selectionbox.rb @@ -0,0 +1,102 @@ +# +# tkextlib/iwidgets/selectionbox.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Selectionbox < Tk::Itk::Widget + end + end +end + +class Tk::Iwidgets::Selectionbox + TkCommandNames = ['::iwidgets::selectionbox'.freeze].freeze + WidgetClassName = 'Selectionbox'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __boolval_optkeys + super() << 'itemson' << 'selectionon' + end + private :__boolval_optkeys + + def __strval_optkeys + super() << 'itemslabel' << 'selectionlabel' + end + private :__strval_optkeys + + def child_site + window(tk_call(@path, 'childsite')) + end + + def clear_items + tk_call(@path, 'clear', 'items') + self + end + + def clear_selection + tk_call(@path, 'clear', 'selection') + self + end + + def get + tk_call(@path, 'get') + end + + def insert_items(idx, *args) + tk_call(@path, 'insert', 'items', idx, *args) + end + + def insert_selection(pos, text) + tk_call(@path, 'insert', 'selection', pos, text) + end + + def select_item + tk_call(@path, 'selectitem') + self + end + + # based on Tk::Listbox ( and TkTextWin ) + def curselection + list(tk_send_without_enc('curselection')) + end + def delete(first, last=None) + tk_send_without_enc('delete', first, last) + self + end + def index(idx) + tk_send_without_enc('index', idx).to_i + end + def nearest(y) + tk_send_without_enc('nearest', y).to_i + 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 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 size + tk_send_without_enc('size').to_i + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/selectiondialog.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/selectiondialog.rb new file mode 100644 index 0000000..45aecf3 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/selectiondialog.rb @@ -0,0 +1,92 @@ +# +# tkextlib/iwidgets/selectiondialog.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Selectiondialog < Tk::Iwidgets::Dialog + end + end +end + +class Tk::Iwidgets::Selectiondialog + TkCommandNames = ['::iwidgets::selectiondialog'.freeze].freeze + WidgetClassName = 'Selectiondialog'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def child_site + window(tk_call(@path, 'childsite')) + end + + def clear_items + tk_call(@path, 'clear', 'items') + self + end + + def clear_selection + tk_call(@path, 'clear', 'selection') + self + end + + def get + tk_call(@path, 'get') + end + + def insert_items(idx, *args) + tk_call(@path, 'insert', 'items', idx, *args) + end + + def insert_selection(pos, text) + tk_call(@path, 'insert', 'selection', pos, text) + end + + def select_item + tk_call(@path, 'selectitem') + self + end + + # based on Tk::Listbox ( and TkTextWin ) + def curselection + list(tk_send_without_enc('curselection')) + end + def delete(first, last=None) + tk_send_without_enc('delete', first, last) + self + end + def index(idx) + tk_send_without_enc('index', idx).to_i + end + def nearest(y) + tk_send_without_enc('nearest', y).to_i + 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 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 size + tk_send_without_enc('size').to_i + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/setup.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/setup.rb new file mode 100644 index 0000000..ee406c6 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/setup.rb @@ -0,0 +1,8 @@ +# +# setup.rb -- setup script before calling TkPackage.require() +# +# If you need some setup operations (for example, add a library path +# to the library search path) before using Tcl/Tk library packages +# wrapped by Ruby scripts in this directory, please write the setup +# operations in this file. +# diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/shell.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/shell.rb new file mode 100644 index 0000000..c560e3a --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/shell.rb @@ -0,0 +1,38 @@ +# +# tkextlib/iwidgets/shell.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Shell < Tk::Itk::Toplevel + end + end +end + +class Tk::Iwidgets::Shell + TkCommandNames = ['::iwidgets::shell'.freeze].freeze + WidgetClassName = 'Shell'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def activate + tk_call(@path, 'activate') # may return val of deactibate method + end + + def center(win=None) + tk_call(@path, 'center', win) + self + end + + def child_site + window(tk_call(@path, 'childsite')) + end + + def deactivate(val=None) + tk_call(@path, 'deactivate', val) + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/spindate.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/spindate.rb new file mode 100644 index 0000000..b3de9ed --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/spindate.rb @@ -0,0 +1,48 @@ +# +# tkextlib/iwidgets/spindate.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Spindate < Tk::Itk::Widget + end + end +end + +class Tk::Iwidgets::Spindate + TkCommandNames = ['::iwidgets::spindate'.freeze].freeze + WidgetClassName = 'Spindate'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __boolval_optkeys + super() << 'dayon' << 'monthon' << 'yearon' + end + private :__boolval_optkeys + + def __strval_optkeys + super() << 'daylabel' << 'monthformat' << 'monthlabel' << 'yearlabel' + end + private :__strval_optkeys + + def get_string + tk_call(@path, 'get', '-string') + end + alias get get_string + + def get_clicks + number(tk_call(@path, 'get', '-clicks')) + end + + def show(date=None) + tk_call(@path, 'show', date) + self + end + def show_now + tk_call(@path, 'show', 'now') + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/spinint.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/spinint.rb new file mode 100644 index 0000000..bede3bb --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/spinint.rb @@ -0,0 +1,30 @@ +# +# tkextlib/iwidgets/spinint.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Spinint < Tk::Iwidgets::Spinner + end + end +end + +class Tk::Iwidgets::Spinint + TkCommandNames = ['::iwidgets::spinint'.freeze].freeze + WidgetClassName = 'Spinint'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __boolval_optkeys + super() << 'wrap' + end + private :__boolval_optkeys + + def __numlistval_optkeys + super() << 'range' + end + private :__numlistval_optkeys +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/spinner.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/spinner.rb new file mode 100644 index 0000000..d960996 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/spinner.rb @@ -0,0 +1,169 @@ +# +# tkextlib/iwidgets/spinner.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Spinner < Tk::Iwidgets::Labeledwidget + end + end +end + +class Tk::Iwidgets::Spinner + TkCommandNames = ['::iwidgets::spinner'.freeze].freeze + WidgetClassName = 'Spinner'.freeze + WidgetClassNames[WidgetClassName] ||= self + + #################################### + + include Tk::ValidateConfigure + + class EntryfieldValidate < TkValidateCommand + #class CalCmdArgs < TkUtil::CallbackSubst + class ValidateArgs < TkUtil::CallbackSubst + KEY_TBL = [ + [ ?c, ?s, :char ], + [ ?P, ?s, :post ], + [ ?S, ?s, :current ], + [ ?W, ?w, :widget ], + nil + ] + PROC_TBL = [ + [ ?s, TkComm.method(:string) ], + [ ?w, TkComm.method(:window) ], + nil + ] + +=begin + # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) + KEY_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) + end + inf + } + + PROC_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + end + inf + } +=end + + _setup_subst_table(KEY_TBL, PROC_TBL); + end + + def self._config_keys + ['validate', 'invalid'] + end + end + + def __validation_class_list + super() << EntryfieldValidate + end + + Tk::ValidateConfigure.__def_validcmd(binding, EntryfieldValidate) + + #################################### + + def up + tk_call_without_enc(@path, 'up') + self + end + + def down + tk_call_without_enc(@path, 'down') + self + end + + def clear + tk_call_without_enc(@path, 'clear') + self + end + + def delete(first, last=None) + tk_send_without_enc('delete', first, last) + self + 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 cursor=(index) + tk_send_without_enc('icursor', index) + #self + index + end + alias icursor cursor= + + def index(idx) + number(tk_send_without_enc('index', idx)) + end + + def insert(pos,text) + tk_send_without_enc('insert', pos, _get_eval_enc_str(text)) + 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 + + # based on tk/scrollable.rb + def xview(*index) + if index.size == 0 + list(tk_send_without_enc('xview')) + else + tk_send_without_enc('xview', *index) + self + end + end + def xview_moveto(*index) + xview('moveto', *index) + end + def xview_scroll(*index) + xview('scroll', *index) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/spintime.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/spintime.rb new file mode 100644 index 0000000..20f8197 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/spintime.rb @@ -0,0 +1,48 @@ +# +# tkextlib/iwidgets/spintime.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Spintime < Tk::Itk::Widget + end + end +end + +class Tk::Iwidgets::Spintime + TkCommandNames = ['::iwidgets::spintime'.freeze].freeze + WidgetClassName = 'Spintime'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __boolval_optkeys + super() << 'houron' << 'militaryon' << 'minutelabel' << 'secondlabel' + end + private :__boolval_optkeys + + def __strval_optkeys + super() << 'hourlabel' << 'minuteon' << 'secondon' + end + private :__strval_optkeys + + def get_string + tk_call(@path, 'get', '-string') + end + alias get get_string + + def get_clicks + number(tk_call(@path, 'get', '-clicks')) + end + + def show(date=None) + tk_call(@path, 'show', date) + self + end + def show_now + tk_call(@path, 'show', 'now') + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/tabnotebook.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/tabnotebook.rb new file mode 100644 index 0000000..f56efa9 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/tabnotebook.rb @@ -0,0 +1,181 @@ +# +# tkextlib/iwidgets/tabnotebook.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Tabnotebook < Tk::Itk::Widget + end + end +end + +class Tk::Iwidgets::Tabnotebook + TkCommandNames = ['::iwidgets::tabnotebook'.freeze].freeze + WidgetClassName = 'Tabnotebook'.freeze + WidgetClassNames[WidgetClassName] ||= self + + #################################### + + include TkItemConfigMethod + + def __item_cget_cmd(id) + [self.path, 'pagecget', id] + end + private :__item_cget_cmd + + def __item_config_cmd(id) + [self.path, 'pageconfigure', id] + end + private :__item_config_cmd + + def __item_strval_optkeys(id) + super(id) << 'tabbackground' << 'tabforeground' + end + private :__item_strval_optkeys + + def tagid(tagOrId) + if tagOrId.kind_of?(Tk::Itk::Component) + tagOrId.name + else + #_get_eval_string(tagOrId) + tagOrId + end + end + + alias pagecget_tkstring itemcget_tkstring + alias pagecget itemcget + alias pagecget_strict itemcget_strict + alias pageconfigure itemconfigure + alias pageconfiginfo itemconfiginfo + alias current_pageconfiginfo current_itemconfiginfo + + private :itemcget_tkstring, :itemcget, :itemcget_strict + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo + + #################################### + + def __boolval_optkeys + super() << 'auto' << 'equaltabs' << 'raiseselect' << 'tabborders' + end + private :__boolval_optkeys + + def __strval_optkeys + super() << 'backdrop' << 'tabbackground' << 'tabforeground' + end + private :__strval_optkeys + + def initialize(*args) + super(*args) + @tabset = self.component_widget('tabset') + end + + def add(keys={}) + window(tk_call(@path, 'add', *hash_kv(keys))) + end + + def child_site_list + list(tk_call(@path, 'childsite')) + end + + def child_site(idx) + window(tk_call(@path, 'childsite', index(idx))) + end + + def delete(idx1, idx2=nil) + if idx2 + tk_call(@path, 'delete', index(idx1), index(idx2)) + else + tk_call(@path, 'delete', index(idx1)) + end + self + end + + def index(idx) + #number(tk_call(@path, 'index', tagid(idx))) + @tabset.index(tagid(idx)) + end + + def insert(idx, keys={}) + window(tk_call(@path, 'insert', index(idx), *hash_kv(keys))) + end + + def next + tk_call(@path, 'next') + self + end + + def prev + tk_call(@path, 'prev') + self + end + + def select(idx) + tk_call(@path, 'select', index(idx)) + self + end + + def show_tab(idx) + @tabset.show_tab(idx) + self + end + + def scrollcommand(cmd=Proc.new) + configure_cmd 'scrollcommand', cmd + self + end + alias xscrollcommand scrollcommand + alias yscrollcommand scrollcommand + + def xscrollbar(bar=nil) + if bar + @scrollbar = bar + @scrollbar.orient 'horizontal' + self.scrollcommand {|*arg| @scrollbar.set(*arg)} + @scrollbar.command {|*arg| self.xview(*arg)} + Tk.update # avoid scrollbar trouble + end + @scrollbar + end + def yscrollbar(bar=nil) + if bar + @scrollbar = bar + @scrollbar.orient 'vertical' + self.scrollcommand {|*arg| @scrollbar.set(*arg)} + @scrollbar.command {|*arg| self.yview(*arg)} + Tk.update # avoid scrollbar trouble + end + @scrollbar + end + alias scrollbar yscrollbar + + def view(*index) + if index.size == 0 + idx = num_or_str(tk_send_without_enc('view')) + if idx.kind_of?(Fixnum) && idx < 0 + nil + else + idx + end + else + tk_send_without_enc('view', *index) + self + end + end + alias xview view + alias yview view + + def view_moveto(*index) + view('moveto', *index) + end + alias xview_moveto view_moveto + alias yview_moveto view_moveto + def view_scroll(index, what='pages') + view('scroll', index, what) + end + alias xview_scroll view_scroll + alias yview_scroll view_scroll +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/tabset.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/tabset.rb new file mode 100644 index 0000000..501ead4 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/tabset.rb @@ -0,0 +1,145 @@ +# +# tkextlib/iwidgets/tabset.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Tabset < Tk::Itk::Widget + end + end +end + +class Tk::Iwidgets::Tabset + TkCommandNames = ['::iwidgets::tabset'.freeze].freeze + WidgetClassName = 'Tabset'.freeze + WidgetClassNames[WidgetClassName] ||= self + + #################################### + + include TkItemConfigMethod + + def __item_cget_cmd(id) + [self.path, 'tabcget', id] + end + private :__item_cget_cmd + + def __item_config_cmd(id) + [self.path, 'tabconfigure', id] + end + private :__item_config_cmd + + def tagid(tagOrId) + if tagOrId.kind_of?(Tk::Itk::Component) + tagOrId.name + else + #_get_eval_string(tagOrId) + tagOrId + end + end + + alias tabcget_tkstring itemcget_tkstring + alias tabcget itemcget + alias tabcget_strict itemcget_strict + alias tabconfigure itemconfigure + alias tabconfiginfo itemconfiginfo + alias current_tabconfiginfo current_itemconfiginfo + + private :itemcget_tkstring, :itemcget, :itemcget_strict + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo + + #################################### + + def __boolval_optkeys + super() << 'equaltabs' << 'raiseselect' << 'tabborders' + end + private :__boolval_optkeys + + def __strval_optkeys + super() << 'backdrop' + end + private :__strval_optkeys + + def add(keys={}) + window(tk_call(@path, 'add', *hash_kv(keys))) + end + + def delete(idx1, idx2=nil) + if idx2 + tk_call(@path, 'delete', index(idx1), index(idx2)) + else + tk_call(@path, 'delete', index(idx1)) + end + self + end + + def index(idx) + number(tk_call(@path, 'index', tagid(idx))) + end + + def insert(idx, keys={}) + window(tk_call(@path, 'insert', index(idx), *hash_kv(keys))) + end + + def next + tk_call(@path, 'next') + self + end + + def prev + tk_call(@path, 'prev') + self + end + + def select(idx) + tk_call(@path, 'select', index(idx)) + self + end + + def show_tab(idx) + if index(idx) == 0 + self.start = 0 + return + end + + reutrn unless @canvas ||= self.winfo_children[0] + + delta = 1 if (delta = cget(:gap)) == 'overlap' || + (delta = self.winfo_pixels(delta) + 1) <= 0 + + case cget(:tabpos) + when 's', 'n' + if (head = tabcget(idx, :left)) < 0 + self.start -= head + return + end + tabs_size = @canvas.winfo_width + tab_start, tab_end = @canvas . + find_overlapping(head, 0, head + delta, @canvas.winfo_height) . + find_all{|id| @canvas.itemtype(id) == TkcPolygon} . + map!{|id| bbox = @canvas.bbox(id); [bbox[0], bbox[2]]} . max + + when 'e', 'w' + if (head = tabcget(idx, :top)) < 0 + self.start -= head + return + end + tabs_size = @canvas.winfo_height + tab_start, tab_end = @canvas . + find_overlapping(0, head, @canvas.winfo_width, head + delta) . + find_all{|id| @canvas.itemtype(id) == TkcPolygon} . + map!{|id| bbox = @canvas.bbox(id); [bbox[1], bbox[3]]} . max + end + + if (size = tab_end - tab_start + 1) > tabs_size + self.start -= tab_start + elsif head + size > tabs_size + self.start -= head + size - tabs_size + end + + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/timeentry.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/timeentry.rb new file mode 100644 index 0000000..b0afb3a --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/timeentry.rb @@ -0,0 +1,25 @@ +# +# tkextlib/iwidgets/timeentry.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Timeentry < Tk::Iwidgets::Timefield + end + end +end + +class Tk::Iwidgets::Timeentry + TkCommandNames = ['::iwidgets::timeentry'.freeze].freeze + WidgetClassName = 'Timeentry'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __strval_optkeys + super() << 'closetext' + end + private :__strval_optkeys +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/timefield.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/timefield.rb new file mode 100644 index 0000000..c34281d --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/timefield.rb @@ -0,0 +1,58 @@ +# +# tkextlib/iwidgets/timefield.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Timefield < Tk::Iwidgets::Labeledwidget + end + end +end + +class Tk::Iwidgets::Timefield + TkCommandNames = ['::iwidgets::timefield'.freeze].freeze + WidgetClassName = 'Timefield'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __boolval_optkeys + super() << 'gmt' + end + private :__boolval_optkeys + + def __strval_optkeys + super() << 'textbackground' + end + private :__strval_optkeys + + def __font_optkeys + super() << 'textfont' + end + private :__font_optkeys + + def get_string + tk_call(@path, 'get', '-string') + end + alias get get_string + + def get_clicks + number(tk_call(@path, 'get', '-clicks')) + end + + def valid? + bool(tk_call(@path, 'isvalid')) + end + alias isvalid? valid? + + def show(time=None) + tk_call(@path, 'show', time) + self + end + def show_now + tk_call(@path, 'show', 'now') + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/toolbar.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/toolbar.rb new file mode 100644 index 0000000..5b474c3 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/toolbar.rb @@ -0,0 +1,112 @@ +# +# tkextlib/iwidgets/toolbar.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Toolbar < Tk::Itk::Widget + end + end +end + +class Tk::Iwidgets::Toolbar + TkCommandNames = ['::iwidgets::toolbar'.freeze].freeze + WidgetClassName = 'Toolbar'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __tkvariable_optkeys + super() << 'helpvariable' + end + private :__tkvariable_optkeys + + #################################### + + include TkItemConfigMethod + + def __item_cget_cmd(id) + [self.path, 'itemcget', self.index(id)] + end + private :__item_cget_cmd + + def __item_config_cmd(id) + [self.path, 'itemconfigure', self.index(id)] + end + private :__item_config_cmd + + def __item_strval_optkeys(id) + super(id) << 'helpstr' << 'balloonstr' + end + private :__item_strval_optkeys + + def tagid(tagOrId) + if tagOrId.kind_of?(Tk::Itk::Component) + tagOrId.name + else + #_get_eval_string(tagOrId) + tagOrId + end + end + + #################################### + + def __strval_optkeys + super() << 'balloonbackground' << 'balloonforeground' + end + private :__strval_optkeys + + def __tkvariable_optkeys + super() << 'helpvariable' + end + private :__tkvariable_optkeys + + def __font_optkeys + super() << 'balloonfont' + end + private :__font_optkeys + + def add(type, tag=nil, keys={}) + if tag.kind_of?(Hash) + keys = tag + tag = nil + end + if tag + tag = Tk::Itk::Component.new(self, tagid(tag)) + else + tag = Tk::Itk::Component.new(self) + end + window(tk_call(@path, 'add', type, tagid(tag), *hash_kv(keys))) + tag + end + + def delete(idx1, idx2=nil) + if idx2 + tk_call(@path, 'delete', index(idx1), index(idx2)) + else + tk_call(@path, 'delete', index(idx1)) + end + self + end + + def index(idx) + number(tk_call(@path, 'index', tagid(idx))) + end + + def insert(idx, type, tag=nil, keys={}) + if tag.kind_of?(Hash) + keys = tag + tag = nil + end + if tag + tag = Tk::Itk::Component.new(self, tagid(tag)) + else + tag = Tk::Itk::Component.new(self) + end + window(tk_call(@path, 'insert', index(idx), type, + tagid(tag), *hash_kv(keys))) + tag + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/iwidgets/watch.rb b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/watch.rb new file mode 100644 index 0000000..f10ec54 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/iwidgets/watch.rb @@ -0,0 +1,56 @@ +# +# tkextlib/iwidgets/watch.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tkextlib/iwidgets.rb' + +module Tk + module Iwidgets + class Watch < Tk::Itk::Widget + end + end +end + +class Tk::Iwidgets::Watch + TkCommandNames = ['::iwidgets::watch'.freeze].freeze + WidgetClassName = 'Watch'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __boolval_optkeys + super() << 'showampm' + end + private :__boolval_optkeys + + def __strval_optkeys + super() << 'clockcolor' << 'hourcolor' << 'minutecolor' << + 'pivotcolor' << 'secondcolor' << 'tickcolor' + end + private :__strval_optkeys + + def get_string + tk_call(@path, 'get', '-string') + end + alias get get_string + + def get_clicks + number(tk_call(@path, 'get', '-clicks')) + end + + def show(time=None) + tk_call(@path, 'show', time) + self + end + def show_now + tk_call(@path, 'show', 'now') + self + end + + def watch(*args) + unless args.empty? + tk_call(@path, 'watch', *args) + end + component_path('canvas') + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/pkg_checker.rb b/jni/ruby/ext/tk/lib/tkextlib/pkg_checker.rb new file mode 100755 index 0000000..e2fd97b --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/pkg_checker.rb @@ -0,0 +1,184 @@ +#!/usr/bin/env ruby +# +# Ruby/Tk extension library checker +# +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +TkRoot.new.withdraw # hide root window + +name = File.basename(__FILE__) + +add_path = false +verbose = false + +def help_msg + print "Usage: #{$0} [-l] [-v] [-h] [--] [dir]\n" + print "\tIf dir is omitted, check the directory that this command exists.\n" + print "\tAvailable options are \n" + print "\t -l : Add dir to $LOAD_PATH\n" + print "\t (If dir == '<parent>/tkextlib', add <parent> also.)\n" + print "\t -v : Verbose mode (show reason of fail)\n" + print "\t -h : Show this message\n" + print "\t -- : End of options\n" +end + +while(ARGV[0] && ARGV[0][0] == ?-) + case ARGV[0] + when '--' + ARGV.shift + break; + when '-l' + ARGV.shift + add_path = true + when '-v' + ARGV.shift + verbose = true + when '-h' + help_msg + exit(0) + else + print "Argument Error!! : unknown option '#{ARGV[0]}'\n" + help_msg + exit(1) + end +end + +if ARGV[0] + dir = File.expand_path(ARGV[0]) +else + dir = File.dirname(File.expand_path(__FILE__)) +end + +if add_path + $LOAD_PATH.unshift(dir) + if File.basename(dir) == 'tkextlib' + $LOAD_PATH.unshift(File.dirname(dir)) + end +end + +print "\nRuby/Tk extension library checker\n" +print "( Note:: This check is very simple one. Shown status may be wrong. )\n" +print "\n check directory :: #{dir}" +print "\n $LOAD_PATH :: #{$LOAD_PATH.inspect}\n" + +def get_pkg_list(file) + pkg_list = [] + + File.foreach(file){|l| + if l =~ /^(?:[^#]+\s|\s*)(?:|;\s*)TkPackage\s*\.\s*require\s*\(?\s*(["'])((\w|:)+)\1/ + pkg = [$2, :package] + pkg_list << pkg unless pkg_list.member?(pkg) + end + if l =~ /^(?:[^#]+\s|\s*)(?:|;\s*)Tk\s*\.\s*load_tcllibrary\s*\(?\s*(["'])((\w|:)+)\1/ + pkg = [$2, :library] + pkg_list << pkg unless pkg_list.member?(pkg) + end + if l =~ /^(?:[^#]+\s|\s*)(?:|;\s*)Tk\s*\.\s*load_tclscript\s*\(?\s*(["'])((\w|:)+)\1/ + pkg = [$2, :script] + pkg_list << pkg unless pkg_list.member?(pkg) + end + if l =~ /^(?:[^#]+\s|\s*)(?:|;\s*)require\s*\(?\s*(["'])((\w|\/|:)+)\1/ + pkg = [$2, :require_ruby_lib] + pkg_list << pkg unless pkg_list.member?(pkg) + end + } + + pkg_list +end + +def check_pkg(file, verbose=false) + pkg_list = get_pkg_list(file) + + error_list = [] + success_list = {} + + pkg_list.each{|name, type| + next if success_list[name] + + begin + case type + when :package + ver = TkPackage.require(name) + success_list[name] = ver + error_list.delete_if{|n, t| n == name} + + when :library + Tk.load_tcllibrary(name) + success_list[name] = :library + error_list.delete_if{|n, t| n == name} + + when :script + Tk.load_tclscript(name) + success_list[name] = :script + error_list.delete_if{|n, t| n == name} + + when :require_ruby_lib + require name + + end + rescue => e + if verbose + error_list << [name, type, e.message] + else + error_list << [name, type] + end + end + } + + success_list.dup.each{|name, ver| + unless ver.kind_of?(String) + begin + ver = TkPackage.require(name) + sccess_list[name] = ver + rescue + end + end + } + + [success_list, error_list] +end + +def subdir_check(dir, verbose=false) + Dir.foreach(dir){|f| + next if f == '.' || f == '..' + if File.directory?(f) + subdir_check(File.join(dir, f)) + elsif File.extname(f) == '.rb' + path = File.join(dir, f) + suc, err = check_pkg(path, verbose) + if err.empty? + print 'Ready : ', path, ' : require->', suc.inspect, "\n" + else + print '*LACK : ', path, ' : require->', suc.inspect, + ' FAIL->', err.inspect, "\n" + end + end + } +end + +Dir.chdir(dir) + +(Dir['*.rb'] - ['setup.rb', name]).each{|f| + subdir = File.basename(f, '.*') +=begin + begin + # read 'setup.rb' as if the library has standard structure + require File.join(subdir, 'setup.rb') + rescue LoadError + # ignore error + end +=end + print "\n" + + suc, err = check_pkg(f, verbose) + if err.empty? + print 'Ready : ', f, ' : require->', suc.inspect, "\n" + else + print '*LACK : ', f, ' : require->', suc.inspect, + ' FAIL->', err.inspect, "\n" + end + + subdir_check(subdir, verbose) if File.directory?(subdir) +} diff --git a/jni/ruby/ext/tk/lib/tkextlib/setup.rb b/jni/ruby/ext/tk/lib/tkextlib/setup.rb new file mode 100644 index 0000000..79facc5 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/setup.rb @@ -0,0 +1,8 @@ +# +# setup.rb -- setup script before using Tk extension libraries +# +# If you need some setup operations for Tk extensions (for example, +# modify the dynamic library path) required, please write the setup +# operations in this file. This file is required at the last of +# "require 'tk'". +# diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib.rb new file mode 100644 index 0000000..2831989 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib.rb @@ -0,0 +1,105 @@ +# +# tcllib extension support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tcllib/setup.rb' + +err = '' + +# package:: autoscroll +target = 'tkextlib/tcllib/autoscroll' +begin + require target +rescue => e + err << "\n ['" << target << "'] " << e.class.name << ' : ' << e.message +end + +# package:: cursor +target = 'tkextlib/tcllib/cursor' +begin + require target +rescue => e + err << "\n ['" << target << "'] " << e.class.name << ' : ' << e.message +end + +# package:: style +target = 'tkextlib/tcllib/style' +begin + require target +rescue => e + err << "\n ['" << target << "'] " << e.class.name << ' : ' << e.message +end + +# autoload +module Tk + module Tcllib + TkComm::TkExtlibAutoloadModule.unshift(self) + + # package:: autoscroll + autoload :Autoscroll, 'tkextlib/tcllib/autoscroll' + + # package:: ctext + autoload :CText, 'tkextlib/tcllib/ctext' + + # package:: cursor + autoload :Cursor, 'tkextlib/tcllib/cursor' + + # package:: datefield + autoload :Datefield, 'tkextlib/tcllib/datefield' + autoload :DateField, 'tkextlib/tcllib/datefield' + + # package:: getstring + autoload :GetString_Dialog, 'tkextlib/tcllib/getstring' + + # package:: history + autoload :History, 'tkextlib/tcllib/history' + + # package:: ico + autoload :ICO, 'tkextlib/tcllib/ico' + + # package:: ipentry + autoload :IP_Entry, 'tkextlib/tcllib/ip_entry' + autoload :IPEntry, 'tkextlib/tcllib/ip_entry' + + # package:: khim + autoload :KHIM, 'tkextlib/tcllib/khim' + + # package:: ntext + autoload :Ntext, 'tkextlib/tcllib/ntext' + + # package:: Plotchart + autoload :Plotchart, 'tkextlib/tcllib/plotchart' + + # package:: style + autoload :Style, 'tkextlib/tcllib/style' + + # package:: swaplist + autoload :Swaplist_Dialog, 'tkextlib/tcllib/swaplist' + + # package:: tablelist + autoload :Tablelist, 'tkextlib/tcllib/tablelist' + autoload :TableList, 'tkextlib/tcllib/tablelist' + autoload :Tablelist_Tile, 'tkextlib/tcllib/tablelist_tile' + autoload :TableList_Tile, 'tkextlib/tcllib/tablelist_tile' + + # package:: tkpiechart + autoload :Tkpiechart, 'tkextlib/tcllib/tkpiechart' + + # package:: tooltip + autoload :Tooltip, 'tkextlib/tcllib/tooltip' + + # package:: widget + autoload :Widget, 'tkextlib/tcllib/widget' + end +end + +if $VERBOSE && !err.empty? + warn("Warning: some sub-packages are failed to require : " + err) +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/README b/jni/ruby/ext/tk/lib/tkextlib/tcllib/README new file mode 100644 index 0000000..441918a --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/README @@ -0,0 +1,135 @@ + + [ tcllib extension support files ] + +Tcllib includes many utilities. But currently, supports TKLib part +only (see the following 'tcllib contents'). + +If you request to support others, please send your message to one of +ruby-talk/ruby-list/ruby-dev/ruby-ext mailing lists. + +-----<from "What is tcllib?">---------------------------- +Tcllib is a collection of utility modules for Tcl. These modules provide +a wide variety of functionality, from implementations of standard data +structures to implementations of common networking protocols. The intent +is to collect commonly used function into a single library, which users +can rely on to be available and stable. +--------------------------------------------------------- + +-----< tcllib contents (based on tcllib-1.6.1) >--------- +Programming tools + * cmdline - Procedures to process command lines and options. + * comm - A remote communications facility for Tcl (7.6, 8.0, and later) + * control - Procedures for control flow structures. + * fileutil - Procedures implementing some file utilities + * log - Procedures to log messages of libraries and applications. + * logger - System to control logging of events. + * multiplexer - One-to-many communication with sockets. + * snit - Snit's Not Incr Tcl + * snitfaq - Snit Frequently Asked Questions + * stooop - Object oriented extension. + * stoop - Simple Tcl Only Object Oriented Programming + * switched - stooop switched class + * profiler - Tcl source code profiler + +Mathematics + * math::statistics - Basic statistical functions and procedures + * math::calculus - Integration and ordinary differential equations + * math::optimize - Optimisation routines + * math::fuzzy - Fuzzy comparison of floating-point numbers + * counter - Procedures for counters and histograms + * combinatorics - Combinatorial functions in the Tcl Math Library + +Data structures + * struct::list - Procedures for manipulating lists + * struct::set - Procedures for manipulating sets + * struct::stack - Create and manipulate stack objects + * struct::queue - Create and manipulate queue objects + * struct::prioqueue - Create and manipulate prioqueue objects + * struct::skiplist - Create and manipulate skiplists + * struct::tree - Create and manipulate tree objects + * struct::graph - Create and manipulate directed graph objects + * struct::record - Define and create records (similar to 'C' structures) + * struct::matrix - Create and manipulate matrix objects + * struct::pool - Create and manipulate pool objects (of discrete items) + * report - Create and manipulate report objects + +Text processing + * expander - Procedures to process templates and expand text. + * base64 - Procedures to encode and decode base64 + * yencode - encode/decoding a binary file + * uuencode - encode/decoding a binary file + * csv - Procedures to handle CSV data. + * inifile - Parsing of Windows INI files + * htmlparse - Procedures to parse HTML strings + * mime - Manipulation of MIME body parts + * Tcl MIME - generates and parses MIME body parts + * textutil - Procedures to manipulate texts and strings. + * exif - Tcl EXIF extracts and parses EXIF fields from digital images + * EXIF - extract and parse EXIF fields from digital images + +Hashes, checksums, and encryption + * cksum - calculate a cksum(1) compatible checksum + * crc16 - Perform a 16bit Cyclic Redundancy Check + * crc32 - Perform a 32bit Cyclic Redundancy Check + * des - Perform DES encryption of Tcl data + * md4 - MD4 Message-Digest Algorithm + * md5 - MD5 Message-Digest Algorithm + * ripemd160 - RIPEMD-160 Message-Digest Algorithm + * ripemd128 - RIPEMD-128 Message-Digest Algorithm + * md5crypt - MD5-based password encryption + * sha1 - Perform sha1 hashing + * sum - calculate a sum(1) compatible checksum + * soundex - Soundex + +Documentation tools + * mpexpand - Markup processor + * doctools - Create and manipulate doctools converter object + * doctoc_fmt - Specification of simple tcl markup for table of contents + * doctools_api - Interface specification for formatter code + * doctools_fmt - Specification of simple tcl markup for manpages + * docidx - Create and manipulate docidx converter objects + * docidx_api - Interface specification for index formatting code + * docidx_fmt - Specification of simple tcl markup for an index + * doctoc - Create and manipulate doctoc converter objects + * doctoc_api - Interface specification for toc formatting code + * doctools::changelog - Handle text in Emacs ChangeLog format + * doctools::cvs - Handle text in 'cvs log' format + +Networking + * uri - URI utilities + * dns - Tcl Domain Name Service Client + * ntp_time - Tcl Time Service Client + * nntp - Tcl client for the NNTP protocol + * pop3 - Tcl client for POP3 email protocol + * pop3d - Tcl POP3 server implementation + * pop3d::udb - Simple user database for pop3d + * pop3d::dbox - Simple mailbox database for pop3d + * ftp - Client-side tcl implementation of the ftp protocol + * ftp - Client-side tcl implementation of the ftp protocol + * ftpd - Tcl FTP server implementation + * smtp - Client-side tcl implementation of the smtp protocol + * smtpd - Tcl SMTP server implementation + * irc - Create IRC connection and interface. + +CGI programming + * ncgi - Procedures to manipulate CGI values. + * html - Procedures to generate HTML structures + * javascript - Procedures to generate HTML and Java Script structures. + +Grammars and finite automata + * grammar::fa - Create and manipulate finite automatons + * grammar::fa::op - Operations on finite automatons + * grammar::dacceptor - Create and use deterministic acceptors + * grammar::dexec - Execute deterministic finite automatons + +TKLib + * Plotchart - Simple plotting and charting package + * autoscroll - Provides for a scrollbar to automatically mapped and + unmapped as needed + * ctext - An extended text widget with customizable Syntax highlighting + * cursor - Procedures to handle CURSOR data + * datefield - Tk datefield widget + * style - Changes default Tk look&feel + * ipentry - An IP address entry widget + * tkpiechart - Creates and dynamically updates 2D or 3D pie charts +--------------------------------------------------------- diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/autoscroll.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/autoscroll.rb new file mode 100644 index 0000000..2def59b --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/autoscroll.rb @@ -0,0 +1,158 @@ +# +# tkextlib/tcllib/autoscroll.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Provides for a scrollbar to automatically mapped and unmapped as needed +# +# (The following is the original description of the library.) +# +# This package allows scrollbars to be mapped and unmapped as needed +# depending on the size and content of the scrollbars scrolled widget. +# The scrollbar must be managed by either pack or grid, other geometry +# managers are not supported. +# +# When managed by pack, any geometry changes made in the scrollbars parent +# between the time a scrollbar is unmapped, and when it is mapped will be +# lost. It is an error to destroy any of the scrollbars siblings while the +# scrollbar is unmapped. When managed by grid, if anything becomes gridded +# in the same row and column the scrollbar occupied it will be replaced by +# the scrollbar when remapped. +# +# This package may be used on any scrollbar-like widget as long as it +# supports the set subcommand in the same style as scrollbar. If the set +# subcommand is not used then this package will have no effect. +# + +require 'tk' +require 'tk/scrollbar' +require 'tkextlib/tcllib.rb' + +module Tk + module Tcllib + module Autoscroll + PACKAGE_NAME = 'autoscroll'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('autoscroll') + rescue + '' + end + end + + def self.not_available + fail RuntimeError, "'tkextlib/tcllib/autoscroll' extension is not available on your current environment." + end + + def self.autoscroll(win) + Tk::Tcllib::Autoscroll.not_available + end + + def self.unautoscroll(win) + Tk::Tcllib::Autoscroll.not_available + end + end + end +end + +module Tk + module Scrollable + def autoscroll(mode = nil) + case mode + when :x, 'x' + if @xscrollbar + Tk::Tcllib::Autoscroll.autoscroll(@xscrollbar) + end + when :y, 'y' + if @yscrollbar + Tk::Tcllib::Autoscroll.autoscroll(@yscrollbar) + end + when nil, :both, 'both' + if @xscrollbar + Tk::Tcllib::Autoscroll.autoscroll(@xscrollbar) + end + if @yscrollbar + Tk::Tcllib::Autoscroll.autoscroll(@yscrollbar) + end + else + fail ArgumentError, "'x', 'y' or 'both' (String or Symbol) is expected" + end + self + end + def unautoscroll(mode = nil) + case mode + when :x, 'x' + if @xscrollbar + Tk::Tcllib::Autoscroll.unautoscroll(@xscrollbar) + end + when :y, 'y' + if @yscrollbar + Tk::Tcllib::Autoscroll.unautoscroll(@yscrollbar) + end + when nil, :both, 'both' + if @xscrollbar + Tk::Tcllib::Autoscroll.unautoscroll(@xscrollbar) + end + if @yscrollbar + Tk::Tcllib::Autoscroll.unautoscroll(@yscrollbar) + end + else + fail ArgumentError, "'x', 'y' or 'both' (String or Symbol) is expected" + end + self + end + end +end + +class Tk::Scrollbar + def autoscroll + # Arranges for the already existing scrollbar to be mapped + # and unmapped as needed. + #tk_call_without_enc('::autoscroll::autoscroll', @path) + Tk::Tcllib::Autoscroll.autoscroll(self) + self + end + def unautoscroll + # Returns the scrollbar to its original static state. + #tk_call_without_enc('::autoscroll::unautoscroll', @path) + Tk::Tcllib::Autoscroll.unautoscroll(self) + self + end +end + +# TkPackage.require('autoscroll', '1.0') +# TkPackage.require('autoscroll', '1.1') +TkPackage.require('autoscroll') + +module Tk + module Tcllib + class << Autoscroll + undef not_available + end + + module Autoscroll + extend TkCore + def self.autoscroll(win) + tk_call_without_enc('::autoscroll::autoscroll', win.path) + end + + def self.unautoscroll(win) + tk_call_without_enc('::autoscroll::unautoscroll', win.path) + end + + def self.wrap + # v1.1 + tk_call_without_enc('::autoscroll::wrap') + end + + def self.unwrap + # v1.1 + tk_call_without_enc('::autoscroll::unwrap') + end + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/calendar.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/calendar.rb new file mode 100644 index 0000000..b6843df --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/calendar.rb @@ -0,0 +1,55 @@ +# +# tkextlib/tcllib/calendar.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * calendar widget +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('widget::calendar', '0.9') +TkPackage.require('widget::calendar') + +module Tk::Tcllib + module Widget + class Calendar < TkCanvas + PACKAGE_NAME = 'widget::calendar'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('widget::calendar') + rescue + '' + end + end + end + end +end + +class Tk::Tcllib::Widget::Calendar + TkCommandNames = ['::widget::calendar'.freeze].freeze + + def __boolval_optkeys + super() << 'showpast' + end + private :__boolval_optkeys + + def create_self(keys) + if keys and keys != None + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self + + def get(what = 'all') + tk_send('get', what) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/canvas_sqmap.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/canvas_sqmap.rb new file mode 100644 index 0000000..ba87cd3 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/canvas_sqmap.rb @@ -0,0 +1,36 @@ +# +# tkextlib/tcllib/canvas.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('widget::canvas_sqmap', '0.2') +TkPackage.require('widget::canvas_sqmap') + +module Tk::Tcllib + module Widget + class Canvas_Sqmap < Canvas + TkCommandNames = ['::widget::canvas_sqmap'.freeze].freeze + + def image_set(cell, img) + tk_send('image', 'set', cell, img) + self + end + + def image_unset(cell) + tk_send('image', 'unset', cell) + self + end + + def flush + tk_send('flush') + self + end + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/canvas_zoom.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/canvas_zoom.rb new file mode 100644 index 0000000..f4ffb48 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/canvas_zoom.rb @@ -0,0 +1,21 @@ +# +# tkextlib/tcllib/canvas.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('widget::canvas_zoom', '0.1') +TkPackage.require('widget::canvas_zoom') + +module Tk::Tcllib + module Widget + class Canvas_Zoom < Canvas + TkCommandNames = ['::widget::canvas_zoom'.freeze].freeze + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/chatwidget.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/chatwidget.rb new file mode 100644 index 0000000..ddb0340 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/chatwidget.rb @@ -0,0 +1,151 @@ +# +# tkextlib/tcllib/chatwidget.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * chatwidget - Provides a multi-paned view suitable for display of +# chat room or irc channel information +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('chatwidget', '1.1.0') +TkPackage.require('chatwidget') + +module Tk::Tcllib + class ChatWidget < TkText + PACKAGE_NAME = 'chatwidget'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('chatwidget') + rescue + '' + end + end + end +end + +class Tk::Tcllib::ChatWidget + TkCommandNames = ['::chatwidget::chatwidget'.freeze].freeze + + def show_topic + tk_send_without_enc('topic', 'show') + self + end + + def hide_topic + tk_send_without_enc('topic', 'hide') + self + end + + def set_topic(topic) + tk_send('topic', 'set', topic) + end + + def list_name + tk_split_simplelist(tk_send('name', 'list')) + end + + def list_name_full + tk_split_simplelist(tk_send('name', 'list')).map{|lst| + nick, *opts = tk_split_simplelist(lst) + h_opt = {} + opts.slice(2){|k, v| h_opt[k[1..-1]] = tk_tcl2ruby(v)} + [nick, h_opt] + } + end + + def add_name(nick, opts={}) + tk_send('name', 'add', nick, *(hash_kv(opts))) + end + + def delete_name(nick) + tk_send('name', 'delete', nick) + end + + def get_name(nick) + lst = tk_send('name', 'get', nick) + return nil if lst.empty? + nick, *opts = tk_split_simplelist(lst) + h_opt = {} + opts.slice(2){|k, v| h_opt[k[1..-1]] = tk_tcl2ruby(v)} + [nick, h_opt] + end + + def message(msg, opts={}) + tk_send('message', msg, *(hash_kv(opts))) + self + end + + def _parse_hook_list(lst) + tk_split_simplelist(lst).map{|hook| + cmd, prior = tk_split_simplelist(hook) + [procedure(cmd), number(prior)] + } + end + private :_parse_hook_list + + def hook_add(type, *args, &blk) # args -> [prior, cmd], [prior], [cmd] + #type -> 'message', 'post', 'names_group', 'names_nick', 'chatstate', 'url' + + if prior = args.shift + if !prior.kind_of?(Numeric) + cmd = prior + if (prior = args.shift) && !prior.kind_of?(Numeric) # error + args.unshift(prior) + end + args.unshift(cmd) + end + prior ||= 50 # default priority + end + + cmd = args.shift || blk + + fail ArgumentError, "invalid arguments" unless args.empty? + fail ArgumentError, "no callback is given" unless cmd + + _parse_hook_list(tk_send('hook', 'add', type, cmd, prior)) + end + + def hook_remove(type, cmd) + #type -> 'message', 'post', 'names_group', 'names_nick', 'chatstate', 'url' + _parse_hook_list(tk_send('hook', 'remove', type, cmd)) + end + + def hook_run(type, *cmd_args) + #type -> 'message', 'post', 'names_group', 'names_nick', 'chatstate', 'url' + tk_send('hook', 'run', type, *cmd_args) + end + + def hook_list(type) + #type -> 'message', 'post', 'names_group', 'names_nick', 'chatstate', 'url' + _parse_hook_list(tk_send('hook', 'list', type)) + end + + def show_names + tk_send('names', 'show') + self + end + + def hide_names + tk_send('names', 'hide') + self + end + + def names_widget + window(tk_send('names')) + end + + def entry_widget + window(tk_send('entry')) + end + + def chat_widget + window(tk_send('chat')) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/crosshair.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/crosshair.rb new file mode 100644 index 0000000..49b5361 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/crosshair.rb @@ -0,0 +1,117 @@ +# +# tkextlib/tcllib/crosshair.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Crosshairs for Tk canvas +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('crosshair', '1.0.2') +TkPackage.require('crosshair') + +module Tk::Tcllib + module Crosshair + PACKAGE_NAME = 'crosshair'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('crosshair') + rescue + '' + end + end + end +end + +module Tk::Tcllib::Crosshair + include TkCore + TkCommandNames = ['::crosshair::crosshair'.freeze].freeze + + def self.crosshair(w, keys={}) + Tk.tk_call('::crosshair::crosshair', w, *hash_kv(keys)) + w + end + def self.on(w, keys={}) + self.crosshair(w, keys) + end + + def self.off(w) + Tk.tk_call('::crosshair::off', w) + w + end + + def self.track_on(w, &b) + Tk.tk_call('::crosshair::track_on', w, b) + w + end + + def self.track_off(w) + Tk.tk_call('::crosshair::track_off', w) + w + end +end + +class << Tk::Tcllib::Crosshair + include TkComm + include TkCanvasItemConfig + + def __item_methodcall_optkeys(id) + {} + end + private :__item_methodcall_optkeys + + def __item_config_cmd(id) + # maybe need to override + ['::crosshair::configure', id] + end + private :__item_config_cmd + + private :itemcget_tkstring, :itemcget, :itemcget_strict + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo + + def confugure(w, slot, value=None) + itemconfigure(w, slot, value) + end + def confuginfo(w, slot = nil) + itemconfiginfo(w, slot) + end + def current_configinfo(w, slot = nil) + current_itemconfiginfo(w, slot) + end + def cget(w, slot) + current_itemconfiginfo(w, slot).values[0] + end +end + +module Tk::Tcllib::Crosshair + def crosshair_on(keys={}) + Tk::Tcllib::Crosshair.on(self, keys) + end + def crosshair_off + Tk::Tcllib::Crosshair.off(self) + end + def crosshair_track_on(&b) + Tk::Tcllib::Crosshair.track_on(self, &b) + end + def crosshair_track_off + Tk::Tcllib::Crosshair.track_off(self) + end + def crosshair_configure(*args) + Tk::Tcllib::Crosshair.configure(self, *args) + end + def crosshair_configinfo(slot = nil) + Tk::Tcllib::Crosshair.configinfo(self, slot) + end + def crosshair_current_configinfo(slot = nil) + Tk::Tcllib::Crosshair.current_configinfo(self, slot) + end + def crosshair_cget(slot) + Tk::Tcllib::Crosshair.cget(self, slot) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/ctext.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/ctext.rb new file mode 100644 index 0000000..308847c --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/ctext.rb @@ -0,0 +1,160 @@ +# +# tkextlib/tcllib/ctext.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Overloads the text widget and provides new commands +# + +require 'tk' +require 'tk/text' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('ctext', '3.1') +TkPackage.require('ctext') + +module Tk + module Tcllib + class CText < Tk::Text + PACKAGE_NAME = 'ctext'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('ctext') + rescue + '' + end + end + end + end +end + +class Tk::Tcllib::CText + TkCommandNames = ['ctext'.freeze].freeze + WidgetClassName = 'Ctext'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def create_self(keys) + if keys and keys != None + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self + + def __strval_optkeys + super() << 'linemapfg' << 'linemapbg' << + 'linemap_select_fg' << 'linemap_select_bg' + end + private :__strval_optkeys + + def __boolval_optkeys + super() << 'highlight' << 'linemap_markable' + end + private :__boolval_optkeys + + def append(*args) + tk_send('append', *args) + end + + def copy + tk_send('copy') + end + + def cut + tk_send('cut') + end + + def fast_delete(*args) + tk_send('fastdelete', *args) + end + + def fast_insert(*args) + tk_send('fastinsert', *args) + end + + def highlight(*args) + tk_send('highlight', *args) + end + + def paste + tk_send('paste') + end + + def edit(*args) + tk_send('edit', *args) + end + + def add_highlight_class(klass, col, *keywords) + tk_call('ctext::addHighlightClass', @path, klass, col, keywords.flatten) + self + end + + def add_highlight_class_for_special_chars(klass, col, *chrs) + tk_call('ctext::addHighlightClassForSpecialChars', + @path, klass, col, chrs.join('')) + self + end + + def add_highlight_class_for_regexp(klass, col, tcl_regexp) + tk_call('ctext::addHighlightClassForRegexp', + @path, klass, col, tcl_regexp) + self + end + + def add_highlight_class_with_only_char_start(klass, col, chr) + tk_call('ctext::addHighlightClassWithOnlyCharStart', + @path, klass, col, chr) + self + end + + def clear_highlight_classes + tk_call('ctext::clearHighlightClasses', @path) + self + end + + def get_highlight_classes + tk_split_simplelist(tk_call('ctext::getHighlightClasses', @path)) + end + + def delete_highlight_class(klass) + tk_call('ctext::deleteHighlightClass', @path, klass) + self + end + + def enable_C_comments + tk_call('ctext::enableComments', @path) + self + end + + def disable_C_comments + tk_call('ctext::disableComments', @path) + self + end + + def find_next_char(idx, chr) + tk_call('ctext::findNextChar', @path, idx, chr) + end + + def find_next_space(idx) + tk_call('ctext::findNextSpace', @path, idx) + end + + def find_previous_space(idx) + tk_call('ctext::findPreviousSpace', @path, idx) + end + + def set_update_proc(cmd=Proc.new) + tk_call('proc', 'ctext::update', '', cmd) + self + end + + def modified?(mode) + bool(tk_call('ctext::modified', @path, mode)) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/cursor.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/cursor.rb new file mode 100644 index 0000000..5c47f97 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/cursor.rb @@ -0,0 +1,97 @@ +# +# tkextlib/tcllib/cursor.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Procedures to handle CURSOR data +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +module Tk + module Tcllib + module Cursor + PACKAGE_NAME = 'cursor'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('cursor') + rescue + '' + end + end + + def self.not_available + fail RuntimeError, "'tkextlib/tcllib/cursor' extension is not available on your current environment." + end + + def self.cursor_display(win=None) + Tk::Tcllib::Cursor.not_available + end + + def self.cursor_propagate(win, cursor) + Tk::Tcllib::Cursor.not_available + end + + def self.cursor_restore(win, cursor = None) + Tk::Tcllib::Cursor.not_available + end + end + end + + def self.cursor_display(parent=None) + # Pops up a dialog with a listbox containing all the cursor names. + # Selecting a cursor name will display it in that dialog. + # This is simply for viewing any available cursors on the platform . + #tk_call_without_enc('::cursor::display', parent) + Tk::Tcllib::Cursor.cursor_display(parent) + end +end + +class TkWindow + def cursor_propagate(cursor) + # Sets the cursor for self and all its descendants to cursor. + #tk_call_without_enc('::cursor::propagate', @path, cursor) + Tk::Tcllib::Cursor.cursor_propagate(self, cursor) + end + def cursor_restore(cursor = None) + # Restore the original or previously set cursor for self and all its + # descendants. If cursor is specified, that will be used if on any + # widget that did not have a preset cursor (set by a previous call + # to TkWindow#cursor_propagate). + #tk_call_without_enc('::cursor::restore', @path, cursor) + Tk::Tcllib::Cursor.cursor_restore(self, cursor) + end +end + +# TkPackage.require('cursor', '0.1') +TkPackage.require('cursor') + +module Tk + module Tcllib + class << Cursor + undef not_available + end + + module Cursor + extend TkCore + def self.cursor_display(win=None) + tk_call_without_enc('::cursor::display', _epath(win)) + end + + def self.cursor_propagate(win, cursor) + #tk_call_without_enc('::cursor::propagate', win.path, cursor) + tk_call_without_enc('::cursor::propagate', _epath(win), cursor) + end + + def self.cursor_restore(win, cursor = None) + #tk_call_without_enc('::cursor::restore', win.path, cursor) + tk_call_without_enc('::cursor::restore', _epath(win), cursor) + end + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/dateentry.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/dateentry.rb new file mode 100644 index 0000000..77038d9 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/dateentry.rb @@ -0,0 +1,62 @@ +# +# tkextlib/tcllib/dateentry.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * dateentry widget +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('widget::dateentry', '0.91') +TkPackage.require('widget::dateentry') + +module Tk::Tcllib + module Widget + class Dateentry < Tk::Tile::TEntry + PACKAGE_NAME = 'widget::dateentry'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('widget::dateentry') + rescue + '' + end + end + end + DateEntry = Dateentry + end +end + +class Tk::Tcllib::Widget::Dateentry + TkCommandNames = ['::widget::dateentry'.freeze].freeze + + def __strval_optkeys + super() << ['dateformat'] + end + private :__strval_optkeys + + def create_self(keys) + if keys and keys != None + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self + + def post + tk_send('post') + self + end + + def unpost + tk_send('unpost') + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/datefield.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/datefield.rb new file mode 100644 index 0000000..4c2eae7 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/datefield.rb @@ -0,0 +1,57 @@ +# +# tkextlib/tcllib/datefield.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Tk datefield widget +# +# (The following is the original description of the library.) +# +# The datefield package provides the datefield widget which is an enhanced +# text entry widget for the purpose of date entry. Only valid dates of the +# form MM/DD/YYYY can be entered. +# +# The datefield widget is, in fact, just an entry widget with specialized +# bindings. This means all the command and options for an entry widget apply +# equally here. + +require 'tk' +require 'tk/entry' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('datefield', '0.1') +TkPackage.require('datefield') + +module Tk + module Tcllib + class Datefield < Tk::Entry + PACKAGE_NAME = 'datefield'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('datefield') + rescue + '' + end + end + end + DateField = Datefield + end +end + +class Tk::Tcllib::Datefield + TkCommandNames = ['::datefield::datefield'.freeze].freeze + + def create_self(keys) + if keys and keys != None + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/diagrams.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/diagrams.rb new file mode 100644 index 0000000..d24ba9d --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/diagrams.rb @@ -0,0 +1,224 @@ +# +# tkextlib/tcllib/diagrams.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Draw diagrams +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('Diagrams', '0.3') +TkPackage.require('Diagrams') + +module Tk::Tcllib + module Diagrams + PACKAGE_NAME = 'Diagrams'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('Diagrams') + rescue + '' + end + end + end +end + +class << Tk::Tcllib::Diagrams + include TkCore + + def drawin(canvas) + tk_call('::Diagrams::drawin', canvas) + canvas + end + alias draw_in drawin + + def saveps(filename) + tk_call('::Diagrams::saveps', filename) + filename + end + alias save_ps saveps + + def direction(dir) + tk_call('::Diagrams::direction', dir) + dir + end + + def currentpos(pos) + list(tk_call('::Diagrams::currentpos', pos)) + end + alias current_pos currentpos + alias currentpos= currentpos + alias current_pos= currentpos + + def getpos(anchor, obj) + list(tk_call('::Diagrams::getpos', anchor, obj)) + end + alias get_pos getpos + + def position(x, y) + list(tk_call('::Diagrams::position', x, y)) + end + + def box(text, width=nil, height=nil) + if width || height + width = '' unless width + height = '' unless height + list(tk_call('::Diagrams::box', text, width, height)) + else + list(tk_call('::Diagrams::box', text)) + end + end + + def plaintext(text, width=nil, height=nil) + if width || height + width = '' unless width + height = '' unless height + list(tk_call('::Diagrams::plaintext', text, width, height)) + else + list(tk_call('::Diagrams::plaintext', text)) + end + end + + def circle(text, radius=nil) + if radius + list(tk_call('::Diagrams::circle', text, radius)) + else + list(tk_call('::Diagrams::circle', text)) + end + end + + def slanted(text, width=nil, height=nil, angle=nil) + if width || height || angle + width = '' unless width + height = '' unless height + if angle + list(tk_call('::Diagrams::slanted', text, width, height, angle)) + else + list(tk_call('::Diagrams::slanted', text, width, height)) + end + else + list(tk_call('::Diagrams::slanted', text)) + end + end + + def diamond(text, width=nil, height=nil) + if width || height + width = '' unless width + height = '' unless height + list(tk_call('::Diagrams::diamond', text, width, height)) + else + list(tk_call('::Diagrams::diamond', text)) + end + end + + def drum(text, width=nil, height=nil) + if width || height + width = '' unless width + height = '' unless height + list(tk_call('::Diagrams::drum', text, width, height)) + else + list(tk_call('::Diagrams::drum', text)) + end + end + + def arrow(text=nil, length=nil, head=nil) + if length || head + text = '' unless text + length = '' unless length + list(tk_call('::Diagrams::arrow', text, length, head)) + else + if text + list(tk_call('::Diagrams::arrow', text)) + else + list(tk_call('::Diagrams::arrow')) + end + end + end + + def line(*args) + ary = [] + args.each{|arg| + if arg.kind_of?(Array) && arg.length == 2 # [length, angle] + ary.concat arg + else # ["POSITION", x, y] or length or angle + ary << arg + end + } + list(tk_call('::Diagrams::line', *ary)) + end + + def bracket(dir, dist, from_pos, to_pos) + list(tk_call('::Diagrams::bracket', dir, dist, from_pos, to_pos)) + end + + def attach(anchor=None) + tk_call('::Diagrams::attach', anchor) + end + + def color(name=None) + tk_call('::Diagrams::color', name) + end + + def fillcolor(name=None) + tk_call('::Diagrams::fillcolor', name) + end + + def textcolor(name=None) + tk_call('::Diagrams::textcolor', name) + end + + def usegap(mode=None) + bool(tk_call('::Diagrams::usegap', mode)) + end + alias use_gap usegap + + def xgap(val=None) + number(tk_call('::Diagrams::xgap', val)) + end + + def ygap(val=None) + number(tk_call('::Diagrams::ygap', val)) + end + + def textfont(fnt=None) + tk_call('::Diagrams::textfont', fnt) + end + + def linewidth(pixels=None) + number(tk_call('::Diagrams::linewidth', pixels)) + end + + def linestyle(style=None) + tk_call('::Diagrams::linestyle', style) + end + + def pushstate + tk_call('::Diagrams::pushstate') + end + alias push_state pushstate + + def popstate + tk_call('::Diagrams::popstate') + end + alias pop_state popstate + + def computepos + list(tk_call('::Diagrams::computepos')) + end + alias compute_pos computepos + + def boxcoords(x1, y1, x2, y2) + list(tk_call('::Diagrams::boxcoords', x1, y1, x2, y2)) + end + + def moveobject(obj) + list(tk_call('::Diagrams::moveobject', obj)) + end + alias move_object moveobject +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/dialog.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/dialog.rb new file mode 100644 index 0000000..86a0ef2 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/dialog.rb @@ -0,0 +1,84 @@ +# +# tkextlib/tcllib/dialog.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Generic dialog widget (themed) +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('widget::dialog', '1.2') +TkPackage.require('widget::dialog') + +module Tk::Tcllib + module Widget + class Dialog < TkWindow + PACKAGE_NAME = 'widget::dialog'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('widget::dialog') + rescue + '' + end + end + end + end +end + +class Tk::Tcllib::Widget::Dialog + TkCommandNames = ['::widget::dialog'.freeze].freeze + + def __boolval_optkeys + ['separator', 'synchronous', 'transient'] + end + private :__boolval_optkeys + + def create_self(keys) + if keys and keys != None + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self + + def add(what, *args) + window(tk_send('add', *args)) + end + + def get_frame + window(tk_send('getframe')) + end + + def set_widget(widget) + tk_send('setwidget', widget) + self + end + + def display + tk_send('display') + self + end + alias show display + + def cancel + tk_send('cancel') + self + end + + def close(reason = None) + tk_send('close', reason) + end + + def withdraw + tk_send('withdraw') + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/getstring.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/getstring.rb new file mode 100644 index 0000000..48711d3 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/getstring.rb @@ -0,0 +1,134 @@ +# +# tkextlib/tcllib/getstring.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * A dialog which consists of an Entry, OK, and Cancel buttons. +# + +require 'tk' +require 'tk/entry' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('getstring', '0.1') +TkPackage.require('getstring') + +module Tk::Tcllib + class GetString_Dialog < TkWindow + PACKAGE_NAME = 'getstring'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('getstring') + rescue + '' + end + end + end +end + + +class Tk::Tcllib::GetString_Dialog + TkCommandNames = ['::getstring::tk_getString'.freeze].freeze + WidgetClassName = 'TkSDialog'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def self.show(*args) + dialog = self.new(*args) + dialog.show + [dialog.status, dialog.value] + end + def self.display(*args) + self.show(*args) + end + + def initialize(*args) # args = (parent=nil, text='', keys=nil) + keys = args.pop + if keys.kind_of?(Hash) + text = args.pop + @keys = _symbolkey2str(keys) + args.push(keys) + else + text = keys + @keys = {} + end + if text + @text = text.dup + else + @text = '' + end + + @variable = TkVariable.new + @status = nil + + super(*args) + end + + def create_self(keys) + # dummy + end + private :create_self + + def show + @variable.value = '' + @status = bool(tk_call(self.class::TkCommandNames[0], + @path, @variable, @text, *hash_kv(@keys))) + end + alias display show + + def status + @status + end + + def value + @variable.value + end + + def cget_strict(slot) + slot = slot.to_s + if slot == 'text' + @text + else + @keys[slot] + end + end + def cget(slot) + cget_strict(slot) + end + + def configure(slot, value=None) + if slot.kind_of?(Hash) + slot.each{|k, v| configure(k, v)} + else + slot = slot.to_s + value = _symbolkey2str(value) if value.kind_of?(Hash) + if value && value != None + if slot == 'text' + @text = value.to_s + else + @keys[slot] = value + end + else + if slot == 'text' + @text = '' + else + @keys.delete(slot) + end + end + end + self + end + + def configinfo(slot = nil) + if slot + slot = slot.to_s + [ slot, nil, nil, nil, ( (slot == 'text')? @text: @keys[slot] ) ] + else + @keys.collect{|k, v| [ k, nil, nil, nil, v ] } \ + << [ 'text', nil, nil, nil, @text ] + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/history.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/history.rb new file mode 100644 index 0000000..a01a4eb --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/history.rb @@ -0,0 +1,73 @@ +# +# tkextlib/tcllib/history.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Provides a history for Entry widgets +# + +require 'tk' +require 'tk/entry' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('history', '0.1') +TkPackage.require('history') + +module Tk::Tcllib + module History + PACKAGE_NAME = 'history'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('history') + rescue + '' + end + end + end +end + +module Tk::Tcllib::History + extend TkCore + + def self.init(entry, length=None) + tk_call_without_enc('::history::init', entry.path, length) + entry.extend(self) # add methods to treat history to the entry widget + end + + def self.remove(entry) + tk_call_without_enc('::history::remove', entry.path) + entry + end + + def history_remove + tk_call_without_enc('::history::remove', @path) + self + end + + def history_add(text) + tk_call('::history::add', @path, text) + self + end + + def history_get + simplelist(tk_call_without_enc('::history::get', @path)) + end + + def history_clear + tk_call_without_enc('::history::clear', @path) + self + end + + def history_configure(opt, value) + tk_call('::history::configure', @path, opt, value) + self + end + + def history_configinfo(opt) + tk_call('::history::configure', @path, opt) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/ico.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/ico.rb new file mode 100644 index 0000000..36a32c6 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/ico.rb @@ -0,0 +1,146 @@ +# +# tkextlib/tcllib/ico.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Reading and writing windows icons +# + +require 'tk' +require 'tk/image' +#require 'tkextlib/tcllib.rb' + +# TkPackage.require('ico', '0.3') +TkPackage.require('ico') + +module Tk + module Tcllib + class ICO < TkImage + PACKAGE_NAME = 'ico'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('ico') + rescue + '' + end + end + end + end +end + +class Tk::Tcllib::ICO + def self.list(file, keys=nil) + tk_split_list(tk_call_without_enc('::ico::getIconList', file, + *hash_kv(keys, true))) + end + + def self.icons(file, keys=nil) + tk_split_simplelist(tk_call_without_enc('::ico::icons', file, + *hash_kv(keys, true))).map{|elem| + num_or_str(elem) + } + end + + def self.get_members(file, name, keys=nil) + tk_split_simplelist(tk_call_without_enc('::ico::getMembers', file, name, + *hash_kv(keys, true))).map{|elem| + name, width, height, bpp = tk_split_simplelist(elem) + [name, number(width), number(height), number(bpp)] + } + end + + def self.get(file, index, keys=nil) + tk_call_without_enc('::ico::getIcon', file, index, *hash_kv(keys, true)) + end + def self.get_icon(*args) + get(*args) + end + + def self.get_by_name(file, name, keys=nil) + tk_call_without_enc('::ico::getIconByName', file, name, + *hash_kv(keys, true)) + end + def self.get_icon_by_name(*args) + get_by_name(*args) + end + + def self.get_fileicon(file, keys=nil) + tk_call_without_enc('::ico::getFileIcon', file, *hash_kv(keys, true)) + end + + def self.get_image(file, index, keys={}) + keys = _symbolkey2str(keys) + keys.delete('format') + self.new(file, index, keys) + end + + def self.get_data(file, index, keys={}) + keys['format'] = 'data' + tk_split_list(tk_call_without_enc('::ico::getIcon', file, index, + *hash_kv(keys, true))) + end + + def self.write(file, index, depth, data, keys=nil) + tk_call_without_enc('::ico::writeIcon', file, index, depth, data, + *hash_kv(keys, true)) + end + + def self.copy(from_file, from_index, to_file, to_index, keys=nil) + tk_call_without_enc('::ico::copyIcon', + from_file, from_index, to_file, to_index, + *hash_kv(keys, true)) + end + + def self.exe_to_ico(exe_file, ico_file, keys=nil) + tk_call_without_enc('::ico::copyIcon', exe_file, ico_file, + *hash_kv(keys, true)) + end + + def self.clear_cache(file=None) + tk_call_without_enc('::ico::clearCache', file) + end + + def self.transparent_color(image, color) + if image.kind_of?(Array) + tk_split_list(tk_call_without_enc('::ico::transparentColor', + image, color)) + else + tk_call_without_enc('::ico::transparentColor', image, color) + end + end + + def self.show(file, keys=nil) + tk_call_without_enc('::ico::Show', file, *hash_kv(keys, true)) + end + + ########################### + + def initialize(file, index, keys=nil) + keys = _symbolkey2str(keys) + if keys.key?('name') + @path = keys['name'].to_s + else + Tk_Image_ID.mutex.synchronize{ + @path = Tk_Image_ID.join(TkCore::INTERP._ip_id_) + Tk_Image_ID[1].succ! + } + end + tk_call_without_enc('::ico::getIcon', file, index, '-name', @path, + '-format', 'image', *hash_kv(keys, true)) + Tk_IMGTBL[@path] = self + end + + def write(file, index, depth, keys=nil) + Tk::Tcllib::ICO.write(file, index, depth, @path, keys=nil) + self + end + + def transparent_color(color) + tk_call_without_enc('::ico::transparentColor', @path, color) + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/ip_entry.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/ip_entry.rb new file mode 100644 index 0000000..4878cc3 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/ip_entry.rb @@ -0,0 +1,75 @@ +# +# tkextlib/tcllib/ip_entry.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * An IP address entry widget +# +# (The following is the original description of the library.) +# +# This package provides a widget for the entering of a IP address. +# It guarantees a valid address at all times. + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('ipentry', '0.1') +TkPackage.require('ipentry') + +module Tk + module Tcllib + class IP_Entry < Tk::Entry + PACKAGE_NAME = 'ipentry'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('ipentry') + rescue + '' + end + end + end + IPEntry = IP_Entry + + class IP_Entry6 < IP_Entry + end + IPEntry6 = IP_Entry6 + IP6_Entry = IP_Entry6 + end +end + +class Tk::Tcllib::IP_Entry + TkCommandNames = ['::ipentry::ipentry'.freeze].freeze + WidgetClassName = 'IPEntry'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def create_self(keys) + if keys and keys != None + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self + + def __strval_optkeys + super() << 'fg' << 'bg' << 'insertbackground' + end + private :__strval_optkeys + + def complete? + bool(tk_send_without_enc('complete')) + end + + def insert(*ip) + tk_send_without_enc('insert', array2tk_list(ip.flatten)) + end +end + +class Tk::Tcllib::IP_Entry6 < Tk::Tcllib::IP_Entry + TkCommandNames = ['::ipentry::ipentry6'.freeze].freeze +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/khim.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/khim.rb new file mode 100644 index 0000000..5dc2130 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/khim.rb @@ -0,0 +1,68 @@ +# +# tkextlib/tcllib/khim.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Kevin's Hacky Input Method +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('khim', '1.0') +TkPackage.require('khim') + +module Tk::Tcllib + class KHIM < TkToplevel + PACKAGE_NAME = 'khim'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('khim') + rescue + '' + end + end + end +end + +class Tk::Tcllib::KHIM + TkCommandNames = ['::khim::getOptions'.freeze].freeze + + def self.get_options(parent='') + path = parent + '.tcllib_widget_khim_dialog' + self.new(:widgetname => path) + end + + def self.get_config #=> cmd_string + Tk.tk_call_without_enc('::khim::getConfig') + end + + def self.set_config(*args) + if args.length == 1 + # cmd_string generated by + #Tk.ip_eval_without_enc(cmd_string) + Tk.ip_eval(cmd_string) + else + # args for setConfig command + #Tk.tk_call_without_enc('::khim::setConfig', *args) + Tk.tk_call('::khim::setConfig', *args) + end + end + + def self.showHelp + Tk::Tcllib::KHIM::Help.new + end + + def create_self(keys=None) + @db_class = @classname = nil + super(None) # ignore keys + end +end + +class Tk::Tcllib::KHIM::Help < TkToplevel + TkCommandNames = ['::khim::showHelp'.freeze].freeze +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/menuentry.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/menuentry.rb new file mode 100644 index 0000000..f1eb2f2 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/menuentry.rb @@ -0,0 +1,47 @@ +# +# tkextlib/tcllib/menuentry.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * menuentry widget +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('widget::menuentry', '1.0') +TkPackage.require('widget::menuentry') + +module Tk::Tcllib + module Widget + class Menuentry < Tk::Tile::TEntry + PACKAGE_NAME = 'widget::menuentry'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('widget::menuentry') + rescue + '' + end + end + end + MenuEntry = Menuentry + end +end + +class Tk::Tcllib::Widget::Menuentry + TkCommandNames = ['::widget::menuentry'.freeze].freeze + + def create_self(keys) + if keys and keys != None + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/ntext.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/ntext.rb new file mode 100644 index 0000000..7888ed4 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/ntext.rb @@ -0,0 +1,146 @@ +# +# tkextlib/tcllib/ntext.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Ntext bindtag +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('ntext', '0.81') +TkPackage.require('ntext') + +module Tk::Tcllib + Ntext = TkBindTag.new_by_name('Ntext') +end + +# variables +Tk::Tcllib::Ntext.instance_eval{ + # boolean + @classicAnchor = TkVarAccess.new('::ntext::classicAnchor') + @classicExtras = TkVarAccess.new('::ntext::classicExtras') + @classicMouseSelect = TkVarAccess.new('::ntext::classicMouseSelect') + @classicWordBreak = TkVarAccess.new('::ntext::classicWordBreak') + @classicWrap = TkVarAccess.new('::ntext::classicWrap') + @overwrite = TkVarAccess.new('::ntext::overwrite') + + # regexp + @newWrapRegexp = TkVarAccess.new('::ntext::newWrapRegexp') + + # variables (advanced use) + @tcl_match_wordBreakAfter = TkVarAccess.new('::ntext::tcl_match_wordBreakAfter') + @tcl_match_wordBreakBefore = TkVarAccess.new('::ntext::tcl_match_wordBreakBefore') + @tcl_match_endOfWord = TkVarAccess.new('::ntext::tcl_match_endOfWord') + @tcl_match_startOfNextWord = TkVarAccess.new('::ntext::tcl_match_startOfNextWord') + @tcl_match_startOfPreviousWord = TkVarAccess.new('::ntext::tcl_match_startOfPreviousWord') +} + +class << Tk::Tcllib::Ntext + def wrapIndent(txt, *args) + TK.tk_call('::next::wrapIndent', txt, *args) + end + + def initializeMatchPatterns + TK.tk_call('::next::initializeMatchPatterns') + self + end + + def createMatchPatterns(*args) + TK.tk_call('::next::createMatchPatterns', *args) + self + end + + # functions (advanced use) + #ntext::new_wordBreakAfter + #ntext::new_wordBreakBefore + #ntext::new_endOfWord + #ntext::new_startOfNextWord + #ntext::new_startOfPreviousWord + + # accessor + def classicAnchor + @classicAnchor.bool + end + def classicAnchor=(mode) + @classicAnchor.bool = mode + end + + def classicExtras + @classicExtras.bool + end + def classicExtras=(mode) + @classicExtras.bool = mode + end + + def classicMouseSelect + @classicMouseSelect.bool + end + def classicMouseSelect=(mode) + @classicMouseSelect.bool = mode + end + + def classicWordBreak + @classicWordBreak.bool + end + def classicWordBreak=(mode) + @classicWordBreak.bool = mode + end + + def classicWrap + @classicWrap.bool + end + def classicWrap=(mode) + @classicWrap.bool = mode + end + + def overwrite + @overwrite.bool + end + def overwrite=(mode) + @classic.bool = mode + end + + def newWrapRegexp + @newWrapRegexp.value + end + def newWrapRegexp=(val) + @newWrapRegexp.value = val + end + + def tcl_match_wordBreakAfter + @tcl_match_wordBreakAfter.value + end + def tcl_match_wordBreakAfter=(val) + @tcl_match_wordBreakAfter.value = val + end + + def tcl_match_wordBreakBefore + @tcl_match_wordBreakBefore.value + end + def tcl_match_wordBreakBefore=(val) + @tcl_match_wordBreakBefore.value = val + end + + def tcl_match_endOfWord + @tcl_match_endOfWord.value + end + def tcl_match_endOfWord=(val) + @tcl_match_endOfWord.value = val + end + + def tcl_match_startOfNextWord + @tcl_match_startOfNextWord.value + end + def tcl_match_startOfNextWord=(val) + @tcl_match_startOfNextWord.value = val + end + + def tcl_match_startOfPreviousWord + @tcl_match_startOfPreviousWord.value + end + def tcl_match_startOfPreviousWord=(val) + @tcl_match_startOfPreviousWord.value = val + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/panelframe.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/panelframe.rb new file mode 100644 index 0000000..020c51c --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/panelframe.rb @@ -0,0 +1,78 @@ +# +# tkextlib/tcllib/panelframe.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Create PanelFrame widgets. +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('widget::panelframe', '1.0') +TkPackage.require('widget::panelframe') + +module Tk::Tcllib + module Widget + class PanelFrame < TkWindow + PACKAGE_NAME = 'widget::panelframe'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('widget::panelframe') + rescue + '' + end + end + end + Panelframe = PanelFrame + end +end + +class Tk::Tcllib::Widget::PanelFrame + TkCommandNames = ['::widget::panelframe'.freeze].freeze + + def create_self(keys) + if keys and keys != None + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self + + def add(what, *args) + window(tk_send('add', *args)) + end + + #def get_frame + # window(tk_send('getframe')) + #end + + def set_widget(widget) + tk_send('setwidget', widget) + self + end + + def remove(*wins) + tk_send('remove', *wins) + self + end + def remove_destroy(*wins) + tk_send('remove', '-destroy', *wins) + self + end + + def delete(*wins) + tk_send('delete', *wins) + self + end + + def items + simplelist(tk_send('items')).collect!{|w| window(w)} + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/plotchart.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/plotchart.rb new file mode 100644 index 0000000..a1ebe86 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/plotchart.rb @@ -0,0 +1,1404 @@ +# +# tkextlib/tcllib/plotchart.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Simple plotting and charting package +# +# (The following is the original description of the library.) +# +# Plotchart is a Tcl-only package that focuses on the easy creation of +# xy-plots, barcharts and other common types of graphical presentations. +# The emphasis is on ease of use, rather than flexibility. The procedures +# that create a plot use the entire canvas window, making the layout of the +# plot completely automatic. +# +# This results in the creation of an xy-plot in, say, ten lines of code: +# -------------------------------------------------------------------- +# package require Plotchart +# +# canvas .c -background white -width 400 -height 200 +# pack .c -fill both +# +# # +# # Create the plot with its x- and y-axes +# # +# set s [::Plotchart::createXYPlot .c {0.0 100.0 10.0} {0.0 100.0 20.0}] +# +# foreach {x y} {0.0 32.0 10.0 50.0 25.0 60.0 78.0 11.0 } { +# $s plot series1 $x $y +# } +# +# $s title "Data series" +# -------------------------------------------------------------------- +# +# A drawback of the package might be that it does not do any data management. +# So if the canvas that holds the plot is to be resized, the whole plot must +# be redrawn. The advantage, though, is that it offers a number of plot and +# chart types: +# +# * XY-plots like the one shown above with any number of data series. +# * Stripcharts, a kind of XY-plots where the horizontal axis is adjusted +# automatically. The result is a kind of sliding window on the data +# series. +# * Polar plots, where the coordinates are polar instead of cartesian. +# * Isometric plots, where the scale of the coordinates in the two +# directions is always the same, i.e. a circle in world coordinates +# appears as a circle on the screen. +# You can zoom in and out, as well as pan with these plots (Note: this +# works best if no axes are drawn, the zooming and panning routines do +# not distinguish the axes), using the mouse buttons with the control +# key and the arrow keys with the control key. +# * Piecharts, with automatic scaling to indicate the proportions. +# * Barcharts, with either vertical or horizontal bars, stacked bars or +# bars side by side. +# * Timecharts, where bars indicate a time period and milestones or other +# important moments in time are represented by triangles. +# * 3D plots (both for displaying surfaces and 3D bars) +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('Plotchart', '0.9') +# TkPackage.require('Plotchart', '1.1') +# TkPackage.require('Plotchart', '1.6.3') +TkPackage.require('Plotchart') + +module Tk + module Tcllib + module Plotchart + PACKAGE_NAME = 'Plotchart'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('Plotchart') + rescue + '' + end + end + end + end +end + +module Tk::Tcllib::Plotchart + extend TkCore + ############################ + def self.view_port(w, *args) # args := pxmin, pymin, pxmax, pymax + tk_call_without_enc('::Plotchart::viewPort', w.path, *(args.flatten)) + end + + def self.world_coordinates(w, *args) # args := xmin, ymin, xmax, ymax + tk_call_without_enc('::Plotchart::worldCoordinates', + w.path, *(args.flatten)) + end + + def self.world_3D_coordinates(w, *args) + # args := xmin, ymin, zmin, xmax, ymax, zmax + tk_call_without_enc('::Plotchart::world3DCoordinates', + w.path, *(args.flatten)) + end + + def self.coords_to_pixel(w, x, y) + list(tk_call_without_enc('::Plotchart::coordsToPixel', w.path, x, y)) + end + + def self.coords_3D_to_pixel(w, x, y, z) + list(tk_call_without_enc('::Plotchart::coords3DToPixel', w.path, x, y, z)) + end + + def self.plotconfig(*args) + case args.length + when 0, 1, 2 + # 0: (no args) --> list of chat types + # 1: charttype --> list of components + # 2: charttype, component --> list of properties + simplelist(tk_call('::Plotchart::plotconfig', *args)) + when 3 + # 3: charttype, component, property --> current value + tk_call('::Plotchart::plotconfig', *args) + else + # 4: charttype, component, property, value : set new value + # 5+: Error on Tcl/Tk + tk_call('::Plotchart::plotconfig', *args) + nil + end + end + + def self.plotpack(w, dir, *plots) + tk_call_without_enc('::Plotchart::plotpack', w.path, dir, *plots) + w + end + + def self.polar_coordinates(w, radmax) + tk_call_without_enc('::Plotchart::polarCoordinates', w.path, radmax) + end + + def self.polar_to_pixel(w, rad, phi) + list(tk_call_without_enc('::Plotchart::polarToPixel', w.path, rad, phi)) + end + + def self.pixel_to_coords(w, x, y) + list(tk_call_without_enc('::Plotchart::pixelToCoords', w.path, x, y)) + end + + def self.determine_scale(*args) # (xmin, xmax, inverted=false) + tk_call_without_enc('::Plotchart::determineScale', *args) + end + + def self.set_zoom_pan(w) + tk_call_without_enc('::Plotchart::setZoomPan', w.path) + end + + ############################ + module ChartMethod + include TkCore + + def title(str) + tk_call_without_enc(@chart, 'title', _get_eval_enc_str(str)) + self + end + + def save_plot(filename) + tk_call_without_enc(@chart, 'saveplot', filename) + self + end + + def xtext(str) + tk_call_without_enc(@chart, 'xtext', _get_eval_enc_str(str)) + self + end + + def ytext(str) + tk_call_without_enc(@chart, 'ytext', _get_eval_enc_str(str)) + self + end + + def xconfig(key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'xconfig', *hash_kv(key, true)) + else + tk_call(@chart, 'xconfig', "-#{key}",value) + end + self + end + + def yconfig(key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'yconfig', *hash_kv(key, true)) + else + tk_call(@chart, 'yconfig', "-#{key}", value) + end + self + end + + def background(part, color_or_image, dir) + tk_call_without_enc(@chart, 'background', + part, color_or_image, dir) + self + end + + def xticklines(color=None) + tk_call(@chart, 'xticklines', color) + self + end + + def yticklines(color=None) + tk_call(@chart, 'yticklines', color) + self + end + + def legendconfig(key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'legendconfig', *hash_kv(key, true)) + else + tk_call(@chart, 'legendconfig', "-#{key}", value) + end + self + end + + def legend(series, text) + tk_call_without_enc(@chart, 'legend', + _get_eval_enc_str(series), _get_eval_enc_str(text)) + self + end + + def balloon(*args) # args => (x, y, text, dir) or ([x, y], text, dir) + if args[0].kind_of?(Array) + # args => ([x, y], text, dir) + x, y = args.shift + else + # args => (x, y, text, dir) + x = args.shift + y = args.shift + end + + text, dir = args + + tk_call_without_enc(@chart, 'balloon', x, y, + _get_eval_enc_str(text), dir) + self + end + + def balloonconfig(key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'balloonconfig', *hash_kv(key, true)) + else + tk_call(@chart, 'balloonconfig', "-#{key}", value) + end + end + + def plaintext(*args) # args => (x, y, text, dir) or ([x, y], text, dir) + if args[0].kind_of?(Array) + # args => ([x, y], text, dir) + x, y = args.shift + else + # args => (x, y, text, dir) + x = args.shift + y = args.shift + end + + text, dir = args + + tk_call_without_enc(@chart, 'plaintext', x, y, + _get_eval_enc_str(text), dir) + self + end + + ############################ + + def view_port(*args) # args := pxmin, pymin, pxmax, pymax + tk_call_without_enc('::Plotchart::viewPort', @path, *(args.flatten)) + self + end + + def world_coordinates(*args) # args := xmin, ymin, xmax, ymax + tk_call_without_enc('::Plotchart::worldCoordinates', + @path, *(args.flatten)) + self + end + + def world_3D_coordinates(*args) + # args := xmin, ymin, zmin, xmax, ymax, zmax + tk_call_without_enc('::Plotchart::world3DCoordinates', + @path, *(args.flatten)) + self + end + + def coords_to_pixel(x, y) + list(tk_call_without_enc('::Plotchart::coordsToPixel', @path, x, y)) + end + + def coords_3D_to_pixel(x, y, z) + list(tk_call_without_enc('::Plotchart::coords3DToPixel', @path, x, y, z)) + end + + def plotpack(dir, *plots) + tk_call_without_enc('::Plotchart::plotpack', @path, dir, *plots) + self + end + + def polar_coordinates(radmax) + tk_call_without_enc('::Plotchart::polarCoordinates', @path, radmax) + self + end + + def polar_to_pixel(rad, phi) + list(tk_call_without_enc('::Plotchart::polarToPixel', @path, rad, phi)) + end + + def pixel_to_coords(x, y) + list(tk_call_without_enc('::Plotchart::pixelToCoords', @path, x, y)) + end + + def determine_scale(xmax, ymax) + tk_call_without_enc('::Plotchart::determineScale', @path, xmax, ymax) + self + end + + def set_zoom_pan() + tk_call_without_enc('::Plotchart::setZoomPan', @path) + self + end + end + + ############################ + class XYPlot < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createXYPlot'.freeze + ].freeze + + def initialize(*args) # args := ([parent,] xaxis, yaxis [, keys]) + # xaxis := Array of [minimum, maximum, stepsize] + # yaxis := Array of [minimum, maximum, stepsize] + if args[0].kind_of?(Array) + @xaxis = args.shift + @yaxis = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @xaxis = args.shift + @yaxis = args.shift + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + array2tk_list(@xaxis), array2tk_list(@yaxis)) + end + private :_create_chart + + def __destroy_hook__ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path) + } + end + + def plot(series, x, y) + tk_call_without_enc(@chart, 'plot', _get_eval_enc_str(series), x, y) + self + end + + def contourlines(xcrd, ycrd, vals, clss=None) + xcrd = array2tk_list(xcrd) if xcrd.kind_of?(Array) + ycrd = array2tk_list(ycrd) if ycrd.kind_of?(Array) + vals = array2tk_list(vals) if vals.kind_of?(Array) + clss = array2tk_list(clss) if clss.kind_of?(Array) + + tk_call(@chart, 'contourlines', xcrd, ycrd, vals, clss) + self + end + + def contourfill(xcrd, ycrd, vals, clss=None) + xcrd = array2tk_list(xcrd) if xcrd.kind_of?(Array) + ycrd = array2tk_list(ycrd) if ycrd.kind_of?(Array) + vals = array2tk_list(vals) if vals.kind_of?(Array) + clss = array2tk_list(clss) if clss.kind_of?(Array) + + tk_call(@chart, 'contourfill', xcrd, ycrd, vals, clss) + self + end + + def contourbox(xcrd, ycrd, vals, clss=None) + xcrd = array2tk_list(xcrd) if xcrd.kind_of?(Array) + ycrd = array2tk_list(ycrd) if ycrd.kind_of?(Array) + vals = array2tk_list(vals) if vals.kind_of?(Array) + clss = array2tk_list(clss) if clss.kind_of?(Array) + + tk_call(@chart, 'contourbox', xcrd, ycrd, vals, clss) + self + end + + def color_map(colors) + colors = array2tk_list(colors) if colors.kind_of?(Array) + + tk_call_without_enc(@chart, 'colorMap', colors) + self + end + + def grid_cells(xcrd, ycrd) + xcrd = array2tk_list(xcrd) if xcrd.kind_of?(Array) + ycrd = array2tk_list(ycrd) if ycrd.kind_of?(Array) + + tk_call_without_enc(@chart, 'grid', xcrd, ycrd) + self + end + + def dataconfig(series, key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'dataconfig', series, *hash_kv(key, true)) + else + tk_call(@chart, 'dataconfig', series, "-#{key}", value) + end + end + + def rescale(xscale, yscale) # xscale|yscale => [newmin, newmax, newstep] + tk_call_without_enc(@chart, 'rescale', xscale, yscale) + self + end + + def trend(series, xcrd, ycrd) + tk_call_without_enc(@chart, 'trend', + _get_eval_enc_str(series), xcrd, ycrd) + self + end + + def rchart(series, xcrd, ycrd) + tk_call_without_enc(@chart, 'rchart', + _get_eval_enc_str(series), xcrd, ycrd) + self + end + + def interval(series, xcrd, ymin, ymax, ycenter=None) + tk_call(@chart, 'interval', series, xcrd, ymin, ymax, ycenter) + self + end + + def box_and_whiskers(series, xcrd, ycrd) + tk_call_without_enc(@chart, 'box-and-whiskers', + _get_eval_enc_str(series), xcrd, ycrd) + self + end + alias box_whiskers box_and_whiskers + + def vectorconfig(series, key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'vectorconfig', + _get_eval_enc_str(series), *hash_kv(key, true)) + else + tk_call(@chart, 'vectorconfig', series, "-#{key}", value) + end + self + end + + def vector(series, xcrd, ycrd, ucmp, vcmp) + tk_call_without_enc(@chart, 'vector', _get_eval_enc_str(series), + xcrd, ycrd, ucmp, vcmp) + self + end + + def dotconfig(series, key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'dotconfig', + _get_eval_enc_str(series), *hash_kv(key, true)) + else + tk_call(@chart, 'dotconfig', series, "-#{key}", value) + end + self + end + + def dot(series, xcrd, ycrd, value) + tk_call_without_enc(@chart, 'dot', _get_eval_enc_str(series), + xcrd, ycrd, value) + self + end + end + + ############################ + class Stripchart < XYPlot + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createStripchart'.freeze + ].freeze + end + + ############################ + class TXPlot < XYPlot + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createTXPlot'.freeze + ].freeze + end + + ############################ + class XLogYPlot < XYPlot + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createXLogYPlot'.freeze + ].freeze + end + + ############################ + class Histogram < XYPlot + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createHistogram'.freeze + ].freeze + end + + ############################ + class PolarPlot < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createPolarplot'.freeze + ].freeze + + def initialize(*args) # args := ([parent,] radius_data [, keys]) + # radius_data := Array of [maximum_radius, stepsize] + if args[0].kind_of?(Array) + @radius_data = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @radius_data = args.shift + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + array2tk_list(@radius_data)) + end + private :_create_chart + + def __destroy_hook__ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path) + } + end + + def plot(series, radius, angle) + tk_call_without_enc(@chart, 'plot', _get_eval_enc_str(series), + radius, angle) + self + end + + def dataconfig(series, key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'dataconfig', _get_eval_enc_str(series), + *hash_kv(key, true)) + else + tk_call(@chart, 'dataconfig', series, "-#{key}", value) + end + end + end + Polarplot = PolarPlot + + ############################ + class IsometricPlot < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createIsometricPlot'.freeze + ].freeze + + def initialize(*args) # args := ([parent,] xaxis, yaxis, [, step] [, keys]) + # xaxis := Array of [minimum, maximum] + # yaxis := Array of [minimum, maximum] + # step := Float of stepsize | "noaxes" | :noaxes + if args[0].kind_of?(Array) + @xaxis = args.shift + @yaxis = args.shift + + if args[0].kind_of?(Hash) + @stepsize = :noaxes + else + @stepsize = args.shift + end + + super(*args) # create canvas widget + else + parent = args.shift + + @xaxis = args.shift + @yaxis = args.shift + + if args[0].kind_of?(Hash) + @stepsize = :noaxes + else + @stepsize = args.shift + end + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + array2tk_list(@xaxis), array2tk_list(@yaxis), + @stepsize) + end + private :_create_chart + + def plot(type, *args) + self.__send__("plot_#{type.to_s.tr('-', '_')}", *args) + end + + def plot_rectangle(*args) # args := x1, y1, x2, y2, color + tk_call_without_enc(@chart, 'plot', 'rectangle', *(args.flatten)) + self + end + + def plot_filled_rectangle(*args) # args := x1, y1, x2, y2, color + tk_call_without_enc(@chart, 'plot', 'filled-rectangle', *(args.flatten)) + self + end + + def plot_circle(*args) # args := xc, yc, radius, color + tk_call_without_enc(@chart, 'plot', 'circle', *(args.flatten)) + self + end + + def plot_filled_circle(*args) # args := xc, yc, radius, color + tk_call_without_enc(@chart, 'plot', 'filled-circle', *(args.flatten)) + self + end + end + Isometricplot = IsometricPlot + + ############################ + class Plot3D < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::create3DPlot'.freeze + ].freeze + + def initialize(*args) # args := ([parent,] xaxis, yaxis, zaxis [, keys]) + # xaxis := Array of [minimum, maximum, stepsize] + # yaxis := Array of [minimum, maximum, stepsize] + # zaxis := Array of [minimum, maximum, stepsize] + if args[0].kind_of?(Array) + @xaxis = args.shift + @yaxis = args.shift + @zaxis = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @xaxis = args.shift + @yaxis = args.shift + @zaxis = args.shift + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + array2tk_list(@xaxis), + array2tk_list(@yaxis), + array2tk_list(@zaxis)) + end + private :_create_chart + + def plot_function(cmd=Proc.new) + Tk.ip_eval("proc #{@path}_#{@chart} {x y} {#{install_cmd(cmd)} $x $y}") + tk_call_without_enc(@chart, 'plotfunc', "#{@path}_#{@chart}") + self + end + + def plot_funcont(conts, cmd=Proc.new) + conts = array2tk_list(conts) if conts.kind_of?(Array) + Tk.ip_eval("proc #{@path}_#{@chart} {x y} {#{install_cmd(cmd)} $x $y}") + tk_call_without_enc(@chart, 'plotfuncont', "#{@path}_#{@chart}", conts) + self + end + + def grid_size(nxcells, nycells) + tk_call_without_enc(@chart, 'gridsize', nxcells, nycells) + self + end + + def plot_line(dat, color) + # dat has to be provided as a 2 level array. + # 1st level contains rows, drawn in y-direction, + # and each row is an array whose elements are drawn in x-direction, + # for the columns. + tk_call_without_enc(@chart, 'plotline', dat, color) + self + end + + def plot_data(dat) + # dat has to be provided as a 2 level array. + # 1st level contains rows, drawn in y-direction, + # and each row is an array whose elements are drawn in x-direction, + # for the columns. + tk_call_without_enc(@chart, 'plotdata', dat) + self + end + + def zconfig(key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'zconfig', *hash_kv(key, true)) + else + tk_call(@chart, 'zconfig', "-#{key}", value) + end + self + end + + def colour(fill, border) + # configure the colours to use for polygon borders and inner area + tk_call_without_enc(@chart, 'colour', fill, border) + self + end + alias colours colour + alias colors colour + alias color colour + end + + ############################ + class Barchart3D < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::create3DBarchart'.freeze + ].freeze + + def initialize(*args) # args := ([parent,] yaxis, nobars [, keys]) + # yaxis := Array of [minimum, maximum, stepsize] + # nobars := number of bars + if args[0].kind_of?(Array) + @yaxis = args.shift + @nobars = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @yaxis = args.shift + @nobars = args.shift + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + array2tk_list(@yaxis), @nobars) + end + private :_create_chart + + def plot(label, yvalue, color) + tk_call_without_enc(@chart, 'plot', _get_eval_enc_str(label), + _get_eval_enc_str(yvalue), color) + self + end + + def config(key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'config', *hash_kv(key, true)) + else + tk_call(@chart, 'config', "-#{key}", value) + end + self + end + end + + ############################ + class RibbonChart3D < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::create3DRibbonChart'.freeze + ].freeze + + def initialize(*args) # args := ([parent,] names, yaxis, zaxis [, keys]) + # names := Array of the series + # yaxis := Array of [minimum, maximum, stepsize] + # zaxis := Array of [minimum, maximum, stepsize] + if args[0].kind_of?(Array) + @names = args.shift + @yaxis = args.shift + @zaxis = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @names = args.shift + @yaxis = args.shift + @zaxis = args.shift + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + array2tk_list(@names), + array2tk_list(@yaxis), + array2tk_list(@zaxis)) + end + private :_create_chart + + def line(*args) # xypairs, color + color = args.pop # last argument is a color + xypairs = TkComm.slice_ary(args.flatten, 2) # regenerate xypairs + tk_call_without_enc(@chart, 'line', xypairs, color) + self + end + + def area(*args) # xypairs, color + color = args.pop # last argument is a color + xypairs = TkComm.slice_ary(args.flatten, 2) # regenerate xypairs + tk_call_without_enc(@chart, 'area', xypairs, color) + self + end + + def zconfig(key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'zconfig', *hash_kv(key, true)) + else + tk_call(@chart, 'zconfig',"-#{key}", value) + end + self + end + end + + + ############################ + class Piechart < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createPiechart'.freeze + ].freeze + + def initialize(*args) # args := ([parent] [, keys]) + if args[0].kind_of?(Tk::Canvas) + parent = args.shift + @path = parent.path + else + super(*args) # create canvas widget + end + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path) + end + private :_create_chart + + def plot(*dat) # argument is a list of [label, value] + tk_call(@chart, 'plot', dat.flatten) + self + end + + def colours(*list) + tk_call_without_enc(@chart, 'colours', *list) + self + end + alias colors colours + end + + + ############################ + class Radialchart < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createRadialchart'.freeze + ].freeze + + def initialize(*args) # args := ([parent,] names, scale, style [, keys]) + # radius_data := Array of [maximum_radius, stepsize] + if args[0].kind_of?(Array) + @names = args.shift + @scale = args.shift + @style = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @names = args.shift + @scale = args.shift + @style = args.shift + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + array2tk_list(@names), @scale, @style) + end + private :_create_chart + + def __destroy_hook__ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path) + } + end + + def plot(data, color, thickness) + tk_call_without_enc(@chart, 'plot', _get_eval_enc_str(data), + color, thickness) + self + end + + def colours(*list) + tk_call_without_enc(@chart, 'colours', *list) + self + end + alias colors colours + end + + ############################ + class Barchart < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createBarchart'.freeze + ].freeze + + def initialize(*args) + # args := ([parent,] xlabels, ylabels [, series] [, keys]) + # xlabels, ylabels := labels | axis ( depend on normal or horizontal ) + # labels := Array of [label, label, ...] + # (It determines the number of bars that will be plotted per series.) + # axis := Array of [minimum, maximum, stepsize] + # series := Integer number of data series | 'stacked' | :stacked + if args[0].kind_of?(Array) + @xlabels = args.shift + @ylabels = args.shift + + if args[0].kind_of?(Hash) + @series_size = :stacked + else + @series_size = args.shift + end + + super(*args) # create canvas widget + else + parent = args.shift + + @xlabels = args.shift + @ylabels = args.shift + + if args[0].kind_of?(Hash) + @series_size = :stacked + else + @series_size = args.shift + end + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + array2tk_list(@xlabels), array2tk_list(@ylabels), + @series_size) + end + private :_create_chart + + def __destroy_hook__ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path) + } + end + + def plot(series, dat, col=None) + tk_call(@chart, 'plot', series, dat, col) + self + end + + def colours(*cols) + # set the colours to be used + tk_call(@chart, 'colours', *cols) + self + end + alias colour colours + alias colors colours + alias color colours + end + + ############################ + class HorizontalBarchart < Barchart + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createHorizontalBarchart'.freeze + ].freeze + end + + ############################ + class Boxplot < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createBoxplot'.freeze + ].freeze + + def initialize(*args) # args := ([parent,] xaxis, ylabels [, keys]) + # xaxis := Array of [minimum, maximum, stepsize] + # yaxis := List of labels for the y-axis + if args[0].kind_of?(Array) + @xaxis = args.shift + @ylabels = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @xaxis = args.shift + @ylabels = args.shift + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + array2tk_list(@xaxis), array2tk_list(@ylabels)) + end + private :_create_chart + + def __destroy_hook__ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path) + } + end + + def plot(label, *values) + tk_call(@chart, 'plot', label, values.flatten) + self + end + end + + ############################ + class RightAxis < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createRightAxis'.freeze + ].freeze + + def initialize(*args) # args := ([parent,] yaxis [, keys]) + # yaxis := Array of [minimum, maximum, stepsize] + if args[0].kind_of?(Array) + @yaxis = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @yaxis = args.shift + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + array2tk_list(@yaxis)) + end + private :_create_chart + + def __destroy_hook__ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path) + } + end + end + + ############################ + class Timechart < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createTimechart'.freeze + ].freeze + + def initialize(*args) + # args := ([parent,] time_begin, time_end, items [, keys]) + # time_begin := String of time format (e.g. "1 january 2004") + # time_end := String of time format (e.g. "1 january 2004") + # items := Expected/maximum number of items + # ( This determines the vertical spacing. ) + if args[0].kind_of?(String) + @time_begin = args.shift + @time_end = args.shift + @items = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @time_begin = args.shift + @time_end = args.shift + @items = args.shift + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + @time_begin, @time_end, @items) + end + private :_create_chart + + def period(txt, time_begin, time_end, col=None) + tk_call(@chart, 'period', txt, time_begin, time_end, col) + self + end + + def milestone(txt, time, col=None) + tk_call(@chart, 'milestone', txt, time, col) + self + end + + def vertline(txt, time) + tk_call(@chart, 'vertline', txt, time) + self + end + + def hscroll=(scr) + tk_call_without_enc(@chart, 'hscroll', scr) + scr + end + def hscroll(scr) + tk_call_without_enc(@chart, 'hscroll', scr) + self + end + + def vscroll=(scr) + tk_call_without_enc(@chart, 'vscroll', scr) + scr + end + def vscroll(scr) + tk_call_without_enc(@chart, 'vscroll', scr) + self + end + end + + ############################ + class Ganttchart < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createGanttchart'.freeze + ].freeze + + def initialize(*args) + # args := ([parent,] time_begin, time_end, items [, text_width] [, keys]) + # time_begin := String of time format (e.g. "1 january 2004") + # time_end := String of time format (e.g. "1 january 2004") + # args := Expected/maximum number of items + # ( This determines the vertical spacing. ), + # Expected/maximum width of items, + # Option Hash ( { key=>value, ... } ) + if args[0].kind_of?(String) + @time_begin = args.shift + @time_end = args.shift + @args = args + + super(*args) # create canvas widget + else + parent = args.shift + + @time_begin = args.shift + @time_end = args.shift + @args = args + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call(self.class::TkCommandNames[1], @path, + @time_begin, @time_end, *args) + end + private :_create_chart + + def task(txt, time_begin, time_end, completed=0.0) + list(tk_call(@chart, 'task', txt, time_begin, time_end, + completed)).collect!{|id| + TkcItem.id2obj(self, id) + } + end + + def milestone(txt, time, col=None) + tk_call(@chart, 'milestone', txt, time, col) + self + end + + def vertline(txt, time) + tk_call(@chart, 'vertline', txt, time) + self + end + + def connect(from_task, to_task) + from_task = array2tk_list(from_task) if from_task.kind_of?(Array) + to_task = array2tk_list(to_task) if to_task.kind_of?(Array) + + tk_call(@chart, 'connect', from_task, to_task) + self + end + + def summary(txt, tasks) + tasks = array2tk_list(tasks) if tasks.kind_of?(Array) + tk_call(@chart, 'summary', tasks) + self + end + + def color_of_part(keyword, newcolor) + tk_call(@chart, 'color', keyword, newcolor) + self + end + + def font_of_part(keyword, newfont) + tk_call(@chart, 'font', keyword, newfont) + self + end + + def hscroll=(scr) + tk_call_without_enc(@chart, 'hscroll', scr) + scr + end + def hscroll(scr) + tk_call_without_enc(@chart, 'hscroll', scr) + self + end + + def vscroll=(scr) + tk_call_without_enc(@chart, 'vscroll', scr) + scr + end + def vscroll(scr) + tk_call_without_enc(@chart, 'vscroll', scr) + self + end + end + + ############################ + class PlotSeries < TkObject + SeriesID_TBL = TkCore::INTERP.create_table + + (Series_ID = ['series'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + TkCore::INTERP.init_ip_env{ + SeriesID_TBL.mutex.synchronize{ SeriesID_TBL.clear } + } + + def self.id2obj(chart, id) + path = chart.path + SeriesID_TBL.mutex.synchronize{ + if SeriesID_TBL[path] + SeriesID_TBL[path][id]? SeriesID_TBL[path][id]: id + else + id + end + } + end + + def initialize(chart, keys=nil) + @parent = @chart_obj = chart + @ppath = @chart_obj.path + Series_ID.mutex.synchronize{ + @path = @series = @id = Series_ID.join(TkCore::INTERP._ip_id_) + Series_ID[1].succ! + } + SeriesID_TBL.mutex.synchronize{ + SeriesID_TBL[@ppath] ||= {} + SeriesID_TBL[@ppath][@id] = self + } + dataconfig(keys) if keys.kind_of?(Hash) + end + + def plot(*args) + @chart_obj.plot(@series, *args) + end + + def dataconfig(key, value=None) + @chart_obj.dataconfig(@series, key, value) + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/ruler.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/ruler.rb new file mode 100644 index 0000000..d22dafa --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/ruler.rb @@ -0,0 +1,65 @@ +# +# tkextlib/tcllib/ruler.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * ruler widget +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('widget::ruler', '1.0') +TkPackage.require('widget::ruler') + +module Tk::Tcllib + module Widget + class Ruler < TkWindow + PACKAGE_NAME = 'widget::ruler'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('widget::ruler') + rescue + '' + end + end + end + end +end + +class Tk::Tcllib::Widget::Ruler + TkCommandNames = ['::widget::ruler'.freeze].freeze + + def __boolval_optkeys + ['showvalues', 'outline', 'grid'] + end + private :__boolval_optkeys + + def __numlistval_optkeys + ['interval', 'sizes'] + end + private :__numlistval_optkeys + + def create_self(keys) + if keys and keys != None + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self + + def redraw + tk_send('redraw') + self + end + + def shade(org, dest, frac) + tk_send('shade', org, dest, frac) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/screenruler.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/screenruler.rb new file mode 100644 index 0000000..75fa36b --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/screenruler.rb @@ -0,0 +1,68 @@ +# +# tkextlib/tcllib/screenruler.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * screenruler dialog +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('widget::screenruler', '1.1') +TkPackage.require('widget::screenruler') + +module Tk::Tcllib + module Widget + class ScreenRuler < TkWindow + PACKAGE_NAME = 'widget::ruler'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('widget::screenruler') + rescue + '' + end + end + end + Screenruler = ScreenRuler + end +end + +class Tk::Tcllib::Widget::ScreenRuler + TkCommandNames = ['::widget::screenruler'.freeze].freeze + + def __boolval_optkeys + ['topmost', 'reflect'] + end + private :__boolval_optkeys + + def __numlistval_optkeys + ['alpha'] + end + private :__numlistval_optkeys + + def create_self(keys) + if keys and keys != None + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self + + def display + tk_send('display') + self + end + alias show display + + def hide + tk_send('hide') + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/scrolledwindow.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/scrolledwindow.rb new file mode 100644 index 0000000..c9488b4 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/scrolledwindow.rb @@ -0,0 +1,57 @@ +# +# tkextlib/tcllib/scrolledwindow.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * scrolledwindow widget +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('widget::scrolledwindow', '1.2') +TkPackage.require('widget::scrolledwindow') + +module Tk::Tcllib + module Widget + class Scrolledwindow < Tk::Tile::TFrame + PACKAGE_NAME = 'widget::scrolledwindow'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('widget::scrolledwindow') + rescue + '' + end + end + end + ScrolledWindow = Scrolledwindow + end +end + +class Tk::Tcllib::Widget::ScrolledWindow + TkCommandNames = ['::widget::scrolledwindow'.freeze].freeze + + def create_self(keys) + if keys and keys != None + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self + + def getframe + window(tk_send_without_enc('getframe')) + end + alias get_frame getframe + + def setwidget(w) + window(tk_send_without_enc('setwidget', w)) + end + alias set_widget setwidget +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/scrollwin.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/scrollwin.rb new file mode 100644 index 0000000..c9f6062 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/scrollwin.rb @@ -0,0 +1,61 @@ +# +# tkextlib/tcllib/scrollwin.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Scrolled widget +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('widget::scrolledwindow', '1.0') +TkPackage.require('widget::scrolledwindow') + +module Tk::Tcllib + module Widget + class ScrolledWindow < TkWindow + PACKAGE_NAME = 'widget::scrolledwindow'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('widget::scrolledwindow') + rescue + '' + end + end + end + Scrolledwindow = ScrolledWindow + end +end + +class Tk::Tcllib::Widget::ScrolledWindow + TkCommandNames = ['::widget::scrolledwindow'.freeze].freeze + + def __numlistval_optkeys + ['ipad'] + end + private :__numlistval_optkeys + + def create_self(keys) + if keys and keys != None + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self + + def get_frame + window(tk_send('getframe')) + end + + def set_widget(widget) + tk_send('setwidget', widget) + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/setup.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/setup.rb new file mode 100644 index 0000000..ee406c6 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/setup.rb @@ -0,0 +1,8 @@ +# +# setup.rb -- setup script before calling TkPackage.require() +# +# If you need some setup operations (for example, add a library path +# to the library search path) before using Tcl/Tk library packages +# wrapped by Ruby scripts in this directory, please write the setup +# operations in this file. +# diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/statusbar.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/statusbar.rb new file mode 100644 index 0000000..46a4b9d --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/statusbar.rb @@ -0,0 +1,79 @@ +# +# tkextlib/tcllib/statusbar.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * statusbar widget +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('widget::statusbar', '1.2') +TkPackage.require('widget::statusbar') + +module Tk::Tcllib + module Widget + class Statusbar < Tk::Tile::TFrame + PACKAGE_NAME = 'widget::statusbar'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('widget::statusbar') + rescue + '' + end + end + end + end +end + +class Tk::Tcllib::Widget::Statusbar + TkCommandNames = ['::widget::statusbar'.freeze].freeze + + def __boolval_optkeys + super() << 'separator' << 'resize' << 'resizeseparator' + end + private :__boolval_optkeys + + def create_self(keys) + if keys and keys != None + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self + + def getframe + window(tk_send_without_enc('getframe')) + end + alias get_frame getframe + + def add(w, keys={}) + window(tk_send_without_enc('setwidget', *(hash_kv(keys)))) + end + + def remove(*wins) + tk_send_without_enc('remove', *wins) + self + end + + def remove_with_destroy(*wins) + tk_send_without_enc('remove', '-destroy', *wins) + self + end + + def delete(*wins) + tk_send_without_enc('delete', *wins) + self + end + + def items(pat=None) + tk_split_list(tk_send('items', pat)) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/style.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/style.rb new file mode 100644 index 0000000..dac6916 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/style.rb @@ -0,0 +1,61 @@ +# +# tkextlib/tcllib/style.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * select and use some 'style' of option (resource) DB +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +module Tk::Tcllib + module Style + PACKAGE_NAME = 'style'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('style') + rescue + '' + end + end + + def self.not_available + fail RuntimeError, "'tkextlib/tcllib/style' extension is not available on your current environment." + end + + def self.names + Tk::Tcllib::Style.not_available + end + + def self.use(style) + Tk::Tcllib::Style.not_available + end + end +end + +# TkPackage.require('style', '0.1') +# TkPackage.require('style', '0.3') +TkPackage.require('style') + +module Tk::Tcllib + class << Style + undef not_available + end + + module Style + extend TkCore + + def self.names + tk_split_simplelist(tk_call('style::names')) + end + + def self.use(style) + tk_call('style::use', style) + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/superframe.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/superframe.rb new file mode 100644 index 0000000..adc9c4a --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/superframe.rb @@ -0,0 +1,51 @@ +# +# tkextlib/tcllib/superframe.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Superframe widget - enhanced labelframe widget +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('widget::superframe', '1.0') +TkPackage.require('widget::superframe') + +module Tk::Tcllib + module Widget + class SuperFrame < TkWindow + PACKAGE_NAME = 'widget::superframe'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('widget::superframe') + rescue + '' + end + end + end + Superframe = SuperlFrame + end +end + +class Tk::Tcllib::Widget::SuperFrame + TkCommandNames = ['::widget::superframe'.freeze].freeze + + def create_self(keys) + if keys and keys != None + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self + + def labelwidget + window(tk_send('labelwidget')) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/swaplist.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/swaplist.rb new file mode 100644 index 0000000..7698640 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/swaplist.rb @@ -0,0 +1,150 @@ +# +# tkextlib/tcllib/swaplist.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * A dialog which allows a user to move options between two lists +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('swaplist', '0.1') +TkPackage.require('swaplist') + +module Tk::Tcllib + class Swaplist_Dialog < TkWindow + PACKAGE_NAME = 'swaplist'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('swaplist') + rescue + '' + end + end + end +end + + +class Tk::Tcllib::Swaplist_Dialog + TkCommandNames = ['::swaplist::swaplist'.freeze].freeze + WidgetClassName = 'Swaplist'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def self.show(*args) + dialog = self.new(*args) + dialog.show + [dialog.status, dialog.value] + end + def self.display(*args) + self.show(*args) + end + + def initialize(*args) + # args = (parent=nil, complete_list=[], selected_list=[], keys=nil) + keys = args.pop + if keys.kind_of?(Hash) + @selected_list = args.pop + @complete_list = args.pop + @keys = _symbolkey2str(keys) + args.push(keys) + else + @selected_list = keys + @complete_list = args.pop + @keys = {} + end + + @selected_list = [] unless @selected_list + @complete_list = [] unless @complete_list + + @variable = TkVariable.new + @status = nil + + super(*args) + end + + def create_self(keys) + # dummy + end + private :create_self + + def show + @variable.value = '' + @status = bool(tk_call(self.class::TkCommandNames[0], + @path, @variable, + @complete_list, @selected_list, + *hash_kv(@keys))) + end + alias display show + + def status + @status + end + + def value + @variable.list + end + alias selected value + + def cget_strict(slot) + slot = slot.to_s + if slot == 'complete_list' + @complete_list + elsif slot == 'selected_list' + @selected_list + else + @keys[slot] + end + end + def cget(slot) + cget_strict(slot) + end + + def configure(slot, value=None) + if slot.kind_of?(Hash) + slot.each{|k, v| configure(k, v)} + else + slot = slot.to_s + value = _symbolkey2str(value) if value.kind_of?(Hash) + if value && value != None + if slot == 'complete_list' + @complete_list = value + elsif slot == 'selected_list' + @selected_list = value + else + @keys[slot] = value + end + else + if slot == 'complete_list' + @complete_list = [] + elsif slot == 'selected_list' + @selected_list = [] + else + @keys.delete(slot) + end + end + end + self + end + + def configinfo(slot = nil) + if slot + slot = slot.to_s + if slot == 'complete_list' + [ slot, nil, nil, nil, @complete_list ] + elsif slot == 'selected_list' + [ slot, nil, nil, nil, @selected_list ] + else + [ slot, nil, nil, nil, @keys[slot] ] + end + else + @keys.collect{|k, v| [ k, nil, nil, nil, v ] } \ + << [ 'complete_list', nil, nil, nil, @complete_list ] \ + << [ 'selected_list', nil, nil, nil, @selected_list ] + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/tablelist.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/tablelist.rb new file mode 100644 index 0000000..bf5ab66 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/tablelist.rb @@ -0,0 +1,28 @@ +# +# tkextlib/tcllib/tablelist.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * A multi-column listbox + +require 'tk' +require 'tkextlib/tcllib.rb' + +# check Tile extension :: If already loaded, use tablelist_tile. +unless defined? Tk::Tcllib::Tablelist_usingTile + Tk::Tcllib::Tablelist_usingTile = + TkPackage.provide('tile') || TkPackage.provide('Ttk') +end + +if Tk::Tcllib::Tablelist_usingTile + # with Tile + require 'tkextlib/tcllib/tablelist_tile' + +else + # without Tile + + # TkPackage.require('tablelist', '4.2') + TkPackage.require('tablelist') + + require 'tkextlib/tcllib/tablelist_core' +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/tablelist_core.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/tablelist_core.rb new file mode 100644 index 0000000..2a5c415 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/tablelist_core.rb @@ -0,0 +1,1072 @@ +# +# tkextlib/tcllib/tablelist_core.rb +# +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * This file is required by 'tkextlib/tcllib/tablelist.rb' or +# 'tkextlib/tcllib/tablelist_tile.rb'. +# + +module Tk + module Tcllib + class Tablelist < TkWindow + if Tk::Tcllib::Tablelist_usingTile + PACKAGE_NAME = 'Tablelist_tile'.freeze + else + PACKAGE_NAME = 'Tablelist'.freeze + end + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require(self.package_name) + rescue + '' + end + end + + def self.use_Tile? + (Tk::Tcllib::Tablelist_usingTile)? true: false + end + end + TableList = Tablelist + end +end + +module Tk::Tcllib::TablelistItemConfig + include TkItemConfigMethod + + def _to_idx(idx) + if idx.kind_of?(Array) + idx.collect{|elem| _get_eval_string(elem)}.join(',') + else + idx + end + end + def _from_idx(idx) + return idx unless idx.kind_of?(String) + + if idx[0] == ?@ # '@x,y' + idx + elsif idx =~ /([^,]+),([^,]+)/ + row = $1, column = $2 + [num_or_str(row), num_or_str(column)] + else + num_or_str(idx) + end + end + private :_to_idx, :_from_idx + + def __item_cget_cmd(mixed_id) + [self.path, mixed_id[0] + 'cget', _to_idx(mixed_id[1])] + end + def __item_config_cmd(mixed_id) + [self.path, mixed_id[0] + 'configure', _to_idx(mixed_id[1])] + end + + def cell_cget_tkstring(tagOrId, option) + itemcget_tkstring(['cell', tagOrId], option) + end + def cell_cget(tagOrId, option) + itemcget(['cell', tagOrId], option) + end + def cell_cget_strict(tagOrId, option) + itemcget_strict(['cell', tagOrId], option) + end + def cell_configure(tagOrId, slot, value=None) + itemconfigure(['cell', tagOrId], slot, value) + end + def cell_configinfo(tagOrId, slot=nil) + itemconfiginfo(['cell', tagOrId], slot) + end + def current_cell_configinfo(tagOrId, slot=nil) + current_itemconfiginfo(['cell', tagOrId], slot) + end + alias cellcget_tkstring cell_cget_tkstring + alias cellcget cell_cget + alias cellcget_strict cell_cget_strict + alias cellconfigure cell_configure + alias cellconfiginfo cell_configinfo + alias current_cellconfiginfo current_cell_configinfo + + def column_cget_tkstring(tagOrId, option) + itemcget_tkstring(['column', tagOrId], option) + end + def column_cget(tagOrId, option) + itemcget(['column', tagOrId], option) + end + def column_cget_strict(tagOrId, option) + itemcget_strict(['column', tagOrId], option) + end + def column_configure(tagOrId, slot, value=None) + itemconfigure(['column', tagOrId], slot, value) + end + def column_configinfo(tagOrId, slot=nil) + itemconfiginfo(['column', tagOrId], slot) + end + def current_column_configinfo(tagOrId, slot=nil) + current_itemconfiginfo(['column', tagOrId], slot) + end + alias columncget_tkstring column_cget_tkstring + alias columncget column_cget + alias columncget_strict column_cget_strict + alias columnconfigure column_configure + alias columnconfiginfo column_configinfo + alias current_columnconfiginfo current_column_configinfo + + def row_cget_tkstring(tagOrId, option) + itemcget_tkstring(['row', tagOrId], option) + end + def row_cget(tagOrId, option) + itemcget(['row', tagOrId], option) + end + def row_cget_strict(tagOrId, option) + itemcget_strict(['row', tagOrId], option) + end + def row_configure(tagOrId, slot, value=None) + itemconfigure(['row', tagOrId], slot, value) + end + def row_configinfo(tagOrId, slot=nil) + itemconfiginfo(['row', tagOrId], slot) + end + def current_row_configinfo(tagOrId, slot=nil) + current_itemconfiginfo(['row', tagOrId], slot) + end + alias rowcget_tkstring row_cget_tkstring + alias rowcget row_cget + alias rowcget_strict row_cget_strict + alias rowconfigure row_configure + alias rowconfiginfo row_configinfo + alias current_rowconfiginfo current_row_configinfo + + private :itemcget_tkstring, :itemcget, :itemcget_strict + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo +end + +class Tk::Tcllib::Tablelist + include Tk::Tcllib::TablelistItemConfig + include Scrollable + + TkCommandNames = ['::tablelist::tablelist'.freeze].freeze + WidgetClassName = 'Tablelist'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def create_self(keys) + if keys and keys != None + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self + + ########################## + + def __numval_optkeys + super() + ['titlecolumns'] + end + private :__numval_optkeys + + def __strval_optkeys + super() + ['snipstring'] + end + private :__strval_optkeys + + def __boolval_optkeys + super() - ['takefocus'] + [ + 'forceeditendcommand', 'movablecolumns', 'movablerows', + 'protecttitlecolumns', 'resizablecolumns', 'setfocus', + 'showarrow', 'showlabels', 'showseparators' + ] + end + private :__boolval_optkeys + + def __listval_optkeys + super() + ['columns', 'columntitles'] + end + private :__listval_optkeys + + def __tkvariable_optkeys + super() + ['listvariable'] + end + private :__tkvariable_optkeys + + def __val2ruby_optkeys # { key=>proc, ... } + # The method is used to convert a opt-value to a ruby's object. + # When get the value of the option "key", "proc.call(value)" is called. + super().update('stretch'=>proc{|v| + (v == 'all')? v: simplelist(v) + }, + 'takefocus'=>proc{|v| + case v + when '1' + true + when '0' + false + when '' + nil + else # cmd + tk_tcl2ruby(cmd) + end + }) + end + private :__val2ruby_optkeys + + def __ruby2val_optkeys # { key=>proc, ... } + # The method is used to convert a ruby's object to a opt-value. + # When set the value of the option "key", "proc.call(value)" is called. + # That is, "-#{key} #{proc.call(value)}". + super().update('stretch'=>proc{|v| + (v.kind_of?(Array))? v.collect{|e| _to_idx(e)}: v + }, + 'takefocus'=>proc{|v| + case v + when true + '1' + when false + '0' + when nil + '' + else + _get_eval_string(v) + end + }) + end + private :__ruby2val_optkeys + + def __font_optkeys + super() + ['labelfont'] + end + private :__font_optkeys + + ########################## + + def __item_strval_optkeys(id) + if id[0] == 'cell' + super(id) + ['title'] + else + super(id) - ['text'] + ['title', 'name'] + end + end + private :__item_strval_optkeys + + def __item_boolval_optkeys(id) + super(id) + [ + 'changesnipside', 'editable', 'hide', 'resizable', 'selectable', + 'showarrow', 'showlinenumbers', 'stretchable', 'stretchwindow', 'wrap' + ] + end + private :__item_boolval_optkeys + + def __item_listval_optkeys(id) + if id[0] == 'cell' + super(id) + else + super(id) + ['text'] + end + end + private :__item_listval_optkeys + + def __item_font_optkeys(id) + # maybe need to override + super(id) + ['labelfont'] + end + private :__item_font_optkeys + + ########################## + + def activate(index) + tk_send('activate', _to_idx(index)) + self + end + + def activate_cell(index) + tk_send('activatecell', _to_idx(index)) + self + end + alias activatecell activate_cell + + def get_attrib(name=nil) + if name && name != None + tk_send('attrib', name) + else + ret = [] + lst = simplelist(tk_send('attrib')) + until lst.empty? + ret << ( [lst.shift] << lst.shift ) + end + ret + end + end + def set_attrib(*args) + tk_send('attrib', *(args.flatten)) + self + end + + def bbox(index) + list(tk_send('bbox', _to_idx(index))) + end + + def bodypath + window(tk_send('bodypath')) + end + + def bodytag + TkBindTag.new_by_name(tk_send('bodytag')) + end + + def cancel_editing + tk_send('cancelediting') + self + end + alias cancelediting cancel_editing + + def get_cellattrib(name=nil) + if name && name != None + tk_send('cellattrib', name) + else + ret = [] + lst = simplelist(tk_send('cellattrib')) + until lst.empty? + ret << ( [lst.shift] << lst.shift ) + end + ret + end + end + def set_cellattrib(*args) + tk_send('cellattrib', *(args.flatten)) + self + end + + def cellindex(idx) + _from_idx(tk_send('cellindex', _to_idx(idx))) + end + + def cellselection_anchor(idx) + tk_send('cellselection', 'anchor', _to_idx(idx)) + self + end + + def cellselection_clear(first, last=nil) + if first.kind_of?(Array) + tk_send('cellselection', 'clear', first.collect{|idx| _to_idx(idx)}) + else + first = _to_idx(first) + last = (last)? _to_idx(last): first + tk_send('cellselection', 'clear', first, last) + end + self + end + + def cellselection_includes(idx) + bool(tk_send('cellselection', 'includes', _to_idx(idx))) + end + + def cellselection_set(first, last=nil) + if first.kind_of?(Array) + tk_send('cellselection', 'set', first.collect{|idx| _to_idx(idx)}) + else + first = _to_idx(first) + last = (last)? _to_idx(last): first + tk_send('cellselection', 'set', first, last) + end + self + end + + def get_columnattrib(name=nil) + if name && name != None + tk_send('columnattrib', name) + else + ret = [] + lst = simplelist(tk_send('columnattrib')) + until lst.empty? + ret << ( [lst.shift] << lst.shift ) + end + ret + end + end + def set_columnattrib(*args) + tk_send('columnattrib', *(args.flatten)) + self + end + + def columncount + number(tk_send('columncount')) + end + + def columnindex(idx) + number(tk_send('columnindex', _to_idx(idx))) + end + + def columnwidth(idx, opt=nil) + if opt + number(tk_send('columnwidth', _to_idx(idx), "-#{opt}")) + else + number(tk_send('columnwidth', _to_idx(idx))) + end + end + def requested_columnwidth(idx) + columnwidth(idx, 'requested') + end + def stretched_columnwidth(idx) + columnwidth(idx, 'stretched') + end + def total_columnwidth(idx) + columnwidth(idx, 'total') + end + + def configcelllist(lst) # lst ==> [idx, opt, val, idx, opt, val, ...] + ary = [] + lst.slice(3){|idx, opt, val| + ary << _to_idx(idx) << "-#{opt}" << val + } + tk_send('configcelllist', ary) + self + end + alias config_celllist configcelllist + + def configcells(*args) # args ==> idx, opt, val, idx, opt, val, ... + ary = [] + args.slice(3){|idx, opt, val| + ary << _to_idx(idx) << "-#{opt}" << val + } + tk_send('configcells', *ary) + self + end + alias config_cells configcells + + def configcolumnlist(lst) # lst ==> [idx, opt, val, idx, opt, val, ...] + ary = [] + lst.slice(3){|idx, opt, val| + ary << _to_idx(idx) << "-#{opt}" << val + } + tk_send('configcolumnlist', ary) + self + end + alias config_columnlist configcolumnlist + + def configcolumns(*args) # args ==> idx, opt, val, idx, opt, val, ... + ary = [] + args.slice(3){|idx, opt, val| + ary << _to_idx(idx) << "-#{opt}" << val + } + tk_send('configcolumns', *ary) + self + end + alias config_columns configcolumns + + def configrowlist(lst) # lst ==> [idx, opt, val, idx, opt, val, ...] + ary = [] + lst.slice(3){|idx, opt, val| + ary << _to_idx(idx) << "-#{opt}" << val + } + tk_send('configrowlist', ary) + self + end + alias config_rowlist configrowlist + + def configrows(*args) # args ==> idx, opt, val, idx, opt, val, ... + ary = [] + args.slice(3){|idx, opt, val| + ary << _to_idx(idx) << "-#{opt}" << val + } + tk_send('configrows', *ary) + self + end + alias config_rows configrows + + def containing(y) + idx = num_or_str(tk_send('containing', y)) + (idx.kind_of?(Fixnum) && idx < 0)? nil: idx + end + + def containing_cell(x, y) + idx = _from_idx(tk_send('containingcell', x, y)) + if idx.kind_of?(Array) + [ + ((idx[0].kind_of?(Fixnum) && idx[0] < 0)? nil: idx[0]), + ((idx[1].kind_of?(Fixnum) && idx[1] < 0)? nil: idx[1]) + ] + else + idx + end + end + alias containingcell containing_cell + + def containing_column(x) + idx = num_or_str(tk_send('containingcolumn', x)) + (idx.kind_of?(Fixnum) && idx < 0)? nil: idx + end + alias containingcolumn containing_column + + def curcellselection + simplelist(tk_send('curcellselection')).collect!{|idx| _from_idx(idx)} + end + + def curselection + list(tk_send('curselection')) + end + + def delete_items(first, last=nil) + if first.kind_of?(Array) + tk_send('delete', first.collect{|idx| _to_idx(idx)}) + else + first = _to_idx(first) + last = (last)? _to_idx(last): first + tk_send('delete', first, last) + end + self + end + alias delete delete_items + alias deleteitems delete_items + + def delete_columns(first, last=nil) + if first.kind_of?(Array) + tk_send('deletecolumns', first.collect{|idx| _to_idx(idx)}) + else + first = _to_idx(first) + last = (last)? _to_idx(last): first + tk_send('deletecolumns', first, last) + end + self + end + alias deletecolumns delete_columns + + def edit_cell(idx) + tk_send('editcell', _to_idx(idx)) + self + end + alias editcell edit_cell + + def editwintag + TkBindTag.new_by_name(tk_send('editwintag')) + end + + def editwinpath + window(tk_send('editwinpath')) + end + + def entrypath + window(tk_send('entrypath')) + end + + def fill_column(idx, txt) + tk_send('fillcolumn', _to_idx(idx), txt) + self + end + alias fillcolumn fill_column + + def finish_editing + tk_send('finishediting') + self + end + alias finishediting finish_editing + + def formatinfo + key, row, col = simplelist(tk_send('formatinfo')) + [key, number(row), number(col)] + end + + def get(first, last=nil) + if first.kind_of?(Array) + simplelist(tk_send('get', first.collect{|idx| _to_idx(idx)})).collect!{|elem| simplelist(elem) } + else + first = _to_idx(first) + last = (last)? _to_idx(last): first + simplelist(tk_send('get', first, last)) + end + end + + def get_cells(first, last=nil) + if first.kind_of?(Array) + simplelist(tk_send('getcells', first.collect{|idx| _to_idx(idx)})).collect!{|elem| simplelist(elem) } + else + first = _to_idx(first) + last = (last)? _to_idx(last): first + simplelist(tk_send('getcells', first, last)) + end + end + alias getcells get_cells + + def get_columns(first, last=nil) + if first.kind_of?(Array) + simplelist(tk_send('getcolumns', first.collect{|idx| _to_idx(idx)})).collect!{|elem| simplelist(elem) } + else + first = _to_idx(first) + last = (last)? _to_idx(last): first + simplelist(tk_send('getcolumns', first, last)) + end + end + alias getcolumns get_columns + + def get_keys(first, last=nil) + if first.kind_of?(Array) + simplelist(tk_send('getkeys', first.collect{|idx| _to_idx(idx)})).collect!{|elem| simplelist(elem) } + else + first = _to_idx(first) + last = (last)? _to_idx(last): first + simplelist(tk_send('getkeys', first, last)) + end + end + alias getkeys get_keys + + def has_attrib?(name) + bool(tk_send('hasattrib', name)) + end + + def has_cellattrib?(idx, name) + bool(tk_send('hascellattrib', _to_idx(idx), name)) + end + + def has_columnattrib?(idx, name) + bool(tk_send('hascolumnattrib', _to_idx(idx), name)) + end + + def has_rowattrib?(idx, name) + bool(tk_send('hasrowattrib', _to_idx(idx), name)) + end + + def imagelabelpath(idx) + window(tk_send('imagelabelpath', _to_idx(idx))) + end + + def index(idx) + number(tk_send('index', _to_idx(idx))) + end + + def insert(idx, *items) + tk_send('insert', _to_idx(idx), *items) + self + end + + def insert_columnlist(idx, columnlist) + tk_send('insertcolumnlist', _to_idx(idx), columnlist) + self + end + alias insertcolumnlist insert_columnlist + + def insert_columns(idx, *args) + tk_send('insertcolums', _to_idx(idx), *args) + self + end + alias insertcolumns insert_columns + + def insert_list(idx, list) + tk_send('insertlist', _to_idx(idx), list) + self + end + alias insertlist insert_list + + def is_elem_snipped?(cellidx, tkvar) + bool(tk_send('iselemsnipped', _to_idx(cellidx), tkvar)) + end + alias elem_snipped? is_elem_snipped? + + def is_title_snipped?(colidx, tkvar) + bool(tk_send('istitlesnipped', _to_idx(colidx), tkvar)) + end + alias title_snipped? is_title_snipped? + + def itemlistvar + TkVarAccess.new(tk_send('itemlistvar')) + end + + def labelpath(idx) + window(tk_send('labelpath', _to_idx(idx))) + end + + def labels + simplelist(tk_send('labels')) + end + + def labeltag + TkBindTag.new_by_name(tk_send('labeltag')) + end + + def move(src, target) + tk_send('move', _to_idx(src), _to_idx(target)) + self + end + + def move_column(src, target) + tk_send('movecolumn', _to_idx(src), _to_idx(target)) + self + end + alias movecolumn move_column + + def nearest(y) + _from_idx(tk_send('nearest', y)) + end + + def nearest_cell(x, y) + _from_idx(tk_send('nearestcell', x, y)) + end + alias nearestcell nearest_cell + + def nearest_column(x) + _from_idx(tk_send('nearestcolumn', x)) + end + alias nearestcolumn nearest_column + + def reject_input + tk_send('rejectinput') + self + end + alias rejectinput reject_input + + def reset_sortinfo + tk_send('resetsortinfo') + self + end + alias resetsortinfo reset_sortinfo + + def get_rowattrib(name=nil) + if name && name != None + tk_send('rowattrib', name) + else + ret = [] + lst = simplelist(tk_send('rowattrib')) + until lst.empty? + ret << ( [lst.shift] << lst.shift ) + end + ret + end + end + def set_rowattrib(*args) + tk_send('rowattrib', *(args.flatten)) + self + end + + def scan_mark(x, y) + tk_send('scan', 'mark', x, y) + self + end + + def scan_dragto(x, y) + tk_send('scan', 'dragto', x, y) + self + end + + def see(idx) + tk_send('see', _to_idx(idx)) + self + end + + def see_cell(idx) + tk_send('seecell', _to_idx(idx)) + self + end + alias seecell see_cell + + def see_column(idx) + tk_send('seecolumn', _to_idx(idx)) + self + end + alias seecolumn see_column + + def selection_anchor(idx) + tk_send('selection', 'anchor', _to_idx(idx)) + self + end + + def selection_clear(first, last=nil) + if first.kind_of?(Array) + tk_send('selection', 'clear', first.collect{|idx| _to_idx(idx)}) + else + first = _to_idx(first) + last = (last)? _to_idx(last): first + tk_send('selection', 'clear', first, last) + end + self + end + + def selection_includes(idx) + bool(tk_send('selection', 'includes', _to_idx(idx))) + end + + def selection_set(first, last=nil) + if first.kind_of?(Array) + tk_send('selection', 'set', first.collect{|idx| _to_idx(idx)}) + else + first = _to_idx(first) + last = (last)? _to_idx(last): first + tk_send('selection', 'set', first, last) + end + self + end + + def separatorpath(idx=nil) + if idx + window(tk_send('separatorpath', _to_idx(idx))) + else + window(tk_send('separatorpath')) + end + end + + def separators + simplelist(tk_send('separators')).collect!{|w| window(w)} + end + + def size + number(tk_send('size')) + end + + def sort(order=nil) + if order + order = order.to_s + order = '-' << order if order[0] != ?- + if order.length < 2 + order = nil + end + end + if order + tk_send('sort', order) + else + tk_send('sort') + end + self + end + def sort_increasing + tk_send('sort', '-increasing') + self + end + def sort_decreasing + tk_send('sort', '-decreasing') + self + end + + + # default of 'labelcommand' option + DEFAULT_labelcommand_value = + DEFAULT_sortByColumn_cmd = '::tablelist::sortByColumn' + + # default of 'labelcommand2' option + DEFAULT_labelcommand2_value = + DEFAULT_addToSortColumns_cmd = '::tablelist::addToSortColumns' + + def sortByColumn_with_event_generate(idx) + tk_call('::tablelist::sortByColumn', @path, _to_idx(idx)) + end + + def addToSortColumns_with_event_generate(idx) + tk_call('::tablelist::addToSortColumns', @path, _to_idx(idx)) + end + + def sort_by_column(idx, order=nil) + if order + order = order.to_s + order = '-' << order if order[0] != ?- + if order.length < 2 + order = nil + end + end + if order + tk_send('sortbycolumn', _to_idx(idx), order) + else + tk_send('sortbycolumn', _to_idx(idx)) + end + self + end + def sort_by_column_increasing(idx) + tk_send('sortbycolumn', _to_idx(idx), '-increasing') + self + end + def sort_by_column_decreasing(idx) + tk_send('sortbycolumn', _to_idx(idx), '-decreasing') + self + end + + def sort_by_columnlist(idxlist, orderlist=None) + # orderlist :: list of 'increasing' or 'decreasing' + tk_send('sortbycolumnlist', idxlist.map{|idx| _to_idx(idx)}, orderlist) + self + end + + def sortcolumn + idx = num_or_str(tk_send('sortcolum')) + (idx.kind_of?(Fixnum) && idx < 0)? nil: idx + end + + def sortcolumnlist + simplelist(tk_send('sortcolumlist')).map{|col| num_or_str(col)} + end + + def sortorder + tk_send('sortorder') + end + + def sortorderlist + simplelist(tk_send('sortorderlist')) + end + + def toggle_columnhide(first, last=nil) + if first.kind_of?(Array) + tk_send('togglecolumnhide', first.collect{|idx| _to_idx(idx)}) + else + first = _to_idx(first) + last = (last)? _to_idx(last): first + tk_send('togglecolumnhide', first, last) + end + end + + def toggle_rowhide(first, last=nil) + if first.kind_of?(Array) + tk_send('togglerowhide', first.collect{|idx| _to_idx(idx)}) + else + first = _to_idx(first) + last = (last)? _to_idx(last): first + tk_send('togglerowhide', first, last) + end + end + + def toggle_visibility(first, last=nil) + if first.kind_of?(Array) + tk_send('togglevisibility', first.collect{|idx| _to_idx(idx)}) + else + first = _to_idx(first) + last = (last)? _to_idx(last): first + tk_send('togglevisibility', first, last) + end + self + end + alias togglevisibility toggle_visibility + + def unset_attrib(name) + tk_send('unsetattrib', name) + self + end + + def unset_cellattrib(idx, name) + tk_send('unsetcellattrib', _to_idx(idx), name) + self + end + + def unset_columnattrib(idx, name) + tk_send('unsetcolumnattrib', _to_idx(idx), name) + self + end + + def unset_rowattrib(idx, name) + tk_send('unsetrowattrib', _to_idx(idx), name) + self + end + + def windowpath(idx) + window(tk_send('windowpath', _to_idx(idx))) + end +end + +class << Tk::Tcllib::Tablelist + ############################################################ + # helper commands + def getTablelistPath(descendant) + window(Tk.tk_call('::tablelist::getTablelistPath', descendant)) + end + + def getTablelistColumn(descendant) + num_or_str(Tk.tk_call('::tablelist::getTablelistColumn', headerlabel)) + end + + + def convEventFields(descendant, x, y) + window(Tk.tk_call('::tablelist::convEventFields', descendant, x, y)) + end + + + ############################################################ + # with the BWidget package + def addBWidgetEntry(name=None) + Tk.tk_call('::tablelist::addBWidgetEntry', name) + end + + def addBWidgetSpinBox(name=None) + Tk.tk_call('::tablelist::addBWidgetSpinBox', name) + end + + def addBWidgetComboBox(name=None) + Tk.tk_call('::tablelist::addBWidgetComboBox', name) + end + + + ############################################################ + # with the Iwidgets ([incr Widgets]) package + def addIncrEntryfield(name=None) + Tk.tk_call('::tablelist::addIncrEntry', name) + end + + def addIncrDateTimeWidget(type, seconds=false, name=None) + # type := 'datefield'|'dateentry'|timefield'|'timeentry' + if seconds && seconds != None + seconds = '-seconds' + else + seconds = None + end + Tk.tk_call('::tablelist::addDateTimeWidget', type, seconds, name) + end + + def addIncrSpinner(name=None) + Tk.tk_call('::tablelist::addIncrSpinner', name) + end + + def addIncrSpinint(name=None) + Tk.tk_call('::tablelist::addIncrSpinint', name) + end + + def addIncrCombobox(name=None) + Tk.tk_call('::tablelist::addIncrCombobox', name) + end + + + ############################################################ + # with Bryan Oakley's combobox package + def addOakleyCombobox(name=None) + Tk.tk_call('::tablelist::addOakleyCombobox', name) + end + + ############################################################ + # with the multi-entry package Mentry is a library extension + def addDateMentry(format, separator, gmt=false, name=None) + if gmt && gmt != None + gmt = '-gmt' + else + gmt = None + end + Tk.tk_call('::tablelist::addDateMentry', format, separator, gmt, name) + end + + def addTimeMentry(format, separator, gmt=false, name=None) + if gmt && gmt != None + gmt = '-gmt' + else + gmt = None + end + Tk.tk_call('::tablelist::addTimeMentry', format, separator, gmt, name) + end + + def addDateTimeMentry(format, date_sep, time_sep, gmt=false, name=None) + if gmt && gmt != None + gmt = '-gmt' + else + gmt = None + end + Tk.tk_call('::tablelist::addDateTimeMentry', + format, date_sep, time_sep, gmt, name) + end + + def addFixedPointMentry(count1, count2, comma=false, name=None) + if comma && comma != None + comma = '-comma' + else + comma = None + end + Tk.tk_call('::tablelist::addFixedPoingMentry', count1, count2, comma, name) + end + + def addIPAddrMentry(name=None) + Tk.tk_call('::tablelist::addIPAddrMentry', name) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/tablelist_tile.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/tablelist_tile.rb new file mode 100644 index 0000000..0a14584 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/tablelist_tile.rb @@ -0,0 +1,43 @@ +# +# tkextlib/tcllib/tablelist_tlie.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * A multi-column listbox + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('tablelist_tile', '4.2') +TkPackage.require('tablelist_tile') + +unless defined? Tk::Tcllib::Tablelist_usingTile + Tk::Tcllib::Tablelist_usingTile = true +end + +requrie 'tkextlib/tcllib/tablelist_core' + +module Tk + module Tcllib + class Tablelist + # commands related to tile Themems + def self.set_theme(theme) + Tk.tk_call('::tablelist::setTheme', theme) + end + + def self.get_current_theme + Tk.tk_call('::tablelist::getCurrentTheme') + end + + def self.get_theme_list + TkComm.simplelist(Tk.tk_call('::tablelist::getThemes')) + end + def self.set_theme_defaults + Tk.tk_call('::tablelist::setThemeDefaults') + end + end + + Tablelist_Tile = Tablelist + TableList_Tile = Tablelist + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/tkpiechart.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/tkpiechart.rb new file mode 100644 index 0000000..2f6e4b4 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/tkpiechart.rb @@ -0,0 +1,314 @@ +# +# tkextlib/tcllib/tkpiechart.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Create 2D or 3D pies with labels in Tcl canvases +# + +require 'tk' +require 'tk/canvas' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('tkpiechart', '6.6') +TkPackage.require('tkpiechart') + +module Tk + module Tcllib + module Tkpiechart + end + end +end + +module Tk::Tcllib::Tkpiechart + PACKAGE_NAME = 'tkpiechart'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('tkpiechart') + rescue + '' + end + end + + module ConfigMethod + include TkConfigMethod + + def __pathname + self.path + ';' + self.tag + end + private :__pathname + + def __cget_cmd + ['::switched::cget', self.tag] + end + + def __config_cmd + ['::switched::configure', self.tag] + end + private :__config_cmd + + def __configinfo_struct + {:key=>0, :alias=>nil, :db_name=>nil, :db_class=>nil, + :default_value=>1, :current_value=>2} + end + private :__configinfo_struct + + def __boolval_optkeys + super() << 'select' << 'autoupdate' << 'selectable' + end + private :__boolval_optkeys + + def __strval_optkeys + super() << 'bordercolor' << 'textbackground' << + 'widestvaluetext' << 'title' + end + private :__strval_optkeys + + def __listval_optkeys + super() << 'colors' + end + private :__listval_optkeys + end + + #################################### + class PieChartObj < TkcItem + include ConfigMethod + + def __font_optkeys + ['titlefont'] + end + private :__font_optkeys + end + + #################################### + class Pie < TkcItem + include ConfigMethod + + def create_self(x, y, width, height, keys=None) + if keys and keys != None + @tag_key = tk_call_without_enc('::stooop::new', 'pie', + @c, x, y, *hash_kv(keys, true)) + else + @tag_key = tk_call_without_enc('::stooop::new', 'pie', @c, x, y) + end + + @slice_tbl = {} + + id = "pie(#{@tag_key})" + + @tag = @tag_pie = TkcNamedTag(@c, id) + @tag_slices = TkcNamedTag(@c, "pieSlices(#{@tag_key})") + + id + end + private :create_self + + def tag_key + @tag_key + end + def tag + @tag + end + def canvas + @c + end + def _entry_slice(slice) + @slice_tbl[slice.to_eval] = slice + end + def _delete_slice(slice) + @slice_tbl.delete(slice.to_eval) + end + + def delete + tk_call_without_enc('::stooop::delete', @tag_key) + CItemID_TBL.mutex.synchronize{ + CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path] + } + self + end + + def new_slice(text=None) + Slice.new(self, text) + end + + def delete_slice(slice) + unless slice.kind_of?(Slice) + unless (slice = @slice_tbl[slice]) + return tk_call_without_enc('pie::deleteSlice', @tag_key, slice) + end + end + unless slice.kind_of?(Slice) && slice.pie == self + fail ArgumentError, "argument is not a slice of self" + end + slice.delete + end + + def selected_slices + tk_split_simplelist(tk_call_without_enc('pie::selectedSlices', + @tag_key)).collect{|slice| + @slice_tbl[slice] || Slice.new(:no_create, self, slice) + } + end + end + + #################################### + class Slice < TkcItem + include ConfigMethod + + def __config_cmd + ['::switched::configure', self.tag] + end + private :__config_cmd + + #------------------------ + + def initialize(pie, *args) + unless pie.kind_of?(Pie) && pie != :no_create + fail ArgumentError, "expects TkPiechart::Pie for 1st argument" + end + + if pie == :no_create + @pie, @tag_key = args + else + text = args[0] || None + @pie = pie + @tag_key = tk_call_without_enc('pie::newSlice', @pie.tag_key, text) + end + @parent = @c = @pie.canvas + @path = @parent.path + + @pie._entry_slice(self) + + @id = "slices(#{@tag_key})" + @tag = TkcNamedTag.new(@pie.canvas, @id) + + CItemID_TBL.mutex.synchronize{ + CItemID_TBL[@path] = {} unless CItemID_TBL[@path] + CItemID_TBL[@path][@id] = self + } + end + + def tag_key + @tag_key + end + def tag + @tag + end + def pie + @pie + end + + def delete + tk_call_without_enc('pie::deleteSlice', @pie.tag_key, @tag_key) + CItemID_TBL.mutex.synchronize{ + CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path] + } + @pie._delete_slice(self) + self + end + + def size(share, disp=None) + tk_call_without_enc('pie::sizeSlice', + @pie.tag_key, @tag_key, share, disp) + self + end + + def label(text) + tk_call_without_enc('pie::labelSlice', @pie.tag_key, @tag_key, text) + self + end + end + + #################################### + class BoxLabeler < TkcItem + include ConfigMethod + + def __config_cmd + ['::switched::configure', self.tag] + end + private :__config_cmd + + #------------------------ + + def create_self(keys=None) + if keys and keys != None + @tag_key = tk_call_without_enc('::stooop::new', 'pieBoxLabeler', + *hash_kv(keys, true)) + else + @tag_key = tk_call_without_enc('::stooop::new', 'pieBoxLabeler') + end + + id = "pieBoxLabeler(#{@tag_key})" + @tag = TkcNamedTag(@c, id) + + id + end + private :create_self + end + + #################################### + class PeripheralLabeler < TkcItem + include ConfigMethod + + def __font_optkeys + ['font', 'smallfont'] + end + private :__font_optkeys + + def __config_cmd + ['::switched::configure', self.tag] + end + private :__config_cmd + + #------------------------ + + def create_self(keys=None) + if keys and keys != None + @tag_key = tk_call_without_enc('::stooop::new', + 'piePeripheralLabeler', + *hash_kv(keys, true)) + else + @tag_key = tk_call_without_enc('::stooop::new', 'piePeripheralLabeler') + end + + id = "piePeripheralLabeler(#{@tag_key})" + @tag = TkcNamedTag(@c, id) + + id + end + private :create_self + end + + #################################### + class Label < TkcItem + include ConfigMethod + + def __config_cmd + ['::switched::configure', self.tag] + end + private :__config_cmd + + #------------------------ + + def create_self(x, y, keys=None) + if keys and keys != None + @tag_key = tk_call_without_enc('::stooop::new', 'canvasLabel', + @c, x, y, width, height, + *hash_kv(keys, true)) + else + @tag_key = tk_call_without_enc('::stooop::new', 'canvasLabel', + @c, x, y, width, height) + end + + id = "canvasLabel(#{@tag_key})" + @tag = TkcNamedTag(@c, id) + + id + end + private :create_self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/toolbar.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/toolbar.rb new file mode 100644 index 0000000..6eae4eb --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/toolbar.rb @@ -0,0 +1,175 @@ +# +# tkextlib/tcllib/toolbar.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * toolbar widget +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('widget::toolbar', '1.2') +TkPackage.require('widget::toolbar') + +module Tk::Tcllib + module Widget + class Toolbar < TkWindow + PACKAGE_NAME = 'widget::toolbar'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('widget::toolbar') + rescue + '' + end + end + end + + module ToolbarItemConfig + include TkItemConfigMethod + end + end +end + + +class Tk::Tcllib::Widget::ToolbarItem < TkObject + include TkTreatTagFont + + ToolbarItemID_TBL = TkCore::INTERP.create_table + + TkCore::INTERP.init_ip_env{ + TTagID_TBL.mutex.synchronize{ TTagID_TBL.clear } + } + + def ToolbarItem.id2obj(tbar, id) + tpath = tbar.path + ToolbarItemID_TBL.mutex.synchronize{ + if ToolbarItemID_TBL[tpath] + ToolbarItemID_TBL[tpath][id]? ToolbarItemID_TBL[tpath][id]: id + else + id + end + } + end + + def initaialize(parent, *args) + @parent = @t = parent + @tpath = parent.path + + @path = @id = @t.tk_send('add', *args) + # A same id is rejected by the Tcl function. + + ToolbarItemID_TBL.mutex.synchronize{ + ToolbarItemID_TBL[@id] = self + ToolbarItemID_TBL[@tpath] = {} unless ToolbarItemID_TBL[@tpath] + ToolbarItemID_TBL[@tpath][@id] = self + } + end + + def [](key) + cget key + end + + def []=(key,val) + configure key, val + val + end + + def cget_tkstring(option) + @t.itemcget_tkstring(@id, option) + end + def cget(option) + @t.itemcget(@id, option) + end + def cget_strict(option) + @t.itemcget_strict(@id, option) + end + + def configure(key, value=None) + @t.itemconfigure(@id, key, value) + self + end + + def configinfo(key=nil) + @t.itemconfiginfo(@id, key) + end + + def current_configinfo(key=nil) + @t.current_itemconfiginfo(@id, key) + end + + def delete + @t.delete(@id) + end + + def itemid + @t.itemid(@id) + end + + def remove + @t.remove(@id) + end + def remove_with_destroy + @t.remove_with_destroy(@id) + end +end + +class Tk::Tcllib::Widget::Toolbar + include Tk::Tcllib::Widget::ToolbarItemConfig + + TkCommandNames = ['::widget::toolbar'.freeze].freeze + + def __destroy_hook__ + Tk::Tcllib::Widget::ToolbarItem::ToolbarItemID_TBL.mutex.synchronize{ + Tk::Tcllib::Widget::ToolbarItem::ToolbarItemID_TBL.delete(@path) + } + end + + def create_self(keys) + if keys and keys != None + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self + + def getframe + window(tk_send('getframe')) + end + alias get_frame getframe + + def add(*args) + Tk::Tcllib::Widget::Toolbar.new(self, *args) + end + + def itemid(item) + window(tk_send('itemid')) + end + + def items(pattern) + tk_split_simplelist(tk_send('items', pattern)).map{|id| + Tk::Tcllib::Widget::ToolbarItem.id2obj(self, id) + } + end + + def remove(*items) + tk_send('remove', *items) + self + end + + def remove_with_destroy(*items) + tk_send('remove', '-destroy', *items) + self + end + + def delete(*items) + tk_send('delete', *items) + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/tooltip.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/tooltip.rb new file mode 100644 index 0000000..070e63a --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/tooltip.rb @@ -0,0 +1,104 @@ +# +# tkextlib/tcllib/tooltip.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Provides tooltips, a small text message that is displayed when the +# mouse hovers over a widget. +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('tooltip', '1.1') +TkPackage.require('tooltip') + +module Tk::Tcllib + module Tooltip + PACKAGE_NAME = 'tooltip'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('tooltip') + rescue + '' + end + end + end +end + +module Tk::Tcllib::Tooltip + extend TkCore + + WidgetClassName = 'Tooltip'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def self.database_classname + self::WidgetClassName + end + def self.database_class + WidgetClassNames[self::WidgetClassName] + end + + def self.clear(glob_path_pat = None) + self.clear_glob(glob_path_pat) + end + + def self.clear_glob(glob_path_pat) + tk_call_without_enc('::tooltip::tooltip', 'clear', glob_path_pat) + end + + def self.clear_widgets(*args) + self.clear_glob("{#{args.collect{|w| _get_eval_string(w)}.join(',')}}") + end + + def self.clear_children(*args) + self.clear_glob("{#{args.collect{|w| s = _get_eval_string(w); "#{s},#{s}.*"}.join(',')}}") + end + + def self.delay(millisecs=None) + number(tk_call_without_enc('::tooltip::tooltip', 'delay', millisecs)) + end + def self.delay=(millisecs) + self.delay(millisecs) + end + + def self.fade? + bool(tk_call_without_enc('::tooltip::tooltip', 'fade')) + end + def self.fade(mode) + tk_call_without_enc('::tooltip::tooltip', 'fade', mode) + end + + def self.disable + tk_call_without_enc('::tooltip::tooltip', 'disable') + false + end + def self.off + self.disable + end + + def self.enable + tk_call_without_enc('::tooltip::tooltip', 'enable') + true + end + def self.on + self.enable + end + + def self.register(widget, msg, keys=nil) + if keys.kind_of?(Hash) + args = hash_kv(keys) << msg + else + args = msg + end + tk_call('::tooltip::tooltip', widget.path, *args) + end + + def self.erase(widget) + tk_call_without_enc('::tooltip::tooltip', widget.path, '') + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/validator.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/validator.rb new file mode 100644 index 0000000..3a71960 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/validator.rb @@ -0,0 +1,65 @@ +# +# tkextlib/tcllib/validator.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Provides a unified validation API +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('widget::validator', '0.1') +TkPackage.require('widget::validator') + +module Tk::Tcllib + module Validator + PACKAGE_NAME = 'widget::validator'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('widget::validator') + rescue + '' + end + end + end +end + +module Tk::Tcllib::Validator + extend TkCore + + def self.attach(widget, color, cmd=Proc.new) + tk_call_without_enc('::widget::validator', 'attach', widget, color, cmd) + nil + end + + def self.detach(widget) + tk_call_without_enc('::widget::validator', 'detach', widget) + nil + end + + def self.validate(widget) + tk_call_without_enc('::widget::validator', 'validate', widget) + nil + end + + def attach_validator(color, cmd=Proc.new) + tk_call_without_enc('::widget::validator', 'attach', @path, color, cmd) + self + end + + def detach_validator(color, cmd=Proc.new) + tk_call_without_enc('::widget::validator', 'detach', @path) + self + end + + def invoke_validator(color, cmd=Proc.new) + tk_call_without_enc('::widget::validator', 'validate', @path) + self + end + alias validate_validator invoke_validator +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/widget.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/widget.rb new file mode 100644 index 0000000..57fdf7a --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/widget.rb @@ -0,0 +1,82 @@ +# +# tkextlib/tcllib/widget.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * megawidget package that uses snit as the object system (snidgets) +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('widget', '3.0') +TkPackage.require('widget') + +module Tk::Tcllib + module Widget + PACKAGE_NAME = 'widget'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('widget') + rescue + '' + end + end + + #--- followings may be private functions of tklib + def self.isa(compare_as, *args) + begin + return Tk.tk_call('::widget::isa', compare_as, *args) + rescue => e + if TkComm.bool(Tk.tk_call('info','command','::widget::isa')) || + ! TkComm.bool(Tk.tk_call('info','command','::widget::validate')) + fail e + end + end + Tk.tk_call('::widget::validate', compare_as, *args) + end + def self.validate(compare_as, *args) + begin + return Tk.tk_call('::widget::validate', compare_as, *args) + rescue => e + if TkComm.bool(Tk.tk_call('info','command','::widget::validate')) || + ! TkComm.bool(Tk.tk_call('info','command','::widget::isa')) + fail e + end + end + Tk.tk_call('::widget::isa', compare_as, *args) + end + end +end + +module Tk::Tcllib::Widget + TkComm::TkExtlibAutoloadModule.unshift(self) + + autoload :Calendar, 'tkextlib/tcllib/calendar' + + autoload :Canvas_Sqmap, 'tkextlib/tcllib/canvas_sqmap' + autoload :Canvas_Zoom, 'tkextlib/tcllib/canvas_zoom' + + autoload :Dialog, 'tkextlib/tcllib/dialog' + + autoload :Panelframe, 'tkextlib/tcllib/panelframe' + autoload :PanelFrame, 'tkextlib/tcllib/panelframe' + + autoload :Ruler, 'tkextlib/tcllib/ruler' + + autoload :Screenruler, 'tkextlib/tcllib/screenruler' + autoload :ScreenRuler, 'tkextlib/tcllib/screenruler' + + autoload :Scrolledwindow, 'tkextlib/tcllib/scrollwin' + autoload :ScrolledWindow, 'tkextlib/tcllib/scrollwin' + + autoload :Superframe, 'tkextlib/tcllib/superframe' + autoload :SuperFrame, 'tkextlib/tcllib/superframe' + + autoload :Toolbar, 'tkextlib/tcllib/toolbar' + autoload :ToolbarItem, 'tkextlib/tcllib/toolbar' +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tclx.rb b/jni/ruby/ext/tk/lib/tkextlib/tclx.rb new file mode 100644 index 0000000..3a4ff27 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tclx.rb @@ -0,0 +1,13 @@ +# +# TclX support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tclx/setup.rb' + +# load library +require 'tkextlib/tclx/tclx' diff --git a/jni/ruby/ext/tk/lib/tkextlib/tclx/setup.rb b/jni/ruby/ext/tk/lib/tkextlib/tclx/setup.rb new file mode 100644 index 0000000..ee406c6 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tclx/setup.rb @@ -0,0 +1,8 @@ +# +# setup.rb -- setup script before calling TkPackage.require() +# +# If you need some setup operations (for example, add a library path +# to the library search path) before using Tcl/Tk library packages +# wrapped by Ruby scripts in this directory, please write the setup +# operations in this file. +# diff --git a/jni/ruby/ext/tk/lib/tkextlib/tclx/tclx.rb b/jni/ruby/ext/tk/lib/tkextlib/tclx/tclx.rb new file mode 100644 index 0000000..5a908fc --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tclx/tclx.rb @@ -0,0 +1,74 @@ +# +# tclx/tclx.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tclx/setup.rb' + +# TkPackage.require('Tclx', '8.0') +TkPackage.require('Tclx') + +module Tk + module TclX + PACKAGE_NAME = 'Tclx'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('Tclx') + rescue + '' + end + end + + def self.infox(*args) + Tk.tk_call('infox', *args) + end + + def self.signal(*args) + warn("Warning: Don't recommend to use TclX's 'signal' command. Please use Ruby's 'Signal.trap' method") + Tk.tk_call('signal', *args) + end + + def self.signal_restart(*args) + warn("Warning: Don't recommend to use TclX's 'signal' command. Please use Ruby's 'Signal.trap' method") + Tk.tk_call('signal', '-restart', *args) + end + + ############################## + + class XPG3_MsgCat + class << self + alias open new + end + + def initialize(catname, fail_mode=false) + if fail_mode + @msgcat_id = Tk.tk_call('catopen', '-fail', catname) + else + @msgcat_id = Tk.tk_call('catopen', '-nofail', catname) + end + end + + def close(fail_mode=false) + if fail_mode + Tk.tk_call('catclose', '-fail', @msgcat_id) + else + Tk.tk_call('catclose', '-nofail', @msgcat_id) + end + self + end + + def get(setnum, msgnum, defaultstr) + Tk.tk_call('catgets', @msgcat_id, setnum, msgnum, defaultstr) + end + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tile.rb b/jni/ruby/ext/tk/lib/tkextlib/tile.rb new file mode 100644 index 0000000..6c11e21 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tile.rb @@ -0,0 +1,449 @@ +# +# Tile theme engin (tile widget set) support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/ttk_selector' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# library directory +require 'tkextlib/tile/setup.rb' + +# load package +# TkPackage.require('tile', '0.4') +# TkPackage.require('tile', '0.6') +# TkPackage.require('tile', '0.7') +if Tk::TK_MAJOR_VERSION > 8 || + (Tk::TK_MAJOR_VERSION == 8 && Tk::TK_MINOR_VERSION >= 5) + begin + TkPackage.require('tile') # for compatibility (version check of 'tile') + rescue RuntimeError + # ignore, even if cannot find package 'tile' + end + pkgname = 'Ttk' +else + pkgname = 'tile' +end + +begin + verstr = TkPackage.require(pkgname) +rescue RuntimeError + # define dummy methods + module Tk + module Tile + CANNOT_FIND_PACKAGE = true + def self.const_missing(sym) + TkPackage.require(PACKAGE_NAME) + end + def self.method_missing(*args) + TkPackage.require(PACKAGE_NAME) + end + end + end + Tk.__cannot_find_tk_package_for_widget_set__(:Ttk, pkgname) + if pkgname == 'Ttk' + verstr = Tk::TK_PATCHLEVEL # dummy + else + verstr = '0.7' # dummy + end +end + +ver = verstr.split('.') +if ver[0].to_i == 0 + # Tile extension package + if ver[1].to_i <= 4 + # version 0.4 or former + module Tk + module Tile + USE_TILE_NAMESPACE = true + USE_TTK_NAMESPACE = false + TILE_SPEC_VERSION_ID = 0 + end + end + elsif ver[1].to_i <= 6 + # version 0.5 -- version 0.6 + module Tk + module Tile + USE_TILE_NAMESPACE = true + USE_TTK_NAMESPACE = true + TILE_SPEC_VERSION_ID = 5 + end + end + elsif ver[1].to_i <= 7 + module Tk + module Tile + USE_TILE_NAMESPACE = false + USE_TTK_NAMESPACE = true + TILE_SPEC_VERSION_ID = 7 + end + end + else + # version 0.8 or later + module Tk + module Tile + USE_TILE_NAMESPACE = false + USE_TTK_NAMESPACE = true + TILE_SPEC_VERSION_ID = 8 + end + end + end + + module Tk::Tile + PACKAGE_NAME = 'tile'.freeze + end +else + # Ttk package merged Tcl/Tk core (Tcl/Tk 8.5+) + module Tk + module Tile + USE_TILE_NAMESPACE = false + USE_TTK_NAMESPACE = true + TILE_SPEC_VERSION_ID = 8 + + PACKAGE_NAME = 'Ttk'.freeze + end + end +end + +# autoload +module Tk + module Tile + TkComm::TkExtlibAutoloadModule.unshift(self) + + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require(PACKAGE_NAME) + rescue + '' + end + end + + def self.__Import_Tile_Widgets__! + warn 'Warning: "Tk::Tile::__Import_Tile_Widgets__!" is obsolete.' << + ' To control default widget set, use "Tk.default_widget_set = :Ttk"' + Tk.tk_call('namespace', 'import', '-force', 'ttk::*') + end + + def self.__define_LoadImages_proc_for_compatibility__! + # Ttk 8.5 (Tile 0.8) lost 'LoadImages' utility procedure. + # So, some old scripts doen't work, because those scripts use the + # procedure to define local styles. + # Of course, rewriting such Tcl/Tk scripts isn't difficult for + # Tcl/Tk users. However, it may be troublesome for Ruby/Tk users + # who use such Tcl/Tk scripts as it is. + # This method may help Ruby/Tk users who don't want to modify old + # Tcl/Tk scripts for the latest version of Ttk (Tile) extension. + # This method defines a comaptible 'LoadImages' procedure on the + # Tcl/Tk interpreter working under Ruby/Tk. + # Please give attention to use this method. It may conflict with + # some definitions on Tcl/Tk scripts. + klass_name = self.name + proc_name = 'LoadImages' + if Tk::Tile::USE_TTK_NAMESPACE + ns_list = ['::tile'] + if Tk.info(:commands, "::ttk::#{proc_name}").empty? + ns_list << '::ttk' + end + else # Tk::Tile::USE_TILE_NAMESPACE + ns_list = ['::ttk'] + if Tk.info(:commands, "::tile::#{proc_name}").empty? + ns_list << '::tile' + end + end + + ns_list.each{|ns| + cmd = "#{ns}::#{proc_name}" + unless Tk.info(:commands, cmd).empty? + #fail RuntimeError, "can't define '#{cmd}' command (already exist)" + + # do nothing !!! + warn "Warning: can't define '#{cmd}' command (already exist)" if $DEBUG + next + end + TkNamespace.eval(ns){ + TkCore::INTERP.add_tk_procs(proc_name, 'imgdir {patterns {*.gif}}', + <<-'EOS') + foreach pattern $patterns { + foreach file [glob -directory $imgdir $pattern] { + set img [file tail [file rootname $file]] + if {![info exists images($img)]} { + set images($img) [image create photo -file $file] + } + } + } + return [array get images] + EOS + } + } + end + + def self.load_images(imgdir, pat=nil) + if Tk::Tile::TILE_SPEC_VERSION_ID < 8 + if Tk::Tile::USE_TTK_NAMESPACE + cmd = '::ttk::LoadImages' + else # Tk::Tile::USE_TILE_NAMESPACE + cmd = '::tile::LoadImages' + end + pat ||= TkComm::None + images = Hash[*TkComm.simplelist(Tk.tk_call(cmd, imgdir, pat))] + images.keys.each{|k| + images[k] = TkPhotoImage.new(:imagename=>images[k], + :without_creating=>true) + } + else ## TILE_SPEC_VERSION_ID >= 8 + pat ||= '*.gif' + if pat.kind_of?(Array) + pat_list = pat + else + pat_list = [ pat ] + end + Dir.chdir(imgdir){ + pat_list.each{|pat| + Dir.glob(pat).each{|f| + img = File.basename(f, '.*') + unless TkComm.bool(Tk.info('exists', "images(#{img})")) + Tk.tk_call('set', "images(#{img})", + Tk.tk_call('image', 'create', 'photo', '-file', f)) + end + } + } + } + images = Hash[*TkComm.simplelist(Tk.tk_call('array', 'get', 'images'))] + images.keys.each{|k| + images[k] = TkPhotoImage.new(:imagename=>images[k], + :without_creating=>true) + } + end + + images + end + + def self.style(*args) + args.map!{|arg| TkComm._get_eval_string(arg)}.join('.') + end + + def self.themes(glob_ptn = nil) + if TILE_SPEC_VERSION_ID < 8 && Tk.info(:commands, '::ttk::themes').empty? + fail RuntimeError, 'not support glob option' if glob_ptn + cmd = ['::tile::availableThemes'] + else + glob_ptn = '*' unless glob_ptn + cmd = ['::ttk::themes', glob_ptn] + end + + begin + TkComm.simplelist(Tk.tk_call_without_enc(*cmd)) + rescue + TkComm.simplelist(Tk.tk_call('lsearch', '-all', '-inline', + Tk::Tile::Style.theme_names, + glob_ptn)) + end + end + + def self.set_theme(theme) + if TILE_SPEC_VERSION_ID < 8 && Tk.info(:commands, '::ttk::setTheme').empty? + cmd = '::tile::setTheme' + else + cmd = '::ttk::setTheme' + end + + begin + Tk.tk_call_without_enc(cmd, theme) + rescue + Tk::Tile::Style.theme_use(theme) + end + end + + module KeyNav + if Tk::Tile::TILE_SPEC_VERSION_ID < 8 + def self.enableMnemonics(w) + Tk.tk_call('::keynav::enableMnemonics', w) + end + def self.defaultButton(w) + Tk.tk_call('::keynav::defaultButton', w) + end + else # dummy + def self.enableMnemonics(w) + "" + end + def self.defaultButton(w) + "" + end + end + end + + module Font + Default = 'TkDefaultFont' + Text = 'TkTextFont' + Heading = 'TkHeadingFont' + Caption = 'TkCaptionFont' + Tooltip = 'TkTooltipFont' + + Fixed = 'TkFixedFont' + Menu = 'TkMenuFont' + SmallCaption = 'TkSmallCaptionFont' + Icon = 'TkIconFont' + + TkFont::SYSTEM_FONT_NAMES.add [ + 'TkDefaultFont', 'TkTextFont', 'TkHeadingFont', + 'TkCaptionFont', 'TkTooltipFont', 'TkFixedFont', + 'TkMenuFont', 'TkSmallCaptionFont', 'TkIconFont' + ] + end + + module ParseStyleLayout + def _style_layout(lst) + ret = [] + until lst.empty? + sub = [lst.shift] + keys = {} + + until lst.empty? + if lst[0][0] == ?- + k = lst.shift[1..-1] + children = lst.shift + children = _style_layout(children) if children.kind_of?(Array) + keys[k] = children + else + break + end + end + + sub << keys unless keys.empty? + ret << sub + end + ret + end + private :_style_layout + end + + module TileWidget + include Tk::Tile::ParseStyleLayout + + def __val2ruby_optkeys # { key=>proc, ... } + # The method is used to convert a opt-value to a ruby's object. + # When get the value of the option "key", "proc.call(value)" is called. + super().update('style'=>proc{|v| _style_layout(list(v))}) + end + private :__val2ruby_optkeys + + def ttk_instate(state, script=nil, &b) + if script + tk_send('instate', state, script) + elsif b + tk_send('instate', state, Proc.new(&b)) + else + bool(tk_send('instate', state)) + end + end + alias tile_instate ttk_instate + + def ttk_state(state=nil) + if state + tk_send('state', state) + else + list(tk_send('state')) + end + end + alias tile_state ttk_state + + def ttk_identify(x, y) + ret = tk_send_without_enc('identify', x, y) + (ret.empty?)? nil: ret + end + alias tile_identify ttk_identify + + # remove instate/state/identify method + # to avoid the conflict with widget options + if Tk.const_defined?(:USE_OBSOLETE_TILE_STATE_METHOD) && Tk::USE_OBSOLETE_TILE_STATE_METHOD + alias instate ttk_instate + alias state ttk_state + alias identify ttk_identify + end + end + + ###################################### + + autoload :TButton, 'tkextlib/tile/tbutton' + autoload :Button, 'tkextlib/tile/tbutton' + + autoload :TCheckButton, 'tkextlib/tile/tcheckbutton' + autoload :CheckButton, 'tkextlib/tile/tcheckbutton' + autoload :TCheckbutton, 'tkextlib/tile/tcheckbutton' + autoload :Checkbutton, 'tkextlib/tile/tcheckbutton' + + autoload :Dialog, 'tkextlib/tile/dialog' + + autoload :TEntry, 'tkextlib/tile/tentry' + autoload :Entry, 'tkextlib/tile/tentry' + + autoload :TCombobox, 'tkextlib/tile/tcombobox' + autoload :Combobox, 'tkextlib/tile/tcombobox' + + autoload :TFrame, 'tkextlib/tile/tframe' + autoload :Frame, 'tkextlib/tile/tframe' + + autoload :TLabelframe, 'tkextlib/tile/tlabelframe' + autoload :Labelframe, 'tkextlib/tile/tlabelframe' + autoload :TLabelFrame, 'tkextlib/tile/tlabelframe' + autoload :LabelFrame, 'tkextlib/tile/tlabelframe' + + autoload :TLabel, 'tkextlib/tile/tlabel' + autoload :Label, 'tkextlib/tile/tlabel' + + autoload :TMenubutton, 'tkextlib/tile/tmenubutton' + autoload :Menubutton, 'tkextlib/tile/tmenubutton' + autoload :TMenuButton, 'tkextlib/tile/tmenubutton' + autoload :MenuButton, 'tkextlib/tile/tmenubutton' + + autoload :TNotebook, 'tkextlib/tile/tnotebook' + autoload :Notebook, 'tkextlib/tile/tnotebook' + + autoload :TPaned, 'tkextlib/tile/tpaned' + autoload :Paned, 'tkextlib/tile/tpaned' + autoload :PanedWindow, 'tkextlib/tile/tpaned' + autoload :Panedwindow, 'tkextlib/tile/tpaned' + + autoload :TProgressbar, 'tkextlib/tile/tprogressbar' + autoload :Progressbar, 'tkextlib/tile/tprogressbar' + + autoload :TRadioButton, 'tkextlib/tile/tradiobutton' + autoload :RadioButton, 'tkextlib/tile/tradiobutton' + autoload :TRadiobutton, 'tkextlib/tile/tradiobutton' + autoload :Radiobutton, 'tkextlib/tile/tradiobutton' + + autoload :TScale, 'tkextlib/tile/tscale' + autoload :Scale, 'tkextlib/tile/tscale' + autoload :TProgress, 'tkextlib/tile/tscale' + autoload :Progress, 'tkextlib/tile/tscale' + + autoload :TScrollbar, 'tkextlib/tile/tscrollbar' + autoload :Scrollbar, 'tkextlib/tile/tscrollbar' + autoload :XScrollbar, 'tkextlib/tile/tscrollbar' + autoload :YScrollbar, 'tkextlib/tile/tscrollbar' + + autoload :TSeparator, 'tkextlib/tile/tseparator' + autoload :Separator, 'tkextlib/tile/tseparator' + + autoload :TSpinbox, 'tkextlib/tile/tspinbox' + autoload :Spinbox, 'tkextlib/tile/tspinbox' + + autoload :TSquare, 'tkextlib/tile/tsquare' + autoload :Square, 'tkextlib/tile/tsquare' + + autoload :SizeGrip, 'tkextlib/tile/sizegrip' + autoload :Sizegrip, 'tkextlib/tile/sizegrip' + + autoload :Treeview, 'tkextlib/tile/treeview' + + autoload :Style, 'tkextlib/tile/style' + end +end + +Ttk = Tk::Tile diff --git a/jni/ruby/ext/tk/lib/tkextlib/tile/dialog.rb b/jni/ruby/ext/tk/lib/tkextlib/tile/dialog.rb new file mode 100644 index 0000000..b112e61 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tile/dialog.rb @@ -0,0 +1,102 @@ +# +# ttk::dialog (tile-0.7+) +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' +require 'tkextlib/tile.rb' + +module Tk + module Tile + class Dialog < TkWindow + end + end +end + +begin + TkPackage.require('ttk::dialog') # this may be required. +rescue RuntimeError + # ignore +end + +class Tk::Tile::Dialog + TkCommandNames = ['::ttk::dialog'.freeze].freeze + + def self.show(*args) + dialog = self.new(*args) + dialog.show + [dialog.status, dialog.value] + end + def self.display(*args) + self.show(*args) + end + + def self.define_dialog_type(name, keys) + Tk.tk_call('::ttk::dialog::define', name, keys) + name + end + + def self.style(*args) + ['Dialog', *(args.map!{|a| _get_eval_string(a)})].join('.') + end + + ######################### + + def initialize(keys={}) + @keys = _symbolkey2str(keys) + super(*args) + end + + def create_self(keys) + # dummy + end + private :create_self + + def show + tk_call(self.class::TkCommandNames[0], @path, *hash_kv(@keys)) + end + alias display show + + def client_frame + window(tk_call_without_enc('::ttk::dialog::clientframe', @path)) + end + + def cget_strict(slot) + @keys[slot.to_s] + end + def cget(slot) + @keys[slot.to_s] + end +=begin + def cget(slot) + unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + cget_strict(slot) + else + cget_strict(slot) rescue nil + end + end +=end + + def configure(slot, value=None) + if slot.kind_of?(Hash) + slot.each{|k, v| configure(k, v)} + else + slot = slot.to_s + value = _symbolkey2str(value) if value.kind_of?(Hash) + if value && value != None + @keys[slot] = value + else + @keys.delete(slot) + end + end + self + end + + def configinfo(slot = nil) + if slot + slot = slot.to_s + [ slot, nil, nil, nil, @keys[slot] ] + else + @keys.collect{|k, v| [ k, nil, nil, nil, v ] } + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tile/setup.rb b/jni/ruby/ext/tk/lib/tkextlib/tile/setup.rb new file mode 100644 index 0000000..ee406c6 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tile/setup.rb @@ -0,0 +1,8 @@ +# +# setup.rb -- setup script before calling TkPackage.require() +# +# If you need some setup operations (for example, add a library path +# to the library search path) before using Tcl/Tk library packages +# wrapped by Ruby scripts in this directory, please write the setup +# operations in this file. +# diff --git a/jni/ruby/ext/tk/lib/tkextlib/tile/sizegrip.rb b/jni/ruby/ext/tk/lib/tkextlib/tile/sizegrip.rb new file mode 100644 index 0000000..9947e0d --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tile/sizegrip.rb @@ -0,0 +1,32 @@ +# +# ttk::sizegrip widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' +require 'tkextlib/tile.rb' + +module Tk + module Tile + class SizeGrip < TkWindow + end + Sizegrip = SizeGrip + end +end + +class Tk::Tile::SizeGrip < TkWindow + include Tk::Tile::TileWidget + + TkCommandNames = ['::ttk::sizegrip'.freeze].freeze + WidgetClassName = 'TSizegrip'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def self.style(*args) + [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') + end +end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Sizegrip, +# :TkSizegrip, :TkSizeGrip) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/sizegrip.rb', + :Ttk, Tk::Tile::Sizegrip, + :TkSizegrip, :TkSizeGrip) diff --git a/jni/ruby/ext/tk/lib/tkextlib/tile/style.rb b/jni/ruby/ext/tk/lib/tkextlib/tile/style.rb new file mode 100644 index 0000000..83a0c9a --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tile/style.rb @@ -0,0 +1,336 @@ +# +# style commands +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' +require 'tkextlib/tile.rb' + +module Tk + module Tile + module Style + end + end +end + +module Tk::Tile::Style + extend TkCore +end + +class << Tk::Tile::Style + if Tk::Tile::TILE_SPEC_VERSION_ID < 8 + TkCommandNames = ['style'.freeze].freeze + + # --- Tk::Tile::Style.__define_wrapper_proc_for_compatibility__! --- + # On Ttk (Tile) extension, 'style' command has incompatible changes + # depend on the version of the extension. It requires modifying the + # Tcl/Tk scripts to define local styles. The rule for modification + # is a simple one. But, if users want to keep compatibility between + # versions of the extension, they will have to contrive to do that. + # It may be troublesome, especially for Ruby/Tk users. + # This method may help such work. This method make some definitions + # on the Tcl/Tk interpreter to work with different version of style + # command format. Please give attention to use this method. It may + # conflict with some definitions on Tcl/Tk scripts. + if Tk::Tile::TILE_SPEC_VERSION_ID < 7 + def __define_wrapper_proc_for_compatibility__! + __define_themes_and_setTheme_proc__! + + unless Tk.info(:commands, '::ttk::style').empty? + # fail RuntimeError, + # "can't define '::ttk::style' command (already exist)" + + # do nothing !!! + warn "Warning: can't define '::ttk::style' command (already exist)" if $DEBUG + return + end + TkCore::INTERP.add_tk_procs('::ttk::style', 'args', <<-'EOS') + if [string equal [lrange $args 0 1] {element create}] { + if [string equal [lindex $args 3] image] { + set spec [lindex $args 4] + set map [lrange $spec 1 end] + if [llength $map] { + # return [eval [concat [list ::style element create [lindex $args 2] image [lindex $spec 0] -map $map] [lrange $args 5 end]]] + return [uplevel 1 [list ::style element create [lindex $args 2] image [lindex $spec 0] -map $map] [lrange $args 5 end]] + } + } + } + # return [eval "::style $args"] + return [uplevel 1 ::style $args] + EOS + ######################### + end + else ### TILE_SPEC_VERSION_ID == 7 + def __define_wrapper_proc_for_compatibility__! + __define_themes_and_setTheme_proc__! + + unless Tk.info(:commands, '::ttk::style').empty? + # fail RuntimeError, + # "can't define '::ttk::style' command (already exist)" + + # do nothing !!! + warn "Warning: can't define '::ttk::style' command (already exist)" if $DEBUG + return + end + TkCore::INTERP.add_tk_procs('::ttk::style', 'args', <<-'EOS') + if [string equal [lrange $args 0 1] {element create}] { + if [string equal [lindex $args 3] image] { + set spec [lindex $args 4] + set map [lrange $spec 1 end] + if [llength $map] { + # return [eval [concat [list ::style element create [lindex $args 2] image [lindex $spec 0] -map $map] [lrange $args 5 end]]] + return [uplevel 1 [list ::style element create [lindex $args 2] image [lindex $spec 0] -map $map] [lrange $args 5 end]]] + } + } + } elseif [string equal [lindex $args 0] default] { + # return [eval "::style [lreplace $args 0 0 configure]"] + return [uplevel 1 ::style [lreplace $args 0 0 configure]] + } + # return [eval "::style $args"] + return [uplevel 1 ::style $args] + EOS + ######################### + end + end + else ### TILE_SPEC_VERSION_ID >= 8 + TkCommandNames = ['::ttk::style'.freeze].freeze + + def __define_wrapper_proc_for_compatibility__! + __define_themes_and_setTheme_proc__! + + unless Tk.info(:commands, '::style').empty? + # fail RuntimeError, "can't define '::style' command (already exist)" + + # do nothing !!! + warn "Warning: can't define '::style' command (already exist)" if $DEBUG + return + end + TkCore::INTERP.add_tk_procs('::style', 'args', <<-'EOS') + if [string equal [lrange $args 0 1] {element create}] { + if [string equal [lindex $args 3] image] { + set name [lindex $args 4] + set opts [lrange $args 5 end] + set idx [lsearch $opts -map] + if {$idx >= 0 && [expr $idx % 2 == 0]} { + # return [eval [concat [list ::ttk::style element create [lindex $args 2] image [concat $name [lindex $opts [expr $idx + 1]]]] [lreplace $opts $idx [expr $idx + 1]]]] + return [uplevel 1 [list ::ttk::style element create [lindex $args 2] image [concat $name [lindex $opts [expr $idx + 1]]]] [lreplace $opts $idx [expr $idx + 1]]] + } + } + } elseif [string equal [lindex $args 0] default] { + # return [eval "::ttk::style [lreplace $args 0 0 configure]"] + return [uplevel 1 ::ttk::style [lreplace $args 0 0 configure]] + } + # return [eval "::ttk::style $args"] + return [uplevel 1 ::ttk::style $args] + EOS + ######################### + end + end + + def __define_themes_and_setTheme_proc__! + TkCore::INTERP.add_tk_procs('::ttk::themes', '{ptn *}', <<-'EOS') + #set themes [list] + set themes [::ttk::style theme names] + foreach pkg [lsearch -inline -all -glob [package names] ttk::theme::$ptn] { + set theme [namespace tail $pkg] + if {[lsearch -exact $themes $theme] < 0} { + lappend themes $theme + } + } + foreach pkg [lsearch -inline -all -glob [package names] tile::theme::$ptn] { + set theme [namespace tail $pkg] + if {[lsearch -exact $themes $theme] < 0} { + lappend themes $theme + } + } + return $themes + EOS + ######################### + TkCore::INTERP.add_tk_procs('::ttk::setTheme', 'theme', <<-'EOS') + variable currentTheme + if {[lsearch -exact [::ttk::style theme names] $theme] < 0} { + package require [lsearch -inline -regexp [package names] (ttk|tile)::theme::$theme] + } + ::ttk::style theme use $theme + set currentTheme $theme + EOS + end + private :__define_themes_and_setTheme_proc__! + + def configure(style=nil, keys=nil) + if style.kind_of?(Hash) + keys = style + style = nil + end + style = '.' unless style + + if Tk::Tile::TILE_SPEC_VERSION_ID < 7 + sub_cmd = 'default' + else + sub_cmd = 'configure' + end + + if keys && keys != None + tk_call(TkCommandNames[0], sub_cmd, style, *hash_kv(keys)) + else + tk_call(TkCommandNames[0], sub_cmd, style) + end + end + alias default configure + + def map(style=nil, keys=nil) + if style.kind_of?(Hash) + keys = style + style = nil + end + style = '.' unless style + + if keys && keys != None + if keys.kind_of?(Hash) + tk_call(TkCommandNames[0], 'map', style, *hash_kv(keys)) + else + simplelist(tk_call(TkCommandNames[0], 'map', style, '-' << keys.to_s)) + end + else + ret = {} + Hash[*(simplelist(tk_call(TkCommandNames[0], 'map', style)))].each{|k, v| + ret[k[1..-1]] = list(v) + } + ret + end + end + alias map_configure map + + def map_configinfo(style=nil, key=None) + style = '.' unless style + map(style, key) + end + + def map_default_configinfo(key=None) + map('.', key) + end + + def lookup(style, opt, state=None, fallback_value=None) + tk_call(TkCommandNames[0], 'lookup', style, + '-' << opt.to_s, state, fallback_value) + end + + include Tk::Tile::ParseStyleLayout + + def layout(style=nil, spec=nil) + if style.kind_of?(Hash) + spec = style + style = nil + end + style = '.' unless style + + if spec + tk_call(TkCommandNames[0], 'layout', style, spec) + else + _style_layout(list(tk_call(TkCommandNames[0], 'layout', style))) + end + end + + def element_create(name, type, *args) + if type == 'image' || type == :image + element_create_image(name, *args) + elsif type == 'vsapi' || type == :vsapi + element_create_vsapi(name, *args) + else + tk_call(TkCommandNames[0], 'element', 'create', name, type, *args) + end + end + + def element_create_image(name, *args) + fail ArgumentError, 'Must supply a base image' unless (spec = args.shift) + if (opts = args.shift) + if opts.kind_of?(Hash) + opts = _symbolkey2str(opts) + else + fail ArgumentError, 'bad option' + end + end + fail ArgumentError, 'too many arguments' unless args.empty? + + if spec.kind_of?(Array) + # probably, command format is tile 0.8+ (Tcl/Tk8.5+) style + if Tk::Tile::TILE_SPEC_VERSION_ID >= 8 + if opts + tk_call(TkCommandNames[0], + 'element', 'create', name, 'image', spec, opts) + else + tk_call(TkCommandNames[0], 'element', 'create', name, 'image', spec) + end + else + fail ArgumentError, 'illegal arguments' if opts.key?('map') + base = spec.shift + opts['map'] = spec + tk_call(TkCommandNames[0], + 'element', 'create', name, 'image', base, opts) + end + else + # probably, command format is tile 0.7.8 or older style + if Tk::Tile::TILE_SPEC_VERSION_ID >= 8 + spec = [spec, *(opts.delete('map'))] if opts.key?('map') + end + if opts + tk_call(TkCommandNames[0], + 'element', 'create', name, 'image', spec, opts) + else + tk_call(TkCommandNames[0], 'element', 'create', name, 'image', spec) + end + end + end + + def element_create_vsapi(name, class_name, part_id, *args) + # supported on Tcl/Tk 8.6 or later + + # argument check + if (state_map = args.shift || None) + if state_map.kind_of?(Hash) + opts = _symbolkey2str(state_map) + state_map = None + end + end + opts = args.shift || None + fail ArgumentError, "too many arguments" unless args.empty? + + # define a Microsoft Visual Styles element + tk_call(TkCommandNames[0], 'element', 'create', name, 'vsapi', + class_name, part_id, state_map, opts) + end + + def element_names() + list(tk_call(TkCommandNames[0], 'element', 'names')) + end + + def element_options(elem) + simplelist(tk_call(TkCommandNames[0], 'element', 'options', elem)) + end + + def theme_create(name, keys=nil) + name = name.to_s + if keys && keys != None + tk_call(TkCommandNames[0], 'theme', 'create', name, *hash_kv(keys)) + else + tk_call(TkCommandNames[0], 'theme', 'create', name) + end + name + end + + def theme_settings(name, cmd=nil, &b) + name = name.to_s + cmd = Proc.new(&b) if !cmd && b + tk_call(TkCommandNames[0], 'theme', 'settings', name, cmd) + name + end + + def theme_names() + list(tk_call(TkCommandNames[0], 'theme', 'names')) + end + + def theme_use(name) + name = name.to_s + tk_call(TkCommandNames[0], 'theme', 'use', name) + name + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tile/tbutton.rb b/jni/ruby/ext/tk/lib/tkextlib/tile/tbutton.rb new file mode 100644 index 0000000..c852024 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tile/tbutton.rb @@ -0,0 +1,34 @@ +# +# tbutton widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' +require 'tkextlib/tile.rb' + +module Tk + module Tile + class TButton < Tk::Button + end + Button = TButton + end +end + +class Tk::Tile::TButton < Tk::Button + include Tk::Tile::TileWidget + + if Tk::Tile::USE_TTK_NAMESPACE + TkCommandNames = ['::ttk::button'.freeze].freeze + else + TkCommandNames = ['::tbutton'.freeze].freeze + end + WidgetClassName = 'TButton'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def self.style(*args) + [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') + end +end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Button, :TkButton) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tbutton.rb', + :Ttk, Tk::Tile::Button, :TkButton) diff --git a/jni/ruby/ext/tk/lib/tkextlib/tile/tcheckbutton.rb b/jni/ruby/ext/tk/lib/tkextlib/tile/tcheckbutton.rb new file mode 100644 index 0000000..01751ed --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tile/tcheckbutton.rb @@ -0,0 +1,38 @@ +# +# tcheckbutton widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' +require 'tkextlib/tile.rb' + +module Tk + module Tile + class TCheckButton < Tk::CheckButton + end + TCheckbutton = TCheckButton + CheckButton = TCheckButton + Checkbutton = TCheckButton + end +end + +class Tk::Tile::TCheckButton < Tk::CheckButton + include Tk::Tile::TileWidget + + if Tk::Tile::USE_TTK_NAMESPACE + TkCommandNames = ['::ttk::checkbutton'.freeze].freeze + else + TkCommandNames = ['::tcheckbutton'.freeze].freeze + end + WidgetClassName = 'TCheckbutton'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def self.style(*args) + [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') + end +end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Checkbutton, +# :TkCheckbutton, :TkCheckButton) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tcheckbutton.rb', + :Ttk, Tk::Tile::Checkbutton, + :TkCheckbutton, :TkCheckButton) diff --git a/jni/ruby/ext/tk/lib/tkextlib/tile/tcombobox.rb b/jni/ruby/ext/tk/lib/tkextlib/tile/tcombobox.rb new file mode 100644 index 0000000..b5ab827 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tile/tcombobox.rb @@ -0,0 +1,55 @@ +# +# tcombobox widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' +require 'tkextlib/tile.rb' + +module Tk + module Tile + class TCombobox < Tk::Tile::TEntry + end + Combobox = TCombobox + end +end + +class Tk::Tile::TCombobox < Tk::Tile::TEntry + include Tk::Tile::TileWidget + + if Tk::Tile::USE_TTK_NAMESPACE + TkCommandNames = ['::ttk::combobox'.freeze].freeze + else + TkCommandNames = ['::tcombobox'.freeze].freeze + end + WidgetClassName = 'TCombobox'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __boolval_optkeys + super() << 'exportselection' + end + private :__boolval_optkeys + + def __listval_optkeys + super() << 'values' + end + private :__listval_optkeys + + def self.style(*args) + [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') + end + + def current + number(tk_send_without_enc('current')) + end + def current=(idx) + tk_send_without_enc('current', idx) + end + + def set(val) + tk_send('set', val) + end +end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Combobox, :TkCombobox) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tcombobox.rb', + :Ttk, Tk::Tile::Combobox, :TkCombobox) diff --git a/jni/ruby/ext/tk/lib/tkextlib/tile/tentry.rb b/jni/ruby/ext/tk/lib/tkextlib/tile/tentry.rb new file mode 100644 index 0000000..8d2633a --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tile/tentry.rb @@ -0,0 +1,49 @@ +# +# tentry widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' +require 'tkextlib/tile.rb' + +module Tk + module Tile + class TEntry < Tk::Entry + end + Entry = TEntry + end +end + +class Tk::Tile::TEntry < Tk::Entry + include Tk::Tile::TileWidget + + if Tk::Tile::USE_TTK_NAMESPACE + TkCommandNames = ['::ttk::entry'.freeze].freeze + else + TkCommandNames = ['::tentry'.freeze].freeze + end + WidgetClassName = 'TEntry'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __optkey_aliases + {:vcmd=>:validatecommand, :invcmd=>:invalidcommand} + end + private :__optkey_aliases + + def __boolval_optkeys + super() << 'exportselection' + end + private :__boolval_optkeys + + def __strval_optkeys + super() << 'show' + end + private :__strval_optkeys + + def self.style(*args) + [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') + end +end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Entry, :TkEntry) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tentry.rb', + :Ttk, Tk::Tile::Entry, :TkEntry) diff --git a/jni/ruby/ext/tk/lib/tkextlib/tile/tframe.rb b/jni/ruby/ext/tk/lib/tkextlib/tile/tframe.rb new file mode 100644 index 0000000..d6d4312 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tile/tframe.rb @@ -0,0 +1,34 @@ +# +# tframe widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' +require 'tkextlib/tile.rb' + +module Tk + module Tile + class TFrame < Tk::Frame + end + Frame = TFrame + end +end + +class Tk::Tile::TFrame < Tk::Frame + include Tk::Tile::TileWidget + + if Tk::Tile::USE_TTK_NAMESPACE + TkCommandNames = ['::ttk::frame'.freeze].freeze + else + TkCommandNames = ['::tframe'.freeze].freeze + end + WidgetClassName = 'TFrame'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def self.style(*args) + [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') + end +end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Frame, :TkFrame) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tframe.rb', + :Ttk, Tk::Tile::Frame, :TkFrame) diff --git a/jni/ruby/ext/tk/lib/tkextlib/tile/tlabel.rb b/jni/ruby/ext/tk/lib/tkextlib/tile/tlabel.rb new file mode 100644 index 0000000..55b98ac --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tile/tlabel.rb @@ -0,0 +1,34 @@ +# +# tlabel widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' +require 'tkextlib/tile.rb' + +module Tk + module Tile + class TLabel < Tk::Label + end + Label = TLabel + end +end + +class Tk::Tile::TLabel < Tk::Label + include Tk::Tile::TileWidget + + if Tk::Tile::USE_TTK_NAMESPACE + TkCommandNames = ['::ttk::label'.freeze].freeze + else + TkCommandNames = ['::tlabel'.freeze].freeze + end + WidgetClassName = 'TLabel'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def self.style(*args) + [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') + end +end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Label, :TkLabel) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tlabel.rb', + :Ttk, Tk::Tile::Label, :TkLabel) diff --git a/jni/ruby/ext/tk/lib/tkextlib/tile/tlabelframe.rb b/jni/ruby/ext/tk/lib/tkextlib/tile/tlabelframe.rb new file mode 100644 index 0000000..a34c985 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tile/tlabelframe.rb @@ -0,0 +1,38 @@ +# +# tlabelframe widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' +require 'tkextlib/tile.rb' + +module Tk + module Tile + class TLabelframe < Tk::Tile::TFrame + end + TLabelFrame = TLabelframe + Labelframe = TLabelframe + LabelFrame = TLabelframe + end +end + +class Tk::Tile::TLabelframe < Tk::Tile::TFrame + include Tk::Tile::TileWidget + + if Tk::Tile::USE_TTK_NAMESPACE + TkCommandNames = ['::ttk::labelframe'.freeze].freeze + else + TkCommandNames = ['::tlabelframe'.freeze].freeze + end + WidgetClassName = 'TLabelframe'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def self.style(*args) + [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') + end +end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Labelframe, +# :TkLabelframe, :TkLabelFrame) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tlabelframe.rb', + :Ttk, Tk::Tile::Labelframe, + :TkLabelframe, :TkLabelFrame) diff --git a/jni/ruby/ext/tk/lib/tkextlib/tile/tmenubutton.rb b/jni/ruby/ext/tk/lib/tkextlib/tile/tmenubutton.rb new file mode 100644 index 0000000..1cf553e --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tile/tmenubutton.rb @@ -0,0 +1,38 @@ +# +# tmenubutton widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' +require 'tkextlib/tile.rb' + +module Tk + module Tile + class TMenubutton < Tk::Menubutton + end + TMenuButton = TMenubutton + Menubutton = TMenubutton + MenuButton = TMenubutton + end +end + +class Tk::Tile::TMenubutton < Tk::Menubutton + include Tk::Tile::TileWidget + + if Tk::Tile::USE_TTK_NAMESPACE + TkCommandNames = ['::ttk::menubutton'.freeze].freeze + else + TkCommandNames = ['::tmenubutton'.freeze].freeze + end + WidgetClassName = 'TMenubutton'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def self.style(*args) + [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') + end +end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Menubutton, +# :TkMenubutton, :TkMenuButton) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tmenubutton.rb', + :Ttk, Tk::Tile::Menubutton, + :TkMenubutton, :TkMenuButton) diff --git a/jni/ruby/ext/tk/lib/tkextlib/tile/tnotebook.rb b/jni/ruby/ext/tk/lib/tkextlib/tile/tnotebook.rb new file mode 100644 index 0000000..9e27e2c --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tile/tnotebook.rb @@ -0,0 +1,147 @@ +# +# tnotebook widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' +require 'tkextlib/tile.rb' + +module Tk + module Tile + class TNotebook < TkWindow + end + Notebook = TNotebook + end +end + +class Tk::Tile::TNotebook < TkWindow + ################################ + include TkItemConfigMethod + + def __item_cget_cmd(id) + [self.path, 'tab', id] + end + private :__item_cget_cmd + + def __item_config_cmd(id) + [self.path, 'tab', id] + end + private :__item_config_cmd + + def __item_listval_optkeys(id) + [] + end + private :__item_listval_optkeys + + def __item_methodcall_optkeys(id) # { key=>method, ... } + {} + end + private :__item_methodcall_optkeys + + #alias tabcget itemcget + #alias tabcget_strict itemcget_strict + alias tabconfigure itemconfigure + alias tabconfiginfo itemconfiginfo + alias current_tabconfiginfo current_itemconfiginfo + + def tabcget_tkstring(tagOrId, option) + tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{option}")), false, true)[-1] + end + def tabcget_strict(tagOrId, option) + tabconfiginfo(tagOrId, option)[-1] + end + def tabcget(tagOrId, option) + unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + tabcget_strict(tagOrId, option) + else + begin + tabcget_strict(tagOrId, option) + rescue => e + begin + if current_tabconfiginfo(tagOrId).has_key?(option.to_s) + # not tag error & option is known -> error on known option + fail e + else + # not tag error & option is unknown + nil + end + rescue + fail e # tag error + end + end + end + end + ################################ + + include Tk::Tile::TileWidget + + if Tk::Tile::USE_TTK_NAMESPACE + TkCommandNames = ['::ttk::notebook'.freeze].freeze + else + TkCommandNames = ['::tnotebook'.freeze].freeze + end + WidgetClassName = 'TNotebook'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def self.style(*args) + [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') + end + + def enable_traversal() + if Tk::Tile::TILE_SPEC_VERSION_ID < 5 + tk_call_without_enc('::tile::enableNotebookTraversal', @path) + elsif Tk::Tile::TILE_SPEC_VERSION_ID < 7 + tk_call_without_enc('::tile::notebook::enableTraversal', @path) + else + tk_call_without_enc('::ttk::notebook::enableTraversal', @path) + end + self + end + + def add(child, keys=nil) + if keys && keys != None + tk_send('add', _epath(child), *hash_kv(keys)) + else + tk_send('add', _epath(child)) + end + self + end + + def forget(idx) + tk_send('forget', idx) + self + end + + def hide(idx) + tk_send('hide', idx) + end + + def index(idx) + number(tk_send('index', idx)) + end + + def insert(idx, subwin, keys=nil) + if keys && keys != None + tk_send('insert', idx, subwin, *hash_kv(keys)) + else + tk_send('insert', idx, subwin) + end + self + end + + def select(idx) + tk_send('select', idx) + self + end + + def selected + window(tk_send_without_enc('select')) + end + + def tabs + list(tk_send('tabs')) + end +end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Notebook, :TkNotebook) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tnotebook.rb', + :Ttk, Tk::Tile::Notebook, :TkNotebook) diff --git a/jni/ruby/ext/tk/lib/tkextlib/tile/tpaned.rb b/jni/ruby/ext/tk/lib/tkextlib/tile/tpaned.rb new file mode 100644 index 0000000..d6ad234 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tile/tpaned.rb @@ -0,0 +1,245 @@ +# +# tpaned widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' +require 'tkextlib/tile.rb' + +module Tk + module Tile + class TPaned < TkWindow + end + PanedWindow = Panedwindow = Paned = TPaned + end +end + +class Tk::Tile::TPaned < TkWindow + include Tk::Tile::TileWidget + + if Tk::Tile::USE_TTK_NAMESPACE + if Tk::Tile::TILE_SPEC_VERSION_ID < 8 + TkCommandNames = ['::ttk::paned'.freeze].freeze + else + TkCommandNames = ['::ttk::panedwindow'.freeze].freeze + end + else + TkCommandNames = ['::tpaned'.freeze].freeze + end + WidgetClassName = 'TPaned'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def self.style(*args) + [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') + end + + 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 == [] + opts = hash_kv(keys) + else + args.push(keys) if keys + opts = [] + end + + args.each{|win| + tk_send_without_enc('add', _epath(win), *opts) + } + self + end + + def forget(pane) + pane = _epath(pane) + tk_send_without_enc('forget', pane) + self + end + + def insert(pos, win, keys) + win = _epath(win) + tk_send_without_enc('insert', pos, win, *hash_kv(keys)) + self + end + + def panecget_tkstring(pane, slot) + pane = _epath(pane) + tk_send_without_enc('pane', pane, "-#{slot}") + end + alias pane_cget_tkstring panecget_tkstring + + def panecget_strict(pane, slot) + pane = _epath(pane) + tk_tcl2ruby(tk_send_without_enc('pane', pane, "-#{slot}")) + end + alias pane_cget_strict panecget_strict + + def panecget(pane, slot) + unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + panecget_strict(pane, slot) + else + begin + panecget_strict(pane, slot) + rescue => e + begin + if current_paneconfiginfo(pane).has_key?(slot.to_s) + # not tag error & option is known -> error on known option + fail e + else + # not tag error & option is unknown + nil + end + rescue + fail e # tag error + end + end + end + end + alias pane_cget panecget + + def paneconfigure(pane, key, value=nil) + pane = _epath(pane) + 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('pane', pane, *params) + else + # value = value.epath if value.kind_of?(TkObject) + value = _epath(value) + tk_send_without_enc('pane', pane, "-#{key}", value) + end + self + end + alias pane_config paneconfigure + alias pane_configure paneconfigure + + def paneconfiginfo(win) + if TkComm::GET_CONFIGINFO_AS_ARRAY + win = _epath(win) + if key + conf = tk_split_list(tk_send_without_enc('pane', win, "-#{key}")) + conf[0] = conf[0][1..-1] + if conf[0] == 'hide' + conf[3] = bool(conf[3]) unless conf[3].empty? + conf[4] = bool(conf[4]) unless conf[4].empty? + end + conf + else + tk_split_simplelist(tk_send_without_enc('pane', + win)).collect{|conflist| + conf = tk_split_simplelist(conflist) + conf[0] = conf[0][1..-1] + if conf[3] + if conf[0] == 'hide' + conf[3] = bool(conf[3]) unless conf[3].empty? + elsif conf[3].index('{') + conf[3] = tk_split_list(conf[3]) + else + conf[3] = tk_tcl2ruby(conf[3]) + end + end + if conf[4] + if conf[0] == 'hide' + conf[4] = bool(conf[4]) unless conf[4].empty? + elsif 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 = _epath(win) + if key + conf = tk_split_list(tk_send_without_enc('pane', win, "-#{key}")) + key = conf.shift[1..-1] + if key == 'hide' + conf[2] = bool(conf[2]) unless conf[2].empty? + conf[3] = bool(conf[3]) unless conf[3].empty? + end + { key => conf } + else + ret = {} + tk_split_simplelist(tk_send_without_enc('pane', + win)).each{|conflist| + conf = tk_split_simplelist(conflist) + key = conf.shift[1..-1] + if key + if key == 'hide' + conf[2] = bool(conf[2]) unless conf[2].empty? + elsif conf[2].index('{') + conf[2] = tk_split_list(conf[2]) + else + conf[2] = tk_tcl2ruby(conf[2]) + end + end + if conf[3] + if key == 'hide' + conf[3] = bool(conf[3]) unless conf[3].empty? + elsif 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 + tk_split_simplelist(tk_send_without_enc('panes')).map{|w| + (obj = window(w))? obj: w + } + end + + def identify(x, y) + num_or_nil(tk_send_without_enc('identify', x, y)) + end + + def sashpos(idx, newpos=None) + num_or_str(tk_send_without_enc('sashpos', idx, newpos)) + end +end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Panedwindow, +# :TkPanedwindow, :TkPanedWindow) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tpaned.rb', + :Ttk, Tk::Tile::Panedwindow, + :TkPanedwindow, :TkPanedWindow) diff --git a/jni/ruby/ext/tk/lib/tkextlib/tile/tprogressbar.rb b/jni/ruby/ext/tk/lib/tkextlib/tile/tprogressbar.rb new file mode 100644 index 0000000..0c9d15e --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tile/tprogressbar.rb @@ -0,0 +1,57 @@ +# +# tprogressbar widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' +require 'tkextlib/tile.rb' + +module Tk + module Tile + class TProgressbar < TkWindow + end + Progressbar = TProgressbar + end +end + +class Tk::Tile::TProgressbar + include Tk::Tile::TileWidget + + if Tk::Tile::USE_TTK_NAMESPACE + TkCommandNames = ['::ttk::progressbar'.freeze].freeze + else + TkCommandNames = ['::tprogressbar'.freeze].freeze + end + WidgetClassName = 'TProgressbar'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def self.style(*args) + [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') + end + + def step(amount=None) + tk_send_without_enc('step', amount).to_f + end + #def step=(amount) + # tk_send_without_enc('step', amount) + #end + + def start(interval=None) + if Tk::Tile::TILE_SPEC_VERSION_ID < 5 + tk_call_without_enc('::tile::progressbar::start', @path, interval) + else + tk_send_without_enc('start', interval) + end + end + + def stop(amount=None) + if Tk::Tile::TILE_SPEC_VERSION_ID < 5 + tk_call_without_enc('::tile::progressbar::stop', @path) + else + tk_send_without_enc('stop', amount) + end + end +end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Progressbar, :TkProgressbar) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tprogressbar.rb', + :Ttk, Tk::Tile::Progressbar, :TkProgressbar) diff --git a/jni/ruby/ext/tk/lib/tkextlib/tile/tradiobutton.rb b/jni/ruby/ext/tk/lib/tkextlib/tile/tradiobutton.rb new file mode 100644 index 0000000..5dbf260 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tile/tradiobutton.rb @@ -0,0 +1,38 @@ +# +# tradiobutton widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' +require 'tkextlib/tile.rb' + +module Tk + module Tile + class TRadioButton < Tk::RadioButton + end + TRadiobutton = TRadioButton + RadioButton = TRadioButton + Radiobutton = TRadioButton + end +end + +class Tk::Tile::TRadioButton < Tk::RadioButton + include Tk::Tile::TileWidget + + if Tk::Tile::USE_TTK_NAMESPACE + TkCommandNames = ['::ttk::radiobutton'.freeze].freeze + else + TkCommandNames = ['::tradiobutton'.freeze].freeze + end + WidgetClassName = 'TRadiobutton'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def self.style(*args) + [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') + end +end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Radiobutton, +# :TkRadiobutton, :TkRadioButton) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tradiobutton.rb', + :Ttk, Tk::Tile::Radiobutton, + :TkRadiobutton, :TkRadioButton) diff --git a/jni/ruby/ext/tk/lib/tkextlib/tile/treeview.rb b/jni/ruby/ext/tk/lib/tkextlib/tile/treeview.rb new file mode 100644 index 0000000..85d7831 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tile/treeview.rb @@ -0,0 +1,1336 @@ +# +# treeview widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' +require 'tkextlib/tile.rb' + +module Tk + module Tile + class Treeview < TkWindow + end + end +end + +module Tk::Tile::TreeviewConfig + include TkItemConfigMethod + + def __item_configinfo_struct(id) + # maybe need to override + {:key=>0, :alias=>nil, :db_name=>nil, :db_class=>nil, + :default_value=>nil, :current_value=>1} + end + private :__item_configinfo_struct + + def __itemconfiginfo_core(tagOrId, slot = nil) + if TkComm::GET_CONFIGINFO_AS_ARRAY + if (slot && slot.to_s =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/) + fontkey = $2 + return [slot.to_s, tagfontobj(tagid(tagOrId), fontkey)] + else + if slot + slot = slot.to_s + + alias_name, real_name = __item_optkey_aliases(tagid(tagOrId)).find{|k, v| k.to_s == slot} + if real_name + slot = real_name.to_s + end + + case slot + when /^(#{__tile_specific_item_optkeys(tagid(tagOrId)).join('|')})$/ + begin + # On tile-0.7.{2-8}, 'state' options has no '-' at its head. + val = tk_call(*(__item_confinfo_cmd(tagid(tagOrId)) << slot)) + rescue + # Maybe, 'state' option has '-' in future. + val = tk_call(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")) + end + return [slot, val] + + when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/ + method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[slot] + optval = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")) + begin + val = method.call(tagOrId, optval) + rescue => e + warn("Warning:: #{e.message} (when #{method}lcall(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG + val = optval + end + return [slot, val] + + when /^(#{__item_methodcall_optkeys(tagid(tagOrId)).keys.join('|')})$/ + method = _symbolkey2str(__item_methodcall_optkeys(tagid(tagOrId)))[slot] + return [slot, self.__send__(method, tagOrId)] + + when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/ + begin + val = number(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))) + rescue + val = nil + end + return [slot, val] + + when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/ + val = num_or_str(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))) + return [slot, val] + + when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/ + begin + val = bool(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))) + rescue + val = nil + end + return [slot, val] + + when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/ + val = simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))) + return [slot, val] + + when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/ + val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")) + if val =~ /^[0-9]/ + return [slot, list(val)] + else + return [slot, val] + end + + when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/ + val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")) + return [slot, val] + + when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/ + val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")) + if val.empty? + return [slot, nil] + else + return [slot, TkVarAccess.new(val)] + end + + else + val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")) + if val.index('{') + return [slot, tk_split_list(val)] + else + return [slot, tk_tcl2ruby(val)] + end + end + + else # ! slot + ret = Hash[*(tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)))), false, false))].to_a.collect{|conf| + conf[0] = conf[0][1..-1] if conf[0][0] == ?- + case conf[0] + when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/ + method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[conf[0]] + optval = conf[1] + begin + val = method.call(tagOrId, optval) + rescue => e + warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG + val = optval + end + conf[1] = val + + when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/ + # do nothing + + when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/ + begin + conf[1] = number(conf[1]) + rescue + conf[1] = nil + end + + when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/ + conf[1] = num_or_str(conf[1]) + + when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/ + begin + conf[1] = bool(conf[1]) + rescue + conf[1] = nil + end + + when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/ + conf[1] = simplelist(conf[1]) + + when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/ + if conf[1] =~ /^[0-9]/ + conf[1] = list(conf[1]) + end + + when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/ + if conf[1].empty? + conf[1] = nil + else + conf[1] = TkVarAccess.new(conf[1]) + end + + else + if conf[1].index('{') + conf[1] = tk_split_list(conf[1]) + else + conf[1] = tk_tcl2ruby(conf[1]) + end + end + + conf + } + + __item_font_optkeys(tagid(tagOrId)).each{|optkey| + optkey = optkey.to_s + fontconf = ret.assoc(optkey) + if fontconf + ret.delete_if{|inf| inf[0] =~ /^(|latin|ascii|kanji)#{optkey}$/} + fontconf[1] = tagfontobj(tagid(tagOrId), optkey) + ret.push(fontconf) + end + } + + __item_methodcall_optkeys(tagid(tagOrId)).each{|optkey, method| + ret << [optkey.to_s, self.__send__(method, tagOrId)] + } + + ret + end + end + + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY + if (slot && slot.to_s =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/) + fontkey = $2 + return {slot.to_s => tagfontobj(tagid(tagOrId), fontkey)} + else + if slot + slot = slot.to_s + + alias_name, real_name = __item_optkey_aliases(tagid(tagOrId)).find{|k, v| k.to_s == slot} + if real_name + slot = real_name.to_s + end + + case slot + when /^(#{__tile_specific_item_optkeys(tagid(tagOrId)).join('|')})$/ + begin + # On tile-0.7.{2-8}, 'state' option has no '-' at its head. + val = tk_call(*(__item_confinfo_cmd(tagid(tagOrId)) << slot)) + rescue + # Maybe, 'state' option has '-' in future. + val = tk_call(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")) + end + return {slot => val} + + when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/ + method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[slot] + optval = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")) + begin + val = method.call(tagOrId, optval) + rescue => e + warn("Warning:: #{e.message} (when #{method}lcall(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG + val = optval + end + return {slot => val} + + when /^(#{__item_methodcall_optkeys(tagid(tagOrId)).keys.join('|')})$/ + method = _symbolkey2str(__item_methodcall_optkeys(tagid(tagOrId)))[slot] + return {slot => self.__send__(method, tagOrId)} + + when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/ + begin + val = number(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))) + rescue + val = nil + end + return {slot => val} + + when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/ + val = num_or_str(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))) + return {slot => val} + + when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/ + begin + val = bool(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))) + rescue + val = nil + end + return {slot => val} + + when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/ + val = simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))) + return {slot => val} + + when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/ + val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")) + if val =~ /^[0-9]/ + return {slot => list(val)} + else + return {slot => val} + end + + when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/ + val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")) + return {slot => val} + + when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/ + val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")) + if val.empty? + return {slot => nil} + else + return {slot => TkVarAccess.new(val)} + end + + else + val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")) + if val.index('{') + return {slot => tk_split_list(val)} + else + return {slot => tk_tcl2ruby(val)} + end + end + + else # ! slot + ret = {} + ret = Hash[*(tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)))), false, false))].to_a.collect{|conf| + conf[0] = conf[0][1..-1] if conf[0][0] == ?- + + optkey = conf[0] + case optkey + when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/ + method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[optkey] + optval = conf[1] + begin + val = method.call(tagOrId, optval) + rescue => e + warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG + val = optval + end + conf[1] = val + + when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/ + # do nothing + + when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/ + begin + conf[1] = number(conf[1]) + rescue + conf[1] = nil + end + + when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/ + conf[1] = num_or_str(conf[1]) + + when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/ + begin + conf[1] = bool(conf[1]) + rescue + conf[1] = nil + end + + when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/ + conf[1] = simplelist(conf[1]) + + when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/ + if conf[1] =~ /^[0-9]/ + conf[1] = list(conf[1]) + end + + when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/ + if conf[1].empty? + conf[1] = nil + else + conf[1] = TkVarAccess.new(conf[1]) + end + + else + if conf[1].index('{') + return [slot, tk_split_list(conf[1])] + else + return [slot, tk_tcl2ruby(conf[1])] + end + end + + ret[conf[0]] = conf[1] + } + + __item_font_optkeys(tagid(tagOrId)).each{|optkey| + optkey = optkey.to_s + fontconf = ret[optkey] + if fontconf.kind_of?(Array) + ret.delete(optkey) + ret.delete('latin' << optkey) + ret.delete('ascii' << optkey) + ret.delete('kanji' << optkey) + fontconf[1] = tagfontobj(tagid(tagOrId), optkey) + ret[optkey] = fontconf + end + } + + __item_methodcall_optkeys(tagid(tagOrId)).each{|optkey, method| + ret[optkey.to_s] = self.__send__(method, tagOrId) + } + + ret + end + end + end + end + + ################### + + def __item_cget_cmd(id) + [self.path, *id] + end + private :__item_cget_cmd + + def __item_config_cmd(id) + [self.path, *id] + end + private :__item_config_cmd + + def __item_numstrval_optkeys(id) + case id[0] + when :item, 'item' + ['width'] + when :column, 'column' + super(id[1]) + ['minwidth'] + when :tag, 'tag' + super(id[1]) + when :heading, 'heading' + super(id[1]) + else + super(id[1]) + end + end + private :__item_numstrval_optkeys + + def __item_strval_optkeys(id) + case id[0] + when :item, 'item' + super(id) + ['id'] + when :column, 'column' + super(id[1]) + when :tag, 'tag' + super(id[1]) + when :heading, 'heading' + super(id[1]) + else + super(id[1]) + end + end + private :__item_strval_optkeys + + def __item_boolval_optkeys(id) + case id[0] + when :item, 'item' + ['open'] + when :column, 'column' + super(id[1]) + ['stretch'] + when :tag, 'tag' + super(id[1]) + when :heading, 'heading' + super(id[1]) + end + end + private :__item_boolval_optkeys + + def __item_listval_optkeys(id) + case id[0] + when :item, 'item' + ['values'] + when :column, 'column' + [] + when :heading, 'heading' + [] + else + [] + end + end + private :__item_listval_optkeys + + def __item_val2ruby_optkeys(id) + case id[0] + when :item, 'item' + { + 'tags'=>proc{|arg_id, val| + simplelist(val).collect{|tag| + Tk::Tile::Treeview::Tag.id2obj(self, tag) + } + } + } + when :column, 'column' + {} + when :heading, 'heading' + {} + else + {} + end + end + private :__item_val2ruby_optkeys + + def __tile_specific_item_optkeys(id) + case id[0] + when :item, 'item' + [] + when :column, 'column' + [] + when :heading, 'heading' + ['state'] # On tile-0.7.{2-8}, 'state' options has no '-' at its head. + else + [] + end + end + private :__item_val2ruby_optkeys + + def itemconfiginfo(tagOrId, slot = nil) + __itemconfiginfo_core(tagOrId, slot) + end + + def current_itemconfiginfo(tagOrId, slot = nil) + if TkComm::GET_CONFIGINFO_AS_ARRAY + if slot + org_slot = slot + begin + conf = __itemconfiginfo_core(tagOrId, slot) + if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \ + || conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 ) + return {conf[0] => conf[-1]} + end + slot = conf[__item_configinfo_struct(tagid(tagOrId))[:alias]] + end while(org_slot != slot) + fail RuntimeError, + "there is a configure alias loop about '#{org_slot}'" + else + ret = {} + __itemconfiginfo_core(tagOrId).each{|conf| + if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \ + || conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 ) + ret[conf[0]] = conf[-1] + end + } + ret + end + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY + ret = {} + __itemconfiginfo_core(tagOrId, slot).each{|key, conf| + ret[key] = conf[-1] if conf.kind_of?(Array) + } + ret + end + end + + alias __itemcget_tkstring itemcget_tkstring + alias __itemcget itemcget + alias __itemcget_strict itemcget_strict + alias __itemconfigure itemconfigure + alias __itemconfiginfo itemconfiginfo + alias __current_itemconfiginfo current_itemconfiginfo + + private :__itemcget_tkstring, :__itemcget, :__itemcget_strict + private :__itemconfigure, :__itemconfiginfo, :__current_itemconfiginfo + + # Treeview Item + def itemcget_tkstring(tagOrId, option) + __itemcget_tkstring([:item, tagOrId], option) + end + def itemcget(tagOrId, option) + __itemcget([:item, tagOrId], option) + end + def itemcget_strict(tagOrId, option) + __itemcget_strict([:item, tagOrId], option) + end + def itemconfigure(tagOrId, slot, value=None) + __itemconfigure([:item, tagOrId], slot, value) + end + def itemconfiginfo(tagOrId, slot=nil) + __itemconfiginfo([:item, tagOrId], slot) + end + def current_itemconfiginfo(tagOrId, slot=nil) + __current_itemconfiginfo([:item, tagOrId], slot) + end + + # Treeview Column + def columncget_tkstring(tagOrId, option) + __itemcget_tkstring([:column, tagOrId], option) + end + def columncget(tagOrId, option) + __itemcget([:column, tagOrId], option) + end + def columncget_strict(tagOrId, option) + __itemcget_strict([:column, tagOrId], option) + end + def columnconfigure(tagOrId, slot, value=None) + __itemconfigure([:column, tagOrId], slot, value) + end + def columnconfiginfo(tagOrId, slot=nil) + __itemconfiginfo([:column, tagOrId], slot) + end + def current_columnconfiginfo(tagOrId, slot=nil) + __current_itemconfiginfo([:column, tagOrId], slot) + end + alias column_cget_tkstring columncget_tkstring + alias column_cget columncget + alias column_cget_strict columncget_strict + alias column_configure columnconfigure + alias column_configinfo columnconfiginfo + alias current_column_configinfo current_columnconfiginfo + + # Treeview Heading + def headingcget_tkstring(tagOrId, option) + if __tile_specific_item_optkeys([:heading, tagOrId]).index(option.to_s) + begin + # On tile-0.7.{2-8}, 'state' options has no '-' at its head. + tk_call(*(__item_cget_cmd([:heading, tagOrId]) << option.to_s)) + rescue + # Maybe, 'state' option has '-' in future. + tk_call(*(__item_cget_cmd([:heading, tagOrId]) << "-#{option}")) + end + else + __itemcget_tkstring([:heading, tagOrId], option) + end + end + def headingcget_strict(tagOrId, option) + if __tile_specific_item_optkeys([:heading, tagOrId]).index(option.to_s) + begin + # On tile-0.7.{2-8}, 'state' options has no '-' at its head. + tk_call(*(__item_cget_cmd([:heading, tagOrId]) << option.to_s)) + rescue + # Maybe, 'state' option has '-' in future. + tk_call(*(__item_cget_cmd([:heading, tagOrId]) << "-#{option}")) + end + else + __itemcget_strict([:heading, tagOrId], option) + end + end + def headingcget(tagOrId, option) + unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ + headingcget_strict(tagOrId, option) + else + begin + headingcget_strict(tagOrId, option) + rescue => e + begin + if current_headingconfiginfo(tagOrId).has_key?(option.to_s) + # not tag error & option is known -> error on known option + fail e + else + # not tag error & option is unknown + nil + end + rescue + fail e # tag error + end + end + end + end + def headingconfigure(tagOrId, slot, value=None) + if slot.kind_of?(Hash) + slot = _symbolkey2str(slot) + sp_kv = [] + __tile_specific_item_optkeys([:heading, tagOrId]).each{|k| + sp_kv << k << _get_eval_string(slot.delete(k)) if slot.has_key?(k) + } + tk_call(*(__item_config_cmd([:heading, tagOrId]).concat(sp_kv))) + tk_call(*(__item_config_cmd([:heading, tagOrId]).concat(hash_kv(slot)))) + elsif __tile_specific_item_optkeys([:heading, tagOrId]).index(slot.to_s) + begin + # On tile-0.7.{2-8}, 'state' options has no '-' at its head. + tk_call(*(__item_cget_cmd([:heading, tagOrId]) << slot.to_s << value)) + rescue + # Maybe, 'state' option has '-' in future. + tk_call(*(__item_cget_cmd([:heading, tagOrId]) << "-#{slot}" << value)) + end + else + __itemconfigure([:heading, tagOrId], slot, value) + end + self + end + def headingconfiginfo(tagOrId, slot=nil) + __itemconfiginfo([:heading, tagOrId], slot) + end + def current_headingconfiginfo(tagOrId, slot=nil) + __current_itemconfiginfo([:heading, tagOrId], slot) + end + alias heading_cget_tkstring headingcget_tkstring + alias heading_cget headingcget + alias heading_cget_strict headingcget_strict + alias heading_configure headingconfigure + alias heading_configinfo headingconfiginfo + alias current_heading_configinfo current_headingconfiginfo + + # Treeview Tag + def tagcget_tkstring(tagOrId, option) + __itemcget_tkstring([:tag, :configure, tagOrId], option) + end + def tagcget(tagOrId, option) + __itemcget([:tag, :configure, tagOrId], option) + end + def tagcget_strict(tagOrId, option) + __itemcget_strict([:tag, :configure, tagOrId], option) + end + def tagconfigure(tagOrId, slot, value=None) + __itemconfigure([:tag, :configure, tagOrId], slot, value) + end + def tagconfiginfo(tagOrId, slot=nil) + __itemconfiginfo([:tag, :configure, tagOrId], slot) + end + def current_tagconfiginfo(tagOrId, slot=nil) + __current_itemconfiginfo([:tag, :configure, tagOrId], slot) + end + alias tag_cget_tkstring tagcget_tkstring + alias tag_cget tagcget + alias tag_cget_strict tagcget_strict + alias tag_configure tagconfigure + alias tag_configinfo tagconfiginfo + alias current_tag_configinfo current_tagconfiginfo +end + +######################## + +class Tk::Tile::Treeview::Item < TkObject + ItemID_TBL = TkCore::INTERP.create_table + + TkCore::INTERP.init_ip_env{ + Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{ + Tk::Tile::Treeview::Item::ItemID_TBL.clear + } + } + + def self.id2obj(tree, id) + tpath = tree.path + Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{ + if Tk::Tile::Treeview::Item::ItemID_TBL[tpath] + (Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id])? \ + Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id]: id + else + id + end + } + end + + def self.assign(tree, id) + tpath = tree.path + obj = nil + Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{ + if Tk::Tile::Treeview::Item::ItemID_TBL[tpath] && + Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id] + return Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id] + end + + obj = self.allocate + obj.instance_eval{ + @parent = @t = tree + @tpath = tpath + @path = @id = id + } + Tk::Tile::Treeview::Item::ItemID_TBL[tpath] ||= {} + Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id] = obj + } + obj + end + + def _insert_item(tree, parent_item, idx, keys={}) + keys = _symbolkey2str(keys) + id = keys.delete('id') + if id + num_or_str(tk_call(tree, 'insert', + parent_item, idx, '-id', id, *hash_kv(keys))) + else + num_or_str(tk_call(tree, 'insert', parent_item, idx, *hash_kv(keys))) + end + end + private :_insert_item + + def initialize(tree, parent_item = '', idx = 'end', keys = {}) + if parent_item.kind_of?(Hash) + keys = parent_item + idx = 'end' + parent_item = '' + elsif idx.kind_of?(Hash) + keys = idx + idx = 'end' + end + + @parent = @t = tree + @tpath = tree.path + @path = @id = _insert_item(@t, parent_item, idx, keys) + Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{ + ItemID_TBL[@tpath] = {} unless ItemID_TBL[@tpath] + ItemID_TBL[@tpath][@id] = self + } + end + def id + @id + end + + def cget_tkstring(option) + @t.itemcget_tkstring(@id, option) + end + def cget(option) + @t.itemcget(@id, option) + end + def cget_strict(option) + @t.itemcget_strict(@id, option) + end + + def configure(key, value=None) + @t.itemconfigure(@id, key, value) + self + end + + def configinfo(key=nil) + @t.itemconfiginfo(@id, key) + end + + def current_configinfo(key=nil) + @t.current_itemconfiginfo(@id, key) + end + + def open? + cget('open') + end + def open + configure('open', true) + self + end + def close + configure('open', false) + self + end + + def tag_has?(tag) + @t.tag_has?(tag, @id) + end + alias has_tag? tag_has? + + def bbox(column=None) + @t.bbox(@id, column) + end + + def children + @t.children(@id) + end + def set_children(*items) + @t.set_children(@id, *items) + self + end + + def delete + @t.delete(@id) + self + end + + def detach + @t.detach(@id) + self + end + + def exist? + @t.exist?(@id) + end + + def focus + @t.focus_item(@id) + end + + def index + @t.index(@id) + end + + def insert(idx='end', keys={}) + @t.insert(@id, idx, keys) + end + + def move(parent, idx) + @t.move(@id, parent, idx) + self + end + + def next_item + @t.next_item(@id) + end + + def parent_item + @t.parent_item(@id) + end + + def prev_item + @t.prev_item(@id) + end + + def see + @t.see(@id) + self + end + + def selection_add + @t.selection_add(@id) + self + end + + def selection_remove + @t.selection_remove(@id) + self + end + + def selection_set + @t.selection_set(@id) + self + end + + def selection_toggle + @t.selection_toggle(@id) + self + end + + def get_directory + @t.get_directory(@id) + end + alias get_dictionary get_directory + + def get(col) + @t.get(@id, col) + end + + def set(col, value) + @t.set(@id, col, value) + end +end + +######################## + +class Tk::Tile::Treeview::Root < Tk::Tile::Treeview::Item + def self.new(tree, keys = {}) + tpath = tree.path + obj = nil + Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{ + if Tk::Tile::Treeview::Item::ItemID_TBL[tpath] && + Tk::Tile::Treeview::Item::ItemID_TBL[tpath][''] + obj = Tk::Tile::Treeview::Item::ItemID_TBL[tpath][''] + else + #super(tree, keys) + (obj = self.allocate).instance_eval{ + @parent = @t = tree + @tpath = tree.path + @path = @id = '' + Tk::Tile::Treeview::Item::ItemID_TBL[@tpath] ||= {} + Tk::Tile::Treeview::Item::ItemID_TBL[@tpath][@id] = self + } + end + } + obj.configure(keys) if keys && ! keys.empty? + obj + end + + def initialize(tree, keys = {}) + # dummy:: not called by 'new' method + @parent = @t = tree + @tpath = tree.path + @path = @id = '' + Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{ + Tk::Tile::Treeview::Item::ItemID_TBL[@tpath] ||= {} + Tk::Tile::Treeview::Item::ItemID_TBL[@tpath][@id] = self + } + end +end + +######################## + +class Tk::Tile::Treeview::Tag < TkObject + include TkTreatTagFont + + TagID_TBL = TkCore::INTERP.create_table + + (Tag_ID = ['tile_treeview_tag'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + TkCore::INTERP.init_ip_env{ + Tk::Tile::Treeview::Tag::TagID_TBL.mutex.synchronize{ + Tk::Tile::Treeview::Tag::TagID_TBL.clear + } + } + + def self.id2obj(tree, id) + tpath = tree.path + Tk::Tile::Treeview::Tag::TagID_TBL.mutex.synchronize{ + if Tk::Tile::Treeview::Tag::TagID_TBL[tpath] + (Tk::Tile::Treeview::Tag::TagID_TBL[tpath][id])? \ + Tk::Tile::Treeview::Tag::TagID_TBL[tpath][id]: id + else + id + end + } + end + + def initialize(tree, keys=nil) + @parent = @t = tree + @tpath = tree.path + Tag_ID.mutex.synchronize{ + @path = @id = Tag_ID.join(TkCore::INTERP._ip_id_) + Tag_ID[1].succ! + } + TagID_TBL.mutex.synchronize{ + TagID_TBL[@tpath] = {} unless TagID_TBL[@tpath] + TagID_TBL[@tpath][@id] = self + } + if keys && keys != None + tk_call_without_enc(@tpath, 'tag', 'configure', @id, *hash_kv(keys,true)) + end + end + def id + @id + end + + def tag_has?(item) + @t.tag_has?(@id, item) + end + alias added? tag_has? + + def tag_has + @t.tag_has(@id) + end + + def add(*items) + @t.tag_add(@id, *items) + end + + def remove(*items) + @t.tag_remove(@id, *items) + end + + def bind(seq, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + @t.tag_bind(@id, seq, cmd, *args) + self + end + + def bind_append(seq, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + @t.tag_bind_append(@id, seq, cmd, *args) + self + end + + def bind_remove(seq) + @t.tag_bind_remove(@id, seq) + self + end + + def bindinfo(seq=nil) + @t.tag_bindinfo(@id, seq) + end + + def cget_tkstring(option) + @t.tagcget_tkstring(@id, option) + end + def cget(option) + @t.tagcget(@id, option) + end + def cget_strict(option) + @t.tagcget_strict(@id, option) + end + + def configure(key, value=None) + @t.tagconfigure(@id, key, value) + self + end + + def configinfo(key=nil) + @t.tagconfiginfo(@id, key) + end + + def current_configinfo(key=nil) + @t.current_tagconfiginfo(@id, key) + end +end + +######################## + +class Tk::Tile::Treeview < TkWindow + include Tk::Tile::TileWidget + include Scrollable + + include Tk::Tile::TreeviewConfig + + if Tk::Tile::USE_TTK_NAMESPACE + TkCommandNames = ['::ttk::treeview'.freeze].freeze + else + TkCommandNames = ['::treeview'.freeze].freeze + end + WidgetClassName = 'Treeview'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __destroy_hook__ + Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{ + Tk::Tile::Treeview::Item::ItemID_TBL.delete(@path) + } + Tk::Tile::Treeview::Tag::ItemID_TBL.mutex.synchronize{ + Tk::Tile::Treeview::Tag::ItemID_TBL.delete(@path) + } + end + + def self.style(*args) + [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') + end + + def tagid(id) + if id.kind_of?(Tk::Tile::Treeview::Item) || + id.kind_of?(Tk::Tile::Treeview::Tag) + id.id + elsif id.kind_of?(Array) + # size is 2 or 3 + id[0..-2] << _get_eval_string(id[-1]) + else + _get_eval_string(id) + end + end + + def root + Tk::Tile::Treeview::Root.new(self) + end + + def bbox(item, column=None) + list(tk_send('item', 'bbox', item, column)) + end + + def children(item) + simplelist(tk_send_without_enc('children', item)).collect{|id| + Tk::Tile::Treeview::Item.id2obj(self, id) + } + end + def set_children(item, *items) + tk_send_without_enc('children', item, + array2tk_list(items.flatten, true)) + self + end + + def delete(*items) + tk_send_without_enc('delete', array2tk_list(items.flatten, true)) + self + end + + def detach(*items) + tk_send_without_enc('detach', array2tk_list(items.flatten, true)) + self + end + + def exist?(item) + bool(tk_send_without_enc('exists', _get_eval_enc_str(item))) + end + + def focus_item(item = nil) + if item + tk_send('focus', item) + item + else + id = tk_send('focus') + (id.empty?)? nil: Tk::Tile::Treeview::Item.id2obj(self, id) + end + end + + def identify(x, y) + # tile-0.7.2 or previous + ret = simplelist(tk_send('identify', x, y)) + case ret[0] + when 'heading', 'separator' + ret[-1] = num_or_str(ret[-1]) + when 'cell' + ret[1] = Tk::Tile::Treeview::Item.id2obj(self, ret[1]) + ret[-1] = num_or_str(ret[-1]) + when 'item', 'row' + ret[1] = Tk::Tile::Treeview::Item.id2obj(self, ret[1]) + end + end + + def identify_region(x, y) + tk_send('identify', 'region', x, y) + end + + def identify_item(x, y) + id = tk_send('identify', 'item', x, y) + (id.empty?)? nil: Tk::Tile::Treeview::Item.id2obj(self, id) + end + + def identify_element(x, y) + tk_send('identify', 'element', x, y) + end + + def row_identify(x, y) + id = tk_send('identify', 'row', x, y) + (id.empty?)? nil: Tk::Tile::Treeview::Item.id2obj(self, id) + end + alias identify_row row_identify + + def column_identify(x, y) + tk_send('identify', 'column', x, y) + end + alias identify_column column_identify + + def index(item) + number(tk_send('index', item)) + end + + # def insert(parent, idx='end', keys={}) + # keys = _symbolkey2str(keys) + # id = keys.delete('id') + # if id + # num_or_str(tk_send('insert', parent, idx, '-id', id, *hash_kv(keys))) + # else + # num_or_str(tk_send('insert', parent, idx, *hash_kv(keys))) + # end + # end + def insert(parent, idx='end', keys={}) + Tk::Tile::Treeview::Item.new(self, parent, idx, keys) + end + + # def instate(spec, cmd=Proc.new) + # tk_send('instate', spec, cmd) + # end + # def state(spec=None) + # tk_send('state', spec) + # end + + def move(item, parent, idx) + tk_send('move', item, parent, idx) + self + end + + def next_item(item) + id = tk_send('next', item) + (id.empty?)? nil: Tk::Tile::Treeview::Item.id2obj(self, id) + end + + def parent_item(item) + if (id = tk_send('parent', item)).empty? + Tk::Tile::Treeview::Root.new(self) + else + Tk::Tile::Treeview::Item.id2obj(self, id) + end + end + + def prev_item(item) + id = tk_send('prev', item) + (id.empty?)? nil: Tk::Tile::Treeview::Item.id2obj(self, id) + end + + def see(item) + tk_send('see', item) + self + end + + def selection + simplelist(tk_send('selection')).collect{|id| + Tk::Tile::Treeview::Item.id2obj(self, id) + } + end + alias selection_get selection + + def selection_add(*items) + tk_send('selection', 'add', array2tk_list(items.flatten, true)) + self + end + def selection_remove(*items) + tk_send('selection', 'remove', array2tk_list(items.flatten, true)) + self + end + def selection_set(*items) + tk_send('selection', 'set', array2tk_list(items.flatten, true)) + self + end + def selection_toggle(*items) + tk_send('selection', 'toggle', array2tk_list(items.flatten, true)) + self + end + + def get_directory(item) + # tile-0.7+ + ret = [] + lst = simplelist(tk_send('set', item)) + until lst.empty? + col = lst.shift + val = lst.shift + ret << [col, val] + end + ret + end + alias get_dictionary get_directory + + def get(item, col) + tk_send('set', item, col) + end + def set(item, col, value) + tk_send('set', item, col, value) + self + end + + def tag_has?(tag, item) + bool(tk_send('tag', 'has', tagid(tag), tagid(item))) + end + def tag_has(tag) + tk_split_simplelist(tk_send('tag', 'has', tagid(tag))).collect{|id| + Tk::Tile::Treeview::Item.id2obj(self, id) + } + end + + def tag_bind(tag, seq, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind([@path, 'tag', 'bind', tag], seq, cmd, *args) + self + end + alias tagbind tag_bind + + def tag_bind_append(tag, seq, *args) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append([@path, 'tag', 'bind', tag], seq, cmd, *args) + self + end + alias tagbind_append tag_bind_append + + def tag_bind_remove(tag, seq) + _bind_remove([@path, 'tag', 'bind', tag], seq) + self + end + alias tagbind_remove tag_bind_remove + + def tag_bindinfo(tag, context=nil) + _bindinfo([@path, 'tag', 'bind', tag], context) + end + alias tagbindinfo tag_bindinfo + + def tag_names + tk_split_simplelist(tk_send('tag', 'names')).collect{|id| + Tk::Tile::Treeview::Tag.id2obj(self, id) + } + end + + def tag_add(tag, *items) + fail ArgumentError, "no target items" if items.empty? + tk_send('tag', 'add', tagid(tag), *(items.collect{|item| tagid(item)})) + self + end + + def tag_remove(tag, *items) + tk_send('tag', 'remove', tagid(tag), *(items.collect{|item| tagid(item)})) + self + end + +end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Treeview, :TkTreeview) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/treeview.rb', + :Ttk, Tk::Tile::Treeview, :TkTreeview) diff --git a/jni/ruby/ext/tk/lib/tkextlib/tile/tscale.rb b/jni/ruby/ext/tk/lib/tkextlib/tile/tscale.rb new file mode 100644 index 0000000..7eefcef --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tile/tscale.rb @@ -0,0 +1,56 @@ +# +# tscale & tprogress widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' +require 'tkextlib/tile.rb' + +module Tk + module Tile + class TScale < Tk::Scale + end + Scale = TScale + + class TProgress < TScale + end + Progress = TProgress + end +end + +class Tk::Tile::TScale < Tk::Scale + include Tk::Tile::TileWidget + + if Tk::Tile::USE_TTK_NAMESPACE + TkCommandNames = ['::ttk::scale'.freeze].freeze + else + TkCommandNames = ['::tscale'.freeze].freeze + end + WidgetClassName = 'TScale'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def self.style(*args) + [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') + end + + alias identify ttk_identify +end + +class Tk::Tile::TProgress < Tk::Tile::TScale + include Tk::Tile::TileWidget + + if Tk::Tile::USE_TTK_NAMESPACE + TkCommandNames = ['::ttk::progress'.freeze].freeze + else + TkCommandNames = ['::tprogress'.freeze].freeze + end + WidgetClassName = 'TProgress'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def self.style(*args) + [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') + end +end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Scale, :TkScale) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tscale.rb', + :Ttk, Tk::Tile::Scale, :TkScale) diff --git a/jni/ruby/ext/tk/lib/tkextlib/tile/tscrollbar.rb b/jni/ruby/ext/tk/lib/tkextlib/tile/tscrollbar.rb new file mode 100644 index 0000000..c6bba58 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tile/tscrollbar.rb @@ -0,0 +1,63 @@ +# +# tscrollbar widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' +require 'tkextlib/tile.rb' + +module Tk + module Tile + class TScrollbar < Tk::Scrollbar + end + Scrollbar = TScrollbar + end +end + +class Tk::Tile::TScrollbar < Tk::Scrollbar + include Tk::Tile::TileWidget + + if Tk::Tile::USE_TTK_NAMESPACE + TkCommandNames = ['::ttk::scrollbar'.freeze].freeze + else + TkCommandNames = ['::tscrollbar'.freeze].freeze + end + WidgetClassName = 'TScrollbar'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def self.style(*args) + [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') + end + + alias identify ttk_identify +end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Scrollbar, :TkScrollbar) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tscrollbar.rb', + :Ttk, Tk::Tile::Scrollbar, :TkScrollbar) + +####################################################################### + +class Tk::Tile::XScrollbar < Tk::Tile::TScrollbar + def create_self(keys) + keys = {} unless keys + keys['orient'] = 'horizontal' + super(keys) + end + private :create_self +end + +class Tk::Tile::YScrollbar < Tk::Tile::TScrollbar + def create_self(keys) + keys = {} unless keys + keys['orient'] = 'vertical' + super(keys) + end + private :create_self +end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::XScrollbar, :TkXScrollbar) +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::YScrollbar, :TkYScrollbar) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tscrollbar.rb', + :Ttk, Tk::Tile::XScrollbar, :TkXScrollbar) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tscrollbar.rb', + :Ttk, Tk::Tile::YScrollbar, :TkYScrollbar) diff --git a/jni/ruby/ext/tk/lib/tkextlib/tile/tseparator.rb b/jni/ruby/ext/tk/lib/tkextlib/tile/tseparator.rb new file mode 100644 index 0000000..ffd2f6f --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tile/tseparator.rb @@ -0,0 +1,34 @@ +# +# tseparator widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' +require 'tkextlib/tile.rb' + +module Tk + module Tile + class TSeparator < TkWindow + end + Separator = TSeparator + end +end + +class Tk::Tile::TSeparator < TkWindow + include Tk::Tile::TileWidget + + if Tk::Tile::USE_TTK_NAMESPACE + TkCommandNames = ['::ttk::separator'.freeze].freeze + else + TkCommandNames = ['::tseparator'.freeze].freeze + end + WidgetClassName = 'TSeparator'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def self.style(*args) + [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') + end +end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Separator, :TkSeparator) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tseparator.rb', + :Ttk, Tk::Tile::Separator, :TkSeparator) diff --git a/jni/ruby/ext/tk/lib/tkextlib/tile/tspinbox.rb b/jni/ruby/ext/tk/lib/tkextlib/tile/tspinbox.rb new file mode 100644 index 0000000..2f2d73c --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tile/tspinbox.rb @@ -0,0 +1,107 @@ +# +# ttk::spinbox widget (Tcl/Tk 8.6b1 or later) +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' +require 'tkextlib/tile.rb' + +module Tk + module Tile + class TSpinbox < Tk::Tile::TEntry + end + Spinbox = TSpinbox + end +end + +class Tk::Tile::TSpinbox < Tk::Tile::TEntry + include Tk::Tile::TileWidget + + if Tk::Tile::USE_TTK_NAMESPACE + TkCommandNames = ['::ttk::spinbox'.freeze].freeze + else + TkCommandNames = ['::tspinbox'.freeze].freeze + end + WidgetClassName = 'TSpinbox'.freeze + WidgetClassNames[WidgetClassName] ||= self + + class SpinCommand < TkValidateCommand + class ValidateArgs < TkUtil::CallbackSubst + KEY_TBL = [ + [ ?d, ?s, :direction ], + [ ?s, ?e, :current ], + [ ?W, ?w, :widget ], + nil + ] + + PROC_TBL = [ + [ ?s, TkComm.method(:string) ], + [ ?w, TkComm.method(:window) ], + + [ ?e, proc{|val| + #enc = Tk.encoding + enc = ((Tk.encoding)? Tk.encoding : Tk.encoding_system) + if enc + Tk.fromUTF8(TkComm::string(val), enc) + else + TkComm::string(val) + end + } + ], + + nil + ] + + _setup_subst_table(KEY_TBL, PROC_TBL); + + def self.ret_val(val) + (val)? '1': '0' + end + end + + def self._config_keys + ['command'] + end + end + + def __validation_class_list + super() << SpinCommand + end + + Tk::ValidateConfigure.__def_validcmd(binding, SpinCommand) + + def __boolval_optkeys + super() << 'wrap' + end + private :__boolval_optkeys + + def __strval_optkeys + super() << 'buttonbackground' << 'format' + end + private :__strval_optkeys + + def __listval_optkeys + super() << 'values' + end + private :__listval_optkeys + + def self.style(*args) + [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') + end + + def current + number(tk_send_without_enc('current')) + end + def current=(idx) + tk_send('current', idx) + end + + def set(val) + tk_send('set', val) + end + + alias identify ttk_identify +end + +#Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Spinbox, :TkSpinbox) +Tk.__set_loaded_toplevel_aliases__('tkextlib/tile/tspinbox.rb', + :Ttk, Tk::Tile::Spinbox, :TkSpinbox) diff --git a/jni/ruby/ext/tk/lib/tkextlib/tile/tsquare.rb b/jni/ruby/ext/tk/lib/tkextlib/tile/tsquare.rb new file mode 100644 index 0000000..a81cd7b --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tile/tsquare.rb @@ -0,0 +1,30 @@ +# +# tsquare widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' +require 'tkextlib/tile.rb' + +module Tk + module Tile + class TSquare < TkWindow + end + Square = TSquare + end +end + +class Tk::Tile::TSquare < TkWindow + include Tk::Tile::TileWidget + + if Tk::Tile::USE_TTK_NAMESPACE + TkCommandNames = ['::ttk::square'.freeze].freeze + else + TkCommandNames = ['::tsquare'.freeze].freeze + end + WidgetClassName = 'TSquare'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def self.style(*args) + [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.') + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkDND.rb b/jni/ruby/ext/tk/lib/tkextlib/tkDND.rb new file mode 100644 index 0000000..5d52e34 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkDND.rb @@ -0,0 +1,18 @@ +# +# TkDND (Tk Drag & Drop Extension) support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tkDND/setup.rb' + +module Tk + module TkDND + autoload :DND, 'tkextlib/tkDND/tkdnd' + autoload :Shape, 'tkextlib/tkDND/shape' + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkDND/setup.rb b/jni/ruby/ext/tk/lib/tkextlib/tkDND/setup.rb new file mode 100644 index 0000000..ee406c6 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkDND/setup.rb @@ -0,0 +1,8 @@ +# +# setup.rb -- setup script before calling TkPackage.require() +# +# If you need some setup operations (for example, add a library path +# to the library search path) before using Tcl/Tk library packages +# wrapped by Ruby scripts in this directory, please write the setup +# operations in this file. +# diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkDND/shape.rb b/jni/ruby/ext/tk/lib/tkextlib/tkDND/shape.rb new file mode 100644 index 0000000..d44068e --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkDND/shape.rb @@ -0,0 +1,125 @@ +# +# tkextlib/tkDND/shape.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tkDND/setup.rb' + +# TkPackage.require('Shape', '0.3') +TkPackage.require('Shape') + +module Tk + module TkDND + module Shape + extend TkCore + + PACKAGE_NAME = 'Shape'.freeze + def self.package_name + PACKAGE_NAME + end + +=begin + def self.package_version + begin + TkPackage.require('Shape') + rescue + '' + end + end +=end + class << self + def package_version + Tk.tk_call('set', 'shape_version') + end + alias shape_version package_version + + def package_patchlevel + Tk.tk_call('set', 'shape_patchLevel') + end + alias shape_patchlevel package_patchlevel + + def version + tk_call('shape', 'version') + end + alias xshape_version version + end + + ############################ + + def shape_bounds(kind=nil) + if kind + ret = tk_call('shape', 'bounds', @path, "-#{kind}") + else + ret = tk_call('shape', 'bounds', @path) + end + if ret == "" + nil + else + list(ret) + end + end + + def shape_get(kind=nil) + if kind + list(tk_call('shape', 'get', @path, "-#{kind}")) + else + list(tk_call('shape', 'get', @path)) + end + end + + def shape_offset(x, y, kind=nil) + if kind + tk_call('shape', 'get', @path, "-#{kind}", x, y) + else + tk_call('shape', 'get', @path, x, y) + end + self + end + + def _parse_shapespec_param(args) + cmd = [] + + kind_keys = ['bounding', 'clip', 'both'] + offset_keys = ['offset'] + srckind_keys = ['bitmap', 'rectangles', 'reset', 'test', 'window'] + + cmd << "-#{args.shift}" if kind_keys.member?(args[0].to_s) + + if offset_keys.member?(args[0].to_s) + cmd << "-#{args.shift}" + cmd << args.shift # xOffset + cmd << args.shift # yOffset + end + + if srckind_keys.member?(args[0].to_s) + cmd << "-#{args.shift}" + end + + cmd.concat(args) + + cmd + end + private :_parse_shapespec_param + + def shape_set(*args) # ?kind? ?offset <x> <y>? srckind ?arg ...? + tk_call('shape', 'set', @path, *(_parse_shapespec_param(args))) + self + end + + def shape_update(op, *args) # ?kind? ?offset <x> <y>? srckind ?arg ...? + tk_call('shape', 'update', @path, op, *(_parse_shapespec_param(args))) + self + end + end + end +end + +class TkWindow + include Tk::TkDND::Shape +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkDND/tkdnd.rb b/jni/ruby/ext/tk/lib/tkextlib/tkDND/tkdnd.rb new file mode 100644 index 0000000..38e05ce --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkDND/tkdnd.rb @@ -0,0 +1,182 @@ +# +# tkextlib/tkDND/tkdnd.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tkDND/setup.rb' + +TkPackage.require('tkdnd') + +module Tk + module TkDND + PACKAGE_NAME = 'tkdnd'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('tkdnd') + rescue + '' + end + end + + class DND_Subst < TkUtil::CallbackSubst + KEY_TBL = [ + [ ?a, ?l, :actions ], + [ ?A, ?s, :action ], + [ ?b, ?L, :codes ], + [ ?c, ?s, :code ], + [ ?d, ?l, :descriptions ], + [ ?D, ?l, :data ], + [ ?L, ?l, :source_types ], + [ ?m, ?l, :modifiers ], + [ ?t, ?l, :types ], + [ ?T, ?s, :type ], + [ ?W, ?w, :widget ], + [ ?x, ?n, :x ], + [ ?X, ?n, :x_root ], + [ ?y, ?n, :y ], + [ ?Y, ?n, :y_root ], + nil + ] + + PROC_TBL = [ + [ ?n, TkComm.method(:num_or_str) ], + [ ?s, TkComm.method(:string) ], + [ ?l, TkComm.method(:list) ], + [ ?L, TkComm.method(:simplelist) ], + [ ?w, TkComm.method(:window) ], + nil + ] + +=begin + # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) + KEY_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) + end + inf + } + + PROC_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + end + inf + } +=end + + # setup tables + _setup_subst_table(KEY_TBL, PROC_TBL); + end + + module DND + def self.version + begin + TkPackage.require('tkdnd') + rescue + '' + end + end + + def dnd_bindtarget_info(type=nil, event=nil) + if event + procedure(tk_call('dnd', 'bindtarget', @path, type, event)) + elsif type + procedure(tk_call('dnd', 'bindtarget', @path, type)) + else + simplelist(tk_call('dnd', 'bindtarget', @path)) + end + end + + #def dnd_bindtarget(type, event, cmd=Proc.new, prior=50, *args) + # event = tk_event_sequence(event) + # if prior.kind_of?(Numeric) + # tk_call('dnd', 'bindtarget', @path, type, event, + # install_bind_for_event_class(DND_Subst, cmd, *args), + # prior) + # else + # tk_call('dnd', 'bindtarget', @path, type, event, + # install_bind_for_event_class(DND_Subst, cmd, prior, *args)) + # end + # self + #end + def dnd_bindtarget(type, event, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + + prior = 50 + prior = args.shift unless args.empty? + + event = tk_event_sequence(event) + if prior.kind_of?(Numeric) + tk_call('dnd', 'bindtarget', @path, type, event, + install_bind_for_event_class(DND_Subst, cmd, *args), + prior) + else + tk_call('dnd', 'bindtarget', @path, type, event, + install_bind_for_event_class(DND_Subst, cmd, prior, *args)) + end + self + end + + def dnd_cleartarget + tk_call('dnd', 'cleartarget', @path) + self + end + + def dnd_bindsource_info(type=nil) + if type + procedure(tk_call('dnd', 'bindsource', @path, type)) + else + simplelist(tk_call('dnd', 'bindsource', @path)) + end + end + + #def dnd_bindsource(type, cmd=Proc.new, prior=None) + # tk_call('dnd', 'bindsource', @path, type, cmd, prior) + # self + #end + def dnd_bindsource(type, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + + args = [TkComm::None] if args.empty? + + tk_call('dnd', 'bindsource', @path, type, cmd, *args) + self + end + + def dnd_clearsource() + tk_call('dnd', 'clearsource', @path) + self + end + + def dnd_drag(keys=nil) + tk_call('dnd', 'drag', @path, *hash_kv(keys)) + self + end + end + end +end + +class TkWindow + include Tk::TkDND::DND +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkHTML.rb b/jni/ruby/ext/tk/lib/tkextlib/tkHTML.rb new file mode 100644 index 0000000..5fddde7 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkHTML.rb @@ -0,0 +1,13 @@ +# +# TkHtml support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tkHTML/setup.rb' + +# load library +require 'tkextlib/tkHTML/htmlwidget' diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb b/jni/ruby/ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb new file mode 100644 index 0000000..b9ee90a --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb @@ -0,0 +1,453 @@ +# +# tkextlib/tkHTML/htmlwidget.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tkHTML/setup.rb' + +# TkPackage.require('Tkhtml', '2.0') +TkPackage.require('Tkhtml') + +module Tk + class HTML_Widget < TkWindow + PACKAGE_NAME = 'Tkhtml'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('Tkhtml') + rescue + '' + end + end + + class ClippingWindow < TkWindow + end + end +end + +class Tk::HTML_Widget::ClippingWindow + WidgetClassName = 'HtmlClip'.freeze + WidgetClassNames[WidgetClassName] ||= self + + HtmlClip_TBL = TkCore::INTERP.create_table + + TkCore::INTERP.init_ip_env{ + HtmlClip_TBL.mutex.synchronize{ HtmlClip_TBL.clear } + } + + def self.new(parent, keys={}) + if parent.kind_of?(Hash) + keys = TkComm._symbolkey2str(parent) + parent = keys.delete('parent') + end + + if parent.kind_of?(String) + ppath = parent.path + elsif parent + ppath = parent + else + ppath = '' + end + HtmlClip_TBL.mutex.synchronize{ + return HtmlClip_TBL[ppath] if HtmlClip_TBL[ppath] + } + + widgetname = keys.delete('widgetname') + if widgetname =~ /^(.*)\.[^.]+$/ + ppath2 = $1 + if ppath2[0] != ?. + ppath2 = ppath + '.' + ppath2 + end + HtmlClip_TBL.mutex.synchronize{ + return HtmlClip_TBL[ppath2] if HtmlClip_TBL[ppath2] + } + + ppath = ppath2 + end + + parent = TkComm._genobj_for_tkwidget(ppath) + unless parent.kind_of?(Tk::HTML_Widget) + fail ArgumentError, "parent must be a Tk::HTML_Widget instance" + end + + super(parent) + end + + def initialize(parent) + @parent = parent + @ppath = parent.path + @path = @id = @ppath + '.x' + HtmlClip_TBL.mutex.synchronize{ + HtmlClip_TBL[@ppath] = self + } + end + + def method_missing(m, *args, &b) + @parent.__send__(m, *args, &b) + end +end + +class Tk::HTML_Widget + include Scrollable + + TkCommandNames = ['html'.freeze].freeze + WidgetClassName = 'Html'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def create_self(keys) + if keys and keys != None + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self + + def __strval_optkeys + super() << 'base' << 'selectioncolor' << 'unvisitedcolor' << 'visitedcolor' + end + private :__strval_optkeys + + ################################### + # class methods + ################################### + def self.reformat(src, dst, txt) + tk_call('html', 'reformat', src, dst, txt) + end + + def self.url_join(*args) # args := sheme authority path query fragment + tk_call('html', 'urljoin', *args) + end + + def self.url_split(uri) + tk_call('html', 'urlsplit', uri) + end + + def self.lockcopy(src, dst) + tk_call('html', 'lockcopy', src, dst) + end + + def self.gzip_file(file, dat) + tk_call('html', 'gzip', 'file', file, dat) + end + + def self.gunzip_file(file, dat) + tk_call('html', 'gunzip', 'file', filet) + end + + def self.gzip_data(dat) + tk_call('html', 'gzip', 'data', file, dat) + end + + def self.gunzip_data(dat) + tk_call('html', 'gunzip', 'data', filet) + end + + def self.base64_encode(dat) + tk_call('html', 'base64', 'encode', dat) + end + + def self.base64_decode(dat) + tk_call('html', 'base64', 'encode', dat) + end + + def self.text_format(dat, len) + tk_call('html', 'text', 'format', dat, len) + end + + def self.xor(cmd, *args) + tk_call('html', 'xor', cmd, *args) + end + + def self.stdchan(cmd, channel) + tk_call('html', 'stdchan', cmd, channel) + end + + def self.crc32(data) + tk_call('html', 'crc32', data) + end + + ################################### + # instance methods + ################################### + def clipping_window + ClippingWindow.new(self) + end + alias clipwin clipping_window + alias htmlclip clipping_window + + def bgimage(image, tid=None) + tk_send('bgimage', image, tid) + self + end + + def clear() + tk_send('clear') + self + end + + def coords(index=None, percent=None) + tk_send('coords', index, percent) + end + + def forminfo(*args) + tk_send('forminfo', *args) + end + alias form_info forminfo + + def href(x, y) + simplelist(tk_send('href', x, y)) + end + + def image_add(id, img) + tk_send('imageadd', id, img) + self + end + + def image_at(x, y) + tk_send('imageat', x, y) + end + + def images() + list(tk_send('images')) + end + + def image_set(id, num) + tk_send('imageset', id, num) + self + end + + def image_update(id, imgs) + tk_send('imageupdate', id, imgs) + self + end + + def index(idx, count=None, unit=None) + tk_send('index', idx, count, unit) + end + + def insert_cursor(idx) + tk_send('insert', idx) + end + + def names() + simple_list(tk_send('names')) + end + + def on_screen(id, x, y) + bool(tk_send('onscreen', id, x, y)) + end + + def over(x, y) + list(tk_send('over', x, y)) + end + + def over_markup(x, y) + list(tk_send('over', x, y, '-muponly')) + end + + def over_attr(x, y, attrs) + list(tk_send('overattr', x, y, attrs)) + end + + def parse(txt) + tk_send('parse', txt) + self + end + + def resolver(*uri_args) + tk_send('resolver', *uri_args) + end + + def selection_clear() + tk_send('selection', 'clear') + self + end + + def selection_set(first, last) + tk_send('selection', 'set', first, last) + self + end + + def refresh(*opts) + tk_send('refresh', *opts) + end + + def layout() + tk_send('layout') + end + + def sizewindow(*args) + tk_send('sizewindow', *args) + end + + def postscript(*args) + tk_send('postscript', *args) + end + + def source() + tk_send('source') + end + + def plain_text(first, last) + tk_send('text', 'ascii', first, last) + end + alias ascii_text plain_text + alias text_ascii plain_text + + def text_delete(first, last) + tk_send('text', 'delete', first, last) + self + end + + def html_text(first, last) + tk_send('text', 'html', first, last) + end + alias text_html html_text + + def text_insert(idx, txt) + tk_send('text', 'insert', idx, txt) + self + end + + def break_text(idx) + tk_send('text', 'break', idx) + end + alias text_break break_text + + def text_find(txt, *args) + tk_send('text', 'find', txt, *args) + end + + def text_table(idx, imgs=None, attrs=None) + tk_send('text', 'table', idx, imgs, attrs) + end + + def token_append(tag, *args) + tk_send('token', 'append', tag, *args) + self + end + + def token_delete(first, last=None) + tk_send('token', 'delete', first, last) + self + end + + def token_define(*args) + tk_send('token', 'defile', *args) + self + end + + def token_find(tag, *args) + list(tk_send('token', 'find', tag, *args)) + end + + def token_get(first, last=None) + list(tk_send('token', 'get', first, last)) + end + + def token_list(first, last=None) + list(tk_send('token', 'list', first, last)) + end + + def token_markup(first, last=None) + list(tk_send('token', 'markup', first, last)) + end + + def token_DOM(first, last=None) + list(tk_send('token', 'domtokens', first, last)) + end + alias token_dom token_DOM + alias token_domtokens token_DOM + alias token_dom_tokens token_DOM + + def token_get_end(idx) + tk_send('token', 'getend', idx) + end + alias token_getend token_get_end + + def token_offset(start, num1, num2) + list(tk_send('token', 'offset', start, num1, num2)) + end + + def token_get_attr(idx, name=None) + list(tk_send('token', 'attr', idx, name)) + end + + def token_set_attr(idx, name=None, val=None) + tk_send('token', 'attr', idx, name, val) + self + end + + def token_handler(tag, cmd=nil, &b) + cmd = Proc.new(&b) if !cmd && b + if cmd + tk_send('token', 'handler', tag, cmd) + return self + else + return tk_send('token', 'handler', tag) + end + end + + def token_insert(idx, tag, *args) + tk_send('token', 'insert', idx, tag, *args) + self + end + + def token_attrs(*args) + list(tk_send('token', 'attrs', *args)) + end + + def token_unique(*args) + list(tk_send('token', 'unique', *args)) + end + + def token_on_events(*args) + list(tk_send('token', 'onEvents', *args)) + end + + def dom_nameidx(tag, name) + number(tk_send('dom', 'nameidx', tag, name)) + end + alias dom_name_index dom_nameidx + + def dom_radioidx(tag, name) + number(tk_send('dom', 'radioidx', tag, name)) + end + alias dom_radio_index dom_radioidx + + def dom_id(*spec) + tk_send('dom', 'id', *spec) + end + + def dom_ids(*spec) + list(tk_send('dom', 'ids', *spec)) + end + + def dom_value(*spec) + list(tk_send('dom', 'value', *spec)) + end + + def dom_attr(idx) + tk_send('dom', 'attr', idx) + end + + def dom_formel(name) + tk_send('dom', 'formel', name) + end + alias dom_form_element dom_formel + + def dom_tree(idx, val) + list(tk_send('dom', 'tree', idx, val)) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkHTML/setup.rb b/jni/ruby/ext/tk/lib/tkextlib/tkHTML/setup.rb new file mode 100644 index 0000000..ee406c6 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkHTML/setup.rb @@ -0,0 +1,8 @@ +# +# setup.rb -- setup script before calling TkPackage.require() +# +# If you need some setup operations (for example, add a library path +# to the library search path) before using Tcl/Tk library packages +# wrapped by Ruby scripts in this directory, please write the setup +# operations in this file. +# diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkimg.rb b/jni/ruby/ext/tk/lib/tkextlib/tkimg.rb new file mode 100644 index 0000000..c01359d --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkimg.rb @@ -0,0 +1,36 @@ +# +# TkImg extension support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tkimg/setup.rb' + +# load all image format handlers +#TkPackage.require('Img', '1.3') +TkPackage.require('Img') + +module Tk + module Img + PACKAGE_NAME = 'Img'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('Img') + rescue + '' + end + end + end +end + +# autoload +autoload :TkPixmapImage, 'tkextlib/tkimg/pixmap' diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkimg/README b/jni/ruby/ext/tk/lib/tkextlib/tkimg/README new file mode 100644 index 0000000..f5981cb --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkimg/README @@ -0,0 +1,26 @@ + + [ Tcl/Tk Image formats (TkImg) support ] + +TkImg contains a collection of format handlers for the Tk photo +image type, and a new image type, pixmaps. + +Supported formats of TkImg version 1.3 are +------------------------------------------------------- + bmp : Windows Bitmap Format + gif : Graphics Interchange Format + ico : Windows Icon Format + jpeg : Joint Picture Expert Group format + pcx : Paintbrush Format + pixmap : Pixmap Image type + png : Portable Network Graphics format + ppm : Portable Pixmap format + ps : Adobe PostScript Format + sgi : SGI Native Format + sun : Sun Raster Format + tga : Truevision Targa Format + tiff : Tagged Image File Format + window : Tk Windows + xbm : X Window Bitmap Format + xpm : X Window Pixmap Format +------------------------------------------------------- + diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkimg/bmp.rb b/jni/ruby/ext/tk/lib/tkextlib/tkimg/bmp.rb new file mode 100644 index 0000000..ea90181 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkimg/bmp.rb @@ -0,0 +1,33 @@ +# +# TkImg - format 'bmp' +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tkimg/setup.rb' + +#TkPackage.require('img::bmp', '1.3') +TkPackage.require('img::bmp') + +module Tk + module Img + module BMP + PACKAGE_NAME = 'img::bmp'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('img::bmp') + rescue + '' + end + end + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkimg/dted.rb b/jni/ruby/ext/tk/lib/tkextlib/tkimg/dted.rb new file mode 100644 index 0000000..cae8336 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkimg/dted.rb @@ -0,0 +1,33 @@ +# +# TkImg - format 'DTED' +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tkimg/setup.rb' + +# TkPackage.require('img::dted', '1.4') +TkPackage.require('img::dted') + +module Tk + module Img + module DTED + PACKAGE_NAME = 'img::dted'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('img::dted') + rescue + '' + end + end + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkimg/gif.rb b/jni/ruby/ext/tk/lib/tkextlib/tkimg/gif.rb new file mode 100644 index 0000000..d542d47 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkimg/gif.rb @@ -0,0 +1,33 @@ +# +# TkImg - format 'gif' +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tkimg/setup.rb' + +# TkPackage.require('img::gif', '1.3') +TkPackage.require('img::gif') + +module Tk + module Img + module GIF + PACKAGE_NAME = 'img::gif'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('img::gif') + rescue + '' + end + end + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkimg/ico.rb b/jni/ruby/ext/tk/lib/tkextlib/tkimg/ico.rb new file mode 100644 index 0000000..e79bdf4 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkimg/ico.rb @@ -0,0 +1,33 @@ +# +# TkImg - format 'ico' +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tkimg/setup.rb' + +# TkPackage.require('img::ico', '1.3') +TkPackage.require('img::ico') + +module Tk + module Img + module ICO + PACKAGE_NAME = 'img::ico'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('img::ico') + rescue + '' + end + end + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkimg/jpeg.rb b/jni/ruby/ext/tk/lib/tkextlib/tkimg/jpeg.rb new file mode 100644 index 0000000..2126120 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkimg/jpeg.rb @@ -0,0 +1,33 @@ +# +# TkImg - format 'jpeg' +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tkimg/setup.rb' + +# TkPackage.require('img::jpeg', '1.3') +TkPackage.require('img::jpeg') + +module Tk + module Img + module JPEG + PACKAGE_NAME = 'img::jpeg'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('img::jpeg') + rescue + '' + end + end + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkimg/pcx.rb b/jni/ruby/ext/tk/lib/tkextlib/tkimg/pcx.rb new file mode 100644 index 0000000..6831f4d --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkimg/pcx.rb @@ -0,0 +1,33 @@ +# +# TkImg - format 'pcx' +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tkimg/setup.rb' + +# TkPackage.require('img::pcx', '1.3') +TkPackage.require('img::pcx') + +module Tk + module Img + module PCX + PACKAGE_NAME = 'img::pcx'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('img::pcx') + rescue + '' + end + end + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkimg/pixmap.rb b/jni/ruby/ext/tk/lib/tkextlib/tkimg/pixmap.rb new file mode 100644 index 0000000..bd1b870 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkimg/pixmap.rb @@ -0,0 +1,44 @@ +# +# TkImg - format 'pixmap' +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tkimg/setup.rb' + +# TkPackage.require('img::pixmap', '1.3') +TkPackage.require('img::pixmap') + +module Tk + module Img + module PIXMAP + PACKAGE_NAME = 'img::pixmap'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('img::pixmap') + rescue + '' + end + end + end + end +end + +class TkPixmapImage<TkImage + def self.version + Tk::Img::PIXMAP.version + end + + def initialize(*args) + @type = 'pixmap' + super(*args) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkimg/png.rb b/jni/ruby/ext/tk/lib/tkextlib/tkimg/png.rb new file mode 100644 index 0000000..5c829f4 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkimg/png.rb @@ -0,0 +1,33 @@ +# +# TkImg - format 'png' +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tkimg/setup.rb' + +# TkPackage.require('img::png', '1.3') +TkPackage.require('img::png') + +module Tk + module Img + module PNG + PACKAGE_NAME = 'img::png'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('img::png') + rescue + '' + end + end + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkimg/ppm.rb b/jni/ruby/ext/tk/lib/tkextlib/tkimg/ppm.rb new file mode 100644 index 0000000..eacfae4 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkimg/ppm.rb @@ -0,0 +1,33 @@ +# +# TkImg - format 'ppm' +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tkimg/setup.rb' + +# TkPackage.require('img::ppm', '1.3') +TkPackage.require('img::ppm') + +module Tk + module Img + module PPM + PACKAGE_NAME = 'img::ppm'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('img::ppm') + rescue + '' + end + end + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkimg/ps.rb b/jni/ruby/ext/tk/lib/tkextlib/tkimg/ps.rb new file mode 100644 index 0000000..68e9178 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkimg/ps.rb @@ -0,0 +1,33 @@ +# +# TkImg - format 'ps' +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tkimg/setup.rb' + +# TkPackage.require('img::ps', '1.3') +TkPackage.require('img::ps') + +module Tk + module Img + module PS + PACKAGE_NAME = 'img::ps'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('img::ps') + rescue + '' + end + end + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkimg/raw.rb b/jni/ruby/ext/tk/lib/tkextlib/tkimg/raw.rb new file mode 100644 index 0000000..5f1cdca --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkimg/raw.rb @@ -0,0 +1,33 @@ +# +# TkImg - format 'Raw Data' +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tkimg/setup.rb' + +# TkPackage.require('img::raw', '1.4') +TkPackage.require('img::raw') + +module Tk + module Img + module Raw + PACKAGE_NAME = 'img::raw'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('img::raw') + rescue + '' + end + end + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkimg/setup.rb b/jni/ruby/ext/tk/lib/tkextlib/tkimg/setup.rb new file mode 100644 index 0000000..ee406c6 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkimg/setup.rb @@ -0,0 +1,8 @@ +# +# setup.rb -- setup script before calling TkPackage.require() +# +# If you need some setup operations (for example, add a library path +# to the library search path) before using Tcl/Tk library packages +# wrapped by Ruby scripts in this directory, please write the setup +# operations in this file. +# diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkimg/sgi.rb b/jni/ruby/ext/tk/lib/tkextlib/tkimg/sgi.rb new file mode 100644 index 0000000..ec7038b --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkimg/sgi.rb @@ -0,0 +1,33 @@ +# +# TkImg - format 'sgi' +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tkimg/setup.rb' + +# TkPackage.require('img::sgi', '1.3') +TkPackage.require('img::sgi') + +module Tk + module Img + module SGI + PACKAGE_NAME = 'img::sgi'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('img::sgi') + rescue + '' + end + end + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkimg/sun.rb b/jni/ruby/ext/tk/lib/tkextlib/tkimg/sun.rb new file mode 100644 index 0000000..651f946 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkimg/sun.rb @@ -0,0 +1,33 @@ +# +# TkImg - format 'sun' +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tkimg/setup.rb' + +# TkPackage.require('img::sun', '1.3') +TkPackage.require('img::sun') + +module Tk + module Img + module SUN + PACKAGE_NAME = 'img::sun'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('img::sun') + rescue + '' + end + end + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkimg/tga.rb b/jni/ruby/ext/tk/lib/tkextlib/tkimg/tga.rb new file mode 100644 index 0000000..1eae407 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkimg/tga.rb @@ -0,0 +1,33 @@ +# +# TkImg - format 'tga' +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tkimg/setup.rb' + +# TkPackage.require('img::tga', '1.3') +TkPackage.require('img::tga') + +module Tk + module Img + module TGA + PACKAGE_NAME = 'img::tga'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('img::tga') + rescue + '' + end + end + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkimg/tiff.rb b/jni/ruby/ext/tk/lib/tkextlib/tkimg/tiff.rb new file mode 100644 index 0000000..ed271c2 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkimg/tiff.rb @@ -0,0 +1,33 @@ +# +# TkImg - format 'tiff' +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tkimg/setup.rb' + +# TkPackage.require('img::tiff', '1.3') +TkPackage.require('img::tiff') + +module Tk + module Img + module TIFF + PACKAGE_NAME = 'img::tiff'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('img::tiff') + rescue + '' + end + end + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkimg/window.rb b/jni/ruby/ext/tk/lib/tkextlib/tkimg/window.rb new file mode 100644 index 0000000..3b5906f --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkimg/window.rb @@ -0,0 +1,33 @@ +# +# TkImg - format 'window' +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tkimg/setup.rb' + +# TkPackage.require('img::window', '1.3') +TkPackage.require('img::window') + +module Tk + module Img + module WINDOW + PACKAGE_NAME = 'img::window'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('img::window') + rescue + '' + end + end + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkimg/xbm.rb b/jni/ruby/ext/tk/lib/tkextlib/tkimg/xbm.rb new file mode 100644 index 0000000..f4bea03 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkimg/xbm.rb @@ -0,0 +1,33 @@ +# +# TkImg - format 'xbm' +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tkimg/setup.rb' + +# TkPackage.require('img::xbm', '1.3') +TkPackage.require('img::xbm') + +module Tk + module Img + module XBM + PACKAGE_NAME = 'img::xbm'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('img::xbm') + rescue + '' + end + end + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tkimg/xpm.rb b/jni/ruby/ext/tk/lib/tkextlib/tkimg/xpm.rb new file mode 100644 index 0000000..5119c87 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tkimg/xpm.rb @@ -0,0 +1,33 @@ +# +# TkImg - format 'xpm' +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tkimg/setup.rb' + +# TkPackage.require('img::xpm', '1.3') +TkPackage.require('img::xpm') + +module Tk + module Img + module XPM + PACKAGE_NAME = 'img::xpm'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('img::xpm') + rescue + '' + end + end + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tktable.rb b/jni/ruby/ext/tk/lib/tkextlib/tktable.rb new file mode 100644 index 0000000..385eb13 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tktable.rb @@ -0,0 +1,14 @@ +# +# TkTable support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tktable/setup.rb' + +# load library +require 'tkextlib/tktable/tktable' diff --git a/jni/ruby/ext/tk/lib/tkextlib/tktable/setup.rb b/jni/ruby/ext/tk/lib/tkextlib/tktable/setup.rb new file mode 100644 index 0000000..ee406c6 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tktable/setup.rb @@ -0,0 +1,8 @@ +# +# setup.rb -- setup script before calling TkPackage.require() +# +# If you need some setup operations (for example, add a library path +# to the library search path) before using Tcl/Tk library packages +# wrapped by Ruby scripts in this directory, please write the setup +# operations in this file. +# diff --git a/jni/ruby/ext/tk/lib/tkextlib/tktable/tktable.rb b/jni/ruby/ext/tk/lib/tkextlib/tktable/tktable.rb new file mode 100644 index 0000000..f707465 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tktable/tktable.rb @@ -0,0 +1,966 @@ +# +# tkextlib/tktable/tktable.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' +require 'tk/validation' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tktable/setup.rb' + +# TkPackage.require('Tktable', '2.8') +TkPackage.require('Tktable') + +module Tk + class TkTable < TkWindow + PACKAGE_NAME = 'Tktable'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('Tktable') + rescue + '' + end + end + + class CellTag < TkObject + end + + module ConfigMethod + end + end +end + +module Tk::TkTable::ConfigMethod + include TkItemConfigMethod + + def __item_cget_cmd(id) # id := [ type, tagOrId ] + [self.path, id[0], 'cget', id[1]] + end + private :__item_cget_cmd + + def __item_config_cmd(id) # id := [ type, tagOrId ] + [self.path, id[0], 'configure', id[1]] + end + private :__item_config_cmd + + def __item_pathname(id) + if id.kind_of?(Array) + id = tagid(id[1]) + end + [self.path, id].join(';') + end + private :__item_pathname + + def __item_boolval_optkeys(id) + super(id) << 'multiline' << 'showtext' << 'wrap' + end + private :__item_boolval_optkeys + + def __item_strval_optkeys(id) + super(id) << 'ellipsis' + end + private :__item_strval_optkeys + + def __item_val2ruby_optkeys(id) # { key=>method, ... } + super(id).update('window'=>proc{|k,v| window(v)}) + end + private :__item_val2ruby_optkeys + + def tag_cget_tkstring(tagOrId, option) + itemcget_tkstring(['tag', tagid(tagOrId)], option) + end + def tag_cget(tagOrId, option) + itemcget(['tag', tagid(tagOrId)], option) + end + def tag_cget_strict(tagOrId, option) + itemcget_strict(['tag', tagid(tagOrId)], option) + end + def tag_configure(tagOrId, slot, value=None) + itemconfigure(['tag', tagid(tagOrId)], slot, value) + end + def tag_configinfo(tagOrId, slot=nil) + itemconfiginfo(['tag', tagid(tagOrId)], slot) + end + def current_tag_configinfo(tagOrId, slot=nil) + current_itemconfiginfo(['tag', tagid(tagOrId)], slot) + end + + def window_cget_tkstring(tagOrId, option) + itemcget_tkstring(['window', tagid(tagOrId)], option) + end + def window_cget(tagOrId, option) + itemcget(['window', tagid(tagOrId)], option) + end + def window_cget_strict(tagOrId, option) + itemcget_strict(['window', tagid(tagOrId)], option) + end + def window_configure(tagOrId, slot, value=None) + if slot == :window || slot == 'window' + value = _epath(value) + elsif slot.kind_of?(Hash) + if slot.key?(:window) || slot.key?('window') + slot = _symbolkey2str(slot) + slot['window'] = _epath(slot['window']) + end + end + itemconfigure(['window', tagid(tagOrId)], slot, value) + end + def window_configinfo(tagOrId, slot=nil) + itemconfiginfo(['window', tagid(tagOrId)], slot) + end + def current_window_configinfo(tagOrId, slot=nil) + current_itemconfiginfo(['window', tagid(tagOrId)], slot) + end + + private :itemcget_tkstring, :itemcget, :itemcget_strict + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo +end + +##################################################### + +class Tk::TkTable::CellTag + include TkTreatTagFont + + CellTagID_TBL = TkCore::INTERP.create_table + + (CellTag_ID = ['tktbl:celltag'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + TkCore::INTERP.init_ip_env{ + CellTagID_TBL.mutex.synchronize{ CellTagID_TBL.clear } + } + + def self.id2obj(table, id) + tpath = table.path + CellTagID_TBL.mutex.synchronize{ + if CellTagID_TBL[tpath] + CellTagID_TBL[tpath][id]? CellTagID_TBL[tpath][id] : id + else + id + end + } + end + + def initialize(parent, keys=nil) + @parent = @t = parent + @tpath - parent.path + CellTag_ID.mutex.synchronize{ + @path = @id = CellTag_ID.join(TkCore::INTERP._ip_id_) + CellTag_ID[1].succ! + } + CellTagID_TBL.mutex.synchronize{ + CellTagID_TBL[@tpath] = {} unless CellTagID_TBL[@tpath] + CellTagID_TBL[@tpath][@id] = self + } + configure(keys) if keys + end + + def id + @id + end + + def destroy + tk_call(@tpath, 'tag', 'delete', @id) + CellTagID_TBL.mutex.synchronize{ + CellTagID_TBL[@tpath].delete(@id) if CellTagID_TBL[@tpath] + } + self + end + alias delete destroy + + def exist? + @t.tag_exist?(@id) + end + def include?(idx) + @t.tag_include?(@id, idx) + end + + def add_cell(*args) + @t.tag_cell(@id, *args) + end + def add_col(*args) + @t.tag_col(@id, *args) + end + def add_row(*args) + @t.tag_row(@id, *args) + end + + def raise(target=None) + @t.tag_raise(@id, target) + end + def lower(target=None) + @t.tag_lower(@id, target) + end + + def cget_tkstring(key) + @t.tag_cget_tkstring(@id, key) + end + def cget(key) + @t.tag_cget(@id, key) + end + def cget_strict(key) + @t.tag_cget_strict(@id, key) + end + def configure(key, val=None) + @t.tag_configure(@id, key, val) + end + def configinfo(key=nil) + @t.tag_configinfo(@id, key) + end + def current_configinfo(key=nil) + @t.current_tag_configinfo(@id, key) + end +end + +class Tk::TkTable::NamedCellTag < Tk::TkTable::CellTag + def self.new(parent, name, keys=nil) + obj = nil + CellTagID_TBL.mutex.synchronize{ + if CellTagID_TBL[parent.path] && CellTagID_TBL[parent.path][name] + obj = CellTagID_TBL[parent.path][name] + else + #super(parent, name, keys) + (obj = self.allocate).instance_eval{ + @parent = @t = parent + @tpath = parent.path + @path = @id = name + CellTagID_TBL[@tpath] = {} unless CellTagID_TBL[@tpath] + CellTagID_TBL[@tpath][@id] = self + } + end + } + obj.configure(keys) if keys && ! keys.empty? + obj + end + + def initialize(parent, name, keys=nil) + # dummy:: not called by 'new' method + @parent = @t = parent + @tpath = parent.path + @path = @id = name + CellTagID_TBL.mutex.synchronize{ + CellTagID_TBL[@tpath] = {} unless CellTagID_TBL[@tpath] + CellTagID_TBL[@tpath][@id] = self + } + configure(keys) if keys && ! keys.empty? + end +end + +##################################################### + +class Tk::TkTable + TkCommandNames = ['table'.freeze].freeze + WidgetClassName = 'Table'.freeze + WidgetClassNames[WidgetClassName] ||= self + + include Scrollable + include Tk::TkTable::ConfigMethod + include Tk::ValidateConfigure + + def __destroy_hook__ + Tk::TkTable::CelTag::CellTagID_TBL.mutex.synchronize{ + Tk::TkTable::CelTag::CellTagID_TBL.delete(@path) + } + end + + def __boolval_optkeys + super() << 'autoclear' << 'flashmode' << 'invertselected' << + 'multiline' << 'selecttitle' << 'wrap' + end + private :__boolval_optkeys + + def __strval_optkeys + super() << 'colseparator' << 'ellipsis' << 'rowseparator' << 'sparsearray' + end + private :__strval_optkeys + + + ################################# + + class BrowseCommand < TkValidateCommand + class ValidateArgs < TkUtil::CallbackSubst + KEY_TBL = [ + [ ?c, ?n, :column ], + [ ?C, ?s, :index ], + [ ?i, ?x, :cursor ], + [ ?r, ?n, :row ], + [ ?s, ?s, :last_index ], + [ ?S, ?s, :new_index ], + [ ?W, ?w, :widget ], + nil + ] + + PROC_TBL = [ + [ ?n, TkComm.method(:number) ], + [ ?x, TkComm.method(:num_or_str) ], + [ ?s, TkComm.method(:string) ], + [ ?w, TkComm.method(:window) ], + nil + ] + +=begin + # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) + KEY_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) + end + inf + } + + PROC_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + end + inf + } +=end + + _setup_subst_table(KEY_TBL, PROC_TBL); + + def self.ret_val(val) + val + end + end + + def self._config_keys + ['browsecommand', 'browsecmd'] + end + end + #-------------------------------- + class CellCommand < TkValidateCommand + class ValidateArgs < TkUtil::CallbackSubst + KEY_TBL = [ + [ ?c, ?n, :column ], + [ ?C, ?s, :index ], + [ ?i, ?m, :rw_mode ], + [ ?r, ?n, :row ], + [ ?s, ?v, :value ], + [ ?W, ?w, :widget ], + nil + ] + + PROC_TBL = [ + [ ?n, TkComm.method(:number) ], + [ ?s, TkComm.method(:string) ], + [ ?w, TkComm.method(:window) ], + [ ?m, proc{|val| (val == '0')? (:r) : (:w)} ], + [ ?v, proc{|val| TkComm.tk_tcl2ruby(val, true, false)} ], + nil + ] + +=begin + # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) + KEY_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) + end + inf + } + + PROC_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + end + inf + } +=end + + _setup_subst_table(KEY_TBL, PROC_TBL); + + def self.ret_val(val) + TkComm._get_eval_string(val) + end + end + + def self._config_keys + ['command'] + end + end + #-------------------------------- + class SelectionCommand < TkValidateCommand + class ValidateArgs < TkUtil::CallbackSubst + KEY_TBL = [ + [ ?c, ?n, :sel_columns ], + [ ?C, ?s, :sel_area ], + [ ?i, ?n, :total ], + [ ?r, ?n, :sel_rows ], + [ ?s, ?s, :value ], + [ ?W, ?w, :widget ], + nil + ] + + PROC_TBL = [ + [ ?n, TkComm.method(:number) ], + [ ?s, TkComm.method(:string) ], + [ ?w, TkComm.method(:window) ], + nil + ] + +=begin + # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) + KEY_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) + end + inf + } + + PROC_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + end + inf + } +=end + + _setup_subst_table(KEY_TBL, PROC_TBL); + + def self.ret_val(val) + val.to_s + end + end + + def self._config_keys + ['selectioncommand', 'selcmd'] + end + end + #-------------------------------- + class ValidateCommand < TkValidateCommand + class ValidateArgs < TkUtil::CallbackSubst + KEY_TBL = [ + [ ?c, ?n, :column ], + [ ?C, ?s, :index ], + [ ?i, ?x, :cursor ], + [ ?r, ?n, :row ], + [ ?s, ?v, :current_value ], + [ ?S, ?v, :new_value ], + [ ?W, ?w, :widget ], + nil + ] + + PROC_TBL = [ + [ ?n, TkComm.method(:number) ], + [ ?x, TkComm.method(:num_or_str) ], + [ ?s, TkComm.method(:string) ], + [ ?w, TkComm.method(:window) ], + [ ?v, proc{|val| TkComm.tk_tcl2ruby(val, true, false)} ], + nil + ] + +=begin + # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) + KEY_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) + end + inf + } + + PROC_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + end + inf + } +=end + + _setup_subst_table(KEY_TBL, PROC_TBL); + end + + def self._config_keys + ['vcmd', 'validatecommand'] + end + end + + ################################# + + def __validation_class_list + super() << + BrowseCommand << CellCommand << SelectionCommand << ValidateCommand + end + + Tk::ValidateConfigure.__def_validcmd(binding, BrowseCommand) + Tk::ValidateConfigure.__def_validcmd(binding, CellCommand) + Tk::ValidateConfigure.__def_validcmd(binding, SelectionCommand) + Tk::ValidateConfigure.__def_validcmd(binding, ValidateCommand) + + ################################# + + def activate(idx) + tk_send('activate', tagid(idx)) + end + + def bbox(idx) + list(tk_send('bbox', tagid(idx))) + end + + def border_mark(x, y) + simplelist(tk_send('border', 'mark', x, y)) + end + def border_mark_row(x, y) + tk_send('border', 'mark', x, y, 'row') + end + def border_mark_col(x, y) + tk_send('border', 'mark', x, y, 'col') + end + def border_dragto(x, y) + tk_send('border', 'dragto', x, y) + end + + def clear_cache(first=None, last=None) + tk_send('clear', 'cache', tagid(first), tagid(last)) + self + end + def clear_sizes(first=None, last=None) + tk_send('clear', 'sizes', tagid(first), tagid(last)) + self + end + def clear_tags(first=None, last=None) + tk_send('clear', 'tags', tagid(first), tagid(last)) + self + end + def clear_all(first=None, last=None) + tk_send('clear', 'all', tagid(first), tagid(last)) + self + end + + def curselection + simplelist(tk_send('curselection')) + end + def curselection=(val) + tk_send('curselection', val) + val + end + + def curvalue + tk_tcl2ruby(tk_send('curvalue'), true, false) + end + def curvalue=(val) + tk_send('curvalue', val) + val + end + + def delete_active(idx1, idx2=None) + tk_send('delete', 'active', tagid(idx1), tagid(idx2)) + self + end + def delete_cols(*args) # ?switches_array?, index, ?count? + params = [] + if args[0].kind_of?(Array) + switches = args.shift + switches.each{|k| params << "-#{k}"} + end + params << '--' + params << tagid(args.shift) + params.concat(args) + tk_send('delete', 'cols', *params) + self + end + def delete_rows(*args) # ?switches_array?, index, ?count? + params = [] + if args[0].kind_of?(Array) + switches = args.shift + switches.each{|k| params << "-#{k}"} + end + params << '--' + params << tagid(args.shift) + params.concat(args) + tk_send('delete', 'rows', *params) + self + end + + def get(idx) + tk_tcl2ruby(tk_send('get', tagid(idx)), true, false) + end + def get_area(idx1, idx2) + simplelist(tk_send('get', tagid(idx1), tagid(idx2))).collect{|v| + tk_tcl2ruby(v, true, false) + } + end + + def height_list + list(tk_send('height')) + end + def height(row) + number(tk_send('height', row)) + end + def set_height(*pairs) + tk_send('height', *(pairs.flatten)) + self + end + + def hidden_list + simplelist(tk_send('hidden')) + end + def hidden?(idx, *args) + if args.empty? + if (ret = tk_send('hidden', tagid(idx))) == '' + false + else + ret + end + else + bool(tk_send('hidden', tagid(idx), *(args.collect{|i| tagid(i)}))) + end + end + + def icursor + number(tk_send('icursor')) + end + def icursor_set(idx) + number(tk_send('icursor', tagid(idx))) + end + + def index(idx) + tk_send('index', tagid(idx)) + end + def row_index(idx) + number(tk_send('index', tagid(idx), 'row')) + end + def col_index(idx) + number(tk_send('index', tagid(idx), 'col')) + end + + def insert_active(idx, val) + tk_send('insert', 'active', tagid(idx), val) + self + end + def insert_cols(*args) # ?switches_array?, index, ?count? + params = [] + if args[0].kind_of?(Array) + switches = args.shift + switches.each{|k| params << "-#{k}"} + end + params << '--' + params.concat(args) + params << tagid(args.shift) + tk_send('insert', 'cols', *params) + self + end + def insert_rows(*args) # ?switches_array?, index, ?count? + params = [] + if args[0].kind_of?(Array) + switches = args.shift + switches.each{|k| params << "-#{k}"} + end + params << '--' + params << tagid(args.shift) + params.concat(args) + tk_send('insert', 'rows', *params) + self + end + + # def postscript(*args) + # tk_send('postscript', *args) + # end + + def reread + tk_send('reread') + self + end + + def scan_mark(x, y) + tk_send('scan', 'mark', x, y) + self + end + def scan_dragto(x, y) + tk_send('scan', 'dragto', x, y) + self + end + + def see(idx) + tk_send('see', tagid(idx)) + self + end + + def selection_anchor(idx) + tk_send('selection', 'anchor', tagid(idx)) + self + end + def selection_clear(first, last=None) + tk_send('selection', 'clear', tagid(first), tagid(last)) + self + end + def selection_clear_all + selection_clear('all') + end + def selection_include?(idx) + bool(tk_send('selection', 'includes', tagid(idx))) + end + def selection_present + bool(tk_send('selection', 'present')) + end + def selection_set(first, last=None) + tk_send('selection', 'set', tagid(first), tagid(last)) + self + end + + def set(*pairs) # idx, val, idx, val, ... + args = [] + 0.step(pairs.size-1, 2){|i| + args << tagid(pairs[i]) + args << pairs[i+1] + } + tk_send('set', *args) + self + end + def set_row(*pairs) # idx, val, idx, val, ... + args = [] + 0.step(pairs.size-1, 2){|i| + args << tagid(pairs[i]) + args << pairs[i+1] + } + tk_send('set', 'row', *args) + self + end + def set_col(*pairs) # idx, val, idx, val, ... + args = [] + 0.step(pairs.size-1, 2){|i| + args << tagid(pairs[i]) + args << pairs[i+1] + } + tk_send('set', 'col', *args) + self + end +=begin + def set(*pairs) # idx, val, idx, val, ... OR [idx, val], [idx, val], ... + if pairs[0].kind_of?(Array) + # [idx, val], [idx, val], ... + args = [] + pairs.each{|idx, val| args << tagid(idx) << val } + tk_send('set', *args) + else + # idx, val, idx, val, ... + args = [] + 0.step(pairs.size-1, 2){|i| + args << tagid(pairs[i]) + args << pairs[i+1] + } + tk_send('set', *args) + end + self + end + def set_row(*pairs) + if pairs[0].kind_of?(Array) + # [idx, val], [idx, val], ... + args = [] + pairs.each{|idx, val| args << tagid(idx) << val } + tk_send('set', 'row', *args) + else + # idx, val, idx, val, ... + args = [] + 0.step(pairs.size-1, 2){|i| + args << tagid(pairs[i]) + args << pairs[i+1] + } + tk_send('set', 'row', *args) + end + self + end + def set_col(*pairs) + if pairs[0].kind_of?(Array) + # [idx, val], [idx, val], ... + args = [] + pairs.each{|idx, val| args << idx << val } + tk_send('set', 'col', *args) + else + # idx, val, idx, val, ... + args = [] + 0.step(pairs.size-1, 2){|i| + args << tagid(pairs[i]) + args << pairs[i+1] + } + tk_send('set', 'col', *args) + end + self + end +=end + + def spans + simplelist(tk_send('spans')).collect{|inf| + lst = simplelist(inf) + idx = lst[0] + rows, cols = lst[1].split(',').map!{|n| Integer(n)} + [idx [rows, cols]] + } + end + alias span_list spans + def span(idx) + lst = simplelist(tk_send('spans', tagid(idx))) + idx = lst[0] + rows, cols = lst[1].split(',').map!{|n| Integer(n)} + [idx [rows, cols]] + end + def set_spans(*pairs) + # idx, val, idx, val, ... + args = [] + 0.step(pairs.size-1, 2){|i| + args << tagid(pairs[i]) + val = pairs[i+1] + if val.kind_of?(Array) + args << val.join(',') + else + args << val + end + } + tk_send('spans', *args) + self + end +=begin + def set_spans(*pairs) + if pairs[0].kind_of?(Array) + # [idx, val], [idx, val], ... + args = [] + pairs.each{|idx, val| + args << tagid(idx) + if val.kind_of?(Array) + args << val.join(',') + else + args << val + end + } + tk_send('spans', *args) + else + # idx, val, idx, val, ... + args = [] + 0.step(pairs.size-1, 2){|i| + args << tagid(pairs[i]) + val = pairs[i+1] + if val.kind_of?(Array) + args << val.join(',') + else + args << val + end + } + tk_send('spans', *args) + end + self + end +=end + + def tagid(tag) + if tag.kind_of?(Tk::TkTable::CellTag) + tag.id + elsif tag.kind_of?(Array) + if tag[0].kind_of?(Integer) && tag[1].kind_of?(Integer) + # [row, col] + tag.join(',') + else + tag + end + else + tag + end + end + + def tagid2obj(tagid) + Tk::TkTable::CellTag::CellTagID_TBL.mutex.synchronize{ + if Tk::TkTable::CellTag::CellTagID_TBL.key?(@path) + if Tk::TkTable::CellTag::CellTagID_TBL[@path].key?(tagid) + Tk::TkTable::CellTag::CellTagID_TBL[@path][tagid] + else + tagid + end + else + tagid + end + } + end + + def tag_cell(tag, *cells) + tk_send('tag', 'cell', tagid(tag), *(cells.collect{|idx| tagid(idx)})) + self + end + def tag_reset(*cells) + tk_send('tag', 'cell', '', *(cells.collect{|idx| tagid(idx)})) + self + end + def tag_col(tag, *cols) + tk_send('tag', 'col', tagid(tag), *cols) + self + end + def tag_col_reset(*cols) + tk_send('tag', 'col', '', *cols) + self + end + def tag_delete(tag) + tk_send('tag', 'delete', tagid(tag)) + Tk::TkTable::CellTag::CellTagID_TBL.mutex.synchronize{ + if Tk::TkTable::CellTag::CellTagID_TBL[@path] + if tag.kind_of? Tk::TkTable::CellTag + Tk::TkTable::CellTag::CellTagID_TBL[@path].delete(tag.id) + else + Tk::TkTable::CellTag::CellTagID_TBL[@path].delete(tag) + end + end + } + self + end + def tag_exist?(tag) + bool(tk_send('tag', 'exists', tagid(tag))) + end + def tag_include?(tag, idx) + bool(tk_send('tag', 'includes', tagid(tag), tagid(idx))) + end + def tag_lower(tag, target=None) + tk_send('tag', 'lower', tagid(tag), tagid(target)) + self + end + def tag_names(pat=None) + simplelist(tk_send('tag', 'names', pat)).collect{|tag| tagid2obj(tag)} + end + def tag_raise(tag, target=None) + tk_send('tag', 'raise', tagid(tag), tagid(target)) + self + end + def tag_row(tag, *rows) + tk_send('tag', 'row', tagid(tag), *rows) + self + end + def tag_row_reset(*rows) + tk_send('tag', 'row', '', *rows) + self + end + + def validate(idx) + bool(tk_send('validate', tagid(idx))) + end + + def width_list + list(tk_send('width')) + end + def width(row) + number(tk_send('width', row)) + end + def set_width(*pairs) + tk_send('width', *(pairs.flatten)) + self + end + + def window_delete(*args) + tk_send('window', 'delete', *(args.collect{|idx| tagid(idx)})) + self + end + def window_move(from_idx, to_idx) + tk_send('window', 'move', tagid(from_idx), tagid(to_idx)) + self + end + def window_names(pat=None) + simplelist(tk_send('window', 'names', pat)) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/tktrans.rb b/jni/ruby/ext/tk/lib/tkextlib/tktrans.rb new file mode 100644 index 0000000..c5de5be --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tktrans.rb @@ -0,0 +1,14 @@ +# +# TkTrans support (win32 only) +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tktrans/setup.rb' + +# load library +require 'tkextlib/tktrans/tktrans' diff --git a/jni/ruby/ext/tk/lib/tkextlib/tktrans/setup.rb b/jni/ruby/ext/tk/lib/tkextlib/tktrans/setup.rb new file mode 100644 index 0000000..ee406c6 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tktrans/setup.rb @@ -0,0 +1,8 @@ +# +# setup.rb -- setup script before calling TkPackage.require() +# +# If you need some setup operations (for example, add a library path +# to the library search path) before using Tcl/Tk library packages +# wrapped by Ruby scripts in this directory, please write the setup +# operations in this file. +# diff --git a/jni/ruby/ext/tk/lib/tkextlib/tktrans/tktrans.rb b/jni/ruby/ext/tk/lib/tkextlib/tktrans/tktrans.rb new file mode 100644 index 0000000..e051c09 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tktrans/tktrans.rb @@ -0,0 +1,64 @@ +# +# TkTrans support (win32 only) +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tktrans/setup.rb' + +TkPackage.require('tktrans') rescue Tk.load_tcllibrary('tktrans') + +module Tk + module TkTrans + PACKAGE_NAME = 'tktrans'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('tktrans') + rescue + '' + end + end + end +end + +class TkWindow + def tktrans_set_image(img) + tk_send('tktrans::setwidget', @path, img) + self + end + def tktrans_get_image() + tk_send('tktrans::setwidget', @path) + end +end + +class Tk::Root + undef tktrans_set_image, tktrans_get_image + + def tktrans_set_image(img) + tk_send('tktrans::settoplevel', @path, img) + self + end + def tktrans_get_image() + tk_send('tktrans::settoplevel', @path) + end +end + +class Tk::Toplevel + undef tktrans_set_image, tktrans_get_image + + def tktrans_set_image(img) + tk_send('tktrans::settoplevel', @path, img) + self + end + def tktrans_get_image() + tk_send('tktrans::settoplevel', @path) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/treectrl.rb b/jni/ruby/ext/tk/lib/tkextlib/treectrl.rb new file mode 100644 index 0000000..1944fb8 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/treectrl.rb @@ -0,0 +1,13 @@ +# +# TkTreeCtrl support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/treectrl/setup.rb' + +# load library +require 'tkextlib/treectrl/tktreectrl' diff --git a/jni/ruby/ext/tk/lib/tkextlib/treectrl/setup.rb b/jni/ruby/ext/tk/lib/tkextlib/treectrl/setup.rb new file mode 100644 index 0000000..ee406c6 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/treectrl/setup.rb @@ -0,0 +1,8 @@ +# +# setup.rb -- setup script before calling TkPackage.require() +# +# If you need some setup operations (for example, add a library path +# to the library search path) before using Tcl/Tk library packages +# wrapped by Ruby scripts in this directory, please write the setup +# operations in this file. +# diff --git a/jni/ruby/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb b/jni/ruby/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb new file mode 100644 index 0000000..1879a53 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb @@ -0,0 +1,2522 @@ +# +# tkextlib/treectrl/tktreectrl.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/treectrl/setup.rb' + +# TkPackage.require('treectrl', '1.0') +# TkPackage.require('treectrl', '1.1') +TkPackage.require('treectrl') + +module Tk + class TreeCtrl < TkWindow + BindTag_FileList = TkBindTag.new_by_name('TreeCtrlFileList') + + PACKAGE_NAME = 'treectrl'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('treectrl') + rescue + '' + end + end + + HasColumnCreateCommand = + (TkPackage.vcompare(self.package_version, '1.1') >= 0) + + # dummy :: + # pkgIndex.tcl of TreeCtrl-1.0 doesn't support auto_load for + # 'loupe' command (probably it is bug, I think). + # So, calling a 'treectrl' command for loading the dll with + # the auto_load facility. + begin + tk_call('treectrl') + rescue + end + def self.loupe(img, x, y, w, h, zoom) + # NOTE: platform == 'unix' only + + # img => TkPhotoImage + # x, y => screen coords + # w, h => magnifier width and height + # zoom => zooming rate + Tk.tk_call_without_enc('loupe', img, x, y, w, h, zoom) + end + + def self.text_layout(font, text, keys={}) + TkComm.list(Tk.tk_call_without_enc('textlayout', font, text, keys)) + end + + def self.image_tint(img, color, alpha) + Tk.tk_call_without_enc('imagetint', img, color, alpha) + end + + class NotifyEvent < TkUtil::CallbackSubst + end + + module ConfigMethod + end + end + TreeCtrl_Widget = TreeCtrl +end + +############################################## + +class Tk::TreeCtrl::NotifyEvent + # [ <'%' subst-key char>, <proc type char>, <instance var (accessor) name>] + KEY_TBL = [ + [ ?c, ?n, :item_num ], + [ ?d, ?s, :detail ], + [ ?D, ?l, :items ], + [ ?e, ?e, :event ], + [ ?I, ?n, :id ], + [ ?l, ?n, :lower_bound ], + [ ?p, ?n, :active_id ], + [ ?P, ?e, :pattern ], + [ ?S, ?l, :sel_items ], + [ ?T, ?w, :widget ], + [ ?u, ?n, :upper_bound ], + [ ?W, ?o, :object ], + [ ??, ?x, :parm_info ], + 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) ], + [ ?l, TkComm.method(:list) ], + [ ?w, TkComm.method(:window) ], + + [ ?e, proc{|val| + case val + when /^<<[^<>]+>>$/ + TkVirtualEvent.getobj(val[1..-2]) + when /^<[^<>]+>$/ + val[1..-2] + else + val + end + } + ], + + [ ?o, proc{|val| TkComm.tk_tcl2ruby(val)} ], + + [ ?x, proc{|val| + begin + inf = {} + Hash[*(TkComm.list(val))].each{|k, v| + if keyinfo = KEY_TBL.assoc(k[0]) + if cmd = PROC_TBL.assoc(keyinfo[1]) + begin + new_v = cmd.call(v) + v = new_v + rescue + end + end + end + inf[k] = v + } + inf + rescue + val + end + } ], + + nil + ] + +=begin + # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) + KEY_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) + end + inf + } + + PROC_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + end + inf + } +=end + + # 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 + +############################################## + +module Tk::TreeCtrl::ConfigMethod + include TkItemConfigMethod + + def treectrl_tagid(key, obj) + if key.kind_of?(Array) + key = key.join(' ') + else + key = key.to_s + end + + if (obj.kind_of?(Tk::TreeCtrl::Column) || + obj.kind_of?(Tk::TreeCtrl::Element) || + obj.kind_of?(Tk::TreeCtrl::Item) || + obj.kind_of?(Tk::TreeCtrl::Style)) + obj = obj.id + end + + case key + when 'column' + obj + + when 'debug' + None + + when 'dragimage' + None + + when 'element' + obj + + when 'item element' + obj + + when 'marquee' + None + + when 'notify' + obj + + when 'style' + obj + + else + obj + end + end + + def tagid(mixed_id) + if mixed_id == 'debug' + ['debug', None] + elsif mixed_id == 'dragimage' + ['dragimage', None] + elsif mixed_id == 'marquee' + ['marquee', None] + elsif mixed_id.kind_of?(Array) + [mixed_id[0], treectrl_tagid(*mixed_id)] + else + tagid(mixed_id.split(':')) + end + end + + def __item_cget_cmd(mixed_id) + if mixed_id[0] == 'column' && mixed_id[1] == 'drag' + return [self.path, 'column', 'dragcget'] + end + + if mixed_id[1].kind_of?(Array) + id = mixed_id[1] + else + id = [mixed_id[1]] + end + + if mixed_id[0].kind_of?(Array) + ([self.path].concat(mixed_id[0]) << 'cget').concat(id) + else + [self.path, mixed_id[0], 'cget'].concat(id) + end + end + private :__item_cget_cmd + + def __item_config_cmd(mixed_id) + if mixed_id[0] == 'column' && mixed_id[1] == 'drag' + return [self.path, 'column', 'dragconfigure'] + end + + if mixed_id[1].kind_of?(Array) + id = mixed_id[1] + else + id = [mixed_id[1]] + end + + if mixed_id[0].kind_of?(Array) + ([self.path].concat(mixed_id[0]) << 'configure').concat(id) + else + [self.path, mixed_id[0], 'configure'].concat(id) + end + end + private :__item_config_cmd + + def __item_pathname(id) + if id.kind_of?(Array) + key = id[0] + if key.kind_of?(Array) + key = key.join(' ') + end + + tag = id[1] + if tag.kind_of?(Array) + tag = tag.join(' ') + end + + id = [key, tag].join(':') + end + [self.path, id].join(';') + end + private :__item_pathname + + def __item_configinfo_struct(id) + if id.kind_of?(Array) && id[0].to_s == 'notify' + {:key=>0, :alias=>nil, :db_name=>nil, :db_class=>nil, + :default_value=>nil, :current_value=>1} + else + {:key=>0, :alias=>1, :db_name=>1, :db_class=>2, + :default_value=>3, :current_value=>4} + end + end + private :__item_configinfo_struct + + + def __item_font_optkeys(id) + if id.kind_of?(Array) && (id[0] == 'element' || + (id[0].kind_of?(Array) && id[0][1] == 'element')) + [] + else + ['font'] + end + end + private :__item_font_optkeys + + def __item_numstrval_optkeys(id) + if id == 'debug' + ['displaydelay'] + else + super(id) + end + end + private :__item_numstrval_optkeys + + def __item_boolval_optkeys(id) + if id == 'debug' + ['data', 'display', 'enable', 'span', 'textlayout'] + elsif id == 'dragimage' + ['visible'] + elsif id == 'marquee' + ['visible'] + elsif id.kind_of?(Array) + case id[0] + when 'item' + ['visible', 'wrap', 'open', 'returnid', 'visible'] + when 'column' + if id[1] == 'drag' + ['enable'] + else + ['button', 'expand', 'resize', 'squeeze', 'sunken', + 'visible', 'widthhack'] + end + when 'element' + ['draw', 'filled', 'showfocus', 'clip', 'destroy'] + when 'notify' + ['active'] + when 'style' + ['detach', 'indent', 'visible'] + else + if id[0].kind_of?(Array) && id[0][1] == 'element' + ['filled', 'showfocus'] + else + super(id) + end + end + else + super(id) + end + end + private :__item_boolval_optkeys + + def __item_strval_optkeys(id) + if id == 'debug' + ['erasecolor'] + elsif id.kind_of?(Array) + case id[0] + when 'column' + if id[1] == 'drag' + ['indicatorcolor'] + else + super(id) << 'textcolor' + end + when 'element' + super(id) << 'fill' << 'outline' << 'format' + else + super(id) + end + else + super(id) + end + end + private :__item_strval_optkeys + + def __item_listval_optkeys(id) + if id.kind_of?(Array) + case id[0] + when 'column' + ['itembackground'] + when 'element' + ['relief'] + when 'style' + ['union'] + else + if id[0].kind_of?(Array) && id[0][1] == 'element' + ['relief'] + else + [] + end + end + else + [] + end + end + private :__item_listval_optkeys + + def __item_val2ruby_optkeys(id) + if id.kind_of?(Array) + case id[0] + when 'item' + { 'button' => proc{|id,val| (val == 'auto')? val: TkComm.bool(val)} } + else + [] + end + else + [] + end + end + private :__item_val2ruby_optkeys + + def __item_keyonly_optkeys(id) # { def_key=>(undef_key|nil), ... } + { + 'notreally'=>nil, + 'increasing'=>'decreasing', + 'decreasing'=>'increasing', + 'ascii'=>nil, + 'dictionary'=>nil, + 'integer'=>nil, + 'real'=>nil + } + end + private :__item_keyonly_optkeys + + def column_cget_tkstring(tagOrId, option) + itemcget_tkstring(['column', tagOrId], option) + end + def column_cget(tagOrId, option) + itemcget(['column', tagOrId], option) + end + def column_cget_strict(tagOrId, option) + itemcget_strict(['column', tagOrId], option) + end + def column_configure(tagOrId, slot, value=None) + itemconfigure(['column', tagOrId], slot, value) + end + def column_configinfo(tagOrId, slot=nil) + itemconfiginfo(['column', tagOrId], slot) + end + def current_column_configinfo(tagOrId, slot=nil) + current_itemconfiginfo(['column', tagOrId], slot) + end + + def column_dragcget_tkstring(option) + itemcget_tkstring(['column', 'drag'], option) + end + def column_dragcget(option) + itemcget(['column', 'drag'], option) + end + def column_dragcget_strict(option) + itemcget_strict(['column', 'drag'], option) + end + def column_dragconfigure(slot, value=None) + itemconfigure(['column', 'drag'], slot, value) + end + def column_dragconfiginfo(slot=nil) + itemconfiginfo(['column', 'drag'], slot) + end + def current_column_dragconfiginfo(slot=nil) + current_itemconfiginfo(['column', 'drag'], slot) + end + + def debug_cget_tkstring(option) + itemcget_tkstring('debug', option) + end + def debug_cget(option) + itemcget('debug', option) + end + def debug_cget_strict(option) + itemcget_strict('debug', option) + end + def debug_configure(slot, value=None) + itemconfigure('debug', slot, value) + end + def debug_configinfo(slot=nil) + itemconfiginfo('debug', slot) + end + def current_debug_configinfo(slot=nil) + current_itemconfiginfo('debug', slot) + end + + def dragimage_cget_tkstring(option) + itemcget_tkstring('dragimage', option) + end + def dragimage_cget(option) + itemcget('dragimage', option) + end + def dragimage_cget_strict(option) + itemcget_strict('dragimage', option) + end + def dragimage_configure(slot, value=None) + itemconfigure('dragimage', slot, value) + end + def dragimage_configinfo(slot=nil) + itemconfiginfo('dragimage', slot) + end + def current_dragimage_configinfo(slot=nil) + current_itemconfiginfo('dragimage', slot) + end + + def element_cget_tkstring(tagOrId, option) + itemcget_tkstring(['element', tagOrId], option) + end + def element_cget(tagOrId, option) + itemcget(['element', tagOrId], option) + end + def element_cget_strict(tagOrId, option) + itemcget_strict(['element', tagOrId], option) + end + def element_configure(tagOrId, slot, value=None) + itemconfigure(['element', tagOrId], slot, value) + end + def element_configinfo(tagOrId, slot=nil) + itemconfiginfo(['element', tagOrId], slot) + end + def current_element_configinfo(tagOrId, slot=nil) + current_itemconfiginfo(['element', tagOrId], slot) + end + + def item_cget_tkstring(tagOrId, option) + itemcget_tkstring(['item', tagOrId], option) + end + def item_cget(tagOrId, option) + itemcget(['item', tagOrId], option) + end + def item_cget_strict(tagOrId, option) + itemcget_strict(['item', tagOrId], option) + end + def item_configure(tagOrId, slot, value=None) + itemconfigure(['item', tagOrId], slot, value) + end + def item_configinfo(tagOrId, slot=nil) + itemconfiginfo(['item', tagOrId], slot) + end + def current_item_configinfo(tagOrId, slot=nil) + current_itemconfiginfo(['item', tagOrId], slot) + end + + def item_element_cget_tkstring(item, column, elem, option) + itemcget_tkstring([['item', 'element'], [item, column, elem]], option) + end + def item_element_cget(item, column, elem, option) + itemcget([['item', 'element'], [item, column, elem]], option) + end + def item_element_cget_strict(item, column, elem, option) + itemcget_strict([['item', 'element'], [item, column, elem]], option) + end + def item_element_configure(item, column, elem, slot, value=None) + itemconfigure([['item', 'element'], [item, column, elem]], slot, value) + end + def item_element_configinfo(item, column, elem, slot=nil) + itemconfiginfo([['item', 'element'], [item, column, elem]], slot) + end + def current_item_element_configinfo(item, column, elem, slot=nil) + current_itemconfiginfo([['item', 'element'], [item, column, elem]], slot) + end + + def marquee_cget_tkstring(option) + itemcget_tkstring('marquee', option) + end + def marquee_cget(option) + itemcget('marquee', option) + end + def marquee_cget_strict(option) + itemcget_strict('marquee', option) + end + def marquee_configure(slot, value=None) + itemconfigure('marquee', slot, value) + end + def marquee_configinfo(slot=nil) + itemconfiginfo('marquee', slot) + end + def current_marquee_configinfo(slot=nil) + current_itemconfiginfo('marquee', slot) + end + + def notify_cget_tkstring(win, pattern, option) + pattern = "<#{pattern}>" + # "notify" doesn't have cget subcommand. + tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(['notify', [win, pattern]])) << "-#{option}")), false, true)[-1] + end + def notify_cget(win, pattern, option) + pattern = "<#{pattern}>" + # "notify" doesn't have cget subcommand. + current_itemconfiginfo(['notify', [win, pattern]])[option.to_s] + end + def notify_cget_strict(win, pattern, option) + pattern = "<#{pattern}>" + # "notify" doesn't have cget subcommand. + info = current_itemconfiginfo(['notify', [win, pattern]]) + option = option.to_s + unless info.has_key?(option) + fail RuntimeError, "unknown option \"#{option}\"" + else + info[option] + end + end + def notify_configure(win, pattern, slot, value=None) + pattern = "<#{pattern}>" + itemconfigure(['notify', [win, pattern]], slot, value) + end + def notify_configinfo(win, pattern, slot=nil) + pattern = "<#{pattern}>" + itemconfiginfo(['notify', [win, pattern]], slot) + end + def current_notify_configinfo(tagOrId, slot=nil) + pattern = "<#{pattern}>" + current_itemconfiginfo(['notify', [win, pattern]], slot) + end + + def style_cget_tkstring(tagOrId, option) + itemcget_tkstring(['style', tagOrId], option) + end + def style_cget(tagOrId, option) + itemcget(['style', tagOrId], option) + end + def style_cget_strict(tagOrId, option) + itemcget_strict(['style', tagOrId], option) + end + def style_configure(tagOrId, slot, value=None) + itemconfigure(['style', tagOrId], slot, value) + end + def style_configinfo(tagOrId, slot=nil) + itemconfiginfo(['style', tagOrId], slot) + end + def current_style_configinfo(tagOrId, slot=nil) + current_itemconfiginfo(['style', tagOrId], slot) + end + + private :itemcget_tkstring, :itemcget, :itemcget_strict + private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo +end + +############################################## + +class Tk::TreeCtrl + include Tk::TreeCtrl::ConfigMethod + include Scrollable + + TkCommandNames = ['treectrl'.freeze].freeze + WidgetClassName = 'TreeCtrl'.freeze + WidgetClassNames[WidgetClassName] ||= self + + ######################### + + def __destroy_hook__ + Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL.mutex.synchronize{ + Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL.delete(@path) + } + Tk::TreeCtrl::Element::TreeCtrlElementID_TBL.mutex.synchronize{ + Tk::TreeCtrl::Element::TreeCtrlElementID_TBL.delete(@path) + } + Tk::TreeCtrl::Item::TreeCtrlItemID_TBL.mutex.synchronize{ + Tk::TreeCtrl::Item::TreeCtrlItemID_TBL.delete(@path) + } + Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL.mutex.synchronize{ + Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL.delete(@path) + } + end + + ######################### + + def __strval_optkeys + super() + [ + 'buttoncolor', 'columnprefix', 'itemprefix', 'linecolor' + ] + end + private :__strval_optkeys + + def __boolval_optkeys + [ + 'itemwidthequal', 'usetheme', + 'showbuttons', 'showheader', 'showlines', 'showroot', + 'showrootbutton', 'showrootlines', 'showrootchildbuttons' + ] + end + private :__boolval_optkeys + + def __listval_optkeys + [ 'defaultstyle' ] + end + private :__listval_optkeys + + ######################### + + def install_bind(cmd, *args) + install_bind_for_event_class(Tk::TreeCtrl::NotifyEvent, cmd, *args) + end + + ######################### + + def create_self(keys) + if keys and keys != None + tk_call_without_enc(self.class::TkCommandNames[0], @path, + *hash_kv(keys, true)) + else + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + end + private :create_self + + ######################### + + def activate(desc) + tk_send('activate', desc) + self + end + + def canvasx(x) + number(tk_send('canvasx', x)) + end + + def canvasy(y) + number(tk_send('canvasy', y)) + end + + def collapse(*dsc) + tk_send_without_enc('collapse', *(dsc.map!{|d| _get_eval_string(d, true)})) + self + end + + def collapse_recurse(*dsc) + tk_send_without_enc('collapse', '-recurse', + *(dsc.map!{|d| _get_eval_string(d, true)})) + self + end + + def column_bbox(idx) + list(tk_send('column', 'bbox', idx)) + end + + def column_compare(column1, op, column2) + bool(tk_send('column', 'compare', column1, op, column2)) + end + + def column_count + num_or_str(tk_send('column', 'count')) + end + + def column_create(keys=nil) + if keys && keys.kind_of?(Hash) + num_or_str(tk_send('column', 'create', *hash_kv(keys))) + else + num_or_str(tk_send('column', 'create')) + end + end + + def column_delete(idx) + Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL.mutex.synchronize{ + if Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[self.path] + Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[self.path].delete(idx) + end + } + tk_send('column', 'delete', idx) + self + end + + def column_index(idx) + num_or_str(tk_send('column', 'index', idx)) + end + + def column_id(idx) + tk_send('column', 'id', idx) + end + + def column_list(visible=false) + if visible + simplelist(tk_send('column', 'list', '-visible')) + else + simplelist(tk_send('column', 'list')) + end + end + def column_visible_list + column_list(true) + end + + def column_move(idx, before) + tk_send('column', 'move', idx, before) + self + end + + def column_needed_width(idx) + num_or_str(tk_send('column', 'neededwidth', idx)) + end + alias column_neededwidth column_needed_width + + def column_order(column, visible=false) + if visible + num_or_str(tk_send('column', 'order', column, '-visible')) + else + num_or_str(tk_send('column', 'order', column)) + end + end + def column_visible_order(column) + column_order(column, true) + end + + def column_width(idx) + num_or_str(tk_send('column', 'width', idx)) + end + + def compare(item1, op, item2) + bool(tk_send('compare', item1, op, item2)) + end + + def contentbox() + list(tk_send('contentbox')) + end + + def depth(item=None) + num_or_str(tk_send_without_enc('depth', _get_eval_string(item, true))) + end + + def dragimage_add(item, *args) + tk_send('dragimage', 'add', item, *args) + self + end + + def dragimage_clear() + tk_send('dragimage', 'clear') + self + end + + def dragimage_offset(*args) # x, y + if args.empty? + list(tk_send('dragimage', 'offset')) + else + tk_send('dragimage', 'offset', *args) + self + end + end + + def dragimage_visible(*args) # mode + if args..empty? + bool(tk_send('dragimage', 'visible')) + else + tk_send('dragimage', 'visible', *args) + self + end + end + def dragimage_visible? + dragimage_visible() + end + + def debug_dinfo + tk_send('debug', 'dinfo') + self + end + + def debug_scroll + tk_send('debug', 'scroll') + end + + def element_create(elem, type, keys=nil) + if keys && keys.kind_of?(Hash) + tk_send('element', 'create', elem, type, *hash_kv(keys)) + else + tk_send('element', 'create', elem, type) + end + end + + def element_delete(*elems) + Tk::TreeCtrl::Element::TreeCtrlElementID_TBL.mutex.synchronize{ + if Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[self.path] + elems.each{|elem| + Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[self.path].delete(elem) + } + end + } + tk_send('element', 'delete', *elems) + self + end + + def element_names() + list(tk_send('element', 'names')).collect!{|elem| + Tk::TreeCtrl::Element.id2obj(self, elem) + } + end + + def _conv_element_perstate_val(opt, val) + case opt + when 'background', 'foreground', 'fill', 'outline', 'format' + val + when 'draw', 'filled', 'showfocus', 'destroy' + bool(val) + else + tk_tcl2ruby(val) + end + end + private :_conv_element_perstate_val + + def element_perstate(elem, opt, st_list) + tk_send('element', 'perstate', elem, "-{opt}", st_list) + end + + def element_type(elem) + tk_send('element', 'type', elem) + end + + def element_class(elem) + Tk::TreeCtrl::Element.type2class(element_type(elem)) + end + + def expand(*dsc) + tk_send('expand', *dsc) + self + end + + def expand_recurse(*dsc) + tk_send('expand', '-recurse', *dsc) + self + end + + def identify(x, y) + lst = list(tk_send('identify', x, y)) + + if lst[0] == 'item' + lst[1] = Tk::TreeCtrl::Item.id2obj(self, lst[1]) + size = lst.size + i = 2 + while i < size + case lst[i] + when 'line' + i += 1 + lst[i] = Tk::TreeCtrl::Item.id2obj(self, lst[i]) + i += 1 + + when 'button' + i += 1 + + when 'column' + i += 2 + + when 'elem' + i += 1 + lst[i] = Tk::TreeCtrl::Element.id2obj(self, lst[i]) + i += 1 + + else + i += 1 + end + end + end + + lst + end + + def index(idx) + num_or_str(tk_send('index', idx)) + end + + def item_ancestors(item) + list(tk_send('item', 'ancestors', item)).collect!{|id| + Tk::TreeCtrl::Item.id2obj(self, id) + } + end + + def item_bbox(item, *args) + list(tk_send('item', 'bbox', item, *args)) + end + + def item_children(item) + list(tk_send('item', 'children', item)).collect!{|id| + Tk::TreeCtrl::Item.id2obj(self, id) + } + end + + def item_collapse(item) + tk_send_without_enc('item', 'collapse', _get_eval_string(item, true)) + self + end + + def item_collapse_recurse(item) + tk_send_without_enc('item', 'collapse', + _get_eval_string(item, true), '-recurse') + self + end + + def item_compare(item1, op, item2) + bool(tk_send('item', 'compare', item1, op, item2)) + end + + def item_complex(item, *args) + tk_send_without_enc('item', 'complex', + _get_eval_string(item, true), + *(args.map!{|arg| _get_eval_string(arg, true)})) + self + end + + def item_count + num_or_str(tk_send('item', 'count')) + end + + def item_create(keys={}) + num_or_str(tk_send_without_enc('item', 'create', *hash_kv(keys, true))) + end + + def _erase_children(item) + item_children(item).each{|i| _erase_children(i)} + # table is already locked + Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[self.path].delete(item) + end + private :_erase_children + + def item_delete(first, last=None) + Tk::TreeCtrl::Item::TreeCtrlItemID_TBL.mutex.synchronize{ + if Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[self.path] + if first == 'all' || first == :all || last == 'all' || last == :all + Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[self.path].clear + elsif last == None + _erase_children(first) + else + self.range(first, last).each{|id| + _erase_children(id) + } + end + end + } + tk_send('item', 'delete', first, last) + self + end + + def item_dump(item) + list(tk_send('item', 'dump', item)) + end + + def item_dump_hash(item) + Hash[*list(tk_send('item', 'dump', item))] + end + + def item_element_actual(item, column, elem, key) + tk_send('item', 'element', 'actual', item, column, elem, "-#{key}") + end + + def item_element_perstate(elem, opt, st_list) + tk_send('item', 'element', 'perstate', elem, "-{opt}", st_list) + end + + def item_expand(item) + tk_send('item', 'expand', item) + self + end + + def item_expand_recurse(item) + tk_send('item', 'expand', item, '-recurse') + self + end + + def item_firstchild(parent, child=nil) + if child + tk_send_without_enc('item', 'firstchild', + _get_eval_string(parent, true), + _get_eval_string(child, true)) + self + else + id = num_or_str(tk_send_without_enc('item', 'firstchild', + _get_eval_string(parent, true))) + Tk::TreeCtrl::Item.id2obj(self, id) + end + end + alias item_first_child item_firstchild + + def item_hasbutton(item, st=None) + if st == None + bool(tk_send_without_enc('item', 'hasbutton', + _get_eval_string(item, true))) + else + tk_send_without_enc('item', 'hasbutton', + _get_eval_string(item, true), + _get_eval_string(st)) + self + end + end + alias item_has_button item_hasbutton + + def item_hasbutton?(item) + item_hasbutton(item) + end + alias item_has_button? item_hasbutton? + + def item_id(item) + tk_send('item', 'id', item) + end + + def item_image(item, column=nil, *args) + if args.empty? + if column + img = tk_send('item', 'image', item, column) + TkImage::Tk_IMGTBL[img]? TkImage::Tk_IMGTBL[img] : img + else + simplelist(tk_send('item', 'image', item)).collect!{|img| + TkImage::Tk_IMGTBL[img]? TkImage::Tk_IMGTBL[img] : img + } + end + else + tk_send('item', 'image', item, column, *args) + self + end + end + def get_item_image(item, column=nil) + item_image(item, column) + end + def set_item_image(item, col, img, *args) + item_image(item, col, img, *args) + end + + def item_index(item) + list(tk_send('item', 'index', item)) + end + + def item_isancestor(item, des) + bool(tk_send('item', 'isancestor', item, des)) + end + alias item_is_ancestor item_isancestor + alias item_isancestor? item_isancestor + alias item_is_ancestor? item_isancestor + + def item_isopen(item) + bool(tk_send('item', 'isopen', item)) + end + alias item_is_open item_isopen + alias item_isopen? item_isopen + alias item_is_open? item_isopen + alias item_isopened? item_isopen + alias item_is_opened? item_isopen + + def item_lastchild(parent, child=nil) + if child + tk_send_without_enc('item', 'lastchild', + _get_eval_string(parent, true), + _get_eval_string(child, true)) + self + else + id = num_or_str(tk_send_without_enc('item', 'lastchild', + _get_eval_string(parent, true))) + Tk::TreeCtrl::Item.id2obj(self, id) + end + end + alias item_last_child item_lastchild + + def item_nextsibling(sibling, nxt=nil) + if nxt + tk_send('item', 'nextsibling', sibling, nxt) + self + else + id = num_or_str(tk_send('item', 'nextsibling', sibling)) + Tk::TreeCtrl::Item.id2obj(self, id) + end + end + alias item_next_sibling item_nextsibling + + def item_numchildren(item) + number(tk_send_without_enc('item', 'numchildren', + _get_eval_string(item, true))) + end + alias item_num_children item_numchildren + alias item_children_size item_numchildren + + def item_order(item, visible=false) + if visible + ret = num_or_str(tk_send('item', 'order', item, '-visible')) + else + ret = num_or_str(tk_send('item', 'order', item)) + end + + (ret.kind_of?(Fixnum) && ret < 0)? nil: ret + end + def item_visible_order(item) + item_order(item, true) + end + + def item_parent(item) + id = num_or_str(tk_send('item', 'parent', item)) + Tk::TreeCtrl::Item.id2obj(self, id) + end + + def item_prevsibling(sibling, prev=nil) + if prev + tk_send('item', 'prevsibling', sibling, prev) + self + else + id = num_or_str(tk_send('item', 'prevsibling', sibling)) + Tk::TreeCtrl::Item.id2obj(self, id) + end + end + alias item_prev_sibling item_prevsibling + + def item_range(first, last) + simplelist(tk_send('item', 'range', first, last)) + end + + def item_remove(item) + tk_send('item', 'remove', item) + self + end + + def item_rnc(item) + list(tk_send('item', 'rnc', item)) + end + + def _item_sort_core(real_sort, item, *opts) + # opts ::= sort_param [, sort_param, ... ] + # sort_param ::= {key=>val, ...} + # [type, desc, {key=>val, ...}] + # param + opts = opts.collect{|param| + if param.kind_of?(Hash) + param = _symbolkey2str(param) + if param.key?('column') + key = '-column' + desc = param.delete('column') + elsif param.key?('element') + key = '-element' + desc = param.delete('element') + else + key = nil + end + + if param.empty? + param = None + else + param = hash_kv(__conv_item_keyonly_opts(item, param)) + end + + if key + [key, desc].concat(param) + else + param + end + + elsif param.kind_of?(Array) + if param[2].kind_of?(Hash) + param[2] = hash_kv(__conv_item_keyonly_opts(item, param[2])) + end + param + + elsif param.kind_of?(String) && param =~ /\A[a-z]+\Z/ + '-' << param + + elsif param.kind_of?(Symbol) + '-' << param.to_s + + else + param + end + }.flatten + + if real_sort + tk_send('item', 'sort', item, *opts) + self + else + list(tk_send('item', 'sort', item, '-notreally', *opts)) + end + end + private :_item_sort_core + + def item_sort(item, *opts) + _item_sort_core(true, item, *opts) + end + def item_sort_not_really(item, *opts) + _item_sort_core(false, item, *opts) + end + + def item_span(item, column=nil, *args) + if args.empty? + if column + list(tk_send('item', 'span', item, column)) + else + simplelist(tk_send('item', 'span', item)).collect!{|elem| list(elem)} + end + else + tk_send('item', 'span', item, column, *args) + self + end + end + def get_item_span(item, column=nil) + item_span(item, column) + end + def set_item_span(item, col, num, *args) + item_span(item, col, num, *args) + end + + def item_state_forcolumn(item, column, *args) + tk_send('item', 'state', 'forcolumn', item, column, *args) + end + alias item_state_for_column item_state_forcolumn + + def item_state_get(item, *args) + if args.empty? + list(tk_send('item', 'state', 'get', item *args)) + else + bool(tk_send('item', 'state', 'get', item)) + end + end + + def item_state_set(item, *args) + tk_send('item', 'state', 'set', item, *args) + end + + def item_style_elements(item, column) + list(tk_send('item', 'style', 'elements', item, column)).collect!{|id| + Tk::TreeCtrl::Style.id2obj(self, id) + } + end + + def item_style_map(item, column, style, map) + tk_send('item', 'style', 'map', item, column, style, map) + self + end + + def item_style_set(item, column=nil, *args) + if args.empty? + if column + id = tk_send_without_enc('item', 'style', 'set', + _get_eval_string(item, true), + _get_eval_string(column, true)) + Tk::TreeCtrl::Style.id2obj(self, id) + else + list(tk_send_without_enc('item', 'style', 'set', + _get_eval_string(item, true))).collect!{|id| + Tk::TreeCtrl::Style.id2obj(self, id) + } + end + else + tk_send_without_enc('item', 'style', 'set', + _get_eval_string(item, true), + _get_eval_string(column, true), + *(args.flatten.map!{|arg| + _get_eval_string(arg, true) + })) + self + end + end + + def item_text(item, column, txt=nil, *args) + if args.empty? + if txt + tk_send('item', 'text', item, column, txt) + self + else + tk_send('item', 'text', item, column) + end + else + tk_send('item', 'text', item, column, txt, *args) + self + end + end + + def item_toggle(item) + tk_send('item', 'toggle', item) + self + end + + def item_toggle_recurse(item) + tk_send('item', 'toggle', item, '-recurse') + self + end + + def item_visible(item, st=None) + if st == None + bool(tk_send('item', 'visible', item)) + else + tk_send('item', 'visible', item, st) + self + end + end + def item_visible?(item) + item_visible(item) + end + + def marquee_anchor(*args) + if args.empty? + list(tk_send('marquee', 'anchor')) + else + tk_send('marquee', 'anchor', *args) + self + end + end + + def marquee_coords(*args) + if args.empty? + list(tk_send('marquee', 'coords')) + else + tk_send('marquee', 'coords', *args) + self + end + end + + def marquee_corner(*args) + if args.empty? + tk_send('marquee', 'corner') + else + tk_send('marquee', 'corner', *args) + self + end + end + + def marquee_identify() + list(tk_send('marquee', 'identify')).collect!{|id| + Tk::TreeCtrl::Item.id2obj(self, id) + } + end + + def marquee_visible(st=None) + if st == None + bool(tk_send('marquee', 'visible')) + else + tk_send('marquee', 'visible', st) + self + end + end + def marquee_visible?() + marquee_visible() + end + + #def notify_bind(obj, event, cmd=Proc.new, *args) + # _bind([@path, 'notify', 'bind', obj], event, cmd, *args) + # self + #end + def notify_bind(obj, event, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind([@path, 'notify', 'bind', obj], event, cmd, *args) + self + end + + #def notify_bind_append(obj, event, cmd=Proc.new, *args) + # _bind_append([@path, 'notify', 'bind', obj], event, cmd, *args) + # self + #end + def notify_bind_append(obj, event, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append([@path, 'notify', 'bind', obj], event, cmd, *args) + self + end + + def notify_bind_remove(obj, event) + _bind_remove([@path, 'notify', 'bind', obj], event) + self + end + + def notify_bindinfo(obj, event=nil) + _bindinfo([@path, 'notify', 'bind', obj], event) + end + + def notify_detailnames(event) + list(tk_send('notify', 'detailnames', event)) + end + + def notify_eventnames() + list(tk_send('notify', 'eventnames')) + end + + def notify_generate(pattern, char_map=None, percents_cmd=None) + pattern = "<#{pattern}>" + tk_send('notify', 'generate', pattern, char_map, percents_cmd) + self + end + + def notify_install(pattern, percents_cmd=nil, &b) + pattern = "<#{pattern}>" + percents_cmd = Proc.new(&b) if !percents_cmd && b + if percents_cmd + procedure(tk_send('notify', 'install', pattern, percents_cmd)) + else + procedure(tk_send('notify', 'install', pattern)) + end + end + + def notify_install_detail(event, detail, percents_cmd=nil, &b) + percents_cmd = Proc.new(&b) if !percents_cmd && b + if percents_cmd + tk_send('notify', 'install', 'detail', event, detail, percents_cmd) + else + tk_send('notify', 'install', 'detail', event, detail) + end + end + + def notify_install_event(event, percents_cmd=nil, &b) + percents_cmd = Proc.new(&b) if !percents_cmd && b + if percents_cmd + tk_send('notify', 'install', 'event', event, percents_cmd) + else + tk_send('notify', 'install', 'event', event) + end + end + + def notify_linkage(pattern, detail=None) + if detail != None + tk_send('notify', 'linkage', pattern, detail) + else + begin + if pattern.to_s.index(?-) + # TreeCtrl 1.1 format? + begin + tk_send('notify', 'linkage', "<#{pattern}>") + rescue + # TreeCtrl 1.0? + tk_send('notify', 'linkage', pattern) + end + else + # TreeCtrl 1.0 format? + begin + tk_send('notify', 'linkage', pattern) + rescue + # TreeCtrl 1.1? + tk_send('notify', 'linkage', "<#{pattern}>") + end + end + end + end + end + + def notify_unbind(pattern=nil) + if pattern + tk_send('notify', 'unbind', "<#{pattern}>") + else + tk_send('notify', 'unbind') + end + self + end + + def notify_uninstall(pattern) + pattern = "<#{pattern}>" + tk_send('notify', 'uninstall', pattern) + self + end + + def notify_uninstall_detail(event, detail) + tk_send('notify', 'uninstall', 'detail', event, detail) + self + end + + def notify_uninstall_event(event) + tk_send('notify', 'uninstall', 'event', event) + self + end + + def numcolumns() + num_or_str(tk_send('numcolumns')) + end + alias num_columns numcolumns + alias columns_size numcolumns + + def numitems() + num_or_str(tk_send('numitems')) + end + alias num_items numitems + alias items_size numitems + + def orphans() + list(tk_send('orphans')).collect!{|id| + Tk::TreeCtrl::Item.id2obj(self, id) + } + end + + def range(first, last) + list(tk_send('range', first, last)).collect!{|id| + Tk::TreeCtrl::Item.id2obj(self, id) + } + end + + def state_define(name) + tk_send('state', 'define', name) + self + end + + def state_linkage(name) + tk_send('state', 'linkage', name) + end + + def state_names() + list(tk_send('state', 'names')) + end + + def state_undefine(*names) + tk_send('state', 'undefine', *names) + self + end + + def see(item, column=None, keys={}) + tk_send('see', item, column, *hash_kv(keys)) + self + end + + def selection_add(first, last=None) + tk_send('selection', 'add', first, last) + self + end + + def selection_anchor(item=None) + id = num_or_str(tk_send('selection', 'anchor', item)) + Tk::TreeCtrl::Item.id2obj(self, id) + end + + def selection_clear(*args) # first, last + tk_send('selection', 'clear', *args) + self + end + + def selection_count() + number(tk_send('selection', 'count')) + end + + def selection_get() + list(tk_send('selection', 'get')).collect!{|id| + Tk::TreeCtrl::Item.id2obj(self, id) + } + end + + def selection_includes(item) + bool(tk_send('selection', 'includes', item)) + end + + def selection_modify(sel, desel) + tk_send('selection', 'modify', sel, desel) + self + end + + def style_create(style, keys=None) + if keys && keys != None + tk_send('style', 'create', style, *hash_kv(keys)) + else + tk_send('style', 'create', style) + end + end + + def style_delete(*args) + Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL.mutex.synchronize{ + if Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[self.path] + args.each{|sty| + Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[self.path].delete(sty) + } + end + } + tk_send('style', 'delete', *args) + self + end + + def style_elements(style, *elems) + if elems.empty? + list(tk_send('style', 'elements', style)).collect!{|id| + Tk::TreeCtrl::Element.id2obj(self, id) + } + else + tk_send('style', 'elements', style, elems.flatten) + self + end + end + + def _conv_style_layout_val(sty, val) + case sty.to_s + when 'padx', 'pady', 'ipadx', 'ipady' + lst = list(val) + (lst.size == 1)? lst[0]: lst + when 'detach', 'indent' + bool(val) + when 'union' + simplelist(val).collect!{|elem| + Tk::TreeCtrl::Element.id2obj(self, elem) + } + else + val + end + end + private :_conv_style_layout_val + + def style_layout(style, elem, keys=None) + if keys && keys != None + if keys.kind_of?(Hash) + tk_send('style', 'layout', style, elem, *hash_kv(keys)) + self + else + _conv_style_layout_val(keys, + tk_send('style', 'layout', + style, elem, "-#{keys}")) + end + else + ret = Hash.new + Hash[*simplelist(tk_send('style', 'layout', style, elem))].each{|k, v| + k = k[1..-1] + ret[k] = _conv_style_layout_val(k, v) + } + ret + end + end + def get_style_layout(style, elem, opt=None) + style_layout(style, elem, opt) + end + def set_style_layout(style, elem, slot, value=None) + if slot.kind_of?(Hash) + style_layout(style, elem, slot) + else + style_layout(style, elem, {slot=>value}) + end + end + + def style_names() + list(tk_send('style', 'names')).collect!{|id| + Tk::TreeCtrl::Style.id2obj(self, id) + } + end + + def toggle(*items) + tk_send('toggle', *items) + self + end + + def toggle_recurse() + tk_send('toggle', '-recurse', *items) + self + end +end + +##################### + +class Tk::TreeCtrl::Column < TkObject + TreeCtrlColumnID_TBL = TkCore::INTERP.create_table + + (TreeCtrlColumnID = ['treectrl_column'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + TkCore::INTERP.init_ip_env{ + Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL.mutex.synchronize{ + Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL.clear + } + } + + def self.id2obj(tree, id) + tpath = tree.path + Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL.mutex.synchronize{ + if Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[tpath] + Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[tpath][id]? \ + Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[tpath][id] : id + else + id + end + } + end + + def initialize(parent, keys={}) + @tree = parent + @tpath = parent.path + + keys = _symbolkey2str(keys) + + Tk::TreeCtrl::Column::TreeCtrlColumnID.mutex.synchronize{ + @path = @id = + keys.delete('tag') || + Tk::TreeCtrl::Column::TreeCtrlColumnID.join(TkCore::INTERP._ip_id_) + Tk::TreeCtrl::Column::TreeCtrlColumnID[1].succ! + } + + keys['tag'] = @id + + Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL.mutex.synchronize{ + Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[@tpath] ||= {} + Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[@tpath][@id] = self + } + + @tree.column_create(keys) + end + + def id + @id + end + + def to_s + @id.to_s.dup + end + + def cget_tkstring(opt) + @tree.column_cget_tkstring(@tree.column_index(@id), opt) + end + def cget(opt) + @tree.column_cget(@tree.column_index(@id), opt) + end + def cget_strict(opt) + @tree.column_cget_strict(@tree.column_index(@id), opt) + end + + def configure(*args) + @tree.column_configure(@tree.column_index(@id), *args) + end + + def configinfo(*args) + @tree.column_configinfo(@tree.column_index(@id), *args) + end + + def current_configinfo(*args) + @tree.current_column_configinfo(@tree.column_index(@id), *args) + end + + def delete + @tree.column_delete(@tree.column_index(@id)) + self + end + + def index + @tree.column_index(@id) + end + + def move(before) + @tree.column_move(@tree.column_index(@id), before) + self + end + + def needed_width + @tree.column_needed_width(@tree.column_index(@id)) + end + alias neededwidth needed_width + + def current_width + @tree.column_width(@tree.column_index(@id)) + end +end + +##################### + +class Tk::TreeCtrl::Element < TkObject + TreeCtrlElementID_TBL = TkCore::INTERP.create_table + + (TreeCtrlElementID = ['treectrl_element'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + TreeCtrlElemTypeToClass = {} + + TkCore::INTERP.init_ip_env{ + Tk::TreeCtrl::Element::TreeCtrlElementID_TBL.mutex.synchronize{ + Tk::TreeCtrl::Element::TreeCtrlElementID_TBL.clear + } + } + + def self.type2class(type) + TreeCtrlElemTypeToClass[type] || type + end + + def self.id2obj(tree, id) + tpath = tree.path + Tk::TreeCtrl::Element::TreeCtrlElementID_TBL.mutex.synchronize{ + if Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[tpath] + Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[tpath][id]? \ + Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[tpath][id] : id + else + id + end + } + end + + def initialize(parent, type, keys=nil) + @tree = parent + @tpath = parent.path + @type = type.to_s + Tk::TreeCtrl::Element::TreeCtrlElementID.mutex.synchronize{ + @path = @id = + Tk::TreeCtrl::Element::TreeCtrlElementID.join(TkCore::INTERP._ip_id_) + Tk::TreeCtrl::Element::TreeCtrlElementID[1].succ! + } + + Tk::TreeCtrl::Element::TreeCtrlElementID_TBL.mutex.synchronize{ + Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[@tpath] ||= {} + Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[@tpath][@id] = self + } + + @tree.element_create(@id, @type, keys) + end + + def id + @id + end + + def to_s + @id.dup + end + + def cget_tkstring(opt) + @tree.element_cget_tkstring(@id, opt) + end + def cget(opt) + @tree.element_cget(@id, opt) + end + def cget_strict(opt) + @tree.element_cget_strict(@id, opt) + end + + def configure(*args) + @tree.element_configure(@id, *args) + end + + def configinfo(*args) + @tree.element_configinfo(@id, *args) + end + + def current_configinfo(*args) + @tree.current_element_configinfo(@id, *args) + end + + def delete + @tree.element_delete(@id) + self + end + + def element_type + @tree.element_type(@id) + end + + def element_class + @tree.element_class(@id) + end +end + +class Tk::TreeCtrl::BitmapElement < Tk::TreeCtrl::Element + TreeCtrlElemTypeToClass['bitmap'] = self + + def initialize(parent, keys=nil) + super(parent, 'bitmap', keys) + end +end + +class Tk::TreeCtrl::BorderElement < Tk::TreeCtrl::Element + TreeCtrlElemTypeToClass['border'] = self + + def initialize(parent, keys=nil) + super(parent, 'border', keys) + end +end + +class Tk::TreeCtrl::ImageElement < Tk::TreeCtrl::Element + TreeCtrlElemTypeToClass['image'] = self + + def initialize(parent, keys=nil) + super(parent, 'image', keys) + end +end + +class Tk::TreeCtrl::RectangleElement < Tk::TreeCtrl::Element + TreeCtrlElemTypeToClass['rect'] = self + + def initialize(parent, keys=nil) + super(parent, 'rect', keys) + end +end + +##################### + +class Tk::TreeCtrl::Item < TkObject + TreeCtrlItemID_TBL = TkCore::INTERP.create_table + + TkCore::INTERP.init_ip_env{ + Tk::TreeCtrl::Item::TreeCtrlItemID_TBL.mutex.synchronize{ + Tk::TreeCtrl::Item::TreeCtrlItemID_TBL.clear + } + } + + def self.id2obj(tree, id) + tpath = tree.path + Tk::TreeCtrl::Item::TreeCtrlItemID_TBL.mutex.synchronize{ + if Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[tpath] + Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[tpath][id]? \ + Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[tpath][id] : id + else + id + end + } + end + + def initialize(parent, keys={}) + @tree = parent + @tpath = parent.path + @path = @id = @tree.item_create(keys) + + Tk::TreeCtrl::Item::TreeCtrlItemID_TBL.mutex.synchronize{ + Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[@tpath] ||= {} + Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[@tpath][@id] = self + } + end + + def id + @id + end + + def to_s + @id.to_s.dup + end + + def ancestors + @tree.item_ancestors(@id) + end + + def bbox(*args) + @tree.item_bbox(@id, *args) + end + + def children + @tree.item_children(@id) + end + + def collapse + @tree.item_collapse(@id) + self + end + + def collapse_recurse + @tree.item_collapse_recurse(@id) + self + end + + def complex(*args) + @tree.item_complex(@id, *args) + self + end + + def cget_tkstring(opt) + @tree.item_cget_tkstring(@id, opt) + end + def cget(opt) + @tree.item_cget(@id, opt) + end + def cget_strict(opt) + @tree.item_cget_strict(@id, opt) + end + + def configure(*args) + @tree.item_configure(@id, *args) + end + + def configinfo(*args) + @tree.item_configinfo(@id, *args) + end + + def current_configinfo(*args) + @tree.current_item_configinfo(@id, *args) + end + + def delete + @tree.item_delete(@id) + self + end + + def element_dump + @tree.item_dump(@id) + end + + def element_dump_hash + @tree.item_dump_hash(@id) + end + + def element_actual(column, elem, key) + @tree.item_element_actual(@id, column, elem, key) + end + + def element_cget_tkstring(opt) + @tree.item_element_cget(@id, opt) + end + def element_cget_tkstring(opt) + @tree.item_element_cget(@id, opt) + end + def element_cget_strict(opt) + @tree.item_element_cget_strict(@id, opt) + end + + def element_configure(*args) + @tree.item_element_configure(@id, *args) + end + + def element_configinfo(*args) + @tree.item_element_configinfo(@id, *args) + end + + def current_element_configinfo(*args) + @tree.current_item_element_configinfo(@id, *args) + end + + def expand + @tree.item_expand(@id) + self + end + + def expand_recurse + @tree.item_expand_recurse(@id) + self + end + + def firstchild(child=nil) + if child + @tree.item_firstchild(@id, child) + self + else + @tree.item_firstchild(@id) + end + end + alias first_child firstchild + + def hasbutton(st=None) + if st == None + @tree.item_hasbutton(@id) + else + @tree.item_hasbutton(@id, st) + self + end + end + alias has_button hasbutton + + def hasbutton? + @tree.item_hasbutton(@id) + end + alias has_button? hasbutton? + + def index + @tree.item_index(@id) + end + + def isancestor(des) + @tree.item_isancestor(@id, des) + end + alias is_ancestor isancestor + alias isancestor? isancestor + alias is_ancestor? isancestor + alias ancestor? isancestor + + def isopen + @tree.item_isopen(@id) + end + alias is_open isopen + alias isopen? isopen + alias is_open? isopen + alias isopened? isopen + alias is_opened? isopen + alias open? isopen + + def lastchild(child=nil) + if child + @tree.item_lastchild(@id, child) + self + else + @tree.item_lastchild(@id) + end + end + alias last_child lastchild + + def nextsibling(nxt=nil) + if nxt + @tree.item_nextsibling(@id, nxt) + self + else + @tree.item_nextsibling(@id) + end + end + alias next_sibling nextsibling + + def numchildren + @tree.item_numchildren(@id) + end + alias num_children numchildren + alias children_size numchildren + + def parent_index + @tree.item_parent(@id) + end + + def prevsibling(nxt=nil) + if nxt + @tree.item_prevsibling(@id, nxt) + self + else + @tree.item_prevsibling(@id) + end + end + alias prev_sibling prevsibling + + def remove + @tree.item_remove(@id) + end + + def rnc + @tree.item_rnc(@id) + end + + def sort(*opts) + @tree.item_sort(@id, *opts) + end + def sort_not_really(*opts) + @tree.item_sort_not_really(@id, *opts) + self + end + + def state_forcolumn(column, *args) + @tree.item_state_forcolumn(@id, column, *args) + self + end + alias state_for_column state_forcolumn + + def state_get(*args) + @tree.item_state_get(@id, *args) + end + + def state_set(*args) + @tree.item_state_set(@id, *args) + self + end + + def style_elements(column) + @tree.item_style_elements(@id, column) + end + + def style_map(column, style, map) + @tree.item_style_map(@id, column, style, map) + self + end + + def style_set(column=nil, *args) + if args.empty? + @tree.item_style_set(@id, column) + else + @tree.item_style_set(@id, column, *args) + self + end + end + + def item_text(column, txt=nil, *args) + if args.empty? + if txt + @tree.item_text(@id, column, txt) + self + else + @tree.item_text(@id, column) + end + else + @tree.item_text(@id, column, txt, *args) + self + end + end + + def toggle + @tree.item_toggle(@id) + self + end + + def toggle_recurse + @tree.item_toggle_recurse(@id) + self + end + + def visible(st=None) + if st == None + @tree.item_visible(@id) + else + @tree.item_visible(@id, st) + self + end + end +end + +##################### + +class Tk::TreeCtrl::Style < TkObject + TreeCtrlStyleID_TBL = TkCore::INTERP.create_table + + (TreeCtrlStyleID = ['treectrl_style'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + TkCore::INTERP.init_ip_env{ + Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL.mutex.synchronize{ + Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL.clear + } + } + + def self.id2obj(tree, id) + tpath = tree.path + Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL.mutex.synchronize{ + if Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[tpath] + Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[tpath][id]? \ + Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[tpath][id] : id + else + id + end + } + end + + def initialize(parent, keys=nil) + @tree = parent + @tpath = parent.path + + Tk::TreeCtrl::Style::TreeCtrlStyleID.mutex.synchronize{ + @path = @id = + Tk::TreeCtrl::Style::TreeCtrlStyleID.join(TkCore::INTERP._ip_id_) + Tk::TreeCtrl::Style::TreeCtrlStyleID[1].succ! + } + + Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL.mutex.synchronize{ + Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[@tpath] ||= {} + Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[@tpath][@id] = self + } + + @tree.style_create(@id, keys) + end + + def id + @id + end + + def to_s + @id.dup + end + + def cget_tkstring(opt) + @tree.style_cget_tkstring(@id, opt) + end + def cget(opt) + @tree.style_cget(@id, opt) + end + def cget_strict(opt) + @tree.style_cget_strict(@id, opt) + end + + def configure(*args) + @tree.style_configure(@id, *args) + end + + def configinfo(*args) + @tree.style_configinfo(@id, *args) + end + + def current_configinfo(*args) + @tree.current_style_configinfo(@id, *args) + end + + def delete + @tree.style_delete(@id) + self + end + + def elements(*elems) + if elems.empty? + @tree.style_elements(@id) + else + @tree.style_elements(@id, *elems) + self + end + end + + def layout(elem, keys=None) + if keys && keys != None && keys.kind_of?(Hash) + @tree.style_layout(@id, elem, keys) + self + else + @tree.style_layout(@id, elem, keys) + end + end +end + +module Tk::TreeCtrl::BindCallback + include Tk + extend Tk +end + +class << Tk::TreeCtrl::BindCallback + def percentsCmd(*args) + tk_call('::TreeCtrl::PercentsCmd', *args) + end + def cursorCheck(w, x, y) + tk_call('::TreeCtrl::CursorCheck', w, x, y) + end + def cursorCheckAux(w) + tk_call('::TreeCtrl::CursorCheckAux', w) + end + def cursorCancel(w) + tk_call('::TreeCtrl::CursorCancel', w) + end + def buttonPress1(w, x, y) + tk_call('::TreeCtrl::ButtonPress1', w, x, y) + end + def doubleButton1(w, x, y) + tk_call('::TreeCtrl::DoubleButton1', w, x, y) + end + def motion1(w, x, y) + tk_call('::TreeCtrl::Motion1', w, x, y) + end + def leave1(w, x, y) + tk_call('::TreeCtrl::Leave1', w, x, y) + end + def release1(w, x, y) + tk_call('::TreeCtrl::Release1', w, x, y) + end + def beginSelect(w, el) + tk_call('::TreeCtrl::BeginSelect', w, el) + end + def motion(w, le) + tk_call('::TreeCtrl::Motion', w, el) + end + def beginExtend(w, el) + tk_call('::TreeCtrl::BeginExtend', w, el) + end + def beginToggle(w, el) + tk_call('::TreeCtrl::BeginToggle', w, el) + end + def cancelRepeat + tk_call('::TreeCtrl::CancelRepeat') + end + def autoScanCheck(w, x, y) + tk_call('::TreeCtrl::AutoScanCheck', w, x, y) + end + def autoScanCheckAux(w) + tk_call('::TreeCtrl::AutoScanCheckAux', w) + end + def autoScanCancel(w) + tk_call('::TreeCtrl::AutoScanCancel', w) + end + def up_down(w, n) + tk_call('::TreeCtrl::UpDown', w, n) + end + def left_right(w, n) + tk_call('::TreeCtrl::LeftRight', w, n) + end + def setActiveItem(w, idx) + tk_call('::TreeCtrl::SetActiveItem', w, idx) + end + def extendUpDown(w, amount) + tk_call('::TreeCtrl::ExtendUpDown', w, amount) + end + def dataExtend(w, el) + tk_call('::TreeCtrl::DataExtend', w, el) + end + def cancel(w) + tk_call('::TreeCtrl::Cancel', w) + end + def selectAll(w) + tk_call('::TreeCtrl::selectAll', w) + end + def marqueeBegin(w, x, y) + tk_call('::TreeCtrl::MarqueeBegin', w, x, y) + end + def marqueeUpdate(w, x, y) + tk_call('::TreeCtrl::MarqueeUpdate', w, x, y) + end + def marqueeEnd(w, x, y) + tk_call('::TreeCtrl::MarqueeEnd', w, x, y) + end + def scanMark(w, x, y) + tk_call('::TreeCtrl::ScanMark', w, x, y) + end + def scanDrag(w, x, y) + tk_call('::TreeCtrl::ScanDrag', w, x, y) + end + + # filelist-bindings + def fileList_button1(w, x, y) + tk_call('::TreeCtrl::FileListButton1', w, x, y) + end + def fileList_motion1(w, x, y) + tk_call('::TreeCtrl::FileListMotion1', w, x, y) + end + def fileList_motion(w, x, y) + tk_call('::TreeCtrl::FileListMotion', w, x, y) + end + def fileList_leave1(w, x, y) + tk_call('::TreeCtrl::FileListLeave1', w, x, y) + end + def fileList_release1(w, x, y) + tk_call('::TreeCtrl::FileListRelease1', w, x, y) + end + def fileList_edit(w, i, s, e) + tk_call('::TreeCtrl::FileListEdit', w, i, s, e) + end + def fileList_editCancel(w) + tk_call('::TreeCtrl::FileListEditCancel', w) + end + def fileList_autoScanCheck(w, x, y) + tk_call('::TreeCtrl::FileListAutoScanCheck', w, x, y) + end + def fileList_autoScanCheckAux(w) + tk_call('::TreeCtrl::FileListAutoScanCheckAux', w) + end + + def entryOpen(w, item, col, elem) + tk_call('::TreeCtrl::EntryOpen', w, item, col, elem) + end + def entryExpanderOpen(w, item, col, elem) + tk_call('::TreeCtrl::EntryExpanderOpen', w, item, col, elem) + end + def entryClose(w, accept) + tk_call('::TreeCtrl::EntryClose', w, accept) + end + def entryExpanderKeypress(w) + tk_call('::TreeCtrl::EntryExpanderKeypress', w) + end + def textOpen(w, item, col, elem, width=0, height=0) + tk_call('::TreeCtrl::TextOpen', w, item, col, elem, width, height) + end + def textExpanderOpen(w, item, col, elem, width) + tk_call('::TreeCtrl::TextOpen', w, item, col, elem, width) + end + def textClose(w, accept) + tk_call('::TreeCtrl::TextClose', w, accept) + end + def textExpanderKeypress(w) + tk_call('::TreeCtrl::TextExpanderKeypress', w) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/trofs.rb b/jni/ruby/ext/tk/lib/tkextlib/trofs.rb new file mode 100644 index 0000000..5914e51 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/trofs.rb @@ -0,0 +1,13 @@ +# +# trofs support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/trofs/setup.rb' + +# load library +require 'tkextlib/trofs/trofs.rb' diff --git a/jni/ruby/ext/tk/lib/tkextlib/trofs/setup.rb b/jni/ruby/ext/tk/lib/tkextlib/trofs/setup.rb new file mode 100644 index 0000000..ee406c6 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/trofs/setup.rb @@ -0,0 +1,8 @@ +# +# setup.rb -- setup script before calling TkPackage.require() +# +# If you need some setup operations (for example, add a library path +# to the library search path) before using Tcl/Tk library packages +# wrapped by Ruby scripts in this directory, please write the setup +# operations in this file. +# diff --git a/jni/ruby/ext/tk/lib/tkextlib/trofs/trofs.rb b/jni/ruby/ext/tk/lib/tkextlib/trofs/trofs.rb new file mode 100644 index 0000000..7a2606a --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/trofs/trofs.rb @@ -0,0 +1,51 @@ +# +# tkextlib/trofs/trofs.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/trofs/setup.rb' + +# TkPackage.require('trofs', '0.4') +TkPackage.require('trofs') + +module Tk + module Trofs + extend TkCore + + PACKAGE_NAME = 'trofs'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('trofs') + rescue + '' + end + end + + ############################################## + + def self.create_archive(dir, archive) + tk_call('::trofs::archive', dir, archive) + archive + end + + def self.mount(archive, mountpoint=None) + # returns the normalized path to mountpoint + tk_call('::trofs::mount', archive, mountpoint) + end + + def self.umount(mountpoint) + tk_call('::trofs::umount', mountpoint) + mountpoint + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/version.rb b/jni/ruby/ext/tk/lib/tkextlib/version.rb new file mode 100644 index 0000000..4bef78f --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/version.rb @@ -0,0 +1,6 @@ +# +# release date of tkextlib +# +module Tk + Tkextlib_RELEASE_DATE = '2010-02-01'.freeze +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/vu.rb b/jni/ruby/ext/tk/lib/tkextlib/vu.rb new file mode 100644 index 0000000..d2234eb --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/vu.rb @@ -0,0 +1,48 @@ +# +# The vu widget set support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/vu/setup.rb' + +# load package +# TkPackage.require('vu', '2.1') +TkPackage.require('vu') + +# autoload +module Tk + module Vu + TkComm::TkExtlibAutoloadModule.unshift(self) + + PACKAGE_NAME = 'vu'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('vu') + rescue + '' + end + end + + ########################################## + + autoload :Dial, 'tkextlib/vu/dial' + + autoload :Pie, 'tkextlib/vu/pie' + autoload :PieSlice, 'tkextlib/vu/pie' + autoload :NamedPieSlice, 'tkextlib/vu/pie' + + autoload :Spinbox, 'tkextlib/vu/spinbox' + + autoload :Bargraph, 'tkextlib/vu/bargraph' + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/vu/bargraph.rb b/jni/ruby/ext/tk/lib/tkextlib/vu/bargraph.rb new file mode 100644 index 0000000..b9fcf92 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/vu/bargraph.rb @@ -0,0 +1,61 @@ +# +# ::vu::bargraph widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# create module/class +module Tk + module Vu + class Bargraph < TkWindow + end + end +end + + +# call setup script -- <libdir>/tkextlib/vu.rb +require 'tkextlib/vu.rb' + +class Tk::Vu::Bargraph < TkWindow + TkCommandNames = ['::vu::bargraph'.freeze].freeze + WidgetClassName = 'Bargraph'.freeze + WidgetClassNames[WidgetClassName] ||= self + + ############################### + + def __boolval_optkeys + ['showminmax', 'showvalue'] + end + private :__boolval_optkeys + + def __strval_optkeys + super() + [ + 'title', + 'barbackground', 'barcolor', 'barcolour', + 'tickcolor', 'tickcolour', + 'textcolor', 'textcolour', + ] + end + private :__strval_optkeys + + def __listval_optkeys + ['alabels', 'blabels'] + end + private :__listval_optkeys + + def __font_optkeys + ['alabfont', 'blabfont'] + end + private :__font_optkeys + + ############################### + + def set(val = None) + tk_call_without_enc(@path, 'set', val) + self + end + + def get() + num_or_str(tk_call_without_enc(@path, 'get')) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/vu/charts.rb b/jni/ruby/ext/tk/lib/tkextlib/vu/charts.rb new file mode 100644 index 0000000..8569ac5 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/vu/charts.rb @@ -0,0 +1,53 @@ +# +# charts -- Create and manipulate canvas Add-On Items +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' +require 'tk/canvas' + +# call setup script -- <libdir>/tkextlib/vu.rb +require 'tkextlib/vu.rb' + +module Tk + module Vu + module ChartsConfig + include TkItemConfigOptkeys + def __item_boolval_optkeys(id) + super(id) << 'lefttrunc' << 'autocolor' + end + private :__item_boolval_optkeys + + def __item_strval_optkeys(id) + super(id) << 'bar' << 'color' << 'outline' << + 'fill' << 'scaleline' << 'stripline' + end + private :__item_strval_optkeys + + def __item_listval_optkeys(id) + super(id) << 'values' << 'tags' + end + private :__item_listval_optkeys + end + + class TkcSticker < TkcItem + include ChartsConfig + + CItemTypeName = 'sticker'.freeze + CItemTypeToClass[CItemTypeName] = self + end + + class TkcStripchart < TkcItem + include ChartsConfig + + CItemTypeName = 'stripchart'.freeze + CItemTypeToClass[CItemTypeName] = self + end + + class TkcBarchart < TkcItem + include ChartsConfig + + CItemTypeName = 'barchart'.freeze + CItemTypeToClass[CItemTypeName] = self + end + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/vu/dial.rb b/jni/ruby/ext/tk/lib/tkextlib/vu/dial.rb new file mode 100644 index 0000000..4d04974 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/vu/dial.rb @@ -0,0 +1,102 @@ +# +# ::vu::dial widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# create module/class +module Tk + module Vu + class Dial < TkWindow + end + end +end + +# call setup script -- <libdir>/tkextlib/vu.rb +require 'tkextlib/vu.rb' + +# define module/class +class Tk::Vu::Dial < TkWindow + TkCommandNames = ['::vu::dial'.freeze].freeze + WidgetClassName = 'Dial'.freeze + WidgetClassNames[WidgetClassName] ||= self + + ############################### + + def __methodcall_optkeys # { key=>method, ... } + {'coords'=>'coords'} + end + private :__methodcall_optkeys + + ############################### + + def coords(val = nil) + if val + tk_send_without_enc('coords', val) + self + else + tk_split_list(tk_send_without_enc('coords')) + end + end + + def constrain(val = None) + num_or_str(tk_call(@path, 'constrain', val)) + end + + def get(*args) + num_or_str(tk_call(@path, 'get', *args)) + end + + def identify(x, y) + tk_call(@path, 'identify', x, y) + end + + def get_label(val=nil) + if val + tk_call(@path, 'label', val) + else + ret = [] + lst = simplelist(tk_call(@path, 'label')) + while lst.size > 0 + ret << ([num_or_str(lst.shift)] << lst.shift) + end + end + end + + def set_label(val, str, *args) + tk_call(@path, 'label', val, str, *args) + self + end + + def set_label_constrain(val, str, *args) + tk_call(@path, 'label', '-constrain', val, str, *args) + self + end + + def get_tag(val=nil) + if val + tk_call(@path, 'tag', val) + else + ret = [] + lst = simplelist(tk_call(@path, 'tag')) + while lst.size > 0 + ret << ([num_or_str(lst.shift)] << lst.shift) + end + end + end + + def set_tag(val, str, *args) + tk_call(@path, 'tag', val, str, *args) + self + end + + def set_tag_constrain(val, str, *args) + tk_call(@path, 'tag', '-constrain', val, str, *args) + self + end + + def set(val = None) + tk_call_without_enc(@path, 'set', val) + self + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/vu/pie.rb b/jni/ruby/ext/tk/lib/tkextlib/vu/pie.rb new file mode 100644 index 0000000..6b0c485 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/vu/pie.rb @@ -0,0 +1,286 @@ +# +# ::vu::pie widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# create module/class +module Tk + module Vu + module PieSliceConfigMethod + end + class Pie < TkWindow + end + class PieSlice < TkObject + end + class NamedPieSlice < PieSlice + end + end +end + +# call setup script -- <libdir>/tkextlib/vu.rb +require 'tkextlib/vu.rb' + +module Tk::Vu::PieSliceConfigMethod + include TkItemConfigMethod + + def __item_pathname(tagOrId) + if tagOrId.kind_of?(Tk::Vu::PieSlice) + self.path + ';' + tagOrId.id.to_s + else + self.path + ';' + tagOrId.to_s + end + end + private :__item_pathname +end + +class Tk::Vu::Pie < TkWindow + TkCommandNames = ['::vu::pie'.freeze].freeze + WidgetClassName = 'Pie'.freeze + WidgetClassNames[WidgetClassName] ||= self + + def __destroy_hook__ + Tk::Vu::PieSlice::SliceID_TBL.delete(@path) + end + + ############################### + + include Tk::Vu::PieSliceConfigMethod + + def tagid(tag) + if tag.kind_of?(Tk::Vu::PieSlice) + tag.id + else + # tag + _get_eval_string(tag) + end + end + + ############################### + + def delete(*glob_pats) + tk_call(@path, 'delete', *glob_pats) + self + end + + def explode(slice, *args) + tk_call(@path, 'explode', slice, *args) + self + end + + def explode_value(slice) + num_or_str(tk_call(@path, 'explode', slice)) + end + + def lower(slice, below=None) + tk_call(@path, 'lower', slice, below) + self + end + + def names(*glob_pats) + simplelist(tk_call(@path, 'names', *glob_pats)) + end + alias slices names + + def order(*args) + tk_call(@path, 'order', *args) + self + end + + def raise(slice, above=None) + tk_call(@path, 'raise', slice, above) + self + end + + def swap(slice1, slice2) + tk_call(@path, 'swap', slice1, slice2) + self + end + + def set(slice, *args) + num_or_str(tk_call(@path, 'set', slice, *args)) + end + alias set_value set + alias set_values set + alias create set + + def slice_value(slice) + num_or_str(tk_call(@path, 'set', slice)) + end + + def value(val = None) + num_or_str(tk_call_without_enc(@path, 'value')) + end + alias sum_value value +end + +class Tk::Vu::PieSlice + SliceID_TBL = TkCore::INTERP.create_table + + (Pie_Slice_ID = ['vu:pie'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + + TkCore::INTERP.init_ip_env{ + SliceID_TBL.mutex.synchronize{ SliceID_TBL.clear } + } + + def self.id2obj(pie, id) + pie_path = pie.path + SliceID_TBL.mutex.synchronize{ + if SliceID_TBL[pie_path] + SliceID_TBL[pie_path][id]? SliceID_TBL[pie_path][id]: id + else + id + end + } + end + + def initialize(parent, *args) + unless parent.kind_of?(Tk::Vu::Pie) + fail ArgumentError, "expect a Tk::Vu::Pie instance for 1st argument" + end + @parent = @pie = parent + @ppath = parent.path + Pie_Slice_ID.mutex.synchronize{ + @path = @id = Pie_Slice_ID.join(TkCore::INTERP._ip_id_) + Pie_Slice_ID[1].succ! + } + SliceID_TBL.mutex.synchronize{ + SliceID_TBL[@ppath] = {} unless SliceID_TBL[@ppath] + SliceID_TBL[@ppath][@id] = self + } + + if args[-1].kind_of?(Hash) + keys = args.unshift + end + @pie.set(@id, *args) + configure(keys) + end + + def id + @id + end + + def [](key) + cget key + end + + def []=(key,val) + configure key, val + val + end + + def cget_tkstring(slot) + @pie.itemcget_tkstring(@id, slot) + end + + def cget(slot) + @pie.itemcget(@id, slot) + end + + def cget_strict(slot) + @pie.itemcget_strict(@id, slot) + end + + def configure(*args) + @pie.itemconfigure(@id, *args) + self + end + + def configinfo(*args) + @pie.itemconfiginfo(@id, *args) + end + + def current_configinfo(*args) + @pie.current_itemconfiginfo(@id, *args) + end + + def delete + @pie.delete(@id) + end + + def explode(value) + @pie.explode(@id, value) + self + end + + def explode_value + @pie.explode_value(@id) + end + + def lower(other=None) + @pie.lower(@id, other) + self + end + + def raise(other=None) + @pie.raise(@id, other) + self + end + + def set(value) + @pie.set(@id, value) + self + end + alias set_value set + + def value + @pie.set(@id) + end +end + +class Tk::Vu::NamedPieSlice + def self.new(parent, name, *args) + obj = nil + SliceID_TBL.mutex.synchronize{ + if SliceID_TBL[parent.path] && SliceID_TBL[parent.path][name] + obj = SliceID_TBL[parent.path][name] + else + #super(parent, name, *args) + unless parent.kind_of?(Tk::Vu::Pie) + fail ArgumentError, "expect a Tk::Vu::Pie instance for 1st argument" + end + obj = self.allocate + obj.instance_eval{ + @parent = @pie = parent + @ppath = parent.path + @path = @id = name.to_s + SliceID_TBL[@ppath] = {} unless SliceID_TBL[@ppath] + SliceID_TBL[@ppath][@id] = self + } + end + } + obj.instance_eval{ + if args[-1].kind_of?(Hash) + keys = args.unshift + end + @pie.set(@id, *args) + configure(keys) + } + + obj + end + + def initialize(parent, name, *args) + # dummy:: not called by 'new' method + unless parent.kind_of?(Tk::Vu::Pie) + fail ArgumentError, "expect a Tk::Vu::Pie instance for 1st argument" + end + @parent = @pie = parent + @ppath = parent.path + @path = @id = name.to_s + SliceID_TBL.mutex.synchronize{ + SliceID_TBL[@ppath] = {} unless SliceID_TBL[@ppath] + SliceID_TBL[@ppath][@id] = self + } + + if args[-1].kind_of?(Hash) + keys = args.unshift + end + @pie.set(@id, *args) + configure(keys) + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/vu/setup.rb b/jni/ruby/ext/tk/lib/tkextlib/vu/setup.rb new file mode 100644 index 0000000..ee406c6 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/vu/setup.rb @@ -0,0 +1,8 @@ +# +# setup.rb -- setup script before calling TkPackage.require() +# +# If you need some setup operations (for example, add a library path +# to the library search path) before using Tcl/Tk library packages +# wrapped by Ruby scripts in this directory, please write the setup +# operations in this file. +# diff --git a/jni/ruby/ext/tk/lib/tkextlib/vu/spinbox.rb b/jni/ruby/ext/tk/lib/tkextlib/vu/spinbox.rb new file mode 100644 index 0000000..7d6104f --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/vu/spinbox.rb @@ -0,0 +1,22 @@ +# +# ::vu::spinbox widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# a standard spinbox (<= 8.3) +# This is the same as the 8.4 core spinbox widget. +# +require 'tk' + +if (Tk::TK_MAJOR_VERSION < 8 || + (Tk::TK_MAJOR_VERSION == 8 && Tk::TK_MINOR_VERSION < 4)) + # call setup script -- <libdir>/tkextlib/vu.rb + require 'tkextlib/vu.rb' + + Tk.tk_call('namespace', 'import', '::vu::spinbox') +end + +module Tk + module Vu + Spinbox = Tk::Spinbox + end +end diff --git a/jni/ruby/ext/tk/lib/tkextlib/winico.rb b/jni/ruby/ext/tk/lib/tkextlib/winico.rb new file mode 100644 index 0000000..ce7b8ea --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/winico.rb @@ -0,0 +1,14 @@ +# +# winico -- Windows Icon extension support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/tktable/setup.rb' + +# load library +require 'tkextlib/winico/winico' diff --git a/jni/ruby/ext/tk/lib/tkextlib/winico/setup.rb b/jni/ruby/ext/tk/lib/tkextlib/winico/setup.rb new file mode 100644 index 0000000..ee406c6 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/winico/setup.rb @@ -0,0 +1,8 @@ +# +# setup.rb -- setup script before calling TkPackage.require() +# +# If you need some setup operations (for example, add a library path +# to the library search path) before using Tcl/Tk library packages +# wrapped by Ruby scripts in this directory, please write the setup +# operations in this file. +# diff --git a/jni/ruby/ext/tk/lib/tkextlib/winico/winico.rb b/jni/ruby/ext/tk/lib/tkextlib/winico/winico.rb new file mode 100644 index 0000000..9160c29 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/winico/winico.rb @@ -0,0 +1,224 @@ +# +# tkextlib/winico/winico.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require 'tkextlib/winico/setup.rb' + +# TkPackage.require('winico', '0.5') +# TkPackage.require('winico', '0.6') +TkPackage.require('winico') + +module Tk + class Winico < TkObject + PACKAGE_NAME = 'winico'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('winico') + rescue + '' + end + end + end +end + +class Tk::Winico + WinicoID_TBL = TkCore::INTERP.create_table + + TkCore::INTERP.init_ip_env{ + WinicoID_TBL.mutex.synchronize{ WinicoID_TBL.clear } + } + + def self.id2obj(id) + WinicoID_TBL.mutex.synchronize{ + (WinicoID_TBL.key?(id))? WinicoID_TBL[id] : id + } + end + + def self.info + simplelist(Tk.tk_call('winico', 'info')).collect{|id| + Tk::Winico.id2obj(id) + } + end + + def self.icon_info(id) + simplelist(Tk.tk_call('winico', 'info', id)).collect{|inf| + h = Hash[*list(inf)] + h.keys.each{|k| h[k[1..-1]] = h.delete(k)} + } + end + + ################################# + + def self.new_from_file(file_name) + self.new(file_name) + end + + def self.new_from_resource(resource_name, file_name = nil) + self.new(file_name, resource_name) + end + + def initialize(file_name, resource_name=nil, winico_id=nil) + if resource_name + # from resource + if file_name + @id = Tk.tk_call('winico', 'load', resource_name, file_name) + else + @id = Tk.tk_call('winico', 'load', resource_name) + end + elsif file_name + # from .ico file + @id = Tk.tk_call('winico', 'createfrom', file_name) + elsif winico_id + @id = winico_id + else + fail ArgumentError, + "must be given proper information from where loading icons" + end + @path = @id + WinicoID_TBL.mutex.synchronize{ + WinicoID_TBL[@id] = self + } + end + + def id + @id + end + + def set_window(win_id, *opts) # opts := ?'big'|'small'?, ?pos? + # NOTE:: the window, which is denoted by win_id, MUST BE MAPPED. + # If not, then this may fail or crash. + tk_call('winico', 'setwindow', win_id, @id, *opts) + end + + def delete + tk_call('winico', 'delete', @id) + WinicoID_TBL.mutex.synchronize{ + WinicoID_TBL.delete(@id) + } + self + end + alias destroy delete + + def info + Tk::Winico.icon_info(@id) + end + + ################################# + + class Winico_callback < TkValidateCommand + class ValidateArgs < TkUtil::CallbackSubst + KEY_TBL = [ + [ ?m, ?s, :message ], + [ ?i, ?x, :icon ], + [ ?x, ?n, :x ], + [ ?y, ?n, :y ], + [ ?X, ?n, :last_x ], + [ ?Y, ?n, :last_y ], + [ ?t, ?n, :tickcount ], + [ ?w, ?n, :icon_idnum ], + [ ?l, ?n, :msg_idnum ], + nil + ] + + PROC_TBL = [ + [ ?n, TkComm.method(:number) ], + [ ?s, TkComm.method(:string) ], + [ ?x, proc{|id| + Tk::Winico::WinicoID_TBL.mutex.synchronize{ + if Tk::Winico::WinicoID_TBL.key?(id) + obj = Tk::Winico::WinicoID_TBL[id] + else + # Tk::Winico.new(nil, nil, id) + obj = Tk::Winico.allocate + obj.instance_eval{ @path = @id = id } + Tk::Winico::WinicoID_TBL[id] = obj + end + obj + } + } ], + nil + ] + +=begin + # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) + KEY_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) + end + inf + } + + PROC_TBL.map!{|inf| + if inf.kind_of?(Array) + inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) + end + inf + } +=end + + _setup_subst_table(KEY_TBL, PROC_TBL); + + def self.ret_val(val) + val + end + end + + def self._config_keys + ['callback'] + end + end + + ################################# + + def add_to_taskbar(keys = {}) + keys = _symbolkey2str(keys) + Winico_callback._config_keys.each{|k| + if keys[k].kind_of?(Array) + cmd, *args = keys[k] + #keys[k] = Winico_callback.new(cmd, args.join(' ')) + keys[k] = Winico_callback.new(cmd, *args) + # elsif keys[k].kind_of?(Proc) + elsif TkComm._callback_entry?(keys[k]) + keys[k] = Winico_callback.new(keys[k]) + end + } + tk_call('winico', 'taskbar', 'add', @id, *(hash_kv(keys))) + self + end + alias taskbar_add add_to_taskbar + + def modify_taskbar(keys = {}) + keys = _symbolkey2str(keys) + Winico_callback._config_keys.each{|k| + if keys[k].kind_of?(Array) + cmd, *args = keys[k] + #keys[k] = Winico_callback.new(cmd, args.join(' ')) + keys[k] = Winico_callback.new(cmd, *args) + # elsif keys[k].kind_of?(Proc) + elsif TkComm._callback_entry?(keys[k]) + keys[k] = Winico_callback.new(keys[k]) + end + } + tk_call('winico', 'taskbar', 'modify', @id, *(hash_kv(keys))) + self + end + alias taskbar_modify modify_taskbar + + def delete_from_taskbar + tk_call('winico', 'taskbar', 'delete', @id) + self + end + alias taskbar_delete delete_from_taskbar +end diff --git a/jni/ruby/ext/tk/lib/tkfont.rb b/jni/ruby/ext/tk/lib/tkfont.rb new file mode 100644 index 0000000..38a9663 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkfont.rb @@ -0,0 +1,4 @@ +# +# tkfont.rb - load tk/font.rb +# +require 'tk/font' diff --git a/jni/ruby/ext/tk/lib/tkmacpkg.rb b/jni/ruby/ext/tk/lib/tkmacpkg.rb new file mode 100644 index 0000000..35560e7 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkmacpkg.rb @@ -0,0 +1,4 @@ +# +# tkmacpkg.rb - load tk/macpkg.rb +# +require 'tk/macpkg' diff --git a/jni/ruby/ext/tk/lib/tkmenubar.rb b/jni/ruby/ext/tk/lib/tkmenubar.rb new file mode 100644 index 0000000..70214fd --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkmenubar.rb @@ -0,0 +1,4 @@ +# +# tkmenubar.rb - load tk/menubar.rb +# +require 'tk/menubar' diff --git a/jni/ruby/ext/tk/lib/tkmngfocus.rb b/jni/ruby/ext/tk/lib/tkmngfocus.rb new file mode 100644 index 0000000..fe70950 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkmngfocus.rb @@ -0,0 +1,4 @@ +# +# tkmngfocus.rb - load tk/mngfocus.rb +# +require 'tk/mngfocus' diff --git a/jni/ruby/ext/tk/lib/tkpalette.rb b/jni/ruby/ext/tk/lib/tkpalette.rb new file mode 100644 index 0000000..56b203b --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkpalette.rb @@ -0,0 +1,4 @@ +# +# tkpalette.rb - load tk/palette.rb +# +require 'tk/palette' diff --git a/jni/ruby/ext/tk/lib/tkscrollbox.rb b/jni/ruby/ext/tk/lib/tkscrollbox.rb new file mode 100644 index 0000000..6093b2e --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkscrollbox.rb @@ -0,0 +1,4 @@ +# +# tkscrollbox.rb - load tk/scrollbox.rb +# +require 'tk/scrollbox' diff --git a/jni/ruby/ext/tk/lib/tktext.rb b/jni/ruby/ext/tk/lib/tktext.rb new file mode 100644 index 0000000..97ad62a --- /dev/null +++ b/jni/ruby/ext/tk/lib/tktext.rb @@ -0,0 +1,4 @@ +# +# tktext.rb - load tk/text.rb +# +require 'tk/text' diff --git a/jni/ruby/ext/tk/lib/tkvirtevent.rb b/jni/ruby/ext/tk/lib/tkvirtevent.rb new file mode 100644 index 0000000..f4fae19 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkvirtevent.rb @@ -0,0 +1,4 @@ +# +# tkvirtevent.rb - load tk/virtevent.rb +# +require 'tk/virtevent' diff --git a/jni/ruby/ext/tk/lib/tkwinpkg.rb b/jni/ruby/ext/tk/lib/tkwinpkg.rb new file mode 100644 index 0000000..83371c5 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkwinpkg.rb @@ -0,0 +1,4 @@ +# +# tkwinpkg.rb - load tk/winpkg.rb +# +require 'tk/winpkg' |