diff options
Diffstat (limited to 'ext/tk/lib')
86 files changed, 7738 insertions, 558 deletions
diff --git a/ext/tk/lib/README b/ext/tk/lib/README index c003adb2c8..5918fe4bf0 100644 --- a/ext/tk/lib/README +++ b/ext/tk/lib/README @@ -1,6 +1,17 @@ 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 diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb index 8462c3064c..9cf2ac3e07 100644 --- a/ext/tk/lib/tk.rb +++ b/ext/tk/lib/tk.rb @@ -103,6 +103,8 @@ module TkComm gen_class_name = 'TkWidget_' + tk_class classname_def = "WidgetClassName = '#{tk_class}'.freeze" end + +=begin unless Object.const_defined? gen_class_name Object.class_eval "class #{gen_class_name}<#{ruby_class_name} #{classname_def} @@ -110,6 +112,21 @@ module TkComm 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 @@ -790,8 +807,8 @@ module TkComm } end end - private :install_bind, :tk_event_sequence, - :_bind_core, :_bind, :_bind_append, :_bind_remove, :_bindinfo + private :tk_event_sequence + private :_bind_core, :_bind, :_bind_append, :_bind_remove, :_bindinfo def bind(tagOrClass, context, cmd=Proc.new, args=nil) _bind(["bind", tagOrClass], context, cmd, args) @@ -1403,9 +1420,17 @@ module 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 @@ -1888,281 +1913,500 @@ else end +module TkBindCore + def bind(context, cmd=Proc.new, args=nil) + Tk.bind(self, context, cmd, args) + end + + def bind_append(context, cmd=Proc.new, args=nil) + 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_configinfo(name = nil) - ret = TkFont.used_on(self.path) - if ret == nil -=begin - if name - ret = name - else - ret = TkFont.init_widget_font(self.path, self.path, 'configure') - end -=end - ret = TkFont.init_widget_font(self.path, self.path, 'configure') + 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, *__config_cmd) + elsif optkeys.size == 1 + pathname = [win, tag, optkeys[0]].join(';') + TkFont.used_on(pathname) || + TkFont.init_widget_font(pathname, *__config_cmd) + 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, *__config_cmd) + } + fonts end - ret end alias fontobj font_configinfo def font_configure(slot) + pathname = __pathname + slot = _symbolkey2str(slot) - if slot.key?('font') - fnt = slot.delete('font') - if fnt.kind_of? TkFont - return fnt.call_font_configure(self.path, self.path,'configure',slot) - else - if fnt - if (slot.key?('kanjifont') || - slot.key?('latinfont') || - slot.key?('asciifont')) - fnt = TkFont.new(fnt) - - lfnt = slot.delete('latinfont') - lfnt = slot.delete('asciifont') if slot.key?('asciifont') - kfnt = slot.delete('kanjifont') - - fnt.latin_replace(lfnt) if lfnt - fnt.kanji_replace(kfnt) if kfnt - else - slot['font'] = fnt - tk_call(self.path, 'configure', *hash_kv(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 + tk_call(*(__config_cmd << "-#{optkey}" << fnt)) + end end + next end - return self end - end - - lfnt = slot.delete('latinfont') - lfnt = slot.delete('asciifont') if slot.key?('asciifont') - kfnt = slot.delete('kanjifont') - if lfnt && kfnt - return TkFont.new(lfnt, kfnt).call_font_configure(self.path, self.path, - 'configure', slot) - 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 + } - latinfont_configure(lfnt) if lfnt - kanjifont_configure(kfnt) if kfnt - - tk_call(self.path, 'configure', *hash_kv(slot)) if slot != {} + # configure other (without font) options + tk_call(*(__config_cmd.concat(hash_kv(slot)))) if slot != {} self end def latinfont_configure(ltn, keys=nil) - if (fobj = TkFont.used_on(self.path)) - fobj = TkFont.new(fobj) # create a new TkFont object - elsif Tk::JAPANIZED_TK - fobj = fontobj # create a new TkFont object + if ltn.kind_of?(Array) + key = ltn[1] + ltn = ltn[0] else - tk_call(self.path, 'configure', '-font', ltn) - return self + key = nil 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)) + 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 + tk_call(*(__config_cmd << "-#{optkey}" << ltn)) + 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_configure(conf) + fobj.latin_replace(ltn) end - else - fobj.latin_replace(ltn) end - end - return fobj.call_font_configure(self.path, self.path, 'configure', {}) + fobj.call_font_configure([pathname, optkey], *(__config_cmd << {})) + } + self end alias asciifont_configure latinfont_configure def kanjifont_configure(knj, keys=nil) - if (fobj = TkFont.used_on(self.path)) - fobj = TkFont.new(fobj) # create a new TkFont object - elsif Tk::JAPANIZED_TK - fobj = fontobj # create a new TkFont object + if knj.kind_of?(Array) + key = knj[1] + knj = knj[0] else - tk_call(self.path, 'configure', '-font', knj) - return self + 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 - 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)) + 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 + tk_call(*(__config_cmd << "-#{optkey}" << knj)) + 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_configure(conf) + fobj.kanji_replace(knj) end - else - fobj.kanji_replace(knj) end - end - return fobj.call_font_configure(self.path, self.path, 'configure', {}) + fobj.call_font_configure([pathname, optkey], *(__config_cmd << {})) + } + self end - def font_copy(window, tag=nil) - if tag - fnt = window.tagfontobj(tag).dup + def font_copy(window, wintag=nil, winkey=nil, targetkey=nil) + if wintag + if winkey + fnt = window.tagfontobj(wintag, winkey).dup + else + fnt = window.tagfontobj(wintag).dup + end else - fnt = window.fontobj.dup + if winkey + fnt = window.fontobj(winkey).dup + else + fnt = window.fontobj.dup + end + end + + if targetkey + fnt.call_font_configure([__pathname, targetkey], *(__config_cmd << {})) + else + fnt.call_font_configure(__pathname, *(__config_cmd << {})) end - fnt.call_font_configure(self.path, self.path, 'configure', {}) self end - def latinfont_copy(window, tag=nil) - fontobj.dup.call_font_configure(self.path, self.path, 'configure', {}) - if tag - fontobj.latin_replace(window.tagfontobj(tag).latin_font_id) + def latinfont_copy(window, 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(window.tagfontobj(wintag, winkey).latin_font_id) + else + fontobj.latin_replace(window.tagfontobj(wintag).latin_font_id) + end else - fontobj.latin_replace(window.fontobj.latin_font_id) + if winkey + fontobj.latin_replace(window.fontobj(winkey).latin_font_id) + else + fontobj.latin_replace(window.fontobj.latin_font_id) + end end self end alias asciifont_copy latinfont_copy - def kanjifont_copy(window, tag=nil) - fontobj.dup.call_font_configure(self.path, self.path, 'configure', {}) - if tag - fontobj.kanji_replace(window.tagfontobj(tag).kanji_font_id) + def kanjifont_copy(window, wintag=nil, winkey=nil, targetkey=nil) + if targetkey + fontobj(targetkey).dup.call_font_configure([__pathname, targetkey], + *(__config_cmd << {})) else - fontobj.kanji_replace(window.fontobj.kanji_font_id) + fontobj.dup.call_font_configure(__pathname, *(__config_cmd << {})) + end + + if wintag + if winkey + fontobj.kanji_replace(window.tagfontobj(wintag, winkey).kanji_font_id) + else + fontobj.kanji_replace(window.tagfontobj(wintag).kanji_font_id) + end + else + if winkey + fontobj.kanji_replace(window.fontobj(winkey).kanji_font_id) + else + fontobj.kanji_replace(window.fontobj.kanji_font_id) + end end self end end -module TkBindCore - def bind(context, cmd=Proc.new, args=nil) - Tk.bind(self, context, cmd, args) - end +module TkConfigMethod + include TkUtil + include TkTreatFont - def bind_append(context, cmd=Proc.new, args=nil) - Tk.bind_append(self, context, cmd, args) + def __cget_cmd + [self.path, 'cget'] end + private :__cget_cmd - def bind_remove(context) - Tk.bind_remove(self, context) + def __config_cmd + [self.path, 'configure'] end + private :__config_cmd - def bindinfo(context=nil) - Tk.bindinfo(self, context) + def __configinfo_struct + {:key=>0, :alias=>1, :db_name=>1, :db_class=>2, + :default_value=>3, :current_value=>4} end -end + private :__configinfo_struct + def __numval_optkeys + [] + end + private :__numval_optkeys -class TkObject<TkKernel - include Tk - include TkTreatFont - include TkBindCore + def __numstrval_optkeys + [] + end + private :__numstrval_optkeys -### --> definition is moved to TkUtil module -# def path -# @path -# end + def __boolval_optkeys + [] + end + private :__boolval_optkeys - def epath - @path + def __strval_optkeys + ['text', 'label', 'show', 'data', 'file'] end + private :__strval_optkeys - def to_eval - @path + def __listval_optkeys + [] end + private :__listval_optkeys - def tk_send(cmd, *rest) - tk_call(path, cmd, *rest) + def __numlistval_optkeys + [] end - def tk_send_without_enc(cmd, *rest) - tk_call_without_enc(path, cmd, *rest) + private :__numlistval_optkeys + + def __methodcall_optkeys # { key=>method, ... } + {} end - def tk_send_with_enc(cmd, *rest) - tk_call_with_enc(path, cmd, *rest) + private :__methodcall_optkeys + + def __keyonly_optkeys # { def_key=>undef_key or nil, ... } + {} end - # private :tk_send, :tk_send_without_enc, :tk_send_with_enc + private :__keyonly_optkeys - def method_missing(id, *args) - name = id.id2name - case args.length - when 1 - if name[-1] == ?= - configure name[0..-2], args[0] + 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 - configure name, args[0] + keys2[k.to_s] = v end - when 0 - begin - cget(name) - rescue - fail NameError, - "undefined local variable or method `#{name}' for #{self.to_s}", - error_at - end - else - fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at - end + } + keys2 end - def [](id) - cget(id) + def config_hash_kv(keys, enc_mode = nil, conf = nil) + hash_kv(__conv_keyonly_opts(keys), enc_mode, conf) end - def []=(id, val) - configure(id, val) - val - end + ################################ def cget(slot) - case slot.to_s - when 'text', 'label', 'show', 'data', 'file' - #tk_call(path, 'cget', "-#{slot}") - _fromUTF8(tk_call_without_enc(path, 'cget', "-#{slot}")) - when 'font', 'kanjifont' - #fnt = tk_tcl2ruby(tk_call(path, 'cget', "-#{slot}")) - #fnt = tk_tcl2ruby(tk_call(path, 'cget', "-font")) - fnt = tk_tcl2ruby(tk_call_without_enc(path, 'cget', "-font"), true) + slot = slot.to_s + + 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(fnt) + fnt = fontobj(fontkey) end - if slot == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/ + 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(path, 'cget', "-#{slot}"), true) + tk_tcl2ruby(tk_call_without_enc(*(__cget_cmd << "-#{slot}")), true) end end def configure(slot, value=None) if slot.kind_of? Hash - if (slot['font'] || slot[:font] || - slot['kanjifont'] || slot[:kanjifont] || - slot['latinfont'] || slot[:latinfont] || - slot['asciifont'] || slot[:asciifont] ) + slot = _symbolkey2str(slot) + + __methodcall_optkeys.each{|key, method| + value = slot.delete(key.to_s) + self.__send__(method, value) if value + } + + __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(path, 'configure', *hash_kv(slot)) + tk_call(*(__config_cmd.concat(hash_kv(slot)))) end else - if (slot == 'font' || slot == :font || - slot == 'kanjifont' || slot == :kanjifont || - slot == 'latinfont' || slot == :latinfont || - slot == 'asciifont' || slot == :asciifont ) + slot = slot.to_s + 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(__methodcall_optkeys)[slot] ) + self.__send__(method, value) + elsif (slot =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/) if value == None - fontobj + fontobj($2) else font_configure({slot=>value}) end else - tk_call(path, 'configure', "-#{slot}", value) + tk_call(*(__config_cmd << "-#{slot}" << value)) end end self @@ -2174,110 +2418,528 @@ class TkObject<TkKernel def configinfo(slot = nil) if TkComm::GET_CONFIGINFO_AS_ARRAY - if slot == 'font' || slot == :font || - slot == 'kanjifont' || slot == :kanjifont - conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('configure', "-#{slot}"))) - conf[0] = conf[0][1..-1] - conf[4] = fontobj(conf[4]) + if (slot.to_s =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/) + fontkey = $2 + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{fontkey}")))) + conf[__configinfo_struct[:key]] = + conf[__configinfo_struct[:key]][1..-1] + if ( ! __configinfo_struct[:alias] \ + || conf.size > __configinfo_struct[:alias] + 1 ) + 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 - case slot.to_s - when 'text', 'label', 'show', 'data', 'file' - conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('configure', "-#{slot}"))) + slot = slot.to_s + case slot + 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(*(__config_cmd << "-#{slot}")))) + + 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(*(__config_cmd << "-#{slot}")))) + + 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(*(__config_cmd << "-#{slot}")))) + + 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(*(__config_cmd << "-#{slot}")))) + + 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(*(__config_cmd << "-#{slot}")))) + + 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(*(__config_cmd << "-#{slot}")))) else - conf = tk_split_list(_fromUTF8(tk_send_without_enc('configure', "-#{slot}"))) + conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) + 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[0] = conf[0][1..-1] + conf + else - ret = tk_split_simplelist(_fromUTF8(tk_send_without_enc('configure'))).collect{|conflist| + ret = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*__config_cmd))).collect{|conflist| conf = tk_split_simplelist(conflist) - conf[0] = conf[0][1..-1] - case conf[0] - when 'text', 'label', 'show', 'data', 'file' + conf[__configinfo_struct[:key]] = + conf[__configinfo_struct[:key]][1..-1] + + case conf[__configinfo_struct[:key]] + 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 + else - if conf[3] - if conf[3].index('{') - conf[3] = tk_split_list(conf[3]) + 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[3] = tk_tcl2ruby(conf[3]) + conf[__configinfo_struct[:default_value]] = + tk_tcl2ruby(conf[__configinfo_struct[:default_value]]) end end - if conf[4] - if conf[4].index('{') - conf[4] = tk_split_list(conf[4]) + 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[4] = tk_tcl2ruby(conf[4]) + conf[__configinfo_struct[:current_value]] = + tk_tcl2ruby(conf[__configinfo_struct[:current_value]]) end end end - conf[1] = conf[1][1..-1] if conf.size == 2 # alias info + + 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 } - fontconf = ret.assoc('font') - if fontconf - ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'} - fontconf[4] = fontobj(fontconf[4]) - ret.push(fontconf) - else - ret - end + + __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}$/} + fontconf[__configinfo_struct[:current_value]] = fontobj(optkey) + ret.push(fontconf) + end + } + + __methodcall_optkeys.each{|optkey, method| + ret << [optkey.to_s, '', '', '', self.__send__(method)] + } + + ret end end + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY - if slot == 'font' || slot == :font || - slot == 'kanjifont' || slot == :kanjifont - conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('configure', "-#{slot}"))) - key = conf.shift[1..-1] - conf[3] = fontobj(conf[3]) - { key => conf } + if (slot.to_s =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/) + fontkey = $2 + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{fontkey}")))) + conf[__configinfo_struct[:key]] = + conf[__configinfo_struct[:key]][1..-1] + + if ( ! __configinfo_struct[:alias] \ + || conf.size > __configinfo_struct[:alias] + 1 ) + 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 - case slot.to_s - when 'text', 'label', 'show', 'data', 'file' - conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('configure', "-#{slot}"))) + slot = slot.to_s + case slot + 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(*(__config_cmd << "-#{slot}")))) + + 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(*(__config_cmd << "-#{slot}")))) + + 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(*(__config_cmd << "-#{slot}")))) + + 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(*(__config_cmd << "-#{slot}")))) + + 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(*(__config_cmd << "-#{slot}")))) + + 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(*(__config_cmd << "-#{slot}")))) else - conf = tk_split_list(_fromUTF8(tk_send_without_enc('configure', "-#{slot}"))) + conf = tk_split_list(_fromUTF8(tk_send_without_enc(*(__config_cmd << "-#{slot}")))) end - key = conf.shift[1..-1] - { key => conf } + 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_send_without_enc('configure'))).each{|conflist| + tk_split_simplelist(_fromUTF8(tk_call_without_enc(*__config_cmd))).each{|conflist| conf = tk_split_simplelist(conflist) - key = conf.shift[1..-1] - case key - when 'text', 'label', 'show', 'data', 'file' + conf[__configinfo_struct[:key]] = + conf[__configinfo_struct[:key]][1..-1] + + case conf[__configinfo_struct[:key]] + 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 + else - if conf[2] - if conf[2].index('{') - conf[2] = tk_split_list(conf[2]) + 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[2] = tk_tcl2ruby(conf[2]) + conf[__configinfo_struct[:default_value]] = + tk_tcl2ruby(conf[__configinfo_struct[:default_value]]) end end - if conf[3] - if conf[3].index('{') - conf[3] = tk_split_list(conf[3]) + 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[3] = tk_tcl2ruby(conf[3]) + conf[__configinfo_struct[:current_value]] = + tk_tcl2ruby(conf[__configinfo_struct[:current_value]]) end end end - if conf.size == 1 - ret[key] = conf[0][1..-1] # alias info + + 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[key] = conf + ret[conf.shift] = conf end } - fontconf = ret['font'] - if fontconf - ret.delete('font') - ret.delete('kanjifont') - fontconf[3] = fontobj(fontconf[3]) - ret['font'] = fontconf - 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) + fontconf[__configinfo_struct[:current_value]] = fontobj(optkey) + ret[optkey] = fontconf + end + } + + __methodcall_optkeys.each{|optkey, method| + ret[optkey.to_s] = ['', '', '', self.__send__(method)] + } + ret end end @@ -2287,12 +2949,24 @@ class TkObject<TkKernel def current_configinfo(slot = nil) if TkComm::GET_CONFIGINFO_AS_ARRAY if slot - conf = configinfo(slot) - {conf[0] => conf[4]} + 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{|conf| - ret[conf[0]] = conf[4] if conf.size > 2 + if ( ! __configinfo_struct[:alias] \ + || conf.size > __configinfo_struct[:alias] + 1 ) + ret[conf[0]] = conf[-1] + end } ret end @@ -2304,6 +2978,67 @@ class TkObject<TkKernel ret end end +end + +class TkObject<TkKernel + 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 method_missing(id, *args) + name = id.id2name + case args.length + when 1 + if name[-1] == ?= + configure name[0..-2], args[0] + else + configure name, args[0] + end + when 0 + begin + cget(name) + rescue + fail NameError, + "undefined local variable or method `#{name}' for #{self.to_s}", + error_at + end + else + fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at + end + end + + def [](id) + cget(id) + end + + def []=(id, val) + configure(id, val) + val + end def event_generate(context, keys=nil) if keys @@ -2337,7 +3072,12 @@ class TkWindow<TkObject include TkWinfo extend TkBindCore + 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 @@ -2375,22 +3115,56 @@ class TkWindow<TkObject 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', '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) + } + + __methodcall_optkeys.each{|key| + key = key.to_s + methodkeys[key] = keys.delete(key) if keys.key?(key) + } end if without_creating && keys - configure(keys) + #configure(keys) + configure(__conv_keyonly_opts(keys)) else - create_self(keys) + #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 - fail RuntimeError, "TkWindow is an abstract class" + 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 + tk_call_without_enc(cmd, @path, *hash_kv(keys, true)) + else + tk_call_without_enc(cmd, @path) + end end private :create_self @@ -2912,3 +3686,11 @@ module Tk autoload :LIBRARY_PATH, 'tk/variable' autoload :TCL_PRECISION, 'tk/variable' end + + +# call setup script for Tk extension libraries (base configuration) +begin + require 'tkextlib/setup.rb' +rescue LoadError + # ignore +end diff --git a/ext/tk/lib/tk/autoload.rb b/ext/tk/lib/tk/autoload.rb index 0a8251af8b..e3c29e96ea 100644 --- a/ext/tk/lib/tk/autoload.rb +++ b/ext/tk/lib/tk/autoload.rb @@ -63,6 +63,8 @@ autoload :TkImage, 'tk/image' autoload :TkBitmapImage, 'tk/image' autoload :TkPhotoImage, 'tk/image' +autoload :TkItemConfigMethod, 'tk/itemconfig' + autoload :TkTreatItemFont, 'tk/itemfont' autoload :TkKinput, 'tk/kinput' @@ -150,6 +152,7 @@ autoload :TkToplevel, 'tk/toplevel' autoload :TkTextWin, 'tk/txtwin_abst' autoload :TkValidation, 'tk/validation' + autoload :TkVariable, 'tk/variable' autoload :TkVarAccess, 'tk/variable' @@ -167,9 +170,13 @@ autoload :TkXIM, 'tk/xim' # sub-module of Tk module Tk autoload :Clock, 'tk/clock' + autoload :OptionObj, 'tk/optionobj' autoload :Scrollable, 'tk/scrollable' autoload :Wm, 'tk/wm' + autoload :ValidateConfigure, 'tk/validation' + autoload :ItemValidateConfigure, 'tk/validation' + autoload :EncodedString, 'tk/encodedstr' def Tk.EncodedString(str, enc = nil); Tk::EncodedString.new(str, enc); end diff --git a/ext/tk/lib/tk/canvas.rb b/ext/tk/lib/tk/canvas.rb index b311db6e20..17a05c0ce1 100644 --- a/ext/tk/lib/tk/canvas.rb +++ b/ext/tk/lib/tk/canvas.rb @@ -7,16 +7,16 @@ # require 'tk' require 'tk/canvastag' -require 'tk/itemfont' +require 'tk/itemconfig' require 'tk/scrollable' -module TkTreatCItemFont - include TkTreatItemFont +module TkCanvasItemConfig + include TkItemConfigMethod - ItemCMD = ['itemconfigure'.freeze, TkComm::None].freeze - def __conf_cmd(idx) - ItemCMD[idx] + def __item_methodcall_optkeys(id) + {'coords'=>'coords'} end + private :__item_methodcall_optkeys def __item_pathname(tagOrId) if tagOrId.kind_of?(TkcItem) || tagOrId.kind_of?(TkcTag) @@ -25,12 +25,11 @@ module TkTreatCItemFont self.path + ';' + tagOrId.to_s end end - - private :__conf_cmd, :__item_pathname + private :__item_pathname end class TkCanvas<TkWindow - include TkTreatCItemFont + include TkCanvasItemConfig include Scrollable TkCommandNames = ['canvas'.freeze].freeze @@ -130,6 +129,7 @@ class TkCanvas<TkWindow tk_split_list(tk_send_without_enc('coords', tagid(tag))) else tk_send_without_enc('coords', tagid(tag), *(args.flatten)) + self end end @@ -217,6 +217,7 @@ class TkCanvas<TkWindow self end +=begin def itemcget(tagOrId, option) case option.to_s when 'dash', 'activedash', 'disableddash' @@ -453,6 +454,7 @@ class TkCanvas<TkWindow ret end end +=end def lower(tag, below=nil) if below @@ -523,6 +525,8 @@ end class TkcItem<TkObject extend Tk include TkcTagAccess + extend TkItemFontOptkeys + extend TkItemConfigOptkeys CItemTypeName = nil CItemTypeToClass = {} @@ -543,6 +547,7 @@ class TkcItem<TkObject ######################################## def self._parse_create_args(args) fontkeys = {} + methodkeys = {} if args[-1].kind_of? Hash keys = _symbolkey2str(args.pop) if args.size == 0 @@ -552,11 +557,30 @@ class TkcItem<TkObject end end - ['font', 'kanjifont', 'latinfont', 'asciifont'].each{|key| - fontkeys[key] = keys.delete(key) if keys.key?(key) + #['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) } - args = args.flatten.concat(hash_kv(keys)) + __item_methodcall_optkeys(nil).each{|key| + key = key.to_s + methodkeys[key] = keys.delete(key) if keys.key?(key) + } + + #args = args.flatten.concat(hash_kv(keys)) + args = args.flatten.concat(itemconfig_hash_kv(nil, keys)) else args = args.flatten end @@ -597,6 +621,14 @@ class TkcItem<TkObject @id end + def exist? + if @c.find_withtag(@id) + true + else + false + end + end + def delete @c.delete @id CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path] diff --git a/ext/tk/lib/tk/canvastag.rb b/ext/tk/lib/tk/canvastag.rb index 5a98127f6b..056bf74c05 100644 --- a/ext/tk/lib/tk/canvastag.rb +++ b/ext/tk/lib/tk/canvastag.rb @@ -204,6 +204,14 @@ class TkcTag<TkObject @id end + def exist? + if @c.find_withtag(@id) + true + else + false + end + end + def delete @c.delete @id CTagID_TBL[@cpath].delete(@id) if CTagID_TBL[@cpath] diff --git a/ext/tk/lib/tk/event.rb b/ext/tk/lib/tk/event.rb index b85c456d41..4c6c0844b2 100644 --- a/ext/tk/lib/tk/event.rb +++ b/ext/tk/lib/tk/event.rb @@ -1,7 +1,17 @@ # # tk/event.rb - module for event # -require 'tk' + +unless $LOADED_FEATURES.member?('tk.rb') + # change loading order + + $LOADED_FEATURES.delete('tk/event.rb') + + require 'tkutil' + require 'tk' + +else +################################################ module TkEvent class Event < TkUtil::CallbackSubst @@ -42,7 +52,7 @@ module TkEvent end # [ <'%' subst-key char>, <proc type char>, <instance var (accessor) name>] - key_tbl = [ + KEY_TBL = [ [ ?#, ?n, :serial ], [ ?a, ?s, :above ], [ ?b, ?n, :num ], @@ -76,7 +86,7 @@ module TkEvent ] # [ <proc type char>, <proc/method to convert tcl-str to ruby-obj>] - proc_tbl = [ + PROC_TBL = [ [ ?n, TkComm.method(:num_or_str) ], [ ?s, TkComm.method(:string) ], [ ?b, TkComm.method(:bool) ], @@ -106,13 +116,13 @@ module TkEvent # ( 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, PROC_TBL); end - def install_bind(cmd, *args) + def install_bind_for_event_class(klass, cmd, *args) if args.compact.size > 0 args = args.join(' ') - keys = Event._get_subst_key(args) + keys = klass._get_subst_key(args) if cmd.kind_of?(String) id = cmd @@ -120,12 +130,12 @@ module TkEvent id = install_cmd(cmd) else id = install_cmd(proc{|*arg| - TkUtil.eval_cmd(cmd, *Event.scan_args(keys, arg)) + TkUtil.eval_cmd(cmd, *klass.scan_args(keys, arg)) }) end id + ' ' + args else - keys, args = Event._get_all_subst_keys + keys, args = klass._get_all_subst_keys if cmd.kind_of?(String) id = cmd @@ -133,10 +143,17 @@ module TkEvent id = install_cmd(cmd) else id = install_cmd(proc{|*arg| - TkUtil.eval_cmd(cmd, Event.new(*Event.scan_args(keys, arg))) + TkUtil.eval_cmd(cmd, klass.new(*klass.scan_args(keys, arg))) }) end id + ' ' + args end end + + def install_bind(cmd, *args) + install_bind_for_event_class(Event, cmd, *args) + end +end + +################################################ end diff --git a/ext/tk/lib/tk/font.rb b/ext/tk/lib/tk/font.rb index 9b38531f59..b4c5c79213 100644 --- a/ext/tk/lib/tk/font.rb +++ b/ext/tk/lib/tk/font.rb @@ -73,25 +73,18 @@ class TkFont 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 rescue ltn = 'Helvetica' - knj = 'mincho' end - knj = ltn + knj = ltn.dup end DEFAULT_LATIN_FONT_NAME = ltn.freeze @@ -202,54 +195,74 @@ class TkFont end end - def TkFont.init_widget_font(path, *args) + def TkFont.init_widget_font(pathname, *args) + win, tag, key = pathname.split(';') + key = 'font' unless key + path = [win, tag, key].join(';') + case (Tk::TK_VERSION) when /^4\.*/ - conf = tk_split_simplelist(tk_call(*args)). - find_all{|prop| prop[0..5]=='-font ' || prop[0..10]=='-kanjifont '}. + regexp = /^-(|kanji)#{key} / + + conf_list = tk_split_simplelist(tk_call(*args)). + find_all{|prop| prop =~ regexp}. collect{|prop| tk_split_simplelist(prop)} - if font_inf = conf.assoc('-font') - ltn = font_inf[4] - ltn = nil if ltn == [] - else - #ltn = nil - raise RuntimeError, "unknown option '-font'" - end - if font_inf = conf.assoc('-kanjifont') - knj = font_inf[4] - knj = nil if knj == [] - else - knj = nil + + if conf_list.size == 0 + raise RuntimeError, "the widget may not support 'font' option" end - TkFont.new(ltn, knj).call_font_configure(path, *(args + [{}])) + + 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\.*/ - font_prop = tk_split_simplelist(tk_call(*args)).find{|prop| - prop[0..5] == '-font ' - } - unless font_prop - raise RuntimeError, "unknown option '-font'" + 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 - fnt = tk_split_simplelist(font_prop)[4] - if fnt == "" - TkFont.new(nil, nil).call_font_configure(path, *(args + [{}])) + + args << {} + + optkey = "-#{key}" + + info = conf_list.find{|conf| conf[0] == optkey} + fnt = info[-1] + fnt = nil if fnt == [] || fnt == "" + + unless fnt + TkFont.new(nil, nil).call_font_configure([path, key], *args) else begin compound = tk_split_simplelist( - Hash[*tk_split_simplelist(tk_call('font', 'configure', - fnt))].collect{|key,value| - [key[1..-1], value] - }.assoc('compound')[1]) + Hash[*tk_split_simplelist(tk_call('font', 'configure', + fnt))].collect{|key,value| + [key[1..-1], value] + }.assoc('compound')[1]) rescue compound = [] end if compound == [] - #TkFont.new(fnt, DEFAULT_KANJI_FONT_NAME) \ - #.call_font_configure(path, *(args + [{}])) - TkFont.new(fnt).call_font_configure(path, *(args + [{}])) + TkFont.new(fnt).call_font_configure([path, key], *args) else - TkFont.new(compound[0], compound[1]) \ - .call_font_configure(path, *(args + [{}])) + TkFont.new(compound[0], + compound[1]).call_font_configure([path, key], *args) end end end @@ -854,15 +867,16 @@ class TkFont if self == fobj begin if w.include?(';') - win, tag = w.split(';') + win, tag, optkey = w.split(';') + optkey = 'font' unless optkey winobj = tk_tcl2ruby(win) # winobj.tagfont_configure(tag, {'font'=>@latinfont}) if winobj.kind_of? TkText - tk_call(win, 'tag', 'configure', tag, '-font', @latinfont) + tk_call(win, 'tag', 'configure', tag, "-#{optkey}", @latinfont) elsif winobj.kind_of? TkCanvas - tk_call(win, 'itemconfigure', tag, '-font', @latinfont) + tk_call(win, 'itemconfigure', tag, "-#{optkey}", @latinfont) elsif winobj.kind_of? TkMenu - tk_call(win, 'entryconfigure', tag, '-font', @latinfont) + tk_call(win, 'entryconfigure', tag, "-#{optkey}", @latinfont) else raise RuntimeError, "unknown widget type" end @@ -888,15 +902,16 @@ class TkFont if self == fobj begin if w.include?(';') - win, tag = w.split(';') + win, tag, optkey = w.split(';') + optkey = 'kanjifont' unless optkey winobj = tk_tcl2ruby(win) # winobj.tagfont_configure(tag, {'kanjifont'=>@kanjifont}) if winobj.kind_of? TkText - tk_call(win, 'tag', 'configure', tag, '-kanjifont', @kanjifont) + tk_call(win, 'tag', 'configure', tag, "-#{optkey}", @kanjifont) elsif winobj.kind_of? TkCanvas - tk_call(win, 'itemconfigure', tag, '-kanjifont', @kanjifont) + tk_call(win, 'itemconfigure', tag, "-#{optkey}", @kanjifont) elsif winobj.kind_of? TkMenu - tk_call(win, 'entryconfigure', tag, '-kanjifont', @latinfont) + tk_call(win, 'entryconfigure', tag, "-#{optkey}", @latinfont) else raise RuntimeError, "unknown widget type" end @@ -1128,36 +1143,77 @@ class TkFont end def call_font_configure(path, *args) - keys = args.pop.update(@fontslot) + 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)) tk_call(*args) - Tk_FontUseTBL[path] = self + Tk_FontUseTBL[[win, tag, optkey].join(';')] = self self end def used ret = [] Tk_FontUseTBL.each{|key,value| + next unless self == value if key.include?(';') - win, tag = key.split(';') + win, tag, optkey = key.split(';') winobj = tk_tcl2ruby(win) if winobj.kind_of? TkText - ret.push([winobj, winobj.tagid2obj(tag)]) + if optkey + ret.push([winobj, winobj.tagid2obj(tag), optkey]) + else + ret.push([winobj, winobj.tagid2obj(tag)]) + end elsif winobj.kind_of? TkCanvas if (tagobj = TkcTag.id2obj(winobj, tag)).kind_of? TkcTag - ret.push([winobj, tagobj]) - elsif (tagobj = TkcItem.id2obj(tag)).kind_of? TkcItem - ret.push([winobj, tagobj]) + 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 - ret.push([winobj, tag]) + if optkey + ret.push([winobj, tag, optkey]) + else + ret.push([winobj, tag]) + end end elsif winobj.kind_of? TkMenu - ret.push([winobj, tag]) + if optkey + ret.push([winobj, tag, optkey]) + else + ret.push([winobj, tag]) + end else - ret.push([win, tag]) + if optkey + ret.push([win, tag, optkey]) + else + ret.push([win, tag]) + end end else - ret.push(tk_tcl2ruby(key)) if value == self + ret.push(tk_tcl2ruby(key)) end } ret diff --git a/ext/tk/lib/tk/itemconfig.rb b/ext/tk/lib/tk/itemconfig.rb new file mode 100644 index 0000000000..b1cc776748 --- /dev/null +++ b/ext/tk/lib/tk/itemconfig.rb @@ -0,0 +1,781 @@ +# +# tk/itemconfig.rb : control item/tag configuration of widget +# +require 'tk' +require 'tkutil' +require 'tk/itemfont.rb' + +module TkItemConfigOptkeys + 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) + [] + end + private :__item_boolval_optkeys + + def __item_strval_optkeys(id) + # maybe need to override + ['text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile'] + 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_methodcall_optkeys(id) # { key=>method, ... } + # 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 __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_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 itemcget(tagOrId, option) + option = option.to_s + + 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_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 + + def itemconfigure(tagOrId, slot, value=None) + if slot.kind_of? Hash + slot = _symbolkey2str(slot) + + __item_methodcall_optkeys(tagid(tagOrId)).each{|key, method| + value = slot.delete(key.to_s) + self.__send__(method, tagOrId, value) if value + } + + __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 + slot = slot.to_s + 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_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 + + def itemconfiginfo(tagOrId, slot = nil) + if TkComm::GET_CONFIGINFO_AS_ARRAY + if (slot.to_s =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/) + fontkey = $2 + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_config_cmd(tagid(tagOrId)) << "-#{fontkey}")))) + 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))[: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 + case slot + 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_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + + 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_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + + 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_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + + 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_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + + 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_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + + 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_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + + else + conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__item_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + 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_config_cmd(tagid(tagOrId)))))).collect{|conflist| + conf = tk_split_simplelist(conflist) + conf[__item_configinfo_struct(tagid(tagOrId))[:key]] = + conf[__item_configinfo_struct(tagid(tagOrId))[:key]][1..-1] + + case conf[__item_configinfo_struct(tagid(tagOrId))[:key]] + 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 + + 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}$/} + 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.to_s =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/) + fontkey = $2 + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_config_cmd(tagid(tagOrId)) << "-#{fontkey}")))) + 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))[:current_value]] = fontobj(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 + case slot + 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_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + + 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_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + + 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_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + + 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_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + + 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_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + + 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_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + + else + conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__item_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + 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_config_cmd(tagid(tagOrId)))))).each{|conflist| + conf = tk_split_simplelist(conflist) + conf[__item_configinfo_struct(tagid(tagOrId))[:key]] = + conf[__item_configinfo_struct(tagid(tagOrId))[:key]][1..-1] + + case conf[__item_configinfo_struct(tagid(tagOrId))[:key]] + 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 + + 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) + 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 + + def current_itemconfiginfo(tagOrId, slot = nil) + if TkComm::GET_CONFIGINFO_AS_ARRAY + if slot + org_slot = slot + begin + conf = itemconfiginfo(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(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(slot).each{|key, conf| + ret[key] = conf[-1] if conf.kind_of?(Array) + } + ret + end + end +end diff --git a/ext/tk/lib/tk/itemfont.rb b/ext/tk/lib/tk/itemfont.rb index 6e92fc001c..f653755b06 100644 --- a/ext/tk/lib/tk/itemfont.rb +++ b/ext/tk/lib/tk/itemfont.rb @@ -3,182 +3,294 @@ # require 'tk' -module TkTreatItemFont - def __conf_cmd(idx) - raise NotImplementedError, "need to define `__conf_cmd'" +module TkItemFontOptkeys + def __item_font_optkeys(id) + # maybe need to override + ['font'] end - def __item_pathname(tagOrId) - raise NotImplementedError, "need to define `__item_pathname'" + private :__item_font_optkeys +end + +module TkTreatItemFont + include TkItemFontOptkeys + + def __item_pathname(id) + # maybe need to override + [self.path, id].join(';') end - private :__conf_cmd, :__item_pathname - - def tagfont_configinfo(tagOrId, name = nil) - pathname = __item_pathname(tagOrId) - ret = TkFont.used_on(pathname) - if ret == nil -=begin - if name - ret = name - else - ret = TkFont.init_widget_font(pathname, self.path, - __conf_cmd(0), __conf_cmd(1), tagOrId) - end -=end - ret = TkFont.init_widget_font(pathname, self.path, - __conf_cmd(0), __conf_cmd(1), tagOrId) + 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_config_cmd(tagid(tagOrId)))) + elsif optkeys.size == 1 + pathname = [win, tag, optkeys[0]].join(';') + TkFont.used_on(pathname) || + TkFont.init_widget_font(pathname, *(__item_config_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_config_cmd(tagid(tagOrId)))) + } + fonts end - ret end alias tagfontobj tagfont_configinfo def tagfont_configure(tagOrId, slot) - pathname = __item_pathname(tagOrId) + pathname = __item_pathname(tagid(tagOrId)) + slot = _symbolkey2str(slot) - if slot.key?('font') - fnt = slot.delete('font') - if fnt.kind_of? TkFont - return fnt.call_font_configure(pathname, self.path, - __conf_cmd(0), __conf_cmd(1), - tagOrId, slot) - else - if fnt - if (slot.key?('kanjifont') || - slot.key?('latinfont') || - slot.key?('asciifont')) - fnt = TkFont.new(fnt) - - lfnt = slot.delete('latinfont') - lfnt = slot.delete('asciifont') if slot.key?('asciifont') - kfnt = slot.delete('kanjifont') - - fnt.latin_replace(lfnt) if lfnt - fnt.kanji_replace(kfnt) if kfnt - end + __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) - slot['font'] = fnt - tk_call(self.path, __conf_cmd(0), __conf_cmd(1), - tagOrId, *hash_kv(slot)) + 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 + tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << fnt)) + end + end + next end - return self end - end - lfnt = slot.delete('latinfont') - lfnt = slot.delete('asciifont') if slot.key?('asciifont') - kfnt = slot.delete('kanjifont') + lfnt = slot.delete(l_optkey) + lfnt = slot.delete(a_optkey) if slot.key?(a_optkey) + kfnt = slot.delete(k_optkey) - if lfnt && kfnt - return TkFont.new(lfnt, kfnt).call_font_configure(pathname, self.path, - __conf_cmd(0), - __conf_cmd(1), - tagOrId, slot) - end + 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 + } - latintagfont_configure(tagOrId, lfnt) if lfnt - kanjitagfont_configure(tagOrId, kfnt) if kfnt - - tk_call(self.path, __conf_cmd(0), __conf_cmd(1), - tagOrId, *hash_kv(slot)) if slot != {} + # 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) - pathname = __item_pathname(tagOrId) - if (fobj = TkFont.used_on(pathname)) - fobj = TkFont.new(fobj) # create a new TkFont object - elsif Tk::JAPANIZED_TK - fobj = tagfontobj(tagOrId) # create a new TkFont object + if ltn.kind_of?(Array) + key = ltn[1] + ltn = ltn[0] else - tk_call(self.path, __conf_cmd(0), __conf_cmd(1), tagOrId, '-font', ltn) - return self + 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 - 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)) + 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 + tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << ltn)) + 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_configure(conf) + fobj.latin_replace(ltn) end - else - fobj.latin_replace(ltn) end - end - return fobj.call_font_configure(pathname, self.path, - __conf_cmd(0), __conf_cmd(1), tagOrId, {}) + 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) - pathname = __item_pathname(tagOrId) - if (fobj = TkFont.used_on(pathname)) - fobj = TkFont.new(fobj) # create a new TkFont object - elsif Tk::JAPANIZED_TK - fobj = tagfontobj(tagOrId) # create a new TkFont object + if knj.kind_of?(Array) + key = knj[1] + knj = knj[0] else - tk_call(self.path, __conf_cmd(0), __conf_cmd(1), tagOrId, '-font', knj) - return self + 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 - 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)) + 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 + tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << knj)) + 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_configure(conf) + fobj.kanji_replace(knj) end - else - fobj.kanji_replace(knj) end - end - return fobj.call_font_configure(pathname, self.path, - __conf_cmd(0), __conf_cmd(1), tagOrId, {}) + fobj.call_font_configure([pathname, optkey], *(__item_config_cmd(tagid(tagOrId)) << {})) + } + self end - def tagfont_copy(tagOrId, window, wintag=nil) - pathname = __item_pathname(tagOrId) + def tagfont_copy(tagOrId, window, wintag=nil, winkey=nil, targetkey=nil) if wintag - fnt = window.tagfontobj(wintag).dup + if winkey + fnt = window.tagfontobj(wintag, winkey).dup + else + fnt = window.tagfontobj(wintag).dup + end else - fnt = window.fontobj.dup + if winkey + fnt = window.fontobj(winkey).dup + else + fnt = window.fontobj.dup + end end - fnt.call_font_configure(pathname, self.path, - __conf_cmd(0), __conf_cmd(1), tagOrId, {}) - return self + + 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, window, wintag=nil) - pathname = __item_pathname(tagOrId) - tagfontobj(tagOrId).dup.call_font_configure(pathname, self.path, - __conf_cmd(0), __conf_cmd(1), - tagOrId, {}) + + def latintagfont_copy(tagOrId, window, 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 - tagfontobj(tagOrId). - latin_replace(window.tagfontobj(wintag).latin_font_id) + if winkey + fontobj.latin_replace(window.tagfontobj(wintag, winkey).latin_font_id) + else + fontobj.latin_replace(window.tagfontobj(wintag).latin_font_id) + end else - tagfontobj(tagOrId).latin_replace(window.fontobj.latin_font_id) + if winkey + fontobj.latin_replace(window.fontobj(winkey).latin_font_id) + else + fontobj.latin_replace(window.fontobj.latin_font_id) + end end self end alias asciitagfont_copy latintagfont_copy - def kanjitagfont_copy(tagOrId, window, wintag=nil) - pathname = __item_pathname(tagOrId) - tagfontobj(tagOrId).dup.call_font_configure(pathname, self.path, - __conf_cmd(0), __conf_cmd(1), - tagOrId, {}) + def kanjifont_copy(tagOrId, window, 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 - tagfontobj(tagOrId). - kanji_replace(window.tagfontobj(wintag).kanji_font_id) + if winkey + fontobj.kanji_replace(window.tagfontobj(wintag, winkey).kanji_font_id) + else + fontobj.kanji_replace(window.tagfontobj(wintag).kanji_font_id) + end else - tagfontobj(tagOrId).kanji_replace(window.fontobj.kanji_font_id) + if winkey + fontobj.kanji_replace(window.fontobj(winkey).kanji_font_id) + else + fontobj.kanji_replace(window.fontobj.kanji_font_id) + end end self end diff --git a/ext/tk/lib/tk/listbox.rb b/ext/tk/lib/tk/listbox.rb index 611226682a..799d573b1d 100644 --- a/ext/tk/lib/tk/listbox.rb +++ b/ext/tk/lib/tk/listbox.rb @@ -2,27 +2,21 @@ # tk/listbox.rb : treat listbox widget # require 'tk' +require 'tk/itemconfig' require 'tk/scrollable' require 'tk/txtwin_abst' -module TkTreatListItemFont - include TkTreatItemFont +module TkListItemConfig + include TkItemConfigMethod - ItemCMD = ['itemconfigure'.freeze, TkComm::None].freeze - def __conf_cmd(idx) - ItemCMD[idx] + def __item_listval_optkeys(id) + [] end - - def __item_pathname(tagOrId) - self.path + ';' + tagOrId.to_s - end - - private :__conf_cmd, :__item_pathname + private :__item_listval_optkeys end - class TkListbox<TkTextWin - include TkTreatListItemFont + include TkListItemConfig include Scrollable TkCommandNames = ['listbox'.freeze].freeze @@ -38,6 +32,10 @@ class TkListbox<TkTextWin end private :create_self + def tagid(id) + id.to_s + end + def activate(y) tk_send_without_enc('activate', y) self @@ -78,6 +76,7 @@ class TkListbox<TkTextWin tk_send_without_enc('index', index).to_i end +=begin def itemcget(index, key) case key.to_s when 'text', 'label', 'show' @@ -249,4 +248,5 @@ class TkListbox<TkTextWin ret end end +=end end diff --git a/ext/tk/lib/tk/menu.rb b/ext/tk/lib/tk/menu.rb index 9c34741b1b..f5a16cf3cf 100644 --- a/ext/tk/lib/tk/menu.rb +++ b/ext/tk/lib/tk/menu.rb @@ -2,24 +2,37 @@ # tk/menu.rb : treat menu and menubutton # require 'tk' +require 'tk/itemconfig' -module TkTreatMenuEntryFont - include TkTreatItemFont +module TkMenuEntryConfig + include TkItemConfigMethod - ItemCMD = ['entryconfigure'.freeze, TkComm::None].freeze - def __conf_cmd(idx) - ItemCMD[idx] + def __item_cget_cmd(id) + [self.path, 'entrycget', id] end - - def __item_pathname(tagOrId) - self.path + ';' + tagOrId.to_s + private :__item_cget_cmd + + def __item_config_cmd(id) + [self.path, 'entryconfigure', id] + end + private :__item_config_cmd + + def __item_listval_optkeys(id) + [] end + private :__item_listval_optkeys + + alias entrycget itemcget + alias entryconfigure itemconfigure + alias entryconfiginfo itemconfiginfo + alias current_entryconfiginfo current_itemconfiginfo - private :__conf_cmd, :__item_pathname + private :itemcget, :itemconfigure + private :itemconfiginfo, :current_itemconfiginfo end class TkMenu<TkWindow - include TkTreatMenuEntryFont + include TkMenuEntryConfig TkCommandNames = ['menu'.freeze].freeze WidgetClassName = 'Menu'.freeze @@ -34,6 +47,10 @@ class TkMenu<TkWindow end private :create_self + def tagid(id) + id.to_s + end + def activate(index) tk_send_without_enc('activate', _get_eval_enc_str(index)) self @@ -116,6 +133,8 @@ class TkMenu<TkWindow 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' @@ -287,6 +306,7 @@ class TkMenu<TkWindow ret end end +=end end diff --git a/ext/tk/lib/tk/optionobj.rb b/ext/tk/lib/tk/optionobj.rb new file mode 100644 index 0000000000..2c8a1efd5e --- /dev/null +++ b/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/ext/tk/lib/tk/package.rb b/ext/tk/lib/tk/package.rb index 8768bf1c79..dbb0ca33e8 100644 --- a/ext/tk/lib/tk/package.rb +++ b/ext/tk/lib/tk/package.rb @@ -18,6 +18,36 @@ module TkPackage 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 @@ -25,26 +55,74 @@ module TkPackage def provide(package, version=nil) if version tk_call('package', 'provide', package, version) + end + if (ret = tk_call('package', 'provide', package)) == '' nil else - tk_call('package', 'provide', package) + ret end end def present(package, version=None) - tk_call('package', 'present', package, version) + begin + tk_call('package', 'present', package, version) + rescue => e + fail e.class, 'TkPackage ' << e.message + end end def present_exact(package, version) - tk_call('package', '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) - tk_call('package', 'require', package, version) + begin + tk_call('package', 'require', package, version) + rescue => e + fail e.class, 'TkPackage ' << e.message + end end def require_exact(package, version) - tk_call('package', '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) diff --git a/ext/tk/lib/tk/scrollable.rb b/ext/tk/lib/tk/scrollable.rb index e591a299ab..c5f4fdb70c 100644 --- a/ext/tk/lib/tk/scrollable.rb +++ b/ext/tk/lib/tk/scrollable.rb @@ -7,10 +7,15 @@ module Tk module Scrollable def xscrollcommand(cmd=Proc.new) configure_cmd 'xscrollcommand', cmd + # Tk.update # avoid scrollbar trouble + self end def yscrollcommand(cmd=Proc.new) configure_cmd 'yscrollcommand', cmd + # Tk.update # avoid scrollbar trouble + self end + def xview(*index) if index.size == 0 list(tk_send_without_enc('xview')) @@ -19,6 +24,13 @@ module Tk 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')) @@ -27,6 +39,13 @@ module Tk self end end + def yview_moveto(*index) + yview('moveto', *index) + end + def yview_scroll(*index) + yview('scroll', *index) + end + def xscrollbar(bar=nil) if bar @xscrollbar = bar @@ -34,6 +53,7 @@ module Tk self.xscrollcommand {|*arg| @xscrollbar.set(*arg)} @xscrollbar.command {|*arg| self.xview(*arg)} end + Tk.update # avoid scrollbar trouble @xscrollbar end def yscrollbar(bar=nil) @@ -43,6 +63,7 @@ module Tk self.yscrollcommand {|*arg| @yscrollbar.set(*arg)} @yscrollbar.command {|*arg| self.yview(*arg)} end + Tk.update # avoid scrollbar trouble @yscrollbar end end diff --git a/ext/tk/lib/tk/scrollbar.rb b/ext/tk/lib/tk/scrollbar.rb index 0ee4423c9a..8d4d40322d 100644 --- a/ext/tk/lib/tk/scrollbar.rb +++ b/ext/tk/lib/tk/scrollbar.rb @@ -41,6 +41,7 @@ class TkScrollbar<TkWindow w.yscrollcommand proc{|first, last| self.set(first, last)} end } + Tk.update # avoid scrollbar trouble self end @@ -52,6 +53,12 @@ class TkScrollbar<TkWindow 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)) diff --git a/ext/tk/lib/tk/scrollbox.rb b/ext/tk/lib/tk/scrollbox.rb index f0fdece260..5f304d377f 100644 --- a/ext/tk/lib/tk/scrollbox.rb +++ b/ext/tk/lib/tk/scrollbox.rb @@ -14,10 +14,15 @@ class TkScrollbox<TkListbox 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) diff --git a/ext/tk/lib/tk/text.rb b/ext/tk/lib/tk/text.rb index be3f814505..7593b59368 100644 --- a/ext/tk/lib/tk/text.rb +++ b/ext/tk/lib/tk/text.rb @@ -4,32 +4,66 @@ # by Yukihiro Matsumoto <matz@caelum.co.jp> require 'tk' require 'tk/itemfont' +require 'tk/itemconfig' require 'tk/scrollable' require 'tk/txtwin_abst' -module TkTreatTextTagFont +module TkTextTagConfig include TkTreatItemFont + include TkItemConfigMethod - ItemCMD = ['tag'.freeze, 'configure'.freeze].freeze - def __conf_cmd(idx) - ItemCMD[idx] + def __item_cget_cmd(id) # id := [ type, tagOrId ] + [self.path, id[0], 'cget', id[1]] end + private :__item_cget_cmd - def __item_pathname(tagOrId) - if tagOrId.kind_of?(TkTextTag) - self.path + ';' + tagOrId.id - else - self.path + ';' + tagOrId + 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 - private :__conf_cmd, :__item_pathname -end + def tag_cget(tagOrId, option) + itemcget(['tag', tagOrId], option) + end + def tag_configure(tagOrId, slot, value=None) + itemconfigure(['tag', tagOrId], slot, value) + end + def tag_configinfo(tagOrId, slot=nil) + itemconfigure(['tag', tagOrId], slot) + end + def current_tag_configinfo(tagOrId, slot=nil) + itemconfigure(['tag', tagOrId], slot) + end + + def window_cget(tagOrId, option) + itemcget(['window', tagOrId], option) + end + def window_configure(tagOrId, slot, value=None) + itemconfigure(['window', tagOrId], slot, value) + end + def window_configinfo(tagOrId, slot=nil) + itemconfigure(['window', tagOrId], slot) + end + def current_window_configinfo(tagOrId, slot=nil) + itemconfigure(['window', tagOrId], slot) + end + private :itemcget, :itemconfigure + private :itemconfiginfo, :current_itemconfiginfo +end class TkText<TkTextWin ItemConfCMD = ['tag'.freeze, 'configure'.freeze].freeze - include TkTreatTextTagFont + #include TkTreatTextTagFont + include TkTextTagConfig include Scrollable TkCommandNames = ['text'.freeze].freeze @@ -90,6 +124,18 @@ class TkText<TkTextWin @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 + end + end + private :tagid + def tagid2obj(tagid) if @tags[tagid] @tags[tagid] @@ -482,6 +528,7 @@ class TkText<TkTextWin _bindinfo([@path, 'tag', 'bind', tag], context) end +=begin def tag_cget(tag, key) case key.to_s when 'text', 'label', 'show', 'data', 'file' @@ -655,6 +702,7 @@ class TkText<TkTextWin ret end end +=end def tag_raise(tag, above=None) tk_send_without_enc('tag', 'raise', _get_eval_enc_str(tag), @@ -698,6 +746,7 @@ class TkText<TkTextWin _get_eval_enc_str(last))) end +=begin def window_cget(index, slot) case slot.to_s when 'text', 'label', 'show', 'data', 'file' @@ -732,7 +781,7 @@ class TkText<TkTextWin if slot['create'] p_create = slot['create'] if p_create.kind_of? Proc -=begin +#=begin slot['create'] = install_cmd(proc{ id = p_create.call if id.kind_of?(TkWindow) @@ -741,7 +790,7 @@ class TkText<TkTextWin id end }) -=end +#=end slot['create'] = install_cmd(proc{_epath(p_create.call)}) end end @@ -757,7 +806,7 @@ class TkText<TkTextWin if slot == 'create' || slot == :create p_create = value if p_create.kind_of? Proc -=begin +#=begin value = install_cmd(proc{ id = p_create.call if id.kind_of?(TkWindow) @@ -766,7 +815,7 @@ class TkText<TkTextWin id end }) -=end +#=end value = install_cmd(proc{_epath(p_create.call)}) end end @@ -879,6 +928,7 @@ class TkText<TkTextWin ret end end +=end def window_names tk_split_simplelist(_fromUTF8(tk_send_without_enc('window', 'names'))).collect{|elt| diff --git a/ext/tk/lib/tk/textmark.rb b/ext/tk/lib/tk/textmark.rb index 8b42df2f0c..18d52a5bfc 100644 --- a/ext/tk/lib/tk/textmark.rb +++ b/ext/tk/lib/tk/textmark.rb @@ -37,6 +37,14 @@ class TkTextMark<TkObject @id end + def exist? + if ( tk_split_simplelist(_fromUTF8(tk_call_without_enc(@t.path, 'mark', 'names'))).find{|id| id == @id } ) + true + else + false + end + end + def +(mod) @id + ' + ' + mod end diff --git a/ext/tk/lib/tk/texttag.rb b/ext/tk/lib/tk/texttag.rb index 561a027f08..17909bbfcf 100644 --- a/ext/tk/lib/tk/texttag.rb +++ b/ext/tk/lib/tk/texttag.rb @@ -49,6 +49,14 @@ class TkTextTag<TkObject @id end + def exist? + if ( tk_split_simplelist(_fromUTF8(tk_call_without_enc(@t.path, 'tag', 'names'))).find{|id| id == @id } ) + true + else + false + end + end + def first @id + '.first' end @@ -100,6 +108,10 @@ class TkTextTag<TkObject end def cget(key) + @t.tag_cget @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}")) @@ -121,6 +133,7 @@ class TkTextTag<TkObject @id, "-#{key}"))) end end +=end def configure(key, val=None) @t.tag_configure @id, key, val diff --git a/ext/tk/lib/tk/validation.rb b/ext/tk/lib/tk/validation.rb index 70e84e6cbf..0524a43757 100644 --- a/ext/tk/lib/tk/validation.rb +++ b/ext/tk/lib/tk/validation.rb @@ -3,7 +3,106 @@ # require 'tk' +module Tk + module ValidateConfigure + 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 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] = 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 = klass.new(value) + end + end + super(slot, value) + end + + self + end + end + + module ItemValidateConfigure + 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 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] = 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 = klass.new(value) + end + end + super(slot, value) + end + + self + end + end +end + module TkValidation + include Tk::ValidateConfigure + class ValidateCmd include TkComm @@ -18,7 +117,7 @@ module TkValidation end class ValidateArgs < TkUtil::CallbackSubst - key_tbl = [ + KEY_TBL = [ [ ?d, ?n, :action ], [ ?i, ?x, :index ], [ ?s, ?e, :current ], @@ -30,7 +129,7 @@ module TkValidation nil ] - proc_tbl = [ + PROC_TBL = [ [ ?n, TkComm.method(:number) ], [ ?s, TkComm.method(:string) ], [ ?w, TkComm.method(:window) ], @@ -58,24 +157,31 @@ module TkValidation nil ] - _setup_subst_table(key_tbl, proc_tbl); + _setup_subst_table(KEY_TBL, PROC_TBL); end - def initialize(cmd = Proc.new, *args) + ############################## + + 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) if args.compact.size > 0 args = args.join(' ') - keys = ValidateArgs._get_subst_key(args) + 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| - (cmd.call(*ValidateArgs.scan_args(keys, arg)))? '1':'0' + (cmd.call(*klass.scan_args(keys, arg)))? '1':'0' }) + ' ' + args end else - keys, args = ValidateArgs._get_all_subst_keys + keys, args = klass._get_all_subst_keys if cmd.kind_of?(String) id = cmd elsif cmd.kind_of?(TkCallbackEntry) @@ -83,13 +189,17 @@ module TkValidation else @id = install_cmd(proc{|*arg| (cmd.call( - ValidateArgs.new(*ValidateArgs.scan_args(keys,arg))) + klass.new(*klass.scan_args(keys,arg))) )? '1': '0' }) + ' ' + args end end end + def initialize(cmd = Proc.new, *args) + _initialize_for_cb_class(ValidateArgs, cmd, *args) + end + def to_eval @id end @@ -97,49 +207,8 @@ module TkValidation ##################################### - def configure(slot, value=TkComm::None) - if slot.kind_of? Hash - slot = _symbolkey2str(slot) - if slot['vcmd'].kind_of? Array - cmd, *args = slot['vcmd'] - slot['vcmd'] = ValidateCmd.new(cmd, args.join(' ')) - elsif slot['vcmd'].kind_of? Proc - slot['vcmd'] = ValidateCmd.new(slot['vcmd']) - end - if slot['validatecommand'].kind_of? Array - cmd, *args = slot['validatecommand'] - slot['validatecommand'] = ValidateCmd.new(cmd, args.join(' ')) - elsif slot['validatecommand'].kind_of? Proc - slot['validatecommand'] = ValidateCmd.new(slot['validatecommand']) - end - if slot['invcmd'].kind_of? Array - cmd, *args = slot['invcmd'] - slot['invcmd'] = ValidateCmd.new(cmd, args.join(' ')) - elsif slot['invcmd'].kind_of? Proc - slot['invcmd'] = ValidateCmd.new(slot['invcmd']) - end - if slot['invalidcommand'].kind_of? Array - cmd, *args = slot['invalidcommand'] - slot['invalidcommand'] = ValidateCmd.new(cmd, args.join(' ')) - elsif slot['invalidcommand'].kind_of? Proc - slot['invalidcommand'] = ValidateCmd.new(slot['invalidcommand']) - end - super(slot) - else - if (slot == 'vcmd' || slot == :vcmd || - slot == 'validatecommand' || slot == :validatecommand || - slot == 'invcmd' || slot == :invcmd || - slot == 'invalidcommand' || slot == :invalidcommand) - if value.kind_of? Array - cmd, *args = value - value = ValidateCmd.new(cmd, args.join(' ')) - elsif value.kind_of? Proc - value = ValidateCmd.new(value) - end - end - super(slot, value) - end - self + def __validation_class_list + super << ValidateCmd end def validatecommand(cmd = Proc.new, args = nil) diff --git a/ext/tk/lib/tk/variable.rb b/ext/tk/lib/tk/variable.rb index 43baac458d..61d6e8a410 100644 --- a/ext/tk/lib/tk/variable.rb +++ b/ext/tk/lib/tk/variable.rb @@ -84,6 +84,14 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL') end end + def self.new_hash(val = {}) + if val.kind_of?(Hash) + self.new(val) + else + fail ArgumentError, 'Hash is expected' + end + end + def initialize(val="") # @id = Tk_VARIABLE_ID.join('') @id = Tk_VARIABLE_ID.join(TkCore::INTERP._ip_id_) @@ -103,6 +111,12 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL') 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 @@ -185,7 +199,7 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL') def is_hash? #ITNERP._eval("global #{@id}; array exist #{@id}") == '1' - ITNERP._invoke_without_enc('array', 'exist', @id) == '1' + INTERP._invoke_without_enc('array', 'exist', @id) == '1' end def is_scalar? @@ -197,7 +211,23 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL') fail RuntimeError, 'cannot get keys from a scalar variable' end #tk_split_simplelist(INTERP._eval("global #{@id}; array get #{@id}")) - tk_split_simplelist(INTERP._fromUTF8(INTERP._invoke_without_enc('array', 'get', @id))) + tk_split_simplelist(INTERP._fromUTF8(INTERP._invoke_without_enc('array', 'names', @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 @@ -222,10 +252,11 @@ if USE_TCLs_SET_VARIABLE_FUNCTIONS def value=(val) 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), + INTERP._set_global_var2(@id, _get_eval_string(k, true), _get_eval_string(v, true)) } self.value @@ -260,7 +291,7 @@ if USE_TCLs_SET_VARIABLE_FUNCTIONS def unset(elem=nil) if elem - INTERP._unset_global_var2(@id, tk_tcl2ruby(elem)) + INTERP._unset_global_var2(@id, _get_eval_string(elem, true)) else INTERP._unset_global_var(@id) end @@ -359,7 +390,7 @@ else def unset(elem=nil) if elem INTERP._eval(Kernel.format('global %s; unset %s(%s)', - @id, @id, tk_tcl2ruby(elem))) + @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) + ')') else @@ -387,6 +418,29 @@ end val end + def bool + # see Tcl_GetBoolean man-page + case value.downcase + when '0', 'false', 'no', 'off' + false + else + true + end + end + + def 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 + end + def to_i number(value).to_i end @@ -570,7 +624,8 @@ end def trace(opts, cmd = Proc.new) @trace_var = [] if @trace_var == nil - opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') + #opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') + opts = ['r','w','u'].find_all{|c| opts.to_s.index(c)}.join('') @trace_var.unshift([opts,cmd]) if @trace_opts == nil TkVar_CB_TBL[@id] = self @@ -619,7 +674,8 @@ end def trace_element(elem, opts, cmd = Proc.new) @trace_elem = {} if @trace_elem == nil @trace_elem[elem] = [] if @trace_elem[elem] == nil - opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') + #opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') + opts = ['r','w','u'].find_all{|c| opts.to_s.index(c)}.join('') @trace_elem[elem].unshift([opts,cmd]) if @trace_opts == nil TkVar_CB_TBL[@id] = self @@ -678,7 +734,8 @@ end def trace_vdelete(opts,cmd) return self unless @trace_var.kind_of? Array - opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') + #opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') + opts = ['r','w','u'].find_all{|c| opts.to_s.index(c)}.join('') idx = -1 newopts = '' @trace_var.each_with_index{|e,i| @@ -702,7 +759,8 @@ end } } - newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('') + #newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('') + newopts = ['r','w','u'].find_all{|c| newopts.to_s.index(c)}.join('') if newopts != @trace_opts Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts, 'rb_var') =begin @@ -739,7 +797,8 @@ end def trace_vdelete_for_element(elem,opts,cmd) return self unless @trace_elem.kind_of? Hash return self unless @trace_elem[elem].kind_of? Array - opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') + # opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') + opts = ['r','w','u'].find_all{|c| opts.to_s.index(c)}.join('') idx = -1 @trace_elem[elem].each_with_index{|e,i| if idx < 0 && e[0] == opts && e[1] == cmd @@ -765,7 +824,8 @@ end } } - newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('') + #newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('') + newopts = ['r','w','u'].find_all{|c| newopts.to_s.index(c)}.join('') if newopts != @trace_opts Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts, 'rb_var') =begin @@ -807,6 +867,15 @@ class TkVarAccess<TkVariable super(name, *args) end + def self.new_hash(name, *args) + return TkVar_ID_TBL[name] if TkVar_ID_TBL[name] + if args.empty? && INTERP._invoke_without_enc('array', 'exist', name) == '0' + self.new(name, {}) # force creating + else + self.new(name, *args) + end + end + def initialize(varname, val=nil) @id = varname TkVar_ID_TBL[@id] = self @@ -815,6 +884,11 @@ class TkVarAccess<TkVariable INTERP._invoke_without_enc('global', @id) 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)) diff --git a/ext/tk/lib/tkextlib/ICONS.rb b/ext/tk/lib/tkextlib/ICONS.rb new file mode 100644 index 0000000000..84f4204c60 --- /dev/null +++ b/ext/tk/lib/tkextlib/ICONS.rb @@ -0,0 +1,16 @@ +# +# ICONS support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# library directory +dir = File.expand_path(__FILE__).sub(/#{File.extname(__FILE__)}$/, '') + +# call setup script +require File.join(dir, 'setup.rb') + +# load library +require File.join(dir, 'icons') diff --git a/ext/tk/lib/tkextlib/ICONS/icons.rb b/ext/tk/lib/tkextlib/ICONS/icons.rb new file mode 100644 index 0000000000..fe8351fa52 --- /dev/null +++ b/ext/tk/lib/tkextlib/ICONS/icons.rb @@ -0,0 +1,84 @@ +# +# 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 File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('icons', '1.0') +TkPackage.require('icons') + +module Tk + class ICONS < TkImage + def self.create(*args) # icon, icon, ..., keys + if args[-1].kind_of?(Hash) + keys = args.pop + icons = simplelist(tk_call('::icons::icons', 'create', + *(hash_kv(keys).concat(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) + return if icons.empty? + tk_call('::icons::icons', 'delete', icons) + end + + def self.query(*args) + if args[-1].kind_of?(Hash) + keys = args.pop + list(tk_call('::icons::icons', 'query', + *(hash_kv(keys).concat(args.flatten)))) + else + list(tk_call('::icons::icons', 'query', *(args.flatten))) + end + end + + ########################################## + + def self.new(name, keys=nil) + Tk_IMGTBL["::icon::#{name}"] || super + 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/ext/tk/lib/tkextlib/ICONS/setup.rb b/ext/tk/lib/tkextlib/ICONS/setup.rb new file mode 100644 index 0000000000..ce0f0bd4d4 --- /dev/null +++ b/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/ext/tk/lib/tkextlib/SUPPORT_STATUS b/ext/tk/lib/tkextlib/SUPPORT_STATUS new file mode 100644 index 0000000000..6cc5e15617 --- /dev/null +++ b/ext/tk/lib/tkextlib/SUPPORT_STATUS @@ -0,0 +1,161 @@ + + [ current support status of Tcl/Tk extensions ] + +The following list shows *CURRENT* status when this file was modifyed +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. + + 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 extention 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 oprations into the "setup.rb" file in the directory + of the wrapper libraries for the extention (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 http://sf.net/projects/tcllib + ==> tcllib (partial support; Tklib part only) + +vu http://tktable.sourceforge.net ==> vu + +TkHTML http://www.hwaci.com/sw/tkhtml/index.html ==> tkHTML + + + +===< support (may be alpha or beta quality) >================================= + +TkImg http://sf.net/projects/tkimg ==> tkimg + +TkTreeCtrl http://tktreectrl.sourceforge.net/ ==> treectrl + +Tile http://tktable.sourceforge.net/tile/ ==> tile + + + +===< possibly support (not tested; alpha quality) >=========================== + +TkTrans http://www2.cmp.uea.ac.uk/~fuzz/tktrans/default.html + ==> tktrans (win32 only) + +TkDND http://sourceforge.net/projects/tkdnd ==> tkDND + +ICONS http://www.satisoft.com/tcltk/icons/ ==> ICONS + + + +===< plan to support (alpha quality libraries may be included) >============== + +TclX http://sf.net/projects/tclx * may support Tk part only + +IncrTcl http://sf.net/projects/incrTcl * may support Tk part only + +IWidgets http://sf.net/projects/incrTcl + +TkTable http://sf.net/projects/tktable + * see http://www.korus.hu/~fery/ruby/tktable.rb + +BWidgets http://sf.net/projects/tcllib + +winico http://tktable.sourceforge.net + + + +===< not determined to supprt or not >======================================== + +GraphViz http://www.graphviz.org/ + +BLT http://sourceforge.net/projects/blt + +Tix http://tixlibrary.sourceforge.net/ + +Tkgeomap http://tkgeomap.sourceforge.net/index.html + +XBit http://www.geocities.com/~chengye/ + +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/ + +vfwtcl http://sourceforge.net/projects/avicaptcl + +QuickTimeTcl http://hem.fyristorg.com/matben/qt/ + +ANIGIF http://cardtable.sourceforge.net/tcltk/ + +IMG_ROTATE http://cardtable.sourceforge.net/tcltk/ + +TclVfs http://sourceforge.net/projects/tclvfs/ + + + +===< may not support (already exist, out of Ruby/Tk scope, and so on) >======= + +TkCon http://sf.net/projects/tkcon + +Expect http://sf.net/projects/expect + +TclXML http://sf.net/projects/tclxml + +TclXSLT http://sf.net/projects/tclxml + +TclDOM http://sf.net/projects/tclxml + +TclSOAP http://sf.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://memchan.sourceforge.net/ + + + +===< tool (may not supprt) >================================================== + +tbcload/tclcompiler http://www.tcl.tk/software/tclpro/ + + + +(End of List)
\ No newline at end of file diff --git a/ext/tk/lib/tkextlib/pkg_checker.rb b/ext/tk/lib/tkextlib/pkg_checker.rb new file mode 100755 index 0000000000..813273e65b --- /dev/null +++ b/ext/tk/lib/tkextlib/pkg_checker.rb @@ -0,0 +1,129 @@ +#!/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__) + +if ARGV[0] + dir = File.expand_path(ARGV[0]) +else + dir = File.dirname(File.expand_path(__FILE__)) +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}\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 + } + + pkg_list +end + +def check_pkg(file) + 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} + + end + rescue + error_list << [name, type] + 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) + 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) + 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 + # read 'setup.rb' as if the library has standard structure + require File.join(subdir, 'setup.rb') + rescue LoadError + # ignore error + end + + print "\n" + + suc, err = check_pkg(f) + 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) if File.directory?(subdir) +} diff --git a/ext/tk/lib/tkextlib/setup.rb b/ext/tk/lib/tkextlib/setup.rb new file mode 100644 index 0000000000..12867e8f9c --- /dev/null +++ b/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/ext/tk/lib/tkextlib/tcllib.rb b/ext/tk/lib/tkextlib/tcllib.rb new file mode 100644 index 0000000000..56f21556ae --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib.rb @@ -0,0 +1,57 @@ +# +# tcllib extension support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# library directory +dir = File.expand_path(__FILE__).sub(/#{File.extname(__FILE__)}$/, '') + +# call setup script +require File.join(dir, 'setup.rb') + +# package:: autoscroll +#require 'tkextlib/tcllib/autoscroll' +require File.join(dir, 'autoscroll') + +# package:: cursor +#require 'tkextlib/tcllib/cursor' +require File.join(dir, 'cursor') + +# package:: style +#require 'tkextlib/tcllib/style' +require File.join(dir, 'style') + + +# autoload +module Tk + module Tcllib + dir = File.expand_path(__FILE__).sub(/#{File.extname(__FILE__)}$/, '') + + # package:: ctext + #autoload :CText, 'tkextlib/tcllib/ctext' + autoload :CText, File.join(dir, 'ctext') + + # package:: datefield + #autoload :Datefield, 'tkextlib/tcllib/datefield' + #autoload :DateField, 'tkextlib/tcllib/datefield' + autoload :Datefield, File.join(dir, 'datefield') + autoload :DateField, File.join(dir, 'datefield') + + # package:: ipentry + #autoload :IP_Entry, 'tkextlib/tcllib/ip_entry' + autoload :IP_Entry, File.join(dir, 'ip_entry') + + # package:: Plotchart + #autoload :Plotchart, 'tkextlib/tcllib/plotchart' + autoload :Plotchart, File.join(dir, 'plotchart') + + # package:: tkpiechart + #autoload :Tkpiechart, 'tkextlib/tcllib/tkpiechart' + autoload :Tkpiechart, File.join(dir, 'tkpiechart') + end +end diff --git a/ext/tk/lib/tkextlib/tcllib/README b/ext/tk/lib/tkextlib/tcllib/README new file mode 100644 index 0000000000..953239befa --- /dev/null +++ b/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/ext/tk/lib/tkextlib/tcllib/autoscroll.rb b/ext/tk/lib/tkextlib/tcllib/autoscroll.rb new file mode 100644 index 0000000000..9c161d7ec9 --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/autoscroll.rb @@ -0,0 +1,100 @@ +# +# 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' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('autoscroll', '1.0') +TkPackage.require('autoscroll') + +module Tk + module Scrollable + def autoscroll(mode = nil) + case mode + when :x, 'x' + if @xscrollbar + tk_send_without_enc('::autoscroll::autoscroll', @xscrollbar) + end + when :y, 'y' + if @yscrollbar + tk_send_without_enc('::autoscroll::autoscroll', @yscrollbar) + end + when nil, :both, 'both' + if @xscrollbar + tk_send_without_enc('::autoscroll::autoscroll', @xscrollbar) + end + if @yscrollbar + tk_send_without_enc('::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_send_without_enc('::autoscroll::unautoscroll', @xscrollbar) + end + when :y, 'y' + if @yscrollbar + tk_send_without_enc('::autoscroll::unautoscroll', @yscrollbar) + end + when nil, :both, 'both' + if @xscrollbar + tk_send_without_enc('::autoscroll::unautoscroll', @xscrollbar) + end + if @yscrollbar + tk_send_without_enc('::autoscroll::unautoscroll', @yscrollbar) + end + else + fail ArgumentError, "'x', 'y' or 'both' (String or Symbol) is expected" + end + self + end + end +end + +class TkScrollbar + def autoscroll + # Arranges for the already existing scrollbar to be mapped + # and unmapped as needed. + tk_send_without_enc('::autoscroll::autoscroll', @path) + self + end + def unautoscroll + # Returns the scrollbar to its original static state. + tk_send_without_enc('::autoscroll::unautoscroll', @path) + self + end +end diff --git a/ext/tk/lib/tkextlib/tcllib/ctext.rb b/ext/tk/lib/tkextlib/tcllib/ctext.rb new file mode 100644 index 0000000000..6fa3e2edda --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/ctext.rb @@ -0,0 +1,141 @@ +# +# 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' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('ctext', '3.1') +TkPackage.require('ctext') + +module Tk + module Tcllib + class CText < TkText + 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('ctext', @path, *hash_kv(keys, true)) + else + tk_call_without_enc('ctext', @path) + end + end + private :create_self + + 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/ext/tk/lib/tkextlib/tcllib/cursor.rb b/ext/tk/lib/tkextlib/tcllib/cursor.rb new file mode 100644 index 0000000000..cf4f247209 --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/cursor.rb @@ -0,0 +1,41 @@ +# +# tkextlib/tcllib/cursor.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Procedures to handle CURSOR data +# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('cursor', '0.1') +TkPackage.require('cursor') + +module Tk + 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) + end +end + +class TkWindow + def cursor_propagate(cursor) + # Sets the cursor for self and all its descendants to cursor. + tk_send_without_enc('::cursor::propagate', @path, 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_send_without_enc('::cursor::restore', @path, cursor) + end +end diff --git a/ext/tk/lib/tkextlib/tcllib/datefield.rb b/ext/tk/lib/tkextlib/tcllib/datefield.rb new file mode 100644 index 0000000000..6d3ba4693f --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/datefield.rb @@ -0,0 +1,50 @@ +# +# 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' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('datefield', '0.1') +TkPackage.require('datefield') + +module Tk + module Tcllib + class Datefield < TkEntry + 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('::datefield::datefield', @path, + *hash_kv(keys, true)) + else + tk_call_without_enc('::datefield::datefield', @path) + end + end + private :create_self +end diff --git a/ext/tk/lib/tkextlib/tcllib/ip_entry.rb b/ext/tk/lib/tkextlib/tcllib/ip_entry.rb new file mode 100644 index 0000000000..aed47da63a --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/ip_entry.rb @@ -0,0 +1,53 @@ +# +# 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 'tk/entry' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('ipentry', '0.1') +TkPackage.require('ipentry') + +module Tk + module Tcllib + class IP_Entry < TkEntry + end + 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('::ipentry::ipentry', @path, *hash_kv(keys, true)) + else + tk_call_without_enc('::ipentry::ipentry', @path) + end + end + private :create_self + + def complete? + bool(tk_send_without_enc('complete')) + end + + def insert(*ip) + tk_send_without_enc('insert', array2tk_list(ip.flatten)) + end +end diff --git a/ext/tk/lib/tkextlib/tcllib/plotchart.rb b/ext/tk/lib/tkextlib/tcllib/plotchart.rb new file mode 100644 index 0000000000..108507b05b --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/plotchart.rb @@ -0,0 +1,666 @@ +# +# 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' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('Plotchart', '0.9') +TkPackage.require('Plotchart') + +module Tk + module Tcllib + module Plotchart + end + end +end + +module Tk::Tcllib::Plotchart + ############################ + 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.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::coordsToPixel', w.path, x, y)) + end + + def self.determine_scale(w, xmax, ymax) + tk_call_without_enc('::Plotchart::determineScale', w.path, xmax, ymax) + end + + def self.set_zoom_pan(w) + tk_call_without_enc('::Plotchart::setZoomPan', w.path) + end + + ############################ + module ChartMethod + include TkUtil + + 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_without_enc(@chart, 'xconfig', + "-#{key}", _get_eval_enc_str(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_without_enc(@chart, 'yconfig', + "-#{key}", _get_eval_enc_str(value)) + end + 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 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::coordsToPixel', @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 < TkCanvas + include ChartMethod + + TkCommandNames = ['::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?(TkCanvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[0] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[0], @path, + array2tk_list(@xaxis), array2tk_list(@yaxis)) + end + private :_create_chart + + def plot(series, x, y) + tk_call_without_enc(@chart, 'plot', _get_eval_enc_str(series), x, y) + 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_without_enc(@chart, 'dataconfig', series, + "-#{key}", _get_eval_enc_str(value)) + end + end + end + + ############################ + class Stripchart < XYPlot + TkCommandNames = ['::Plotchart::createStripchart'.freeze].freeze + end + + ############################ + class PolarPlot < TkCanvas + include ChartMethod + + TkCommandNames = ['::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?(TkCanvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[0] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[0], @path, + array2tk_list(@radius_data)) + end + private :_create_chart + + 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', series, *hash_kv(key, true)) + else + tk_call_without_enc(@chart, 'dataconfig', series, + "-#{key}", _get_eval_enc_str(value)) + end + end + end + Polarplot = PolarPlot + + ############################ + class IsometricPlot < TkCanvas + include ChartMethod + + TkCommandNames = ['::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?(TkCanvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[0] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[0], @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 < TkCanvas + include ChartMethod + + TkCommandNames = ['::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?(TkCanvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[0] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[0], @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 grid_size(nxcells, nycells) + tk_call_without_enc(@chart, 'gridsize', nxcells, nycells) + 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 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 Piechart < TkCanvas + include ChartMethod + + TkCommandNames = ['::Plotchart::createPiechart'.freeze].freeze + + def initialize(*args) # args := ([parent] [, keys]) + if args[0].kind_of?(TkCanvas) + parent = args.shift + @path = parent.path + else + super(*args) # create canvas widget + end + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[0] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + private :_create_chart + + def plot(*dat) # argument is a list of [label, value] + tk_call_without_enc(@chart, 'plot', dat.flatten) + self + end + end + + ############################ + class Barchart < TkCanvas + include ChartMethod + + TkCommandNames = ['::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?(TkCanvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[0] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[0], @path, + array2tk_list(@xlabels), array2tk_list(@ylabels), + @series_size) + end + private :_create_chart + + def plot(series, dat, col=None) + tk_call_without_enc(@chart, 'plot', series, dat, col) + self + end + + def colours(*cols) + # set the colours to be used + tk_call_without_enc(@chart, 'colours', *cols) + self + end + alias colour colours + alias colors colours + alias color colours + end + + ############################ + class HorizontalBarchart < Barchart + TkCommandNames = ['::Plotchart::createHorizontalBarchart'.freeze].freeze + end + + ############################ + class Timechart < TkCanvas + include ChartMethod + + TkCommandNames = ['::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?(Array) + @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?(TkCanvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[0] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[0], @path, + @time_begin, @time_end, @items) + end + private :_create_chart + + def period(txt, time_begin, time_end, col=None) + tk_call_without_enc(@chart, 'period', txt, time_begin, time_end, col) + self + end + + def milestone(txt, time, col=None) + tk_call_without_enc(@chart, 'milestone', txt, time, col) + self + end + + def vertline(txt, time) + tk_call_without_enc(@chart, 'vertline', txt, time) + self + end + end + + ############################ + class PlotSeries < TkObject + SeriesID_TBL = TkCore::INTERP.create_table + Series_ID = ['series'.freeze, '00000'.taint].freeze + TkCore::INTERP.init_ip_env{ SeriesID_TBL.clear } + + def self.id2obj(chart, id) + path = chart.path + return id unless SeriesID_TBL[path] + SeriesID_TBL[path][id]? SeriesID_TBL[path][id]: id + end + + def initialize(chart, keys=nil) + @parent = @chart_obj = chart + @ppath = @chart_obj.path + @path = @series = @id = Series_ID.join(TkCore::INTERP._ip_id_) + SeriesID_TBL[@id] = self + SeriesID_TBL[@ppath] = {} unless SeriesID_TBL[@ppath] + SeriesID_TBL[@ppath][@id] = self + Series_ID[1].succ! + 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/ext/tk/lib/tkextlib/tcllib/setup.rb b/ext/tk/lib/tkextlib/tcllib/setup.rb new file mode 100644 index 0000000000..ce0f0bd4d4 --- /dev/null +++ b/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/ext/tk/lib/tkextlib/tcllib/style.rb b/ext/tk/lib/tkextlib/tcllib/style.rb new file mode 100644 index 0000000000..e441cd83b0 --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/style.rb @@ -0,0 +1,30 @@ +# +# 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' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('style', '0.1') +TkPackage.require('style') + +module Tk + module Style + 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/ext/tk/lib/tkextlib/tcllib/tkpiechart.rb b/ext/tk/lib/tkextlib/tcllib/tkpiechart.rb new file mode 100644 index 0000000000..1ef49ef4f4 --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/tkpiechart.rb @@ -0,0 +1,284 @@ +# +# 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' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('tkpiechart', '6.6') +TkPackage.require('tkpiechart') + +module Tk + module Tcllib + module Tkpiechart + end + end +end + +module Tk::Tcllib::Tkpiechart + 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 + 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[@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[@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[@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/ext/tk/lib/tkextlib/tile.rb b/ext/tk/lib/tkextlib/tile.rb new file mode 100644 index 0000000000..866cdf0644 --- /dev/null +++ b/ext/tk/lib/tkextlib/tile.rb @@ -0,0 +1,73 @@ +# +# Tile theme engin (tile widget set) support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# library directory +dir = File.expand_path(__FILE__).sub(/#{File.extname(__FILE__)}$/, '') + +# call setup script +require File.join(dir, 'setup.rb') + +# load package +# TkPackage.require('tile', '0.4') +TkPackage.require('tile') + +# autoload +module Tk + module Tile + module TileWidget + def 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 + + def state(state=nil) + if state + tk_send('state', state) + else + list(tk_send('state')) + end + end + end + + + # library directory + dir = File.expand_path(__FILE__).sub(/#{File.extname(__FILE__)}$/, '') + + #autoload :TButton, 'tkextlib/tile/tbutton' + autoload :TButton, File.join(dir, 'tbutton') + + #autoload :TCheckButton, 'tkextlib/tile/tcheckbutton' + #autoload :TCheckbutton, 'tkextlib/tile/tcheckbutton' + autoload :TCheckButton, File.join(dir, 'tcheckbutton') + autoload :TCheckbutton, File.join(dir, 'tcheckbutton') + + #autoload :TLabel, 'tkextlib/tile/tlabel' + autoload :TLabel, File.join(dir, 'tlabel') + + #autoload :TMenubutton, 'tkextlib/tile/tmenubutton' + autoload :TMenubutton, File.join(dir, 'tmenubutton') + + #autoload :TNotebook, 'tkextlib/tile/tnotebook' + autoload :TNotebook, File.join(dir, 'tnotebook') + + #autoload :TRadioButton, 'tkextlib/tile/tradiobutton' + #autoload :TRadiobutton, 'tkextlib/tile/tradiobutton' + autoload :TRadioButton, File.join(dir, 'tradiobutton') + autoload :TRadiobutton, File.join(dir, 'tradiobutton') + + #autoload :Style, 'tkextlib/tile/style' + autoload :Style, File.join(dir, 'style') + end +end diff --git a/ext/tk/lib/tkextlib/tile/setup.rb b/ext/tk/lib/tkextlib/tile/setup.rb new file mode 100644 index 0000000000..ce0f0bd4d4 --- /dev/null +++ b/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/ext/tk/lib/tkextlib/tile/style.rb b/ext/tk/lib/tkextlib/tile/style.rb new file mode 100644 index 0000000000..be4b45ab73 --- /dev/null +++ b/ext/tk/lib/tkextlib/tile/style.rb @@ -0,0 +1,67 @@ +# +# style commands +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script -- <libdir>/tkextlib/tile.rb +require(File.dirname(File.expand_path(__FILE__)) + '.rb') + +module Tk::Tile::Style +end + +class << Tk::Tile::Style + def default(style, keys=nil) + if keys && keys != None + tk_call('style', 'default', style, *hash_kv(keys)) + else + tk_call('style', 'default', style) + end + end + + def map(style, keys=nil) + if keys && keys != None + tk_call('style', 'map', style, *hash_kv(keys)) + else + tk_call('style', 'map', style) + end + end + + def layout(style, spec=nil) + if spec + tk_call('style', 'layout', style, spec) + else + tk_call('style', 'layout', style) + end + end + + def element_create(name, type, *args) + tk_call('style', 'element', 'create', name, type, *args) + end + + def element_names() + list(tk_call('style', 'element', 'names')) + end + + def theme_create(name, keys=nil) + if keys && keys != None + tk_call('style', 'theme', 'create', name, type, *hash_kv(keys)) + else + tk_call('style', 'theme', 'create', name, type) + end + end + + def theme_settings(name, cmd=nil, &b) + end + + def theme_names() + list(tk_call('style', 'theme', 'names')) + end + + def theme_use(name) + tk_call('style', 'use', name) + end +end diff --git a/ext/tk/lib/tkextlib/tile/tbutton.rb b/ext/tk/lib/tkextlib/tile/tbutton.rb new file mode 100644 index 0000000000..c73b7904ed --- /dev/null +++ b/ext/tk/lib/tkextlib/tile/tbutton.rb @@ -0,0 +1,28 @@ +# +# tbutton widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script -- <libdir>/tkextlib/tile.rb +require(File.dirname(File.expand_path(__FILE__)) + '.rb') + +class Tk::Tile::TButton < TkButton + include Tk::Tile::TileWidget + + TkCommandNames = ['tbutton'.freeze].freeze + WidgetClassName = 'TButton'.freeze + WidgetClassNames[WidgetClassName] = self + + def create_self(keys) + if keys and keys != None + tk_call_without_enc('tbutton', @path, *hash_kv(keys, true)) + else + tk_call_without_enc('tbutton', @path) + end + end + private :create_self +end diff --git a/ext/tk/lib/tkextlib/tile/tcheckbutton.rb b/ext/tk/lib/tkextlib/tile/tcheckbutton.rb new file mode 100644 index 0000000000..f5ab008820 --- /dev/null +++ b/ext/tk/lib/tkextlib/tile/tcheckbutton.rb @@ -0,0 +1,33 @@ +# +# tcheckbutton widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script -- <libdir>/tkextlib/tile.rb +require(File.dirname(File.expand_path(__FILE__)) + '.rb') + +class Tk::Tile::TCheckButton < TkCheckButton + include Tk::Tile::TileWidget + + TkCommandNames = ['tcheckbutton'.freeze].freeze + WidgetClassName = 'TCheckbutton'.freeze + WidgetClassNames[WidgetClassName] = self + + def create_self(keys) + if keys and keys != None + tk_call_without_enc('tcheckbutton', @path, *hash_kv(keys, true)) + else + tk_call_without_enc('tcheckbutton', @path) + end + end + private :create_self +end +module Tk + module Tile + TCheckbutton = TCheckButton + end +end diff --git a/ext/tk/lib/tkextlib/tile/tlabel.rb b/ext/tk/lib/tkextlib/tile/tlabel.rb new file mode 100644 index 0000000000..1b7302cab1 --- /dev/null +++ b/ext/tk/lib/tkextlib/tile/tlabel.rb @@ -0,0 +1,28 @@ +# +# tlabel widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script -- <libdir>/tkextlib/tile.rb +require(File.dirname(File.expand_path(__FILE__)) + '.rb') + +class Tk::Tile::TLabel < TkLabel + include Tk::Tile::TileWidget + + TkCommandNames = ['tlabel'.freeze].freeze + WidgetClassName = 'TLabel'.freeze + WidgetClassNames[WidgetClassName] = self + + def create_self(keys) + if keys and keys != None + tk_call_without_enc('tlabel', @path, *hash_kv(keys, true)) + else + tk_call_without_enc('tlabel', @path) + end + end + private :create_self +end diff --git a/ext/tk/lib/tkextlib/tile/tmenubutton.rb b/ext/tk/lib/tkextlib/tile/tmenubutton.rb new file mode 100644 index 0000000000..c827629c7d --- /dev/null +++ b/ext/tk/lib/tkextlib/tile/tmenubutton.rb @@ -0,0 +1,28 @@ +# +# tmenubutton widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script -- <libdir>/tkextlib/tile.rb +require(File.dirname(File.expand_path(__FILE__)) + '.rb') + +class Tk::Tile::TMenubutton < TkMenubutton + include Tk::Tile::TileWidget + + TkCommandNames = ['tmenubutton'.freeze].freeze + WidgetClassName = 'TMenubutton'.freeze + WidgetClassNames[WidgetClassName] = self + + def create_self(keys) + if keys and keys != None + tk_call_without_enc('tmenubutton', @path, *hash_kv(keys, true)) + else + tk_call_without_enc('tmenubutton', @path) + end + end + private :create_self +end diff --git a/ext/tk/lib/tkextlib/tile/tnotebook.rb b/ext/tk/lib/tkextlib/tile/tnotebook.rb new file mode 100644 index 0000000000..40242b5235 --- /dev/null +++ b/ext/tk/lib/tkextlib/tile/tnotebook.rb @@ -0,0 +1,90 @@ +# +# tnotebook widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script -- <libdir>/tkextlib/tile.rb +require(File.dirname(File.expand_path(__FILE__)) + '.rb') + +class Tk::Tile::TNotebook < TkWindow + ################################ + 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 __item_listval_optkeys + [] + end + private :__item_listval_optkeys + + def __item_methodcall_optkeys # { key=>method, ... } + {} + end + private :__item_listval_optkeys + + alias tabcget itemcget + alias tabconfigure itemconfigure + alias tabconfiginfo itemconfiginfo + alias current_tabconfiginfo current_itemconfiginfo + ################################ + + include Tk::Tile::TileWidget + + TkCommandNames = ['tnotebook'.freeze].freeze + WidgetClassName = 'TNotebook'.freeze + WidgetClassNames[WidgetClassName] = self + + def create_self(keys) + if keys and keys != None + tk_call_without_enc('tnotebook', @path, *hash_kv(keys, true)) + else + tk_call_without_enc('tnotebook', @path) + end + end + private :create_self + + def enable_traversal() + tk_call_without_end('tile::enableNotebookTraversal', @path) + self + end + + def add(child, keys=nil) + if keys && keys != None + tk_send_without_enc('add', _epath(child), *hash_kv(keys)) + else + tk_send_without_enc('add', _epath(child)) + end + self + end + + def forget(idx) + tk_send('forget', idx) + self + end + + def index(idx) + number(tk_send('index', idx)) + end + + def select(idx) + tk_send('select', idx) + self + end + + def tabs + list(tk_send('tabs')) + end +end diff --git a/ext/tk/lib/tkextlib/tile/tradiobutton.rb b/ext/tk/lib/tkextlib/tile/tradiobutton.rb new file mode 100644 index 0000000000..2587a74cf3 --- /dev/null +++ b/ext/tk/lib/tkextlib/tile/tradiobutton.rb @@ -0,0 +1,33 @@ +# +# tradiobutton widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script -- <libdir>/tkextlib/tile.rb +require(File.dirname(File.expand_path(__FILE__)) + '.rb') + +class Tk::Tile::TRadioButton < TkRadioButton + include Tk::Tile::TileWidget + + TkCommandNames = ['tradiobutton'.freeze].freeze + WidgetClassName = 'TRadiobutton'.freeze + WidgetClassNames[WidgetClassName] = self + + def create_self(keys) + if keys and keys != None + tk_call_without_enc('tradiobutton', @path, *hash_kv(keys, true)) + else + tk_call_without_enc('tradiobutton', @path) + end + end + private :create_self +end +module Tk + module Tile + TRadiobutton = TRadioButton + end +end diff --git a/ext/tk/lib/tkextlib/tkDND.rb b/ext/tk/lib/tkextlib/tkDND.rb new file mode 100644 index 0000000000..ba5b23b538 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkDND.rb @@ -0,0 +1,25 @@ +# +# 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' + +# library directory +dir = File.expand_path(__FILE__).sub(/#{File.extname(__FILE__)}$/, '') + +# call setup script +require File.join(dir, 'setup.rb') + +module Tk + module TkDND + dir = File.expand_path(__FILE__).sub(/#{File.extname(__FILE__)}$/, '') + + #autoload :DND 'tkextlib/tkDND/tkdnd' + #autoload :Shape 'tkextlib/tkDND/shape' + autoload :DND File.join(dir, 'tkdnd') + autoload :Shape File.join(dir, 'shape') + end +end diff --git a/ext/tk/lib/tkextlib/tkDND/setup.rb b/ext/tk/lib/tkextlib/tkDND/setup.rb new file mode 100644 index 0000000000..ce0f0bd4d4 --- /dev/null +++ b/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/ext/tk/lib/tkextlib/tkDND/shape.rb b/ext/tk/lib/tkextlib/tkDND/shape.rb new file mode 100644 index 0000000000..3e4a94f526 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkDND/shape.rb @@ -0,0 +1,96 @@ +# +# 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 File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('shape', '0.3') +TkPackage.require('shape') + +module Tk + module TkDND + module Shape + def self.version + tk_call('shape', '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/ext/tk/lib/tkextlib/tkDND/tkdnd.rb b/ext/tk/lib/tkextlib/tkDND/tkdnd.rb new file mode 100644 index 0000000000..036d1998bd --- /dev/null +++ b/ext/tk/lib/tkextlib/tkDND/tkdnd.rb @@ -0,0 +1,108 @@ +# +# 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 File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +TkPackage.require('tkdnd') + +module Tk + module TkDND + 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 + ] + + # setup tables + _setup_subst_table(KEY_TBL, PROC_TBL); + end + + module DND + 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_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_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/ext/tk/lib/tkextlib/tkHTML.rb b/ext/tk/lib/tkextlib/tkHTML.rb new file mode 100644 index 0000000000..f32aed99f1 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkHTML.rb @@ -0,0 +1,16 @@ +# +# TkHtml support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# library directory +dir = File.expand_path(__FILE__).sub(/#{File.extname(__FILE__)}$/, '') + +# call setup script +require File.join(dir, 'setup.rb') + +# load library +require File.join(dir, 'htmlwidget') diff --git a/ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb b/ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb new file mode 100644 index 0000000000..5c0657025a --- /dev/null +++ b/ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb @@ -0,0 +1,427 @@ +# +# 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 File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('Tkhtml', '2.0') +TkPackage.require('Tkhtml') + +module Tk + class HTML_Widget < TkWindow + class ClippingWindow < TkWindow + end + end +end + +class Tk::HTML_Widget::ClippingWindow + extend TkUtil + + WidgetClassName = 'HtmlClip'.freeze + WidgetClassNames[WidgetClassName] = self + + HtmlClip_TBL = TkCore::INTERP.create_table + TkCore::INTERP.init_ip_env{ HtmlClip_TBL.clear } + + def self.new(parent, keys={}) + if parent.kind_of?(Hash) + keys = _symbolkey2str(parent) + parent = keys.delete('parent') + end + + if parent.kind_of?(String) + ppath = parent.path + elsif parent + ppath = parent + else + ppath = '' + end + return HtmlClip_TBL[ppath] if HtmlClip_TBL[ppath] + + widgetname = keys.delete('widgetname') + if widgetname =~ /^(.*)\.[^.]+$/ + ppath2 = $1 + if ppath2[0] != ?. + ppath2 = ppath + '.' + ppath2 + end + 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[@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('html', @path, *hash_kv(keys, true)) + else + tk_call_without_enc('html', @path) + end + end + private :create_self + + ################################### + # 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/ext/tk/lib/tkextlib/tkHTML/setup.rb b/ext/tk/lib/tkextlib/tkHTML/setup.rb new file mode 100644 index 0000000000..ce0f0bd4d4 --- /dev/null +++ b/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/ext/tk/lib/tkextlib/tkimg.rb b/ext/tk/lib/tkextlib/tkimg.rb new file mode 100644 index 0000000000..06184589b4 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkimg.rb @@ -0,0 +1,23 @@ +# +# TkImg extension support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# library directory +dir = File.expand_path(__FILE__).sub(/#{File.extname(__FILE__)}$/, '') + +# call setup script +require File.join(dir, 'setup.rb') + +# load all image format handlers +#TkPackage.require('Img', '1.3') +TkPackage.require('Img') + +# autoload +#autoload :TkPixmapImage, 'tkextlib/tkimg/pixmap' +autoload :TkPixmapImage, File.join(dir, 'pixmap') diff --git a/ext/tk/lib/tkextlib/tkimg/README b/ext/tk/lib/tkextlib/tkimg/README new file mode 100644 index 0000000000..65d36365d0 --- /dev/null +++ b/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/ext/tk/lib/tkextlib/tkimg/bmp.rb b/ext/tk/lib/tkextlib/tkimg/bmp.rb new file mode 100644 index 0000000000..5bef0c7168 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkimg/bmp.rb @@ -0,0 +1,14 @@ +# +# 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 File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +#TkPackage.require('img::bmp', '1.3') +TkPackage.require('img::bmp') diff --git a/ext/tk/lib/tkextlib/tkimg/gif.rb b/ext/tk/lib/tkextlib/tkimg/gif.rb new file mode 100644 index 0000000000..65c3b88a50 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkimg/gif.rb @@ -0,0 +1,14 @@ +# +# 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 File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('img::gif', '1.3') +TkPackage.require('img::gif') diff --git a/ext/tk/lib/tkextlib/tkimg/ico.rb b/ext/tk/lib/tkextlib/tkimg/ico.rb new file mode 100644 index 0000000000..43646ec8da --- /dev/null +++ b/ext/tk/lib/tkextlib/tkimg/ico.rb @@ -0,0 +1,14 @@ +# +# 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 File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('img::ico', '1.3') +TkPackage.require('img::ico') diff --git a/ext/tk/lib/tkextlib/tkimg/jpeg.rb b/ext/tk/lib/tkextlib/tkimg/jpeg.rb new file mode 100644 index 0000000000..7b4df8c050 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkimg/jpeg.rb @@ -0,0 +1,14 @@ +# +# 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 File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('img::jpeg', '1.3') +TkPackage.require('img::jpeg') diff --git a/ext/tk/lib/tkextlib/tkimg/pcx.rb b/ext/tk/lib/tkextlib/tkimg/pcx.rb new file mode 100644 index 0000000000..4486ba2449 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkimg/pcx.rb @@ -0,0 +1,14 @@ +# +# 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 File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('img::pcx', '1.3') +TkPackage.require('img::pcx') diff --git a/ext/tk/lib/tkextlib/tkimg/pixmap.rb b/ext/tk/lib/tkextlib/tkimg/pixmap.rb new file mode 100644 index 0000000000..0c18c71408 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkimg/pixmap.rb @@ -0,0 +1,21 @@ +# +# 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 File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('img::pixmap', '1.3') +TkPackage.require('img::pixmap') + +class TkPixmapImage<TkImage + def initialize(*args) + @type = 'pixmap' + super + end +end diff --git a/ext/tk/lib/tkextlib/tkimg/png.rb b/ext/tk/lib/tkextlib/tkimg/png.rb new file mode 100644 index 0000000000..275035f47e --- /dev/null +++ b/ext/tk/lib/tkextlib/tkimg/png.rb @@ -0,0 +1,14 @@ +# +# 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 File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('img::png', '1.3') +TkPackage.require('img::png') diff --git a/ext/tk/lib/tkextlib/tkimg/ppm.rb b/ext/tk/lib/tkextlib/tkimg/ppm.rb new file mode 100644 index 0000000000..730978b281 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkimg/ppm.rb @@ -0,0 +1,14 @@ +# +# 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 File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('img::ppm', '1.3') +TkPackage.require('img::ppm') diff --git a/ext/tk/lib/tkextlib/tkimg/ps.rb b/ext/tk/lib/tkextlib/tkimg/ps.rb new file mode 100644 index 0000000000..edfb8dd783 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkimg/ps.rb @@ -0,0 +1,14 @@ +# +# 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 File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('img::ps', '1.3') +TkPackage.require('img::ps') diff --git a/ext/tk/lib/tkextlib/tkimg/setup.rb b/ext/tk/lib/tkextlib/tkimg/setup.rb new file mode 100644 index 0000000000..ce0f0bd4d4 --- /dev/null +++ b/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/ext/tk/lib/tkextlib/tkimg/sgi.rb b/ext/tk/lib/tkextlib/tkimg/sgi.rb new file mode 100644 index 0000000000..9dcfa614b0 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkimg/sgi.rb @@ -0,0 +1,14 @@ +# +# 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 File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('img::sgi', '1.3') +TkPackage.require('img::sgi') diff --git a/ext/tk/lib/tkextlib/tkimg/sun.rb b/ext/tk/lib/tkextlib/tkimg/sun.rb new file mode 100644 index 0000000000..4ada9c7ff1 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkimg/sun.rb @@ -0,0 +1,14 @@ +# +# 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 File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('img::sun', '1.3') +TkPackage.require('img::sun') diff --git a/ext/tk/lib/tkextlib/tkimg/tga.rb b/ext/tk/lib/tkextlib/tkimg/tga.rb new file mode 100644 index 0000000000..221ebe5db1 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkimg/tga.rb @@ -0,0 +1,14 @@ +# +# 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 File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('img::tga', '1.3') +TkPackage.require('img::tga') diff --git a/ext/tk/lib/tkextlib/tkimg/tiff.rb b/ext/tk/lib/tkextlib/tkimg/tiff.rb new file mode 100644 index 0000000000..1c7e940843 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkimg/tiff.rb @@ -0,0 +1,14 @@ +# +# 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 File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('img::tiff', '1.3') +TkPackage.require('img::tiff') diff --git a/ext/tk/lib/tkextlib/tkimg/window.rb b/ext/tk/lib/tkextlib/tkimg/window.rb new file mode 100644 index 0000000000..056aa8f3cf --- /dev/null +++ b/ext/tk/lib/tkextlib/tkimg/window.rb @@ -0,0 +1,14 @@ +# +# 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 File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('img::window', '1.3') +TkPackage.require('img::window') diff --git a/ext/tk/lib/tkextlib/tkimg/xbm.rb b/ext/tk/lib/tkextlib/tkimg/xbm.rb new file mode 100644 index 0000000000..80010c77de --- /dev/null +++ b/ext/tk/lib/tkextlib/tkimg/xbm.rb @@ -0,0 +1,14 @@ +# +# 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 File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('img::xbm', '1.3') +TkPackage.require('img::xbm') diff --git a/ext/tk/lib/tkextlib/tkimg/xpm.rb b/ext/tk/lib/tkextlib/tkimg/xpm.rb new file mode 100644 index 0000000000..04d56287ef --- /dev/null +++ b/ext/tk/lib/tkextlib/tkimg/xpm.rb @@ -0,0 +1,14 @@ +# +# 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 File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('img::xpm', '1.3') +TkPackage.require('img::xpm') diff --git a/ext/tk/lib/tkextlib/tktrans.rb b/ext/tk/lib/tkextlib/tktrans.rb new file mode 100644 index 0000000000..93bb338a9b --- /dev/null +++ b/ext/tk/lib/tkextlib/tktrans.rb @@ -0,0 +1,17 @@ +# +# 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' + +# library directory +dir = File.expand_path(__FILE__).sub(/#{File.extname(__FILE__)}$/, '') + +# call setup script +require File.join(dir, 'setup.rb') + +# load library +require File.join(dir, 'tktrans') diff --git a/ext/tk/lib/tkextlib/tktrans/setup.rb b/ext/tk/lib/tkextlib/tktrans/setup.rb new file mode 100644 index 0000000000..ce0f0bd4d4 --- /dev/null +++ b/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/ext/tk/lib/tkextlib/tktrans/tktrans.rb b/ext/tk/lib/tkextlib/tktrans/tktrans.rb new file mode 100644 index 0000000000..fa5d7a2eae --- /dev/null +++ b/ext/tk/lib/tkextlib/tktrans/tktrans.rb @@ -0,0 +1,53 @@ +# +# 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 File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +TkPackage.require('tktrans') rescue Tk.load_tcllibrary('tktrans') + +class TkWindow + begin + TkTrans_VERSION = TkPackage.require('tktrans') + rescue + TkTrans_VERSION = nil + end + + 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 TkRoot + 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 TkToplevel + 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/ext/tk/lib/tkextlib/treectrl.rb b/ext/tk/lib/tkextlib/treectrl.rb new file mode 100644 index 0000000000..fb03283a8d --- /dev/null +++ b/ext/tk/lib/tkextlib/treectrl.rb @@ -0,0 +1,16 @@ +# +# TkTreeCtrl support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# library directory +dir = File.expand_path(__FILE__).sub(/#{File.extname(__FILE__)}$/, '') + +# call setup script +require File.join(dir, 'setup.rb') + +# load library +require File.join(dir, 'tktreectrl') diff --git a/ext/tk/lib/tkextlib/treectrl/setup.rb b/ext/tk/lib/tkextlib/treectrl/setup.rb new file mode 100644 index 0000000000..ce0f0bd4d4 --- /dev/null +++ b/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/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb b/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb new file mode 100644 index 0000000000..fb74b72c3b --- /dev/null +++ b/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb @@ -0,0 +1,887 @@ +# +# tkextlib/treectrl/tktreectrl.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' + +# call setup script +require File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('treectrl', '1.0') +#TkPackage.require('treectrl') + +module Tk + class TreeCtrl_Widget < TkWindow + #VERSION = TkPackage.require('treectrl', '1.0') + VERSION = TkPackage.require('treectrl') + + class NotifyEvent < TkUtil::CallbackSubst + end + + module ConfigMethod + end + end +end + +############################################## + +class Tk::TreeCtrl_Widget::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, ?b, :lower_bound ], + [ ?p, ?n, :active_id ], + [ ?S, ?l, :sel_items ], + [ ?T, ?w, :widget ], + [ ?U, ?b, :upper_bound ], + [ ?W, ?o, :object ], + 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) ], + + [ ?b, proc{|val| list(val)} ], + + [ ?e, proc{|val| + case val + when /^<<[^<>]+>>$/ + TkVirtualEvent.getobj(val[1..-2]) + when /^<[^<>]+>$/ + val[1..-2] + else + val + end + } + ], + + [ ?o, proc{|val| tk_tcl2ruby(val)} ], + + nil + ] + + # setup tables to be used by scan_args, _get_subst_key, _get_all_subst_keys + # + # _get_subst_key() and _get_all_subst_keys() generates key-string + # which describe how to convert callback arguments to ruby objects. + # When binding parameters are given, use _get_subst_key(). + # But when no parameters are given, use _get_all_subst_keys() to + # create a Event class object as a callback parameter. + # + # scan_args() is used when doing callback. It convert arguments + # ( which are Tcl strings ) to ruby objects based on the key string + # that is generated by _get_subst_key() or _get_all_subst_keys(). + # + _setup_subst_table(KEY_TBL, PROC_TBL); +end + +############################################## + +module Tk::TreeCtrl_Widget::ConfigMethod + include TkItemConfigMethod + + def treectrl_tagid(key, obj) + if key.kind_of?(Array) + key = key.join(' ') + else + key = key.to_s + end + + case key + when 'column' + obj + + when 'dragimage' + obj + + when 'element' + obj + + when 'item element' + obj + + when 'marquee' + obj + + when 'notify' + obj + + when 'style' + obj + + else + obj + end + end + + def tagid(mixed_id) + if mixed_id.kind_of?(Array) + [mixed_id[0], treectrl_tagid(*mixed_id)] + else + tagid(mixed_id.split(':')) + end + fail ArgumentError, "unknown id format" + end + + def __item_cget_cmd(mixed_id) + 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[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_listval_optkeys(id) + [] + end + private :__item_listval_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(tagOrId, option) + itemcget(['column', tagOrId], option) + end + def column_configure(tagOrId, slot, value=None) + itemconfigure(['column', tagOrId], slot, value) + end + def column_configinfo(tagOrId, slot=nil) + itemconfigure(['column', tagOrId], slot) + end + def current_column_configinfo(tagOrId, slot=nil) + itemconfigure(['column', tagOrId], slot) + end + + def dragimage_cget(tagOrId, option) + itemcget(['dragimage', tagOrId], option) + end + def dragimage_configure(tagOrId, slot, value=None) + itemconfigure(['dragimage', tagOrId], slot, value) + end + def dragimage_configinfo(tagOrId, slot=nil) + itemconfigure(['dragimage', tagOrId], slot) + end + def current_dragimage_configinfo(tagOrId, slot=nil) + itemconfigure(['dragimage', tagOrId], slot) + end + + def element_cget(tagOrId, option) + itemcget(['element', tagOrId], option) + end + def element_configure(tagOrId, slot, value=None) + itemconfigure(['element', tagOrId], slot, value) + end + def element_configinfo(tagOrId, slot=nil) + itemconfigure(['element', tagOrId], slot) + end + def current_element_configinfo(tagOrId, slot=nil) + itemconfigure(['element', tagOrId], slot) + end + + def item_element_cget(tagOrId, option) + itemcget([['item', 'element'], tagOrId], option) + end + def item_element_configure(tagOrId, slot, value=None) + itemconfigure([['item', 'element'], tagOrId], slot, value) + end + def item_element_configinfo(tagOrId, slot=nil) + itemconfigure([['item', 'element'], tagOrId], slot) + end + def current_item_element_configinfo(tagOrId, slot=nil) + itemconfigure([['item', 'element'], tagOrId], slot) + end + + def marquee_cget(tagOrId, option) + itemcget(['marquee', tagOrId], option) + end + def marquee_configure(tagOrId, slot, value=None) + itemconfigure(['marquee', tagOrId], slot, value) + end + def marquee_configinfo(tagOrId, slot=nil) + itemconfigure(['marquee', tagOrId], slot) + end + def current_marquee_configinfo(tagOrId, slot=nil) + itemconfigure(['marquee', tagOrId], slot) + end + + def notify_cget(win, pattern, option) + itemconfigure(['notify', [win, pattern]], option) + end + def notify_configure(win, pattern, slot, value=None) + itemconfigure(['notify', [win, pattern]], slot, value) + end + def notify_configinfo(win, pattern, slot=nil) + itemconfigure(['notify', [win, pattern]], slot) + end + alias current_notify_configinfo notify_configinfo + + def style_cget(tagOrId, option) + itemcget(['style', tagOrId], option) + end + def style_configure(tagOrId, slot, value=None) + itemconfigure(['style', tagOrId], slot, value) + end + def style_configinfo(tagOrId, slot=nil) + itemconfigure(['style', tagOrId], slot) + end + def current_style_configinfo(tagOrId, slot=nil) + itemconfigure(['style', tagOrId], slot) + end + + private :itemcget, :itemconfigure + private :itemconfiginfo, :current_itemconfiginfo +end + +############################################## + +class Tk::TreeCtrl_Widget + include Tk::TreeCtrl_Widget::ConfigMethod + include Scrollable + + TkCommandNames = ['treectrl'.freeze].freeze + WidgetClassName = ''.freeze + WidgetClassNames[WidgetClassName] = self + + def create_self(keys) + if keys and keys != None + tk_call_without_enc('treectrl', @path, *hash_kv(keys, true)) + else + tk_call_without_enc('treectrl', @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('collapse', *dsc) + self + end + + def collapse_recurse(*dsc) + tk_send('collapse', '-recurse', *dsc) + self + end + + def column_bbox(idx) + list(tk_send('column', 'bbox', idx)) + end + + def column_delete(idx) + tk_send('column', 'delete', idx) + self + end + + def column_index(idx) + num_or_str(tk_send('column', 'index', idx)) + end + + def column_move(idx, to) + tk_send('column', 'move', idx, to) + self + end + + def column_needed_width(idx) + num_or_str(tk_send('column', 'neededwidth', idx)) + end + alias column_neededwidth column_needed_width + + def column_width(idx) + num_or_str(tk_send('column', 'width', idx)) + end + + def compare(item1, op, item2) + number(tk_send('compare', item1, op, item2)) + end + + def contentbox() + list(tk_send('contentbox')) + end + + def depth(item=None) + num_or_str(tk_send('depth', item)) + 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 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_send('element', 'delete', *elems) + self + end + + def element_names() + list(tk_send('element', 'names')) + end + + def element_type(elem) + tk_send('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) + list(tk_send('identify', x, y)) + end + + def index(idx) + num_or_str(tk_send('index', idx)) + end + + def item_ancestors(item) + list(tk_send('item', 'ancestors', item)) + end + + def item_bbox(item, *args) + list(tk_send('item', 'bbox', item, *args)) + end + + def item_children(item) + list(tk_send('item', 'children', item)) + end + + def item_complex(item, *args) + tk_send('item', 'complex', item, *args) + self + end + + def item_create() + num_or_str(tk_send('item', 'create')) + end + + def item_delete(first, last=None) + tk_send('item', 'delete', first, last) + self + end + + def item_dump(item) + 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_firstchild(parent, child=nil) + if child + tk_send('item', 'firstchild', parent, child) + self + else + num_or_str(tk_send('item', 'firstchild', parent)) + end + end + alias item_first_child item_firstchild + + def item_hashbutton(item, st=None) + if st == None + bool(tk_send('item', 'hashbutton')) + else + tk_send('item', 'hashbutton', st) + self + end + end + def item_hashbutton?(item) + item_hashbutton(item) + 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 + + def item_lastchild(parent, child=nil) + if child + tk_send('item', 'lastchild', parent, child) + self + else + num_or_str(tk_send('item', 'lastchild', parent)) + end + end + alias item_last_child item_lastchild + + def item_nextsibling(sibling, nxt=nil) + if nxt + tk_send('item', 'nextsibling', sibling, nxt) + self + else + num_or_str(tk_send('item', 'nextsibling', sibling)) + end + end + alias item_next_sibling item_nextsibling + + def item_numchildren() + number(tk_send('item', 'numchildren')) + end + alias item_num_children item_numchildren + alias item_children_size item_numchildren + + def item_parent(item) + num_or_str(tk_send('item', 'parent', item)) + end + + def item_prevsibling(sibling, prev=nil) + if prev + tk_send('item', 'prevsibling', sibling, prev) + self + else + num_or_str(tk_send('item', 'prevsibling', sibling)) + end + end + alias item_prev_sibling item_prevsibling + + def item_remove(item) + list(tk_send('item', 'remove', item)) + end + + def item_rnc(item) + list(tk_send('item', 'rnc', item)) + end + + def item_sort(item, *opts) + flag = false + if opts[-1].kind_of?(Hash) + opts[-1,1] = __conv_item_keyonly_opts(item, opts[-1]).to_a + end + + opts = opts.collect{|opt| + if opt.kind_of?(Array) + key = "-#{opt[0]}" + flag = true if key == '-notreally' + ["-#{opt[0]}", opt[1]] + else + key = "-#{opt}" + flag = true if key == '-notreally' + key + end + }.flatten + + ret = tk_send('item', 'sort', item, *opts) + if flag + list(ret) + else + ret + end + end + + 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', *args) + self + end + + def item_style_elements(item, colun) + list(tk_send('item', 'style', 'elements', item, column)) + 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 + tk_send('item', 'style', 'set', item, column) + else + list(tk_send('item', 'style', 'set', item)) + end + else + tk_send('item', 'style', 'set', item, *(args.flatten)) + 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, txt, *args) + self + end + 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')) + 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=nil) + _bind([@path, 'notify', 'bind', obj], event, cmd, args) + self + end + + def notify_bind_append(obj, event, cmd=Proc.new, args=nil) + _bind([@path, 'notify', 'bind', obj], event, cmd, args) + 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) + tk_send('notify', 'generate', pattern, char_map) + self + 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(event, detail=None) + tk_send('notify', 'linkage', event, detail) + 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 + + def numitems() + num_or_str(tk_send('numitems')) + end + + def orphans() + list(tk_send('orphans')) + end + + def range(first, last) + list(tk_send('range', first, last)) + 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) + tk_send('see', item) + self + end + + def selection_add(first, last=None) + tk_send('selection', 'add', first, last) + self + end + + def selection_anchor(item=None) + num_or_str(tk_send('selection', 'anchor', item)) + 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')) + 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_send('style', 'delete', *args) + self + end + + def style_elements(style, *elems) + if elems.empty? + list(tk_send('style', 'elements', style)) + else + tk_send('style', 'elements', style, elems.flatten) + self + end + end + + 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 + tk_send('style', 'layout', style, elem, "-#{keys}") + end + else + list(tk_send('style', 'layout', style, elem)) + end + end + + def style_names() + list(tk_send('style', 'names')) + end + + def toggle(*items) + tk_send('toggle', *items) + self + end + + def toggle_recurse() + tk_send('toggle', '-recurse', *items) + self + end +end diff --git a/ext/tk/lib/tkextlib/vu.rb b/ext/tk/lib/tkextlib/vu.rb new file mode 100644 index 0000000000..923b67ce4e --- /dev/null +++ b/ext/tk/lib/tkextlib/vu.rb @@ -0,0 +1,40 @@ +# +# 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' + +# library directory +dir = File.expand_path(__FILE__).sub(/#{File.extname(__FILE__)}$/, '') + +# call setup script +require File.join(dir, 'setup.rb') + +# load package +# TkPackage.require('vu', '2.1') +#TkPackage.require('vu') + +# autoload +module Tk + module Vu + # load package + # VERSION = TkPackage.require('vu', '2.1') + VERSION = TkPackage.require('vu') + + dir = File.expand_path(__FILE__).sub(/#{File.extname(__FILE__)}$/, '') + + autoload :Dial, File.join(dir, 'dial') + + autoload :Pie, File.join(dir, 'pie') + autoload :PieSlice, File.join(dir, 'pie') + autoload :NamedPieSlice, File.join(dir, 'pie') + + autoload :Spinbox, File.join(dir, 'spinbox') + + autoload :Bargraph, File.join(dir, 'bargraph') + end +end diff --git a/ext/tk/lib/tkextlib/vu/bargraph.rb b/ext/tk/lib/tkextlib/vu/bargraph.rb new file mode 100644 index 0000000000..1dbd49db28 --- /dev/null +++ b/ext/tk/lib/tkextlib/vu/bargraph.rb @@ -0,0 +1,50 @@ +# +# ::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(File.dirname(File.expand_path(__FILE__)) + '.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 __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/ext/tk/lib/tkextlib/vu/charts.rb b/ext/tk/lib/tkextlib/vu/charts.rb new file mode 100644 index 0000000000..bf2a3075bd --- /dev/null +++ b/ext/tk/lib/tkextlib/vu/charts.rb @@ -0,0 +1,47 @@ +# +# 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(File.dirname(File.expand_path(__FILE__)) + '.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_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/ext/tk/lib/tkextlib/vu/dial.rb b/ext/tk/lib/tkextlib/vu/dial.rb new file mode 100644 index 0000000000..4d5770a320 --- /dev/null +++ b/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(File.dirname(File.expand_path(__FILE__)) + '.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_split_list(tk_send_without_enc('coords')) + else + tk_send_without_enc('coords', val) + self + 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/ext/tk/lib/tkextlib/vu/pie.rb b/ext/tk/lib/tkextlib/vu/pie.rb new file mode 100644 index 0000000000..833039c9f2 --- /dev/null +++ b/ext/tk/lib/tkextlib/vu/pie.rb @@ -0,0 +1,229 @@ +# +# ::vu::pie widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +# 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(File.dirname(File.expand_path(__FILE__)) + '.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 + + ############################### + + include Tk::Vu::PieSliceConfigMethod + + def tagid(tag) + if tag.kind_of?(Tk::Vu::PieSlice) + tag.id + else + 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, '00000'.taint].freeze + TkCore::INTERP.init_ip_env{ SliceID_TBL.clear } + + def self.id2obj(pie, id) + pie_path = pie.path + return id unless SliceID_TBL[pie_path] + SliceID_TBL[pie_path][id]? SliceID_TBL[pie_path][id]: id + end + + def initialize(parent, *args) + unless parent.kind_of?(Tk::Vu::Pie) + fail ArguemntError, "expect a Tk::Vu::Pie instance for 1st argument" + end + @parent = @pie = parent + @ppath = parent.path + @path = @id = Pie_Slice_ID.join(TkCore::INTERP._ip_id_) + SliceID_TBL[@ppath] = {} unless SliceID_TBL[@ppath] + SliceID_TBL[@ppath][@id] = self + Pie_Slice_ID[1].succ! + + 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(slot) + @pie.itemcget(@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) + if SliceID_TBL[parent.path] && SliceID_TBL[parent.path][name] + return SliceID_TBL[parent.path][name] + else + super(parent, name, *args) + end + end + + def initialize(parent, name, *args) + unless parent.kind_of?(Tk::Vu::Pie) + fail ArguemntError, "expect a Tk::Vu::Pie instance for 1st argument" + end + @parent = @pie = parent + @ppath = parent.path + @path = @id = name.to_s + 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/ext/tk/lib/tkextlib/vu/setup.rb b/ext/tk/lib/tkextlib/vu/setup.rb new file mode 100644 index 0000000000..ce0f0bd4d4 --- /dev/null +++ b/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/ext/tk/lib/tkextlib/vu/spinbox.rb b/ext/tk/lib/tkextlib/vu/spinbox.rb new file mode 100644 index 0000000000..db2743613c --- /dev/null +++ b/ext/tk/lib/tkextlib/vu/spinbox.rb @@ -0,0 +1,17 @@ +# +# ::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. +# + +if (Tk::TK_MAJOR_VERSION < 8 || + (Tk::TK_MAJOR_VERSION == 8 && Tk::TK_MINOR_VERSION < 4)) + # call setup script -- <libdir>/tkextlib/vu.rb + require(File.dirname(File.expand_path(__FILE__)) + '.rb') + + Tk.tk_call('namespace', 'import', '::vu::spinbox') +end + +Tk::Vu::Spinbox = TkSpinbox |