diff options
Diffstat (limited to 'ruby_1_8_6/ext/tk/lib/tk/canvas.rb')
-rw-r--r-- | ruby_1_8_6/ext/tk/lib/tk/canvas.rb | 759 |
1 files changed, 759 insertions, 0 deletions
diff --git a/ruby_1_8_6/ext/tk/lib/tk/canvas.rb b/ruby_1_8_6/ext/tk/lib/tk/canvas.rb new file mode 100644 index 0000000000..c30fd79bb9 --- /dev/null +++ b/ruby_1_8_6/ext/tk/lib/tk/canvas.rb @@ -0,0 +1,759 @@ +# +# tk/canvas.rb - Tk canvas classes +# $Date$ +# by Yukihiro Matsumoto <matz@caelum.co.jp> +# +require 'tk' +require 'tk/canvastag' +require 'tk/itemconfig' +require 'tk/scrollable' + +module TkCanvasItemConfig + include TkItemConfigMethod + + def __item_strval_optkeys(id) + # maybe need to override + super(id) + [ + 'fill', 'activefill', 'disabledfill', + 'outline', 'activeoutline', 'disabledoutline' + ] + end + private :__item_strval_optkeys + + def __item_methodcall_optkeys(id) + {'coords'=>'coords'} + end + private :__item_methodcall_optkeys + + def __item_val2ruby_optkeys(id) # { key=>proc, ... } + super(id).update('window'=>proc{|i, v| window(v)}) + end + private :__item_val2ruby_optkeys + + def __item_pathname(tagOrId) + if tagOrId.kind_of?(TkcItem) || tagOrId.kind_of?(TkcTag) + self.path + ';' + tagOrId.id.to_s + else + self.path + ';' + tagOrId.to_s + end + end + private :__item_pathname +end + +class TkCanvas<TkWindow + include TkCanvasItemConfig + include Tk::Scrollable + + TkCommandNames = ['canvas'.freeze].freeze + WidgetClassName = 'Canvas'.freeze + WidgetClassNames[WidgetClassName] = self + + def __destroy_hook__ + TkcItem::CItemID_TBL.delete(@path) + end + + #def create_self(keys) + # if keys and keys != None + # tk_call_without_enc('canvas', @path, *hash_kv(keys, true)) + # else + # tk_call_without_enc('canvas', @path) + # end + #end + #private :create_self + + def __numval_optkeys + super() + ['closeenough'] + end + private :__numval_optkeys + + def __boolval_optkeys + super() + ['confine'] + end + private :__boolval_optkeys + + def tagid(tag) + if tag.kind_of?(TkcItem) || tag.kind_of?(TkcTag) + tag.id + else + tag # maybe an Array of configure paramters + end + end + private :tagid + + + # create a canvas item without creating a TkcItem object + def create(type, *args) + type.create(self, *args) + end + + + def addtag(tag, mode, *args) + mode = mode.to_s + if args[0] && mode =~ /^(above|below|with(tag)?)$/ + args[0] = tagid(args[0]) + end + tk_send_without_enc('addtag', tagid(tag), mode, *args) + self + end + def addtag_above(tagOrId, target) + addtag(tagOrId, 'above', tagid(target)) + end + def addtag_all(tagOrId) + addtag(tagOrId, 'all') + end + def addtag_below(tagOrId, target) + addtag(tagOrId, 'below', tagid(target)) + end + def addtag_closest(tagOrId, x, y, halo=None, start=None) + addtag(tagOrId, 'closest', x, y, halo, start) + end + def addtag_enclosed(tagOrId, x1, y1, x2, y2) + addtag(tagOrId, 'enclosed', x1, y1, x2, y2) + end + def addtag_overlapping(tagOrId, x1, y1, x2, y2) + addtag(tagOrId, 'overlapping', x1, y1, x2, y2) + end + def addtag_withtag(tagOrId, tag) + addtag(tagOrId, 'withtag', tagid(tag)) + end + + def bbox(tagOrId, *tags) + list(tk_send_without_enc('bbox', tagid(tagOrId), + *tags.collect{|t| tagid(t)})) + end + + #def itembind(tag, context, cmd=Proc.new, *args) + # _bind([path, "bind", tagid(tag)], context, cmd, *args) + # self + #end + def itembind(tag, context, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind([path, "bind", tagid(tag)], context, cmd, *args) + self + end + + #def itembind_append(tag, context, cmd=Proc.new, *args) + # _bind_append([path, "bind", tagid(tag)], context, cmd, *args) + # self + #end + def itembind_append(tag, context, *args) + # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) + if TkComm._callback_entry?(args[0]) || !block_given? + cmd = args.shift + else + cmd = Proc.new + end + _bind_append([path, "bind", tagid(tag)], context, cmd, *args) + self + end + + def itembind_remove(tag, context) + _bind_remove([path, "bind", tagid(tag)], context) + self + end + + def itembindinfo(tag, context=nil) + _bindinfo([path, "bind", tagid(tag)], context) + end + + def canvasx(screen_x, *args) + #tk_tcl2ruby(tk_send_without_enc('canvasx', screen_x, *args)) + number(tk_send_without_enc('canvasx', screen_x, *args)) + end + def canvasy(screen_y, *args) + #tk_tcl2ruby(tk_send_without_enc('canvasy', screen_y, *args)) + number(tk_send_without_enc('canvasy', screen_y, *args)) + end + + def coords(tag, *args) + if args == [] + tk_split_list(tk_send_without_enc('coords', tagid(tag))) + else + tk_send_without_enc('coords', tagid(tag), *(args.flatten)) + self + end + end + + def dchars(tag, first, last=None) + tk_send_without_enc('dchars', tagid(tag), + _get_eval_enc_str(first), _get_eval_enc_str(last)) + self + end + + def delete(*args) + if TkcItem::CItemID_TBL[self.path] + args.each{|tag| + find('withtag', tag).each{|item| + if item.kind_of?(TkcItem) + TkcItem::CItemID_TBL[self.path].delete(item.id) + end + } + } + end + tk_send_without_enc('delete', *args.collect{|t| tagid(t)}) + self + end + alias remove delete + + def dtag(tag, tag_to_del=None) + tk_send_without_enc('dtag', tagid(tag), tagid(tag_to_del)) + self + end + alias deltag dtag + + def find(mode, *args) + list(tk_send_without_enc('find', mode, *args)).collect!{|id| + TkcItem.id2obj(self, id) + } + end + def find_above(target) + find('above', tagid(target)) + end + def find_all + find('all') + end + def find_below(target) + find('below', tagid(target)) + end + def find_closest(x, y, halo=None, start=None) + find('closest', x, y, halo, start) + end + def find_enclosed(x1, y1, x2, y2) + find('enclosed', x1, y1, x2, y2) + end + def find_overlapping(x1, y1, x2, y2) + find('overlapping', x1, y1, x2, y2) + end + def find_withtag(tag) + find('withtag', tag) + end + + def itemfocus(tagOrId=nil) + if tagOrId + tk_send_without_enc('focus', tagid(tagOrId)) + self + else + ret = tk_send_without_enc('focus') + if ret == "" + nil + else + TkcItem.id2obj(self, ret) + end + end + end + + def gettags(tagOrId) + list(tk_send_without_enc('gettags', tagid(tagOrId))).collect{|tag| + TkcTag.id2obj(self, tag) + } + end + + def icursor(tagOrId, index) + tk_send_without_enc('icursor', tagid(tagOrId), index) + self + end + + def index(tagOrId, idx) + number(tk_send_without_enc('index', tagid(tagOrId), idx)) + end + + def insert(tagOrId, index, string) + tk_send_without_enc('insert', tagid(tagOrId), index, + _get_eval_enc_str(string)) + self + end + +=begin + def itemcget(tagOrId, option) + case option.to_s + when 'dash', 'activedash', 'disableddash' + conf = tk_send_without_enc('itemcget', tagid(tagOrId), "-#{option}") + if conf =~ /^[0-9]/ + list(conf) + else + conf + end + when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile' + _fromUTF8(tk_send_without_enc('itemcget', tagid(tagOrId), "-#{option}")) + when 'font', 'kanjifont' + #fnt = tk_tcl2ruby(tk_send('itemcget', tagid(tagOrId), "-#{option}")) + fnt = tk_tcl2ruby(_fromUTF8(tk_send_with_enc('itemcget', tagid(tagOrId), '-font'))) + unless fnt.kind_of?(TkFont) + fnt = tagfontobj(tagid(tagOrId), fnt) + end + if option.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/ + # obsolete; just for compatibility + fnt.kanji_font + else + fnt + end + else + tk_tcl2ruby(_fromUTF8(tk_send_without_enc('itemcget', tagid(tagOrId), + "-#{option}"))) + end + end + + def itemconfigure(tagOrId, key, value=None) + if key.kind_of? Hash + key = _symbolkey2str(key) + coords = key.delete('coords') + self.coords(tagOrId, coords) if coords + + if ( key['font'] || key['kanjifont'] \ + || key['latinfont'] || key['asciifont'] ) + tagfont_configure(tagid(tagOrId), key.dup) + else + _fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId), + *hash_kv(key, true))) + end + + else + if ( key == 'coords' || key == :coords ) + self.coords(tagOrId, value) + elsif ( key == 'font' || key == :font || + key == 'kanjifont' || key == :kanjifont || + key == 'latinfont' || key == :latinfont || + key == 'asciifont' || key == :asciifont ) + if value == None + tagfontobj(tagid(tagOrId)) + else + tagfont_configure(tagid(tagOrId), {key=>value}) + end + else + _fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId), + "-#{key}", _get_eval_enc_str(value))) + end + end + self + end +# def itemconfigure(tagOrId, key, value=None) +# if key.kind_of? Hash +# tk_send 'itemconfigure', tagid(tagOrId), *hash_kv(key) +# else +# tk_send 'itemconfigure', tagid(tagOrId), "-#{key}", value +# end +# end +# def itemconfigure(tagOrId, keys) +# tk_send 'itemconfigure', tagid(tagOrId), *hash_kv(keys) +# end + + def itemconfiginfo(tagOrId, key=nil) + if TkComm::GET_CONFIGINFO_AS_ARRAY + if key + case key.to_s + when 'coords' + return ['coords', '', '', '', self.coords(tagOrId)] + when 'dash', 'activedash', 'disableddash' + conf = tk_split_simplelist(tk_send_without_enc('itemconfigure', tagid(tagOrId), "-#{key}")) + if conf[3] && conf[3] =~ /^[0-9]/ + conf[3] = list(conf[3]) + end + if conf[4] && conf[4] =~ /^[0-9]/ + conf[4] = list(conf[4]) + end + when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile' + conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId), "-#{key}"))) + when 'font', 'kanjifont' + conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId),"-#{key}"))) + conf[4] = tagfont_configinfo(tagid(tagOrId), conf[4]) + else + conf = tk_split_list(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId), "-#{key}"))) + end + conf[0] = conf[0][1..-1] + conf + else + ret = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId)))).collect{|conflist| + conf = tk_split_simplelist(conflist) + conf[0] = conf[0][1..-1] + case conf[0] + when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile' + when 'dash', 'activedash', 'disableddash' + if conf[3] && conf[3] =~ /^[0-9]/ + conf[3] = list(conf[3]) + end + if conf[4] && conf[4] =~ /^[0-9]/ + conf[4] = list(conf[4]) + end + else + if conf[3] + if conf[3].index('{') + conf[3] = tk_split_list(conf[3]) + else + conf[3] = tk_tcl2ruby(conf[3]) + end + end + if conf[4] + if conf[4].index('{') + conf[4] = tk_split_list(conf[4]) + else + conf[4] = tk_tcl2ruby(conf[4]) + end + end + end + conf[1] = conf[1][1..-1] if conf.size == 2 # alias info + conf + } + + fontconf = ret.assoc('font') + if fontconf + ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'} + fontconf[4] = tagfont_configinfo(tagid(tagOrId), fontconf[4]) + ret.push(fontconf) + end + + ret << ['coords', '', '', '', self.coords(tagOrId)] + end + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY + if key + case key.to_s + when 'coords' + {'coords' => ['', '', '', self.coords(tagOrId)]} + when 'dash', 'activedash', 'disableddash' + conf = tk_split_simplelist(tk_send_without_enc('itemconfigure', + tagid(tagOrId), + "-#{key}")) + if conf[3] && conf[3] =~ /^[0-9]/ + conf[3] = list(conf[3]) + end + if conf[4] && conf[4] =~ /^[0-9]/ + conf[4] = list(conf[4]) + end + when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile' + conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId), "-#{key}"))) + when 'font', 'kanjifont' + conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId),"-#{key}"))) + conf[4] = tagfont_configinfo(tagid(tagOrId), conf[4]) + else + conf = tk_split_list(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId), "-#{key}"))) + end + key = conf.shift[1..-1] + { key => conf } + else + ret = {} + tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId)))).each{|conflist| + conf = tk_split_simplelist(conflist) + key = conf.shift[1..-1] + case key + when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile' + when 'dash', 'activedash', 'disableddash' + if conf[2] && conf[2] =~ /^[0-9]/ + conf[2] = list(conf[2]) + end + if conf[3] && conf[3] =~ /^[0-9]/ + conf[3] = list(conf[3]) + end + else + if conf[2] + if conf[2].index('{') + conf[2] = tk_split_list(conf[2]) + else + conf[2] = tk_tcl2ruby(conf[2]) + end + end + if conf[3] + if conf[3].index('{') + conf[3] = tk_split_list(conf[3]) + else + conf[3] = tk_tcl2ruby(conf[3]) + end + end + end + if conf.size == 1 + ret[key] = conf[0][1..-1] # alias info + else + ret[key] = conf + end + } + + fontconf = ret['font'] + if fontconf + ret.delete('font') + ret.delete('kanjifont') + fontconf[3] = tagfont_configinfo(tagid(tagOrId), fontconf[3]) + ret['font'] = fontconf + end + + ret['coords'] = ['', '', '', self.coords(tagOrId)] + + ret + end + end + end + + def current_itemconfiginfo(tagOrId, key=nil) + if TkComm::GET_CONFIGINFO_AS_ARRAY + if key + conf = itemconfiginfo(tagOrId, key) + {conf[0] => conf[4]} + else + ret = {} + itemconfiginfo(tagOrId).each{|conf| + ret[conf[0]] = conf[4] if conf.size > 2 + } + ret + end + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY + ret = {} + itemconfiginfo(tagOrId, key).each{|k, conf| + ret[k] = conf[-1] if conf.kind_of?(Array) + } + ret + end + end +=end + + def lower(tag, below=nil) + if below + tk_send_without_enc('lower', tagid(tag), tagid(below)) + else + tk_send_without_enc('lower', tagid(tag)) + end + self + end + + def move(tag, x, y) + tk_send_without_enc('move', tagid(tag), x, y) + self + end + + def postscript(keys) + tk_send("postscript", *hash_kv(keys)) + end + + def raise(tag, above=nil) + if above + tk_send_without_enc('raise', tagid(tag), tagid(above)) + else + tk_send_without_enc('raise', tagid(tag)) + end + self + end + + def scale(tag, x, y, xs, ys) + tk_send_without_enc('scale', tagid(tag), x, y, xs, ys) + self + end + + def scan_mark(x, y) + tk_send_without_enc('scan', 'mark', x, y) + self + end + def scan_dragto(x, y, gain=None) + tk_send_without_enc('scan', 'dragto', x, y, gain) + self + end + + def select(mode, *args) + r = tk_send_without_enc('select', mode, *args) + (mode == 'item')? TkcItem.id2obj(self, r): self + end + def select_adjust(tagOrId, index) + select('adjust', tagid(tagOrId), index) + end + def select_clear + select('clear') + end + def select_from(tagOrId, index) + select('from', tagid(tagOrId), index) + end + def select_item + select('item') + end + def select_to(tagOrId, index) + select('to', tagid(tagOrId), index) + end + + def itemtype(tag) + TkcItem.type2class(tk_send('type', tagid(tag))) + end +end + +class TkcItem<TkObject + extend Tk + include TkcTagAccess + extend TkItemFontOptkeys + extend TkItemConfigOptkeys + + CItemTypeName = nil + CItemTypeToClass = {} + CItemID_TBL = TkCore::INTERP.create_table + + TkCore::INTERP.init_ip_env{ CItemID_TBL.clear } + + def TkcItem.type2class(type) + CItemTypeToClass[type] + end + + def TkcItem.id2obj(canvas, id) + cpath = canvas.path + return id unless CItemID_TBL[cpath] + CItemID_TBL[cpath][id]? CItemID_TBL[cpath][id]: id + end + + ######################################## + def self._parse_create_args(args) + fontkeys = {} + methodkeys = {} + if args[-1].kind_of? Hash + keys = _symbolkey2str(args.pop) + if args.size == 0 + args = keys.delete('coords') + unless args.kind_of?(Array) + fail "coords parameter must be given by an Array" + end + end + + #['font', 'kanjifont', 'latinfont', 'asciifont'].each{|key| + # fontkeys[key] = keys.delete(key) if keys.key?(key) + #} + __item_font_optkeys(nil).each{|key| + fkey = key.to_s + fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) + + fkey = "kanji#{key}" + fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) + + fkey = "latin#{key}" + fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) + + fkey = "ascii#{key}" + fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) + } + + __item_methodcall_optkeys(nil).each{|key| + key = key.to_s + methodkeys[key] = keys.delete(key) if keys.key?(key) + } + + __item_ruby2val_optkeys(nil).each{|key, method| + key = key.to_s + keys[key] = method.call(keys[key]) if keys.has_key?(key) + } + + #args = args.flatten.concat(hash_kv(keys)) + args = args.flatten.concat(itemconfig_hash_kv(nil, keys)) + else + args = args.flatten + end + + [args, fontkeys] + end + private_class_method :_parse_create_args + + def self.create(canvas, *args) + unless self::CItemTypeName + fail RuntimeError, "#{self} is an abstract class" + end + args, fontkeys = _parse_create_args(args) + idnum = tk_call_without_enc(canvas.path, 'create', + self::CItemTypeName, *args) + canvas.itemconfigure(idnum, fontkeys) unless fontkeys.empty? + idnum.to_i # 'canvas item id' is an integer number + end + ######################################## + + def initialize(parent, *args) + #unless parent.kind_of?(TkCanvas) + # fail ArgumentError, "expect TkCanvas for 1st argument" + #end + @parent = @c = parent + @path = parent.path + + @id = create_self(*args) # an integer number as 'canvas item id' + CItemID_TBL[@path] = {} unless CItemID_TBL[@path] + CItemID_TBL[@path][@id] = self + end + def create_self(*args) + self.class.create(@c, *args) # return an integer number as 'canvas item id' + end + private :create_self + + def id + @id + end + + def exist? + if @c.find_withtag(@id) + true + else + false + end + end + + def delete + @c.delete @id + CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path] + self + end + alias remove delete + alias destroy delete +end + +class TkcArc<TkcItem + CItemTypeName = 'arc'.freeze + CItemTypeToClass[CItemTypeName] = self +end + +class TkcBitmap<TkcItem + CItemTypeName = 'bitmap'.freeze + CItemTypeToClass[CItemTypeName] = self +end + +class TkcImage<TkcItem + CItemTypeName = 'image'.freeze + CItemTypeToClass[CItemTypeName] = self +end + +class TkcLine<TkcItem + CItemTypeName = 'line'.freeze + CItemTypeToClass[CItemTypeName] = self +end + +class TkcOval<TkcItem + CItemTypeName = 'oval'.freeze + CItemTypeToClass[CItemTypeName] = self +end + +class TkcPolygon<TkcItem + CItemTypeName = 'polygon'.freeze + CItemTypeToClass[CItemTypeName] = self +end + +class TkcRectangle<TkcItem + CItemTypeName = 'rectangle'.freeze + CItemTypeToClass[CItemTypeName] = self +end + +class TkcText<TkcItem + CItemTypeName = 'text'.freeze + CItemTypeToClass[CItemTypeName] = self + def self.create(canvas, *args) + if args[-1].kind_of?(Hash) + keys = _symbolkey2str(args.pop) + txt = keys['text'] + keys['text'] = _get_eval_enc_str(txt) if txt + args.push(keys) + end + super(canvas, *args) + end +end + +class TkcWindow<TkcItem + CItemTypeName = 'window'.freeze + CItemTypeToClass[CItemTypeName] = self + def self.create(canvas, *args) + if args[-1].kind_of?(Hash) + keys = _symbolkey2str(args.pop) + win = keys['window'] + # keys['window'] = win.epath if win.kind_of?(TkWindow) + keys['window'] = _epath(win) if win + args.push(keys) + end + super(canvas, *args) + end +end |