# This module exports classes for the various canvas item types

# NOTE: This module was an experiment and is now obsolete.
# It's best to use the Tkinter.Canvas class directly.

from Tkinter import Canvas, _cnfmerge, _flatten


class CanvasItem:
    def __init__(self, canvas, itemType, *args, **kw):
        self.canvas = canvas
        self.id = canvas._create(itemType, args, kw)
        if not hasattr(canvas, 'items'):
            canvas.items = {}
        canvas.items[self.id] = self
    def __str__(self):
        return str(self.id)
    def __repr__(self):
        return '<%s, id=%d>' % (self.__class__.__name__, self.id)
    def delete(self):
        del self.canvas.items[self.id]
        self.canvas.delete(self.id)
    def __getitem__(self, key):
        v = self.canvas.tk.split(self.canvas.tk.call(
                self.canvas._w, 'itemconfigure',
                self.id, '-' + key))
        return v[4]
    cget = __getitem__
    def __setitem__(self, key, value):
        self.canvas.itemconfig(self.id, {key: value})
    def keys(self):
        if not hasattr(self, '_keys'):
            self._keys = map(lambda x, tk=self.canvas.tk:
                             tk.splitlist(x)[0][1:],
                             self.canvas.tk.splitlist(
                                     self.canvas._do(
                                             'itemconfigure',
                                             (self.id,))))
        return self._keys
    def __contains__(self, key):
        return key in self.keys()
    def addtag(self, tag, option='withtag'):
        self.canvas.addtag(tag, option, self.id)
    def bbox(self):
        x1, y1, x2, y2 = self.canvas.bbox(self.id)
        return (x1, y1), (x2, y2)
    def bind(self, sequence=None, command=None, add=None):
        return self.canvas.tag_bind(self.id, sequence, command, add)
    def unbind(self, sequence, funcid=None):
        self.canvas.tag_unbind(self.id, sequence, funcid)
    def config(self, cnf={}, **kw):
        return self.canvas.itemconfig(self.id, _cnfmerge((cnf, kw)))
    def coords(self, pts = ()):
        flat = ()
        for x, y in pts: flat = flat + (x, y)
        return self.canvas.coords(self.id, *flat)
    def dchars(self, first, last=None):
        self.canvas.dchars(self.id, first, last)
    def dtag(self, ttd):
        self.canvas.dtag(self.id, ttd)
    def focus(self):
        self.canvas.focus(self.id)
    def gettags(self):
        return self.canvas.gettags(self.id)
    def icursor(self, index):
        self.canvas.icursor(self.id, index)
    def index(self, index):
        return self.canvas.index(self.id, index)
    def insert(self, beforethis, string):
        self.canvas.insert(self.id, beforethis, string)
    def lower(self, belowthis=None):
        self.canvas.tag_lower(self.id, belowthis)
    def move(self, xamount, yamount):
        self.canvas.move(self.id, xamount, yamount)
    def tkraise(self, abovethis=None):
        self.canvas.tag_raise(self.id, abovethis)
    raise_ = tkraise # BW compat
    def scale(self, xorigin, yorigin, xscale, yscale):
        self.canvas.scale(self.id, xorigin, yorigin, xscale, yscale)
    def type(self):
        return self.canvas.type(self.id)

class Arc(CanvasItem):
    def __init__(self, canvas, *args, **kw):
        CanvasItem.__init__(self, canvas, 'arc', *args, **kw)

class Bitmap(CanvasItem):
    def __init__(self, canvas, *args, **kw):
        CanvasItem.__init__(self, canvas, 'bitmap', *args, **kw)

class ImageItem(CanvasItem):
    def __init__(self, canvas, *args, **kw):
        CanvasItem.__init__(self, canvas, 'image', *args, **kw)

class Line(CanvasItem):
    def __init__(self, canvas, *args, **kw):
        CanvasItem.__init__(self, canvas, 'line', *args, **kw)

class Oval(CanvasItem):
    def __init__(self, canvas, *args, **kw):
        CanvasItem.__init__(self, canvas, 'oval', *args, **kw)

class Polygon(CanvasItem):
    def __init__(self, canvas, *args, **kw):
        CanvasItem.__init__(self, canvas, 'polygon', *args, **kw)

class Rectangle(CanvasItem):
    def __init__(self, canvas, *args, **kw):
        CanvasItem.__init__(self, canvas, 'rectangle', *args, **kw)

# XXX "Text" is taken by the Text widget...
class CanvasText(CanvasItem):
    def __init__(self, canvas, *args, **kw):
        CanvasItem.__init__(self, canvas, 'text', *args, **kw)

class Window(CanvasItem):
    def __init__(self, canvas, *args, **kw):
        CanvasItem.__init__(self, canvas, 'window', *args, **kw)

class Group:
    def __init__(self, canvas, tag=None):
        if not tag:
            tag = 'Group%d' % id(self)
        self.tag = self.id = tag
        self.canvas = canvas
        self.canvas.dtag(self.tag)
    def str(self):
        return self.tag
    __str__ = str
    def _do(self, cmd, *args):
        return self.canvas._do(cmd, (self.tag,) + _flatten(args))
    def addtag_above(self, tagOrId):
        self._do('addtag', 'above', tagOrId)
    def addtag_all(self):
        self._do('addtag', 'all')
    def addtag_below(self, tagOrId):
        self._do('addtag', 'below', tagOrId)
    def addtag_closest(self, x, y, halo=None, start=None):
        self._do('addtag', 'closest', x, y, halo, start)
    def addtag_enclosed(self, x1, y1, x2, y2):
        self._do('addtag', 'enclosed', x1, y1, x2, y2)
    def addtag_overlapping(self, x1, y1, x2, y2):
        self._do('addtag', 'overlapping', x1, y1, x2, y2)
    def addtag_withtag(self, tagOrId):
        self._do('addtag', 'withtag', tagOrId)
    def bbox(self):
        return self.canvas._getints(self._do('bbox'))
    def bind(self, sequence=None, command=None, add=None):
        return self.canvas.tag_bind(self.id, sequence, command, add)
    def unbind(self, sequence, funcid=None):
        self.canvas.tag_unbind(self.id, sequence, funcid)
    def coords(self, *pts):
        return self._do('coords', pts)
    def dchars(self, first, last=None):
        self._do('dchars', first, last)
    def delete(self):
        self._do('delete')
    def dtag(self, tagToDelete=None):
        self._do('dtag', tagToDelete)
    def focus(self):
        self._do('focus')
    def gettags(self):
        return self.canvas.tk.splitlist(self._do('gettags', self.tag))
    def icursor(self, index):
        return self._do('icursor', index)
    def index(self, index):
        return self.canvas.tk.getint(self._do('index', index))
    def insert(self, beforeThis, string):
        self._do('insert', beforeThis, string)
    def config(self, cnf={}, **kw):
        return self.canvas.itemconfigure(self.tag, _cnfmerge((cnf,kw)))
    def lower(self, belowThis=None):
        self._do('lower', belowThis)
    def move(self, xAmount, yAmount):
        self._do('move', xAmount, yAmount)
    def tkraise(self, aboveThis=None):
        self._do('raise', aboveThis)
    lift = tkraise
    def scale(self, xOrigin, yOrigin, xScale, yScale):
        self._do('scale', xOrigin, yOrigin, xScale, yScale)
    def select_adjust(self, index):
        self.canvas._do('select', ('adjust', self.tag, index))
    def select_from(self, index):
        self.canvas._do('select', ('from', self.tag, index))
    def select_to(self, index):
        self.canvas._do('select', ('to', self.tag, index))
    def type(self):
        return self._do('type')
