# 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 has_key(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 apply(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):
        apply(CanvasItem.__init__, (self, canvas, 'arc') + args, kw)

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

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

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

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

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

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

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

class Window(CanvasItem):
    def __init__(self, canvas, *args, **kw):
        apply(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('tag_lower', belowThis)
    def move(self, xAmount, yAmount):
        self._do('move', xAmount, yAmount)
    def tkraise(self, aboveThis=None):
        self._do('tag_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')
